2 * Copyright 2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
37 #include "cryptuiapi.h"
38 #include "cryptuires.h"
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
47 static HINSTANCE hInstance
;
49 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
51 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
55 case DLL_WINE_PREATTACH
:
56 return FALSE
; /* prefer native version */
57 case DLL_PROCESS_ATTACH
:
59 DisableThreadLibraryCalls(hinstDLL
);
65 #define MAX_STRING_LEN 512
67 static void add_cert_columns(HWND hwnd
)
69 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
71 WCHAR buf
[MAX_STRING_LEN
];
74 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
75 GetWindowRect(lv
, &rc
);
76 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
,
77 sizeof(buf
) / sizeof(buf
[0]));
78 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
79 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
81 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
82 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
,
83 sizeof(buf
) / sizeof(buf
[0]));
84 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
85 column
.cx
= (rc
.right
- rc
.left
) * 16 / 100 - 2;
86 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
,
87 sizeof(buf
) / sizeof(buf
[0]));
88 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
89 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
90 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
,
91 sizeof(buf
) / sizeof(buf
[0]));
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
)
114 HeapFree(GetProcessHeap(), 0, *str
);
115 *str
= HeapAlloc(GetProcessHeap(), 0, 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
)
132 HeapFree(GetProcessHeap(), 0, *str
);
133 *str
= HeapAlloc(GetProcessHeap(), 0, 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
,
147 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
148 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
149 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
150 sizeof(date
) / sizeof(date
[0]));
153 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
155 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
157 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
158 if (len
> *allocatedLen
)
160 HeapFree(GetProcessHeap(), 0, *str
);
161 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
167 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
173 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
177 static LPSTR
get_cert_mgr_usages(void)
179 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
180 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
181 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
182 'r','p','o','s','e',0 };
186 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
192 rc
= RegQueryValueExA(key
, "Purpose", NULL
, &type
, NULL
, &size
);
193 if ((!rc
|| rc
== ERROR_MORE_DATA
) && type
== REG_SZ
)
195 str
= HeapAlloc(GetProcessHeap(), 0, size
);
198 rc
= RegQueryValueExA(key
, "Purpose", NULL
, NULL
, (LPBYTE
)str
,
202 HeapFree(GetProcessHeap(), 0, str
);
213 PurposeFilterShowAll
= 0,
214 PurposeFilterShowAdvanced
= 1,
215 PurposeFilterShowOID
= 2
218 static void initialize_purpose_selection(HWND hwnd
)
220 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
221 WCHAR buf
[MAX_STRING_LEN
];
225 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
,
226 sizeof(buf
) / sizeof(buf
[0]));
227 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
228 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAll
);
229 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
,
230 sizeof(buf
) / sizeof(buf
[0]));
231 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
232 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAdvanced
);
233 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
234 if ((usages
= get_cert_mgr_usages()))
238 for (ptr
= usages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
239 ptr
= comma
? comma
+ 1 : NULL
,
240 comma
= ptr
? strchr(ptr
, ',') : NULL
)
242 PCCRYPT_OID_INFO info
;
246 if ((info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, ptr
, 0)))
248 index
= SendMessageW(cb
, CB_INSERTSTRING
, 0,
249 (LPARAM
)info
->pwszName
);
250 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)info
);
253 HeapFree(GetProcessHeap(), 0, usages
);
257 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
258 PCCRYPT_OID_INFO
**usages
);
260 static CERT_ENHKEY_USAGE
*add_oid_to_usage(CERT_ENHKEY_USAGE
*usage
, LPSTR oid
)
262 if (!usage
->cUsageIdentifier
)
263 usage
->rgpszUsageIdentifier
= HeapAlloc(GetProcessHeap(), 0,
266 usage
->rgpszUsageIdentifier
= HeapReAlloc(GetProcessHeap(), 0,
267 usage
->rgpszUsageIdentifier
,
268 (usage
->cUsageIdentifier
+ 1) * sizeof(LPSTR
));
269 if (usage
->rgpszUsageIdentifier
)
270 usage
->rgpszUsageIdentifier
[usage
->cUsageIdentifier
++] = oid
;
273 HeapFree(GetProcessHeap(), 0, usage
);
279 static CERT_ENHKEY_USAGE
*convert_usages_str_to_usage(LPSTR usageStr
)
281 CERT_ENHKEY_USAGE
*usage
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
282 sizeof(CERT_ENHKEY_USAGE
));
288 for (ptr
= usageStr
, comma
= strchr(ptr
, ','); usage
&& ptr
&& *ptr
;
289 ptr
= comma
? comma
+ 1 : NULL
,
290 comma
= ptr
? strchr(ptr
, ',') : NULL
)
294 usage
= add_oid_to_usage(usage
, ptr
);
300 static CERT_ENHKEY_USAGE
*create_advanced_filter(void)
302 CERT_ENHKEY_USAGE
*advancedUsage
= HeapAlloc(GetProcessHeap(),
303 HEAP_ZERO_MEMORY
, sizeof(CERT_ENHKEY_USAGE
));
307 PCCRYPT_OID_INFO
*usages
;
309 if (WTHelperGetKnownUsages(1, &usages
))
311 LPSTR disabledUsagesStr
;
313 if ((disabledUsagesStr
= get_cert_mgr_usages()))
315 CERT_ENHKEY_USAGE
*disabledUsages
=
316 convert_usages_str_to_usage(disabledUsagesStr
);
320 PCCRYPT_OID_INFO
*ptr
;
322 for (ptr
= usages
; advancedUsage
&& *ptr
; ptr
++)
325 BOOL disabled
= FALSE
;
327 for (i
= 0; !disabled
&&
328 i
< disabledUsages
->cUsageIdentifier
; i
++)
329 if (!strcmp(disabledUsages
->rgpszUsageIdentifier
[i
],
333 advancedUsage
= add_oid_to_usage(advancedUsage
,
334 (LPSTR
)(*ptr
)->pszOID
);
336 /* The individual strings are pointers to disabledUsagesStr,
337 * so they're freed when it is.
339 HeapFree(GetProcessHeap(), 0,
340 disabledUsages
->rgpszUsageIdentifier
);
341 HeapFree(GetProcessHeap(), 0, disabledUsages
);
343 HeapFree(GetProcessHeap(), 0, disabledUsagesStr
);
345 WTHelperGetKnownUsages(2, &usages
);
348 return advancedUsage
;
351 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
);
353 static void show_store_certs(HWND hwnd
, HCERTSTORE store
)
355 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
356 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
357 PCCERT_CONTEXT cert
= NULL
;
358 DWORD allocatedLen
= 0;
361 PurposeFilter filter
= PurposeFilterShowAll
;
363 CERT_ENHKEY_USAGE
*advanced
= NULL
;
365 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
368 INT_PTR data
= SendMessageW(cb
, CB_GETITEMDATA
, index
, 0);
374 PCCRYPT_OID_INFO info
= (PCCRYPT_OID_INFO
)data
;
376 filter
= PurposeFilterShowOID
;
380 if (filter
== PurposeFilterShowAdvanced
)
381 advanced
= create_advanced_filter();
383 cert
= CertEnumCertificatesInStore(store
, cert
);
388 if (filter
== PurposeFilterShowAll
)
395 if (CertGetValidUsages(1, &cert
, &numOIDs
, NULL
, &cbOIDs
))
399 /* -1 implies all usages are valid */
404 LPSTR
*oids
= HeapAlloc(GetProcessHeap(), 0, cbOIDs
);
408 if (CertGetValidUsages(1, &cert
, &numOIDs
, oids
,
413 if (filter
== PurposeFilterShowOID
)
415 for (i
= 0; !show
&& i
< numOIDs
; i
++)
416 if (!strcmp(oids
[i
], oid
))
421 for (i
= 0; !show
&& i
< numOIDs
; i
++)
426 j
< advanced
->cUsageIdentifier
; j
++)
428 advanced
->rgpszUsageIdentifier
[j
]))
433 HeapFree(GetProcessHeap(), 0, oids
);
439 add_cert_to_view(lv
, cert
, &allocatedLen
, &str
);
442 HeapFree(GetProcessHeap(), 0, str
);
445 HeapFree(GetProcessHeap(), 0, advanced
->rgpszUsageIdentifier
);
446 HeapFree(GetProcessHeap(), 0, advanced
);
448 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
449 (LPARAM
)cert_mgr_sort_by_subject
);
452 static const WCHAR my
[] = { 'M','y',0 };
453 static const WCHAR addressBook
[] = {
454 'A','d','d','r','e','s','s','B','o','o','k',0 };
455 static const WCHAR ca
[] = { 'C','A',0 };
456 static const WCHAR root
[] = { 'R','o','o','t',0 };
457 static const WCHAR trustedPublisher
[] = {
458 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
459 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
461 struct CertMgrStoreInfo
465 int removePluralWarning
;
468 static const struct CertMgrStoreInfo defaultStoreList
[] = {
469 { my
, IDS_WARN_REMOVE_MY
, IDS_WARN_REMOVE_PLURAL_MY
},
470 { addressBook
, IDS_WARN_REMOVE_ADDRESSBOOK
,
471 IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK
},
472 { ca
, IDS_WARN_REMOVE_CA
, IDS_WARN_REMOVE_PLURAL_CA
},
473 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
474 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
475 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
476 { disallowed
, IDS_WARN_REMOVE_DEFAULT
},
479 static const struct CertMgrStoreInfo publisherStoreList
[] = {
480 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
481 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
482 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
483 { disallowed
, IDS_WARN_REMOVE_PLURAL_DEFAULT
},
488 HIMAGELIST imageList
;
491 const struct CertMgrStoreInfo
*stores
;
494 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
, struct CertMgrData
*data
)
496 const struct CertMgrStoreInfo
*storeList
;
498 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
500 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
502 storeList
= publisherStoreList
;
503 cStores
= sizeof(publisherStoreList
) / sizeof(publisherStoreList
[0]);
507 storeList
= defaultStoreList
;
508 cStores
= sizeof(defaultStoreList
) / sizeof(defaultStoreList
[0]);
510 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
512 data
->nStores
= cStores
;
513 data
->stores
= storeList
;
514 for (i
= 0; i
< cStores
; i
++)
520 if (!(name
= CryptFindLocalizedName(storeList
[i
].name
)))
521 name
= storeList
[i
].name
;
522 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
523 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
].name
);
524 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
525 item
.pszText
= (LPWSTR
)name
;
526 item
.lParam
= (LPARAM
)store
;
527 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
531 static void free_certs(HWND lv
)
534 int items
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
536 for (i
= 0; i
< items
; i
++)
538 item
.mask
= LVIF_PARAM
;
541 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
542 CertFreeCertificateContext((PCCERT_CONTEXT
)item
.lParam
);
546 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
550 item
.mask
= TCIF_PARAM
;
551 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
552 return (HCERTSTORE
)item
.lParam
;
555 static HCERTSTORE
cert_mgr_current_store(HWND hwnd
)
557 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
559 return cert_mgr_index_to_store(tab
, SendMessageW(tab
, TCM_GETCURSEL
, 0, 0));
562 static void close_stores(HWND tab
)
564 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
566 for (i
= 0; i
< tabs
; i
++)
567 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
570 static void refresh_store_certs(HWND hwnd
)
572 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
575 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
576 show_store_certs(hwnd
, cert_mgr_current_store(hwnd
));
580 CheckBitmapIndexUnchecked
= 1,
581 CheckBitmapIndexChecked
= 2,
582 CheckBitmapIndexDisabledUnchecked
= 3,
583 CheckBitmapIndexDisabledChecked
= 4
586 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
,
587 CheckBitmapIndex state
)
591 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
592 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
593 item
.stateMask
= LVIS_STATEIMAGEMASK
;
594 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
596 item
.lParam
= (LPARAM
)info
;
597 item
.pszText
= (LPWSTR
)info
->pwszName
;
598 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
601 static void add_known_usages_to_list(HWND lv
, CheckBitmapIndex state
)
603 PCCRYPT_OID_INFO
*usages
;
605 if (WTHelperGetKnownUsages(1, &usages
))
607 PCCRYPT_OID_INFO
*ptr
;
609 for (ptr
= usages
; *ptr
; ptr
++)
610 add_known_usage(lv
, *ptr
, state
);
611 WTHelperGetKnownUsages(2, &usages
);
615 static void toggle_usage(HWND hwnd
, int iItem
)
619 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
621 item
.mask
= LVIF_STATE
;
624 item
.stateMask
= LVIS_STATEIMAGEMASK
;
625 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
628 int state
= item
.state
>> 12;
630 item
.state
= INDEXTOSTATEIMAGEMASK(
631 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
632 CheckBitmapIndexChecked
);
633 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
637 static LONG_PTR
find_oid_in_list(HWND lv
, LPCSTR oid
)
639 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
640 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
645 LVFINDINFOW findInfo
;
647 findInfo
.flags
= LVFI_PARAM
;
648 findInfo
.lParam
= (LPARAM
)oidInfo
;
649 ret
= SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
);
653 LVFINDINFOA findInfo
;
655 findInfo
.flags
= LVFI_STRING
;
657 ret
= SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
);
662 static void save_cert_mgr_usages(HWND hwnd
)
664 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
665 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
666 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
667 'r','p','o','s','e',0 };
669 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
670 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
674 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
676 item
.stateMask
= LVIS_STATEIMAGEMASK
;
677 for (i
= 0; i
< purposes
; i
++)
680 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
682 int state
= item
.state
>> 12;
684 if (state
== CheckBitmapIndexUnchecked
)
686 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
687 BOOL firstString
= TRUE
;
690 str
= HeapAlloc(GetProcessHeap(), 0,
691 strlen(info
->pszOID
) + 1);
694 str
= HeapReAlloc(GetProcessHeap(), 0, str
,
695 strlen(str
) + 1 + strlen(info
->pszOID
) + 1);
700 LPSTR ptr
= firstString
? str
: str
+ strlen(str
);
704 strcpy(ptr
, info
->pszOID
);
709 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_ALL_ACCESS
,
713 RegSetValueExA(key
, "Purpose", 0, REG_SZ
, (const BYTE
*)str
,
716 RegDeleteValueA(key
, "Purpose");
719 HeapFree(GetProcessHeap(), 0, str
);
722 static LRESULT CALLBACK
cert_mgr_advanced_dlg_proc(HWND hwnd
, UINT msg
,
723 WPARAM wp
, LPARAM lp
)
731 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
732 HIMAGELIST imageList
;
733 LPSTR disabledUsages
;
735 GetWindowRect(lv
, &rc
);
736 column
.mask
= LVCF_WIDTH
;
737 column
.cx
= rc
.right
- rc
.left
;
738 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
739 imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 4, 0);
743 COLORREF backColor
= RGB(255, 0, 255);
745 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
746 ImageList_AddMasked(imageList
, bmp
, backColor
);
748 ImageList_SetBkColor(imageList
, CLR_NONE
);
749 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)imageList
);
750 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)imageList
);
752 add_known_usages_to_list(lv
, CheckBitmapIndexChecked
);
753 if ((disabledUsages
= get_cert_mgr_usages()))
757 for (ptr
= disabledUsages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
758 ptr
= comma
? comma
+ 1 : NULL
,
759 comma
= ptr
? strchr(ptr
, ',') : NULL
)
765 if ((index
= find_oid_in_list(lv
, ptr
)) != -1)
766 toggle_usage(hwnd
, index
);
768 HeapFree(GetProcessHeap(), 0, disabledUsages
);
774 NMHDR
*hdr
= (NMHDR
*)lp
;
780 nm
= (NMITEMACTIVATE
*)lp
;
781 toggle_usage(hwnd
, nm
->iItem
);
782 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
791 save_cert_mgr_usages(hwnd
);
792 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
793 EndDialog(hwnd
, IDOK
);
796 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
797 EndDialog(hwnd
, IDCANCEL
);
805 static void cert_mgr_clear_cert_selection(HWND hwnd
)
807 WCHAR empty
[] = { 0 };
809 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), FALSE
);
810 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), FALSE
);
811 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), FALSE
);
812 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
814 refresh_store_certs(hwnd
);
817 static PCCERT_CONTEXT
cert_mgr_index_to_cert(HWND hwnd
, int index
)
819 PCCERT_CONTEXT cert
= NULL
;
822 item
.mask
= LVIF_PARAM
;
825 if (SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_GETITEMW
, 0,
827 cert
= (PCCERT_CONTEXT
)item
.lParam
;
831 static void show_selected_cert(HWND hwnd
, int index
)
833 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
837 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
839 memset(&viewInfo
, 0, sizeof(viewInfo
));
840 viewInfo
.dwSize
= sizeof(viewInfo
);
841 viewInfo
.hwndParent
= hwnd
;
842 viewInfo
.pCertContext
= cert
;
843 /* FIXME: this should be modal */
844 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
848 static void cert_mgr_show_cert_usages(HWND hwnd
, int index
)
850 HWND text
= GetDlgItem(hwnd
, IDC_MGR_PURPOSES
);
851 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
852 PCERT_ENHKEY_USAGE usage
;
855 /* Get enhanced key usage. Have to check for a property and an extension
856 * separately, because CertGetEnhancedKeyUsage will succeed and return an
857 * empty usage if neither is set. Unfortunately an empty usage implies
858 * no usage is allowed, so we have to distinguish between the two cases.
860 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
863 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
864 if (!CertGetEnhancedKeyUsage(cert
,
865 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
867 HeapFree(GetProcessHeap(), 0, usage
);
871 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
874 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
875 if (!CertGetEnhancedKeyUsage(cert
,
876 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
878 HeapFree(GetProcessHeap(), 0, usage
);
886 if (usage
->cUsageIdentifier
)
888 static const WCHAR commaSpace
[] = { ',',' ',0 };
892 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
894 PCCRYPT_OID_INFO info
=
895 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
896 usage
->rgpszUsageIdentifier
[i
],
897 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
900 len
+= strlenW(info
->pwszName
);
902 len
+= strlen(usage
->rgpszUsageIdentifier
[i
]);
903 if (i
< usage
->cUsageIdentifier
- 1)
904 len
+= strlenW(commaSpace
);
906 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
909 for (i
= 0, ptr
= str
; i
< usage
->cUsageIdentifier
; i
++)
911 PCCRYPT_OID_INFO info
=
912 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
913 usage
->rgpszUsageIdentifier
[i
],
914 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
918 strcpyW(ptr
, info
->pwszName
);
919 ptr
+= strlenW(info
->pwszName
);
923 LPCSTR src
= usage
->rgpszUsageIdentifier
[i
];
925 for (; *src
; ptr
++, src
++)
929 if (i
< usage
->cUsageIdentifier
- 1)
931 strcpyW(ptr
, commaSpace
);
932 ptr
+= strlenW(commaSpace
);
936 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)str
);
937 HeapFree(GetProcessHeap(), 0, str
);
939 HeapFree(GetProcessHeap(), 0, usage
);
943 WCHAR buf
[MAX_STRING_LEN
];
945 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_NONE
, buf
,
946 sizeof(buf
) / sizeof(buf
[0]));
947 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
952 WCHAR buf
[MAX_STRING_LEN
];
954 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_ALL
, buf
,
955 sizeof(buf
) / sizeof(buf
[0]));
956 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
960 static void cert_mgr_do_remove(HWND hwnd
)
962 int tabIndex
= SendMessageW(GetDlgItem(hwnd
, IDC_MGR_STORES
),
963 TCM_GETCURSEL
, 0, 0);
964 struct CertMgrData
*data
=
965 (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
967 if (tabIndex
< data
->nStores
)
969 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
970 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
974 if (SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0) > 1)
975 warningID
= data
->stores
[tabIndex
].removePluralWarning
;
977 warningID
= data
->stores
[tabIndex
].removeWarning
;
979 pTitle
= data
->title
;
982 LoadStringW(hInstance
, IDS_CERT_MGR
, title
,
983 sizeof(title
) / sizeof(title
[0]));
986 LoadStringW(hInstance
, warningID
, warning
,
987 sizeof(warning
) / sizeof(warning
[0]));
988 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
993 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
997 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1000 CertDeleteCertificateFromStore(cert
);
1002 } while (selection
>= 0);
1003 cert_mgr_clear_cert_selection(hwnd
);
1008 static void cert_mgr_do_export(HWND hwnd
)
1010 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1011 int selectionCount
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1013 if (selectionCount
== 1)
1015 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1020 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, selection
);
1024 CRYPTUI_WIZ_EXPORT_INFO info
;
1026 info
.dwSize
= sizeof(info
);
1027 info
.pwszExportFileName
= NULL
;
1028 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
1029 info
.u
.pCertContext
= cert
;
1031 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1035 else if (selectionCount
> 1)
1037 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1038 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1042 CRYPTUI_WIZ_EXPORT_INFO info
;
1045 info
.dwSize
= sizeof(info
);
1046 info
.pwszExportFileName
= NULL
;
1047 info
.dwSubjectChoice
=
1048 CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
;
1049 info
.u
.hCertStore
= store
;
1052 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1056 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1059 CertAddCertificateContextToStore(store
, cert
,
1060 CERT_STORE_ADD_ALWAYS
, NULL
);
1062 } while (selection
>= 0);
1063 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1064 CertCloseStore(store
, 0);
1069 static int cert_mgr_sort_by_text(HWND lv
, int col
, int index1
, int index2
)
1072 WCHAR buf1
[MAX_STRING_LEN
];
1073 WCHAR buf2
[MAX_STRING_LEN
];
1075 item
.cchTextMax
= sizeof(buf1
) / sizeof(buf1
[0]);
1076 item
.mask
= LVIF_TEXT
;
1077 item
.pszText
= buf1
;
1078 item
.iItem
= index1
;
1079 item
.iSubItem
= col
;
1080 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1081 item
.pszText
= buf2
;
1082 item
.iItem
= index2
;
1083 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1084 return strcmpW(buf1
, buf2
);
1087 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1089 return cert_mgr_sort_by_text((HWND
)lp
, 0, lp1
, lp2
);
1092 static int CALLBACK
cert_mgr_sort_by_issuer(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1094 return cert_mgr_sort_by_text((HWND
)lp
, 1, lp1
, lp2
);
1097 static int CALLBACK
cert_mgr_sort_by_date(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1099 PCCERT_CONTEXT cert1
= (PCCERT_CONTEXT
)lp1
;
1100 PCCERT_CONTEXT cert2
= (PCCERT_CONTEXT
)lp2
;
1101 return CompareFileTime(&cert1
->pCertInfo
->NotAfter
,
1102 &cert2
->pCertInfo
->NotAfter
);
1105 static int CALLBACK
cert_mgr_sort_by_friendly_name(LPARAM lp1
, LPARAM lp2
,
1108 return cert_mgr_sort_by_text((HWND
)lp
, 3, lp1
, lp2
);
1111 static LRESULT CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1114 struct CertMgrData
*data
;
1120 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
1121 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
1122 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
1124 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData
));
1127 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
1128 if (data
->imageList
)
1131 COLORREF backColor
= RGB(255, 0, 255);
1133 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
1134 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
1136 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
1137 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_SETIMAGELIST
,
1138 LVSIL_SMALL
, (LPARAM
)data
->imageList
);
1140 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
1141 data
->title
= pCryptUICertMgr
->pwszTitle
;
1143 initialize_purpose_selection(hwnd
);
1144 add_cert_columns(hwnd
);
1145 if (pCryptUICertMgr
->pwszTitle
)
1146 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1147 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
1148 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
, data
);
1149 show_store_certs(hwnd
, cert_mgr_index_to_store(tab
, 0));
1154 NMHDR
*hdr
= (NMHDR
*)lp
;
1159 cert_mgr_clear_cert_selection(hwnd
);
1161 case LVN_ITEMCHANGED
:
1163 WCHAR empty
[] = { 0 };
1164 NMITEMACTIVATE
*nm
= (NMITEMACTIVATE
*)lp
;
1165 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1166 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1168 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), numSelected
> 0);
1169 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), numSelected
> 0);
1170 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), numSelected
== 1);
1171 if (numSelected
== 1)
1172 cert_mgr_show_cert_usages(hwnd
, nm
->iItem
);
1174 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
1179 show_selected_cert(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
1183 NMLVKEYDOWN
*lvk
= (NMLVKEYDOWN
*)lp
;
1185 if (lvk
->wVKey
== VK_DELETE
)
1186 cert_mgr_do_remove(hwnd
);
1189 case LVN_COLUMNCLICK
:
1191 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
1192 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1194 /* FIXME: doesn't support swapping sort order between ascending
1197 switch (nmlv
->iSubItem
)
1200 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1201 (LPARAM
)cert_mgr_sort_by_subject
);
1204 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1205 (LPARAM
)cert_mgr_sort_by_issuer
);
1208 SendMessageW(lv
, LVM_SORTITEMS
, 0,
1209 (LPARAM
)cert_mgr_sort_by_date
);
1212 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1213 (LPARAM
)cert_mgr_sort_by_friendly_name
);
1224 case ((CBN_SELCHANGE
<< 16) | IDC_MGR_PURPOSE_SELECTION
):
1225 cert_mgr_clear_cert_selection(hwnd
);
1227 case IDC_MGR_IMPORT
:
1228 if (CryptUIWizImport(0, hwnd
, NULL
, NULL
,
1229 cert_mgr_current_store(hwnd
)))
1230 refresh_store_certs(hwnd
);
1232 case IDC_MGR_ADVANCED
:
1233 if (DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR_ADVANCED
),
1234 hwnd
, cert_mgr_advanced_dlg_proc
) == IDOK
)
1236 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
1238 LPWSTR curString
= NULL
;
1240 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
1243 len
= SendMessageW(cb
, CB_GETLBTEXTLEN
, index
, 0);
1244 curString
= HeapAlloc(GetProcessHeap(), 0,
1245 (len
+ 1) * sizeof(WCHAR
));
1246 SendMessageW(cb
, CB_GETLBTEXT
, index
, (LPARAM
)curString
);
1248 SendMessageW(cb
, CB_RESETCONTENT
, 0, 0);
1249 initialize_purpose_selection(hwnd
);
1252 index
= SendMessageW(cb
, CB_FINDSTRINGEXACT
, -1,
1255 SendMessageW(cb
, CB_SETCURSEL
, index
, 0);
1256 HeapFree(GetProcessHeap(), 0, curString
);
1258 refresh_store_certs(hwnd
);
1263 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1264 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1268 show_selected_cert(hwnd
, selection
);
1271 case IDC_MGR_EXPORT
:
1272 cert_mgr_do_export(hwnd
);
1274 case IDC_MGR_REMOVE
:
1275 cert_mgr_do_remove(hwnd
);
1278 free_certs(GetDlgItem(hwnd
, IDC_MGR_CERTS
));
1279 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1280 data
= (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1281 ImageList_Destroy(data
->imageList
);
1282 HeapFree(GetProcessHeap(), 0, data
);
1283 EndDialog(hwnd
, IDCANCEL
);
1291 /***********************************************************************
1292 * CryptUIDlgCertMgr (CRYPTUI.@)
1294 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
1296 TRACE("(%p)\n", pCryptUICertMgr
);
1298 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
1300 WARN("unexpected size %d\n", pCryptUICertMgr
->dwSize
);
1301 SetLastError(E_INVALIDARG
);
1304 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
1305 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
1309 /* FIXME: real names are unknown, functions are undocumented */
1310 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
1313 void *pvSystemStoreLocationPara
;
1314 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
1316 typedef struct _CRYPTUI_ENUM_DATA
1319 HCERTSTORE
*rghStore
;
1321 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
1322 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
1324 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
1327 /* Values for dwFlags */
1328 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
1330 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
1337 CRYPTUI_ENUM_DATA
*pEnumData
;
1338 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1340 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
1342 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
1349 CRYPTUI_ENUM_DATA
*pEnumData
;
1350 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1352 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
1366 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
1367 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
1370 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
1371 TVINSERTSTRUCTW tvis
;
1372 LPCWSTR localizedName
;
1375 tvis
.hParent
= NULL
;
1376 tvis
.hInsertAfter
= TVI_LAST
;
1377 tvis
.u
.item
.mask
= TVIF_TEXT
;
1378 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
1380 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(), 0,
1381 sizeof(struct StoreInfo
));
1385 storeInfo
->type
= SystemStore
;
1386 storeInfo
->u
.name
= HeapAlloc(GetProcessHeap(), 0,
1387 (strlenW(pvSystemStore
) + 1) * sizeof(WCHAR
));
1388 if (storeInfo
->u
.name
)
1390 tvis
.u
.item
.mask
|= TVIF_PARAM
;
1391 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1392 strcpyW(storeInfo
->u
.name
, pvSystemStore
);
1396 HeapFree(GetProcessHeap(), 0, storeInfo
);
1402 tvis
.u
.item
.pszText
= (LPWSTR
)localizedName
;
1405 tvis
.u
.item
.pszText
= (LPWSTR
)pvSystemStore
;
1406 /* FIXME: need a folder icon for the store too */
1408 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1412 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
1415 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1417 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
1418 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
1419 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
1420 hwnd
, enum_store_callback
);
1421 for (i
= 0; i
< pEnumData
->cStores
; i
++)
1425 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1426 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
1428 LPWSTR name
= HeapAlloc(GetProcessHeap(), 0, size
);
1432 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1433 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
1435 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(),
1436 0, sizeof(struct StoreInfo
));
1440 TVINSERTSTRUCTW tvis
;
1442 storeInfo
->type
= StoreHandle
;
1443 storeInfo
->u
.store
= pEnumData
->rghStore
[i
];
1444 tvis
.hParent
= NULL
;
1445 tvis
.hInsertAfter
= TVI_LAST
;
1446 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
1447 tvis
.u
.item
.pszText
= name
;
1448 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1449 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1452 HeapFree(GetProcessHeap(), 0, name
);
1458 static void free_store_info(HWND tree
)
1460 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
1467 memset(&item
, 0, sizeof(item
));
1468 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
1470 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1473 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1475 if (storeInfo
->type
== SystemStore
)
1476 HeapFree(GetProcessHeap(), 0, storeInfo
->u
.name
);
1477 HeapFree(GetProcessHeap(), 0, storeInfo
);
1479 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
1484 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
1486 WCHAR buf
[MAX_STRING_LEN
];
1490 memset(&item
, 0, sizeof(item
));
1491 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
1493 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
1495 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1498 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1500 if (storeInfo
->type
== StoreHandle
)
1501 store
= storeInfo
->u
.store
;
1503 store
= CertOpenSystemStoreW(0, storeInfo
->u
.name
);
1507 /* It's implicitly a system store */
1508 store
= CertOpenSystemStoreW(0, buf
);
1513 struct SelectStoreInfo
1515 PCRYPTUI_SELECTSTORE_INFO_W info
;
1519 static LRESULT CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1522 struct SelectStoreInfo
*selectInfo
;
1529 selectInfo
= (struct SelectStoreInfo
*)lp
;
1530 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
1531 if (selectInfo
->info
->pwszTitle
)
1532 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1533 (LPARAM
)selectInfo
->info
->pwszTitle
);
1534 if (selectInfo
->info
->pwszText
)
1535 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
1536 (LPARAM
)selectInfo
->info
->pwszText
);
1537 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
1538 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
1539 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
1547 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1548 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
1549 TVM_GETNEXTITEM
, TVGN_CARET
, 0);
1551 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
1555 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
1557 if (selectInfo
->info
->pwszTitle
)
1558 pTitle
= selectInfo
->info
->pwszTitle
;
1561 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
,
1562 sizeof(title
) / sizeof(title
[0]));
1565 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
,
1566 sizeof(error
) / sizeof(error
[0]));
1567 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
1571 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
1573 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
1574 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
1575 selectInfo
->info
->pvArg
))
1577 selectInfo
->store
= store
;
1578 free_store_info(tree
);
1579 EndDialog(hwnd
, IDOK
);
1582 CertCloseStore(store
, 0);
1588 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
1589 EndDialog(hwnd
, IDCANCEL
);
1598 /***********************************************************************
1599 * CryptUIDlgSelectStoreW (CRYPTUI.@)
1601 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
1603 struct SelectStoreInfo selectInfo
= { info
, NULL
};
1605 TRACE("(%p)\n", info
);
1607 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
1609 WARN("unexpected size %d\n", info
->dwSize
);
1610 SetLastError(E_INVALIDARG
);
1613 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
1614 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
1615 return selectInfo
.store
;
1618 /***********************************************************************
1619 * CryptUIDlgSelectStoreA (CRYPTUI.@)
1621 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
1623 CRYPTUI_SELECTSTORE_INFO_W infoW
;
1627 TRACE("(%p)\n", info
);
1629 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
1631 WARN("unexpected size %d\n", info
->dwSize
);
1632 SetLastError(E_INVALIDARG
);
1635 memcpy(&infoW
, info
, sizeof(*info
));
1638 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
1639 infoW
.pwszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1640 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
1645 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
1646 infoW
.pwszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1647 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
1649 ret
= CryptUIDlgSelectStoreW(&infoW
);
1650 HeapFree(GetProcessHeap(), 0, infoW
.pwszText
);
1651 HeapFree(GetProcessHeap(), 0, infoW
.pwszTitle
);
1655 /***********************************************************************
1656 * CryptUIDlgViewCertificateA (CRYPTUI.@)
1658 BOOL WINAPI
CryptUIDlgViewCertificateA(
1659 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
1661 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
1662 LPWSTR title
= NULL
;
1665 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
1667 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
1668 if (pCertViewInfo
->szTitle
)
1670 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
1673 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1676 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
1678 viewInfo
.szTitle
= title
;
1686 if (pCertViewInfo
->cPropSheetPages
)
1688 FIXME("ignoring additional prop sheet pages\n");
1689 viewInfo
.cPropSheetPages
= 0;
1691 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
1692 HeapFree(GetProcessHeap(), 0, title
);
1697 struct ReadStringStruct
1704 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
1707 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
1708 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
1710 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
1712 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
1714 *pcb
= cch
* sizeof(WCHAR
);
1718 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
1720 struct ReadStringStruct string
;
1721 EDITSTREAM editstream
;
1723 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
1728 editstream
.dwCookie
= (DWORD_PTR
)&string
;
1729 editstream
.dwError
= 0;
1730 editstream
.pfnCallback
= read_text_callback
;
1731 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
1732 (LPARAM
)&editstream
);
1735 static void add_string_resource_to_control(HWND hwnd
, int id
)
1740 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1741 add_unformatted_text_to_control(hwnd
, str
, len
);
1744 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
1745 LONG len
, const PARAFORMAT2
*fmt
)
1747 add_unformatted_text_to_control(hwnd
, text
, len
);
1748 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
1751 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
1752 const PARAFORMAT2
*fmt
)
1757 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1758 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
1761 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
1767 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
1770 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1772 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
1777 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
1778 DWORD dwType
, DWORD dwFlags
)
1780 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
1784 /* Don't include NULL-terminator in output */
1785 DWORD len
= lstrlenW(name
);
1787 add_unformatted_text_to_control(hwnd
, name
, len
);
1788 HeapFree(GetProcessHeap(), 0, name
);
1792 static void add_icon_to_control(HWND hwnd
, int id
)
1795 LPRICHEDITOLE richEditOle
= NULL
;
1796 LPOLEOBJECT object
= NULL
;
1798 LPOLECACHE oleCache
= NULL
;
1799 FORMATETC formatEtc
;
1801 LPDATAOBJECT dataObject
= NULL
;
1802 HBITMAP bitmap
= NULL
;
1804 LPOLECLIENTSITE clientSite
= NULL
;
1807 TRACE("(%p, %d)\n", hwnd
, id
);
1809 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
1812 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
1816 hr
= IOleObject_GetUserClassID(object
, &clsid
);
1819 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
1822 formatEtc
.cfFormat
= CF_BITMAP
;
1823 formatEtc
.ptd
= NULL
;
1824 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
1825 formatEtc
.lindex
= -1;
1826 formatEtc
.tymed
= TYMED_GDI
;
1827 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
1830 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
1831 (void**)&dataObject
);
1834 hr
= IRichEditOle_GetClientSite(richEditOle
, &clientSite
);
1837 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
1838 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
1841 stgm
.tymed
= TYMED_GDI
;
1842 stgm
.u
.hBitmap
= bitmap
;
1843 stgm
.pUnkForRelease
= NULL
;
1844 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
1848 reObject
.cbStruct
= sizeof(reObject
);
1849 reObject
.cp
= REO_CP_SELECTION
;
1850 reObject
.clsid
= clsid
;
1851 reObject
.poleobj
= object
;
1852 reObject
.pstg
= NULL
;
1853 reObject
.polesite
= clientSite
;
1854 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
1855 reObject
.dvaspect
= DVASPECT_CONTENT
;
1856 reObject
.dwFlags
= 0;
1857 reObject
.dwUser
= 0;
1859 IRichEditOle_InsertObject(richEditOle
, &reObject
);
1863 IOleClientSite_Release(clientSite
);
1865 IDataObject_Release(dataObject
);
1867 IOleCache_Release(oleCache
);
1869 IOleObject_Release(object
);
1871 IRichEditOle_Release(richEditOle
);
1874 #define MY_INDENT 200
1876 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
1879 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
1882 parFmt
.cbSize
= sizeof(parFmt
);
1883 parFmt
.dwMask
= PFM_STARTINDENT
;
1884 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1887 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
1888 lstrlenW(oidInfo
->pwszName
), &parFmt
);
1889 add_unformatted_text_to_control(hwnd
, &nl
, 1);
1899 /* The following list MUST be lexicographically sorted by OID */
1900 static struct OIDToString oidMap
[] = {
1901 /* 1.3.6.1.4.1.311.10.3.1 */
1902 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
1903 /* 1.3.6.1.4.1.311.10.3.4 */
1904 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
1905 /* 1.3.6.1.4.1.311.10.3.4.1 */
1906 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
1907 /* 1.3.6.1.4.1.311.10.3.5 */
1908 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
1909 /* 1.3.6.1.4.1.311.10.3.6 */
1910 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
1911 /* 1.3.6.1.4.1.311.10.3.7 */
1912 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
1913 /* 1.3.6.1.4.1.311.10.3.8 */
1914 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
1915 /* 1.3.6.1.4.1.311.10.3.9 */
1916 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
1917 /* 1.3.6.1.4.1.311.10.3.10 */
1918 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
1919 /* 1.3.6.1.4.1.311.10.3.11 */
1920 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
1921 /* 1.3.6.1.4.1.311.10.3.12 */
1922 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
1923 /* 1.3.6.1.4.1.311.10.3.13 */
1924 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
1925 /* 1.3.6.1.4.1.311.10.5.1 */
1926 { szOID_DRM
, IDS_PURPOSE_DRM
},
1927 /* 1.3.6.1.4.1.311.10.6.1 */
1928 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
1929 /* 1.3.6.1.4.1.311.10.6.2 */
1930 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
1931 /* 1.3.6.1.4.1.311.20.2.1 */
1932 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
1933 /* 1.3.6.1.4.1.311.20.2.2 */
1934 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
1935 /* 1.3.6.1.4.1.311.21.5 */
1936 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
1937 /* 1.3.6.1.4.1.311.21.6 */
1938 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
1939 /* 1.3.6.1.4.1.311.21.19 */
1940 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
1941 /* 1.3.6.1.5.5.7.3.1 */
1942 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
1943 /* 1.3.6.1.5.5.7.3.2 */
1944 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
1945 /* 1.3.6.1.5.5.7.3.3 */
1946 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
1947 /* 1.3.6.1.5.5.7.3.4 */
1948 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
1949 /* 1.3.6.1.5.5.7.3.5 */
1950 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
1951 /* 1.3.6.1.5.5.7.3.6 */
1952 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
1953 /* 1.3.6.1.5.5.7.3.7 */
1954 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
1955 /* 1.3.6.1.5.5.7.3.8 */
1956 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
1959 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
1961 int indexHigh
= sizeof(oidMap
) / sizeof(oidMap
[0]) - 1, indexLow
= 0;
1963 while (indexLow
<= indexHigh
)
1965 int cmp
, i
= (indexLow
+ indexHigh
) / 2;
1966 if (!(cmp
= strcmp(oid
, oidMap
[i
].oid
)))
1976 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
1978 struct OIDToString
*entry
;
1982 parFmt
.cbSize
= sizeof(parFmt
);
1983 parFmt
.dwMask
= PFM_STARTINDENT
;
1984 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1985 if ((entry
= findSupportedOID(oid
)))
1987 WCHAR
*str
, *linebreak
, *ptr
;
1988 BOOL multiline
= FALSE
;
1991 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
1994 if ((linebreak
= memchrW(ptr
, '\n', len
)))
1996 WCHAR copy
[MAX_STRING_LEN
];
1999 /* The source string contains a newline, which the richedit
2000 * control won't find since it's interpreted as a paragraph
2001 * break. Therefore copy up to the newline. lstrcpynW always
2002 * NULL-terminates, so pass one more than the length of the
2003 * source line so the copy includes the entire line and the
2006 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
2007 add_text_with_paraformat_to_control(text
, copy
,
2008 linebreak
- ptr
, &parFmt
);
2009 ptr
= linebreak
+ 1;
2010 add_unformatted_text_to_control(text
, &nl
, 1);
2012 else if (multiline
&& *ptr
)
2014 /* Add the last line */
2015 add_text_with_paraformat_to_control(text
, ptr
,
2016 len
- (ptr
- str
), &parFmt
);
2017 add_unformatted_text_to_control(text
, &nl
, 1);
2019 } while (linebreak
);
2022 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
2023 add_unformatted_text_to_control(text
, &nl
, 1);
2028 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
2029 (strlen(oid
) + 1) * sizeof(WCHAR
));
2036 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
2039 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
2041 add_unformatted_text_to_control(text
, &nl
, 1);
2042 HeapFree(GetProcessHeap(), 0, oidW
);
2047 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
2048 BOOL
*anyUsageAdded
)
2050 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
2052 CHARFORMATW charFmt
;
2053 PCERT_EXTENSION policyExt
;
2054 if (!*anyUsageAdded
)
2058 parFmt
.cbSize
= sizeof(parFmt
);
2059 parFmt
.dwMask
= PFM_STARTINDENT
;
2060 parFmt
.dxStartIndent
= MY_INDENT
;
2061 add_string_resource_with_paraformat_to_control(text
,
2062 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2063 add_unformatted_text_to_control(text
, &nl
, 1);
2064 *anyUsageAdded
= TRUE
;
2066 memset(&charFmt
, 0, sizeof(charFmt
));
2067 charFmt
.cbSize
= sizeof(charFmt
);
2068 charFmt
.dwMask
= CFM_BOLD
;
2069 charFmt
.dwEffects
= 0;
2070 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2071 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
2072 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
2074 CERT_POLICIES_INFO
*policies
;
2077 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
2078 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2079 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2083 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
2087 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2088 add_local_oid_text_to_control(text
,
2089 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2090 pszPolicyQualifierId
);
2092 LocalFree(policies
);
2096 add_oid_text_to_control(text
, any_app_policy
);
2099 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
2100 BOOL
*anyUsageAdded
)
2104 BOOL badUsages
= FALSE
;
2106 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
2108 CHARFORMATW charFmt
;
2109 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
2110 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
2114 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
2118 if (!*anyUsageAdded
)
2122 parFmt
.cbSize
= sizeof(parFmt
);
2123 parFmt
.dwMask
= PFM_STARTINDENT
;
2124 parFmt
.dxStartIndent
= MY_INDENT
;
2125 add_string_resource_with_paraformat_to_control(text
,
2126 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2127 add_unformatted_text_to_control(text
, &nl
, 1);
2128 *anyUsageAdded
= TRUE
;
2130 memset(&charFmt
, 0, sizeof(charFmt
));
2131 charFmt
.cbSize
= sizeof(charFmt
);
2132 charFmt
.dwMask
= CFM_BOLD
;
2133 charFmt
.dwEffects
= 0;
2134 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
2136 if (!usage
->cUsageIdentifier
)
2137 add_oid_text_to_control(text
, any_cert_policy
);
2139 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2140 add_local_oid_text_to_control(text
,
2141 usage
->rgpszUsageIdentifier
[i
]);
2145 HeapFree(GetProcessHeap(), 0, usage
);
2155 static void set_policy_text(HWND text
,
2156 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2158 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
2159 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
2161 if (pCertViewInfo
->cPurposes
)
2165 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
2167 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
2168 includeCertUsages
= TRUE
;
2169 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
2170 szOID_ANY_APPLICATION_POLICY
))
2171 includeAppUsages
= TRUE
;
2177 includeAppUsages
= includeCertUsages
= TRUE
;
2178 if (includeAppUsages
)
2179 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
2180 if (includeCertUsages
)
2181 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
2187 parFmt
.cbSize
= sizeof(parFmt
);
2188 parFmt
.dwMask
= PFM_STARTINDENT
;
2189 parFmt
.dxStartIndent
= MY_INDENT
;
2190 add_string_resource_with_paraformat_to_control(text
,
2191 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
2195 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
2198 CRYPT_OBJID_BLOB
*ret
= NULL
;
2201 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
2205 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2206 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2207 pszPolicyQualifierId
, policyOid
))
2208 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2214 static WCHAR
*get_cps_str_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2216 LPWSTR qualifierStr
= NULL
;
2217 CERT_NAME_VALUE
*qualifierValue
;
2220 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
2221 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2222 &qualifierValue
, &size
))
2224 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
2225 &qualifierValue
->Value
, NULL
, 0);
2226 qualifierStr
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
2228 CertRDNValueToStrW(qualifierValue
->dwValueType
,
2229 &qualifierValue
->Value
, qualifierStr
, size
);
2230 LocalFree(qualifierValue
);
2232 return qualifierStr
;
2235 static WCHAR
*get_user_notice_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2238 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
2241 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
2242 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
2243 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2244 &qualifierValue
, &size
))
2246 str
= HeapAlloc(GetProcessHeap(), 0,
2247 (strlenW(qualifierValue
->pszDisplayText
) + 1) * sizeof(WCHAR
));
2249 strcpyW(str
, qualifierValue
->pszDisplayText
);
2250 LocalFree(qualifierValue
);
2255 struct IssuerStatement
2261 static void set_issuer_statement(HWND hwnd
,
2262 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2264 PCERT_EXTENSION policyExt
;
2266 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
2267 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
2268 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
2269 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
2271 CERT_POLICIES_INFO
*policies
;
2274 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
2275 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2276 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2278 CRYPT_OBJID_BLOB
*qualifier
;
2279 LPWSTR cps
= NULL
, userNotice
= NULL
;
2281 if ((qualifier
= find_policy_qualifier(policies
,
2282 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
2283 cps
= get_cps_str_from_qualifier(qualifier
);
2284 if ((qualifier
= find_policy_qualifier(policies
,
2285 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
2286 userNotice
= get_user_notice_from_qualifier(qualifier
);
2287 if (cps
|| userNotice
)
2289 struct IssuerStatement
*issuerStatement
=
2290 HeapAlloc(GetProcessHeap(), 0, sizeof(struct IssuerStatement
));
2292 if (issuerStatement
)
2294 issuerStatement
->cps
= cps
;
2295 issuerStatement
->userNotice
= userNotice
;
2296 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
2297 SetWindowLongPtrW(hwnd
, DWLP_USER
,
2298 (ULONG_PTR
)issuerStatement
);
2301 LocalFree(policies
);
2306 static void set_cert_info(HWND hwnd
,
2307 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2309 CHARFORMATW charFmt
;
2311 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
2312 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
2313 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2314 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
2315 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
2316 pCertViewInfo
->idxCounterSigner
);
2317 CRYPT_PROVIDER_CERT
*root
=
2318 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
2320 if (!provSigner
->pChainContext
||
2321 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2322 CERT_TRUST_IS_PARTIAL_CHAIN
))
2323 add_icon_to_control(icon
, IDB_CERT_WARNING
);
2324 else if (!root
->fTrustedRoot
)
2325 add_icon_to_control(icon
, IDB_CERT_ERROR
);
2327 add_icon_to_control(icon
, IDB_CERT
);
2329 memset(&charFmt
, 0, sizeof(charFmt
));
2330 charFmt
.cbSize
= sizeof(charFmt
);
2331 charFmt
.dwMask
= CFM_BOLD
;
2332 charFmt
.dwEffects
= CFE_BOLD
;
2333 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2334 /* FIXME: vertically center text */
2335 parFmt
.cbSize
= sizeof(parFmt
);
2336 parFmt
.dwMask
= PFM_STARTINDENT
;
2337 parFmt
.dxStartIndent
= MY_INDENT
;
2338 add_string_resource_with_paraformat_to_control(text
,
2339 IDS_CERTIFICATEINFORMATION
, &parFmt
);
2341 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
2342 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2343 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
2344 add_string_resource_with_paraformat_to_control(text
,
2345 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
2346 else if (!provSigner
->pChainContext
||
2347 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2348 CERT_TRUST_IS_PARTIAL_CHAIN
))
2349 add_string_resource_with_paraformat_to_control(text
,
2350 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
2351 else if (!root
->fTrustedRoot
)
2353 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
2354 add_string_resource_with_paraformat_to_control(text
,
2355 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
2357 add_string_resource_with_paraformat_to_control(text
,
2358 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
2362 set_policy_text(text
, pCertViewInfo
);
2363 set_issuer_statement(hwnd
, pCertViewInfo
);
2367 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
2368 DWORD nameFlags
, int heading
)
2371 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2372 CHARFORMATW charFmt
;
2375 memset(&charFmt
, 0, sizeof(charFmt
));
2376 charFmt
.cbSize
= sizeof(charFmt
);
2377 charFmt
.dwMask
= CFM_BOLD
;
2378 charFmt
.dwEffects
= CFE_BOLD
;
2379 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2380 parFmt
.cbSize
= sizeof(parFmt
);
2381 parFmt
.dwMask
= PFM_STARTINDENT
;
2382 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2383 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
2384 charFmt
.dwEffects
= 0;
2385 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2386 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2388 add_unformatted_text_to_control(text
, &nl
, 1);
2389 add_unformatted_text_to_control(text
, &nl
, 1);
2390 add_unformatted_text_to_control(text
, &nl
, 1);
2394 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
2396 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
2400 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
2401 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2402 FileTimeToSystemTime(fileTime
, &sysTime
);
2403 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
2404 sizeof(date
) / sizeof(date
[0]));
2405 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
2408 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
2411 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2412 CHARFORMATW charFmt
;
2415 memset(&charFmt
, 0, sizeof(charFmt
));
2416 charFmt
.cbSize
= sizeof(charFmt
);
2417 charFmt
.dwMask
= CFM_BOLD
;
2418 charFmt
.dwEffects
= CFE_BOLD
;
2419 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2420 parFmt
.cbSize
= sizeof(parFmt
);
2421 parFmt
.dwMask
= PFM_STARTINDENT
;
2422 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2423 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
2425 charFmt
.dwEffects
= 0;
2426 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2427 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
2428 charFmt
.dwEffects
= CFE_BOLD
;
2429 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2430 add_string_resource_to_control(text
, IDS_VALID_TO
);
2431 charFmt
.dwEffects
= 0;
2432 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2433 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
2434 add_unformatted_text_to_control(text
, &nl
, 1);
2437 static void set_general_info(HWND hwnd
,
2438 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2440 set_cert_info(hwnd
, pCertViewInfo
);
2441 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
2442 IDS_SUBJECT_HEADING
);
2443 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
2444 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
2445 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
2448 static LRESULT CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2453 struct IssuerStatement
*issuerStatement
;
2458 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
2459 issuerStatement
= (struct IssuerStatement
*)lp
;
2460 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
2461 strlenW(issuerStatement
->userNotice
));
2462 if (issuerStatement
->cps
)
2463 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
2465 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
2471 EndDialog(hwnd
, IDOK
);
2476 IBindCtx
*bctx
= NULL
;
2479 CreateBindCtx(0, &bctx
);
2480 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2481 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
2482 HLNF_OPENINNEWWINDOW
, 0);
2483 IBindCtx_Release(bctx
);
2491 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
2493 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
2494 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
2497 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2500 PROPSHEETPAGEW
*page
;
2501 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2503 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2508 page
= (PROPSHEETPAGEW
*)lp
;
2509 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
2510 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
2511 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
2512 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
2513 set_general_info(hwnd
, pCertViewInfo
);
2518 case IDC_ADDTOSTORE
:
2519 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
2521 case IDC_ISSUERSTATEMENT
:
2523 struct IssuerStatement
*issuerStatement
=
2524 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2526 if (issuerStatement
)
2528 if (issuerStatement
->userNotice
)
2529 show_user_notice(hwnd
, issuerStatement
);
2530 else if (issuerStatement
->cps
)
2532 IBindCtx
*bctx
= NULL
;
2534 CreateBindCtx(0, &bctx
);
2535 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
2536 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
2537 IBindCtx_Release(bctx
);
2548 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
2549 PROPSHEETPAGEW
*page
)
2551 struct IssuerStatement
*issuerStatement
;
2557 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2558 if (issuerStatement
)
2560 HeapFree(GetProcessHeap(), 0, issuerStatement
->cps
);
2561 HeapFree(GetProcessHeap(), 0, issuerStatement
->userNotice
);
2562 HeapFree(GetProcessHeap(), 0, issuerStatement
);
2569 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2570 PROPSHEETPAGEW
*page
)
2572 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2573 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2574 page
->dwFlags
= PSP_USECALLBACK
;
2575 page
->pfnCallback
= general_callback_proc
;
2576 page
->hInstance
= hInstance
;
2577 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
2578 page
->pfnDlgProc
= general_dlg_proc
;
2579 page
->lParam
= (LPARAM
)pCertViewInfo
;
2582 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
2584 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
2586 static const WCHAR fmt
[] = { 'V','%','d',0 };
2587 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, 12 * sizeof(WCHAR
));
2590 sprintfW(buf
, fmt
, cert
->pCertInfo
->dwVersion
);
2594 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
2596 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, (cb
* 3 + 1) * sizeof(WCHAR
));
2600 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2604 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
2605 sprintfW(ptr
, fmt
, ((BYTE
*)pb
)[i
]);
2610 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
2612 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
2613 cert
->pCertInfo
->SerialNumber
.cbData
);
2616 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
2618 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2619 CERT_NAME_ISSUER_FLAG
);
2622 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
2625 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
2626 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, NULL
, 0);
2630 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2632 CertNameToStrW(X509_ASN_ENCODING
, name
,
2633 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, str
, len
);
2638 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
2640 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
2643 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
2645 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2648 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
2650 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
2653 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
2655 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
2660 /* FIXME: format isn't quite right, want time too */
2661 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
,
2662 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2663 FileTimeToSystemTime(fileTime
, &sysTime
);
2664 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
2667 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2669 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
2675 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
2677 return format_long_date(&cert
->pCertInfo
->NotBefore
);
2680 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
2682 return format_long_date(&cert
->pCertInfo
->NotAfter
);
2685 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
2687 PCCRYPT_OID_INFO oidInfo
;
2690 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2691 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
2694 WCHAR fmt
[MAX_STRING_LEN
];
2696 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
,
2697 sizeof(fmt
) / sizeof(fmt
[0])))
2701 /* Allocate the output buffer. Use the number of bytes in the
2702 * public key as a conservative (high) estimate for the number of
2703 * digits in its output.
2704 * The output is of the form (in English)
2705 * "<public key algorithm> (<public key bit length> bits)".
2706 * Ordinarily having two positional parameters in a string is not a
2707 * good idea, but as this isn't a sentence fragment, it shouldn't
2708 * be word-order dependent.
2710 len
= strlenW(fmt
) + strlenW(oidInfo
->pwszName
) +
2711 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8;
2712 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(*buf
));
2716 args
[0] = (DWORD_PTR
)oidInfo
->pwszName
;
2717 args
[1] = CertGetPublicKeyLength(X509_ASN_ENCODING
,
2718 &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2719 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
2720 fmt
, 0, 0, buf
, len
, (__ms_va_list
*)args
);
2727 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
2729 return format_hex_string(
2730 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
2731 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
2734 struct field_value_data
;
2737 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2738 BOOL
*pfPropertiesChanged
;
2740 struct field_value_data
*fields
;
2743 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
2745 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
2747 struct field_value_data
2749 create_detailed_value_func create
;
2750 LPWSTR detailed_value
;
2754 static void add_field_value_data(struct detail_data
*data
,
2755 create_detailed_value_func create
, void *param
)
2758 data
->fields
= HeapReAlloc(GetProcessHeap(), 0, data
->fields
,
2759 (data
->cFields
+ 1) * sizeof(struct field_value_data
));
2761 data
->fields
= HeapAlloc(GetProcessHeap(), 0,
2762 sizeof(struct field_value_data
));
2765 data
->fields
[data
->cFields
].create
= create
;
2766 data
->fields
[data
->cFields
].detailed_value
= NULL
;
2767 data
->fields
[data
->cFields
].param
= param
;
2772 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2773 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2776 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2778 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
2781 item
.pszText
= field
;
2782 item
.lParam
= (LPARAM
)data
;
2783 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2786 item
.pszText
= value
;
2788 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
2790 add_field_value_data(data
, create
, param
);
2793 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2794 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2796 WCHAR buf
[MAX_STRING_LEN
];
2798 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2799 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
2805 field_format_func format
;
2806 create_detailed_value_func create_detailed_value
;
2809 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
2810 const struct v1_field
*field
)
2812 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
2816 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
2817 field
->create_detailed_value
, NULL
);
2818 HeapFree(GetProcessHeap(), 0, val
);
2822 static const struct v1_field v1_fields
[] = {
2823 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
2824 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
2825 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
2826 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
2827 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
2828 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
2829 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
2830 field_format_detailed_public_key
}
2833 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
2836 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2838 /* The last item in v1_fields is the public key, which is not in the loop
2839 * because it's a special case.
2841 for (i
= 0; i
< sizeof(v1_fields
) / sizeof(v1_fields
[0]) - 1; i
++)
2842 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2843 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
2844 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2847 static WCHAR
*crypt_format_extension(const CERT_EXTENSION
*ext
, DWORD formatStrType
)
2852 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2853 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
2855 str
= HeapAlloc(GetProcessHeap(), 0, size
);
2856 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2857 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
2862 static WCHAR
*field_format_extension_hex_with_ascii(const CERT_EXTENSION
*ext
)
2866 if (ext
->Value
.cbData
)
2868 /* The output is formatted as:
2869 * <hex bytes> <ascii bytes>\n
2870 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
2871 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
2872 * the byte is not printable.
2873 * So, for example, the extension value consisting of the following
2875 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
2876 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
2878 * 30 14 31 12 30 10 06 03 0.1.0...
2879 * 55 04 03 13 09 4a 75 61 U....Jua
2880 * 6e 20 4c 61 6e 67 n Lang
2881 * The allocation size therefore requires:
2882 * - 4 characters per character in an 8-byte line
2883 * (2 for the hex format, one for the space, one for the ASCII value)
2884 * - 3 more characters per 8-byte line (two spaces and a newline)
2885 * - 1 character for the terminating nul
2886 * FIXME: should use a fixed-width font for this
2888 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
2890 str
= HeapAlloc(GetProcessHeap(), 0,
2891 (lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
2894 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2898 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
2900 /* Output as hex bytes first */
2901 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
2902 sprintfW(ptr
, fmt
, ext
->Value
.pbData
[j
]);
2903 /* Pad the hex output with spaces for alignment */
2904 if (j
== ext
->Value
.cbData
&& j
% 8)
2906 static const WCHAR pad
[] = { ' ',' ',' ' };
2908 for (; j
% 8; j
++, ptr
+= sizeof(pad
) / sizeof(pad
[0]))
2909 memcpy(ptr
, pad
, sizeof(pad
));
2911 /* The last sprintfW included a space, so just insert one
2912 * more space between the hex bytes and the ASCII output
2915 /* Output as ASCII bytes */
2916 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
2918 if (isprintW(ext
->Value
.pbData
[j
]) &&
2919 !isspaceW(ext
->Value
.pbData
[j
]))
2920 *ptr
= ext
->Value
.pbData
[j
];
2932 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
2934 PCERT_EXTENSION ext
= param
;
2935 LPWSTR str
= crypt_format_extension(ext
,
2936 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
2939 str
= field_format_extension_hex_with_ascii(ext
);
2943 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
2944 PCERT_EXTENSION ext
)
2946 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2948 LPWSTR val
= crypt_format_extension(ext
, 0);
2951 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
2952 val
, field_format_detailed_extension
, ext
);
2955 DWORD len
= strlen(ext
->pszObjId
);
2956 LPWSTR oidW
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
2962 for (i
= 0; i
<= len
; i
++)
2963 oidW
[i
] = ext
->pszObjId
[i
];
2964 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
2965 field_format_detailed_extension
, ext
);
2966 HeapFree(GetProcessHeap(), 0, oidW
);
2969 HeapFree(GetProcessHeap(), 0, val
);
2972 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
2975 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2977 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2978 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
2981 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
2984 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2986 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2987 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
2988 add_cert_extension_detail(hwnd
, data
,
2989 &cert
->pCertInfo
->rgExtension
[i
]);
2992 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
2994 struct prop_id_to_string_id
2998 BOOL prop_is_string
;
2999 prop_to_value_func prop_to_value
;
3002 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
3006 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
3007 ext
.fCritical
= FALSE
;
3008 ext
.Value
.pbData
= pb
;
3009 ext
.Value
.cbData
= cb
;
3010 return crypt_format_extension(&ext
, 0);
3013 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
3014 * disabled for read-only certificates, but native doesn't appear to do that.
3016 static const struct prop_id_to_string_id prop_id_map
[] = {
3017 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
3018 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
3019 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
3020 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
3021 format_enhanced_key_usage_value
},
3024 static void add_properties(HWND hwnd
, struct detail_data
*data
)
3027 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
3029 for (i
= 0; i
< sizeof(prop_id_map
) / sizeof(prop_id_map
[0]); i
++)
3033 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
3039 /* FIXME: MS adds a separate value for the signature hash
3042 pb
= HeapAlloc(GetProcessHeap(), 0, cb
);
3045 if (CertGetCertificateContextProperty(cert
,
3046 prop_id_map
[i
].prop
, pb
, &cb
))
3048 if (prop_id_map
[i
].prop_is_string
)
3051 /* Don't double-free pb */
3055 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
3057 HeapFree(GetProcessHeap(), 0, pb
);
3059 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
3065 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
3067 add_v1_fields(hwnd
, data
);
3068 add_all_extensions(hwnd
, data
);
3069 add_properties(hwnd
, data
);
3072 struct selection_list_item
3075 add_fields_func add
;
3078 static const struct selection_list_item listItems
[] = {
3079 { IDS_FIELDS_ALL
, add_all_fields
},
3080 { IDS_FIELDS_V1
, add_v1_fields
},
3081 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
3082 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
3083 { IDS_FIELDS_PROPERTIES
, add_properties
},
3086 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
3088 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3089 WCHAR buf
[MAX_STRING_LEN
];
3092 for (i
= 0; i
< sizeof(listItems
) / sizeof(listItems
[0]); i
++)
3096 LoadStringW(hInstance
, listItems
[i
].id
, buf
,
3097 sizeof(buf
) / sizeof(buf
[0]));
3098 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
3099 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
3101 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
3104 static void create_listview_columns(HWND hwnd
)
3106 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3108 WCHAR buf
[MAX_STRING_LEN
];
3111 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
3112 GetWindowRect(lv
, &rc
);
3113 LoadStringW(hInstance
, IDS_FIELD
, buf
, sizeof(buf
) / sizeof(buf
[0]));
3114 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
3115 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
3116 column
.pszText
= buf
;
3117 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3118 LoadStringW(hInstance
, IDS_VALUE
, buf
, sizeof(buf
) / sizeof(buf
[0]));
3119 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
3122 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
3124 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3126 if (sel
>= 0 && sel
< sizeof(listItems
) / sizeof(listItems
[0]))
3128 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
3129 listItems
[sel
].add(list
, data
);
3133 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
3135 create_show_list(hwnd
, data
);
3136 create_listview_columns(hwnd
);
3137 set_fields_selection(hwnd
, data
, 0);
3140 static void add_purpose(HWND hwnd
, LPCSTR oid
)
3142 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3143 PCRYPT_OID_INFO info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3144 sizeof(CRYPT_OID_INFO
));
3148 char *oidCopy
= HeapAlloc(GetProcessHeap(), 0, strlen(oid
) + 1);
3154 strcpy(oidCopy
, oid
);
3155 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
3156 info
->pszOID
= oidCopy
;
3157 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
3158 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
3159 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3160 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3162 item
.lParam
= (LPARAM
)info
;
3163 item
.pszText
= oidCopy
;
3164 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3167 HeapFree(GetProcessHeap(), 0, info
);
3171 static BOOL
is_valid_oid(LPCSTR oid
)
3175 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
3177 else if (oid
[1] != '.')
3184 BOOL expectNum
= TRUE
;
3186 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
3192 else if (*(ptr
+ 1) == '.')
3199 else if (!(*(ptr
+ 1)))
3209 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
3211 return find_oid_in_list(GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
), oid
)
3215 #define MAX_PURPOSE 255
3217 static LRESULT CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
3218 WPARAM wp
, LPARAM lp
)
3221 char buf
[MAX_PURPOSE
+ 1];
3226 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
3228 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
3229 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
3235 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
3237 /* Show/hide scroll bar on description depending on how much
3240 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
3241 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3243 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3250 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
,
3251 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3254 /* An empty purpose is the same as cancelling */
3255 EndDialog(hwnd
, IDCANCEL
);
3258 else if (!is_valid_oid(buf
))
3260 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3262 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
,
3263 sizeof(error
) / sizeof(error
[0]));
3264 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3265 sizeof(title
) / sizeof(title
[0]));
3266 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
3268 else if (is_oid_in_list(
3269 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
3271 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3273 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
,
3274 error
, sizeof(error
) / sizeof(error
[0]));
3275 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3276 sizeof(title
) / sizeof(title
[0]));
3277 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
3281 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3283 add_purpose(parent
, buf
);
3284 EndDialog(hwnd
, wp
);
3289 EndDialog(hwnd
, wp
);
3300 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
3305 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
3307 name
= HeapAlloc(GetProcessHeap(), 0, cb
);
3310 if (!CertGetCertificateContextProperty(cert
, prop
, name
, &cb
))
3312 HeapFree(GetProcessHeap(), 0, name
);
3320 static void redraw_states(HWND list
, BOOL enabled
)
3322 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
3324 for (i
= 0; i
< items
; i
++)
3326 BOOL change
= FALSE
;
3329 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
3330 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
3331 * to be a handy macro for it.
3336 if (state
== CheckBitmapIndexDisabledChecked
)
3338 state
= CheckBitmapIndexChecked
;
3341 if (state
== CheckBitmapIndexDisabledUnchecked
)
3343 state
= CheckBitmapIndexUnchecked
;
3349 if (state
== CheckBitmapIndexChecked
)
3351 state
= CheckBitmapIndexDisabledChecked
;
3354 if (state
== CheckBitmapIndexUnchecked
)
3356 state
= CheckBitmapIndexDisabledUnchecked
;
3364 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
3365 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3366 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
3372 PurposeEnableAll
= 0,
3374 PurposeEnableSelected
3377 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
3379 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3383 case PurposeEnableAll
:
3384 case PurposeDisableAll
:
3385 EnableWindow(lv
, FALSE
);
3386 redraw_states(lv
, FALSE
);
3387 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
3389 case PurposeEnableSelected
:
3390 EnableWindow(lv
, TRUE
);
3391 redraw_states(lv
, TRUE
);
3392 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
3396 struct edit_cert_data
3398 PCCERT_CONTEXT cert
;
3399 BOOL
*pfPropertiesChanged
;
3400 HIMAGELIST imageList
;
3403 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
3405 PCCERT_CONTEXT cert
= data
->cert
;
3406 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3407 PCERT_ENHKEY_USAGE usage
;
3411 PurposeSelection purposeSelection
= PurposeEnableAll
;
3413 GetWindowRect(lv
, &rc
);
3414 column
.mask
= LVCF_WIDTH
;
3415 column
.cx
= rc
.right
- rc
.left
;
3416 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3417 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
3419 /* Get enhanced key usage. Have to check for a property and an extension
3420 * separately, because CertGetEnhancedKeyUsage will succeed and return an
3421 * empty usage if neither is set. Unfortunately an empty usage implies
3422 * no usage is allowed, so we have to distinguish between the two cases.
3424 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
3427 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3428 if (!CertGetEnhancedKeyUsage(cert
,
3429 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3431 HeapFree(GetProcessHeap(), 0, usage
);
3434 else if (usage
->cUsageIdentifier
)
3435 purposeSelection
= PurposeEnableSelected
;
3437 purposeSelection
= PurposeDisableAll
;
3439 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
3442 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3443 if (!CertGetEnhancedKeyUsage(cert
,
3444 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3446 HeapFree(GetProcessHeap(), 0, usage
);
3449 else if (usage
->cUsageIdentifier
)
3450 purposeSelection
= PurposeEnableAll
;
3452 purposeSelection
= PurposeDisableAll
;
3456 purposeSelection
= PurposeEnableAll
;
3463 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
3465 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
3466 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
3469 add_known_usage(lv
, info
, CheckBitmapIndexDisabledChecked
);
3471 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
3473 HeapFree(GetProcessHeap(), 0, usage
);
3476 add_known_usages_to_list(lv
, CheckBitmapIndexDisabledChecked
);
3477 select_purposes(hwnd
, purposeSelection
);
3478 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
3482 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
3484 PCCERT_CONTEXT cert
= data
->cert
;
3487 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
3489 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
3491 HeapFree(GetProcessHeap(), 0, str
);
3493 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
3495 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
3497 HeapFree(GetProcessHeap(), 0, str
);
3499 show_cert_usages(hwnd
, data
);
3502 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
3505 if (str
&& strlenW(str
))
3507 CRYPT_DATA_BLOB blob
;
3509 blob
.pbData
= (BYTE
*)str
;
3510 blob
.cbData
= (strlenW(str
) + 1) * sizeof(WCHAR
);
3511 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
3514 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
3517 #define WM_REFRESH_VIEW WM_USER + 0
3519 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
3521 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
3522 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
3526 #define MAX_FRIENDLY_NAME 40
3527 #define MAX_DESCRIPTION 255
3529 static void apply_general_changes(HWND hwnd
)
3531 WCHAR buf
[MAX_DESCRIPTION
+ 1];
3532 struct edit_cert_data
*data
=
3533 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3535 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
,
3536 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3537 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
3538 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
,
3539 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3540 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
3541 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
3543 /* Setting a NULL usage removes the enhanced key usage property. */
3544 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
3546 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
3548 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3550 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3552 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
3554 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3555 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3556 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
3559 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3561 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3562 for (i
= 0; i
< purposes
; i
++)
3565 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
3567 int state
= item
.state
>> 12;
3569 if (state
== CheckBitmapIndexChecked
)
3571 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
3573 if (usage
.cUsageIdentifier
)
3574 usage
.rgpszUsageIdentifier
=
3575 HeapReAlloc(GetProcessHeap(), 0,
3576 usage
.rgpszUsageIdentifier
,
3577 (usage
.cUsageIdentifier
+ 1) * sizeof(LPSTR
));
3579 usage
.rgpszUsageIdentifier
=
3580 HeapAlloc(GetProcessHeap(), 0, sizeof(LPSTR
));
3581 if (usage
.rgpszUsageIdentifier
)
3582 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
3583 (LPSTR
)info
->pszOID
;
3587 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3588 HeapFree(GetProcessHeap(), 0, usage
.rgpszUsageIdentifier
);
3590 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
3591 if (data
->pfPropertiesChanged
)
3592 *data
->pfPropertiesChanged
= TRUE
;
3595 static LRESULT CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
3596 WPARAM wp
, LPARAM lp
)
3598 PROPSHEETPAGEW
*page
;
3600 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3606 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3607 struct detail_data
*detailData
;
3608 struct edit_cert_data
*editData
;
3610 page
= (PROPSHEETPAGEW
*)lp
;
3611 detailData
= (struct detail_data
*)page
->lParam
;
3612 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
3613 MAX_FRIENDLY_NAME
, 0);
3614 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
3615 ShowScrollBar(description
, SB_VERT
, FALSE
);
3616 editData
= HeapAlloc(GetProcessHeap(), 0,
3617 sizeof(struct edit_cert_data
));
3620 editData
->imageList
= ImageList_Create(16, 16,
3621 ILC_COLOR4
| ILC_MASK
, 4, 0);
3622 if (editData
->imageList
)
3625 COLORREF backColor
= RGB(255, 0, 255);
3627 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
3628 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
3630 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
3632 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
3633 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
3634 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
3635 set_general_cert_properties(hwnd
, editData
);
3641 NMHDR
*hdr
= (NMHDR
*)lp
;
3647 nm
= (NMITEMACTIVATE
*)lp
;
3648 toggle_usage(hwnd
, nm
->iItem
);
3649 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3652 apply_general_changes(hwnd
);
3661 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3662 if (LOWORD(wp
) == IDC_DESCRIPTION
)
3664 /* Show/hide scroll bar on description depending on how much
3667 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3668 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3670 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3676 case IDC_ADD_PURPOSE
:
3677 if (DialogBoxParamW(hInstance
,
3678 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
3679 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
3680 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3682 case IDC_ENABLE_ALL_PURPOSES
:
3683 case IDC_DISABLE_ALL_PURPOSES
:
3684 case IDC_ENABLE_SELECTED_PURPOSES
:
3685 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3686 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
3696 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
3697 PROPSHEETPAGEW
*page
)
3701 struct edit_cert_data
*data
;
3706 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3707 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3708 for (i
= 0; i
< cItem
; i
++)
3712 item
.mask
= LVIF_PARAM
;
3715 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
3717 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
3719 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
3721 HeapFree(GetProcessHeap(), 0, (LPSTR
)info
->pszOID
);
3722 HeapFree(GetProcessHeap(), 0, info
);
3726 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3729 ImageList_Destroy(data
->imageList
);
3730 HeapFree(GetProcessHeap(), 0, data
);
3737 static void show_edit_cert_properties_dialog(HWND parent
,
3738 struct detail_data
*data
)
3740 PROPSHEETHEADERW hdr
;
3741 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
3743 TRACE("(%p)\n", data
);
3745 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
3746 page
.dwSize
= sizeof(page
);
3747 page
.dwFlags
= PSP_USECALLBACK
;
3748 page
.pfnCallback
= cert_properties_general_callback
;
3749 page
.hInstance
= hInstance
;
3750 page
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
3751 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
3752 page
.lParam
= (LPARAM
)data
;
3754 memset(&hdr
, 0, sizeof(hdr
));
3755 hdr
.dwSize
= sizeof(hdr
);
3756 hdr
.hwndParent
= parent
;
3757 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
3758 hdr
.hInstance
= hInstance
;
3759 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
3760 hdr
.u3
.ppsp
= &page
;
3762 PropertySheetW(&hdr
);
3765 static void free_detail_fields(struct detail_data
*data
)
3769 for (i
= 0; i
< data
->cFields
; i
++)
3770 HeapFree(GetProcessHeap(), 0, data
->fields
[i
].detailed_value
);
3771 HeapFree(GetProcessHeap(), 0, data
->fields
);
3772 data
->fields
= NULL
;
3776 static void refresh_details_view(HWND hwnd
)
3778 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3780 struct detail_data
*data
;
3782 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3783 /* Actually, any index will do, since they all store the same data value */
3784 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
3785 free_detail_fields(data
);
3786 set_fields_selection(hwnd
, data
, curSel
);
3789 static LRESULT CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3792 PROPSHEETPAGEW
*page
;
3793 struct detail_data
*data
;
3795 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3800 page
= (PROPSHEETPAGEW
*)lp
;
3801 data
= (struct detail_data
*)page
->lParam
;
3802 create_cert_details_list(hwnd
, data
);
3803 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
3804 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
3805 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
3806 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
3811 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3813 nm
= (NMITEMACTIVATE
*)lp
;
3814 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
3815 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
3817 data
= (struct detail_data
*)nm
->lParam
;
3818 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
3820 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
3821 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
3823 if (data
->fields
[nm
->iItem
].create
)
3824 val
= data
->fields
[nm
->iItem
].create(
3825 data
->pCertViewInfo
->pCertContext
,
3826 data
->fields
[nm
->iItem
].param
);
3832 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
3833 item
.mask
= LVIF_TEXT
;
3835 item
.iItem
= nm
->iItem
;
3837 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
3841 /* Select all the text in the control, the next update will
3844 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
3845 add_unformatted_text_to_control(valueCtl
, val
,
3846 val
? strlenW(val
) : 0);
3848 HeapFree(GetProcessHeap(), 0, val
);
3858 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3859 CRYPTUI_WIZ_EXPORT_INFO info
;
3861 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, 0, 0);
3862 info
.dwSize
= sizeof(info
);
3863 info
.pwszExportFileName
= NULL
;
3864 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
3865 info
.u
.pCertContext
= data
->pCertViewInfo
->pCertContext
;
3867 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
3870 case IDC_EDITPROPERTIES
:
3872 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3875 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3876 /* Actually, any index will do, since they all store the same
3879 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
3881 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
3884 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
3885 refresh_details_view(hwnd
);
3889 case WM_REFRESH_VIEW
:
3890 refresh_details_view(hwnd
);
3896 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
3897 PROPSHEETPAGEW
*page
)
3899 struct detail_data
*data
;
3904 data
= (struct detail_data
*)page
->lParam
;
3905 free_detail_fields(data
);
3906 HeapFree(GetProcessHeap(), 0, data
);
3912 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3913 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
3916 struct detail_data
*data
= HeapAlloc(GetProcessHeap(), 0,
3917 sizeof(struct detail_data
));
3921 data
->pCertViewInfo
= pCertViewInfo
;
3922 data
->pfPropertiesChanged
= pfPropertiesChanged
;
3924 data
->fields
= NULL
;
3925 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3926 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3927 page
->dwFlags
= PSP_USECALLBACK
;
3928 page
->pfnCallback
= detail_callback
;
3929 page
->hInstance
= hInstance
;
3930 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
3931 page
->pfnDlgProc
= detail_dlg_proc
;
3932 page
->lParam
= (LPARAM
)data
;
3940 struct hierarchy_data
3942 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
3943 HIMAGELIST imageList
;
3947 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
3949 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3950 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3951 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3952 data
->pCertViewInfo
->idxCounterSigner
);
3954 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
3955 * therefore always even.
3957 if (index
== provSigner
->csCertChain
- 1)
3958 return (LPARAM
)data
;
3959 return index
<< 1 | 1;
3962 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
3964 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3965 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3966 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3967 data
->pCertViewInfo
->idxCounterSigner
);
3970 return provSigner
->csCertChain
- 1;
3974 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
3977 struct hierarchy_data
*data
= NULL
;
3978 HTREEITEM root
= NULL
;
3981 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
3982 TVGN_PARENT
, (LPARAM
)hItem
);
3992 item
.mask
= TVIF_PARAM
;
3994 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
3995 data
= (struct hierarchy_data
*)item
.lParam
;
4000 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
4002 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
4005 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
4009 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
4011 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4012 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4013 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4014 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
4015 data
->pCertViewInfo
->idxCounterSigner
);
4017 HTREEITEM parent
= NULL
;
4019 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
4020 for (i
= provSigner
->csCertChain
; i
; i
--)
4024 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
4027 TVINSERTSTRUCTW tvis
;
4029 tvis
.hParent
= parent
;
4030 tvis
.hInsertAfter
= TVI_LAST
;
4031 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
4032 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
4033 tvis
.u
.item
.pszText
= name
;
4034 tvis
.u
.item
.state
= TVIS_EXPANDED
;
4035 tvis
.u
.item
.stateMask
= TVIS_EXPANDED
;
4036 if (i
== 1 && (!provSigner
->pChainContext
||
4037 provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
4038 CERT_TRUST_IS_PARTIAL_CHAIN
))
4040 /* The root of the chain has a special case: if the chain is
4041 * a partial chain, the icon is a warning icon rather than an
4044 tvis
.u
.item
.iImage
= 2;
4046 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
4048 tvis
.u
.item
.iImage
= 0;
4050 tvis
.u
.item
.iImage
= 1;
4051 tvis
.u
.item
.iSelectedImage
= tvis
.u
.item
.iImage
;
4052 tvis
.u
.item
.lParam
= index_to_lparam(data
, i
- 1);
4053 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
4055 HeapFree(GetProcessHeap(), 0, name
);
4060 static void set_certificate_status(HWND hwnd
, const CRYPT_PROVIDER_CERT
*cert
)
4062 /* Select all the text in the control, the next update will replace it */
4063 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
4064 /* Set the highest priority error messages first. */
4065 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
4066 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
4067 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
4068 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
4069 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
4070 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
4071 else if (cert
->dwRevokedReason
)
4072 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
4074 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
4077 static void set_certificate_status_for_end_cert(HWND hwnd
,
4078 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
4080 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
4081 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4082 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
4083 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
4084 pCertViewInfo
->idxCounterSigner
);
4085 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
4086 pCertViewInfo
->idxCert
);
4088 set_certificate_status(status
, provCert
);
4091 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
4093 /* Disable view certificate button until a certificate is selected */
4094 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
4095 show_cert_chain(hwnd
, data
);
4096 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
4099 static void show_dialog_for_selected_cert(HWND hwnd
)
4101 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4103 struct hierarchy_data
*data
;
4106 memset(&item
, 0, sizeof(item
));
4107 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4108 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
, 0);
4109 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4110 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4111 selection
= lparam_to_index(data
, item
.lParam
);
4114 CRYPT_PROVIDER_SGNR
*provSigner
;
4115 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4116 BOOL changed
= FALSE
;
4118 provSigner
= WTHelperGetProvSignerFromChain(
4119 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4120 data
->pCertViewInfo
->idxSigner
,
4121 data
->pCertViewInfo
->fCounterSigner
,
4122 data
->pCertViewInfo
->idxCounterSigner
);
4123 memset(&viewInfo
, 0, sizeof(viewInfo
));
4124 viewInfo
.dwSize
= sizeof(viewInfo
);
4125 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
4126 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
4127 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
4128 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
4129 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
4130 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
4131 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
4132 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
4133 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
4136 /* Delete the contents of the tree */
4137 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4138 /* Reinitialize the tree */
4139 show_cert_hierarchy(hwnd
, data
);
4144 static LRESULT CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4147 PROPSHEETPAGEW
*page
;
4148 struct hierarchy_data
*data
;
4150 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4152 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
4157 page
= (PROPSHEETPAGEW
*)lp
;
4158 data
= (struct hierarchy_data
*)page
->lParam
;
4159 show_cert_hierarchy(hwnd
, data
);
4168 case TVN_SELCHANGEDW
:
4170 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
4172 CRYPT_PROVIDER_SGNR
*provSigner
;
4174 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
4175 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
4176 provSigner
= WTHelperGetProvSignerFromChain(
4177 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4178 data
->pCertViewInfo
->idxSigner
,
4179 data
->pCertViewInfo
->fCounterSigner
,
4180 data
->pCertViewInfo
->idxCounterSigner
);
4181 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
4182 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
4183 &provSigner
->pasCertChain
[selection
]);
4187 show_dialog_for_selected_cert(hwnd
);
4188 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4197 case IDC_VIEWCERTIFICATE
:
4198 show_dialog_for_selected_cert(hwnd
);
4202 case WM_REFRESH_VIEW
:
4206 /* Get hierarchy data */
4207 memset(&item
, 0, sizeof(item
));
4208 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4209 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
4211 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4212 /* Delete the contents of the tree */
4213 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4214 /* Reinitialize the tree */
4215 show_cert_hierarchy(hwnd
, data
);
4222 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
4223 PROPSHEETPAGEW
*page
)
4225 struct hierarchy_data
*data
;
4230 data
= (struct hierarchy_data
*)page
->lParam
;
4231 ImageList_Destroy(data
->imageList
);
4232 HeapFree(GetProcessHeap(), 0, data
);
4238 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4239 PROPSHEETPAGEW
*page
)
4241 struct hierarchy_data
*data
= HeapAlloc(GetProcessHeap(), 0,
4242 sizeof(struct hierarchy_data
));
4247 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
4248 if (data
->imageList
)
4251 COLORREF backColor
= RGB(255, 0, 255);
4253 data
->pCertViewInfo
= pCertViewInfo
;
4254 data
->selectedCert
= 0xffffffff;
4256 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
4257 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
4259 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
4261 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
4262 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
4263 page
->dwFlags
= PSP_USECALLBACK
;
4264 page
->hInstance
= hInstance
;
4265 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
4266 page
->pfnDlgProc
= hierarchy_dlg_proc
;
4267 page
->lParam
= (LPARAM
)data
;
4268 page
->pfnCallback
= hierarchy_callback
;
4272 HeapFree(GetProcessHeap(), 0, data
);
4277 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
4281 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
4285 case PSCB_INITIALIZED
:
4286 /* Get cancel button's position.. */
4287 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
4288 MapWindowPoints( 0, hwnd
, (POINT
*)&rc
, 2 );
4289 /* hide the cancel button.. */
4290 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
4291 /* and move the OK button to the cancel button's original position. */
4292 SetWindowPos(GetDlgItem(hwnd
, IDOK
), 0, rc
.left
, rc
.top
, 0, 0,
4293 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
4299 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4300 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
4302 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
4304 PROPSHEETPAGEW
*pages
;
4306 HMODULE lib
= LoadLibraryW(riched
);
4308 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
4309 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4311 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4313 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
4316 PROPSHEETHEADERW hdr
;
4317 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
4320 memset(&hdr
, 0, sizeof(hdr
));
4321 hdr
.dwSize
= sizeof(hdr
);
4322 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
4323 hdr
.hInstance
= hInstance
;
4324 if (pCertViewInfo
->szTitle
)
4325 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
4327 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
4328 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
4329 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4331 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
4332 &pages
[hdr
.nPages
]))
4335 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4337 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
4340 /* Copy each additional page, and create the init dialog struct for it
4342 if (pCertViewInfo
->cPropSheetPages
)
4344 init
= HeapAlloc(GetProcessHeap(), 0,
4345 pCertViewInfo
->cPropSheetPages
*
4346 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
4349 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
4351 memcpy(&pages
[hdr
.nPages
+ i
],
4352 &pCertViewInfo
->rgPropSheetPages
[i
],
4353 sizeof(PROPSHEETPAGEW
));
4354 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
4355 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
4356 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
4358 if (pCertViewInfo
->nStartPage
& 0x8000)
4360 /* Start page index is relative to the number of default
4363 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
4366 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
4367 hdr
.nPages
= nPages
;
4371 SetLastError(ERROR_OUTOFMEMORY
);
4375 /* Ignore the relative flag if there aren't any additional pages */
4376 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
4383 hdr
.u3
.ppsp
= pages
;
4384 hdr
.pfnCallback
= cert_prop_sheet_proc
;
4385 l
= PropertySheetW(&hdr
);
4388 SetLastError(ERROR_CANCELLED
);
4392 HeapFree(GetProcessHeap(), 0, init
);
4393 HeapFree(GetProcessHeap(), 0, pages
);
4396 SetLastError(ERROR_OUTOFMEMORY
);
4401 /***********************************************************************
4402 * CryptUIDlgViewCertificateW (CRYPTUI.@)
4404 BOOL WINAPI
CryptUIDlgViewCertificateW(
4405 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
4407 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
4408 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4410 WINTRUST_CERT_INFO cert
;
4412 CRYPT_PROVIDER_SGNR
*signer
;
4413 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
4415 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
4417 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
4419 SetLastError(ERROR_INVALID_PARAMETER
);
4422 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
4423 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
4424 if (!pCertViewInfo
->u
.hWVTStateData
)
4426 memset(&wvt
, 0, sizeof(wvt
));
4427 wvt
.cbStruct
= sizeof(wvt
);
4428 wvt
.dwUIChoice
= WTD_UI_NONE
;
4429 if (viewInfo
.dwFlags
&
4430 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
4431 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
4432 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
4433 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
4434 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
4435 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
4436 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
4437 memset(&cert
, 0, sizeof(cert
));
4438 cert
.cbStruct
= sizeof(cert
);
4439 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
4440 cert
.chStores
= viewInfo
.cStores
;
4441 cert
.pahStores
= viewInfo
.rghStores
;
4442 wvt
.u
.pCert
= &cert
;
4443 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
4444 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4445 viewInfo
.u
.pCryptProviderData
=
4446 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
4447 signer
= WTHelperGetProvSignerFromChain(
4448 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
4449 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
4454 viewInfo
.u
.pCryptProviderData
=
4455 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
4456 signer
= WTHelperGetProvSignerFromChain(
4457 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
4458 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
4459 viewInfo
.idxCounterSigner
);
4460 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
4465 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
4466 if (!pCertViewInfo
->u
.hWVTStateData
)
4468 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
4469 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4475 /***********************************************************************
4476 * CryptUIDlgViewContext (CRYPTUI.@)
4478 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
4479 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
4483 TRACE("(%d, %p, %p, %s, %08x, %p)\n", dwContextType
, pvContext
, hwnd
,
4484 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
4486 switch (dwContextType
)
4488 case CERT_STORE_CERTIFICATE_CONTEXT
:
4490 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4492 memset(&viewInfo
, 0, sizeof(viewInfo
));
4493 viewInfo
.dwSize
= sizeof(viewInfo
);
4494 viewInfo
.hwndParent
= hwnd
;
4495 viewInfo
.szTitle
= pwszTitle
;
4496 viewInfo
.pCertContext
= pvContext
;
4497 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
4501 FIXME("unimplemented for context type %d\n", dwContextType
);
4502 SetLastError(E_INVALIDARG
);
4508 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
4509 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
4510 * should be a CA. If neither extension is present, returns
4511 * defaultIfNotSpecified.
4513 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
4515 BOOL isCA
= defaultIfNotSpecified
;
4516 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
4517 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4521 CERT_BASIC_CONSTRAINTS_INFO
*info
;
4524 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
4525 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
4526 NULL
, &info
, &size
))
4528 if (info
->SubjectType
.cbData
== 1)
4529 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
4535 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
4536 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4539 CERT_BASIC_CONSTRAINTS2_INFO info
;
4540 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4542 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
4543 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
4544 0, NULL
, &info
, &size
))
4551 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
4555 if (is_ca_cert(cert
, TRUE
))
4558 storeName
= addressBook
;
4559 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4560 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
4563 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
4570 SetLastError(E_INVALIDARG
);
4573 if (hDestCertStore
) store
= hDestCertStore
;
4576 if (!(store
= choose_store_for_cert(cert
)))
4578 WARN("unable to open certificate store\n");
4582 ret
= CertAddCertificateContextToStore(store
, cert
,
4583 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4584 if (!hDestCertStore
) CertCloseStore(store
, 0);
4588 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
4595 SetLastError(E_INVALIDARG
);
4598 if (hDestCertStore
) store
= hDestCertStore
;
4601 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4602 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
4604 WARN("unable to open certificate store\n");
4608 ret
= CertAddCRLContextToStore(store
, crl
,
4609 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4610 if (!hDestCertStore
) CertCloseStore(store
, 0);
4614 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
4621 SetLastError(E_INVALIDARG
);
4624 if (hDestCertStore
) store
= hDestCertStore
;
4627 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
4629 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4630 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
4632 WARN("unable to open certificate store\n");
4636 ret
= CertAddCTLContextToStore(store
, ctl
,
4637 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4638 if (!hDestCertStore
) CertCloseStore(store
, 0);
4642 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
4643 * CryptQueryObject, against the allowed types. Returns TRUE if the
4644 * type is allowed, FALSE otherwise.
4646 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
4651 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4652 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4656 case CERT_QUERY_CONTENT_CERT
:
4657 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4658 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
4660 case CERT_QUERY_CONTENT_CRL
:
4661 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4662 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
4664 case CERT_QUERY_CONTENT_CTL
:
4665 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4666 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
4669 /* The remaining types contain more than one type, so allow
4677 /* No allowed types specified, so any type is allowed */
4681 SetLastError(E_INVALIDARG
);
4686 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4689 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4691 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4698 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
4699 sizeof(title
) / sizeof(title
[0]));
4702 LoadStringW(hInstance
, warningID
, error
,
4703 sizeof(error
) / sizeof(error
[0]));
4704 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
4708 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
4710 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
4713 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
4718 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4719 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4721 PCCERT_CONTEXT cert
;
4726 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
4728 CertFreeCertificateContext(cert
);
4729 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
4732 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
4734 CertFreeCRLContext(crl
);
4735 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
4738 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
4740 CertFreeCTLContext(ctl
);
4741 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4748 SetLastError(E_INVALIDARG
);
4752 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4753 HCERTSTORE source
, HCERTSTORE dest
)
4757 if ((ret
= check_store_context_type(dwFlags
, source
)))
4759 PCCERT_CONTEXT cert
= NULL
;
4760 PCCRL_CONTEXT crl
= NULL
;
4761 PCCTL_CONTEXT ctl
= NULL
;
4764 cert
= CertEnumCertificatesInStore(source
, cert
);
4766 ret
= import_cert(cert
, dest
);
4767 } while (ret
&& cert
);
4769 crl
= CertEnumCRLsInStore(source
, crl
);
4771 ret
= import_crl(crl
, dest
);
4772 } while (ret
&& crl
);
4774 ctl
= CertEnumCTLsInStore(source
, ctl
);
4776 ret
= import_ctl(ctl
, dest
);
4777 } while (ret
&& ctl
);
4780 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
4784 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
4785 DWORD
*pContentType
)
4787 HCERTSTORE store
= NULL
;
4788 DWORD contentType
= 0, expectedContentTypeFlags
;
4791 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4792 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4794 expectedContentTypeFlags
=
4795 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4796 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4797 CERT_QUERY_CONTENT_FLAG_PFX
;
4798 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
4799 expectedContentTypeFlags
|=
4800 CERT_QUERY_CONTENT_FLAG_CERT
|
4801 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
4802 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
4803 expectedContentTypeFlags
|=
4804 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4805 CERT_QUERY_CONTENT_FLAG_CRL
;
4806 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
4807 expectedContentTypeFlags
|=
4808 CERT_QUERY_CONTENT_FLAG_CTL
|
4809 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
4812 expectedContentTypeFlags
=
4813 CERT_QUERY_CONTENT_FLAG_CERT
|
4814 CERT_QUERY_CONTENT_FLAG_CTL
|
4815 CERT_QUERY_CONTENT_FLAG_CRL
|
4816 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4817 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
4818 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
4819 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4820 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4821 CERT_QUERY_CONTENT_FLAG_PFX
;
4823 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
4824 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
4825 &contentType
, NULL
, &store
, NULL
, NULL
);
4827 *pContentType
= contentType
;
4831 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4832 LPCWSTR fileName
, HCERTSTORE dest
)
4837 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
4839 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
4840 CertCloseStore(source
, 0);
4847 struct ImportWizData
4851 LPCWSTR pwszWizardTitle
;
4852 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
4856 HCERTSTORE hDestCertStore
;
4862 static LRESULT CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4871 struct ImportWizData
*data
;
4872 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4873 WCHAR fontFace
[MAX_STRING_LEN
];
4874 HDC hDC
= GetDC(hwnd
);
4877 data
= (struct ImportWizData
*)page
->lParam
;
4878 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
4879 sizeof(fontFace
) / sizeof(fontFace
[0]));
4880 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
4881 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
4882 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
4883 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
4884 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4885 (WPARAM
)data
->titleFont
, TRUE
);
4886 ReleaseDC(hwnd
, hDC
);
4891 NMHDR
*hdr
= (NMHDR
*)lp
;
4896 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
4906 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
4908 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
4910 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
4911 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
4912 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
4913 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
4915 static const WCHAR filter_all
[] = { '*','.','*',0 };
4917 static struct StringToFilter
4922 } import_filters
[] = {
4923 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
4924 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
4925 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
4926 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
4927 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
4928 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
4929 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
4932 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
4935 int len
, totalLen
= 2;
4936 LPWSTR filter
= NULL
, str
;
4938 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4940 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4941 (dwFlags
& import_filters
[i
].allowFlags
))
4943 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
4944 totalLen
+= len
+ strlenW(import_filters
[i
].filter
) + 2;
4947 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
4953 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4955 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4956 (dwFlags
& import_filters
[i
].allowFlags
))
4958 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
4960 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
4963 strcpyW(ptr
, import_filters
[i
].filter
);
4964 ptr
+= strlenW(import_filters
[i
].filter
) + 1;
4972 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
4978 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
4979 OPEN_EXISTING
, 0, NULL
);
4980 if (file
!= INVALID_HANDLE_VALUE
)
4982 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
4983 &data
->contentType
);
4987 warningID
= IDS_IMPORT_BAD_FORMAT
;
4988 else if (!check_store_context_type(data
->dwFlags
, source
))
4989 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
4992 data
->importSrc
.dwSubjectChoice
=
4993 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
4994 data
->importSrc
.u
.hCertStore
= source
;
4995 data
->freeSource
= TRUE
;
5000 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5007 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5009 LPWSTR msgBuf
, fullError
;
5011 if (data
->pwszWizardTitle
)
5012 pTitle
= data
->pwszWizardTitle
;
5015 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
5016 sizeof(title
) / sizeof(title
[0]));
5019 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
5020 sizeof(error
) / sizeof(error
[0]));
5022 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
5023 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
5024 fullError
= HeapAlloc(GetProcessHeap(), 0,
5025 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
5029 LPWSTR ptr
= fullError
;
5031 strcpyW(ptr
, error
);
5032 ptr
+= strlenW(error
);
5033 strcpyW(ptr
, fileName
);
5034 ptr
+= strlenW(fileName
);
5037 strcpyW(ptr
, msgBuf
);
5038 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
5039 HeapFree(GetProcessHeap(), 0, fullError
);
5046 static LRESULT CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5050 struct ImportWizData
*data
;
5056 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5058 data
= (struct ImportWizData
*)page
->lParam
;
5059 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5062 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5064 SendMessageW(fileNameEdit
, WM_SETTEXT
, 0, (LPARAM
)data
->fileName
);
5070 NMHDR
*hdr
= (NMHDR
*)lp
;
5075 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5076 PSWIZB_BACK
| PSWIZB_NEXT
);
5081 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5082 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
5084 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5087 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5088 IDS_IMPORT_EMPTY_FILE
);
5089 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5094 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
5095 (len
+ 1) * sizeof(WCHAR
));
5099 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
5101 if (!import_validate_filename(hwnd
, data
, fileName
))
5103 HeapFree(GetProcessHeap(), 0, fileName
);
5104 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5108 data
->fileName
= fileName
;
5119 case IDC_IMPORT_BROWSE_FILE
:
5122 WCHAR fileBuf
[MAX_PATH
];
5124 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5125 memset(&ofn
, 0, sizeof(ofn
));
5126 ofn
.lStructSize
= sizeof(ofn
);
5127 ofn
.hwndOwner
= hwnd
;
5128 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
5129 ofn
.lpstrFile
= fileBuf
;
5130 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
5132 if (GetOpenFileNameW(&ofn
))
5133 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
5134 0, (LPARAM
)ofn
.lpstrFile
);
5135 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
5144 static LRESULT CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5148 struct ImportWizData
*data
;
5154 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5156 data
= (struct ImportWizData
*)page
->lParam
;
5157 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5158 if (!data
->hDestCertStore
)
5160 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
,
5162 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5163 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5164 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
5168 WCHAR storeTitle
[MAX_STRING_LEN
];
5170 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), BM_CLICK
,
5172 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5173 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5174 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
),
5175 !(data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
));
5176 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5177 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5178 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5179 0, (LPARAM
)storeTitle
);
5185 NMHDR
*hdr
= (NMHDR
*)lp
;
5190 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5191 PSWIZB_BACK
| PSWIZB_NEXT
);
5196 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5197 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
5198 !data
->hDestCertStore
)
5200 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5201 IDS_IMPORT_SELECT_STORE
);
5202 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5213 case IDC_IMPORT_AUTO_STORE
:
5214 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5215 data
->autoDest
= TRUE
;
5216 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5217 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5219 case IDC_IMPORT_SPECIFY_STORE
:
5220 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5221 data
->autoDest
= FALSE
;
5222 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5223 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5225 case IDC_IMPORT_BROWSE_STORE
:
5227 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
5228 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
5229 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
5230 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
5233 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5234 selectInfo
.dwSize
= sizeof(selectInfo
);
5235 selectInfo
.parent
= hwnd
;
5236 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
5237 selectInfo
.pwszTitle
= NULL
;
5238 selectInfo
.pwszText
= NULL
;
5239 selectInfo
.pEnumData
= &enumData
;
5240 selectInfo
.pfnSelectedStoreCallback
= NULL
;
5241 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
5243 WCHAR storeTitle
[MAX_STRING_LEN
];
5245 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5246 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5247 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5248 0, (LPARAM
)storeTitle
);
5249 data
->hDestCertStore
= store
;
5250 data
->freeDest
= TRUE
;
5260 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
5262 WCHAR text
[MAX_STRING_LEN
];
5266 item
.mask
= LVIF_TEXT
;
5267 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5269 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
,
5270 sizeof(text
)/ sizeof(text
[0]));
5271 item
.pszText
= text
;
5272 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5275 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
,
5276 sizeof(text
)/ sizeof(text
[0]));
5278 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
,
5279 sizeof(text
)/ sizeof(text
[0]));
5280 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5281 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5283 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
,
5284 sizeof(text
)/ sizeof(text
[0]));
5285 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5286 switch (data
->contentType
)
5288 case CERT_QUERY_CONTENT_CERT
:
5289 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
5290 contentID
= IDS_IMPORT_CONTENT_CERT
;
5292 case CERT_QUERY_CONTENT_CRL
:
5293 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
5294 contentID
= IDS_IMPORT_CONTENT_CRL
;
5296 case CERT_QUERY_CONTENT_CTL
:
5297 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
5298 contentID
= IDS_IMPORT_CONTENT_CTL
;
5300 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
5301 contentID
= IDS_IMPORT_CONTENT_CMS
;
5303 case CERT_QUERY_CONTENT_FLAG_PFX
:
5304 contentID
= IDS_IMPORT_CONTENT_PFX
;
5307 contentID
= IDS_IMPORT_CONTENT_STORE
;
5310 LoadStringW(hInstance
, contentID
, text
, sizeof(text
)/ sizeof(text
[0]));
5312 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5315 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5317 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
5318 sizeof(text
)/ sizeof(text
[0]));
5319 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5321 item
.pszText
= data
->fileName
;
5322 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5326 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5327 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5331 switch (pImportSrc
->dwSubjectChoice
)
5333 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
5334 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
5335 pImportSrc
->u
.pwszFileName
, hDestCertStore
);
5337 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5338 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
5339 ret
= import_cert(pImportSrc
->u
.pCertContext
, hDestCertStore
);
5341 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5343 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5344 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
5345 ret
= import_crl(pImportSrc
->u
.pCRLContext
, hDestCertStore
);
5347 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5349 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5350 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
5351 ret
= import_ctl(pImportSrc
->u
.pCTLContext
, hDestCertStore
);
5353 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5355 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5356 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
5357 pImportSrc
->u
.hCertStore
, hDestCertStore
);
5360 WARN("unknown source type: %u\n", pImportSrc
->dwSubjectChoice
);
5361 SetLastError(E_INVALIDARG
);
5367 static LRESULT CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5371 struct ImportWizData
*data
;
5377 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5378 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5382 data
= (struct ImportWizData
*)page
->lParam
;
5383 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5384 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
5385 (WPARAM
)data
->titleFont
, TRUE
);
5386 GetWindowRect(lv
, &rc
);
5387 column
.mask
= LVCF_WIDTH
;
5388 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
5389 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
5390 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
5391 show_import_details(lv
, data
);
5396 NMHDR
*hdr
= (NMHDR
*)lp
;
5402 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5404 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5405 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
5406 show_import_details(lv
, data
);
5407 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5408 PSWIZB_BACK
| PSWIZB_FINISH
);
5414 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5415 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
5416 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
5418 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
5421 if (data
->pwszWizardTitle
)
5422 pTitle
= data
->pwszWizardTitle
;
5425 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
5426 sizeof(title
) / sizeof(title
[0]));
5429 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
,
5430 sizeof(message
) / sizeof(message
[0]));
5431 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
5434 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5445 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
5446 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
5447 HCERTSTORE hDestCertStore
)
5449 PROPSHEETHEADERW hdr
;
5450 PROPSHEETPAGEW pages
[4];
5451 struct ImportWizData data
;
5454 data
.dwFlags
= dwFlags
;
5455 data
.pwszWizardTitle
= pwszWizardTitle
;
5458 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
5459 data
.fileName
= (LPWSTR
)pImportSrc
->u
.pwszFileName
;
5463 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
5464 data
.fileName
= NULL
;
5466 data
.freeSource
= FALSE
;
5467 data
.hDestCertStore
= hDestCertStore
;
5468 data
.freeDest
= FALSE
;
5469 data
.autoDest
= TRUE
;
5470 data
.success
= TRUE
;
5472 memset(pages
, 0, sizeof(pages
));
5474 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5475 pages
[nPages
].hInstance
= hInstance
;
5476 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
5477 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
5478 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5479 pages
[nPages
].lParam
= (LPARAM
)&data
;
5483 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
5485 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5486 pages
[nPages
].hInstance
= hInstance
;
5487 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
5488 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
5489 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5490 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
5491 pages
[nPages
].pszHeaderSubTitle
=
5492 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
5493 pages
[nPages
].lParam
= (LPARAM
)&data
;
5498 switch (pImportSrc
->dwSubjectChoice
)
5500 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5501 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
5503 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5504 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
5506 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5507 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
5509 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5510 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
5515 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5516 pages
[nPages
].hInstance
= hInstance
;
5517 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
5518 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
5519 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5520 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
5521 pages
[nPages
].pszHeaderSubTitle
=
5522 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
5523 pages
[nPages
].lParam
= (LPARAM
)&data
;
5526 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5527 pages
[nPages
].hInstance
= hInstance
;
5528 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
5529 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
5530 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5531 pages
[nPages
].lParam
= (LPARAM
)&data
;
5534 memset(&hdr
, 0, sizeof(hdr
));
5535 hdr
.dwSize
= sizeof(hdr
);
5536 hdr
.hwndParent
= hwndParent
;
5537 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
5539 hdr
.hInstance
= hInstance
;
5540 if (pwszWizardTitle
)
5541 hdr
.pszCaption
= pwszWizardTitle
;
5543 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
5544 hdr
.u3
.ppsp
= pages
;
5545 hdr
.nPages
= nPages
;
5546 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
5547 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
5548 PropertySheetW(&hdr
);
5549 if (data
.fileName
!= data
.importSrc
.u
.pwszFileName
)
5550 HeapFree(GetProcessHeap(), 0, data
.fileName
);
5551 if (data
.freeSource
&&
5552 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
5553 CertCloseStore(data
.importSrc
.u
.hCertStore
, 0);
5554 DeleteObject(data
.titleFont
);
5555 return data
.success
;
5558 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5559 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5563 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
5564 pImportSrc
, hDestCertStore
);
5567 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
5569 SetLastError(E_INVALIDARG
);
5573 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
5574 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5576 else if (pImportSrc
)
5577 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5581 /* Can't have no UI without specifying source */
5582 SetLastError(E_INVALIDARG
);
5589 struct ExportWizData
5593 LPCWSTR pwszWizardTitle
;
5594 CRYPTUI_WIZ_EXPORT_INFO exportInfo
;
5595 CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo
;
5597 PCRYPT_KEY_PROV_INFO keyProvInfo
;
5604 static LRESULT CALLBACK
export_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5613 struct ExportWizData
*data
;
5614 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5615 WCHAR fontFace
[MAX_STRING_LEN
];
5616 HDC hDC
= GetDC(hwnd
);
5619 data
= (struct ExportWizData
*)page
->lParam
;
5620 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
5621 sizeof(fontFace
) / sizeof(fontFace
[0]));
5622 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
5623 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
5624 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
5625 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
5626 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
5627 (WPARAM
)data
->titleFont
, TRUE
);
5628 ReleaseDC(hwnd
, hDC
);
5633 NMHDR
*hdr
= (NMHDR
*)lp
;
5638 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
5648 static PCRYPT_KEY_PROV_INFO
export_get_private_key_info(PCCERT_CONTEXT cert
)
5650 PCRYPT_KEY_PROV_INFO info
= NULL
;
5653 if (CertGetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
,
5656 info
= HeapAlloc(GetProcessHeap(), 0, size
);
5659 if (!CertGetCertificateContextProperty(cert
,
5660 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
))
5662 HeapFree(GetProcessHeap(), 0, info
);
5670 static BOOL
export_acquire_private_key(const CRYPT_KEY_PROV_INFO
*info
,
5675 ret
= CryptAcquireContextW(phProv
, info
->pwszContainerName
,
5676 info
->pwszProvName
, info
->dwProvType
, 0);
5681 for (i
= 0; i
< info
->cProvParam
; i
++)
5682 CryptSetProvParam(*phProv
, info
->rgProvParam
[i
].dwParam
,
5683 info
->rgProvParam
[i
].pbData
, info
->rgProvParam
[i
].dwFlags
);
5688 static BOOL
export_is_key_exportable(HCRYPTPROV hProv
, DWORD keySpec
)
5693 if ((ret
= CryptGetUserKey(hProv
, keySpec
, &key
)))
5695 DWORD permissions
, size
= sizeof(permissions
);
5697 if ((ret
= CryptGetKeyParam(key
, KP_PERMISSIONS
, (BYTE
*)&permissions
,
5698 &size
, 0)) && !(permissions
& CRYPT_EXPORT
))
5700 CryptDestroyKey(key
);
5705 static LRESULT CALLBACK
export_private_key_dlg_proc(HWND hwnd
, UINT msg
,
5706 WPARAM wp
, LPARAM lp
)
5709 struct ExportWizData
*data
;
5715 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5716 PCRYPT_KEY_PROV_INFO info
;
5717 HCRYPTPROV hProv
= 0;
5720 data
= (struct ExportWizData
*)page
->lParam
;
5721 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5722 /* Get enough information about a key to see whether it's exportable.
5724 if (!(info
= export_get_private_key_info(
5725 data
->exportInfo
.u
.pCertContext
)))
5726 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5727 else if (!export_acquire_private_key(info
, &hProv
))
5728 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5729 else if (!export_is_key_exportable(hProv
, info
->dwKeySpec
))
5730 errorID
= IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE
;
5734 WCHAR error
[MAX_STRING_LEN
];
5736 LoadStringW(hInstance
, errorID
, error
,
5737 sizeof(error
) / sizeof(error
[0]));
5738 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE
),
5739 WM_SETTEXT
, 0, (LPARAM
)error
);
5740 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_YES
), FALSE
);
5743 data
->keyProvInfo
= info
;
5745 CryptReleaseContext(hProv
, 0);
5746 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
), BM_CLICK
,
5752 NMHDR
*hdr
= (NMHDR
*)lp
;
5757 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5758 PSWIZB_BACK
| PSWIZB_NEXT
);
5762 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5763 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
))
5765 data
->contextInfo
.dwExportFormat
=
5766 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5767 data
->contextInfo
.fExportPrivateKeys
= FALSE
;
5771 data
->contextInfo
.dwExportFormat
=
5772 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5773 data
->contextInfo
.fExportPrivateKeys
= TRUE
;
5783 static BOOL
export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
)
5787 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
)
5791 /* If there's a CRYPT_KEY_PROV_INFO set for this cert, assume the
5792 * cert has a private key.
5794 if (CertGetCertificateContextProperty(pExportInfo
->u
.pCertContext
,
5795 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
))
5801 static void export_format_enable_controls(HWND hwnd
, const struct ExportWizData
*data
)
5803 int defaultFormatID
;
5805 switch (data
->contextInfo
.dwExportFormat
)
5807 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
5808 defaultFormatID
= IDC_EXPORT_FORMAT_BASE64
;
5810 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
5811 defaultFormatID
= IDC_EXPORT_FORMAT_CMS
;
5813 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
5814 defaultFormatID
= IDC_EXPORT_FORMAT_PFX
;
5817 defaultFormatID
= IDC_EXPORT_FORMAT_DER
;
5819 SendMessageW(GetDlgItem(hwnd
, defaultFormatID
), BM_CLICK
, 0, 0);
5820 if (defaultFormatID
== IDC_EXPORT_FORMAT_PFX
)
5822 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), FALSE
);
5823 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), FALSE
);
5824 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), FALSE
);
5825 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), TRUE
);
5829 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), TRUE
);
5830 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), TRUE
);
5831 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), TRUE
);
5832 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), FALSE
);
5836 static LRESULT CALLBACK
export_format_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5840 struct ExportWizData
*data
;
5846 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5848 data
= (struct ExportWizData
*)page
->lParam
;
5849 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5850 export_format_enable_controls(hwnd
, data
);
5855 NMHDR
*hdr
= (NMHDR
*)lp
;
5860 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5861 PSWIZB_BACK
| PSWIZB_NEXT
);
5862 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5863 export_format_enable_controls(hwnd
, data
);
5868 BOOL skipPasswordPage
= TRUE
;
5870 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5871 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_DER
))
5872 data
->contextInfo
.dwExportFormat
=
5873 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5874 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_BASE64
))
5875 data
->contextInfo
.dwExportFormat
=
5876 CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
;
5877 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_CMS
))
5879 data
->contextInfo
.dwExportFormat
=
5880 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5881 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
))
5882 data
->contextInfo
.fExportChain
=
5883 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5887 data
->contextInfo
.dwExportFormat
=
5888 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5889 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
))
5890 data
->contextInfo
.fExportChain
= TRUE
;
5891 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
))
5892 data
->contextInfo
.fStrongEncryption
= TRUE
;
5893 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
))
5894 data
->deleteKeys
= TRUE
;
5895 skipPasswordPage
= FALSE
;
5897 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
,
5898 skipPasswordPage
? IDD_EXPORT_FILE
: 0);
5911 case IDC_EXPORT_FORMAT_DER
:
5912 case IDC_EXPORT_FORMAT_BASE64
:
5913 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5915 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5917 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5919 EnableWindow(GetDlgItem(hwnd
,
5920 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), FALSE
);
5922 case IDC_EXPORT_FORMAT_CMS
:
5923 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5926 case IDC_EXPORT_FORMAT_PFX
:
5927 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5929 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5931 EnableWindow(GetDlgItem(hwnd
,
5932 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), TRUE
);
5942 static void export_password_mismatch(HWND hwnd
, const struct ExportWizData
*data
)
5944 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5947 if (data
->pwszWizardTitle
)
5948 pTitle
= data
->pwszWizardTitle
;
5951 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
5952 sizeof(title
) / sizeof(title
[0]));
5955 LoadStringW(hInstance
, IDS_EXPORT_PASSWORD_MISMATCH
, error
,
5956 sizeof(error
) / sizeof(error
[0]));
5957 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
5958 SetFocus(GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
));
5961 static LRESULT CALLBACK
export_password_dlg_proc(HWND hwnd
, UINT msg
,
5962 WPARAM wp
, LPARAM lp
)
5965 struct ExportWizData
*data
;
5971 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5973 data
= (struct ExportWizData
*)page
->lParam
;
5974 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5979 NMHDR
*hdr
= (NMHDR
*)lp
;
5984 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5985 PSWIZB_BACK
| PSWIZB_NEXT
);
5990 HWND passwordEdit
= GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
);
5991 HWND passwordConfirmEdit
= GetDlgItem(hwnd
,
5992 IDC_EXPORT_PASSWORD_CONFIRM
);
5993 DWORD passwordLen
= SendMessageW(passwordEdit
, WM_GETTEXTLENGTH
,
5995 DWORD passwordConfirmLen
= SendMessageW(passwordConfirmEdit
,
5996 WM_GETTEXTLENGTH
, 0, 0);
5998 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5999 if (!passwordLen
&& !passwordConfirmLen
)
6000 data
->contextInfo
.pwszPassword
= NULL
;
6001 else if (passwordLen
!= passwordConfirmLen
)
6003 export_password_mismatch(hwnd
, data
);
6004 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6009 LPWSTR password
= HeapAlloc(GetProcessHeap(), 0,
6010 (passwordLen
+ 1) * sizeof(WCHAR
));
6011 LPWSTR passwordConfirm
= HeapAlloc(GetProcessHeap(), 0,
6012 (passwordConfirmLen
+ 1) * sizeof(WCHAR
));
6013 BOOL freePassword
= TRUE
;
6015 if (password
&& passwordConfirm
)
6017 SendMessageW(passwordEdit
, WM_GETTEXT
, passwordLen
+ 1,
6019 SendMessageW(passwordConfirmEdit
, WM_GETTEXT
,
6020 passwordConfirmLen
+ 1, (LPARAM
)passwordConfirm
);
6021 if (strcmpW(password
, passwordConfirm
))
6023 export_password_mismatch(hwnd
, data
);
6024 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6029 data
->contextInfo
.pwszPassword
= password
;
6030 freePassword
= FALSE
;
6031 data
->freePassword
= TRUE
;
6035 HeapFree(GetProcessHeap(), 0, password
);
6036 HeapFree(GetProcessHeap(), 0, passwordConfirm
);
6047 static LPWSTR
export_append_extension(const struct ExportWizData
*data
,
6050 static const WCHAR cer
[] = { '.','c','e','r',0 };
6051 static const WCHAR crl
[] = { '.','c','r','l',0 };
6052 static const WCHAR ctl
[] = { '.','c','t','l',0 };
6053 static const WCHAR p7b
[] = { '.','p','7','b',0 };
6054 static const WCHAR pfx
[] = { '.','p','f','x',0 };
6055 static const WCHAR sst
[] = { '.','s','s','t',0 };
6058 BOOL appendExtension
;
6060 switch (data
->contextInfo
.dwExportFormat
)
6062 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6065 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6069 switch (data
->exportInfo
.dwSubjectChoice
)
6071 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6074 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6077 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6084 dot
= strrchrW(fileName
, '.');
6086 appendExtension
= strcmpiW(dot
, extension
) != 0;
6088 appendExtension
= TRUE
;
6089 if (appendExtension
)
6091 fileName
= HeapReAlloc(GetProcessHeap(), 0, fileName
,
6092 (strlenW(fileName
) + strlenW(extension
) + 1) * sizeof(WCHAR
));
6094 strcatW(fileName
, extension
);
6099 static BOOL
export_validate_filename(HWND hwnd
, struct ExportWizData
*data
,
6103 BOOL tryCreate
= TRUE
, forceCreate
= FALSE
, ret
= FALSE
;
6105 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6106 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, NULL
);
6107 if (file
!= INVALID_HANDLE_VALUE
)
6109 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
6112 if (data
->pwszWizardTitle
)
6113 pTitle
= data
->pwszWizardTitle
;
6116 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6117 sizeof(title
) / sizeof(title
[0]));
6120 LoadStringW(hInstance
, IDS_EXPORT_FILE_EXISTS
, warning
,
6121 sizeof(warning
) / sizeof(warning
[0]));
6122 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
6130 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6131 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6132 forceCreate
? CREATE_ALWAYS
: CREATE_NEW
,
6134 if (file
!= INVALID_HANDLE_VALUE
)
6141 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6143 LPWSTR msgBuf
, fullError
;
6145 if (data
->pwszWizardTitle
)
6146 pTitle
= data
->pwszWizardTitle
;
6149 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6150 sizeof(title
) / sizeof(title
[0]));
6153 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
6154 sizeof(error
) / sizeof(error
[0]));
6156 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
6157 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
6158 fullError
= HeapAlloc(GetProcessHeap(), 0,
6159 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
6163 LPWSTR ptr
= fullError
;
6165 strcpyW(ptr
, error
);
6166 ptr
+= strlenW(error
);
6167 strcpyW(ptr
, fileName
);
6168 ptr
+= strlenW(fileName
);
6171 strcpyW(ptr
, msgBuf
);
6172 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
6173 HeapFree(GetProcessHeap(), 0, fullError
);
6181 static const WCHAR export_filter_cert
[] = { '*','.','c','e','r',0 };
6182 static const WCHAR export_filter_crl
[] = { '*','.','c','r','l',0 };
6183 static const WCHAR export_filter_ctl
[] = { '*','.','s','t','l',0 };
6184 static const WCHAR export_filter_cms
[] = { '*','.','p','7','b',0 };
6185 static const WCHAR export_filter_pfx
[] = { '*','.','p','f','x',0 };
6186 static const WCHAR export_filter_sst
[] = { '*','.','s','s','t',0 };
6188 static WCHAR
*make_export_file_filter(DWORD exportFormat
, DWORD subjectChoice
)
6190 int baseLen
, allLen
, totalLen
= 2, baseID
;
6191 LPWSTR filter
= NULL
, baseFilter
, all
;
6194 switch (exportFormat
)
6196 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6197 baseID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6198 filterStr
= export_filter_cert
;
6200 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6201 baseID
= IDS_EXPORT_FILTER_PFX
;
6202 filterStr
= export_filter_pfx
;
6204 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6205 baseID
= IDS_EXPORT_FILTER_CMS
;
6206 filterStr
= export_filter_cms
;
6209 switch (subjectChoice
)
6211 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6212 baseID
= IDS_EXPORT_FILTER_CRL
;
6213 filterStr
= export_filter_crl
;
6215 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6216 baseID
= IDS_EXPORT_FILTER_CTL
;
6217 filterStr
= export_filter_ctl
;
6219 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6220 baseID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6221 filterStr
= export_filter_sst
;
6224 baseID
= IDS_EXPORT_FILTER_CERT
;
6225 filterStr
= export_filter_cert
;
6229 baseLen
= LoadStringW(hInstance
, baseID
, (LPWSTR
)&baseFilter
, 0);
6230 totalLen
+= baseLen
+ strlenW(filterStr
) + 2;
6231 allLen
= LoadStringW(hInstance
, IDS_IMPORT_FILTER_ALL
, (LPWSTR
)&all
, 0);
6232 totalLen
+= allLen
+ strlenW(filter_all
) + 2;
6233 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
6239 memcpy(ptr
, baseFilter
, baseLen
* sizeof(WCHAR
));
6242 strcpyW(ptr
, filterStr
);
6243 ptr
+= strlenW(filterStr
) + 1;
6244 memcpy(ptr
, all
, allLen
* sizeof(WCHAR
));
6247 strcpyW(ptr
, filter_all
);
6248 ptr
+= strlenW(filter_all
) + 1;
6254 static LRESULT CALLBACK
export_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6258 struct ExportWizData
*data
;
6264 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6266 data
= (struct ExportWizData
*)page
->lParam
;
6267 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6268 if (data
->exportInfo
.pwszExportFileName
)
6269 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
, 0,
6270 (LPARAM
)data
->exportInfo
.pwszExportFileName
);
6275 NMHDR
*hdr
= (NMHDR
*)lp
;
6280 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6281 if (data
->contextInfo
.dwExportFormat
!=
6282 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
)
6284 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, IDD_EXPORT_FORMAT
);
6290 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
);
6291 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
6293 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6296 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6299 if (data
->pwszWizardTitle
)
6300 pTitle
= data
->pwszWizardTitle
;
6303 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6304 sizeof(title
) / sizeof(title
[0]));
6307 LoadStringW(hInstance
, IDS_IMPORT_EMPTY_FILE
, error
,
6308 sizeof(error
) / sizeof(error
[0]));
6309 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
6310 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6315 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
6316 (len
+ 1) * sizeof(WCHAR
));
6320 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
6322 fileName
= export_append_extension(data
, fileName
);
6323 if (!export_validate_filename(hwnd
, data
, fileName
))
6325 HeapFree(GetProcessHeap(), 0, fileName
);
6326 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6330 data
->fileName
= fileName
;
6336 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6337 PSWIZB_BACK
| PSWIZB_NEXT
);
6346 case IDC_EXPORT_BROWSE_FILE
:
6349 WCHAR fileBuf
[MAX_PATH
];
6351 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6352 memset(&ofn
, 0, sizeof(ofn
));
6353 ofn
.lStructSize
= sizeof(ofn
);
6354 ofn
.hwndOwner
= hwnd
;
6355 ofn
.lpstrFilter
= make_export_file_filter(
6356 data
->contextInfo
.dwExportFormat
,
6357 data
->exportInfo
.dwSubjectChoice
);
6358 ofn
.lpstrFile
= fileBuf
;
6359 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
6361 if (GetSaveFileNameW(&ofn
))
6362 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
,
6363 0, (LPARAM
)ofn
.lpstrFile
);
6364 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
6373 static void show_export_details(HWND lv
, const struct ExportWizData
*data
)
6375 WCHAR text
[MAX_STRING_LEN
];
6379 item
.mask
= LVIF_TEXT
;
6382 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6384 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
6385 sizeof(text
)/ sizeof(text
[0]));
6386 item
.pszText
= text
;
6387 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6389 item
.pszText
= data
->fileName
;
6390 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6393 item
.pszText
= text
;
6394 switch (data
->exportInfo
.dwSubjectChoice
)
6396 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6397 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6398 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6399 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6404 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6406 LoadStringW(hInstance
, IDS_EXPORT_INCLUDE_CHAIN
, text
,
6407 sizeof(text
) / sizeof(text
[0]));
6408 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6410 LoadStringW(hInstance
,
6411 data
->contextInfo
.fExportChain
? IDS_YES
: IDS_NO
, text
,
6412 sizeof(text
) / sizeof(text
[0]));
6413 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6415 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6417 LoadStringW(hInstance
, IDS_EXPORT_KEYS
, text
,
6418 sizeof(text
) / sizeof(text
[0]));
6419 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6421 LoadStringW(hInstance
,
6422 data
->contextInfo
.fExportPrivateKeys
? IDS_YES
: IDS_NO
, text
,
6423 sizeof(text
) / sizeof(text
[0]));
6424 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6428 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6430 LoadStringW(hInstance
, IDS_EXPORT_FORMAT
, text
,
6431 sizeof(text
)/ sizeof(text
[0]));
6432 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6435 switch (data
->exportInfo
.dwSubjectChoice
)
6437 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6438 contentID
= IDS_EXPORT_FILTER_CRL
;
6440 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6441 contentID
= IDS_EXPORT_FILTER_CTL
;
6443 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6444 contentID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6447 switch (data
->contextInfo
.dwExportFormat
)
6449 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6450 contentID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6452 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6453 contentID
= IDS_EXPORT_FILTER_CMS
;
6455 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6456 contentID
= IDS_EXPORT_FILTER_PFX
;
6459 contentID
= IDS_EXPORT_FILTER_CERT
;
6462 LoadStringW(hInstance
, contentID
, text
, sizeof(text
) / sizeof(text
[0]));
6463 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6466 static inline BOOL
save_der(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6470 return WriteFile(file
, pb
, cb
, &bytesWritten
, NULL
);
6473 static BOOL
save_base64(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6478 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, NULL
, &size
)))
6480 LPSTR buf
= HeapAlloc(GetProcessHeap(), 0, size
);
6484 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, buf
,
6486 ret
= WriteFile(file
, buf
, size
, &size
, NULL
);
6487 HeapFree(GetProcessHeap(), 0, buf
);
6491 SetLastError(ERROR_OUTOFMEMORY
);
6498 static inline BOOL
save_store_as_cms(HANDLE file
, HCERTSTORE store
)
6500 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6501 CERT_STORE_SAVE_AS_PKCS7
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6504 static BOOL
save_cert_as_cms(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6508 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
6509 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6515 HCERTSTORE addlStore
= CertOpenStore(CERT_STORE_PROV_COLLECTION
,
6516 0, 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6523 for (i
= 0; ret
&& i
< pExportInfo
->cStores
; i
++)
6524 ret
= CertAddStoreToCollection(addlStore
,
6525 pExportInfo
->rghStores
, 0, 0);
6528 PCCERT_CHAIN_CONTEXT chain
;
6530 ret
= CertGetCertificateChain(NULL
,
6531 pExportInfo
->u
.pCertContext
, NULL
, addlStore
, NULL
, 0,
6537 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6538 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6540 ret
= CertAddCertificateContextToStore(store
,
6541 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6542 CERT_STORE_ADD_ALWAYS
, NULL
);
6543 CertFreeCertificateChain(chain
);
6547 /* No chain could be created, just add the individual
6548 * cert to the message.
6550 ret
= CertAddCertificateContextToStore(store
,
6551 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
,
6555 CertCloseStore(addlStore
, 0);
6561 ret
= CertAddCertificateContextToStore(store
,
6562 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, NULL
);
6564 ret
= save_store_as_cms(file
, store
);
6565 CertCloseStore(store
, 0);
6572 static BOOL
save_serialized_store(HANDLE file
, HCERTSTORE store
)
6574 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6575 CERT_STORE_SAVE_AS_STORE
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6578 static BOOL
save_pfx(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6579 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6580 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6582 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, X509_ASN_ENCODING
,
6583 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6588 CRYPT_DATA_BLOB pfxBlob
= { 0, NULL
};
6589 PCCERT_CONTEXT cert
= NULL
;
6590 BOOL freeKeyProvInfo
= FALSE
;
6592 if (pContextInfo
->fExportChain
)
6594 HCERTCHAINENGINE engine
= NULL
;
6596 if (pExportInfo
->cStores
)
6598 CERT_CHAIN_ENGINE_CONFIG config
;
6600 memset(&config
, 0, sizeof(config
));
6601 config
.cbSize
= sizeof(config
);
6602 config
.cAdditionalStore
= pExportInfo
->cStores
;
6603 config
.rghAdditionalStore
= pExportInfo
->rghStores
;
6604 ret
= CertCreateCertificateChainEngine(&config
, &engine
);
6610 CERT_CHAIN_PARA chainPara
;
6611 PCCERT_CHAIN_CONTEXT chain
;
6613 memset(&chainPara
, 0, sizeof(chainPara
));
6614 chainPara
.cbSize
= sizeof(chainPara
);
6615 ret
= CertGetCertificateChain(engine
,
6616 pExportInfo
->u
.pCertContext
, NULL
, NULL
, &chainPara
, 0, NULL
,
6622 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6623 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6626 if (i
== 0 && j
== 0)
6627 ret
= CertAddCertificateContextToStore(store
,
6628 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6629 CERT_STORE_ADD_ALWAYS
, &cert
);
6631 ret
= CertAddCertificateContextToStore(store
,
6632 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6633 CERT_STORE_ADD_ALWAYS
, NULL
);
6635 CertFreeCertificateChain(chain
);
6639 CertFreeCertificateChainEngine(engine
);
6642 ret
= CertAddCertificateContextToStore(store
,
6643 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, &cert
);
6644 /* Copy private key info to newly created cert, so it'll get exported
6645 * along with the cert.
6647 if (ret
&& pContextInfo
->fExportPrivateKeys
)
6650 ret
= CertSetCertificateContextProperty(cert
,
6651 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6654 if (!(keyProvInfo
= export_get_private_key_info(cert
)))
6658 ret
= CertSetCertificateContextProperty(cert
,
6659 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6660 freeKeyProvInfo
= TRUE
;
6667 REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
| EXPORT_PRIVATE_KEYS
;
6669 ret
= PFXExportCertStore(store
, &pfxBlob
,
6670 pContextInfo
->pwszPassword
, exportFlags
);
6673 pfxBlob
.pbData
= HeapAlloc(GetProcessHeap(), 0, pfxBlob
.cbData
);
6676 ret
= PFXExportCertStore(store
, &pfxBlob
,
6677 pContextInfo
->pwszPassword
, exportFlags
);
6682 ret
= WriteFile(file
, pfxBlob
.pbData
, pfxBlob
.cbData
,
6683 &bytesWritten
, NULL
);
6688 SetLastError(ERROR_OUTOFMEMORY
);
6693 if (ret
&& deleteKeys
)
6697 CryptAcquireContextW(&prov
, keyProvInfo
->pwszContainerName
,
6698 keyProvInfo
->pwszProvName
, keyProvInfo
->dwProvType
,
6699 CRYPT_DELETEKEYSET
);
6701 if (freeKeyProvInfo
)
6702 HeapFree(GetProcessHeap(), 0, keyProvInfo
);
6703 CertFreeCertificateContext(cert
);
6704 CertCloseStore(store
, 0);
6709 static BOOL
do_export(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6710 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6711 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6715 if (pContextInfo
->dwSize
!= sizeof(CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
))
6717 SetLastError(E_INVALIDARG
);
6720 switch (pExportInfo
->dwSubjectChoice
)
6722 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6723 ret
= save_der(file
,
6724 pExportInfo
->u
.pCRLContext
->pbCrlEncoded
,
6725 pExportInfo
->u
.pCRLContext
->cbCrlEncoded
);
6727 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6728 ret
= save_der(file
,
6729 pExportInfo
->u
.pCTLContext
->pbCtlEncoded
,
6730 pExportInfo
->u
.pCTLContext
->cbCtlEncoded
);
6732 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6733 ret
= save_serialized_store(file
, pExportInfo
->u
.hCertStore
);
6735 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6736 ret
= save_store_as_cms(file
, pExportInfo
->u
.hCertStore
);
6739 switch (pContextInfo
->dwExportFormat
)
6741 case CRYPTUI_WIZ_EXPORT_FORMAT_DER
:
6742 ret
= save_der(file
, pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6743 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6745 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6746 ret
= save_base64(file
,
6747 pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6748 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6750 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6751 ret
= save_cert_as_cms(file
, pExportInfo
,
6752 pContextInfo
->fExportChain
);
6754 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6755 ret
= save_pfx(file
, pExportInfo
, pContextInfo
, keyProvInfo
,
6759 SetLastError(E_FAIL
);
6766 static LRESULT CALLBACK
export_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6770 struct ExportWizData
*data
;
6776 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6777 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6781 data
= (struct ExportWizData
*)page
->lParam
;
6782 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6783 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
6784 (WPARAM
)data
->titleFont
, TRUE
);
6785 GetWindowRect(lv
, &rc
);
6786 column
.mask
= LVCF_WIDTH
;
6787 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
6788 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
6789 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
6790 show_export_details(lv
, data
);
6795 NMHDR
*hdr
= (NMHDR
*)lp
;
6801 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6803 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6804 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
6805 show_export_details(lv
, data
);
6806 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6807 PSWIZB_BACK
| PSWIZB_FINISH
);
6814 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
6818 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6819 if ((data
->success
= do_export(data
->file
, &data
->exportInfo
,
6820 &data
->contextInfo
, data
->keyProvInfo
, data
->deleteKeys
)))
6822 messageID
= IDS_EXPORT_SUCCEEDED
;
6827 messageID
= IDS_EXPORT_FAILED
;
6828 mbFlags
= MB_OK
| MB_ICONERROR
;
6830 if (data
->pwszWizardTitle
)
6831 pTitle
= data
->pwszWizardTitle
;
6834 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6835 sizeof(title
) / sizeof(title
[0]));
6838 LoadStringW(hInstance
, messageID
, message
,
6839 sizeof(message
) / sizeof(message
[0]));
6840 MessageBoxW(hwnd
, message
, pTitle
, mbFlags
);
6850 static BOOL
show_export_ui(DWORD dwFlags
, HWND hwndParent
,
6851 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, const void *pvoid
)
6853 PROPSHEETHEADERW hdr
;
6854 PROPSHEETPAGEW pages
[6];
6855 struct ExportWizData data
;
6857 BOOL hasPrivateKey
, showFormatPage
= TRUE
;
6860 data
.dwFlags
= dwFlags
;
6861 data
.pwszWizardTitle
= pwszWizardTitle
;
6862 memset(&data
.exportInfo
, 0, sizeof(data
.exportInfo
));
6863 memcpy(&data
.exportInfo
, pExportInfo
,
6864 min(sizeof(data
.exportInfo
), pExportInfo
->dwSize
));
6865 if (pExportInfo
->dwSize
> sizeof(data
.exportInfo
))
6866 data
.exportInfo
.dwSize
= sizeof(data
.exportInfo
);
6867 data
.contextInfo
.dwSize
= sizeof(data
.contextInfo
);
6868 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6869 data
.contextInfo
.fExportChain
= FALSE
;
6870 data
.contextInfo
.fStrongEncryption
= FALSE
;
6871 data
.contextInfo
.fExportPrivateKeys
= FALSE
;
6872 data
.contextInfo
.pwszPassword
= NULL
;
6873 data
.freePassword
= FALSE
;
6874 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
&&
6876 memcpy(&data
.contextInfo
, pvoid
,
6877 min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
)pvoid
)->dwSize
,
6878 sizeof(data
.contextInfo
)));
6879 data
.keyProvInfo
= NULL
;
6880 data
.deleteKeys
= FALSE
;
6881 data
.fileName
= NULL
;
6882 data
.file
= INVALID_HANDLE_VALUE
;
6883 data
.success
= FALSE
;
6885 memset(pages
, 0, sizeof(pages
));
6887 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6888 pages
[nPages
].hInstance
= hInstance
;
6889 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_WELCOME
);
6890 pages
[nPages
].pfnDlgProc
= export_welcome_dlg_proc
;
6891 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6892 pages
[nPages
].lParam
= (LPARAM
)&data
;
6895 hasPrivateKey
= export_info_has_private_key(pExportInfo
);
6896 switch (pExportInfo
->dwSubjectChoice
)
6898 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6899 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6900 showFormatPage
= FALSE
;
6901 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6903 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6904 showFormatPage
= FALSE
;
6905 data
.contextInfo
.dwExportFormat
=
6906 CRYPTUI_WIZ_EXPORT_FORMAT_SERIALIZED_CERT_STORE
;
6908 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6909 showFormatPage
= FALSE
;
6910 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
6914 if (hasPrivateKey
&& showFormatPage
)
6916 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6917 pages
[nPages
].hInstance
= hInstance
;
6918 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY
);
6919 pages
[nPages
].pfnDlgProc
= export_private_key_dlg_proc
;
6920 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6921 pages
[nPages
].pszHeaderTitle
=
6922 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE
);
6923 pages
[nPages
].pszHeaderSubTitle
=
6924 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE
);
6925 pages
[nPages
].lParam
= (LPARAM
)&data
;
6930 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6931 pages
[nPages
].hInstance
= hInstance
;
6932 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FORMAT
);
6933 pages
[nPages
].pfnDlgProc
= export_format_dlg_proc
;
6934 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6935 pages
[nPages
].pszHeaderTitle
=
6936 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_TITLE
);
6937 pages
[nPages
].pszHeaderSubTitle
=
6938 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_SUBTITLE
);
6939 pages
[nPages
].lParam
= (LPARAM
)&data
;
6942 if (hasPrivateKey
&& showFormatPage
)
6944 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6945 pages
[nPages
].hInstance
= hInstance
;
6946 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD
);
6947 pages
[nPages
].pfnDlgProc
= export_password_dlg_proc
;
6948 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6949 pages
[nPages
].pszHeaderTitle
=
6950 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE
);
6951 pages
[nPages
].pszHeaderSubTitle
=
6952 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE
);
6953 pages
[nPages
].lParam
= (LPARAM
)&data
;
6957 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6958 pages
[nPages
].hInstance
= hInstance
;
6959 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FILE
);
6960 pages
[nPages
].pfnDlgProc
= export_file_dlg_proc
;
6961 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6962 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_EXPORT_FILE_TITLE
);
6963 pages
[nPages
].pszHeaderSubTitle
=
6964 MAKEINTRESOURCEW(IDS_EXPORT_FILE_SUBTITLE
);
6965 pages
[nPages
].lParam
= (LPARAM
)&data
;
6968 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6969 pages
[nPages
].hInstance
= hInstance
;
6970 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FINISH
);
6971 pages
[nPages
].pfnDlgProc
= export_finish_dlg_proc
;
6972 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6973 pages
[nPages
].lParam
= (LPARAM
)&data
;
6976 memset(&hdr
, 0, sizeof(hdr
));
6977 hdr
.dwSize
= sizeof(hdr
);
6978 hdr
.hwndParent
= hwndParent
;
6979 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
6981 hdr
.hInstance
= hInstance
;
6982 if (pwszWizardTitle
)
6983 hdr
.pszCaption
= pwszWizardTitle
;
6985 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_EXPORT_WIZARD
);
6986 hdr
.u3
.ppsp
= pages
;
6987 hdr
.nPages
= nPages
;
6988 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
6989 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
6990 l
= PropertySheetW(&hdr
);
6991 DeleteObject(data
.titleFont
);
6992 if (data
.freePassword
)
6993 HeapFree(GetProcessHeap(), 0,
6994 (LPWSTR
)data
.contextInfo
.pwszPassword
);
6995 HeapFree(GetProcessHeap(), 0, data
.keyProvInfo
);
6996 CloseHandle(data
.file
);
6997 HeapFree(GetProcessHeap(), 0, data
.fileName
);
7000 SetLastError(ERROR_CANCELLED
);
7004 return data
.success
;
7007 BOOL WINAPI
CryptUIWizExport(DWORD dwFlags
, HWND hwndParent
,
7008 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, void *pvoid
)
7012 TRACE("(%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
,
7013 debugstr_w(pwszWizardTitle
), pExportInfo
, pvoid
);
7015 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
7016 ret
= show_export_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pExportInfo
,
7020 HANDLE file
= CreateFileW(pExportInfo
->pwszExportFileName
,
7021 GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
7022 CREATE_ALWAYS
, 0, NULL
);
7024 if (file
!= INVALID_HANDLE_VALUE
)
7026 ret
= do_export(file
, pExportInfo
, pvoid
, NULL
, FALSE
);
7035 BOOL WINAPI
CryptUIDlgViewSignerInfoA(CRYPTUI_VIEWSIGNERINFO_STRUCTA
*pcvsi
)
7037 FIXME("%p: stub\n", pcvsi
);
7041 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateW(PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
)
7043 FIXME("%p: stub\n", pcsc
);
7047 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateA(PCCRYPTUI_SELECTCERTIFICATE_STRUCTA pcsc
)
7049 FIXME("%p: stub\n", pcsc
);