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
19 #define WIN32_NO_STATUS
21 #define COM_NO_WINDOWS_H
28 #define NONAMELESSUNION
41 #include <cryptuiapi.h>
42 #include "cryptuires.h"
46 #include <wine/debug.h>
47 #include <wine/unicode.h>
49 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
51 static HINSTANCE hInstance
;
53 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
55 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
59 case DLL_WINE_PREATTACH
:
60 return FALSE
; /* prefer native version */
61 case DLL_PROCESS_ATTACH
:
63 DisableThreadLibraryCalls(hinstDLL
);
65 case DLL_PROCESS_DETACH
:
73 #define MAX_STRING_LEN 512
75 static void add_cert_columns(HWND hwnd
)
77 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
79 WCHAR buf
[MAX_STRING_LEN
];
82 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
83 GetWindowRect(lv
, &rc
);
84 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
,
85 sizeof(buf
) / sizeof(buf
[0]));
86 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
87 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
89 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
90 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
,
91 sizeof(buf
) / sizeof(buf
[0]));
92 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
93 column
.cx
= (rc
.right
- rc
.left
) * 16 / 100 - 2;
94 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
,
95 sizeof(buf
) / sizeof(buf
[0]));
96 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
97 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
98 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
,
99 sizeof(buf
) / sizeof(buf
[0]));
100 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 3, (LPARAM
)&column
);
103 static void add_cert_to_view(HWND lv
, PCCERT_CONTEXT cert
, DWORD
*allocatedLen
,
108 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
113 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
114 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
117 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
118 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
120 if (len
> *allocatedLen
)
122 HeapFree(GetProcessHeap(), 0, *str
);
123 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
129 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
132 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
135 item
.mask
= LVIF_TEXT
;
136 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
137 CERT_NAME_ISSUER_FLAG
, NULL
, NULL
, 0);
138 if (len
> *allocatedLen
)
140 HeapFree(GetProcessHeap(), 0, *str
);
141 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
147 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
148 CERT_NAME_ISSUER_FLAG
, NULL
, *str
, len
);
151 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
154 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
155 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
156 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
157 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
158 sizeof(date
) / sizeof(date
[0]));
161 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
163 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
165 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
166 if (len
> *allocatedLen
)
168 HeapFree(GetProcessHeap(), 0, *str
);
169 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
175 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
181 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
185 static LPSTR
get_cert_mgr_usages(void)
187 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
188 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
189 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
190 'r','p','o','s','e',0 };
194 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
200 rc
= RegQueryValueExA(key
, "Purpose", NULL
, &type
, NULL
, &size
);
201 if ((!rc
|| rc
== ERROR_MORE_DATA
) && type
== REG_SZ
)
203 str
= HeapAlloc(GetProcessHeap(), 0, size
);
206 rc
= RegQueryValueExA(key
, "Purpose", NULL
, NULL
, (LPBYTE
)str
,
210 HeapFree(GetProcessHeap(), 0, str
);
221 PurposeFilterShowAll
= 0,
222 PurposeFilterShowAdvanced
= 1,
223 PurposeFilterShowOID
= 2
226 static void initialize_purpose_selection(HWND hwnd
)
228 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
229 WCHAR buf
[MAX_STRING_LEN
];
233 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
,
234 sizeof(buf
) / sizeof(buf
[0]));
235 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
236 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAll
);
237 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
,
238 sizeof(buf
) / sizeof(buf
[0]));
239 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
240 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAdvanced
);
241 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
242 if ((usages
= get_cert_mgr_usages()))
246 for (ptr
= usages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
247 ptr
= comma
? comma
+ 1 : NULL
,
248 comma
= ptr
? strchr(ptr
, ',') : NULL
)
250 PCCRYPT_OID_INFO info
;
254 if ((info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, ptr
, 0)))
256 index
= SendMessageW(cb
, CB_INSERTSTRING
, 0,
257 (LPARAM
)info
->pwszName
);
258 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)info
);
261 HeapFree(GetProcessHeap(), 0, usages
);
265 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
266 PCCRYPT_OID_INFO
**usages
);
268 static CERT_ENHKEY_USAGE
*add_oid_to_usage(CERT_ENHKEY_USAGE
*usage
, LPSTR oid
)
270 if (!usage
->cUsageIdentifier
)
271 usage
->rgpszUsageIdentifier
= HeapAlloc(GetProcessHeap(), 0,
274 usage
->rgpszUsageIdentifier
= HeapReAlloc(GetProcessHeap(), 0,
275 usage
->rgpszUsageIdentifier
,
276 (usage
->cUsageIdentifier
+ 1) * sizeof(LPSTR
));
277 if (usage
->rgpszUsageIdentifier
)
278 usage
->rgpszUsageIdentifier
[usage
->cUsageIdentifier
++] = oid
;
281 HeapFree(GetProcessHeap(), 0, usage
);
287 static CERT_ENHKEY_USAGE
*convert_usages_str_to_usage(LPSTR usageStr
)
289 CERT_ENHKEY_USAGE
*usage
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
290 sizeof(CERT_ENHKEY_USAGE
));
296 for (ptr
= usageStr
, comma
= strchr(ptr
, ','); usage
&& ptr
&& *ptr
;
297 ptr
= comma
? comma
+ 1 : NULL
,
298 comma
= ptr
? strchr(ptr
, ',') : NULL
)
302 add_oid_to_usage(usage
, ptr
);
308 static CERT_ENHKEY_USAGE
*create_advanced_filter(void)
310 CERT_ENHKEY_USAGE
*advancedUsage
= HeapAlloc(GetProcessHeap(),
311 HEAP_ZERO_MEMORY
, sizeof(CERT_ENHKEY_USAGE
));
315 PCCRYPT_OID_INFO
*usages
;
317 if (WTHelperGetKnownUsages(1, &usages
))
319 LPSTR disabledUsagesStr
;
321 if ((disabledUsagesStr
= get_cert_mgr_usages()))
323 CERT_ENHKEY_USAGE
*disabledUsages
=
324 convert_usages_str_to_usage(disabledUsagesStr
);
328 PCCRYPT_OID_INFO
*ptr
;
330 for (ptr
= usages
; *ptr
; ptr
++)
333 BOOL disabled
= FALSE
;
335 for (i
= 0; !disabled
&&
336 i
< disabledUsages
->cUsageIdentifier
; i
++)
337 if (!strcmp(disabledUsages
->rgpszUsageIdentifier
[i
],
341 add_oid_to_usage(advancedUsage
,
342 (LPSTR
)(*ptr
)->pszOID
);
344 /* The individual strings are pointers to disabledUsagesStr,
345 * so they're freed when it is.
347 HeapFree(GetProcessHeap(), 0,
348 disabledUsages
->rgpszUsageIdentifier
);
349 HeapFree(GetProcessHeap(), 0, disabledUsages
);
351 HeapFree(GetProcessHeap(), 0, disabledUsagesStr
);
353 WTHelperGetKnownUsages(2, &usages
);
356 return advancedUsage
;
359 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
);
361 static void show_store_certs(HWND hwnd
, HCERTSTORE store
)
363 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
364 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
365 PCCERT_CONTEXT cert
= NULL
;
366 DWORD allocatedLen
= 0;
369 PurposeFilter filter
= PurposeFilterShowAll
;
371 CERT_ENHKEY_USAGE
*advanced
= NULL
;
373 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
376 INT_PTR data
= SendMessageW(cb
, CB_GETITEMDATA
, index
, 0);
382 PCCRYPT_OID_INFO info
= (PCCRYPT_OID_INFO
)data
;
384 filter
= PurposeFilterShowOID
;
388 if (filter
== PurposeFilterShowAdvanced
)
389 advanced
= create_advanced_filter();
391 cert
= CertEnumCertificatesInStore(store
, cert
);
396 if (filter
== PurposeFilterShowAll
)
403 if (CertGetValidUsages(1, &cert
, &numOIDs
, NULL
, &cbOIDs
))
407 /* -1 implies all usages are valid */
412 LPSTR
*oids
= HeapAlloc(GetProcessHeap(), 0, cbOIDs
);
416 if (CertGetValidUsages(1, &cert
, &numOIDs
, oids
,
421 if (filter
== PurposeFilterShowOID
)
423 for (i
= 0; !show
&& i
< numOIDs
; i
++)
424 if (!strcmp(oids
[i
], oid
))
429 for (i
= 0; !show
&& i
< numOIDs
; i
++)
434 j
< advanced
->cUsageIdentifier
; j
++)
436 advanced
->rgpszUsageIdentifier
[j
]))
441 HeapFree(GetProcessHeap(), 0, oids
);
447 add_cert_to_view(lv
, cert
, &allocatedLen
, &str
);
450 HeapFree(GetProcessHeap(), 0, str
);
453 HeapFree(GetProcessHeap(), 0, advanced
->rgpszUsageIdentifier
);
454 HeapFree(GetProcessHeap(), 0, advanced
);
456 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
457 (LPARAM
)cert_mgr_sort_by_subject
);
460 static const WCHAR my
[] = { 'M','y',0 };
461 static const WCHAR addressBook
[] = {
462 'A','d','d','r','e','s','s','B','o','o','k',0 };
463 static const WCHAR ca
[] = { 'C','A',0 };
464 static const WCHAR root
[] = { 'R','o','o','t',0 };
465 static const WCHAR trustedPublisher
[] = {
466 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
467 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
469 struct CertMgrStoreInfo
473 int removePluralWarning
;
476 static const struct CertMgrStoreInfo defaultStoreList
[] = {
477 { my
, IDS_WARN_REMOVE_MY
, IDS_WARN_REMOVE_PLURAL_MY
},
478 { addressBook
, IDS_WARN_REMOVE_ADDRESSBOOK
,
479 IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK
},
480 { ca
, IDS_WARN_REMOVE_CA
, IDS_WARN_REMOVE_PLURAL_CA
},
481 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
482 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
483 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
484 { disallowed
, IDS_WARN_REMOVE_DEFAULT
},
487 static const struct CertMgrStoreInfo publisherStoreList
[] = {
488 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
489 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
490 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
491 { disallowed
, IDS_WARN_REMOVE_PLURAL_DEFAULT
},
496 HIMAGELIST imageList
;
499 const struct CertMgrStoreInfo
*stores
;
502 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
, struct CertMgrData
*data
)
504 const struct CertMgrStoreInfo
*storeList
;
506 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
508 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
510 storeList
= publisherStoreList
;
511 cStores
= sizeof(publisherStoreList
) / sizeof(publisherStoreList
[0]);
515 storeList
= defaultStoreList
;
516 cStores
= sizeof(defaultStoreList
) / sizeof(defaultStoreList
[0]);
518 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
520 data
->nStores
= cStores
;
521 data
->stores
= storeList
;
522 for (i
= 0; i
< cStores
; i
++)
528 if (!(name
= CryptFindLocalizedName(storeList
[i
].name
)))
529 name
= storeList
[i
].name
;
530 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
531 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
].name
);
532 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
533 item
.pszText
= (LPWSTR
)name
;
534 item
.lParam
= (LPARAM
)store
;
535 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
539 static void free_certs(HWND lv
)
542 int items
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
544 for (i
= 0; i
< items
; i
++)
546 item
.mask
= LVIF_PARAM
;
549 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
550 CertFreeCertificateContext((PCCERT_CONTEXT
)item
.lParam
);
554 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
558 item
.mask
= TCIF_PARAM
;
559 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
560 return (HCERTSTORE
)item
.lParam
;
563 static HCERTSTORE
cert_mgr_current_store(HWND hwnd
)
565 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
567 return cert_mgr_index_to_store(tab
, SendMessageW(tab
, TCM_GETCURSEL
, 0, 0));
570 static void close_stores(HWND tab
)
572 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
574 for (i
= 0; i
< tabs
; i
++)
575 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
578 static void refresh_store_certs(HWND hwnd
)
580 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
583 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
584 show_store_certs(hwnd
, cert_mgr_current_store(hwnd
));
588 CheckBitmapIndexUnchecked
= 1,
589 CheckBitmapIndexChecked
= 2,
590 CheckBitmapIndexDisabledUnchecked
= 3,
591 CheckBitmapIndexDisabledChecked
= 4
594 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
,
595 CheckBitmapIndex state
)
599 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
600 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
601 item
.stateMask
= LVIS_STATEIMAGEMASK
;
602 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
604 item
.lParam
= (LPARAM
)info
;
605 item
.pszText
= (LPWSTR
)info
->pwszName
;
606 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
609 static void add_known_usages_to_list(HWND lv
, CheckBitmapIndex state
)
611 PCCRYPT_OID_INFO
*usages
;
613 if (WTHelperGetKnownUsages(1, &usages
))
615 PCCRYPT_OID_INFO
*ptr
;
617 for (ptr
= usages
; *ptr
; ptr
++)
618 add_known_usage(lv
, *ptr
, state
);
619 WTHelperGetKnownUsages(2, &usages
);
623 static void toggle_usage(HWND hwnd
, int iItem
)
627 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
629 item
.mask
= LVIF_STATE
;
632 item
.stateMask
= LVIS_STATEIMAGEMASK
;
633 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
636 int state
= item
.state
>> 12;
638 item
.state
= INDEXTOSTATEIMAGEMASK(
639 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
640 CheckBitmapIndexChecked
);
641 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
645 static LONG_PTR
find_oid_in_list(HWND lv
, LPCSTR oid
)
647 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
648 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
653 LVFINDINFOW findInfo
;
655 findInfo
.flags
= LVFI_PARAM
;
656 findInfo
.lParam
= (LPARAM
)oidInfo
;
657 ret
= SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
);
661 LVFINDINFOA findInfo
;
663 findInfo
.flags
= LVFI_STRING
;
665 ret
= SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
);
670 static void save_cert_mgr_usages(HWND hwnd
)
672 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
673 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
674 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
675 'r','p','o','s','e',0 };
677 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
678 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
682 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
684 item
.stateMask
= LVIS_STATEIMAGEMASK
;
685 for (i
= 0; i
< purposes
; i
++)
688 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
690 int state
= item
.state
>> 12;
692 if (state
== CheckBitmapIndexUnchecked
)
694 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
695 BOOL firstString
= TRUE
;
698 str
= HeapAlloc(GetProcessHeap(), 0,
699 strlen(info
->pszOID
) + 1);
702 str
= HeapReAlloc(GetProcessHeap(), 0, str
,
703 strlen(str
) + 1 + strlen(info
->pszOID
) + 1);
708 LPSTR ptr
= firstString
? str
: str
+ strlen(str
);
712 strcpy(ptr
, info
->pszOID
);
717 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_ALL_ACCESS
,
721 RegSetValueExA(key
, "Purpose", 0, REG_SZ
, (const BYTE
*)str
,
724 RegDeleteValueA(key
, "Purpose");
727 HeapFree(GetProcessHeap(), 0, str
);
730 static LRESULT CALLBACK
cert_mgr_advanced_dlg_proc(HWND hwnd
, UINT msg
,
731 WPARAM wp
, LPARAM lp
)
739 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
740 HIMAGELIST imageList
;
741 LPSTR disabledUsages
;
743 GetWindowRect(lv
, &rc
);
744 column
.mask
= LVCF_WIDTH
;
745 column
.cx
= rc
.right
- rc
.left
;
746 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
747 imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 4, 0);
751 COLORREF backColor
= RGB(255, 0, 255);
753 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
754 ImageList_AddMasked(imageList
, bmp
, backColor
);
756 ImageList_SetBkColor(imageList
, CLR_NONE
);
757 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)imageList
);
758 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)imageList
);
760 add_known_usages_to_list(lv
, CheckBitmapIndexChecked
);
761 if ((disabledUsages
= get_cert_mgr_usages()))
765 for (ptr
= disabledUsages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
766 ptr
= comma
? comma
+ 1 : NULL
,
767 comma
= ptr
? strchr(ptr
, ',') : NULL
)
773 if ((index
= find_oid_in_list(lv
, ptr
)) != -1)
774 toggle_usage(hwnd
, index
);
776 HeapFree(GetProcessHeap(), 0, disabledUsages
);
782 NMHDR
*hdr
= (NMHDR
*)lp
;
788 nm
= (NMITEMACTIVATE
*)lp
;
789 toggle_usage(hwnd
, nm
->iItem
);
790 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
799 save_cert_mgr_usages(hwnd
);
800 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
801 EndDialog(hwnd
, IDOK
);
804 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
805 EndDialog(hwnd
, IDCANCEL
);
813 static void cert_mgr_clear_cert_selection(HWND hwnd
)
815 WCHAR empty
[] = { 0 };
817 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), FALSE
);
818 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), FALSE
);
819 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), FALSE
);
820 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
822 refresh_store_certs(hwnd
);
825 static PCCERT_CONTEXT
cert_mgr_index_to_cert(HWND hwnd
, int index
)
827 PCCERT_CONTEXT cert
= NULL
;
830 item
.mask
= LVIF_PARAM
;
833 if (SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_GETITEMW
, 0,
835 cert
= (PCCERT_CONTEXT
)item
.lParam
;
839 static void show_selected_cert(HWND hwnd
, int index
)
841 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
845 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
847 memset(&viewInfo
, 0, sizeof(viewInfo
));
848 viewInfo
.dwSize
= sizeof(viewInfo
);
849 viewInfo
.hwndParent
= hwnd
;
850 viewInfo
.pCertContext
= cert
;
851 /* FIXME: this should be modal */
852 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
856 static void cert_mgr_show_cert_usages(HWND hwnd
, int index
)
858 HWND text
= GetDlgItem(hwnd
, IDC_MGR_PURPOSES
);
859 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
860 PCERT_ENHKEY_USAGE usage
;
863 /* Get enhanced key usage. Have to check for a property and an extension
864 * separately, because CertGetEnhancedKeyUsage will succeed and return an
865 * empty usage if neither is set. Unfortunately an empty usage implies
866 * no usage is allowed, so we have to distinguish between the two cases.
868 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
871 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
872 if (!CertGetEnhancedKeyUsage(cert
,
873 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
875 HeapFree(GetProcessHeap(), 0, usage
);
879 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
882 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
883 if (!CertGetEnhancedKeyUsage(cert
,
884 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
886 HeapFree(GetProcessHeap(), 0, usage
);
894 if (usage
->cUsageIdentifier
)
896 static const WCHAR commaSpace
[] = { ',',' ',0 };
900 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
902 PCCRYPT_OID_INFO info
=
903 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
904 usage
->rgpszUsageIdentifier
[i
],
905 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
908 len
+= strlenW(info
->pwszName
);
910 len
+= strlen(usage
->rgpszUsageIdentifier
[i
]);
911 if (i
< usage
->cUsageIdentifier
- 1)
912 len
+= strlenW(commaSpace
);
914 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
917 for (i
= 0, ptr
= str
; i
< usage
->cUsageIdentifier
; i
++)
919 PCCRYPT_OID_INFO info
=
920 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
921 usage
->rgpszUsageIdentifier
[i
],
922 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
926 strcpyW(ptr
, info
->pwszName
);
927 ptr
+= strlenW(info
->pwszName
);
931 LPCSTR src
= usage
->rgpszUsageIdentifier
[i
];
933 for (; *src
; ptr
++, src
++)
937 if (i
< usage
->cUsageIdentifier
- 1)
939 strcpyW(ptr
, commaSpace
);
940 ptr
+= strlenW(commaSpace
);
944 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)str
);
945 HeapFree(GetProcessHeap(), 0, str
);
947 HeapFree(GetProcessHeap(), 0, usage
);
951 WCHAR buf
[MAX_STRING_LEN
];
953 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_NONE
, buf
,
954 sizeof(buf
) / sizeof(buf
[0]));
955 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
960 WCHAR buf
[MAX_STRING_LEN
];
962 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_ALL
, buf
,
963 sizeof(buf
) / sizeof(buf
[0]));
964 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
968 static void cert_mgr_do_remove(HWND hwnd
)
970 int tabIndex
= SendMessageW(GetDlgItem(hwnd
, IDC_MGR_STORES
),
971 TCM_GETCURSEL
, 0, 0);
972 struct CertMgrData
*data
=
973 (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
975 if (tabIndex
< data
->nStores
)
977 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
978 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
982 if (SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0) > 1)
983 warningID
= data
->stores
[tabIndex
].removePluralWarning
;
985 warningID
= data
->stores
[tabIndex
].removeWarning
;
987 pTitle
= data
->title
;
990 LoadStringW(hInstance
, IDS_CERT_MGR
, title
,
991 sizeof(title
) / sizeof(title
[0]));
994 LoadStringW(hInstance
, warningID
, warning
,
995 sizeof(warning
) / sizeof(warning
[0]));
996 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
1001 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1005 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1008 CertDeleteCertificateFromStore(cert
);
1010 } while (selection
>= 0);
1011 cert_mgr_clear_cert_selection(hwnd
);
1016 static void cert_mgr_do_export(HWND hwnd
)
1018 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1019 int selectionCount
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1021 if (selectionCount
== 1)
1023 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1028 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, selection
);
1032 CRYPTUI_WIZ_EXPORT_INFO info
;
1034 info
.dwSize
= sizeof(info
);
1035 info
.pwszExportFileName
= NULL
;
1036 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
1037 info
.u
.pCertContext
= cert
;
1039 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1043 else if (selectionCount
> 1)
1045 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1046 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1050 CRYPTUI_WIZ_EXPORT_INFO info
;
1053 info
.dwSize
= sizeof(info
);
1054 info
.pwszExportFileName
= NULL
;
1055 info
.dwSubjectChoice
=
1056 CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
;
1057 info
.u
.hCertStore
= store
;
1060 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1064 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1067 CertAddCertificateContextToStore(store
, cert
,
1068 CERT_STORE_ADD_ALWAYS
, NULL
);
1070 } while (selection
>= 0);
1071 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1072 CertCloseStore(store
, 0);
1077 static int cert_mgr_sort_by_text(HWND lv
, int col
, int index1
, int index2
)
1080 WCHAR buf1
[MAX_STRING_LEN
];
1081 WCHAR buf2
[MAX_STRING_LEN
];
1083 item
.cchTextMax
= sizeof(buf1
) / sizeof(buf1
[0]);
1084 item
.mask
= LVIF_TEXT
;
1085 item
.pszText
= buf1
;
1086 item
.iItem
= index1
;
1087 item
.iSubItem
= col
;
1088 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1089 item
.pszText
= buf2
;
1090 item
.iItem
= index2
;
1091 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1092 return strcmpW(buf1
, buf2
);
1095 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1097 return cert_mgr_sort_by_text((HWND
)lp
, 0, lp1
, lp2
);
1100 static int CALLBACK
cert_mgr_sort_by_issuer(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1102 return cert_mgr_sort_by_text((HWND
)lp
, 1, lp1
, lp2
);
1105 static int CALLBACK
cert_mgr_sort_by_date(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1107 PCCERT_CONTEXT cert1
= (PCCERT_CONTEXT
)lp1
;
1108 PCCERT_CONTEXT cert2
= (PCCERT_CONTEXT
)lp2
;
1109 return CompareFileTime(&cert1
->pCertInfo
->NotAfter
,
1110 &cert2
->pCertInfo
->NotAfter
);
1113 static int CALLBACK
cert_mgr_sort_by_friendly_name(LPARAM lp1
, LPARAM lp2
,
1116 return cert_mgr_sort_by_text((HWND
)lp
, 3, lp1
, lp2
);
1119 static LRESULT CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1122 struct CertMgrData
*data
;
1128 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
1129 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
1130 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
1132 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData
));
1135 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
1136 if (data
->imageList
)
1139 COLORREF backColor
= RGB(255, 0, 255);
1141 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
1142 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
1144 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
1145 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_SETIMAGELIST
,
1146 LVSIL_SMALL
, (LPARAM
)data
->imageList
);
1148 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
1149 data
->title
= pCryptUICertMgr
->pwszTitle
;
1151 initialize_purpose_selection(hwnd
);
1152 add_cert_columns(hwnd
);
1153 if (pCryptUICertMgr
->pwszTitle
)
1154 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1155 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
1156 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
, data
);
1157 show_store_certs(hwnd
, cert_mgr_index_to_store(tab
, 0));
1162 NMHDR
*hdr
= (NMHDR
*)lp
;
1167 cert_mgr_clear_cert_selection(hwnd
);
1169 case LVN_ITEMCHANGED
:
1171 WCHAR empty
[] = { 0 };
1172 NMITEMACTIVATE
*nm
= (NMITEMACTIVATE
*)lp
;
1173 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1174 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1176 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), numSelected
> 0);
1177 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), numSelected
> 0);
1178 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), numSelected
== 1);
1179 if (numSelected
== 1)
1180 cert_mgr_show_cert_usages(hwnd
, nm
->iItem
);
1182 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
1187 show_selected_cert(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
1191 NMLVKEYDOWN
*lvk
= (NMLVKEYDOWN
*)lp
;
1193 if (lvk
->wVKey
== VK_DELETE
)
1194 cert_mgr_do_remove(hwnd
);
1197 case LVN_COLUMNCLICK
:
1199 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
1200 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1202 /* FIXME: doesn't support swapping sort order between ascending
1205 switch (nmlv
->iSubItem
)
1208 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1209 (LPARAM
)cert_mgr_sort_by_subject
);
1212 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1213 (LPARAM
)cert_mgr_sort_by_issuer
);
1216 SendMessageW(lv
, LVM_SORTITEMS
, 0,
1217 (LPARAM
)cert_mgr_sort_by_date
);
1220 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1221 (LPARAM
)cert_mgr_sort_by_friendly_name
);
1232 case ((CBN_SELCHANGE
<< 16) | IDC_MGR_PURPOSE_SELECTION
):
1233 cert_mgr_clear_cert_selection(hwnd
);
1235 case IDC_MGR_IMPORT
:
1236 if (CryptUIWizImport(0, hwnd
, NULL
, NULL
,
1237 cert_mgr_current_store(hwnd
)))
1238 refresh_store_certs(hwnd
);
1240 case IDC_MGR_ADVANCED
:
1241 if (DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR_ADVANCED
),
1242 hwnd
, cert_mgr_advanced_dlg_proc
) == IDOK
)
1244 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
1246 LPWSTR curString
= NULL
;
1248 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
1251 len
= SendMessageW(cb
, CB_GETLBTEXTLEN
, index
, 0);
1252 curString
= HeapAlloc(GetProcessHeap(), 0,
1253 (len
+ 1) * sizeof(WCHAR
));
1254 SendMessageW(cb
, CB_GETLBTEXT
, index
, (LPARAM
)curString
);
1256 SendMessageW(cb
, CB_RESETCONTENT
, 0, 0);
1257 initialize_purpose_selection(hwnd
);
1260 index
= SendMessageW(cb
, CB_FINDSTRINGEXACT
, -1,
1263 SendMessageW(cb
, CB_SETCURSEL
, index
, 0);
1264 HeapFree(GetProcessHeap(), 0, curString
);
1266 refresh_store_certs(hwnd
);
1271 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1272 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1276 show_selected_cert(hwnd
, selection
);
1279 case IDC_MGR_EXPORT
:
1280 cert_mgr_do_export(hwnd
);
1282 case IDC_MGR_REMOVE
:
1283 cert_mgr_do_remove(hwnd
);
1286 free_certs(GetDlgItem(hwnd
, IDC_MGR_CERTS
));
1287 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1288 data
= (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1289 ImageList_Destroy(data
->imageList
);
1290 HeapFree(GetProcessHeap(), 0, data
);
1291 EndDialog(hwnd
, IDCANCEL
);
1299 /***********************************************************************
1300 * CryptUIDlgCertMgr (CRYPTUI.@)
1302 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
1304 TRACE("(%p)\n", pCryptUICertMgr
);
1306 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
1308 WARN("unexpected size %d\n", pCryptUICertMgr
->dwSize
);
1309 SetLastError(E_INVALIDARG
);
1312 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
1313 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
1317 /* FIXME: real names are unknown, functions are undocumented */
1318 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
1321 void *pvSystemStoreLocationPara
;
1322 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
1324 typedef struct _CRYPTUI_ENUM_DATA
1327 HCERTSTORE
*rghStore
;
1329 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
1330 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
1332 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
1335 /* Values for dwFlags */
1336 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
1338 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
1345 CRYPTUI_ENUM_DATA
*pEnumData
;
1346 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1348 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
1350 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
1357 CRYPTUI_ENUM_DATA
*pEnumData
;
1358 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1360 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
1374 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
1375 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
1378 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
1379 TVINSERTSTRUCTW tvis
;
1380 LPCWSTR localizedName
;
1383 tvis
.hParent
= NULL
;
1384 tvis
.hInsertAfter
= TVI_LAST
;
1385 tvis
.u
.item
.mask
= TVIF_TEXT
;
1386 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
1388 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(), 0,
1389 sizeof(struct StoreInfo
));
1393 storeInfo
->type
= SystemStore
;
1394 storeInfo
->u
.name
= HeapAlloc(GetProcessHeap(), 0,
1395 (strlenW(pvSystemStore
) + 1) * sizeof(WCHAR
));
1396 if (storeInfo
->u
.name
)
1398 tvis
.u
.item
.mask
|= TVIF_PARAM
;
1399 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1400 strcpyW(storeInfo
->u
.name
, pvSystemStore
);
1404 HeapFree(GetProcessHeap(), 0, storeInfo
);
1410 tvis
.u
.item
.pszText
= (LPWSTR
)localizedName
;
1413 tvis
.u
.item
.pszText
= (LPWSTR
)pvSystemStore
;
1414 /* FIXME: need a folder icon for the store too */
1416 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1420 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
1423 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1425 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
1426 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
1427 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
1428 hwnd
, enum_store_callback
);
1429 for (i
= 0; i
< pEnumData
->cStores
; i
++)
1433 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1434 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
1436 LPWSTR name
= HeapAlloc(GetProcessHeap(), 0, size
);
1440 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1441 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
1443 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(),
1444 0, sizeof(struct StoreInfo
));
1448 TVINSERTSTRUCTW tvis
;
1450 storeInfo
->type
= StoreHandle
;
1451 storeInfo
->u
.store
= pEnumData
->rghStore
[i
];
1452 tvis
.hParent
= NULL
;
1453 tvis
.hInsertAfter
= TVI_LAST
;
1454 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
1455 tvis
.u
.item
.pszText
= name
;
1456 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1457 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1460 HeapFree(GetProcessHeap(), 0, name
);
1466 static void free_store_info(HWND tree
)
1468 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
1475 memset(&item
, 0, sizeof(item
));
1476 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
1478 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1481 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1483 if (storeInfo
->type
== SystemStore
)
1484 HeapFree(GetProcessHeap(), 0, storeInfo
->u
.name
);
1485 HeapFree(GetProcessHeap(), 0, storeInfo
);
1487 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
1492 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
1494 WCHAR buf
[MAX_STRING_LEN
];
1498 memset(&item
, 0, sizeof(item
));
1499 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
1501 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
1503 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1506 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1508 if (storeInfo
->type
== StoreHandle
)
1509 store
= storeInfo
->u
.store
;
1511 store
= CertOpenSystemStoreW(0, storeInfo
->u
.name
);
1515 /* It's implicitly a system store */
1516 store
= CertOpenSystemStoreW(0, buf
);
1521 struct SelectStoreInfo
1523 PCRYPTUI_SELECTSTORE_INFO_W info
;
1527 static LRESULT CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1530 struct SelectStoreInfo
*selectInfo
;
1537 selectInfo
= (struct SelectStoreInfo
*)lp
;
1538 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
1539 if (selectInfo
->info
->pwszTitle
)
1540 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1541 (LPARAM
)selectInfo
->info
->pwszTitle
);
1542 if (selectInfo
->info
->pwszText
)
1543 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
1544 (LPARAM
)selectInfo
->info
->pwszText
);
1545 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
1546 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
1547 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
1555 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1556 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
1557 TVM_GETNEXTITEM
, TVGN_CARET
, 0);
1559 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
1563 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
1565 if (selectInfo
->info
->pwszTitle
)
1566 pTitle
= selectInfo
->info
->pwszTitle
;
1569 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
,
1570 sizeof(title
) / sizeof(title
[0]));
1573 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
,
1574 sizeof(error
) / sizeof(error
[0]));
1575 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
1579 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
1581 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
1582 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
1583 selectInfo
->info
->pvArg
))
1585 selectInfo
->store
= store
;
1586 free_store_info(tree
);
1587 EndDialog(hwnd
, IDOK
);
1590 CertCloseStore(store
, 0);
1596 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
1597 EndDialog(hwnd
, IDCANCEL
);
1606 /***********************************************************************
1607 * CryptUIDlgSelectStoreW (CRYPTUI.@)
1609 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
1611 struct SelectStoreInfo selectInfo
= { info
, NULL
};
1613 TRACE("(%p)\n", info
);
1615 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
1617 WARN("unexpected size %d\n", info
->dwSize
);
1618 SetLastError(E_INVALIDARG
);
1621 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
1622 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
1623 return selectInfo
.store
;
1626 /***********************************************************************
1627 * CryptUIDlgSelectStoreA (CRYPTUI.@)
1629 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
1631 CRYPTUI_SELECTSTORE_INFO_W infoW
;
1635 TRACE("(%p)\n", info
);
1637 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
1639 WARN("unexpected size %d\n", info
->dwSize
);
1640 SetLastError(E_INVALIDARG
);
1643 memcpy(&infoW
, info
, sizeof(*info
));
1646 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
1647 infoW
.pwszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1648 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
1653 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
1654 infoW
.pwszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1655 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
1657 ret
= CryptUIDlgSelectStoreW(&infoW
);
1658 HeapFree(GetProcessHeap(), 0, infoW
.pwszText
);
1659 HeapFree(GetProcessHeap(), 0, infoW
.pwszTitle
);
1663 /***********************************************************************
1664 * CryptUIDlgViewCertificateA (CRYPTUI.@)
1666 BOOL WINAPI
CryptUIDlgViewCertificateA(
1667 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
1669 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
1670 LPWSTR title
= NULL
;
1673 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
1675 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
1676 if (pCertViewInfo
->szTitle
)
1678 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
1681 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1684 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
1686 viewInfo
.szTitle
= title
;
1694 if (pCertViewInfo
->cPropSheetPages
)
1696 FIXME("ignoring additional prop sheet pages\n");
1697 viewInfo
.cPropSheetPages
= 0;
1699 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
1700 HeapFree(GetProcessHeap(), 0, title
);
1705 struct ReadStringStruct
1712 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
1715 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
1716 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
1718 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
1720 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
1722 *pcb
= cch
* sizeof(WCHAR
);
1726 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
1728 struct ReadStringStruct string
;
1729 EDITSTREAM editstream
;
1731 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
1736 editstream
.dwCookie
= (DWORD_PTR
)&string
;
1737 editstream
.dwError
= 0;
1738 editstream
.pfnCallback
= read_text_callback
;
1739 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
1740 (LPARAM
)&editstream
);
1743 static void add_string_resource_to_control(HWND hwnd
, int id
)
1748 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1749 add_unformatted_text_to_control(hwnd
, str
, len
);
1752 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
1753 LONG len
, const PARAFORMAT2
*fmt
)
1755 add_unformatted_text_to_control(hwnd
, text
, len
);
1756 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
1759 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
1760 const PARAFORMAT2
*fmt
)
1765 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1766 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
1769 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
1775 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
1778 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1780 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
1785 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
1786 DWORD dwType
, DWORD dwFlags
)
1788 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
1792 /* Don't include NULL-terminator in output */
1793 DWORD len
= lstrlenW(name
);
1795 add_unformatted_text_to_control(hwnd
, name
, len
);
1796 HeapFree(GetProcessHeap(), 0, name
);
1800 static void add_icon_to_control(HWND hwnd
, int id
)
1803 LPRICHEDITOLE richEditOle
= NULL
;
1804 LPOLEOBJECT object
= NULL
;
1806 LPOLECACHE oleCache
= NULL
;
1807 FORMATETC formatEtc
;
1809 LPDATAOBJECT dataObject
= NULL
;
1810 HBITMAP bitmap
= NULL
;
1813 LPOLECLIENTSITE clientSite
= NULL
;
1816 TRACE("(%p, %d)\n", hwnd
, id
);
1818 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
1821 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
1825 hr
= IOleObject_GetUserClassID(object
, &clsid
);
1828 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
1831 formatEtc
.cfFormat
= CF_BITMAP
;
1832 formatEtc
.ptd
= NULL
;
1833 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
1834 formatEtc
.lindex
= -1;
1835 formatEtc
.tymed
= TYMED_GDI
;
1836 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
1839 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
1840 (void**)&dataObject
);
1843 hr
= IRichEditOle_GetClientSite(richEditOle
, &clientSite
);
1846 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
1847 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
1850 rect
.left
= rect
.top
= 0;
1851 rect
.right
= GetSystemMetrics(SM_CXICON
);
1852 rect
.bottom
= GetSystemMetrics(SM_CYICON
);
1853 stgm
.tymed
= TYMED_GDI
;
1854 stgm
.u
.hBitmap
= bitmap
;
1855 stgm
.pUnkForRelease
= NULL
;
1856 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
1860 reObject
.cbStruct
= sizeof(reObject
);
1861 reObject
.cp
= REO_CP_SELECTION
;
1862 reObject
.clsid
= clsid
;
1863 reObject
.poleobj
= object
;
1864 reObject
.pstg
= NULL
;
1865 reObject
.polesite
= clientSite
;
1866 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
1867 reObject
.dvaspect
= DVASPECT_CONTENT
;
1868 reObject
.dwFlags
= 0;
1869 reObject
.dwUser
= 0;
1871 IRichEditOle_InsertObject(richEditOle
, &reObject
);
1875 IOleClientSite_Release(clientSite
);
1877 IDataObject_Release(dataObject
);
1879 IOleCache_Release(oleCache
);
1881 IOleObject_Release(object
);
1883 IRichEditOle_Release(richEditOle
);
1886 #define MY_INDENT 200
1888 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
1891 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
1894 parFmt
.cbSize
= sizeof(parFmt
);
1895 parFmt
.dwMask
= PFM_STARTINDENT
;
1896 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1899 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
1900 lstrlenW(oidInfo
->pwszName
), &parFmt
);
1901 add_unformatted_text_to_control(hwnd
, &nl
, 1);
1911 /* The following list MUST be lexicographically sorted by OID */
1912 static struct OIDToString oidMap
[] = {
1913 /* 1.3.6.1.4.1.311.10.3.1 */
1914 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
1915 /* 1.3.6.1.4.1.311.10.3.4 */
1916 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
1917 /* 1.3.6.1.4.1.311.10.3.4.1 */
1918 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
1919 /* 1.3.6.1.4.1.311.10.3.5 */
1920 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
1921 /* 1.3.6.1.4.1.311.10.3.6 */
1922 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
1923 /* 1.3.6.1.4.1.311.10.3.7 */
1924 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
1925 /* 1.3.6.1.4.1.311.10.3.8 */
1926 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
1927 /* 1.3.6.1.4.1.311.10.3.9 */
1928 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
1929 /* 1.3.6.1.4.1.311.10.3.10 */
1930 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
1931 /* 1.3.6.1.4.1.311.10.3.11 */
1932 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
1933 /* 1.3.6.1.4.1.311.10.3.12 */
1934 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
1935 /* 1.3.6.1.4.1.311.10.3.13 */
1936 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
1937 /* 1.3.6.1.4.1.311.10.5.1 */
1938 { szOID_DRM
, IDS_PURPOSE_DRM
},
1939 /* 1.3.6.1.4.1.311.10.6.1 */
1940 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
1941 /* 1.3.6.1.4.1.311.10.6.2 */
1942 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
1943 /* 1.3.6.1.4.1.311.20.2.1 */
1944 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
1945 /* 1.3.6.1.4.1.311.20.2.2 */
1946 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
1947 /* 1.3.6.1.4.1.311.21.5 */
1948 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
1949 /* 1.3.6.1.4.1.311.21.6 */
1950 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
1951 /* 1.3.6.1.4.1.311.21.19 */
1952 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
1953 /* 1.3.6.1.5.5.7.3.1 */
1954 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
1955 /* 1.3.6.1.5.5.7.3.2 */
1956 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
1957 /* 1.3.6.1.5.5.7.3.3 */
1958 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
1959 /* 1.3.6.1.5.5.7.3.4 */
1960 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
1961 /* 1.3.6.1.5.5.7.3.5 */
1962 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
1963 /* 1.3.6.1.5.5.7.3.6 */
1964 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
1965 /* 1.3.6.1.5.5.7.3.7 */
1966 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
1967 /* 1.3.6.1.5.5.7.3.8 */
1968 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
1971 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
1973 int indexHigh
= sizeof(oidMap
) / sizeof(oidMap
[0]) - 1, indexLow
= 0;
1975 while (indexLow
<= indexHigh
)
1977 int cmp
, i
= (indexLow
+ indexHigh
) / 2;
1978 if (!(cmp
= strcmp(oid
, oidMap
[i
].oid
)))
1988 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
1990 struct OIDToString
*entry
;
1994 parFmt
.cbSize
= sizeof(parFmt
);
1995 parFmt
.dwMask
= PFM_STARTINDENT
;
1996 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1997 if ((entry
= findSupportedOID(oid
)))
1999 WCHAR
*str
, *linebreak
, *ptr
;
2000 BOOL multiline
= FALSE
;
2003 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
2006 if ((linebreak
= memchrW(ptr
, '\n', len
)))
2008 WCHAR copy
[MAX_STRING_LEN
];
2011 /* The source string contains a newline, which the richedit
2012 * control won't find since it's interpreted as a paragraph
2013 * break. Therefore copy up to the newline. lstrcpynW always
2014 * NULL-terminates, so pass one more than the length of the
2015 * source line so the copy includes the entire line and the
2018 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
2019 add_text_with_paraformat_to_control(text
, copy
,
2020 linebreak
- ptr
, &parFmt
);
2021 ptr
= linebreak
+ 1;
2022 add_unformatted_text_to_control(text
, &nl
, 1);
2024 else if (multiline
&& *ptr
)
2026 /* Add the last line */
2027 add_text_with_paraformat_to_control(text
, ptr
,
2028 len
- (ptr
- str
), &parFmt
);
2029 add_unformatted_text_to_control(text
, &nl
, 1);
2031 } while (linebreak
);
2034 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
2035 add_unformatted_text_to_control(text
, &nl
, 1);
2040 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
2041 (strlen(oid
) + 1) * sizeof(WCHAR
));
2048 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
2051 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
2053 add_unformatted_text_to_control(text
, &nl
, 1);
2054 HeapFree(GetProcessHeap(), 0, oidW
);
2059 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
2060 BOOL
*anyUsageAdded
)
2062 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
2064 CHARFORMATW charFmt
;
2065 PCERT_EXTENSION policyExt
;
2066 if (!*anyUsageAdded
)
2070 parFmt
.cbSize
= sizeof(parFmt
);
2071 parFmt
.dwMask
= PFM_STARTINDENT
;
2072 parFmt
.dxStartIndent
= MY_INDENT
;
2073 add_string_resource_with_paraformat_to_control(text
,
2074 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2075 add_unformatted_text_to_control(text
, &nl
, 1);
2076 *anyUsageAdded
= TRUE
;
2078 memset(&charFmt
, 0, sizeof(charFmt
));
2079 charFmt
.cbSize
= sizeof(charFmt
);
2080 charFmt
.dwMask
= CFM_BOLD
;
2081 charFmt
.dwEffects
= 0;
2082 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2083 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
2084 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
2086 CERT_POLICIES_INFO
*policies
;
2089 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
2090 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2091 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2095 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
2099 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2100 add_local_oid_text_to_control(text
,
2101 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2102 pszPolicyQualifierId
);
2104 LocalFree(policies
);
2108 add_oid_text_to_control(text
, any_app_policy
);
2111 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
2112 BOOL
*anyUsageAdded
)
2116 BOOL badUsages
= FALSE
;
2118 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
2120 CHARFORMATW charFmt
;
2121 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
2122 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
2126 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
2130 if (!*anyUsageAdded
)
2134 parFmt
.cbSize
= sizeof(parFmt
);
2135 parFmt
.dwMask
= PFM_STARTINDENT
;
2136 parFmt
.dxStartIndent
= MY_INDENT
;
2137 add_string_resource_with_paraformat_to_control(text
,
2138 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2139 add_unformatted_text_to_control(text
, &nl
, 1);
2140 *anyUsageAdded
= TRUE
;
2142 memset(&charFmt
, 0, sizeof(charFmt
));
2143 charFmt
.cbSize
= sizeof(charFmt
);
2144 charFmt
.dwMask
= CFM_BOLD
;
2145 charFmt
.dwEffects
= 0;
2146 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
2148 if (!usage
->cUsageIdentifier
)
2149 add_oid_text_to_control(text
, any_cert_policy
);
2151 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2152 add_local_oid_text_to_control(text
,
2153 usage
->rgpszUsageIdentifier
[i
]);
2157 HeapFree(GetProcessHeap(), 0, usage
);
2167 static void set_policy_text(HWND text
,
2168 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2170 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
2171 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
2173 if (pCertViewInfo
->cPurposes
)
2177 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
2179 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
2180 includeCertUsages
= TRUE
;
2181 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
2182 szOID_ANY_APPLICATION_POLICY
))
2183 includeAppUsages
= TRUE
;
2189 includeAppUsages
= includeCertUsages
= TRUE
;
2190 if (includeAppUsages
)
2191 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
2192 if (includeCertUsages
)
2193 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
2199 parFmt
.cbSize
= sizeof(parFmt
);
2200 parFmt
.dwMask
= PFM_STARTINDENT
;
2201 parFmt
.dxStartIndent
= MY_INDENT
;
2202 add_string_resource_with_paraformat_to_control(text
,
2203 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
2207 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
2210 CRYPT_OBJID_BLOB
*ret
= NULL
;
2213 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
2217 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2218 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2219 pszPolicyQualifierId
, policyOid
))
2220 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2226 static WCHAR
*get_cps_str_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2228 LPWSTR qualifierStr
= NULL
;
2229 CERT_NAME_VALUE
*qualifierValue
;
2232 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
2233 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2234 &qualifierValue
, &size
))
2236 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
2237 &qualifierValue
->Value
, NULL
, 0);
2238 qualifierStr
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
2240 CertRDNValueToStrW(qualifierValue
->dwValueType
,
2241 &qualifierValue
->Value
, qualifierStr
, size
);
2242 LocalFree(qualifierValue
);
2244 return qualifierStr
;
2247 static WCHAR
*get_user_notice_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2250 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
2253 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
2254 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
2255 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2256 &qualifierValue
, &size
))
2258 str
= HeapAlloc(GetProcessHeap(), 0,
2259 (strlenW(qualifierValue
->pszDisplayText
) + 1) * sizeof(WCHAR
));
2261 strcpyW(str
, qualifierValue
->pszDisplayText
);
2262 LocalFree(qualifierValue
);
2267 struct IssuerStatement
2273 static void set_issuer_statement(HWND hwnd
,
2274 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2276 PCERT_EXTENSION policyExt
;
2278 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
2279 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
2280 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
2281 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
2283 CERT_POLICIES_INFO
*policies
;
2286 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
2287 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2288 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2290 CRYPT_OBJID_BLOB
*qualifier
;
2291 LPWSTR cps
= NULL
, userNotice
= NULL
;
2293 if ((qualifier
= find_policy_qualifier(policies
,
2294 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
2295 cps
= get_cps_str_from_qualifier(qualifier
);
2296 if ((qualifier
= find_policy_qualifier(policies
,
2297 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
2298 userNotice
= get_user_notice_from_qualifier(qualifier
);
2299 if (cps
|| userNotice
)
2301 struct IssuerStatement
*issuerStatement
=
2302 HeapAlloc(GetProcessHeap(), 0, sizeof(struct IssuerStatement
));
2304 if (issuerStatement
)
2306 issuerStatement
->cps
= cps
;
2307 issuerStatement
->userNotice
= userNotice
;
2308 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
2309 SetWindowLongPtrW(hwnd
, DWLP_USER
,
2310 (ULONG_PTR
)issuerStatement
);
2313 LocalFree(policies
);
2318 static void set_cert_info(HWND hwnd
,
2319 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2321 CHARFORMATW charFmt
;
2323 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
2324 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
2325 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2326 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
2327 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
2328 pCertViewInfo
->idxCounterSigner
);
2329 CRYPT_PROVIDER_CERT
*root
=
2330 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
2332 if (!provSigner
->pChainContext
||
2333 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2334 CERT_TRUST_IS_PARTIAL_CHAIN
))
2335 add_icon_to_control(icon
, IDB_CERT_WARNING
);
2336 else if (!root
->fTrustedRoot
)
2337 add_icon_to_control(icon
, IDB_CERT_ERROR
);
2339 add_icon_to_control(icon
, IDB_CERT
);
2341 memset(&charFmt
, 0, sizeof(charFmt
));
2342 charFmt
.cbSize
= sizeof(charFmt
);
2343 charFmt
.dwMask
= CFM_BOLD
;
2344 charFmt
.dwEffects
= CFE_BOLD
;
2345 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2346 /* FIXME: vertically center text */
2347 parFmt
.cbSize
= sizeof(parFmt
);
2348 parFmt
.dwMask
= PFM_STARTINDENT
;
2349 parFmt
.dxStartIndent
= MY_INDENT
;
2350 add_string_resource_with_paraformat_to_control(text
,
2351 IDS_CERTIFICATEINFORMATION
, &parFmt
);
2353 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
2354 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2355 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
2356 add_string_resource_with_paraformat_to_control(text
,
2357 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
2358 else if (!provSigner
->pChainContext
||
2359 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2360 CERT_TRUST_IS_PARTIAL_CHAIN
))
2361 add_string_resource_with_paraformat_to_control(text
,
2362 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
2363 else if (!root
->fTrustedRoot
)
2365 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
2366 add_string_resource_with_paraformat_to_control(text
,
2367 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
2369 add_string_resource_with_paraformat_to_control(text
,
2370 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
2374 set_policy_text(text
, pCertViewInfo
);
2375 set_issuer_statement(hwnd
, pCertViewInfo
);
2379 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
2380 DWORD nameFlags
, int heading
)
2383 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2384 CHARFORMATW charFmt
;
2387 memset(&charFmt
, 0, sizeof(charFmt
));
2388 charFmt
.cbSize
= sizeof(charFmt
);
2389 charFmt
.dwMask
= CFM_BOLD
;
2390 charFmt
.dwEffects
= CFE_BOLD
;
2391 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2392 parFmt
.cbSize
= sizeof(parFmt
);
2393 parFmt
.dwMask
= PFM_STARTINDENT
;
2394 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2395 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
2396 charFmt
.dwEffects
= 0;
2397 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2398 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2400 add_unformatted_text_to_control(text
, &nl
, 1);
2401 add_unformatted_text_to_control(text
, &nl
, 1);
2402 add_unformatted_text_to_control(text
, &nl
, 1);
2406 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
2408 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
2412 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
2413 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2414 FileTimeToSystemTime(fileTime
, &sysTime
);
2415 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
2416 sizeof(date
) / sizeof(date
[0]));
2417 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
2420 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
2423 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2424 CHARFORMATW charFmt
;
2427 memset(&charFmt
, 0, sizeof(charFmt
));
2428 charFmt
.cbSize
= sizeof(charFmt
);
2429 charFmt
.dwMask
= CFM_BOLD
;
2430 charFmt
.dwEffects
= CFE_BOLD
;
2431 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2432 parFmt
.cbSize
= sizeof(parFmt
);
2433 parFmt
.dwMask
= PFM_STARTINDENT
;
2434 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2435 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
2437 charFmt
.dwEffects
= 0;
2438 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2439 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
2440 charFmt
.dwEffects
= CFE_BOLD
;
2441 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2442 add_string_resource_to_control(text
, IDS_VALID_TO
);
2443 charFmt
.dwEffects
= 0;
2444 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2445 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
2446 add_unformatted_text_to_control(text
, &nl
, 1);
2449 static void set_general_info(HWND hwnd
,
2450 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2452 set_cert_info(hwnd
, pCertViewInfo
);
2453 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
2454 IDS_SUBJECT_HEADING
);
2455 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
2456 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
2457 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
2460 static LRESULT CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2465 struct IssuerStatement
*issuerStatement
;
2470 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
2471 issuerStatement
= (struct IssuerStatement
*)lp
;
2472 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
2473 strlenW(issuerStatement
->userNotice
));
2474 if (issuerStatement
->cps
)
2475 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
2477 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
2483 EndDialog(hwnd
, IDOK
);
2488 IBindCtx
*bctx
= NULL
;
2491 CreateBindCtx(0, &bctx
);
2492 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2493 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
2494 HLNF_OPENINNEWWINDOW
, 0);
2495 IBindCtx_Release(bctx
);
2503 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
2505 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
2506 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
2509 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2512 PROPSHEETPAGEW
*page
;
2513 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2515 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2520 page
= (PROPSHEETPAGEW
*)lp
;
2521 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
2522 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
2523 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
2524 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
2525 set_general_info(hwnd
, pCertViewInfo
);
2530 case IDC_ADDTOSTORE
:
2531 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
2533 case IDC_ISSUERSTATEMENT
:
2535 struct IssuerStatement
*issuerStatement
=
2536 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2538 if (issuerStatement
)
2540 if (issuerStatement
->userNotice
)
2541 show_user_notice(hwnd
, issuerStatement
);
2542 else if (issuerStatement
->cps
)
2544 IBindCtx
*bctx
= NULL
;
2546 CreateBindCtx(0, &bctx
);
2547 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
2548 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
2549 IBindCtx_Release(bctx
);
2560 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
2561 PROPSHEETPAGEW
*page
)
2563 struct IssuerStatement
*issuerStatement
;
2569 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2570 if (issuerStatement
)
2572 HeapFree(GetProcessHeap(), 0, issuerStatement
->cps
);
2573 HeapFree(GetProcessHeap(), 0, issuerStatement
->userNotice
);
2574 HeapFree(GetProcessHeap(), 0, issuerStatement
);
2581 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2582 PROPSHEETPAGEW
*page
)
2584 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2585 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2586 page
->dwFlags
= PSP_USECALLBACK
;
2587 page
->pfnCallback
= general_callback_proc
;
2588 page
->hInstance
= hInstance
;
2589 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
2590 page
->pfnDlgProc
= general_dlg_proc
;
2591 page
->lParam
= (LPARAM
)pCertViewInfo
;
2594 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
2596 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
2598 static const WCHAR fmt
[] = { 'V','%','d',0 };
2599 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, 12 * sizeof(WCHAR
));
2602 sprintfW(buf
, fmt
, cert
->pCertInfo
->dwVersion
);
2606 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
2608 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, (cb
* 3 + 1) * sizeof(WCHAR
));
2612 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2616 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
2617 sprintfW(ptr
, fmt
, ((BYTE
*)pb
)[i
]);
2622 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
2624 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
2625 cert
->pCertInfo
->SerialNumber
.cbData
);
2628 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
2630 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2631 CERT_NAME_ISSUER_FLAG
);
2634 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
2637 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
2638 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, NULL
, 0);
2642 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2644 CertNameToStrW(X509_ASN_ENCODING
, name
,
2645 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, str
, len
);
2650 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
2652 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
2655 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
2657 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2660 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
2662 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
2665 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
2667 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
2672 /* FIXME: format isn't quite right, want time too */
2673 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
,
2674 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2675 FileTimeToSystemTime(fileTime
, &sysTime
);
2676 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
2679 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2681 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
2687 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
2689 return format_long_date(&cert
->pCertInfo
->NotBefore
);
2692 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
2694 return format_long_date(&cert
->pCertInfo
->NotAfter
);
2697 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
2699 PCCRYPT_OID_INFO oidInfo
;
2702 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2703 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
2706 WCHAR fmt
[MAX_STRING_LEN
];
2708 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
,
2709 sizeof(fmt
) / sizeof(fmt
[0])))
2713 /* Allocate the output buffer. Use the number of bytes in the
2714 * public key as a conservative (high) estimate for the number of
2715 * digits in its output.
2716 * The output is of the form (in English)
2717 * "<public key algorithm> (<public key bit length> bits)".
2718 * Ordinarily having two positional parameters in a string is not a
2719 * good idea, but as this isn't a sentence fragment, it shouldn't
2720 * be word-order dependent.
2722 len
= strlenW(fmt
) + strlenW(oidInfo
->pwszName
) +
2723 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8;
2724 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(*buf
));
2728 args
[0] = (DWORD_PTR
)oidInfo
->pwszName
;
2729 args
[1] = CertGetPublicKeyLength(X509_ASN_ENCODING
,
2730 &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2731 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
2732 fmt
, 0, 0, buf
, len
, (__ms_va_list
*)args
);
2739 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
2741 return format_hex_string(
2742 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
2743 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
2746 struct field_value_data
;
2749 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2750 BOOL
*pfPropertiesChanged
;
2752 struct field_value_data
*fields
;
2755 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
2757 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
2759 struct field_value_data
2761 create_detailed_value_func create
;
2762 LPWSTR detailed_value
;
2766 static void add_field_value_data(struct detail_data
*data
,
2767 create_detailed_value_func create
, void *param
)
2770 data
->fields
= HeapReAlloc(GetProcessHeap(), 0, data
->fields
,
2771 (data
->cFields
+ 1) * sizeof(struct field_value_data
));
2773 data
->fields
= HeapAlloc(GetProcessHeap(), 0,
2774 sizeof(struct field_value_data
));
2777 data
->fields
[data
->cFields
].create
= create
;
2778 data
->fields
[data
->cFields
].detailed_value
= NULL
;
2779 data
->fields
[data
->cFields
].param
= param
;
2784 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2785 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2788 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2790 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
2793 item
.pszText
= field
;
2794 item
.lParam
= (LPARAM
)data
;
2795 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2798 item
.pszText
= value
;
2800 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
2802 add_field_value_data(data
, create
, param
);
2805 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2806 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2808 WCHAR buf
[MAX_STRING_LEN
];
2810 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2811 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
2817 field_format_func format
;
2818 create_detailed_value_func create_detailed_value
;
2821 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
2822 const struct v1_field
*field
)
2824 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
2828 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
2829 field
->create_detailed_value
, NULL
);
2830 HeapFree(GetProcessHeap(), 0, val
);
2834 static const struct v1_field v1_fields
[] = {
2835 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
2836 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
2837 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
2838 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
2839 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
2840 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
2841 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
2842 field_format_detailed_public_key
}
2845 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
2848 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2850 /* The last item in v1_fields is the public key, which is not in the loop
2851 * because it's a special case.
2853 for (i
= 0; i
< sizeof(v1_fields
) / sizeof(v1_fields
[0]) - 1; i
++)
2854 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2855 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
2856 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2859 static WCHAR
*crypt_format_extension(const CERT_EXTENSION
*ext
, DWORD formatStrType
)
2864 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2865 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
2867 str
= HeapAlloc(GetProcessHeap(), 0, size
);
2868 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2869 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
2874 static WCHAR
*field_format_extension_hex_with_ascii(const CERT_EXTENSION
*ext
)
2878 if (ext
->Value
.cbData
)
2880 /* The output is formatted as:
2881 * <hex bytes> <ascii bytes>\n
2882 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
2883 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
2884 * the byte is not printable.
2885 * So, for example, the extension value consisting of the following
2887 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
2888 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
2890 * 30 14 31 12 30 10 06 03 0.1.0...
2891 * 55 04 03 13 09 4a 75 61 U....Jua
2892 * 6e 20 4c 61 6e 67 n Lang
2893 * The allocation size therefore requires:
2894 * - 4 characters per character in an 8-byte line
2895 * (2 for the hex format, one for the space, one for the ASCII value)
2896 * - 3 more characters per 8-byte line (two spaces and a newline)
2897 * - 1 character for the terminating nul
2898 * FIXME: should use a fixed-width font for this
2900 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
2902 str
= HeapAlloc(GetProcessHeap(), 0,
2903 (lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
2906 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2910 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
2912 /* Output as hex bytes first */
2913 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
2914 sprintfW(ptr
, fmt
, ext
->Value
.pbData
[j
]);
2915 /* Pad the hex output with spaces for alignment */
2916 if (j
== ext
->Value
.cbData
&& j
% 8)
2918 static const WCHAR pad
[] = { ' ',' ',' ' };
2920 for (; j
% 8; j
++, ptr
+= sizeof(pad
) / sizeof(pad
[0]))
2921 memcpy(ptr
, pad
, sizeof(pad
));
2923 /* The last sprintfW included a space, so just insert one
2924 * more space between the hex bytes and the ASCII output
2927 /* Output as ASCII bytes */
2928 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
2930 if (isprintW(ext
->Value
.pbData
[j
]) &&
2931 !isspaceW(ext
->Value
.pbData
[j
]))
2932 *ptr
= ext
->Value
.pbData
[j
];
2944 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
2946 PCERT_EXTENSION ext
= param
;
2947 LPWSTR str
= crypt_format_extension(ext
,
2948 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
2951 str
= field_format_extension_hex_with_ascii(ext
);
2955 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
2956 PCERT_EXTENSION ext
)
2958 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2960 LPWSTR val
= crypt_format_extension(ext
, 0);
2963 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
2964 val
, field_format_detailed_extension
, ext
);
2967 DWORD len
= strlen(ext
->pszObjId
);
2968 LPWSTR oidW
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
2974 for (i
= 0; i
<= len
; i
++)
2975 oidW
[i
] = ext
->pszObjId
[i
];
2976 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
2977 field_format_detailed_extension
, ext
);
2978 HeapFree(GetProcessHeap(), 0, oidW
);
2981 HeapFree(GetProcessHeap(), 0, val
);
2984 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
2987 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2989 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2990 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
2993 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
2996 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2998 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2999 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
3000 add_cert_extension_detail(hwnd
, data
,
3001 &cert
->pCertInfo
->rgExtension
[i
]);
3004 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
3006 struct prop_id_to_string_id
3010 BOOL prop_is_string
;
3011 prop_to_value_func prop_to_value
;
3014 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
3018 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
3019 ext
.fCritical
= FALSE
;
3020 ext
.Value
.pbData
= pb
;
3021 ext
.Value
.cbData
= cb
;
3022 return crypt_format_extension(&ext
, 0);
3025 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
3026 * disabled for read-only certificates, but native doesn't appear to do that.
3028 static const struct prop_id_to_string_id prop_id_map
[] = {
3029 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
3030 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
3031 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
3032 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
3033 format_enhanced_key_usage_value
},
3036 static void add_properties(HWND hwnd
, struct detail_data
*data
)
3039 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
3041 for (i
= 0; i
< sizeof(prop_id_map
) / sizeof(prop_id_map
[0]); i
++)
3045 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
3051 /* FIXME: MS adds a separate value for the signature hash
3054 pb
= HeapAlloc(GetProcessHeap(), 0, cb
);
3057 if (CertGetCertificateContextProperty(cert
,
3058 prop_id_map
[i
].prop
, pb
, &cb
))
3060 if (prop_id_map
[i
].prop_is_string
)
3063 /* Don't double-free pb */
3067 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
3069 HeapFree(GetProcessHeap(), 0, pb
);
3071 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
3077 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
3079 add_v1_fields(hwnd
, data
);
3080 add_all_extensions(hwnd
, data
);
3081 add_properties(hwnd
, data
);
3084 struct selection_list_item
3087 add_fields_func add
;
3090 static const struct selection_list_item listItems
[] = {
3091 { IDS_FIELDS_ALL
, add_all_fields
},
3092 { IDS_FIELDS_V1
, add_v1_fields
},
3093 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
3094 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
3095 { IDS_FIELDS_PROPERTIES
, add_properties
},
3098 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
3100 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3101 WCHAR buf
[MAX_STRING_LEN
];
3104 for (i
= 0; i
< sizeof(listItems
) / sizeof(listItems
[0]); i
++)
3108 LoadStringW(hInstance
, listItems
[i
].id
, buf
,
3109 sizeof(buf
) / sizeof(buf
[0]));
3110 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
3111 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
3113 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
3116 static void create_listview_columns(HWND hwnd
)
3118 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3120 WCHAR buf
[MAX_STRING_LEN
];
3123 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
3124 GetWindowRect(lv
, &rc
);
3125 LoadStringW(hInstance
, IDS_FIELD
, buf
, sizeof(buf
) / sizeof(buf
[0]));
3126 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
3127 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
3128 column
.pszText
= buf
;
3129 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3130 LoadStringW(hInstance
, IDS_VALUE
, buf
, sizeof(buf
) / sizeof(buf
[0]));
3131 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
3134 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
3136 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3138 if (sel
>= 0 && sel
< sizeof(listItems
) / sizeof(listItems
[0]))
3140 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
3141 listItems
[sel
].add(list
, data
);
3145 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
3147 create_show_list(hwnd
, data
);
3148 create_listview_columns(hwnd
);
3149 set_fields_selection(hwnd
, data
, 0);
3152 static void add_purpose(HWND hwnd
, LPCSTR oid
)
3154 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3155 PCRYPT_OID_INFO info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3156 sizeof(CRYPT_OID_INFO
));
3160 char *oidCopy
= HeapAlloc(GetProcessHeap(), 0, strlen(oid
) + 1);
3166 strcpy(oidCopy
, oid
);
3167 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
3168 info
->pszOID
= oidCopy
;
3169 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
3170 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
3171 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3172 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3174 item
.lParam
= (LPARAM
)info
;
3175 item
.pszText
= oidCopy
;
3176 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3179 HeapFree(GetProcessHeap(), 0, info
);
3183 static BOOL
is_valid_oid(LPCSTR oid
)
3187 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
3189 else if (oid
[1] != '.')
3196 BOOL expectNum
= TRUE
;
3198 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
3204 else if (*(ptr
+ 1) == '.')
3211 else if (!(*(ptr
+ 1)))
3221 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
3223 return find_oid_in_list(GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
), oid
)
3227 #define MAX_PURPOSE 255
3229 static LRESULT CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
3230 WPARAM wp
, LPARAM lp
)
3233 char buf
[MAX_PURPOSE
+ 1];
3238 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
3240 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
3241 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
3247 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
3249 /* Show/hide scroll bar on description depending on how much
3252 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
3253 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3255 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3262 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
,
3263 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3266 /* An empty purpose is the same as cancelling */
3267 EndDialog(hwnd
, IDCANCEL
);
3270 else if (!is_valid_oid(buf
))
3272 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3274 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
,
3275 sizeof(error
) / sizeof(error
[0]));
3276 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3277 sizeof(title
) / sizeof(title
[0]));
3278 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
3280 else if (is_oid_in_list(
3281 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
3283 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3285 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
,
3286 error
, sizeof(error
) / sizeof(error
[0]));
3287 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3288 sizeof(title
) / sizeof(title
[0]));
3289 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
3293 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3295 add_purpose(parent
, buf
);
3296 EndDialog(hwnd
, wp
);
3301 EndDialog(hwnd
, wp
);
3312 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
3317 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
3319 name
= HeapAlloc(GetProcessHeap(), 0, cb
);
3322 if (!CertGetCertificateContextProperty(cert
, prop
, name
, &cb
))
3324 HeapFree(GetProcessHeap(), 0, name
);
3332 static void redraw_states(HWND list
, BOOL enabled
)
3334 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
3336 for (i
= 0; i
< items
; i
++)
3338 BOOL change
= FALSE
;
3341 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
3342 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
3343 * to be a handy macro for it.
3348 if (state
== CheckBitmapIndexDisabledChecked
)
3350 state
= CheckBitmapIndexChecked
;
3353 if (state
== CheckBitmapIndexDisabledUnchecked
)
3355 state
= CheckBitmapIndexUnchecked
;
3361 if (state
== CheckBitmapIndexChecked
)
3363 state
= CheckBitmapIndexDisabledChecked
;
3366 if (state
== CheckBitmapIndexUnchecked
)
3368 state
= CheckBitmapIndexDisabledUnchecked
;
3376 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
3377 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3378 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
3384 PurposeEnableAll
= 0,
3386 PurposeEnableSelected
3389 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
3391 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3395 case PurposeEnableAll
:
3396 case PurposeDisableAll
:
3397 EnableWindow(lv
, FALSE
);
3398 redraw_states(lv
, FALSE
);
3399 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
3401 case PurposeEnableSelected
:
3402 EnableWindow(lv
, TRUE
);
3403 redraw_states(lv
, TRUE
);
3404 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
3408 struct edit_cert_data
3410 PCCERT_CONTEXT cert
;
3411 BOOL
*pfPropertiesChanged
;
3412 HIMAGELIST imageList
;
3415 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
3417 PCCERT_CONTEXT cert
= data
->cert
;
3418 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3419 PCERT_ENHKEY_USAGE usage
;
3423 PurposeSelection purposeSelection
= PurposeEnableAll
;
3425 GetWindowRect(lv
, &rc
);
3426 column
.mask
= LVCF_WIDTH
;
3427 column
.cx
= rc
.right
- rc
.left
;
3428 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3429 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
3431 /* Get enhanced key usage. Have to check for a property and an extension
3432 * separately, because CertGetEnhancedKeyUsage will succeed and return an
3433 * empty usage if neither is set. Unfortunately an empty usage implies
3434 * no usage is allowed, so we have to distinguish between the two cases.
3436 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
3439 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3440 if (!CertGetEnhancedKeyUsage(cert
,
3441 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3443 HeapFree(GetProcessHeap(), 0, usage
);
3446 else if (usage
->cUsageIdentifier
)
3447 purposeSelection
= PurposeEnableSelected
;
3449 purposeSelection
= PurposeDisableAll
;
3451 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
3454 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3455 if (!CertGetEnhancedKeyUsage(cert
,
3456 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3458 HeapFree(GetProcessHeap(), 0, usage
);
3461 else if (usage
->cUsageIdentifier
)
3462 purposeSelection
= PurposeEnableAll
;
3464 purposeSelection
= PurposeDisableAll
;
3468 purposeSelection
= PurposeEnableAll
;
3475 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
3477 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
3478 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
3481 add_known_usage(lv
, info
, CheckBitmapIndexDisabledChecked
);
3483 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
3485 HeapFree(GetProcessHeap(), 0, usage
);
3488 add_known_usages_to_list(lv
, CheckBitmapIndexDisabledChecked
);
3489 select_purposes(hwnd
, purposeSelection
);
3490 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
3494 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
3496 PCCERT_CONTEXT cert
= data
->cert
;
3499 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
3501 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
3503 HeapFree(GetProcessHeap(), 0, str
);
3505 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
3507 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
3509 HeapFree(GetProcessHeap(), 0, str
);
3511 show_cert_usages(hwnd
, data
);
3514 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
3517 if (str
&& strlenW(str
))
3519 CRYPT_DATA_BLOB blob
;
3521 blob
.pbData
= (BYTE
*)str
;
3522 blob
.cbData
= (strlenW(str
) + 1) * sizeof(WCHAR
);
3523 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
3526 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
3529 #define WM_REFRESH_VIEW WM_USER + 0
3531 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
3533 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
3534 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
3538 #define MAX_FRIENDLY_NAME 40
3539 #define MAX_DESCRIPTION 255
3541 static void apply_general_changes(HWND hwnd
)
3543 WCHAR buf
[MAX_DESCRIPTION
+ 1];
3544 struct edit_cert_data
*data
=
3545 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3547 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
,
3548 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3549 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
3550 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
,
3551 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3552 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
3553 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
3555 /* Setting a NULL usage removes the enhanced key usage property. */
3556 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
3558 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
3560 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3562 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3564 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
3566 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3567 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3568 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
3571 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3573 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3574 for (i
= 0; i
< purposes
; i
++)
3577 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
3579 int state
= item
.state
>> 12;
3581 if (state
== CheckBitmapIndexChecked
)
3583 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
3585 if (usage
.cUsageIdentifier
)
3586 usage
.rgpszUsageIdentifier
=
3587 HeapReAlloc(GetProcessHeap(), 0,
3588 usage
.rgpszUsageIdentifier
,
3589 (usage
.cUsageIdentifier
+ 1) * sizeof(LPSTR
));
3591 usage
.rgpszUsageIdentifier
=
3592 HeapAlloc(GetProcessHeap(), 0, sizeof(LPSTR
));
3593 if (usage
.rgpszUsageIdentifier
)
3594 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
3595 (LPSTR
)info
->pszOID
;
3599 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3600 HeapFree(GetProcessHeap(), 0, usage
.rgpszUsageIdentifier
);
3602 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
3603 if (data
->pfPropertiesChanged
)
3604 *data
->pfPropertiesChanged
= TRUE
;
3607 static LRESULT CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
3608 WPARAM wp
, LPARAM lp
)
3610 PROPSHEETPAGEW
*page
;
3612 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3618 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3619 struct detail_data
*detailData
;
3620 struct edit_cert_data
*editData
;
3622 page
= (PROPSHEETPAGEW
*)lp
;
3623 detailData
= (struct detail_data
*)page
->lParam
;
3624 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
3625 MAX_FRIENDLY_NAME
, 0);
3626 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
3627 ShowScrollBar(description
, SB_VERT
, FALSE
);
3628 editData
= HeapAlloc(GetProcessHeap(), 0,
3629 sizeof(struct edit_cert_data
));
3632 editData
->imageList
= ImageList_Create(16, 16,
3633 ILC_COLOR4
| ILC_MASK
, 4, 0);
3634 if (editData
->imageList
)
3637 COLORREF backColor
= RGB(255, 0, 255);
3639 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
3640 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
3642 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
3644 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
3645 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
3646 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
3647 set_general_cert_properties(hwnd
, editData
);
3653 NMHDR
*hdr
= (NMHDR
*)lp
;
3659 nm
= (NMITEMACTIVATE
*)lp
;
3660 toggle_usage(hwnd
, nm
->iItem
);
3661 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3664 apply_general_changes(hwnd
);
3673 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3674 if (LOWORD(wp
) == IDC_DESCRIPTION
)
3676 /* Show/hide scroll bar on description depending on how much
3679 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3680 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3682 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3688 case IDC_ADD_PURPOSE
:
3689 if (DialogBoxParamW(hInstance
,
3690 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
3691 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
3692 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3694 case IDC_ENABLE_ALL_PURPOSES
:
3695 case IDC_DISABLE_ALL_PURPOSES
:
3696 case IDC_ENABLE_SELECTED_PURPOSES
:
3697 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3698 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
3708 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
3709 PROPSHEETPAGEW
*page
)
3713 struct edit_cert_data
*data
;
3718 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3719 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3720 for (i
= 0; i
< cItem
; i
++)
3724 item
.mask
= LVIF_PARAM
;
3727 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
3729 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
3731 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
3733 HeapFree(GetProcessHeap(), 0, (LPSTR
)info
->pszOID
);
3734 HeapFree(GetProcessHeap(), 0, info
);
3738 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3741 ImageList_Destroy(data
->imageList
);
3742 HeapFree(GetProcessHeap(), 0, data
);
3749 static void show_edit_cert_properties_dialog(HWND parent
,
3750 struct detail_data
*data
)
3752 PROPSHEETHEADERW hdr
;
3753 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
3755 TRACE("(%p)\n", data
);
3757 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
3758 page
.dwSize
= sizeof(page
);
3759 page
.dwFlags
= PSP_USECALLBACK
;
3760 page
.pfnCallback
= cert_properties_general_callback
;
3761 page
.hInstance
= hInstance
;
3762 page
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
3763 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
3764 page
.lParam
= (LPARAM
)data
;
3766 memset(&hdr
, 0, sizeof(hdr
));
3767 hdr
.dwSize
= sizeof(hdr
);
3768 hdr
.hwndParent
= parent
;
3769 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
3770 hdr
.hInstance
= hInstance
;
3771 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
3772 hdr
.u3
.ppsp
= &page
;
3774 PropertySheetW(&hdr
);
3777 static void free_detail_fields(struct detail_data
*data
)
3781 for (i
= 0; i
< data
->cFields
; i
++)
3782 HeapFree(GetProcessHeap(), 0, data
->fields
[i
].detailed_value
);
3783 HeapFree(GetProcessHeap(), 0, data
->fields
);
3784 data
->fields
= NULL
;
3788 static void refresh_details_view(HWND hwnd
)
3790 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3792 struct detail_data
*data
;
3794 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3795 /* Actually, any index will do, since they all store the same data value */
3796 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
3797 free_detail_fields(data
);
3798 set_fields_selection(hwnd
, data
, curSel
);
3801 static LRESULT CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3804 PROPSHEETPAGEW
*page
;
3805 struct detail_data
*data
;
3807 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3812 page
= (PROPSHEETPAGEW
*)lp
;
3813 data
= (struct detail_data
*)page
->lParam
;
3814 create_cert_details_list(hwnd
, data
);
3815 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
3816 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
3817 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
3818 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
3823 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3825 nm
= (NMITEMACTIVATE
*)lp
;
3826 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
3827 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
3829 data
= (struct detail_data
*)nm
->lParam
;
3830 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
3832 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
3833 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
3835 if (data
->fields
[nm
->iItem
].create
)
3836 val
= data
->fields
[nm
->iItem
].create(
3837 data
->pCertViewInfo
->pCertContext
,
3838 data
->fields
[nm
->iItem
].param
);
3844 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
3845 item
.mask
= LVIF_TEXT
;
3847 item
.iItem
= nm
->iItem
;
3849 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
3853 /* Select all the text in the control, the next update will
3856 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
3857 add_unformatted_text_to_control(valueCtl
, val
,
3858 val
? strlenW(val
) : 0);
3860 HeapFree(GetProcessHeap(), 0, val
);
3870 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3871 CRYPTUI_WIZ_EXPORT_INFO info
;
3873 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, 0, 0);
3874 info
.dwSize
= sizeof(info
);
3875 info
.pwszExportFileName
= NULL
;
3876 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
3877 info
.u
.pCertContext
= data
->pCertViewInfo
->pCertContext
;
3879 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
3882 case IDC_EDITPROPERTIES
:
3884 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3887 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3888 /* Actually, any index will do, since they all store the same
3891 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
3893 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
3896 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
3897 refresh_details_view(hwnd
);
3901 case WM_REFRESH_VIEW
:
3902 refresh_details_view(hwnd
);
3908 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
3909 PROPSHEETPAGEW
*page
)
3911 struct detail_data
*data
;
3916 data
= (struct detail_data
*)page
->lParam
;
3917 free_detail_fields(data
);
3918 HeapFree(GetProcessHeap(), 0, data
);
3924 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3925 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
3928 struct detail_data
*data
= HeapAlloc(GetProcessHeap(), 0,
3929 sizeof(struct detail_data
));
3933 data
->pCertViewInfo
= pCertViewInfo
;
3934 data
->pfPropertiesChanged
= pfPropertiesChanged
;
3936 data
->fields
= NULL
;
3937 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3938 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3939 page
->dwFlags
= PSP_USECALLBACK
;
3940 page
->pfnCallback
= detail_callback
;
3941 page
->hInstance
= hInstance
;
3942 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
3943 page
->pfnDlgProc
= detail_dlg_proc
;
3944 page
->lParam
= (LPARAM
)data
;
3952 struct hierarchy_data
3954 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
3955 HIMAGELIST imageList
;
3959 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
3961 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3962 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3963 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3964 data
->pCertViewInfo
->idxCounterSigner
);
3966 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
3967 * therefore always even.
3969 if (index
== provSigner
->csCertChain
- 1)
3970 return (LPARAM
)data
;
3971 return index
<< 1 | 1;
3974 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
3976 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3977 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3978 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3979 data
->pCertViewInfo
->idxCounterSigner
);
3982 return provSigner
->csCertChain
- 1;
3986 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
3989 struct hierarchy_data
*data
= NULL
;
3990 HTREEITEM root
= NULL
;
3993 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
3994 TVGN_PARENT
, (LPARAM
)hItem
);
4004 item
.mask
= TVIF_PARAM
;
4006 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4007 data
= (struct hierarchy_data
*)item
.lParam
;
4012 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
4014 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
4017 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
4021 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
4023 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4024 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4025 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4026 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
4027 data
->pCertViewInfo
->idxCounterSigner
);
4029 HTREEITEM parent
= NULL
;
4031 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
4032 for (i
= provSigner
->csCertChain
; i
; i
--)
4036 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
4039 TVINSERTSTRUCTW tvis
;
4041 tvis
.hParent
= parent
;
4042 tvis
.hInsertAfter
= TVI_LAST
;
4043 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
4044 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
4045 tvis
.u
.item
.pszText
= name
;
4046 tvis
.u
.item
.state
= TVIS_EXPANDED
;
4047 tvis
.u
.item
.stateMask
= TVIS_EXPANDED
;
4048 if (i
== 1 && (!provSigner
->pChainContext
||
4049 provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
4050 CERT_TRUST_IS_PARTIAL_CHAIN
))
4052 /* The root of the chain has a special case: if the chain is
4053 * a partial chain, the icon is a warning icon rather than an
4056 tvis
.u
.item
.iImage
= 2;
4058 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
4060 tvis
.u
.item
.iImage
= 0;
4062 tvis
.u
.item
.iImage
= 1;
4063 tvis
.u
.item
.iSelectedImage
= tvis
.u
.item
.iImage
;
4064 tvis
.u
.item
.lParam
= index_to_lparam(data
, i
- 1);
4065 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
4067 HeapFree(GetProcessHeap(), 0, name
);
4072 static void set_certificate_status(HWND hwnd
, const CRYPT_PROVIDER_CERT
*cert
)
4074 /* Select all the text in the control, the next update will replace it */
4075 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
4076 /* Set the highest priority error messages first. */
4077 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
4078 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
4079 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
4080 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
4081 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
4082 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
4083 else if (cert
->dwRevokedReason
)
4084 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
4086 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
4089 static void set_certificate_status_for_end_cert(HWND hwnd
,
4090 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
4092 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
4093 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4094 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
4095 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
4096 pCertViewInfo
->idxCounterSigner
);
4097 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
4098 pCertViewInfo
->idxCert
);
4100 set_certificate_status(status
, provCert
);
4103 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
4105 /* Disable view certificate button until a certificate is selected */
4106 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
4107 show_cert_chain(hwnd
, data
);
4108 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
4111 static void show_dialog_for_selected_cert(HWND hwnd
)
4113 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4115 struct hierarchy_data
*data
;
4118 memset(&item
, 0, sizeof(item
));
4119 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4120 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
, 0);
4121 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4122 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4123 selection
= lparam_to_index(data
, item
.lParam
);
4126 CRYPT_PROVIDER_SGNR
*provSigner
;
4127 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4128 BOOL changed
= FALSE
;
4130 provSigner
= WTHelperGetProvSignerFromChain(
4131 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4132 data
->pCertViewInfo
->idxSigner
,
4133 data
->pCertViewInfo
->fCounterSigner
,
4134 data
->pCertViewInfo
->idxCounterSigner
);
4135 memset(&viewInfo
, 0, sizeof(viewInfo
));
4136 viewInfo
.dwSize
= sizeof(viewInfo
);
4137 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
4138 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
4139 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
4140 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
4141 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
4142 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
4143 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
4144 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
4145 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
4148 /* Delete the contents of the tree */
4149 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4150 /* Reinitialize the tree */
4151 show_cert_hierarchy(hwnd
, data
);
4156 static LRESULT CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4159 PROPSHEETPAGEW
*page
;
4160 struct hierarchy_data
*data
;
4162 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4164 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
4169 page
= (PROPSHEETPAGEW
*)lp
;
4170 data
= (struct hierarchy_data
*)page
->lParam
;
4171 show_cert_hierarchy(hwnd
, data
);
4180 case TVN_SELCHANGEDW
:
4182 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
4184 CRYPT_PROVIDER_SGNR
*provSigner
;
4186 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
4187 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
4188 provSigner
= WTHelperGetProvSignerFromChain(
4189 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4190 data
->pCertViewInfo
->idxSigner
,
4191 data
->pCertViewInfo
->fCounterSigner
,
4192 data
->pCertViewInfo
->idxCounterSigner
);
4193 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
4194 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
4195 &provSigner
->pasCertChain
[selection
]);
4199 show_dialog_for_selected_cert(hwnd
);
4200 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4209 case IDC_VIEWCERTIFICATE
:
4210 show_dialog_for_selected_cert(hwnd
);
4214 case WM_REFRESH_VIEW
:
4218 /* Get hierarchy data */
4219 memset(&item
, 0, sizeof(item
));
4220 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4221 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
4223 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4224 /* Delete the contents of the tree */
4225 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4226 /* Reinitialize the tree */
4227 show_cert_hierarchy(hwnd
, data
);
4234 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
4235 PROPSHEETPAGEW
*page
)
4237 struct hierarchy_data
*data
;
4242 data
= (struct hierarchy_data
*)page
->lParam
;
4243 ImageList_Destroy(data
->imageList
);
4244 HeapFree(GetProcessHeap(), 0, data
);
4250 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4251 PROPSHEETPAGEW
*page
)
4253 struct hierarchy_data
*data
= HeapAlloc(GetProcessHeap(), 0,
4254 sizeof(struct hierarchy_data
));
4259 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
4260 if (data
->imageList
)
4263 COLORREF backColor
= RGB(255, 0, 255);
4265 data
->pCertViewInfo
= pCertViewInfo
;
4266 data
->selectedCert
= 0xffffffff;
4268 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
4269 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
4271 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
4273 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
4274 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
4275 page
->dwFlags
= PSP_USECALLBACK
;
4276 page
->hInstance
= hInstance
;
4277 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
4278 page
->pfnDlgProc
= hierarchy_dlg_proc
;
4279 page
->lParam
= (LPARAM
)data
;
4280 page
->pfnCallback
= hierarchy_callback
;
4284 HeapFree(GetProcessHeap(), 0, data
);
4289 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
4293 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
4297 case PSCB_INITIALIZED
:
4298 /* Get cancel button's position.. */
4299 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
4300 MapWindowPoints( 0, hwnd
, (POINT
*)&rc
, 2 );
4301 /* hide the cancel button.. */
4302 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
4303 /* and move the OK button to the cancel button's original position. */
4304 SetWindowPos(GetDlgItem(hwnd
, IDOK
), 0, rc
.left
, rc
.top
, 0, 0,
4305 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
4311 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4312 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
4314 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
4316 PROPSHEETPAGEW
*pages
;
4318 HMODULE lib
= LoadLibraryW(riched
);
4320 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
4321 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4323 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4325 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
4328 PROPSHEETHEADERW hdr
;
4329 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
4332 memset(&hdr
, 0, sizeof(hdr
));
4333 hdr
.dwSize
= sizeof(hdr
);
4334 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
4335 hdr
.hInstance
= hInstance
;
4336 if (pCertViewInfo
->szTitle
)
4337 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
4339 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
4340 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
4341 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4343 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
4344 &pages
[hdr
.nPages
]))
4347 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4349 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
4352 /* Copy each additional page, and create the init dialog struct for it
4354 if (pCertViewInfo
->cPropSheetPages
)
4356 init
= HeapAlloc(GetProcessHeap(), 0,
4357 pCertViewInfo
->cPropSheetPages
*
4358 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
4361 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
4363 memcpy(&pages
[hdr
.nPages
+ i
],
4364 &pCertViewInfo
->rgPropSheetPages
[i
],
4365 sizeof(PROPSHEETPAGEW
));
4366 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
4367 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
4368 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
4370 if (pCertViewInfo
->nStartPage
& 0x8000)
4372 /* Start page index is relative to the number of default
4375 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
4378 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
4379 hdr
.nPages
= nPages
;
4383 SetLastError(ERROR_OUTOFMEMORY
);
4387 /* Ignore the relative flag if there aren't any additional pages */
4388 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
4395 hdr
.u3
.ppsp
= pages
;
4396 hdr
.pfnCallback
= cert_prop_sheet_proc
;
4397 l
= PropertySheetW(&hdr
);
4400 SetLastError(ERROR_CANCELLED
);
4404 HeapFree(GetProcessHeap(), 0, init
);
4405 HeapFree(GetProcessHeap(), 0, pages
);
4408 SetLastError(ERROR_OUTOFMEMORY
);
4413 /***********************************************************************
4414 * CryptUIDlgViewCertificateW (CRYPTUI.@)
4416 BOOL WINAPI
CryptUIDlgViewCertificateW(
4417 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
4419 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
4420 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4422 WINTRUST_CERT_INFO cert
;
4424 CRYPT_PROVIDER_SGNR
*signer
;
4425 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
4427 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
4429 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
4431 SetLastError(ERROR_INVALID_PARAMETER
);
4434 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
4435 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
4436 if (!pCertViewInfo
->u
.hWVTStateData
)
4438 memset(&wvt
, 0, sizeof(wvt
));
4439 wvt
.cbStruct
= sizeof(wvt
);
4440 wvt
.dwUIChoice
= WTD_UI_NONE
;
4441 if (viewInfo
.dwFlags
&
4442 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
4443 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
4444 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
4445 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
4446 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
4447 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
4448 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
4449 memset(&cert
, 0, sizeof(cert
));
4450 cert
.cbStruct
= sizeof(cert
);
4451 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
4452 cert
.chStores
= viewInfo
.cStores
;
4453 cert
.pahStores
= viewInfo
.rghStores
;
4454 wvt
.u
.pCert
= &cert
;
4455 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
4456 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4457 viewInfo
.u
.pCryptProviderData
=
4458 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
4459 signer
= WTHelperGetProvSignerFromChain(
4460 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
4461 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
4466 viewInfo
.u
.pCryptProviderData
=
4467 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
4468 signer
= WTHelperGetProvSignerFromChain(
4469 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
4470 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
4471 viewInfo
.idxCounterSigner
);
4472 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
4477 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
4478 if (!pCertViewInfo
->u
.hWVTStateData
)
4480 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
4481 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4487 /***********************************************************************
4488 * CryptUIDlgViewContext (CRYPTUI.@)
4490 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
4491 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
4495 TRACE("(%d, %p, %p, %s, %08x, %p)\n", dwContextType
, pvContext
, hwnd
,
4496 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
4498 switch (dwContextType
)
4500 case CERT_STORE_CERTIFICATE_CONTEXT
:
4502 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4504 memset(&viewInfo
, 0, sizeof(viewInfo
));
4505 viewInfo
.dwSize
= sizeof(viewInfo
);
4506 viewInfo
.hwndParent
= hwnd
;
4507 viewInfo
.szTitle
= pwszTitle
;
4508 viewInfo
.pCertContext
= pvContext
;
4509 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
4513 FIXME("unimplemented for context type %d\n", dwContextType
);
4514 SetLastError(E_INVALIDARG
);
4520 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
4521 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
4522 * should be a CA. If neither extension is present, returns
4523 * defaultIfNotSpecified.
4525 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
4527 BOOL isCA
= defaultIfNotSpecified
;
4528 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
4529 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4533 CERT_BASIC_CONSTRAINTS_INFO
*info
;
4536 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
4537 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
4538 NULL
, &info
, &size
))
4540 if (info
->SubjectType
.cbData
== 1)
4541 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
4547 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
4548 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4551 CERT_BASIC_CONSTRAINTS2_INFO info
;
4552 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4554 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
4555 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
4556 0, NULL
, &info
, &size
))
4563 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
4567 if (is_ca_cert(cert
, TRUE
))
4570 storeName
= addressBook
;
4571 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4572 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
4575 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
4582 SetLastError(E_INVALIDARG
);
4585 if (hDestCertStore
) store
= hDestCertStore
;
4588 if (!(store
= choose_store_for_cert(cert
)))
4590 WARN("unable to open certificate store\n");
4594 ret
= CertAddCertificateContextToStore(store
, cert
,
4595 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4596 if (!hDestCertStore
) CertCloseStore(store
, 0);
4600 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
4607 SetLastError(E_INVALIDARG
);
4610 if (hDestCertStore
) store
= hDestCertStore
;
4613 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4614 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
4616 WARN("unable to open certificate store\n");
4620 ret
= CertAddCRLContextToStore(store
, crl
,
4621 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4622 if (!hDestCertStore
) CertCloseStore(store
, 0);
4626 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
4633 SetLastError(E_INVALIDARG
);
4636 if (hDestCertStore
) store
= hDestCertStore
;
4639 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
4641 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4642 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
4644 WARN("unable to open certificate store\n");
4648 ret
= CertAddCTLContextToStore(store
, ctl
,
4649 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4650 if (!hDestCertStore
) CertCloseStore(store
, 0);
4654 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
4655 * CryptQueryObject, against the allowed types. Returns TRUE if the
4656 * type is allowed, FALSE otherwise.
4658 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
4663 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4664 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4668 case CERT_QUERY_CONTENT_CERT
:
4669 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4670 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
4672 case CERT_QUERY_CONTENT_CRL
:
4673 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4674 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
4676 case CERT_QUERY_CONTENT_CTL
:
4677 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4678 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
4681 /* The remaining types contain more than one type, so allow
4689 /* No allowed types specified, so any type is allowed */
4693 SetLastError(E_INVALIDARG
);
4698 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4701 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4703 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4710 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
4711 sizeof(title
) / sizeof(title
[0]));
4714 LoadStringW(hInstance
, warningID
, error
,
4715 sizeof(error
) / sizeof(error
[0]));
4716 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
4720 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
4722 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
4725 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
4730 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4731 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4733 PCCERT_CONTEXT cert
;
4738 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
4740 CertFreeCertificateContext(cert
);
4741 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
4744 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
4746 CertFreeCRLContext(crl
);
4747 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
4750 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
4752 CertFreeCTLContext(ctl
);
4753 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4760 SetLastError(E_INVALIDARG
);
4764 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4765 HCERTSTORE source
, HCERTSTORE dest
)
4769 if ((ret
= check_store_context_type(dwFlags
, source
)))
4771 PCCERT_CONTEXT cert
= NULL
;
4772 PCCRL_CONTEXT crl
= NULL
;
4773 PCCTL_CONTEXT ctl
= NULL
;
4776 cert
= CertEnumCertificatesInStore(source
, cert
);
4778 ret
= import_cert(cert
, dest
);
4779 } while (ret
&& cert
);
4781 crl
= CertEnumCRLsInStore(source
, crl
);
4783 ret
= import_crl(crl
, dest
);
4784 } while (ret
&& crl
);
4786 ctl
= CertEnumCTLsInStore(source
, ctl
);
4788 ret
= import_ctl(ctl
, dest
);
4789 } while (ret
&& ctl
);
4792 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
4796 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
4797 DWORD
*pContentType
)
4799 HCERTSTORE store
= NULL
;
4800 DWORD contentType
= 0, expectedContentTypeFlags
;
4803 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4804 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4806 expectedContentTypeFlags
=
4807 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4808 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4809 CERT_QUERY_CONTENT_FLAG_PFX
;
4810 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
4811 expectedContentTypeFlags
|=
4812 CERT_QUERY_CONTENT_FLAG_CERT
|
4813 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
4814 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
4815 expectedContentTypeFlags
|=
4816 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4817 CERT_QUERY_CONTENT_FLAG_CRL
;
4818 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
4819 expectedContentTypeFlags
|=
4820 CERT_QUERY_CONTENT_FLAG_CTL
|
4821 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
4824 expectedContentTypeFlags
=
4825 CERT_QUERY_CONTENT_FLAG_CERT
|
4826 CERT_QUERY_CONTENT_FLAG_CTL
|
4827 CERT_QUERY_CONTENT_FLAG_CRL
|
4828 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4829 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
4830 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
4831 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4832 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4833 CERT_QUERY_CONTENT_FLAG_PFX
;
4835 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
4836 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
4837 &contentType
, NULL
, &store
, NULL
, NULL
);
4839 *pContentType
= contentType
;
4843 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4844 LPCWSTR fileName
, HCERTSTORE dest
)
4849 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
4851 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
4852 CertCloseStore(source
, 0);
4859 struct ImportWizData
4863 LPCWSTR pwszWizardTitle
;
4864 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
4868 HCERTSTORE hDestCertStore
;
4874 static LRESULT CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4883 struct ImportWizData
*data
;
4884 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4885 WCHAR fontFace
[MAX_STRING_LEN
];
4886 HDC hDC
= GetDC(hwnd
);
4889 data
= (struct ImportWizData
*)page
->lParam
;
4890 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
4891 sizeof(fontFace
) / sizeof(fontFace
[0]));
4892 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
4893 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
4894 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
4895 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
4896 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4897 (WPARAM
)data
->titleFont
, TRUE
);
4898 ReleaseDC(hwnd
, hDC
);
4903 NMHDR
*hdr
= (NMHDR
*)lp
;
4908 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
4918 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
4920 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
4922 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
4923 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
4924 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
4925 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
4927 static const WCHAR filter_all
[] = { '*','.','*',0 };
4929 static struct StringToFilter
4934 } import_filters
[] = {
4935 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
4936 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
4937 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
4938 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
4939 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
4940 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
4941 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
4944 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
4947 int len
, totalLen
= 2;
4948 LPWSTR filter
= NULL
, str
;
4950 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4952 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4953 (dwFlags
& import_filters
[i
].allowFlags
))
4955 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
4956 totalLen
+= len
+ strlenW(import_filters
[i
].filter
) + 2;
4959 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
4965 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4967 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4968 (dwFlags
& import_filters
[i
].allowFlags
))
4970 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
4972 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
4975 strcpyW(ptr
, import_filters
[i
].filter
);
4976 ptr
+= strlenW(import_filters
[i
].filter
) + 1;
4984 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
4990 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
4991 OPEN_EXISTING
, 0, NULL
);
4992 if (file
!= INVALID_HANDLE_VALUE
)
4994 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
4995 &data
->contentType
);
4999 warningID
= IDS_IMPORT_BAD_FORMAT
;
5000 else if (!check_store_context_type(data
->dwFlags
, source
))
5001 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
5004 data
->importSrc
.dwSubjectChoice
=
5005 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
5006 data
->importSrc
.u
.hCertStore
= source
;
5007 data
->freeSource
= TRUE
;
5012 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5019 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5021 LPWSTR msgBuf
, fullError
;
5023 if (data
->pwszWizardTitle
)
5024 pTitle
= data
->pwszWizardTitle
;
5027 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
5028 sizeof(title
) / sizeof(title
[0]));
5031 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
5032 sizeof(error
) / sizeof(error
[0]));
5034 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
5035 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
5036 fullError
= HeapAlloc(GetProcessHeap(), 0,
5037 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
5041 LPWSTR ptr
= fullError
;
5043 strcpyW(ptr
, error
);
5044 ptr
+= strlenW(error
);
5045 strcpyW(ptr
, fileName
);
5046 ptr
+= strlenW(fileName
);
5049 strcpyW(ptr
, msgBuf
);
5050 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
5051 HeapFree(GetProcessHeap(), 0, fullError
);
5058 static LRESULT CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5062 struct ImportWizData
*data
;
5068 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5070 data
= (struct ImportWizData
*)page
->lParam
;
5071 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5074 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5076 SendMessageW(fileNameEdit
, WM_SETTEXT
, 0, (LPARAM
)data
->fileName
);
5082 NMHDR
*hdr
= (NMHDR
*)lp
;
5087 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5088 PSWIZB_BACK
| PSWIZB_NEXT
);
5093 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5094 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
5096 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5099 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5100 IDS_IMPORT_EMPTY_FILE
);
5101 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5106 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
5107 (len
+ 1) * sizeof(WCHAR
));
5111 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
5113 if (!import_validate_filename(hwnd
, data
, fileName
))
5115 HeapFree(GetProcessHeap(), 0, fileName
);
5116 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5120 data
->fileName
= fileName
;
5131 case IDC_IMPORT_BROWSE_FILE
:
5134 WCHAR fileBuf
[MAX_PATH
];
5136 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5137 memset(&ofn
, 0, sizeof(ofn
));
5138 ofn
.lStructSize
= sizeof(ofn
);
5139 ofn
.hwndOwner
= hwnd
;
5140 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
5141 ofn
.lpstrFile
= fileBuf
;
5142 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
5144 if (GetOpenFileNameW(&ofn
))
5145 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
5146 0, (LPARAM
)ofn
.lpstrFile
);
5147 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
5156 static LRESULT CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5160 struct ImportWizData
*data
;
5166 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5168 data
= (struct ImportWizData
*)page
->lParam
;
5169 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5170 if (!data
->hDestCertStore
)
5172 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
,
5174 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5175 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5176 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
5180 WCHAR storeTitle
[MAX_STRING_LEN
];
5182 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), BM_CLICK
,
5184 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5185 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5186 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
),
5187 !(data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
));
5188 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5189 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5190 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5191 0, (LPARAM
)storeTitle
);
5197 NMHDR
*hdr
= (NMHDR
*)lp
;
5202 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5203 PSWIZB_BACK
| PSWIZB_NEXT
);
5208 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5209 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
5210 !data
->hDestCertStore
)
5212 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5213 IDS_IMPORT_SELECT_STORE
);
5214 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5225 case IDC_IMPORT_AUTO_STORE
:
5226 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5227 data
->autoDest
= TRUE
;
5228 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5229 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5231 case IDC_IMPORT_SPECIFY_STORE
:
5232 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5233 data
->autoDest
= FALSE
;
5234 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5235 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5237 case IDC_IMPORT_BROWSE_STORE
:
5239 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
5240 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
5241 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
5242 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
5245 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5246 selectInfo
.dwSize
= sizeof(selectInfo
);
5247 selectInfo
.parent
= hwnd
;
5248 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
5249 selectInfo
.pwszTitle
= NULL
;
5250 selectInfo
.pwszText
= NULL
;
5251 selectInfo
.pEnumData
= &enumData
;
5252 selectInfo
.pfnSelectedStoreCallback
= NULL
;
5253 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
5255 WCHAR storeTitle
[MAX_STRING_LEN
];
5257 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5258 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5259 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5260 0, (LPARAM
)storeTitle
);
5261 data
->hDestCertStore
= store
;
5262 data
->freeDest
= TRUE
;
5272 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
5274 WCHAR text
[MAX_STRING_LEN
];
5278 item
.mask
= LVIF_TEXT
;
5279 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5281 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
,
5282 sizeof(text
)/ sizeof(text
[0]));
5283 item
.pszText
= text
;
5284 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5287 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
,
5288 sizeof(text
)/ sizeof(text
[0]));
5290 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
,
5291 sizeof(text
)/ sizeof(text
[0]));
5292 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5293 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5295 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
,
5296 sizeof(text
)/ sizeof(text
[0]));
5297 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5298 switch (data
->contentType
)
5300 case CERT_QUERY_CONTENT_CERT
:
5301 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
5302 contentID
= IDS_IMPORT_CONTENT_CERT
;
5304 case CERT_QUERY_CONTENT_CRL
:
5305 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
5306 contentID
= IDS_IMPORT_CONTENT_CRL
;
5308 case CERT_QUERY_CONTENT_CTL
:
5309 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
5310 contentID
= IDS_IMPORT_CONTENT_CTL
;
5312 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
5313 contentID
= IDS_IMPORT_CONTENT_CMS
;
5315 case CERT_QUERY_CONTENT_FLAG_PFX
:
5316 contentID
= IDS_IMPORT_CONTENT_PFX
;
5319 contentID
= IDS_IMPORT_CONTENT_STORE
;
5322 LoadStringW(hInstance
, contentID
, text
, sizeof(text
)/ sizeof(text
[0]));
5324 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5327 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5329 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
5330 sizeof(text
)/ sizeof(text
[0]));
5331 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5333 item
.pszText
= data
->fileName
;
5334 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5338 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5339 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5343 switch (pImportSrc
->dwSubjectChoice
)
5345 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
5346 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
5347 pImportSrc
->u
.pwszFileName
, hDestCertStore
);
5349 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5350 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
5351 ret
= import_cert(pImportSrc
->u
.pCertContext
, hDestCertStore
);
5353 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5355 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5356 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
5357 ret
= import_crl(pImportSrc
->u
.pCRLContext
, hDestCertStore
);
5359 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5361 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5362 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
5363 ret
= import_ctl(pImportSrc
->u
.pCTLContext
, hDestCertStore
);
5365 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5367 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5368 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
5369 pImportSrc
->u
.hCertStore
, hDestCertStore
);
5372 WARN("unknown source type: %u\n", pImportSrc
->dwSubjectChoice
);
5373 SetLastError(E_INVALIDARG
);
5379 static LRESULT CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5383 struct ImportWizData
*data
;
5389 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5390 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5394 data
= (struct ImportWizData
*)page
->lParam
;
5395 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5396 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
5397 (WPARAM
)data
->titleFont
, TRUE
);
5398 GetWindowRect(lv
, &rc
);
5399 column
.mask
= LVCF_WIDTH
;
5400 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
5401 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
5402 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
5403 show_import_details(lv
, data
);
5408 NMHDR
*hdr
= (NMHDR
*)lp
;
5414 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5416 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5417 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
5418 show_import_details(lv
, data
);
5419 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5420 PSWIZB_BACK
| PSWIZB_FINISH
);
5426 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5427 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
5428 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
5430 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
5433 if (data
->pwszWizardTitle
)
5434 pTitle
= data
->pwszWizardTitle
;
5437 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
5438 sizeof(title
) / sizeof(title
[0]));
5441 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
,
5442 sizeof(message
) / sizeof(message
[0]));
5443 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
5446 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5457 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
5458 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
5459 HCERTSTORE hDestCertStore
)
5461 PROPSHEETHEADERW hdr
;
5462 PROPSHEETPAGEW pages
[4];
5463 struct ImportWizData data
;
5466 data
.dwFlags
= dwFlags
;
5467 data
.pwszWizardTitle
= pwszWizardTitle
;
5470 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
5471 data
.fileName
= (LPWSTR
)pImportSrc
->u
.pwszFileName
;
5475 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
5476 data
.fileName
= NULL
;
5478 data
.freeSource
= FALSE
;
5479 data
.hDestCertStore
= hDestCertStore
;
5480 data
.freeDest
= FALSE
;
5481 data
.autoDest
= TRUE
;
5482 data
.success
= TRUE
;
5484 memset(pages
, 0, sizeof(pages
));
5486 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5487 pages
[nPages
].hInstance
= hInstance
;
5488 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
5489 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
5490 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5491 pages
[nPages
].lParam
= (LPARAM
)&data
;
5495 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
5497 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5498 pages
[nPages
].hInstance
= hInstance
;
5499 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
5500 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
5501 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5502 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
5503 pages
[nPages
].pszHeaderSubTitle
=
5504 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
5505 pages
[nPages
].lParam
= (LPARAM
)&data
;
5510 switch (pImportSrc
->dwSubjectChoice
)
5512 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5513 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
5515 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5516 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
5518 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5519 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
5521 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5522 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
5527 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5528 pages
[nPages
].hInstance
= hInstance
;
5529 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
5530 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
5531 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5532 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
5533 pages
[nPages
].pszHeaderSubTitle
=
5534 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
5535 pages
[nPages
].lParam
= (LPARAM
)&data
;
5538 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5539 pages
[nPages
].hInstance
= hInstance
;
5540 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
5541 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
5542 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5543 pages
[nPages
].lParam
= (LPARAM
)&data
;
5546 memset(&hdr
, 0, sizeof(hdr
));
5547 hdr
.dwSize
= sizeof(hdr
);
5548 hdr
.hwndParent
= hwndParent
;
5549 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
5551 hdr
.hInstance
= hInstance
;
5552 if (pwszWizardTitle
)
5553 hdr
.pszCaption
= pwszWizardTitle
;
5555 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
5556 hdr
.u3
.ppsp
= pages
;
5557 hdr
.nPages
= nPages
;
5558 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
5559 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
5560 PropertySheetW(&hdr
);
5561 if (data
.fileName
!= data
.importSrc
.u
.pwszFileName
)
5562 HeapFree(GetProcessHeap(), 0, data
.fileName
);
5563 if (data
.freeSource
&&
5564 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
5565 CertCloseStore(data
.importSrc
.u
.hCertStore
, 0);
5566 DeleteObject(data
.titleFont
);
5567 return data
.success
;
5570 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5571 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5575 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
5576 pImportSrc
, hDestCertStore
);
5579 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
5581 SetLastError(E_INVALIDARG
);
5585 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
5586 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5588 else if (pImportSrc
)
5589 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5593 /* Can't have no UI without specifying source */
5594 SetLastError(E_INVALIDARG
);
5601 struct ExportWizData
5605 LPCWSTR pwszWizardTitle
;
5606 CRYPTUI_WIZ_EXPORT_INFO exportInfo
;
5607 CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo
;
5609 PCRYPT_KEY_PROV_INFO keyProvInfo
;
5616 static LRESULT CALLBACK
export_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5625 struct ExportWizData
*data
;
5626 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5627 WCHAR fontFace
[MAX_STRING_LEN
];
5628 HDC hDC
= GetDC(hwnd
);
5631 data
= (struct ExportWizData
*)page
->lParam
;
5632 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
5633 sizeof(fontFace
) / sizeof(fontFace
[0]));
5634 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
5635 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
5636 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
5637 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
5638 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
5639 (WPARAM
)data
->titleFont
, TRUE
);
5640 ReleaseDC(hwnd
, hDC
);
5645 NMHDR
*hdr
= (NMHDR
*)lp
;
5650 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
5660 static PCRYPT_KEY_PROV_INFO
export_get_private_key_info(PCCERT_CONTEXT cert
)
5662 PCRYPT_KEY_PROV_INFO info
= NULL
;
5665 if (CertGetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
,
5668 info
= HeapAlloc(GetProcessHeap(), 0, size
);
5671 if (!CertGetCertificateContextProperty(cert
,
5672 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
))
5674 HeapFree(GetProcessHeap(), 0, info
);
5682 static BOOL
export_acquire_private_key(const CRYPT_KEY_PROV_INFO
*info
,
5687 ret
= CryptAcquireContextW(phProv
, info
->pwszContainerName
,
5688 info
->pwszProvName
, info
->dwProvType
, 0);
5693 for (i
= 0; i
< info
->cProvParam
; i
++)
5694 CryptSetProvParam(*phProv
, info
->rgProvParam
[i
].dwParam
,
5695 info
->rgProvParam
[i
].pbData
, info
->rgProvParam
[i
].dwFlags
);
5700 static BOOL
export_is_key_exportable(HCRYPTPROV hProv
, DWORD keySpec
)
5705 if ((ret
= CryptGetUserKey(hProv
, keySpec
, &key
)))
5707 DWORD permissions
, size
= sizeof(permissions
);
5709 if ((ret
= CryptGetKeyParam(key
, KP_PERMISSIONS
, (BYTE
*)&permissions
,
5710 &size
, 0)) && !(permissions
& CRYPT_EXPORT
))
5712 CryptDestroyKey(key
);
5717 static LRESULT CALLBACK
export_private_key_dlg_proc(HWND hwnd
, UINT msg
,
5718 WPARAM wp
, LPARAM lp
)
5721 struct ExportWizData
*data
;
5727 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5728 PCRYPT_KEY_PROV_INFO info
;
5729 HCRYPTPROV hProv
= 0;
5732 data
= (struct ExportWizData
*)page
->lParam
;
5733 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5734 /* Get enough information about a key to see whether it's exportable.
5736 if (!(info
= export_get_private_key_info(
5737 data
->exportInfo
.u
.pCertContext
)))
5738 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5739 else if (!export_acquire_private_key(info
, &hProv
))
5740 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5741 else if (!export_is_key_exportable(hProv
, info
->dwKeySpec
))
5742 errorID
= IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE
;
5746 WCHAR error
[MAX_STRING_LEN
];
5748 LoadStringW(hInstance
, errorID
, error
,
5749 sizeof(error
) / sizeof(error
[0]));
5750 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE
),
5751 WM_SETTEXT
, 0, (LPARAM
)error
);
5752 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_YES
), FALSE
);
5755 data
->keyProvInfo
= info
;
5757 CryptReleaseContext(hProv
, 0);
5758 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
), BM_CLICK
,
5764 NMHDR
*hdr
= (NMHDR
*)lp
;
5769 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5770 PSWIZB_BACK
| PSWIZB_NEXT
);
5774 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5775 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
))
5777 data
->contextInfo
.dwExportFormat
=
5778 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5779 data
->contextInfo
.fExportPrivateKeys
= FALSE
;
5783 data
->contextInfo
.dwExportFormat
=
5784 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5785 data
->contextInfo
.fExportPrivateKeys
= TRUE
;
5795 static BOOL
export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
)
5799 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
)
5803 /* If there's a CRYPT_KEY_PROV_INFO set for this cert, assume the
5804 * cert has a private key.
5806 if (CertGetCertificateContextProperty(pExportInfo
->u
.pCertContext
,
5807 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
))
5813 static void export_format_enable_controls(HWND hwnd
, const struct ExportWizData
*data
)
5815 int defaultFormatID
;
5817 switch (data
->contextInfo
.dwExportFormat
)
5819 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
5820 defaultFormatID
= IDC_EXPORT_FORMAT_BASE64
;
5822 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
5823 defaultFormatID
= IDC_EXPORT_FORMAT_CMS
;
5825 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
5826 defaultFormatID
= IDC_EXPORT_FORMAT_PFX
;
5829 defaultFormatID
= IDC_EXPORT_FORMAT_DER
;
5831 SendMessageW(GetDlgItem(hwnd
, defaultFormatID
), BM_CLICK
, 0, 0);
5832 if (defaultFormatID
== IDC_EXPORT_FORMAT_PFX
)
5834 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), FALSE
);
5835 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), FALSE
);
5836 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), FALSE
);
5837 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), TRUE
);
5841 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), TRUE
);
5842 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), TRUE
);
5843 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), TRUE
);
5844 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), FALSE
);
5848 static LRESULT CALLBACK
export_format_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5852 struct ExportWizData
*data
;
5858 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5860 data
= (struct ExportWizData
*)page
->lParam
;
5861 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5862 export_format_enable_controls(hwnd
, data
);
5867 NMHDR
*hdr
= (NMHDR
*)lp
;
5872 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5873 PSWIZB_BACK
| PSWIZB_NEXT
);
5874 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5875 export_format_enable_controls(hwnd
, data
);
5880 BOOL skipPasswordPage
= TRUE
;
5882 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5883 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_DER
))
5884 data
->contextInfo
.dwExportFormat
=
5885 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5886 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_BASE64
))
5887 data
->contextInfo
.dwExportFormat
=
5888 CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
;
5889 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_CMS
))
5891 data
->contextInfo
.dwExportFormat
=
5892 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5893 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
))
5894 data
->contextInfo
.fExportChain
=
5895 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5899 data
->contextInfo
.dwExportFormat
=
5900 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5901 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
))
5902 data
->contextInfo
.fExportChain
= TRUE
;
5903 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
))
5904 data
->contextInfo
.fStrongEncryption
= TRUE
;
5905 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
))
5906 data
->deleteKeys
= TRUE
;
5907 skipPasswordPage
= FALSE
;
5909 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
,
5910 skipPasswordPage
? IDD_EXPORT_FILE
: 0);
5923 case IDC_EXPORT_FORMAT_DER
:
5924 case IDC_EXPORT_FORMAT_BASE64
:
5925 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
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
), FALSE
);
5934 case IDC_EXPORT_FORMAT_CMS
:
5935 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5938 case IDC_EXPORT_FORMAT_PFX
:
5939 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5941 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5943 EnableWindow(GetDlgItem(hwnd
,
5944 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), TRUE
);
5954 static void export_password_mismatch(HWND hwnd
, const struct ExportWizData
*data
)
5956 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5959 if (data
->pwszWizardTitle
)
5960 pTitle
= data
->pwszWizardTitle
;
5963 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
5964 sizeof(title
) / sizeof(title
[0]));
5967 LoadStringW(hInstance
, IDS_EXPORT_PASSWORD_MISMATCH
, error
,
5968 sizeof(error
) / sizeof(error
[0]));
5969 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
5970 SetFocus(GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
));
5973 static LRESULT CALLBACK
export_password_dlg_proc(HWND hwnd
, UINT msg
,
5974 WPARAM wp
, LPARAM lp
)
5977 struct ExportWizData
*data
;
5983 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5985 data
= (struct ExportWizData
*)page
->lParam
;
5986 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5991 NMHDR
*hdr
= (NMHDR
*)lp
;
5996 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5997 PSWIZB_BACK
| PSWIZB_NEXT
);
6002 HWND passwordEdit
= GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
);
6003 HWND passwordConfirmEdit
= GetDlgItem(hwnd
,
6004 IDC_EXPORT_PASSWORD_CONFIRM
);
6005 DWORD passwordLen
= SendMessageW(passwordEdit
, WM_GETTEXTLENGTH
,
6007 DWORD passwordConfirmLen
= SendMessageW(passwordConfirmEdit
,
6008 WM_GETTEXTLENGTH
, 0, 0);
6010 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6011 if (!passwordLen
&& !passwordConfirmLen
)
6012 data
->contextInfo
.pwszPassword
= NULL
;
6013 else if (passwordLen
!= passwordConfirmLen
)
6015 export_password_mismatch(hwnd
, data
);
6016 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6021 LPWSTR password
= HeapAlloc(GetProcessHeap(), 0,
6022 (passwordLen
+ 1) * sizeof(WCHAR
));
6023 LPWSTR passwordConfirm
= HeapAlloc(GetProcessHeap(), 0,
6024 (passwordConfirmLen
+ 1) * sizeof(WCHAR
));
6025 BOOL freePassword
= TRUE
;
6027 if (password
&& passwordConfirm
)
6029 SendMessageW(passwordEdit
, WM_GETTEXT
, passwordLen
+ 1,
6031 SendMessageW(passwordConfirmEdit
, WM_GETTEXT
,
6032 passwordConfirmLen
+ 1, (LPARAM
)passwordConfirm
);
6033 if (strcmpW(password
, passwordConfirm
))
6035 export_password_mismatch(hwnd
, data
);
6036 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6041 data
->contextInfo
.pwszPassword
= password
;
6042 freePassword
= FALSE
;
6043 data
->freePassword
= TRUE
;
6047 HeapFree(GetProcessHeap(), 0, password
);
6048 HeapFree(GetProcessHeap(), 0, passwordConfirm
);
6059 static LPWSTR
export_append_extension(const struct ExportWizData
*data
,
6062 static const WCHAR cer
[] = { '.','c','e','r',0 };
6063 static const WCHAR crl
[] = { '.','c','r','l',0 };
6064 static const WCHAR ctl
[] = { '.','c','t','l',0 };
6065 static const WCHAR p7b
[] = { '.','p','7','b',0 };
6066 static const WCHAR pfx
[] = { '.','p','f','x',0 };
6067 static const WCHAR sst
[] = { '.','s','s','t',0 };
6070 BOOL appendExtension
;
6072 switch (data
->contextInfo
.dwExportFormat
)
6074 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6077 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6081 switch (data
->exportInfo
.dwSubjectChoice
)
6083 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6086 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6089 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6096 dot
= strrchrW(fileName
, '.');
6098 appendExtension
= strcmpiW(dot
, extension
) != 0;
6100 appendExtension
= TRUE
;
6101 if (appendExtension
)
6103 fileName
= HeapReAlloc(GetProcessHeap(), 0, fileName
,
6104 (strlenW(fileName
) + strlenW(extension
) + 1) * sizeof(WCHAR
));
6106 strcatW(fileName
, extension
);
6111 static BOOL
export_validate_filename(HWND hwnd
, struct ExportWizData
*data
,
6115 BOOL tryCreate
= TRUE
, forceCreate
= FALSE
, ret
= FALSE
;
6117 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6118 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, NULL
);
6119 if (file
!= INVALID_HANDLE_VALUE
)
6121 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
6124 if (data
->pwszWizardTitle
)
6125 pTitle
= data
->pwszWizardTitle
;
6128 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6129 sizeof(title
) / sizeof(title
[0]));
6132 LoadStringW(hInstance
, IDS_EXPORT_FILE_EXISTS
, warning
,
6133 sizeof(warning
) / sizeof(warning
[0]));
6134 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
6142 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6143 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6144 forceCreate
? CREATE_ALWAYS
: CREATE_NEW
,
6146 if (file
!= INVALID_HANDLE_VALUE
)
6153 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6155 LPWSTR msgBuf
, fullError
;
6157 if (data
->pwszWizardTitle
)
6158 pTitle
= data
->pwszWizardTitle
;
6161 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6162 sizeof(title
) / sizeof(title
[0]));
6165 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
6166 sizeof(error
) / sizeof(error
[0]));
6168 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
6169 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
6170 fullError
= HeapAlloc(GetProcessHeap(), 0,
6171 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
6175 LPWSTR ptr
= fullError
;
6177 strcpyW(ptr
, error
);
6178 ptr
+= strlenW(error
);
6179 strcpyW(ptr
, fileName
);
6180 ptr
+= strlenW(fileName
);
6183 strcpyW(ptr
, msgBuf
);
6184 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
6185 HeapFree(GetProcessHeap(), 0, fullError
);
6193 static const WCHAR export_filter_cert
[] = { '*','.','c','e','r',0 };
6194 static const WCHAR export_filter_crl
[] = { '*','.','c','r','l',0 };
6195 static const WCHAR export_filter_ctl
[] = { '*','.','s','t','l',0 };
6196 static const WCHAR export_filter_cms
[] = { '*','.','p','7','b',0 };
6197 static const WCHAR export_filter_pfx
[] = { '*','.','p','f','x',0 };
6198 static const WCHAR export_filter_sst
[] = { '*','.','s','s','t',0 };
6200 static WCHAR
*make_export_file_filter(DWORD exportFormat
, DWORD subjectChoice
)
6202 int baseLen
, allLen
, totalLen
= 2, baseID
;
6203 LPWSTR filter
= NULL
, baseFilter
, all
;
6206 switch (exportFormat
)
6208 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6209 baseID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6210 filterStr
= export_filter_cert
;
6212 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6213 baseID
= IDS_EXPORT_FILTER_PFX
;
6214 filterStr
= export_filter_pfx
;
6216 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6217 baseID
= IDS_EXPORT_FILTER_CMS
;
6218 filterStr
= export_filter_cms
;
6221 switch (subjectChoice
)
6223 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6224 baseID
= IDS_EXPORT_FILTER_CRL
;
6225 filterStr
= export_filter_crl
;
6227 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6228 baseID
= IDS_EXPORT_FILTER_CTL
;
6229 filterStr
= export_filter_ctl
;
6231 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6232 baseID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6233 filterStr
= export_filter_sst
;
6236 baseID
= IDS_EXPORT_FILTER_CERT
;
6237 filterStr
= export_filter_cert
;
6241 baseLen
= LoadStringW(hInstance
, baseID
, (LPWSTR
)&baseFilter
, 0);
6242 totalLen
+= baseLen
+ strlenW(filterStr
) + 2;
6243 allLen
= LoadStringW(hInstance
, IDS_IMPORT_FILTER_ALL
, (LPWSTR
)&all
, 0);
6244 totalLen
+= allLen
+ strlenW(filter_all
) + 2;
6245 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
6251 memcpy(ptr
, baseFilter
, baseLen
* sizeof(WCHAR
));
6254 strcpyW(ptr
, filterStr
);
6255 ptr
+= strlenW(filterStr
) + 1;
6256 memcpy(ptr
, all
, allLen
* sizeof(WCHAR
));
6259 strcpyW(ptr
, filter_all
);
6260 ptr
+= strlenW(filter_all
) + 1;
6266 static LRESULT CALLBACK
export_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6270 struct ExportWizData
*data
;
6276 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6278 data
= (struct ExportWizData
*)page
->lParam
;
6279 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6280 if (data
->exportInfo
.pwszExportFileName
)
6281 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
, 0,
6282 (LPARAM
)data
->exportInfo
.pwszExportFileName
);
6287 NMHDR
*hdr
= (NMHDR
*)lp
;
6292 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6293 if (data
->contextInfo
.dwExportFormat
!=
6294 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
)
6296 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, IDD_EXPORT_FORMAT
);
6302 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
);
6303 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
6305 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6308 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6311 if (data
->pwszWizardTitle
)
6312 pTitle
= data
->pwszWizardTitle
;
6315 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6316 sizeof(title
) / sizeof(title
[0]));
6319 LoadStringW(hInstance
, IDS_IMPORT_EMPTY_FILE
, error
,
6320 sizeof(error
) / sizeof(error
[0]));
6321 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
6322 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6327 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
6328 (len
+ 1) * sizeof(WCHAR
));
6332 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
6334 fileName
= export_append_extension(data
, fileName
);
6335 if (!export_validate_filename(hwnd
, data
, fileName
))
6337 HeapFree(GetProcessHeap(), 0, fileName
);
6338 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6342 data
->fileName
= fileName
;
6348 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6349 PSWIZB_BACK
| PSWIZB_NEXT
);
6358 case IDC_EXPORT_BROWSE_FILE
:
6361 WCHAR fileBuf
[MAX_PATH
];
6363 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6364 memset(&ofn
, 0, sizeof(ofn
));
6365 ofn
.lStructSize
= sizeof(ofn
);
6366 ofn
.hwndOwner
= hwnd
;
6367 ofn
.lpstrFilter
= make_export_file_filter(
6368 data
->contextInfo
.dwExportFormat
,
6369 data
->exportInfo
.dwSubjectChoice
);
6370 ofn
.lpstrFile
= fileBuf
;
6371 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
6373 if (GetSaveFileNameW(&ofn
))
6374 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
,
6375 0, (LPARAM
)ofn
.lpstrFile
);
6376 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
6385 static void show_export_details(HWND lv
, const struct ExportWizData
*data
)
6387 WCHAR text
[MAX_STRING_LEN
];
6391 item
.mask
= LVIF_TEXT
;
6394 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6396 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
6397 sizeof(text
)/ sizeof(text
[0]));
6398 item
.pszText
= text
;
6399 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6401 item
.pszText
= data
->fileName
;
6402 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6405 item
.pszText
= text
;
6406 switch (data
->exportInfo
.dwSubjectChoice
)
6408 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6409 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6410 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6411 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6416 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6418 LoadStringW(hInstance
, IDS_EXPORT_INCLUDE_CHAIN
, text
,
6419 sizeof(text
) / sizeof(text
[0]));
6420 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6422 LoadStringW(hInstance
,
6423 data
->contextInfo
.fExportChain
? IDS_YES
: IDS_NO
, text
,
6424 sizeof(text
) / sizeof(text
[0]));
6425 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6427 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6429 LoadStringW(hInstance
, IDS_EXPORT_KEYS
, text
,
6430 sizeof(text
) / sizeof(text
[0]));
6431 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6433 LoadStringW(hInstance
,
6434 data
->contextInfo
.fExportPrivateKeys
? IDS_YES
: IDS_NO
, text
,
6435 sizeof(text
) / sizeof(text
[0]));
6436 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6440 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6442 LoadStringW(hInstance
, IDS_EXPORT_FORMAT
, text
,
6443 sizeof(text
)/ sizeof(text
[0]));
6444 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6447 switch (data
->exportInfo
.dwSubjectChoice
)
6449 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6450 contentID
= IDS_EXPORT_FILTER_CRL
;
6452 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6453 contentID
= IDS_EXPORT_FILTER_CTL
;
6455 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6456 contentID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6459 switch (data
->contextInfo
.dwExportFormat
)
6461 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6462 contentID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6464 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6465 contentID
= IDS_EXPORT_FILTER_CMS
;
6467 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6468 contentID
= IDS_EXPORT_FILTER_PFX
;
6471 contentID
= IDS_EXPORT_FILTER_CERT
;
6474 LoadStringW(hInstance
, contentID
, text
, sizeof(text
) / sizeof(text
[0]));
6475 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6478 static inline BOOL
save_der(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6482 return WriteFile(file
, pb
, cb
, &bytesWritten
, NULL
);
6485 static BOOL
save_base64(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6490 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, NULL
, &size
)))
6492 LPSTR buf
= HeapAlloc(GetProcessHeap(), 0, size
);
6496 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, buf
,
6498 ret
= WriteFile(file
, buf
, size
, &size
, NULL
);
6499 HeapFree(GetProcessHeap(), 0, buf
);
6503 SetLastError(ERROR_OUTOFMEMORY
);
6510 static inline BOOL
save_store_as_cms(HANDLE file
, HCERTSTORE store
)
6512 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6513 CERT_STORE_SAVE_AS_PKCS7
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6516 static BOOL
save_cert_as_cms(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6520 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
6521 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6527 HCERTSTORE addlStore
= CertOpenStore(CERT_STORE_PROV_COLLECTION
,
6528 0, 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6535 for (i
= 0; ret
&& i
< pExportInfo
->cStores
; i
++)
6536 ret
= CertAddStoreToCollection(addlStore
,
6537 pExportInfo
->rghStores
, 0, 0);
6540 PCCERT_CHAIN_CONTEXT chain
;
6542 ret
= CertGetCertificateChain(NULL
,
6543 pExportInfo
->u
.pCertContext
, NULL
, addlStore
, NULL
, 0,
6549 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6550 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6552 ret
= CertAddCertificateContextToStore(store
,
6553 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6554 CERT_STORE_ADD_ALWAYS
, NULL
);
6555 CertFreeCertificateChain(chain
);
6559 /* No chain could be created, just add the individual
6560 * cert to the message.
6562 ret
= CertAddCertificateContextToStore(store
,
6563 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
,
6567 CertCloseStore(addlStore
, 0);
6573 ret
= CertAddCertificateContextToStore(store
,
6574 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, NULL
);
6576 ret
= save_store_as_cms(file
, store
);
6577 CertCloseStore(store
, 0);
6584 static BOOL
save_serialized_store(HANDLE file
, HCERTSTORE store
)
6586 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6587 CERT_STORE_SAVE_AS_STORE
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6590 static BOOL
save_pfx(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6591 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6592 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6594 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, X509_ASN_ENCODING
,
6595 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6600 CRYPT_DATA_BLOB pfxBlob
= { 0, NULL
};
6601 PCCERT_CONTEXT cert
= NULL
;
6602 BOOL freeKeyProvInfo
= FALSE
;
6604 if (pContextInfo
->fExportChain
)
6606 HCERTCHAINENGINE engine
= NULL
;
6608 if (pExportInfo
->cStores
)
6610 CERT_CHAIN_ENGINE_CONFIG config
;
6612 memset(&config
, 0, sizeof(config
));
6613 config
.cbSize
= sizeof(config
);
6614 config
.cAdditionalStore
= pExportInfo
->cStores
;
6615 config
.rghAdditionalStore
= pExportInfo
->rghStores
;
6616 ret
= CertCreateCertificateChainEngine(&config
, &engine
);
6622 CERT_CHAIN_PARA chainPara
;
6623 PCCERT_CHAIN_CONTEXT chain
;
6625 memset(&chainPara
, 0, sizeof(chainPara
));
6626 chainPara
.cbSize
= sizeof(chainPara
);
6627 ret
= CertGetCertificateChain(engine
,
6628 pExportInfo
->u
.pCertContext
, NULL
, NULL
, &chainPara
, 0, NULL
,
6634 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6635 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6638 if (i
== 0 && j
== 0)
6639 ret
= CertAddCertificateContextToStore(store
,
6640 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6641 CERT_STORE_ADD_ALWAYS
, &cert
);
6643 ret
= CertAddCertificateContextToStore(store
,
6644 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6645 CERT_STORE_ADD_ALWAYS
, NULL
);
6647 CertFreeCertificateChain(chain
);
6651 CertFreeCertificateChainEngine(engine
);
6654 ret
= CertAddCertificateContextToStore(store
,
6655 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, &cert
);
6656 /* Copy private key info to newly created cert, so it'll get exported
6657 * along with the cert.
6659 if (ret
&& pContextInfo
->fExportPrivateKeys
)
6662 ret
= CertSetCertificateContextProperty(cert
,
6663 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6666 if (!(keyProvInfo
= export_get_private_key_info(cert
)))
6670 ret
= CertSetCertificateContextProperty(cert
,
6671 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6672 freeKeyProvInfo
= TRUE
;
6679 REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
| EXPORT_PRIVATE_KEYS
;
6681 ret
= PFXExportCertStore(store
, &pfxBlob
,
6682 pContextInfo
->pwszPassword
, exportFlags
);
6685 pfxBlob
.pbData
= HeapAlloc(GetProcessHeap(), 0, pfxBlob
.cbData
);
6688 ret
= PFXExportCertStore(store
, &pfxBlob
,
6689 pContextInfo
->pwszPassword
, exportFlags
);
6694 ret
= WriteFile(file
, pfxBlob
.pbData
, pfxBlob
.cbData
,
6695 &bytesWritten
, NULL
);
6700 SetLastError(ERROR_OUTOFMEMORY
);
6705 if (ret
&& deleteKeys
)
6709 CryptAcquireContextW(&prov
, keyProvInfo
->pwszContainerName
,
6710 keyProvInfo
->pwszProvName
, keyProvInfo
->dwProvType
,
6711 CRYPT_DELETEKEYSET
);
6713 if (freeKeyProvInfo
)
6714 HeapFree(GetProcessHeap(), 0, keyProvInfo
);
6715 CertFreeCertificateContext(cert
);
6716 CertCloseStore(store
, 0);
6721 static BOOL
do_export(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6722 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6723 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6727 if (pContextInfo
->dwSize
!= sizeof(CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
))
6729 SetLastError(E_INVALIDARG
);
6732 switch (pExportInfo
->dwSubjectChoice
)
6734 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6735 ret
= save_der(file
,
6736 pExportInfo
->u
.pCRLContext
->pbCrlEncoded
,
6737 pExportInfo
->u
.pCRLContext
->cbCrlEncoded
);
6739 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6740 ret
= save_der(file
,
6741 pExportInfo
->u
.pCTLContext
->pbCtlEncoded
,
6742 pExportInfo
->u
.pCTLContext
->cbCtlEncoded
);
6744 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6745 ret
= save_serialized_store(file
, pExportInfo
->u
.hCertStore
);
6747 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6748 ret
= save_store_as_cms(file
, pExportInfo
->u
.hCertStore
);
6751 switch (pContextInfo
->dwExportFormat
)
6753 case CRYPTUI_WIZ_EXPORT_FORMAT_DER
:
6754 ret
= save_der(file
, pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6755 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6757 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6758 ret
= save_base64(file
,
6759 pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6760 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6762 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6763 ret
= save_cert_as_cms(file
, pExportInfo
,
6764 pContextInfo
->fExportChain
);
6766 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6767 ret
= save_pfx(file
, pExportInfo
, pContextInfo
, keyProvInfo
,
6771 SetLastError(E_FAIL
);
6778 static LRESULT CALLBACK
export_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6782 struct ExportWizData
*data
;
6788 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6789 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6793 data
= (struct ExportWizData
*)page
->lParam
;
6794 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6795 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
6796 (WPARAM
)data
->titleFont
, TRUE
);
6797 GetWindowRect(lv
, &rc
);
6798 column
.mask
= LVCF_WIDTH
;
6799 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
6800 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
6801 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
6802 show_export_details(lv
, data
);
6807 NMHDR
*hdr
= (NMHDR
*)lp
;
6813 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6815 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6816 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
6817 show_export_details(lv
, data
);
6818 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6819 PSWIZB_BACK
| PSWIZB_FINISH
);
6826 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
6830 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6831 if ((data
->success
= do_export(data
->file
, &data
->exportInfo
,
6832 &data
->contextInfo
, data
->keyProvInfo
, data
->deleteKeys
)))
6834 messageID
= IDS_EXPORT_SUCCEEDED
;
6839 messageID
= IDS_EXPORT_FAILED
;
6840 mbFlags
= MB_OK
| MB_ICONERROR
;
6842 if (data
->pwszWizardTitle
)
6843 pTitle
= data
->pwszWizardTitle
;
6846 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6847 sizeof(title
) / sizeof(title
[0]));
6850 LoadStringW(hInstance
, messageID
, message
,
6851 sizeof(message
) / sizeof(message
[0]));
6852 MessageBoxW(hwnd
, message
, pTitle
, mbFlags
);
6862 static BOOL
show_export_ui(DWORD dwFlags
, HWND hwndParent
,
6863 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, const void *pvoid
)
6865 PROPSHEETHEADERW hdr
;
6866 PROPSHEETPAGEW pages
[6];
6867 struct ExportWizData data
;
6869 BOOL hasPrivateKey
, showFormatPage
= TRUE
;
6872 data
.dwFlags
= dwFlags
;
6873 data
.pwszWizardTitle
= pwszWizardTitle
;
6874 memset(&data
.exportInfo
, 0, sizeof(data
.exportInfo
));
6875 memcpy(&data
.exportInfo
, pExportInfo
,
6876 min(sizeof(data
.exportInfo
), pExportInfo
->dwSize
));
6877 if (pExportInfo
->dwSize
> sizeof(data
.exportInfo
))
6878 data
.exportInfo
.dwSize
= sizeof(data
.exportInfo
);
6879 data
.contextInfo
.dwSize
= sizeof(data
.contextInfo
);
6880 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6881 data
.contextInfo
.fExportChain
= FALSE
;
6882 data
.contextInfo
.fStrongEncryption
= FALSE
;
6883 data
.contextInfo
.fExportPrivateKeys
= FALSE
;
6884 data
.contextInfo
.pwszPassword
= NULL
;
6885 data
.freePassword
= FALSE
;
6886 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
&&
6888 memcpy(&data
.contextInfo
, pvoid
,
6889 min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
)pvoid
)->dwSize
,
6890 sizeof(data
.contextInfo
)));
6891 data
.keyProvInfo
= NULL
;
6892 data
.deleteKeys
= FALSE
;
6893 data
.fileName
= NULL
;
6894 data
.file
= INVALID_HANDLE_VALUE
;
6895 data
.success
= FALSE
;
6897 memset(pages
, 0, sizeof(pages
));
6899 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6900 pages
[nPages
].hInstance
= hInstance
;
6901 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_WELCOME
);
6902 pages
[nPages
].pfnDlgProc
= export_welcome_dlg_proc
;
6903 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6904 pages
[nPages
].lParam
= (LPARAM
)&data
;
6907 hasPrivateKey
= export_info_has_private_key(pExportInfo
);
6908 switch (pExportInfo
->dwSubjectChoice
)
6910 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6911 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6912 showFormatPage
= FALSE
;
6913 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6915 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6916 showFormatPage
= FALSE
;
6917 data
.contextInfo
.dwExportFormat
=
6918 CRYPTUI_WIZ_EXPORT_FORMAT_SERIALIZED_CERT_STORE
;
6920 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6921 showFormatPage
= FALSE
;
6922 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
6926 if (hasPrivateKey
&& showFormatPage
)
6928 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6929 pages
[nPages
].hInstance
= hInstance
;
6930 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY
);
6931 pages
[nPages
].pfnDlgProc
= export_private_key_dlg_proc
;
6932 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6933 pages
[nPages
].pszHeaderTitle
=
6934 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE
);
6935 pages
[nPages
].pszHeaderSubTitle
=
6936 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE
);
6937 pages
[nPages
].lParam
= (LPARAM
)&data
;
6942 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6943 pages
[nPages
].hInstance
= hInstance
;
6944 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FORMAT
);
6945 pages
[nPages
].pfnDlgProc
= export_format_dlg_proc
;
6946 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6947 pages
[nPages
].pszHeaderTitle
=
6948 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_TITLE
);
6949 pages
[nPages
].pszHeaderSubTitle
=
6950 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_SUBTITLE
);
6951 pages
[nPages
].lParam
= (LPARAM
)&data
;
6954 if (hasPrivateKey
&& showFormatPage
)
6956 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6957 pages
[nPages
].hInstance
= hInstance
;
6958 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD
);
6959 pages
[nPages
].pfnDlgProc
= export_password_dlg_proc
;
6960 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6961 pages
[nPages
].pszHeaderTitle
=
6962 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE
);
6963 pages
[nPages
].pszHeaderSubTitle
=
6964 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE
);
6965 pages
[nPages
].lParam
= (LPARAM
)&data
;
6969 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6970 pages
[nPages
].hInstance
= hInstance
;
6971 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FILE
);
6972 pages
[nPages
].pfnDlgProc
= export_file_dlg_proc
;
6973 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6974 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_EXPORT_FILE_TITLE
);
6975 pages
[nPages
].pszHeaderSubTitle
=
6976 MAKEINTRESOURCEW(IDS_EXPORT_FILE_SUBTITLE
);
6977 pages
[nPages
].lParam
= (LPARAM
)&data
;
6980 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6981 pages
[nPages
].hInstance
= hInstance
;
6982 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FINISH
);
6983 pages
[nPages
].pfnDlgProc
= export_finish_dlg_proc
;
6984 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6985 pages
[nPages
].lParam
= (LPARAM
)&data
;
6988 memset(&hdr
, 0, sizeof(hdr
));
6989 hdr
.dwSize
= sizeof(hdr
);
6990 hdr
.hwndParent
= hwndParent
;
6991 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
6993 hdr
.hInstance
= hInstance
;
6994 if (pwszWizardTitle
)
6995 hdr
.pszCaption
= pwszWizardTitle
;
6997 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_EXPORT_WIZARD
);
6998 hdr
.u3
.ppsp
= pages
;
6999 hdr
.nPages
= nPages
;
7000 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
7001 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
7002 l
= PropertySheetW(&hdr
);
7003 DeleteObject(data
.titleFont
);
7004 if (data
.freePassword
)
7005 HeapFree(GetProcessHeap(), 0,
7006 (LPWSTR
)data
.contextInfo
.pwszPassword
);
7007 HeapFree(GetProcessHeap(), 0, data
.keyProvInfo
);
7008 CloseHandle(data
.file
);
7009 HeapFree(GetProcessHeap(), 0, data
.fileName
);
7012 SetLastError(ERROR_CANCELLED
);
7016 return data
.success
;
7019 BOOL WINAPI
CryptUIWizExport(DWORD dwFlags
, HWND hwndParent
,
7020 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, void *pvoid
)
7024 TRACE("(%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
,
7025 debugstr_w(pwszWizardTitle
), pExportInfo
, pvoid
);
7027 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
7028 ret
= show_export_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pExportInfo
,
7032 HANDLE file
= CreateFileW(pExportInfo
->pwszExportFileName
,
7033 GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
7034 CREATE_ALWAYS
, 0, NULL
);
7036 if (file
!= INVALID_HANDLE_VALUE
)
7038 ret
= do_export(file
, pExportInfo
, pvoid
, NULL
, FALSE
);
7047 BOOL WINAPI
CryptUIDlgViewSignerInfoA(CRYPTUI_VIEWSIGNERINFO_STRUCTA
*pcvsi
)
7049 FIXME("%p: stub\n", pcvsi
);
7053 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateW(PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
)
7055 FIXME("%p: stub\n", pcsc
);
7059 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateA(PCCRYPTUI_SELECTCERTIFICATE_STRUCTA pcsc
)
7061 FIXME("%p: stub\n", pcsc
);