2 * Copyright 2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
37 #include "cryptuiapi.h"
38 #include "cryptuires.h"
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
47 static HINSTANCE hInstance
;
49 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
51 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
55 case DLL_WINE_PREATTACH
:
56 return FALSE
; /* prefer native version */
57 case DLL_PROCESS_ATTACH
:
59 DisableThreadLibraryCalls(hinstDLL
);
61 case DLL_PROCESS_DETACH
:
69 #define MAX_STRING_LEN 512
71 static void add_cert_columns(HWND hwnd
)
73 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
75 WCHAR buf
[MAX_STRING_LEN
];
78 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
79 GetWindowRect(lv
, &rc
);
80 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
,
81 sizeof(buf
) / sizeof(buf
[0]));
82 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
83 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
85 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
86 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
,
87 sizeof(buf
) / sizeof(buf
[0]));
88 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
89 column
.cx
= (rc
.right
- rc
.left
) * 16 / 100 - 2;
90 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
,
91 sizeof(buf
) / sizeof(buf
[0]));
92 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
93 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
94 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
,
95 sizeof(buf
) / sizeof(buf
[0]));
96 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 3, (LPARAM
)&column
);
99 static void add_cert_to_view(HWND lv
, PCCERT_CONTEXT cert
, DWORD
*allocatedLen
,
104 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
109 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
110 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
113 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
114 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
116 if (len
> *allocatedLen
)
118 HeapFree(GetProcessHeap(), 0, *str
);
119 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
125 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
128 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
131 item
.mask
= LVIF_TEXT
;
132 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
133 CERT_NAME_ISSUER_FLAG
, NULL
, NULL
, 0);
134 if (len
> *allocatedLen
)
136 HeapFree(GetProcessHeap(), 0, *str
);
137 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
143 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
144 CERT_NAME_ISSUER_FLAG
, NULL
, *str
, len
);
147 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
150 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
151 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
152 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
153 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
154 sizeof(date
) / sizeof(date
[0]));
157 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
159 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
161 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
162 if (len
> *allocatedLen
)
164 HeapFree(GetProcessHeap(), 0, *str
);
165 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
171 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
177 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
181 static LPSTR
get_cert_mgr_usages(void)
183 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
184 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
185 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
186 'r','p','o','s','e',0 };
190 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
196 rc
= RegQueryValueExA(key
, "Purpose", NULL
, &type
, NULL
, &size
);
197 if ((!rc
|| rc
== ERROR_MORE_DATA
) && type
== REG_SZ
)
199 str
= HeapAlloc(GetProcessHeap(), 0, size
);
202 rc
= RegQueryValueExA(key
, "Purpose", NULL
, NULL
, (LPBYTE
)str
,
206 HeapFree(GetProcessHeap(), 0, str
);
217 PurposeFilterShowAll
= 0,
218 PurposeFilterShowAdvanced
= 1,
219 PurposeFilterShowOID
= 2
222 static void initialize_purpose_selection(HWND hwnd
)
224 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
225 WCHAR buf
[MAX_STRING_LEN
];
229 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
,
230 sizeof(buf
) / sizeof(buf
[0]));
231 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
232 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAll
);
233 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
,
234 sizeof(buf
) / sizeof(buf
[0]));
235 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
236 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAdvanced
);
237 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
238 if ((usages
= get_cert_mgr_usages()))
242 for (ptr
= usages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
243 ptr
= comma
? comma
+ 1 : NULL
,
244 comma
= ptr
? strchr(ptr
, ',') : NULL
)
246 PCCRYPT_OID_INFO info
;
250 if ((info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, ptr
, 0)))
252 index
= SendMessageW(cb
, CB_INSERTSTRING
, 0,
253 (LPARAM
)info
->pwszName
);
254 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)info
);
257 HeapFree(GetProcessHeap(), 0, usages
);
261 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
262 PCCRYPT_OID_INFO
**usages
);
264 static CERT_ENHKEY_USAGE
*add_oid_to_usage(CERT_ENHKEY_USAGE
*usage
, LPSTR oid
)
266 if (!usage
->cUsageIdentifier
)
267 usage
->rgpszUsageIdentifier
= HeapAlloc(GetProcessHeap(), 0,
270 usage
->rgpszUsageIdentifier
= HeapReAlloc(GetProcessHeap(), 0,
271 usage
->rgpszUsageIdentifier
,
272 (usage
->cUsageIdentifier
+ 1) * sizeof(LPSTR
));
273 if (usage
->rgpszUsageIdentifier
)
274 usage
->rgpszUsageIdentifier
[usage
->cUsageIdentifier
++] = oid
;
277 HeapFree(GetProcessHeap(), 0, usage
);
283 static CERT_ENHKEY_USAGE
*convert_usages_str_to_usage(LPSTR usageStr
)
285 CERT_ENHKEY_USAGE
*usage
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
286 sizeof(CERT_ENHKEY_USAGE
));
292 for (ptr
= usageStr
, comma
= strchr(ptr
, ','); usage
&& ptr
&& *ptr
;
293 ptr
= comma
? comma
+ 1 : NULL
,
294 comma
= ptr
? strchr(ptr
, ',') : NULL
)
298 add_oid_to_usage(usage
, ptr
);
304 static CERT_ENHKEY_USAGE
*create_advanced_filter(void)
306 CERT_ENHKEY_USAGE
*advancedUsage
= HeapAlloc(GetProcessHeap(),
307 HEAP_ZERO_MEMORY
, sizeof(CERT_ENHKEY_USAGE
));
311 PCCRYPT_OID_INFO
*usages
;
313 if (WTHelperGetKnownUsages(1, &usages
))
315 LPSTR disabledUsagesStr
;
317 if ((disabledUsagesStr
= get_cert_mgr_usages()))
319 CERT_ENHKEY_USAGE
*disabledUsages
=
320 convert_usages_str_to_usage(disabledUsagesStr
);
324 PCCRYPT_OID_INFO
*ptr
;
326 for (ptr
= usages
; *ptr
; ptr
++)
329 BOOL disabled
= FALSE
;
331 for (i
= 0; !disabled
&&
332 i
< disabledUsages
->cUsageIdentifier
; i
++)
333 if (!strcmp(disabledUsages
->rgpszUsageIdentifier
[i
],
337 add_oid_to_usage(advancedUsage
,
338 (LPSTR
)(*ptr
)->pszOID
);
340 /* The individual strings are pointers to disabledUsagesStr,
341 * so they're freed when it is.
343 HeapFree(GetProcessHeap(), 0,
344 disabledUsages
->rgpszUsageIdentifier
);
345 HeapFree(GetProcessHeap(), 0, disabledUsages
);
347 HeapFree(GetProcessHeap(), 0, disabledUsagesStr
);
349 WTHelperGetKnownUsages(2, &usages
);
352 return advancedUsage
;
355 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
);
357 static void show_store_certs(HWND hwnd
, HCERTSTORE store
)
359 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
360 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
361 PCCERT_CONTEXT cert
= NULL
;
362 DWORD allocatedLen
= 0;
365 PurposeFilter filter
= PurposeFilterShowAll
;
367 CERT_ENHKEY_USAGE
*advanced
= NULL
;
369 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
372 INT_PTR data
= SendMessageW(cb
, CB_GETITEMDATA
, index
, 0);
378 PCCRYPT_OID_INFO info
= (PCCRYPT_OID_INFO
)data
;
380 filter
= PurposeFilterShowOID
;
384 if (filter
== PurposeFilterShowAdvanced
)
385 advanced
= create_advanced_filter();
387 cert
= CertEnumCertificatesInStore(store
, cert
);
392 if (filter
== PurposeFilterShowAll
)
399 if (CertGetValidUsages(1, &cert
, &numOIDs
, NULL
, &cbOIDs
))
403 /* -1 implies all usages are valid */
408 LPSTR
*oids
= HeapAlloc(GetProcessHeap(), 0, cbOIDs
);
412 if (CertGetValidUsages(1, &cert
, &numOIDs
, oids
,
417 if (filter
== PurposeFilterShowOID
)
419 for (i
= 0; !show
&& i
< numOIDs
; i
++)
420 if (!strcmp(oids
[i
], oid
))
425 for (i
= 0; !show
&& i
< numOIDs
; i
++)
430 j
< advanced
->cUsageIdentifier
; j
++)
432 advanced
->rgpszUsageIdentifier
[j
]))
437 HeapFree(GetProcessHeap(), 0, oids
);
443 add_cert_to_view(lv
, cert
, &allocatedLen
, &str
);
446 HeapFree(GetProcessHeap(), 0, str
);
449 HeapFree(GetProcessHeap(), 0, advanced
->rgpszUsageIdentifier
);
450 HeapFree(GetProcessHeap(), 0, advanced
);
452 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
453 (LPARAM
)cert_mgr_sort_by_subject
);
456 static const WCHAR my
[] = { 'M','y',0 };
457 static const WCHAR addressBook
[] = {
458 'A','d','d','r','e','s','s','B','o','o','k',0 };
459 static const WCHAR ca
[] = { 'C','A',0 };
460 static const WCHAR root
[] = { 'R','o','o','t',0 };
461 static const WCHAR trustedPublisher
[] = {
462 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
463 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
465 struct CertMgrStoreInfo
469 int removePluralWarning
;
472 static const struct CertMgrStoreInfo defaultStoreList
[] = {
473 { my
, IDS_WARN_REMOVE_MY
, IDS_WARN_REMOVE_PLURAL_MY
},
474 { addressBook
, IDS_WARN_REMOVE_ADDRESSBOOK
,
475 IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK
},
476 { ca
, IDS_WARN_REMOVE_CA
, IDS_WARN_REMOVE_PLURAL_CA
},
477 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
478 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
479 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
480 { disallowed
, IDS_WARN_REMOVE_DEFAULT
},
483 static const struct CertMgrStoreInfo publisherStoreList
[] = {
484 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
485 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
486 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
487 { disallowed
, IDS_WARN_REMOVE_PLURAL_DEFAULT
},
492 HIMAGELIST imageList
;
495 const struct CertMgrStoreInfo
*stores
;
498 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
, struct CertMgrData
*data
)
500 const struct CertMgrStoreInfo
*storeList
;
502 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
504 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
506 storeList
= publisherStoreList
;
507 cStores
= sizeof(publisherStoreList
) / sizeof(publisherStoreList
[0]);
511 storeList
= defaultStoreList
;
512 cStores
= sizeof(defaultStoreList
) / sizeof(defaultStoreList
[0]);
514 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
516 data
->nStores
= cStores
;
517 data
->stores
= storeList
;
518 for (i
= 0; i
< cStores
; i
++)
524 if (!(name
= CryptFindLocalizedName(storeList
[i
].name
)))
525 name
= storeList
[i
].name
;
526 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
527 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
].name
);
528 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
529 item
.pszText
= (LPWSTR
)name
;
530 item
.lParam
= (LPARAM
)store
;
531 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
535 static void free_certs(HWND lv
)
538 int items
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
540 for (i
= 0; i
< items
; i
++)
542 item
.mask
= LVIF_PARAM
;
545 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
546 CertFreeCertificateContext((PCCERT_CONTEXT
)item
.lParam
);
550 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
554 item
.mask
= TCIF_PARAM
;
555 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
556 return (HCERTSTORE
)item
.lParam
;
559 static HCERTSTORE
cert_mgr_current_store(HWND hwnd
)
561 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
563 return cert_mgr_index_to_store(tab
, SendMessageW(tab
, TCM_GETCURSEL
, 0, 0));
566 static void close_stores(HWND tab
)
568 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
570 for (i
= 0; i
< tabs
; i
++)
571 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
574 static void refresh_store_certs(HWND hwnd
)
576 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
579 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
580 show_store_certs(hwnd
, cert_mgr_current_store(hwnd
));
584 CheckBitmapIndexUnchecked
= 1,
585 CheckBitmapIndexChecked
= 2,
586 CheckBitmapIndexDisabledUnchecked
= 3,
587 CheckBitmapIndexDisabledChecked
= 4
590 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
,
591 CheckBitmapIndex state
)
595 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
596 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
597 item
.stateMask
= LVIS_STATEIMAGEMASK
;
598 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
600 item
.lParam
= (LPARAM
)info
;
601 item
.pszText
= (LPWSTR
)info
->pwszName
;
602 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
605 static void add_known_usages_to_list(HWND lv
, CheckBitmapIndex state
)
607 PCCRYPT_OID_INFO
*usages
;
609 if (WTHelperGetKnownUsages(1, &usages
))
611 PCCRYPT_OID_INFO
*ptr
;
613 for (ptr
= usages
; *ptr
; ptr
++)
614 add_known_usage(lv
, *ptr
, state
);
615 WTHelperGetKnownUsages(2, &usages
);
619 static void toggle_usage(HWND hwnd
, int iItem
)
623 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
625 item
.mask
= LVIF_STATE
;
628 item
.stateMask
= LVIS_STATEIMAGEMASK
;
629 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
632 int state
= item
.state
>> 12;
634 item
.state
= INDEXTOSTATEIMAGEMASK(
635 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
636 CheckBitmapIndexChecked
);
637 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
641 static LONG_PTR
find_oid_in_list(HWND lv
, LPCSTR oid
)
643 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
644 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
649 LVFINDINFOW findInfo
;
651 findInfo
.flags
= LVFI_PARAM
;
652 findInfo
.lParam
= (LPARAM
)oidInfo
;
653 ret
= SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
);
657 LVFINDINFOA findInfo
;
659 findInfo
.flags
= LVFI_STRING
;
661 ret
= SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
);
666 static void save_cert_mgr_usages(HWND hwnd
)
668 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
669 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
670 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
671 'r','p','o','s','e',0 };
673 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
674 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
678 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
680 item
.stateMask
= LVIS_STATEIMAGEMASK
;
681 for (i
= 0; i
< purposes
; i
++)
684 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
686 int state
= item
.state
>> 12;
688 if (state
== CheckBitmapIndexUnchecked
)
690 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
691 BOOL firstString
= TRUE
;
694 str
= HeapAlloc(GetProcessHeap(), 0,
695 strlen(info
->pszOID
) + 1);
698 str
= HeapReAlloc(GetProcessHeap(), 0, str
,
699 strlen(str
) + 1 + strlen(info
->pszOID
) + 1);
704 LPSTR ptr
= firstString
? str
: str
+ strlen(str
);
708 strcpy(ptr
, info
->pszOID
);
713 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_ALL_ACCESS
,
717 RegSetValueExA(key
, "Purpose", 0, REG_SZ
, (const BYTE
*)str
,
720 RegDeleteValueA(key
, "Purpose");
723 HeapFree(GetProcessHeap(), 0, str
);
726 static LRESULT CALLBACK
cert_mgr_advanced_dlg_proc(HWND hwnd
, UINT msg
,
727 WPARAM wp
, LPARAM lp
)
735 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
736 HIMAGELIST imageList
;
737 LPSTR disabledUsages
;
739 GetWindowRect(lv
, &rc
);
740 column
.mask
= LVCF_WIDTH
;
741 column
.cx
= rc
.right
- rc
.left
;
742 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
743 imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 4, 0);
747 COLORREF backColor
= RGB(255, 0, 255);
749 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
750 ImageList_AddMasked(imageList
, bmp
, backColor
);
752 ImageList_SetBkColor(imageList
, CLR_NONE
);
753 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)imageList
);
754 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)imageList
);
756 add_known_usages_to_list(lv
, CheckBitmapIndexChecked
);
757 if ((disabledUsages
= get_cert_mgr_usages()))
761 for (ptr
= disabledUsages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
762 ptr
= comma
? comma
+ 1 : NULL
,
763 comma
= ptr
? strchr(ptr
, ',') : NULL
)
769 if ((index
= find_oid_in_list(lv
, ptr
)) != -1)
770 toggle_usage(hwnd
, index
);
772 HeapFree(GetProcessHeap(), 0, disabledUsages
);
778 NMHDR
*hdr
= (NMHDR
*)lp
;
784 nm
= (NMITEMACTIVATE
*)lp
;
785 toggle_usage(hwnd
, nm
->iItem
);
786 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
795 save_cert_mgr_usages(hwnd
);
796 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
797 EndDialog(hwnd
, IDOK
);
800 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
801 EndDialog(hwnd
, IDCANCEL
);
809 static void cert_mgr_clear_cert_selection(HWND hwnd
)
811 WCHAR empty
[] = { 0 };
813 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), FALSE
);
814 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), FALSE
);
815 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), FALSE
);
816 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
818 refresh_store_certs(hwnd
);
821 static PCCERT_CONTEXT
cert_mgr_index_to_cert(HWND hwnd
, int index
)
823 PCCERT_CONTEXT cert
= NULL
;
826 item
.mask
= LVIF_PARAM
;
829 if (SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_GETITEMW
, 0,
831 cert
= (PCCERT_CONTEXT
)item
.lParam
;
835 static void show_selected_cert(HWND hwnd
, int index
)
837 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
841 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
843 memset(&viewInfo
, 0, sizeof(viewInfo
));
844 viewInfo
.dwSize
= sizeof(viewInfo
);
845 viewInfo
.hwndParent
= hwnd
;
846 viewInfo
.pCertContext
= cert
;
847 /* FIXME: this should be modal */
848 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
852 static void cert_mgr_show_cert_usages(HWND hwnd
, int index
)
854 HWND text
= GetDlgItem(hwnd
, IDC_MGR_PURPOSES
);
855 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
856 PCERT_ENHKEY_USAGE usage
;
859 /* Get enhanced key usage. Have to check for a property and an extension
860 * separately, because CertGetEnhancedKeyUsage will succeed and return an
861 * empty usage if neither is set. Unfortunately an empty usage implies
862 * no usage is allowed, so we have to distinguish between the two cases.
864 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
867 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
868 if (!CertGetEnhancedKeyUsage(cert
,
869 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
871 HeapFree(GetProcessHeap(), 0, usage
);
875 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
878 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
879 if (!CertGetEnhancedKeyUsage(cert
,
880 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
882 HeapFree(GetProcessHeap(), 0, usage
);
890 if (usage
->cUsageIdentifier
)
892 static const WCHAR commaSpace
[] = { ',',' ',0 };
896 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
898 PCCRYPT_OID_INFO info
=
899 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
900 usage
->rgpszUsageIdentifier
[i
],
901 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
904 len
+= strlenW(info
->pwszName
);
906 len
+= strlen(usage
->rgpszUsageIdentifier
[i
]);
907 if (i
< usage
->cUsageIdentifier
- 1)
908 len
+= strlenW(commaSpace
);
910 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
913 for (i
= 0, ptr
= str
; i
< usage
->cUsageIdentifier
; i
++)
915 PCCRYPT_OID_INFO info
=
916 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
917 usage
->rgpszUsageIdentifier
[i
],
918 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
922 strcpyW(ptr
, info
->pwszName
);
923 ptr
+= strlenW(info
->pwszName
);
927 LPCSTR src
= usage
->rgpszUsageIdentifier
[i
];
929 for (; *src
; ptr
++, src
++)
933 if (i
< usage
->cUsageIdentifier
- 1)
935 strcpyW(ptr
, commaSpace
);
936 ptr
+= strlenW(commaSpace
);
940 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)str
);
941 HeapFree(GetProcessHeap(), 0, str
);
943 HeapFree(GetProcessHeap(), 0, usage
);
947 WCHAR buf
[MAX_STRING_LEN
];
949 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_NONE
, buf
,
950 sizeof(buf
) / sizeof(buf
[0]));
951 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
956 WCHAR buf
[MAX_STRING_LEN
];
958 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_ALL
, buf
,
959 sizeof(buf
) / sizeof(buf
[0]));
960 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
964 static void cert_mgr_do_remove(HWND hwnd
)
966 int tabIndex
= SendMessageW(GetDlgItem(hwnd
, IDC_MGR_STORES
),
967 TCM_GETCURSEL
, 0, 0);
968 struct CertMgrData
*data
=
969 (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
971 if (tabIndex
< data
->nStores
)
973 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
974 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
978 if (SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0) > 1)
979 warningID
= data
->stores
[tabIndex
].removePluralWarning
;
981 warningID
= data
->stores
[tabIndex
].removeWarning
;
983 pTitle
= data
->title
;
986 LoadStringW(hInstance
, IDS_CERT_MGR
, title
,
987 sizeof(title
) / sizeof(title
[0]));
990 LoadStringW(hInstance
, warningID
, warning
,
991 sizeof(warning
) / sizeof(warning
[0]));
992 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
997 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1001 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1004 CertDeleteCertificateFromStore(cert
);
1006 } while (selection
>= 0);
1007 cert_mgr_clear_cert_selection(hwnd
);
1012 static void cert_mgr_do_export(HWND hwnd
)
1014 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1015 int selectionCount
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1017 if (selectionCount
== 1)
1019 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1024 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, selection
);
1028 CRYPTUI_WIZ_EXPORT_INFO info
;
1030 info
.dwSize
= sizeof(info
);
1031 info
.pwszExportFileName
= NULL
;
1032 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
1033 info
.u
.pCertContext
= cert
;
1035 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1039 else if (selectionCount
> 1)
1041 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1042 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1046 CRYPTUI_WIZ_EXPORT_INFO info
;
1049 info
.dwSize
= sizeof(info
);
1050 info
.pwszExportFileName
= NULL
;
1051 info
.dwSubjectChoice
=
1052 CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
;
1053 info
.u
.hCertStore
= store
;
1056 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1060 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1063 CertAddCertificateContextToStore(store
, cert
,
1064 CERT_STORE_ADD_ALWAYS
, NULL
);
1066 } while (selection
>= 0);
1067 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1068 CertCloseStore(store
, 0);
1073 static int cert_mgr_sort_by_text(HWND lv
, int col
, int index1
, int index2
)
1076 WCHAR buf1
[MAX_STRING_LEN
];
1077 WCHAR buf2
[MAX_STRING_LEN
];
1079 item
.cchTextMax
= sizeof(buf1
) / sizeof(buf1
[0]);
1080 item
.mask
= LVIF_TEXT
;
1081 item
.pszText
= buf1
;
1082 item
.iItem
= index1
;
1083 item
.iSubItem
= col
;
1084 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1085 item
.pszText
= buf2
;
1086 item
.iItem
= index2
;
1087 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1088 return strcmpW(buf1
, buf2
);
1091 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1093 return cert_mgr_sort_by_text((HWND
)lp
, 0, lp1
, lp2
);
1096 static int CALLBACK
cert_mgr_sort_by_issuer(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1098 return cert_mgr_sort_by_text((HWND
)lp
, 1, lp1
, lp2
);
1101 static int CALLBACK
cert_mgr_sort_by_date(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1103 PCCERT_CONTEXT cert1
= (PCCERT_CONTEXT
)lp1
;
1104 PCCERT_CONTEXT cert2
= (PCCERT_CONTEXT
)lp2
;
1105 return CompareFileTime(&cert1
->pCertInfo
->NotAfter
,
1106 &cert2
->pCertInfo
->NotAfter
);
1109 static int CALLBACK
cert_mgr_sort_by_friendly_name(LPARAM lp1
, LPARAM lp2
,
1112 return cert_mgr_sort_by_text((HWND
)lp
, 3, lp1
, lp2
);
1115 static LRESULT CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1118 struct CertMgrData
*data
;
1124 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
1125 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
1126 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
1128 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData
));
1131 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
1132 if (data
->imageList
)
1135 COLORREF backColor
= RGB(255, 0, 255);
1137 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
1138 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
1140 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
1141 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_SETIMAGELIST
,
1142 LVSIL_SMALL
, (LPARAM
)data
->imageList
);
1144 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
1145 data
->title
= pCryptUICertMgr
->pwszTitle
;
1147 initialize_purpose_selection(hwnd
);
1148 add_cert_columns(hwnd
);
1149 if (pCryptUICertMgr
->pwszTitle
)
1150 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1151 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
1152 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
, data
);
1153 show_store_certs(hwnd
, cert_mgr_index_to_store(tab
, 0));
1158 NMHDR
*hdr
= (NMHDR
*)lp
;
1163 cert_mgr_clear_cert_selection(hwnd
);
1165 case LVN_ITEMCHANGED
:
1168 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1170 nm
= (NMITEMACTIVATE
*)lp
;
1171 if (nm
->uNewState
& LVN_ITEMACTIVATE
)
1173 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1175 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), numSelected
> 0);
1176 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), numSelected
> 0);
1177 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), numSelected
== 1);
1178 if (numSelected
== 1)
1179 cert_mgr_show_cert_usages(hwnd
, nm
->iItem
);
1184 show_selected_cert(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
1188 NMLVKEYDOWN
*lvk
= (NMLVKEYDOWN
*)lp
;
1190 if (lvk
->wVKey
== VK_DELETE
)
1191 cert_mgr_do_remove(hwnd
);
1194 case LVN_COLUMNCLICK
:
1196 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
1197 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1199 /* FIXME: doesn't support swapping sort order between ascending
1202 switch (nmlv
->iSubItem
)
1205 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1206 (LPARAM
)cert_mgr_sort_by_subject
);
1209 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1210 (LPARAM
)cert_mgr_sort_by_issuer
);
1213 SendMessageW(lv
, LVM_SORTITEMS
, 0,
1214 (LPARAM
)cert_mgr_sort_by_date
);
1217 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1218 (LPARAM
)cert_mgr_sort_by_friendly_name
);
1229 case ((CBN_SELCHANGE
<< 16) | IDC_MGR_PURPOSE_SELECTION
):
1230 cert_mgr_clear_cert_selection(hwnd
);
1232 case IDC_MGR_IMPORT
:
1233 if (CryptUIWizImport(0, hwnd
, NULL
, NULL
,
1234 cert_mgr_current_store(hwnd
)))
1235 refresh_store_certs(hwnd
);
1237 case IDC_MGR_ADVANCED
:
1238 if (DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR_ADVANCED
),
1239 hwnd
, cert_mgr_advanced_dlg_proc
) == IDOK
)
1241 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
1243 LPWSTR curString
= NULL
;
1245 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
1248 len
= SendMessageW(cb
, CB_GETLBTEXTLEN
, index
, 0);
1249 curString
= HeapAlloc(GetProcessHeap(), 0,
1250 (len
+ 1) * sizeof(WCHAR
));
1251 SendMessageW(cb
, CB_GETLBTEXT
, index
, (LPARAM
)curString
);
1253 SendMessageW(cb
, CB_RESETCONTENT
, 0, 0);
1254 initialize_purpose_selection(hwnd
);
1257 index
= SendMessageW(cb
, CB_FINDSTRINGEXACT
, -1,
1260 SendMessageW(cb
, CB_SETCURSEL
, index
, 0);
1261 HeapFree(GetProcessHeap(), 0, curString
);
1263 refresh_store_certs(hwnd
);
1268 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1269 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1273 show_selected_cert(hwnd
, selection
);
1276 case IDC_MGR_EXPORT
:
1277 cert_mgr_do_export(hwnd
);
1279 case IDC_MGR_REMOVE
:
1280 cert_mgr_do_remove(hwnd
);
1283 free_certs(GetDlgItem(hwnd
, IDC_MGR_CERTS
));
1284 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1285 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1286 data
= (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1287 ImageList_Destroy(data
->imageList
);
1288 HeapFree(GetProcessHeap(), 0, data
);
1289 EndDialog(hwnd
, IDCANCEL
);
1297 /***********************************************************************
1298 * CryptUIDlgCertMgr (CRYPTUI.@)
1300 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
1302 TRACE("(%p)\n", pCryptUICertMgr
);
1304 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
1306 WARN("unexpected size %d\n", pCryptUICertMgr
->dwSize
);
1307 SetLastError(E_INVALIDARG
);
1310 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
1311 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
1315 /* FIXME: real names are unknown, functions are undocumented */
1316 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
1319 void *pvSystemStoreLocationPara
;
1320 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
1322 typedef struct _CRYPTUI_ENUM_DATA
1325 HCERTSTORE
*rghStore
;
1327 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
1328 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
1330 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
1333 /* Values for dwFlags */
1334 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
1336 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
1343 CRYPTUI_ENUM_DATA
*pEnumData
;
1344 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1346 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
1348 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
1355 CRYPTUI_ENUM_DATA
*pEnumData
;
1356 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1358 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
1372 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
1373 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
1376 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
1377 TVINSERTSTRUCTW tvis
;
1378 LPCWSTR localizedName
;
1381 tvis
.hParent
= NULL
;
1382 tvis
.hInsertAfter
= TVI_LAST
;
1383 tvis
.u
.item
.mask
= TVIF_TEXT
;
1384 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
1386 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(), 0,
1387 sizeof(struct StoreInfo
));
1391 storeInfo
->type
= SystemStore
;
1392 storeInfo
->u
.name
= HeapAlloc(GetProcessHeap(), 0,
1393 (strlenW(pvSystemStore
) + 1) * sizeof(WCHAR
));
1394 if (storeInfo
->u
.name
)
1396 tvis
.u
.item
.mask
|= TVIF_PARAM
;
1397 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1398 strcpyW(storeInfo
->u
.name
, pvSystemStore
);
1402 HeapFree(GetProcessHeap(), 0, storeInfo
);
1408 tvis
.u
.item
.pszText
= (LPWSTR
)localizedName
;
1411 tvis
.u
.item
.pszText
= (LPWSTR
)pvSystemStore
;
1412 /* FIXME: need a folder icon for the store too */
1414 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1418 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
1421 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1423 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
1424 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
1425 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
1426 hwnd
, enum_store_callback
);
1427 for (i
= 0; i
< pEnumData
->cStores
; i
++)
1431 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1432 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
1434 LPWSTR name
= HeapAlloc(GetProcessHeap(), 0, size
);
1438 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1439 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
1441 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(),
1442 0, sizeof(struct StoreInfo
));
1446 TVINSERTSTRUCTW tvis
;
1448 storeInfo
->type
= StoreHandle
;
1449 storeInfo
->u
.store
= pEnumData
->rghStore
[i
];
1450 tvis
.hParent
= NULL
;
1451 tvis
.hInsertAfter
= TVI_LAST
;
1452 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
1453 tvis
.u
.item
.pszText
= name
;
1454 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1455 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1458 HeapFree(GetProcessHeap(), 0, name
);
1464 static void free_store_info(HWND tree
)
1466 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
1473 memset(&item
, 0, sizeof(item
));
1474 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
1476 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1479 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1481 if (storeInfo
->type
== SystemStore
)
1482 HeapFree(GetProcessHeap(), 0, storeInfo
->u
.name
);
1483 HeapFree(GetProcessHeap(), 0, storeInfo
);
1485 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
1490 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
1492 WCHAR buf
[MAX_STRING_LEN
];
1496 memset(&item
, 0, sizeof(item
));
1497 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
1499 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
1501 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1504 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1506 if (storeInfo
->type
== StoreHandle
)
1507 store
= storeInfo
->u
.store
;
1509 store
= CertOpenSystemStoreW(0, storeInfo
->u
.name
);
1513 /* It's implicitly a system store */
1514 store
= CertOpenSystemStoreW(0, buf
);
1519 struct SelectStoreInfo
1521 PCRYPTUI_SELECTSTORE_INFO_W info
;
1525 static LRESULT CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1528 struct SelectStoreInfo
*selectInfo
;
1535 selectInfo
= (struct SelectStoreInfo
*)lp
;
1536 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
1537 if (selectInfo
->info
->pwszTitle
)
1538 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1539 (LPARAM
)selectInfo
->info
->pwszTitle
);
1540 if (selectInfo
->info
->pwszText
)
1541 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
1542 (LPARAM
)selectInfo
->info
->pwszText
);
1543 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
1544 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
1545 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
1553 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1554 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
1555 TVM_GETNEXTITEM
, TVGN_CARET
, (LPARAM
)NULL
);
1557 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
1561 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
1563 if (selectInfo
->info
->pwszTitle
)
1564 pTitle
= selectInfo
->info
->pwszTitle
;
1567 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
,
1568 sizeof(title
) / sizeof(title
[0]));
1571 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
,
1572 sizeof(error
) / sizeof(error
[0]));
1573 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
1577 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
1579 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
1580 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
1581 selectInfo
->info
->pvArg
))
1583 selectInfo
->store
= store
;
1584 free_store_info(tree
);
1585 EndDialog(hwnd
, IDOK
);
1588 CertCloseStore(store
, 0);
1594 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
1595 EndDialog(hwnd
, IDCANCEL
);
1604 /***********************************************************************
1605 * CryptUIDlgSelectStoreW (CRYPTUI.@)
1607 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
1609 struct SelectStoreInfo selectInfo
= { info
, NULL
};
1611 TRACE("(%p)\n", info
);
1613 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
1615 WARN("unexpected size %d\n", info
->dwSize
);
1616 SetLastError(E_INVALIDARG
);
1619 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
1620 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
1621 return selectInfo
.store
;
1624 /***********************************************************************
1625 * CryptUIDlgSelectStoreA (CRYPTUI.@)
1627 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
1629 CRYPTUI_SELECTSTORE_INFO_W infoW
;
1633 TRACE("(%p)\n", info
);
1635 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
1637 WARN("unexpected size %d\n", info
->dwSize
);
1638 SetLastError(E_INVALIDARG
);
1641 memcpy(&infoW
, &info
, sizeof(info
));
1644 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
1645 infoW
.pwszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1646 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
1651 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
1652 infoW
.pwszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1653 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
1655 ret
= CryptUIDlgSelectStoreW(&infoW
);
1656 HeapFree(GetProcessHeap(), 0, infoW
.pwszText
);
1657 HeapFree(GetProcessHeap(), 0, infoW
.pwszTitle
);
1661 /***********************************************************************
1662 * CryptUIDlgViewCertificateA (CRYPTUI.@)
1664 BOOL WINAPI
CryptUIDlgViewCertificateA(
1665 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
1667 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
1668 LPWSTR title
= NULL
;
1671 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
1673 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
1674 if (pCertViewInfo
->szTitle
)
1676 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
1679 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1682 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
1684 viewInfo
.szTitle
= title
;
1692 if (pCertViewInfo
->cPropSheetPages
)
1694 FIXME("ignoring additional prop sheet pages\n");
1695 viewInfo
.cPropSheetPages
= 0;
1697 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
1698 HeapFree(GetProcessHeap(), 0, title
);
1703 struct ReadStringStruct
1710 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
1713 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
1714 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
1716 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
1718 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
1720 *pcb
= cch
* sizeof(WCHAR
);
1724 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
1726 struct ReadStringStruct string
;
1727 EDITSTREAM editstream
;
1729 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
1734 editstream
.dwCookie
= (DWORD_PTR
)&string
;
1735 editstream
.dwError
= 0;
1736 editstream
.pfnCallback
= read_text_callback
;
1737 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
1738 (LPARAM
)&editstream
);
1741 static void add_string_resource_to_control(HWND hwnd
, int id
)
1746 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1747 add_unformatted_text_to_control(hwnd
, str
, len
);
1750 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
1751 LONG len
, const PARAFORMAT2
*fmt
)
1753 add_unformatted_text_to_control(hwnd
, text
, len
);
1754 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
1757 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
1758 const PARAFORMAT2
*fmt
)
1763 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1764 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
1767 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
1773 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
1776 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1778 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
1783 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
1784 DWORD dwType
, DWORD dwFlags
)
1786 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
1790 /* Don't include NULL-terminator in output */
1791 DWORD len
= lstrlenW(name
);
1793 add_unformatted_text_to_control(hwnd
, name
, len
);
1794 HeapFree(GetProcessHeap(), 0, name
);
1798 static void add_icon_to_control(HWND hwnd
, int id
)
1801 LPRICHEDITOLE richEditOle
= NULL
;
1802 LPOLEOBJECT object
= NULL
;
1804 LPOLECACHE oleCache
= NULL
;
1805 FORMATETC formatEtc
;
1807 LPDATAOBJECT dataObject
= NULL
;
1808 HBITMAP bitmap
= NULL
;
1811 LPOLECLIENTSITE clientSite
= NULL
;
1814 TRACE("(%p, %d)\n", hwnd
, id
);
1816 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
1819 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
1823 hr
= IOleObject_GetUserClassID(object
, &clsid
);
1826 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
1829 formatEtc
.cfFormat
= CF_BITMAP
;
1830 formatEtc
.ptd
= NULL
;
1831 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
1832 formatEtc
.lindex
= -1;
1833 formatEtc
.tymed
= TYMED_GDI
;
1834 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
1837 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
1838 (void**)&dataObject
);
1841 hr
= IRichEditOle_GetClientSite(richEditOle
, &clientSite
);
1844 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
1845 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
1848 rect
.left
= rect
.top
= 0;
1849 rect
.right
= GetSystemMetrics(SM_CXICON
);
1850 rect
.bottom
= GetSystemMetrics(SM_CYICON
);
1851 stgm
.tymed
= TYMED_GDI
;
1852 stgm
.u
.hBitmap
= bitmap
;
1853 stgm
.pUnkForRelease
= NULL
;
1854 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
1858 reObject
.cbStruct
= sizeof(reObject
);
1859 reObject
.cp
= REO_CP_SELECTION
;
1860 reObject
.clsid
= clsid
;
1861 reObject
.poleobj
= object
;
1862 reObject
.pstg
= NULL
;
1863 reObject
.polesite
= clientSite
;
1864 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
1865 reObject
.dvaspect
= DVASPECT_CONTENT
;
1866 reObject
.dwFlags
= 0;
1867 reObject
.dwUser
= 0;
1869 IRichEditOle_InsertObject(richEditOle
, &reObject
);
1873 IOleClientSite_Release(clientSite
);
1875 IDataObject_Release(dataObject
);
1877 IOleCache_Release(oleCache
);
1879 IOleObject_Release(object
);
1881 IRichEditOle_Release(richEditOle
);
1884 #define MY_INDENT 200
1886 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
1889 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
1892 parFmt
.cbSize
= sizeof(parFmt
);
1893 parFmt
.dwMask
= PFM_STARTINDENT
;
1894 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1897 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
1898 lstrlenW(oidInfo
->pwszName
), &parFmt
);
1899 add_unformatted_text_to_control(hwnd
, &nl
, 1);
1909 /* The following list MUST be lexicographically sorted by OID */
1910 static struct OIDToString oidMap
[] = {
1911 /* 1.3.6.1.4.1.311.10.3.1 */
1912 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
1913 /* 1.3.6.1.4.1.311.10.3.4 */
1914 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
1915 /* 1.3.6.1.4.1.311.10.3.4.1 */
1916 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
1917 /* 1.3.6.1.4.1.311.10.3.5 */
1918 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
1919 /* 1.3.6.1.4.1.311.10.3.6 */
1920 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
1921 /* 1.3.6.1.4.1.311.10.3.7 */
1922 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
1923 /* 1.3.6.1.4.1.311.10.3.8 */
1924 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
1925 /* 1.3.6.1.4.1.311.10.3.9 */
1926 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
1927 /* 1.3.6.1.4.1.311.10.3.10 */
1928 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
1929 /* 1.3.6.1.4.1.311.10.3.11 */
1930 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
1931 /* 1.3.6.1.4.1.311.10.3.12 */
1932 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
1933 /* 1.3.6.1.4.1.311.10.3.13 */
1934 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
1935 /* 1.3.6.1.4.1.311.10.5.1 */
1936 { szOID_DRM
, IDS_PURPOSE_DRM
},
1937 /* 1.3.6.1.4.1.311.10.6.1 */
1938 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
1939 /* 1.3.6.1.4.1.311.10.6.2 */
1940 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
1941 /* 1.3.6.1.4.1.311.20.2.1 */
1942 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
1943 /* 1.3.6.1.4.1.311.20.2.2 */
1944 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
1945 /* 1.3.6.1.4.1.311.21.5 */
1946 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
1947 /* 1.3.6.1.4.1.311.21.6 */
1948 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
1949 /* 1.3.6.1.4.1.311.21.19 */
1950 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
1951 /* 1.3.6.1.5.5.7.3.1 */
1952 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
1953 /* 1.3.6.1.5.5.7.3.2 */
1954 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
1955 /* 1.3.6.1.5.5.7.3.3 */
1956 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
1957 /* 1.3.6.1.5.5.7.3.4 */
1958 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
1959 /* 1.3.6.1.5.5.7.3.5 */
1960 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
1961 /* 1.3.6.1.5.5.7.3.6 */
1962 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
1963 /* 1.3.6.1.5.5.7.3.7 */
1964 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
1965 /* 1.3.6.1.5.5.7.3.8 */
1966 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
1969 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
1971 int indexHigh
= sizeof(oidMap
) / sizeof(oidMap
[0]) - 1, indexLow
= 0, i
;
1972 struct OIDToString
*ret
= NULL
;
1974 for (i
= (indexLow
+ indexHigh
) / 2; !ret
&& indexLow
<= indexHigh
;
1975 i
= (indexLow
+ indexHigh
) / 2)
1979 cmp
= strcmp(oid
, oidMap
[i
].oid
);
1990 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
1992 struct OIDToString
*entry
;
1996 parFmt
.cbSize
= sizeof(parFmt
);
1997 parFmt
.dwMask
= PFM_STARTINDENT
;
1998 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1999 if ((entry
= findSupportedOID(oid
)))
2001 WCHAR
*str
, *linebreak
, *ptr
;
2002 BOOL multiline
= FALSE
;
2005 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
2008 if ((linebreak
= memchrW(ptr
, '\n', len
)))
2010 WCHAR copy
[MAX_STRING_LEN
];
2013 /* The source string contains a newline, which the richedit
2014 * control won't find since it's interpreted as a paragraph
2015 * break. Therefore copy up to the newline. lstrcpynW always
2016 * NULL-terminates, so pass one more than the length of the
2017 * source line so the copy includes the entire line and the
2020 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
2021 add_text_with_paraformat_to_control(text
, copy
,
2022 linebreak
- ptr
, &parFmt
);
2023 ptr
= linebreak
+ 1;
2024 add_unformatted_text_to_control(text
, &nl
, 1);
2026 else if (multiline
&& *ptr
)
2028 /* Add the last line */
2029 add_text_with_paraformat_to_control(text
, ptr
,
2030 len
- (ptr
- str
), &parFmt
);
2031 add_unformatted_text_to_control(text
, &nl
, 1);
2033 } while (linebreak
);
2036 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
2037 add_unformatted_text_to_control(text
, &nl
, 1);
2042 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
2043 (strlen(oid
) + 1) * sizeof(WCHAR
));
2050 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
2053 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
2055 add_unformatted_text_to_control(text
, &nl
, 1);
2056 HeapFree(GetProcessHeap(), 0, oidW
);
2061 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
2062 BOOL
*anyUsageAdded
)
2064 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
2066 CHARFORMATW charFmt
;
2067 PCERT_EXTENSION policyExt
;
2068 if (!*anyUsageAdded
)
2072 parFmt
.cbSize
= sizeof(parFmt
);
2073 parFmt
.dwMask
= PFM_STARTINDENT
;
2074 parFmt
.dxStartIndent
= MY_INDENT
;
2075 add_string_resource_with_paraformat_to_control(text
,
2076 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2077 add_unformatted_text_to_control(text
, &nl
, 1);
2078 *anyUsageAdded
= TRUE
;
2080 memset(&charFmt
, 0, sizeof(charFmt
));
2081 charFmt
.cbSize
= sizeof(charFmt
);
2082 charFmt
.dwMask
= CFM_BOLD
;
2083 charFmt
.dwEffects
= 0;
2084 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2085 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
2086 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
2088 CERT_POLICIES_INFO
*policies
;
2091 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
2092 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2093 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2097 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
2101 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2102 add_local_oid_text_to_control(text
,
2103 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2104 pszPolicyQualifierId
);
2106 LocalFree(policies
);
2110 add_oid_text_to_control(text
, any_app_policy
);
2113 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
2114 BOOL
*anyUsageAdded
)
2118 BOOL badUsages
= FALSE
;
2120 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
2122 CHARFORMATW charFmt
;
2123 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
2124 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
2128 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
2132 if (!*anyUsageAdded
)
2136 parFmt
.cbSize
= sizeof(parFmt
);
2137 parFmt
.dwMask
= PFM_STARTINDENT
;
2138 parFmt
.dxStartIndent
= MY_INDENT
;
2139 add_string_resource_with_paraformat_to_control(text
,
2140 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2141 add_unformatted_text_to_control(text
, &nl
, 1);
2142 *anyUsageAdded
= TRUE
;
2144 memset(&charFmt
, 0, sizeof(charFmt
));
2145 charFmt
.cbSize
= sizeof(charFmt
);
2146 charFmt
.dwMask
= CFM_BOLD
;
2147 charFmt
.dwEffects
= 0;
2148 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
2150 if (!usage
->cUsageIdentifier
)
2151 add_oid_text_to_control(text
, any_cert_policy
);
2153 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2154 add_local_oid_text_to_control(text
,
2155 usage
->rgpszUsageIdentifier
[i
]);
2159 HeapFree(GetProcessHeap(), 0, usage
);
2169 static void set_policy_text(HWND text
,
2170 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2172 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
2173 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
2175 if (pCertViewInfo
->cPurposes
)
2179 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
2181 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
2182 includeCertUsages
= TRUE
;
2183 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
2184 szOID_ANY_APPLICATION_POLICY
))
2185 includeAppUsages
= TRUE
;
2191 includeAppUsages
= includeCertUsages
= TRUE
;
2192 if (includeAppUsages
)
2193 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
2194 if (includeCertUsages
)
2195 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
2201 parFmt
.cbSize
= sizeof(parFmt
);
2202 parFmt
.dwMask
= PFM_STARTINDENT
;
2203 parFmt
.dxStartIndent
= MY_INDENT
;
2204 add_string_resource_with_paraformat_to_control(text
,
2205 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
2209 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
2212 CRYPT_OBJID_BLOB
*ret
= NULL
;
2215 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
2219 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2220 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2221 pszPolicyQualifierId
, policyOid
))
2222 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2228 static WCHAR
*get_cps_str_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2230 LPWSTR qualifierStr
= NULL
;
2231 CERT_NAME_VALUE
*qualifierValue
;
2234 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
2235 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2236 &qualifierValue
, &size
))
2238 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
2239 &qualifierValue
->Value
, NULL
, 0);
2240 qualifierStr
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
2242 CertRDNValueToStrW(qualifierValue
->dwValueType
,
2243 &qualifierValue
->Value
, qualifierStr
, size
);
2244 LocalFree(qualifierValue
);
2246 return qualifierStr
;
2249 static WCHAR
*get_user_notice_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2252 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
2255 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
2256 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
2257 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2258 &qualifierValue
, &size
))
2260 str
= HeapAlloc(GetProcessHeap(), 0,
2261 (strlenW(qualifierValue
->pszDisplayText
) + 1) * sizeof(WCHAR
));
2263 strcpyW(str
, qualifierValue
->pszDisplayText
);
2264 LocalFree(qualifierValue
);
2269 struct IssuerStatement
2275 static void set_issuer_statement(HWND hwnd
,
2276 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2278 PCERT_EXTENSION policyExt
;
2280 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
2281 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
2282 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
2283 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
2285 CERT_POLICIES_INFO
*policies
;
2288 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
2289 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2290 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2292 CRYPT_OBJID_BLOB
*qualifier
;
2293 LPWSTR cps
= NULL
, userNotice
= NULL
;
2295 if ((qualifier
= find_policy_qualifier(policies
,
2296 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
2297 cps
= get_cps_str_from_qualifier(qualifier
);
2298 if ((qualifier
= find_policy_qualifier(policies
,
2299 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
2300 userNotice
= get_user_notice_from_qualifier(qualifier
);
2301 if (cps
|| userNotice
)
2303 struct IssuerStatement
*issuerStatement
=
2304 HeapAlloc(GetProcessHeap(), 0, sizeof(struct IssuerStatement
));
2306 if (issuerStatement
)
2308 issuerStatement
->cps
= cps
;
2309 issuerStatement
->userNotice
= userNotice
;
2310 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
2311 SetWindowLongPtrW(hwnd
, DWLP_USER
,
2312 (ULONG_PTR
)issuerStatement
);
2315 LocalFree(policies
);
2320 static void set_cert_info(HWND hwnd
,
2321 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2323 CHARFORMATW charFmt
;
2325 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
2326 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
2327 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2328 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
2329 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
2330 pCertViewInfo
->idxCounterSigner
);
2331 CRYPT_PROVIDER_CERT
*root
=
2332 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
2334 if (!provSigner
->pChainContext
||
2335 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2336 CERT_TRUST_IS_PARTIAL_CHAIN
))
2337 add_icon_to_control(icon
, IDB_CERT_WARNING
);
2338 else if (!root
->fTrustedRoot
)
2339 add_icon_to_control(icon
, IDB_CERT_ERROR
);
2341 add_icon_to_control(icon
, IDB_CERT
);
2343 memset(&charFmt
, 0, sizeof(charFmt
));
2344 charFmt
.cbSize
= sizeof(charFmt
);
2345 charFmt
.dwMask
= CFM_BOLD
;
2346 charFmt
.dwEffects
= CFE_BOLD
;
2347 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2348 /* FIXME: vertically center text */
2349 parFmt
.cbSize
= sizeof(parFmt
);
2350 parFmt
.dwMask
= PFM_STARTINDENT
;
2351 parFmt
.dxStartIndent
= MY_INDENT
;
2352 add_string_resource_with_paraformat_to_control(text
,
2353 IDS_CERTIFICATEINFORMATION
, &parFmt
);
2355 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
2356 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2357 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
2358 add_string_resource_with_paraformat_to_control(text
,
2359 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
2360 else if (!provSigner
->pChainContext
||
2361 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2362 CERT_TRUST_IS_PARTIAL_CHAIN
))
2363 add_string_resource_with_paraformat_to_control(text
,
2364 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
2365 else if (!root
->fTrustedRoot
)
2367 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
2368 add_string_resource_with_paraformat_to_control(text
,
2369 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
2371 add_string_resource_with_paraformat_to_control(text
,
2372 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
2376 set_policy_text(text
, pCertViewInfo
);
2377 set_issuer_statement(hwnd
, pCertViewInfo
);
2381 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
2382 DWORD nameFlags
, int heading
)
2385 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2386 CHARFORMATW charFmt
;
2389 memset(&charFmt
, 0, sizeof(charFmt
));
2390 charFmt
.cbSize
= sizeof(charFmt
);
2391 charFmt
.dwMask
= CFM_BOLD
;
2392 charFmt
.dwEffects
= CFE_BOLD
;
2393 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2394 parFmt
.cbSize
= sizeof(parFmt
);
2395 parFmt
.dwMask
= PFM_STARTINDENT
;
2396 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2397 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
2398 charFmt
.dwEffects
= 0;
2399 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2400 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2402 add_unformatted_text_to_control(text
, &nl
, 1);
2403 add_unformatted_text_to_control(text
, &nl
, 1);
2404 add_unformatted_text_to_control(text
, &nl
, 1);
2408 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
2410 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
2414 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
2415 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2416 FileTimeToSystemTime(fileTime
, &sysTime
);
2417 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
2418 sizeof(date
) / sizeof(date
[0]));
2419 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
2422 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
2425 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2426 CHARFORMATW charFmt
;
2429 memset(&charFmt
, 0, sizeof(charFmt
));
2430 charFmt
.cbSize
= sizeof(charFmt
);
2431 charFmt
.dwMask
= CFM_BOLD
;
2432 charFmt
.dwEffects
= CFE_BOLD
;
2433 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2434 parFmt
.cbSize
= sizeof(parFmt
);
2435 parFmt
.dwMask
= PFM_STARTINDENT
;
2436 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2437 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
2439 charFmt
.dwEffects
= 0;
2440 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2441 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
2442 charFmt
.dwEffects
= CFE_BOLD
;
2443 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2444 add_string_resource_to_control(text
, IDS_VALID_TO
);
2445 charFmt
.dwEffects
= 0;
2446 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2447 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
2448 add_unformatted_text_to_control(text
, &nl
, 1);
2451 static void set_general_info(HWND hwnd
,
2452 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2454 set_cert_info(hwnd
, pCertViewInfo
);
2455 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
2456 IDS_SUBJECT_HEADING
);
2457 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
2458 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
2459 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
2462 static LRESULT CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2467 struct IssuerStatement
*issuerStatement
;
2472 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
2473 issuerStatement
= (struct IssuerStatement
*)lp
;
2474 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
2475 strlenW(issuerStatement
->userNotice
));
2476 if (issuerStatement
->cps
)
2477 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
2479 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
2485 EndDialog(hwnd
, IDOK
);
2490 IBindCtx
*bctx
= NULL
;
2493 CreateBindCtx(0, &bctx
);
2494 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2495 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
2496 HLNF_OPENINNEWWINDOW
, 0);
2497 IBindCtx_Release(bctx
);
2505 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
2507 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
2508 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
2511 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2514 PROPSHEETPAGEW
*page
;
2515 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2517 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2522 page
= (PROPSHEETPAGEW
*)lp
;
2523 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
2524 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
2525 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
2526 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
2527 set_general_info(hwnd
, pCertViewInfo
);
2532 case IDC_ADDTOSTORE
:
2533 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
2535 case IDC_ISSUERSTATEMENT
:
2537 struct IssuerStatement
*issuerStatement
=
2538 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2540 if (issuerStatement
)
2542 if (issuerStatement
->userNotice
)
2543 show_user_notice(hwnd
, issuerStatement
);
2544 else if (issuerStatement
->cps
)
2546 IBindCtx
*bctx
= NULL
;
2548 CreateBindCtx(0, &bctx
);
2549 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
2550 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
2551 IBindCtx_Release(bctx
);
2562 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
2563 PROPSHEETPAGEW
*page
)
2565 struct IssuerStatement
*issuerStatement
;
2571 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2572 if (issuerStatement
)
2574 HeapFree(GetProcessHeap(), 0, issuerStatement
->cps
);
2575 HeapFree(GetProcessHeap(), 0, issuerStatement
->userNotice
);
2576 HeapFree(GetProcessHeap(), 0, issuerStatement
);
2583 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2584 PROPSHEETPAGEW
*page
)
2586 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2587 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2588 page
->dwFlags
= PSP_USECALLBACK
;
2589 page
->pfnCallback
= general_callback_proc
;
2590 page
->hInstance
= hInstance
;
2591 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
2592 page
->pfnDlgProc
= general_dlg_proc
;
2593 page
->lParam
= (LPARAM
)pCertViewInfo
;
2596 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
2598 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
2600 static const WCHAR fmt
[] = { 'V','%','d',0 };
2601 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, 12 * sizeof(WCHAR
));
2604 sprintfW(buf
, fmt
, cert
->pCertInfo
->dwVersion
);
2608 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
2610 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, (cb
* 3 + 1) * sizeof(WCHAR
));
2614 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2618 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
2619 sprintfW(ptr
, fmt
, ((BYTE
*)pb
)[i
]);
2624 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
2626 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
2627 cert
->pCertInfo
->SerialNumber
.cbData
);
2630 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
2632 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2633 CERT_NAME_ISSUER_FLAG
);
2636 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
2639 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
2640 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, NULL
, 0);
2644 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2646 CertNameToStrW(X509_ASN_ENCODING
, name
,
2647 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, str
, len
);
2652 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
2654 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
2657 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
2659 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2662 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
2664 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
2667 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
2669 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
2674 /* FIXME: format isn't quite right, want time too */
2675 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
,
2676 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2677 FileTimeToSystemTime(fileTime
, &sysTime
);
2678 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
2681 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2683 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
2689 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
2691 return format_long_date(&cert
->pCertInfo
->NotBefore
);
2694 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
2696 return format_long_date(&cert
->pCertInfo
->NotAfter
);
2699 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
2701 PCCRYPT_OID_INFO oidInfo
;
2704 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2705 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
2708 WCHAR fmt
[MAX_STRING_LEN
];
2710 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
,
2711 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 buf
= HeapAlloc(GetProcessHeap(), 0,
2723 (strlenW(fmt
) + strlenW(oidInfo
->pwszName
) +
2724 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8)
2727 sprintfW(buf
, fmt
, oidInfo
->pwszName
,
2728 CertGetPublicKeyLength(X509_ASN_ENCODING
,
2729 &cert
->pCertInfo
->SubjectPublicKeyInfo
));
2735 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
2737 return format_hex_string(
2738 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
2739 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
2742 struct field_value_data
;
2745 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2746 BOOL
*pfPropertiesChanged
;
2748 struct field_value_data
*fields
;
2751 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
2753 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
2755 struct field_value_data
2757 create_detailed_value_func create
;
2758 LPWSTR detailed_value
;
2762 static void add_field_value_data(struct detail_data
*data
,
2763 create_detailed_value_func create
, void *param
)
2766 data
->fields
= HeapReAlloc(GetProcessHeap(), 0, data
->fields
,
2767 (data
->cFields
+ 1) * sizeof(struct field_value_data
));
2769 data
->fields
= HeapAlloc(GetProcessHeap(), 0,
2770 sizeof(struct field_value_data
));
2773 data
->fields
[data
->cFields
].create
= create
;
2774 data
->fields
[data
->cFields
].detailed_value
= NULL
;
2775 data
->fields
[data
->cFields
].param
= param
;
2780 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2781 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2784 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2786 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
2789 item
.pszText
= field
;
2790 item
.lParam
= (LPARAM
)data
;
2791 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2794 item
.pszText
= value
;
2796 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
2798 add_field_value_data(data
, create
, param
);
2801 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2802 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2804 WCHAR buf
[MAX_STRING_LEN
];
2806 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2807 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
2813 field_format_func format
;
2814 create_detailed_value_func create_detailed_value
;
2817 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
2818 const struct v1_field
*field
)
2820 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
2824 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
2825 field
->create_detailed_value
, NULL
);
2826 HeapFree(GetProcessHeap(), 0, val
);
2830 static const struct v1_field v1_fields
[] = {
2831 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
2832 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
2833 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
2834 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
2835 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
2836 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
2837 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
2838 field_format_detailed_public_key
}
2841 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
2844 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2846 /* The last item in v1_fields is the public key, which is not in the loop
2847 * because it's a special case.
2849 for (i
= 0; i
< sizeof(v1_fields
) / sizeof(v1_fields
[0]) - 1; i
++)
2850 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2851 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
2852 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2855 static WCHAR
*crypt_format_extension(const CERT_EXTENSION
*ext
, DWORD formatStrType
)
2860 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2861 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
2863 str
= HeapAlloc(GetProcessHeap(), 0, size
);
2864 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2865 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
2870 static WCHAR
*field_format_extension_hex_with_ascii(const CERT_EXTENSION
*ext
)
2874 if (ext
->Value
.cbData
)
2876 /* The output is formatted as:
2877 * <hex bytes> <ascii bytes>\n
2878 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
2879 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
2880 * the byte is not printable.
2881 * So, for example, the extension value consisting of the following
2883 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
2884 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
2886 * 30 14 31 12 30 10 06 03 0.1.0...
2887 * 55 04 03 13 09 4a 75 61 U....Jua
2888 * 6e 20 4c 61 6e 67 n Lang
2889 * The allocation size therefore requires:
2890 * - 4 characters per character in an 8-byte line
2891 * (2 for the hex format, one for the space, one for the ASCII value)
2892 * - 3 more characters per 8-byte line (two spaces and a newline)
2893 * - 1 character for the terminating nul
2894 * FIXME: should use a fixed-width font for this
2896 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
2898 str
= HeapAlloc(GetProcessHeap(), 0,
2899 (lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
2902 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2906 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
2908 /* Output as hex bytes first */
2909 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
2910 sprintfW(ptr
, fmt
, ext
->Value
.pbData
[j
]);
2911 /* Pad the hex output with spaces for alignment */
2912 if (j
== ext
->Value
.cbData
&& j
% 8)
2914 static const WCHAR pad
[] = { ' ',' ',' ' };
2916 for (; j
% 8; j
++, ptr
+= sizeof(pad
) / sizeof(pad
[0]))
2917 memcpy(ptr
, pad
, sizeof(pad
));
2919 /* The last sprintfW included a space, so just insert one
2920 * more space between the hex bytes and the ASCII output
2923 /* Output as ASCII bytes */
2924 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
2926 if (isprintW(ext
->Value
.pbData
[j
]) &&
2927 !isspaceW(ext
->Value
.pbData
[j
]))
2928 *ptr
= ext
->Value
.pbData
[j
];
2940 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
2942 PCERT_EXTENSION ext
= param
;
2943 LPWSTR str
= crypt_format_extension(ext
,
2944 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
2947 str
= field_format_extension_hex_with_ascii(ext
);
2951 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
2952 PCERT_EXTENSION ext
)
2954 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2956 LPWSTR val
= crypt_format_extension(ext
, 0);
2959 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
2960 val
, field_format_detailed_extension
, ext
);
2963 DWORD len
= strlen(ext
->pszObjId
);
2964 LPWSTR oidW
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
2970 for (i
= 0; i
<= len
; i
++)
2971 oidW
[i
] = ext
->pszObjId
[i
];
2972 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
2973 field_format_detailed_extension
, ext
);
2974 HeapFree(GetProcessHeap(), 0, oidW
);
2977 HeapFree(GetProcessHeap(), 0, val
);
2980 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
2983 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2985 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2986 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
2989 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
2992 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2994 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2995 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
2996 add_cert_extension_detail(hwnd
, data
,
2997 &cert
->pCertInfo
->rgExtension
[i
]);
3000 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
3002 struct prop_id_to_string_id
3006 BOOL prop_is_string
;
3007 prop_to_value_func prop_to_value
;
3010 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
3014 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
3015 ext
.fCritical
= FALSE
;
3016 ext
.Value
.pbData
= pb
;
3017 ext
.Value
.cbData
= cb
;
3018 return crypt_format_extension(&ext
, 0);
3021 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
3022 * disabled for read-only certificates, but native doesn't appear to do that.
3024 static const struct prop_id_to_string_id prop_id_map
[] = {
3025 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
3026 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
3027 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
3028 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
3029 format_enhanced_key_usage_value
},
3032 static void add_properties(HWND hwnd
, struct detail_data
*data
)
3035 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
3037 for (i
= 0; i
< sizeof(prop_id_map
) / sizeof(prop_id_map
[0]); i
++)
3041 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
3047 /* FIXME: MS adds a separate value for the signature hash
3050 pb
= HeapAlloc(GetProcessHeap(), 0, cb
);
3053 if (CertGetCertificateContextProperty(cert
,
3054 prop_id_map
[i
].prop
, pb
, &cb
))
3056 if (prop_id_map
[i
].prop_is_string
)
3059 /* Don't double-free pb */
3063 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
3065 HeapFree(GetProcessHeap(), 0, pb
);
3067 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
3073 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
3075 add_v1_fields(hwnd
, data
);
3076 add_all_extensions(hwnd
, data
);
3077 add_properties(hwnd
, data
);
3080 struct selection_list_item
3083 add_fields_func add
;
3086 const struct selection_list_item listItems
[] = {
3087 { IDS_FIELDS_ALL
, add_all_fields
},
3088 { IDS_FIELDS_V1
, add_v1_fields
},
3089 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
3090 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
3091 { IDS_FIELDS_PROPERTIES
, add_properties
},
3094 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
3096 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3097 WCHAR buf
[MAX_STRING_LEN
];
3100 for (i
= 0; i
< sizeof(listItems
) / sizeof(listItems
[0]); i
++)
3104 LoadStringW(hInstance
, listItems
[i
].id
, buf
,
3105 sizeof(buf
) / sizeof(buf
[0]));
3106 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
3107 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
3109 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
3112 static void create_listview_columns(HWND hwnd
)
3114 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3116 WCHAR buf
[MAX_STRING_LEN
];
3119 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
3120 GetWindowRect(lv
, &rc
);
3121 LoadStringW(hInstance
, IDS_FIELD
, buf
, sizeof(buf
) / sizeof(buf
[0]));
3122 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
3123 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
3124 column
.pszText
= buf
;
3125 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3126 LoadStringW(hInstance
, IDS_VALUE
, buf
, sizeof(buf
) / sizeof(buf
[0]));
3127 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
3130 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
3132 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3134 if (sel
>= 0 && sel
< sizeof(listItems
) / sizeof(listItems
[0]))
3136 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
3137 listItems
[sel
].add(list
, data
);
3141 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
3143 create_show_list(hwnd
, data
);
3144 create_listview_columns(hwnd
);
3145 set_fields_selection(hwnd
, data
, 0);
3148 static void add_purpose(HWND hwnd
, LPCSTR oid
)
3150 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3151 PCRYPT_OID_INFO info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3152 sizeof(CRYPT_OID_INFO
));
3156 char *oidCopy
= HeapAlloc(GetProcessHeap(), 0, strlen(oid
) + 1);
3162 strcpy(oidCopy
, oid
);
3163 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
3164 info
->pszOID
= oidCopy
;
3165 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
3166 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
3167 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3168 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3170 item
.lParam
= (LPARAM
)info
;
3171 item
.pszText
= oidCopy
;
3172 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3175 HeapFree(GetProcessHeap(), 0, info
);
3179 static BOOL
is_valid_oid(LPCSTR oid
)
3183 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
3185 else if (oid
[1] != '.')
3192 BOOL expectNum
= TRUE
;
3194 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
3200 else if (*(ptr
+ 1) == '.')
3207 else if (!(*(ptr
+ 1)))
3217 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
3219 return find_oid_in_list(GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
), oid
)
3223 #define MAX_PURPOSE 255
3225 static LRESULT CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
3226 WPARAM wp
, LPARAM lp
)
3229 char buf
[MAX_PURPOSE
+ 1];
3234 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
3236 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
3237 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
3243 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
3245 /* Show/hide scroll bar on description depending on how much
3248 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
3249 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3251 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3258 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
,
3259 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3262 /* An empty purpose is the same as cancelling */
3263 EndDialog(hwnd
, IDCANCEL
);
3266 else if (!is_valid_oid(buf
))
3268 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3270 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
,
3271 sizeof(error
) / sizeof(error
[0]));
3272 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3273 sizeof(title
) / sizeof(title
[0]));
3274 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
3276 else if (is_oid_in_list(
3277 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
3279 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3281 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
,
3282 error
, sizeof(error
) / sizeof(error
[0]));
3283 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3284 sizeof(title
) / sizeof(title
[0]));
3285 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
3289 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3291 add_purpose(parent
, buf
);
3292 EndDialog(hwnd
, wp
);
3297 EndDialog(hwnd
, wp
);
3308 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
3313 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
3315 name
= HeapAlloc(GetProcessHeap(), 0, cb
);
3318 if (!CertGetCertificateContextProperty(cert
, prop
, name
, &cb
))
3320 HeapFree(GetProcessHeap(), 0, name
);
3328 static void redraw_states(HWND list
, BOOL enabled
)
3330 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
3332 for (i
= 0; i
< items
; i
++)
3334 BOOL change
= FALSE
;
3337 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
3338 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
3339 * to be a handy macro for it.
3344 if (state
== CheckBitmapIndexDisabledChecked
)
3346 state
= CheckBitmapIndexChecked
;
3349 if (state
== CheckBitmapIndexDisabledUnchecked
)
3351 state
= CheckBitmapIndexUnchecked
;
3357 if (state
== CheckBitmapIndexChecked
)
3359 state
= CheckBitmapIndexDisabledChecked
;
3362 if (state
== CheckBitmapIndexUnchecked
)
3364 state
= CheckBitmapIndexDisabledUnchecked
;
3372 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
3373 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3374 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
3380 PurposeEnableAll
= 0,
3382 PurposeEnableSelected
3385 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
3387 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3391 case PurposeEnableAll
:
3392 case PurposeDisableAll
:
3393 EnableWindow(lv
, FALSE
);
3394 redraw_states(lv
, FALSE
);
3395 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
3397 case PurposeEnableSelected
:
3398 EnableWindow(lv
, TRUE
);
3399 redraw_states(lv
, TRUE
);
3400 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
3404 struct edit_cert_data
3406 PCCERT_CONTEXT cert
;
3407 BOOL
*pfPropertiesChanged
;
3408 HIMAGELIST imageList
;
3411 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
3413 PCCERT_CONTEXT cert
= data
->cert
;
3414 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3415 PCERT_ENHKEY_USAGE usage
;
3419 PurposeSelection purposeSelection
= PurposeEnableAll
;
3421 GetWindowRect(lv
, &rc
);
3422 column
.mask
= LVCF_WIDTH
;
3423 column
.cx
= rc
.right
- rc
.left
;
3424 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3425 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
3427 /* Get enhanced key usage. Have to check for a property and an extension
3428 * separately, because CertGetEnhancedKeyUsage will succeed and return an
3429 * empty usage if neither is set. Unfortunately an empty usage implies
3430 * no usage is allowed, so we have to distinguish between the two cases.
3432 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
3435 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3436 if (!CertGetEnhancedKeyUsage(cert
,
3437 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3439 HeapFree(GetProcessHeap(), 0, usage
);
3442 else if (usage
->cUsageIdentifier
)
3443 purposeSelection
= PurposeEnableSelected
;
3445 purposeSelection
= PurposeDisableAll
;
3447 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
3450 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3451 if (!CertGetEnhancedKeyUsage(cert
,
3452 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3454 HeapFree(GetProcessHeap(), 0, usage
);
3457 else if (usage
->cUsageIdentifier
)
3458 purposeSelection
= PurposeEnableAll
;
3460 purposeSelection
= PurposeDisableAll
;
3464 purposeSelection
= PurposeEnableAll
;
3471 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
3473 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
3474 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
3477 add_known_usage(lv
, info
, CheckBitmapIndexDisabledChecked
);
3479 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
3481 HeapFree(GetProcessHeap(), 0, usage
);
3484 add_known_usages_to_list(lv
, CheckBitmapIndexDisabledChecked
);
3485 select_purposes(hwnd
, purposeSelection
);
3486 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
3490 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
3492 PCCERT_CONTEXT cert
= data
->cert
;
3495 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
3497 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
3499 HeapFree(GetProcessHeap(), 0, str
);
3501 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
3503 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
3505 HeapFree(GetProcessHeap(), 0, str
);
3507 show_cert_usages(hwnd
, data
);
3510 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
3513 if (str
&& strlenW(str
))
3515 CRYPT_DATA_BLOB blob
;
3517 blob
.pbData
= (BYTE
*)str
;
3518 blob
.cbData
= (strlenW(str
) + 1) * sizeof(WCHAR
);
3519 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
3522 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
3525 #define WM_REFRESH_VIEW WM_USER + 0
3527 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
3529 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
3530 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
3534 #define MAX_FRIENDLY_NAME 40
3535 #define MAX_DESCRIPTION 255
3537 static void apply_general_changes(HWND hwnd
)
3539 WCHAR buf
[MAX_DESCRIPTION
+ 1];
3540 struct edit_cert_data
*data
=
3541 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3543 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
,
3544 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3545 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
3546 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
,
3547 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3548 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
3549 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
3551 /* Setting a NULL usage removes the enhanced key usage property. */
3552 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
3554 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
3556 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3558 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3560 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
3562 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3563 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3564 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
3567 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3569 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3570 for (i
= 0; i
< purposes
; i
++)
3573 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
3575 int state
= item
.state
>> 12;
3577 if (state
== CheckBitmapIndexChecked
)
3579 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
3581 if (usage
.cUsageIdentifier
)
3582 usage
.rgpszUsageIdentifier
=
3583 HeapReAlloc(GetProcessHeap(), 0,
3584 usage
.rgpszUsageIdentifier
,
3585 (usage
.cUsageIdentifier
+ 1) * sizeof(LPSTR
));
3587 usage
.rgpszUsageIdentifier
=
3588 HeapAlloc(GetProcessHeap(), 0, sizeof(LPSTR
));
3589 if (usage
.rgpszUsageIdentifier
)
3590 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
3591 (LPSTR
)info
->pszOID
;
3595 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3596 HeapFree(GetProcessHeap(), 0, usage
.rgpszUsageIdentifier
);
3598 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
3599 if (data
->pfPropertiesChanged
)
3600 *data
->pfPropertiesChanged
= TRUE
;
3603 static LRESULT CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
3604 WPARAM wp
, LPARAM lp
)
3606 PROPSHEETPAGEW
*page
;
3608 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3614 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3615 struct detail_data
*detailData
;
3616 struct edit_cert_data
*editData
;
3618 page
= (PROPSHEETPAGEW
*)lp
;
3619 detailData
= (struct detail_data
*)page
->lParam
;
3620 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
3621 MAX_FRIENDLY_NAME
, 0);
3622 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
3623 ShowScrollBar(description
, SB_VERT
, FALSE
);
3624 editData
= HeapAlloc(GetProcessHeap(), 0,
3625 sizeof(struct edit_cert_data
));
3628 editData
->imageList
= ImageList_Create(16, 16,
3629 ILC_COLOR4
| ILC_MASK
, 4, 0);
3630 if (editData
->imageList
)
3633 COLORREF backColor
= RGB(255, 0, 255);
3635 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
3636 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
3638 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
3640 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
3641 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
3642 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
3643 set_general_cert_properties(hwnd
, editData
);
3649 NMHDR
*hdr
= (NMHDR
*)lp
;
3655 nm
= (NMITEMACTIVATE
*)lp
;
3656 toggle_usage(hwnd
, nm
->iItem
);
3657 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3660 apply_general_changes(hwnd
);
3669 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3670 if (LOWORD(wp
) == IDC_DESCRIPTION
)
3672 /* Show/hide scroll bar on description depending on how much
3675 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3676 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3678 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3684 case IDC_ADD_PURPOSE
:
3685 if (DialogBoxParamW(hInstance
,
3686 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
3687 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
3688 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3690 case IDC_ENABLE_ALL_PURPOSES
:
3691 case IDC_DISABLE_ALL_PURPOSES
:
3692 case IDC_ENABLE_SELECTED_PURPOSES
:
3693 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3694 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
3704 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
3705 PROPSHEETPAGEW
*page
)
3709 struct edit_cert_data
*data
;
3714 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3715 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3716 for (i
= 0; i
< cItem
; i
++)
3720 item
.mask
= LVIF_PARAM
;
3723 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
3725 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
3727 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
3729 HeapFree(GetProcessHeap(), 0, (LPSTR
)info
->pszOID
);
3730 HeapFree(GetProcessHeap(), 0, info
);
3734 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3737 ImageList_Destroy(data
->imageList
);
3738 HeapFree(GetProcessHeap(), 0, data
);
3745 static void show_edit_cert_properties_dialog(HWND parent
,
3746 struct detail_data
*data
)
3748 PROPSHEETHEADERW hdr
;
3749 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
3751 TRACE("(%p)\n", data
);
3753 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
3754 page
.dwSize
= sizeof(page
);
3755 page
.dwFlags
= PSP_USECALLBACK
;
3756 page
.pfnCallback
= cert_properties_general_callback
;
3757 page
.hInstance
= hInstance
;
3758 page
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
3759 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
3760 page
.lParam
= (LPARAM
)data
;
3762 memset(&hdr
, 0, sizeof(hdr
));
3763 hdr
.dwSize
= sizeof(hdr
);
3764 hdr
.hwndParent
= parent
;
3765 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
3766 hdr
.hInstance
= hInstance
;
3767 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
3768 hdr
.u3
.ppsp
= &page
;
3770 PropertySheetW(&hdr
);
3773 static void free_detail_fields(struct detail_data
*data
)
3777 for (i
= 0; i
< data
->cFields
; i
++)
3778 HeapFree(GetProcessHeap(), 0, data
->fields
[i
].detailed_value
);
3779 HeapFree(GetProcessHeap(), 0, data
->fields
);
3780 data
->fields
= NULL
;
3784 static void refresh_details_view(HWND hwnd
)
3786 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3788 struct detail_data
*data
;
3790 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3791 /* Actually, any index will do, since they all store the same data value */
3792 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
3793 free_detail_fields(data
);
3794 set_fields_selection(hwnd
, data
, curSel
);
3797 static LRESULT CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3800 PROPSHEETPAGEW
*page
;
3801 struct detail_data
*data
;
3803 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3808 page
= (PROPSHEETPAGEW
*)lp
;
3809 data
= (struct detail_data
*)page
->lParam
;
3810 create_cert_details_list(hwnd
, data
);
3811 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
3812 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
3813 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
3814 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
3819 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3821 nm
= (NMITEMACTIVATE
*)lp
;
3822 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
3823 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
3825 data
= (struct detail_data
*)nm
->lParam
;
3826 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
3828 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
3829 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
3831 if (data
->fields
[nm
->iItem
].create
)
3832 val
= data
->fields
[nm
->iItem
].create(
3833 data
->pCertViewInfo
->pCertContext
,
3834 data
->fields
[nm
->iItem
].param
);
3840 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
3841 item
.mask
= LVIF_TEXT
;
3843 item
.iItem
= nm
->iItem
;
3845 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
3849 /* Select all the text in the control, the next update will
3852 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
3853 add_unformatted_text_to_control(valueCtl
, val
,
3854 val
? strlenW(val
) : 0);
3856 HeapFree(GetProcessHeap(), 0, val
);
3866 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3867 CRYPTUI_WIZ_EXPORT_INFO info
;
3869 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, 0, 0);
3870 info
.dwSize
= sizeof(info
);
3871 info
.pwszExportFileName
= NULL
;
3872 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
3873 info
.u
.pCertContext
= data
->pCertViewInfo
->pCertContext
;
3875 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
3878 case IDC_EDITPROPERTIES
:
3880 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3883 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3884 /* Actually, any index will do, since they all store the same
3887 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
3889 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
3892 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
3893 refresh_details_view(hwnd
);
3897 case WM_REFRESH_VIEW
:
3898 refresh_details_view(hwnd
);
3904 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
3905 PROPSHEETPAGEW
*page
)
3907 struct detail_data
*data
;
3912 data
= (struct detail_data
*)page
->lParam
;
3913 free_detail_fields(data
);
3914 HeapFree(GetProcessHeap(), 0, data
);
3920 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3921 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
3924 struct detail_data
*data
= HeapAlloc(GetProcessHeap(), 0,
3925 sizeof(struct detail_data
));
3929 data
->pCertViewInfo
= pCertViewInfo
;
3930 data
->pfPropertiesChanged
= pfPropertiesChanged
;
3932 data
->fields
= NULL
;
3933 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3934 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3935 page
->dwFlags
= PSP_USECALLBACK
;
3936 page
->pfnCallback
= detail_callback
;
3937 page
->hInstance
= hInstance
;
3938 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
3939 page
->pfnDlgProc
= detail_dlg_proc
;
3940 page
->lParam
= (LPARAM
)data
;
3948 struct hierarchy_data
3950 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
3951 HIMAGELIST imageList
;
3955 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
3957 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3958 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3959 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3960 data
->pCertViewInfo
->idxCounterSigner
);
3962 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
3963 * therefore always even.
3965 if (index
== provSigner
->csCertChain
- 1)
3966 return (LPARAM
)data
;
3967 return index
<< 1 | 1;
3970 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
3972 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3973 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3974 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3975 data
->pCertViewInfo
->idxCounterSigner
);
3978 return provSigner
->csCertChain
- 1;
3982 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
3985 struct hierarchy_data
*data
= NULL
;
3986 HTREEITEM root
= NULL
;
3989 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
3990 TVGN_PARENT
, (LPARAM
)hItem
);
4000 item
.mask
= TVIF_PARAM
;
4002 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4003 data
= (struct hierarchy_data
*)item
.lParam
;
4008 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
4010 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
4013 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
4017 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
4019 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4020 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4021 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4022 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
4023 data
->pCertViewInfo
->idxCounterSigner
);
4025 HTREEITEM parent
= NULL
;
4027 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
4028 for (i
= provSigner
->csCertChain
; i
; i
--)
4032 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
4035 TVINSERTSTRUCTW tvis
;
4037 tvis
.hParent
= parent
;
4038 tvis
.hInsertAfter
= TVI_LAST
;
4039 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
4040 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
4041 tvis
.u
.item
.pszText
= name
;
4042 tvis
.u
.item
.state
= TVIS_EXPANDED
;
4043 tvis
.u
.item
.stateMask
= TVIS_EXPANDED
;
4045 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
4046 CERT_TRUST_IS_PARTIAL_CHAIN
))
4048 /* The root of the chain has a special case: if the chain is
4049 * a partial chain, the icon is a warning icon rather than an
4052 tvis
.u
.item
.iImage
= 2;
4054 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
4056 tvis
.u
.item
.iImage
= 0;
4058 tvis
.u
.item
.iImage
= 1;
4059 tvis
.u
.item
.iSelectedImage
= tvis
.u
.item
.iImage
;
4060 tvis
.u
.item
.lParam
= index_to_lparam(data
, i
- 1);
4061 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
4063 HeapFree(GetProcessHeap(), 0, name
);
4068 static void set_certificate_status(HWND hwnd
, const CRYPT_PROVIDER_CERT
*cert
)
4070 /* Select all the text in the control, the next update will replace it */
4071 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
4072 /* Set the highest priority error messages first. */
4073 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
4074 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
4075 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
4076 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
4077 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
4078 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
4079 else if (cert
->dwRevokedReason
)
4080 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
4082 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
4085 static void set_certificate_status_for_end_cert(HWND hwnd
,
4086 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
4088 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
4089 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4090 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
4091 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
4092 pCertViewInfo
->idxCounterSigner
);
4093 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
4094 pCertViewInfo
->idxCert
);
4096 set_certificate_status(status
, provCert
);
4099 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
4101 /* Disable view certificate button until a certificate is selected */
4102 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
4103 show_cert_chain(hwnd
, data
);
4104 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
4107 static void show_dialog_for_selected_cert(HWND hwnd
)
4109 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4111 struct hierarchy_data
*data
;
4114 memset(&item
, 0, sizeof(item
));
4115 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4116 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
,
4118 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4119 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4120 selection
= lparam_to_index(data
, item
.lParam
);
4123 CRYPT_PROVIDER_SGNR
*provSigner
;
4124 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4125 BOOL changed
= FALSE
;
4127 provSigner
= WTHelperGetProvSignerFromChain(
4128 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4129 data
->pCertViewInfo
->idxSigner
,
4130 data
->pCertViewInfo
->fCounterSigner
,
4131 data
->pCertViewInfo
->idxCounterSigner
);
4132 memset(&viewInfo
, 0, sizeof(viewInfo
));
4133 viewInfo
.dwSize
= sizeof(viewInfo
);
4134 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
4135 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
4136 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
4137 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
4138 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
4139 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
4140 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
4141 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
4142 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
4145 /* Delete the contents of the tree */
4146 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4147 /* Reinitialize the tree */
4148 show_cert_hierarchy(hwnd
, data
);
4153 static LRESULT CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4156 PROPSHEETPAGEW
*page
;
4157 struct hierarchy_data
*data
;
4159 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4161 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
4166 page
= (PROPSHEETPAGEW
*)lp
;
4167 data
= (struct hierarchy_data
*)page
->lParam
;
4168 show_cert_hierarchy(hwnd
, data
);
4177 case TVN_SELCHANGEDW
:
4179 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
4181 CRYPT_PROVIDER_SGNR
*provSigner
;
4183 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
4184 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
4185 provSigner
= WTHelperGetProvSignerFromChain(
4186 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4187 data
->pCertViewInfo
->idxSigner
,
4188 data
->pCertViewInfo
->fCounterSigner
,
4189 data
->pCertViewInfo
->idxCounterSigner
);
4190 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
4191 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
4192 &provSigner
->pasCertChain
[selection
]);
4196 show_dialog_for_selected_cert(hwnd
);
4197 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4206 case IDC_VIEWCERTIFICATE
:
4207 show_dialog_for_selected_cert(hwnd
);
4211 case WM_REFRESH_VIEW
:
4215 /* Get hierarchy data */
4216 memset(&item
, 0, sizeof(item
));
4217 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4218 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
4220 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4221 /* Delete the contents of the tree */
4222 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4223 /* Reinitialize the tree */
4224 show_cert_hierarchy(hwnd
, data
);
4231 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
4232 PROPSHEETPAGEW
*page
)
4234 struct hierarchy_data
*data
;
4239 data
= (struct hierarchy_data
*)page
->lParam
;
4240 ImageList_Destroy(data
->imageList
);
4241 HeapFree(GetProcessHeap(), 0, data
);
4247 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4248 PROPSHEETPAGEW
*page
)
4250 struct hierarchy_data
*data
= HeapAlloc(GetProcessHeap(), 0,
4251 sizeof(struct hierarchy_data
));
4256 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
4257 if (data
->imageList
)
4260 COLORREF backColor
= RGB(255, 0, 255);
4262 data
->pCertViewInfo
= pCertViewInfo
;
4263 data
->selectedCert
= 0xffffffff;
4265 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
4266 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
4268 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
4270 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
4271 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
4272 page
->dwFlags
= PSP_USECALLBACK
;
4273 page
->hInstance
= hInstance
;
4274 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
4275 page
->pfnDlgProc
= hierarchy_dlg_proc
;
4276 page
->lParam
= (LPARAM
)data
;
4277 page
->pfnCallback
= hierarchy_callback
;
4281 HeapFree(GetProcessHeap(), 0, data
);
4286 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
4291 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
4295 case PSCB_INITIALIZED
:
4296 /* Get cancel button's position.. */
4297 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
4298 topLeft
.x
= rc
.left
;
4300 ScreenToClient(hwnd
, &topLeft
);
4301 /* hide the cancel button.. */
4302 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
4303 /* get the OK button's size.. */
4304 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
4305 /* and move the OK button to the cancel button's original position. */
4306 MoveWindow(GetDlgItem(hwnd
, IDOK
), topLeft
.x
, topLeft
.y
,
4307 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, FALSE
);
4308 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
4314 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4315 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
4317 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
4319 PROPSHEETPAGEW
*pages
;
4321 HMODULE lib
= LoadLibraryW(riched
);
4323 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
4324 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4326 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4328 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
4331 PROPSHEETHEADERW hdr
;
4332 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
4335 memset(&hdr
, 0, sizeof(hdr
));
4336 hdr
.dwSize
= sizeof(hdr
);
4337 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
4338 hdr
.hInstance
= hInstance
;
4339 if (pCertViewInfo
->szTitle
)
4340 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
4342 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
4343 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
4344 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4346 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
4347 &pages
[hdr
.nPages
]))
4350 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4352 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
4355 /* Copy each additional page, and create the init dialog struct for it
4357 if (pCertViewInfo
->cPropSheetPages
)
4359 init
= HeapAlloc(GetProcessHeap(), 0,
4360 pCertViewInfo
->cPropSheetPages
*
4361 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
4364 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
4366 memcpy(&pages
[hdr
.nPages
+ i
],
4367 &pCertViewInfo
->rgPropSheetPages
[i
],
4368 sizeof(PROPSHEETPAGEW
));
4369 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
4370 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
4371 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
4373 if (pCertViewInfo
->nStartPage
& 0x8000)
4375 /* Start page index is relative to the number of default
4378 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
4381 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
4382 hdr
.nPages
= nPages
;
4386 SetLastError(ERROR_OUTOFMEMORY
);
4390 /* Ignore the relative flag if there aren't any additional pages */
4391 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
4398 hdr
.u3
.ppsp
= pages
;
4399 hdr
.pfnCallback
= cert_prop_sheet_proc
;
4400 l
= PropertySheetW(&hdr
);
4403 SetLastError(ERROR_CANCELLED
);
4407 HeapFree(GetProcessHeap(), 0, init
);
4408 HeapFree(GetProcessHeap(), 0, pages
);
4411 SetLastError(ERROR_OUTOFMEMORY
);
4416 /***********************************************************************
4417 * CryptUIDlgViewCertificateW (CRYPTUI.@)
4419 BOOL WINAPI
CryptUIDlgViewCertificateW(
4420 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
4422 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
4423 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4425 WINTRUST_CERT_INFO cert
;
4427 CRYPT_PROVIDER_SGNR
*signer
;
4428 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
4430 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
4432 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
4434 SetLastError(ERROR_INVALID_PARAMETER
);
4437 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
4438 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
4439 if (!viewInfo
.u
.hWVTStateData
)
4441 memset(&wvt
, 0, sizeof(wvt
));
4442 wvt
.cbStruct
= sizeof(wvt
);
4443 wvt
.dwUIChoice
= WTD_UI_NONE
;
4444 if (viewInfo
.dwFlags
&
4445 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
4446 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
4447 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
4448 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
4449 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
4450 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
4451 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
4452 memset(&cert
, 0, sizeof(cert
));
4453 cert
.cbStruct
= sizeof(cert
);
4454 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
4455 cert
.chStores
= viewInfo
.cStores
;
4456 cert
.pahStores
= viewInfo
.rghStores
;
4457 wvt
.u
.pCert
= &cert
;
4458 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
4459 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4460 viewInfo
.u
.pCryptProviderData
=
4461 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
4462 signer
= WTHelperGetProvSignerFromChain(
4463 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
4464 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
4469 viewInfo
.u
.pCryptProviderData
=
4470 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
4471 signer
= WTHelperGetProvSignerFromChain(
4472 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
4473 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
4474 viewInfo
.idxCounterSigner
);
4475 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
4480 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
4481 if (!viewInfo
.u
.hWVTStateData
)
4483 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
4484 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4490 /***********************************************************************
4491 * CryptUIDlgViewContext (CRYPTUI.@)
4493 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
4494 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
4498 TRACE("(%d, %p, %p, %s, %08x, %p)\n", dwContextType
, pvContext
, hwnd
,
4499 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
4501 switch (dwContextType
)
4503 case CERT_STORE_CERTIFICATE_CONTEXT
:
4505 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4507 memset(&viewInfo
, 0, sizeof(viewInfo
));
4508 viewInfo
.dwSize
= sizeof(viewInfo
);
4509 viewInfo
.hwndParent
= hwnd
;
4510 viewInfo
.szTitle
= pwszTitle
;
4511 viewInfo
.pCertContext
= pvContext
;
4512 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
4516 FIXME("unimplemented for context type %d\n", dwContextType
);
4517 SetLastError(E_INVALIDARG
);
4523 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
4524 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
4525 * should be a CA. If neither extension is present, returns
4526 * defaultIfNotSpecified.
4528 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
4530 BOOL isCA
= defaultIfNotSpecified
;
4531 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
4532 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4536 CERT_BASIC_CONSTRAINTS_INFO
*info
;
4539 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
4540 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
4541 NULL
, &info
, &size
))
4543 if (info
->SubjectType
.cbData
== 1)
4544 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
4550 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
4551 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4554 CERT_BASIC_CONSTRAINTS2_INFO info
;
4555 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4557 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
4558 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
4559 0, NULL
, &info
, &size
))
4566 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
4570 if (is_ca_cert(cert
, TRUE
))
4573 storeName
= addressBook
;
4574 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4575 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
4578 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
4585 SetLastError(E_INVALIDARG
);
4588 if (hDestCertStore
) store
= hDestCertStore
;
4591 if (!(store
= choose_store_for_cert(cert
)))
4593 WARN("unable to open certificate store\n");
4597 ret
= CertAddCertificateContextToStore(store
, cert
,
4598 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4599 if (!hDestCertStore
) CertCloseStore(store
, 0);
4603 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
4610 SetLastError(E_INVALIDARG
);
4613 if (hDestCertStore
) store
= hDestCertStore
;
4616 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4617 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
4619 WARN("unable to open certificate store\n");
4623 ret
= CertAddCRLContextToStore(store
, crl
,
4624 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4625 if (!hDestCertStore
) CertCloseStore(store
, 0);
4629 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
4636 SetLastError(E_INVALIDARG
);
4639 if (hDestCertStore
) store
= hDestCertStore
;
4642 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
4644 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4645 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
4647 WARN("unable to open certificate store\n");
4651 ret
= CertAddCTLContextToStore(store
, ctl
,
4652 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4653 if (!hDestCertStore
) CertCloseStore(store
, 0);
4657 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
4658 * CryptQueryObject, against the allowed types. Returns TRUE if the
4659 * type is allowed, FALSE otherwise.
4661 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
4666 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4667 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4671 case CERT_QUERY_CONTENT_CERT
:
4672 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4673 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
4675 case CERT_QUERY_CONTENT_CRL
:
4676 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4677 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
4679 case CERT_QUERY_CONTENT_CTL
:
4680 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4681 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
4684 /* The remaining types contain more than one type, so allow
4692 /* No allowed types specified, so any type is allowed */
4696 SetLastError(E_INVALIDARG
);
4701 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4704 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4706 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4713 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
4714 sizeof(title
) / sizeof(title
[0]));
4717 LoadStringW(hInstance
, warningID
, error
,
4718 sizeof(error
) / sizeof(error
[0]));
4719 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
4723 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
4725 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
4728 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
4733 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4734 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4736 PCCERT_CONTEXT cert
;
4741 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
4743 CertFreeCertificateContext(cert
);
4744 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
4747 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
4749 CertFreeCRLContext(crl
);
4750 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
4753 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
4755 CertFreeCTLContext(ctl
);
4756 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4763 SetLastError(E_INVALIDARG
);
4767 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4768 HCERTSTORE source
, HCERTSTORE dest
)
4772 if ((ret
= check_store_context_type(dwFlags
, source
)))
4774 PCCERT_CONTEXT cert
= NULL
;
4775 PCCRL_CONTEXT crl
= NULL
;
4776 PCCTL_CONTEXT ctl
= NULL
;
4779 cert
= CertEnumCertificatesInStore(source
, cert
);
4781 ret
= import_cert(cert
, dest
);
4782 } while (ret
&& cert
);
4784 crl
= CertEnumCRLsInStore(source
, crl
);
4786 ret
= import_crl(crl
, dest
);
4787 } while (ret
&& crl
);
4789 ctl
= CertEnumCTLsInStore(source
, ctl
);
4791 ret
= import_ctl(ctl
, dest
);
4792 } while (ret
&& ctl
);
4795 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
4799 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
4800 DWORD
*pContentType
)
4802 HCERTSTORE store
= NULL
;
4803 DWORD contentType
= 0, expectedContentTypeFlags
;
4806 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4807 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4809 expectedContentTypeFlags
=
4810 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4811 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4812 CERT_QUERY_CONTENT_FLAG_PFX
;
4813 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
4814 expectedContentTypeFlags
|=
4815 CERT_QUERY_CONTENT_FLAG_CERT
|
4816 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
4817 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
4818 expectedContentTypeFlags
|=
4819 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4820 CERT_QUERY_CONTENT_FLAG_CRL
;
4821 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
4822 expectedContentTypeFlags
|=
4823 CERT_QUERY_CONTENT_FLAG_CTL
|
4824 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
4827 expectedContentTypeFlags
=
4828 CERT_QUERY_CONTENT_FLAG_CERT
|
4829 CERT_QUERY_CONTENT_FLAG_CTL
|
4830 CERT_QUERY_CONTENT_FLAG_CRL
|
4831 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4832 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
4833 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
4834 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4835 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4836 CERT_QUERY_CONTENT_FLAG_PFX
;
4838 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
4839 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
4840 &contentType
, NULL
, &store
, NULL
, NULL
);
4842 *pContentType
= contentType
;
4846 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4847 LPCWSTR fileName
, HCERTSTORE dest
)
4852 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
4854 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
4855 CertCloseStore(source
, 0);
4862 struct ImportWizData
4866 LPCWSTR pwszWizardTitle
;
4867 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
4871 HCERTSTORE hDestCertStore
;
4877 static LRESULT CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4886 struct ImportWizData
*data
;
4887 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4888 WCHAR fontFace
[MAX_STRING_LEN
];
4889 HDC hDC
= GetDC(hwnd
);
4892 data
= (struct ImportWizData
*)page
->lParam
;
4893 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
4894 sizeof(fontFace
) / sizeof(fontFace
[0]));
4895 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
4896 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
4897 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
4898 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
4899 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4900 (WPARAM
)data
->titleFont
, TRUE
);
4901 ReleaseDC(hwnd
, hDC
);
4906 NMHDR
*hdr
= (NMHDR
*)lp
;
4911 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
4921 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
4923 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
4925 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
4926 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
4927 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
4928 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
4930 static const WCHAR filter_all
[] = { '*','.','*',0 };
4932 struct StringToFilter
4937 } import_filters
[] = {
4938 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
4939 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
4940 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
4941 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
4942 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
4943 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
4944 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
4947 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
4950 int len
, totalLen
= 2;
4951 LPWSTR filter
= NULL
, str
;
4953 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4955 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4956 (dwFlags
& import_filters
[i
].allowFlags
))
4958 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
4959 totalLen
+= len
+ strlenW(import_filters
[i
].filter
) + 2;
4962 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
4968 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4970 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4971 (dwFlags
& import_filters
[i
].allowFlags
))
4973 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
4975 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
4978 strcpyW(ptr
, import_filters
[i
].filter
);
4979 ptr
+= strlenW(import_filters
[i
].filter
) + 1;
4987 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
4993 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
4994 OPEN_EXISTING
, 0, NULL
);
4995 if (file
!= INVALID_HANDLE_VALUE
)
4997 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
4998 &data
->contentType
);
5002 warningID
= IDS_IMPORT_BAD_FORMAT
;
5003 else if (!check_store_context_type(data
->dwFlags
, source
))
5004 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
5007 data
->importSrc
.dwSubjectChoice
=
5008 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
5009 data
->importSrc
.u
.hCertStore
= source
;
5010 data
->freeSource
= TRUE
;
5015 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5022 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5024 LPWSTR msgBuf
, fullError
;
5026 if (data
->pwszWizardTitle
)
5027 pTitle
= data
->pwszWizardTitle
;
5030 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
5031 sizeof(title
) / sizeof(title
[0]));
5034 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
5035 sizeof(error
) / sizeof(error
[0]));
5037 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
5038 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
5039 fullError
= HeapAlloc(GetProcessHeap(), 0,
5040 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
5044 LPWSTR ptr
= fullError
;
5046 strcpyW(ptr
, error
);
5047 ptr
+= strlenW(error
);
5048 strcpyW(ptr
, fileName
);
5049 ptr
+= strlenW(fileName
);
5052 strcpyW(ptr
, msgBuf
);
5053 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
5054 HeapFree(GetProcessHeap(), 0, fullError
);
5061 static LRESULT CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5065 struct ImportWizData
*data
;
5071 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5073 data
= (struct ImportWizData
*)page
->lParam
;
5074 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5077 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5079 SendMessageW(fileNameEdit
, WM_SETTEXT
, 0, (LPARAM
)data
->fileName
);
5085 NMHDR
*hdr
= (NMHDR
*)lp
;
5090 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5091 PSWIZB_BACK
| PSWIZB_NEXT
);
5096 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5097 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
5099 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5102 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5103 IDS_IMPORT_EMPTY_FILE
);
5104 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5109 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
5110 (len
+ 1) * sizeof(WCHAR
));
5114 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
5116 if (!import_validate_filename(hwnd
, data
, fileName
))
5118 HeapFree(GetProcessHeap(), 0, fileName
);
5119 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5123 data
->fileName
= fileName
;
5134 case IDC_IMPORT_BROWSE_FILE
:
5137 WCHAR fileBuf
[MAX_PATH
];
5139 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5140 memset(&ofn
, 0, sizeof(ofn
));
5141 ofn
.lStructSize
= sizeof(ofn
);
5142 ofn
.hwndOwner
= hwnd
;
5143 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
5144 ofn
.lpstrFile
= fileBuf
;
5145 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
5147 if (GetOpenFileNameW(&ofn
))
5148 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
5149 0, (LPARAM
)ofn
.lpstrFile
);
5150 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
5159 static LRESULT CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5163 struct ImportWizData
*data
;
5169 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5171 data
= (struct ImportWizData
*)page
->lParam
;
5172 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5173 if (!data
->hDestCertStore
)
5175 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
,
5177 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5178 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5179 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
5183 WCHAR storeTitle
[MAX_STRING_LEN
];
5185 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), BM_CLICK
,
5187 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5188 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5189 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
),
5190 !(data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
));
5191 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5192 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5193 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5194 0, (LPARAM
)storeTitle
);
5200 NMHDR
*hdr
= (NMHDR
*)lp
;
5205 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5206 PSWIZB_BACK
| PSWIZB_NEXT
);
5211 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5212 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
5213 !data
->hDestCertStore
)
5215 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5216 IDS_IMPORT_SELECT_STORE
);
5217 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5228 case IDC_IMPORT_AUTO_STORE
:
5229 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5230 data
->autoDest
= TRUE
;
5231 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5232 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5234 case IDC_IMPORT_SPECIFY_STORE
:
5235 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5236 data
->autoDest
= FALSE
;
5237 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5238 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5240 case IDC_IMPORT_BROWSE_STORE
:
5242 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
5243 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
5244 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
5245 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
5248 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5249 selectInfo
.dwSize
= sizeof(selectInfo
);
5250 selectInfo
.parent
= hwnd
;
5251 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
5252 selectInfo
.pwszTitle
= NULL
;
5253 selectInfo
.pwszText
= NULL
;
5254 selectInfo
.pEnumData
= &enumData
;
5255 selectInfo
.pfnSelectedStoreCallback
= NULL
;
5256 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
5258 WCHAR storeTitle
[MAX_STRING_LEN
];
5260 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5261 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5262 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5263 0, (LPARAM
)storeTitle
);
5264 data
->hDestCertStore
= store
;
5265 data
->freeDest
= TRUE
;
5275 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
5277 WCHAR text
[MAX_STRING_LEN
];
5281 item
.mask
= LVIF_TEXT
;
5282 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5284 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
,
5285 sizeof(text
)/ sizeof(text
[0]));
5286 item
.pszText
= text
;
5287 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5290 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
,
5291 sizeof(text
)/ sizeof(text
[0]));
5293 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
,
5294 sizeof(text
)/ sizeof(text
[0]));
5295 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5296 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5298 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
,
5299 sizeof(text
)/ sizeof(text
[0]));
5300 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5301 switch (data
->contentType
)
5303 case CERT_QUERY_CONTENT_CERT
:
5304 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
5305 contentID
= IDS_IMPORT_CONTENT_CERT
;
5307 case CERT_QUERY_CONTENT_CRL
:
5308 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
5309 contentID
= IDS_IMPORT_CONTENT_CRL
;
5311 case CERT_QUERY_CONTENT_CTL
:
5312 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
5313 contentID
= IDS_IMPORT_CONTENT_CTL
;
5315 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
5316 contentID
= IDS_IMPORT_CONTENT_CMS
;
5318 case CERT_QUERY_CONTENT_FLAG_PFX
:
5319 contentID
= IDS_IMPORT_CONTENT_PFX
;
5322 contentID
= IDS_IMPORT_CONTENT_STORE
;
5325 LoadStringW(hInstance
, contentID
, text
, sizeof(text
)/ sizeof(text
[0]));
5327 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5330 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5332 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
5333 sizeof(text
)/ sizeof(text
[0]));
5334 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5336 item
.pszText
= data
->fileName
;
5337 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5341 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5342 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5346 switch (pImportSrc
->dwSubjectChoice
)
5348 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
5349 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
5350 pImportSrc
->u
.pwszFileName
, hDestCertStore
);
5352 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5353 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
5354 ret
= import_cert(pImportSrc
->u
.pCertContext
, hDestCertStore
);
5356 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5358 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5359 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
5360 ret
= import_crl(pImportSrc
->u
.pCRLContext
, hDestCertStore
);
5362 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5364 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5365 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
5366 ret
= import_ctl(pImportSrc
->u
.pCTLContext
, hDestCertStore
);
5368 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5370 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5371 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
5372 pImportSrc
->u
.hCertStore
, hDestCertStore
);
5375 WARN("unknown source type: %u\n", pImportSrc
->dwSubjectChoice
);
5376 SetLastError(E_INVALIDARG
);
5382 static LRESULT CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5386 struct ImportWizData
*data
;
5392 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5393 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5397 data
= (struct ImportWizData
*)page
->lParam
;
5398 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5399 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
5400 (WPARAM
)data
->titleFont
, TRUE
);
5401 GetWindowRect(lv
, &rc
);
5402 column
.mask
= LVCF_WIDTH
;
5403 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
5404 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
5405 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
5406 show_import_details(lv
, data
);
5411 NMHDR
*hdr
= (NMHDR
*)lp
;
5417 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5419 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5420 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
5421 show_import_details(lv
, data
);
5422 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5423 PSWIZB_BACK
| PSWIZB_FINISH
);
5429 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5430 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
5431 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
5433 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
5436 if (data
->pwszWizardTitle
)
5437 pTitle
= data
->pwszWizardTitle
;
5440 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
5441 sizeof(title
) / sizeof(title
[0]));
5444 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
,
5445 sizeof(message
) / sizeof(message
[0]));
5446 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
5449 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5460 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
5461 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
5462 HCERTSTORE hDestCertStore
)
5464 PROPSHEETHEADERW hdr
;
5465 PROPSHEETPAGEW pages
[4];
5466 struct ImportWizData data
;
5469 data
.dwFlags
= dwFlags
;
5470 data
.pwszWizardTitle
= pwszWizardTitle
;
5473 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
5474 data
.fileName
= (LPWSTR
)pImportSrc
->u
.pwszFileName
;
5478 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
5479 data
.fileName
= NULL
;
5481 data
.freeSource
= FALSE
;
5482 data
.hDestCertStore
= hDestCertStore
;
5483 data
.freeDest
= FALSE
;
5484 data
.autoDest
= TRUE
;
5485 data
.success
= TRUE
;
5487 memset(&pages
, 0, sizeof(pages
));
5489 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5490 pages
[nPages
].hInstance
= hInstance
;
5491 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
5492 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
5493 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5494 pages
[nPages
].lParam
= (LPARAM
)&data
;
5498 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
5500 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5501 pages
[nPages
].hInstance
= hInstance
;
5502 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
5503 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
5504 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5505 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
5506 pages
[nPages
].pszHeaderSubTitle
=
5507 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
5508 pages
[nPages
].lParam
= (LPARAM
)&data
;
5513 switch (pImportSrc
->dwSubjectChoice
)
5515 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5516 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
5518 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5519 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
5521 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5522 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
5524 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5525 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
5530 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5531 pages
[nPages
].hInstance
= hInstance
;
5532 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
5533 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
5534 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5535 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
5536 pages
[nPages
].pszHeaderSubTitle
=
5537 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
5538 pages
[nPages
].lParam
= (LPARAM
)&data
;
5541 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5542 pages
[nPages
].hInstance
= hInstance
;
5543 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
5544 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
5545 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5546 pages
[nPages
].lParam
= (LPARAM
)&data
;
5549 memset(&hdr
, 0, sizeof(hdr
));
5550 hdr
.dwSize
= sizeof(hdr
);
5551 hdr
.hwndParent
= hwndParent
;
5552 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
5554 hdr
.hInstance
= hInstance
;
5555 if (pwszWizardTitle
)
5556 hdr
.pszCaption
= pwszWizardTitle
;
5558 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
5559 hdr
.u3
.ppsp
= pages
;
5560 hdr
.nPages
= nPages
;
5561 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
5562 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
5563 PropertySheetW(&hdr
);
5564 if (data
.fileName
!= data
.importSrc
.u
.pwszFileName
)
5565 HeapFree(GetProcessHeap(), 0, data
.fileName
);
5566 if (data
.freeSource
&&
5567 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
5568 CertCloseStore(data
.importSrc
.u
.hCertStore
, 0);
5569 DeleteObject(data
.titleFont
);
5570 return data
.success
;
5573 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5574 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5578 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
5579 pImportSrc
, hDestCertStore
);
5582 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
5584 SetLastError(E_INVALIDARG
);
5588 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
5589 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5591 else if (pImportSrc
)
5592 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5596 /* Can't have no UI without specifying source */
5597 SetLastError(E_INVALIDARG
);
5604 struct ExportWizData
5608 LPCWSTR pwszWizardTitle
;
5609 CRYPTUI_WIZ_EXPORT_INFO exportInfo
;
5610 CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo
;
5612 PCRYPT_KEY_PROV_INFO keyProvInfo
;
5619 static LRESULT CALLBACK
export_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5628 struct ExportWizData
*data
;
5629 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5630 WCHAR fontFace
[MAX_STRING_LEN
];
5631 HDC hDC
= GetDC(hwnd
);
5634 data
= (struct ExportWizData
*)page
->lParam
;
5635 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
5636 sizeof(fontFace
) / sizeof(fontFace
[0]));
5637 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
5638 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
5639 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
5640 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
5641 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
5642 (WPARAM
)data
->titleFont
, TRUE
);
5643 ReleaseDC(hwnd
, hDC
);
5648 NMHDR
*hdr
= (NMHDR
*)lp
;
5653 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
5663 static PCRYPT_KEY_PROV_INFO
export_get_private_key_info(PCCERT_CONTEXT cert
)
5665 PCRYPT_KEY_PROV_INFO info
= NULL
;
5668 if (CertGetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
,
5671 info
= HeapAlloc(GetProcessHeap(), 0, size
);
5674 if (!CertGetCertificateContextProperty(cert
,
5675 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
))
5677 HeapFree(GetProcessHeap(), 0, info
);
5685 static BOOL
export_acquire_private_key(const CRYPT_KEY_PROV_INFO
*info
,
5690 ret
= CryptAcquireContextW(phProv
, info
->pwszContainerName
,
5691 info
->pwszProvName
, info
->dwProvType
, 0);
5696 for (i
= 0; i
< info
->cProvParam
; i
++)
5697 CryptSetProvParam(*phProv
, info
->rgProvParam
[i
].dwParam
,
5698 info
->rgProvParam
[i
].pbData
, info
->rgProvParam
[i
].dwFlags
);
5703 static BOOL
export_is_key_exportable(HCRYPTPROV hProv
, DWORD keySpec
)
5708 if ((ret
= CryptGetUserKey(hProv
, keySpec
, &key
)))
5710 DWORD permissions
, size
= sizeof(permissions
);
5712 if ((ret
= CryptGetKeyParam(key
, KP_PERMISSIONS
, (BYTE
*)&permissions
,
5713 &size
, 0)) && !(permissions
& CRYPT_EXPORT
))
5715 CryptDestroyKey(key
);
5720 static LRESULT CALLBACK
export_private_key_dlg_proc(HWND hwnd
, UINT msg
,
5721 WPARAM wp
, LPARAM lp
)
5724 struct ExportWizData
*data
;
5730 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5731 PCRYPT_KEY_PROV_INFO info
;
5732 HCRYPTPROV hProv
= 0;
5735 data
= (struct ExportWizData
*)page
->lParam
;
5736 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5737 /* Get enough information about a key to see whether it's exportable.
5739 if (!(info
= export_get_private_key_info(
5740 data
->exportInfo
.u
.pCertContext
)))
5741 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5742 else if (!export_acquire_private_key(info
, &hProv
))
5743 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5744 else if (!export_is_key_exportable(hProv
, info
->dwKeySpec
))
5745 errorID
= IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE
;
5749 WCHAR error
[MAX_STRING_LEN
];
5751 LoadStringW(hInstance
, errorID
, error
,
5752 sizeof(error
) / sizeof(error
[0]));
5753 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE
),
5754 WM_SETTEXT
, 0, (LPARAM
)error
);
5755 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_YES
), FALSE
);
5758 data
->keyProvInfo
= info
;
5760 CryptReleaseContext(hProv
, 0);
5761 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
), BM_CLICK
,
5767 NMHDR
*hdr
= (NMHDR
*)lp
;
5772 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5773 PSWIZB_BACK
| PSWIZB_NEXT
);
5777 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5778 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
))
5780 data
->contextInfo
.dwExportFormat
=
5781 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5782 data
->contextInfo
.fExportPrivateKeys
= FALSE
;
5786 data
->contextInfo
.dwExportFormat
=
5787 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5788 data
->contextInfo
.fExportPrivateKeys
= TRUE
;
5798 static BOOL
export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
)
5802 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
)
5806 /* If there's a CRYPT_KEY_PROV_INFO set for this cert, assume the
5807 * cert has a private key.
5809 if (CertGetCertificateContextProperty(pExportInfo
->u
.pCertContext
,
5810 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
))
5816 static void export_format_enable_controls(HWND hwnd
, const struct ExportWizData
*data
)
5818 int defaultFormatID
;
5820 switch (data
->contextInfo
.dwExportFormat
)
5822 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
5823 defaultFormatID
= IDC_EXPORT_FORMAT_BASE64
;
5825 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
5826 defaultFormatID
= IDC_EXPORT_FORMAT_CMS
;
5828 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
5829 defaultFormatID
= IDC_EXPORT_FORMAT_PFX
;
5832 defaultFormatID
= IDC_EXPORT_FORMAT_DER
;
5834 SendMessageW(GetDlgItem(hwnd
, defaultFormatID
), BM_CLICK
, 0, 0);
5835 if (defaultFormatID
== IDC_EXPORT_FORMAT_PFX
)
5837 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), FALSE
);
5838 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), FALSE
);
5839 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), FALSE
);
5840 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), TRUE
);
5844 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), TRUE
);
5845 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), TRUE
);
5846 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), TRUE
);
5847 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), FALSE
);
5851 static LRESULT CALLBACK
export_format_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5855 struct ExportWizData
*data
;
5861 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5863 data
= (struct ExportWizData
*)page
->lParam
;
5864 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5865 export_format_enable_controls(hwnd
, data
);
5870 NMHDR
*hdr
= (NMHDR
*)lp
;
5875 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5876 PSWIZB_BACK
| PSWIZB_NEXT
);
5877 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5878 export_format_enable_controls(hwnd
, data
);
5883 BOOL skipPasswordPage
= TRUE
;
5885 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5886 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_DER
))
5887 data
->contextInfo
.dwExportFormat
=
5888 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5889 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_BASE64
))
5890 data
->contextInfo
.dwExportFormat
=
5891 CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
;
5892 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_CMS
))
5894 data
->contextInfo
.dwExportFormat
=
5895 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5896 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
))
5897 data
->contextInfo
.fExportChain
=
5898 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5902 data
->contextInfo
.dwExportFormat
=
5903 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5904 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
))
5905 data
->contextInfo
.fExportChain
= TRUE
;
5906 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
))
5907 data
->contextInfo
.fStrongEncryption
= TRUE
;
5908 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
))
5909 data
->deleteKeys
= TRUE
;
5910 skipPasswordPage
= FALSE
;
5912 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
,
5913 skipPasswordPage
? IDD_EXPORT_FILE
: 0);
5926 case IDC_EXPORT_FORMAT_DER
:
5927 case IDC_EXPORT_FORMAT_BASE64
:
5928 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5930 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5932 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5934 EnableWindow(GetDlgItem(hwnd
,
5935 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), FALSE
);
5937 case IDC_EXPORT_FORMAT_CMS
:
5938 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5941 case IDC_EXPORT_FORMAT_PFX
:
5942 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5944 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5946 EnableWindow(GetDlgItem(hwnd
,
5947 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), TRUE
);
5957 static void export_password_mismatch(HWND hwnd
, const struct ExportWizData
*data
)
5959 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5962 if (data
->pwszWizardTitle
)
5963 pTitle
= data
->pwszWizardTitle
;
5966 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
5967 sizeof(title
) / sizeof(title
[0]));
5970 LoadStringW(hInstance
, IDS_EXPORT_PASSWORD_MISMATCH
, error
,
5971 sizeof(error
) / sizeof(error
[0]));
5972 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
5973 SetFocus(GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
));
5976 static LRESULT CALLBACK
export_password_dlg_proc(HWND hwnd
, UINT msg
,
5977 WPARAM wp
, LPARAM lp
)
5980 struct ExportWizData
*data
;
5986 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5988 data
= (struct ExportWizData
*)page
->lParam
;
5989 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5994 NMHDR
*hdr
= (NMHDR
*)lp
;
5999 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6000 PSWIZB_BACK
| PSWIZB_NEXT
);
6005 HWND passwordEdit
= GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
);
6006 HWND passwordConfirmEdit
= GetDlgItem(hwnd
,
6007 IDC_EXPORT_PASSWORD_CONFIRM
);
6008 DWORD passwordLen
= SendMessageW(passwordEdit
, WM_GETTEXTLENGTH
,
6010 DWORD passwordConfirmLen
= SendMessageW(passwordConfirmEdit
,
6011 WM_GETTEXTLENGTH
, 0, 0);
6013 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6014 if (!passwordLen
&& !passwordConfirmLen
)
6015 data
->contextInfo
.pwszPassword
= NULL
;
6016 else if (passwordLen
!= passwordConfirmLen
)
6018 export_password_mismatch(hwnd
, data
);
6019 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6024 LPWSTR password
= HeapAlloc(GetProcessHeap(), 0,
6025 (passwordLen
+ 1) * sizeof(WCHAR
));
6026 LPWSTR passwordConfirm
= HeapAlloc(GetProcessHeap(), 0,
6027 (passwordConfirmLen
+ 1) * sizeof(WCHAR
));
6028 BOOL freePassword
= TRUE
;
6030 if (password
&& passwordConfirm
)
6032 SendMessageW(passwordEdit
, WM_GETTEXT
, passwordLen
+ 1,
6034 SendMessageW(passwordConfirmEdit
, WM_GETTEXT
,
6035 passwordConfirmLen
+ 1, (LPARAM
)passwordConfirm
);
6036 if (strcmpW(password
, passwordConfirm
))
6038 export_password_mismatch(hwnd
, data
);
6039 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6044 data
->contextInfo
.pwszPassword
= password
;
6045 freePassword
= FALSE
;
6046 data
->freePassword
= TRUE
;
6050 HeapFree(GetProcessHeap(), 0, password
);
6051 HeapFree(GetProcessHeap(), 0, passwordConfirm
);
6062 static LPWSTR
export_append_extension(const struct ExportWizData
*data
,
6065 static const WCHAR cer
[] = { '.','c','e','r',0 };
6066 static const WCHAR crl
[] = { '.','c','r','l',0 };
6067 static const WCHAR ctl
[] = { '.','c','t','l',0 };
6068 static const WCHAR p7b
[] = { '.','p','7','b',0 };
6069 static const WCHAR pfx
[] = { '.','p','f','x',0 };
6070 static const WCHAR sst
[] = { '.','s','s','t',0 };
6073 BOOL appendExtension
;
6075 switch (data
->contextInfo
.dwExportFormat
)
6077 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6080 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6084 switch (data
->exportInfo
.dwSubjectChoice
)
6086 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6089 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6092 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6099 dot
= strrchrW(fileName
, '.');
6101 appendExtension
= strcmpiW(dot
, extension
) != 0;
6103 appendExtension
= TRUE
;
6104 if (appendExtension
)
6106 fileName
= HeapReAlloc(GetProcessHeap(), 0, fileName
,
6107 (strlenW(fileName
) + strlenW(extension
) + 1) * sizeof(WCHAR
));
6109 strcatW(fileName
, extension
);
6114 static BOOL
export_validate_filename(HWND hwnd
, struct ExportWizData
*data
,
6118 BOOL tryCreate
= TRUE
, forceCreate
= FALSE
, ret
= FALSE
;
6120 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6121 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, NULL
);
6122 if (file
!= INVALID_HANDLE_VALUE
)
6124 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
6127 if (data
->pwszWizardTitle
)
6128 pTitle
= data
->pwszWizardTitle
;
6131 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6132 sizeof(title
) / sizeof(title
[0]));
6135 LoadStringW(hInstance
, IDS_EXPORT_FILE_EXISTS
, warning
,
6136 sizeof(warning
) / sizeof(warning
[0]));
6137 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
6145 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6146 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6147 forceCreate
? CREATE_ALWAYS
: CREATE_NEW
,
6149 if (file
!= INVALID_HANDLE_VALUE
)
6156 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6158 LPWSTR msgBuf
, fullError
;
6160 if (data
->pwszWizardTitle
)
6161 pTitle
= data
->pwszWizardTitle
;
6164 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6165 sizeof(title
) / sizeof(title
[0]));
6168 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
6169 sizeof(error
) / sizeof(error
[0]));
6171 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
6172 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
6173 fullError
= HeapAlloc(GetProcessHeap(), 0,
6174 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
6178 LPWSTR ptr
= fullError
;
6180 strcpyW(ptr
, error
);
6181 ptr
+= strlenW(error
);
6182 strcpyW(ptr
, fileName
);
6183 ptr
+= strlenW(fileName
);
6186 strcpyW(ptr
, msgBuf
);
6187 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
6188 HeapFree(GetProcessHeap(), 0, fullError
);
6196 static const WCHAR export_filter_cert
[] = { '*','.','c','e','r',0 };
6197 static const WCHAR export_filter_crl
[] = { '*','.','c','r','l',0 };
6198 static const WCHAR export_filter_ctl
[] = { '*','.','s','t','l',0 };
6199 static const WCHAR export_filter_cms
[] = { '*','.','p','7','b',0 };
6200 static const WCHAR export_filter_pfx
[] = { '*','.','p','f','x',0 };
6201 static const WCHAR export_filter_sst
[] = { '*','.','s','s','t',0 };
6203 static WCHAR
*make_export_file_filter(DWORD exportFormat
, DWORD subjectChoice
)
6205 int baseLen
, allLen
, totalLen
= 2, baseID
;
6206 LPWSTR filter
= NULL
, baseFilter
, all
;
6209 switch (exportFormat
)
6211 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6212 baseID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6213 filterStr
= export_filter_cert
;
6215 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6216 baseID
= IDS_EXPORT_FILTER_PFX
;
6217 filterStr
= export_filter_pfx
;
6219 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6220 baseID
= IDS_EXPORT_FILTER_CMS
;
6221 filterStr
= export_filter_cms
;
6224 switch (subjectChoice
)
6226 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6227 baseID
= IDS_EXPORT_FILTER_CRL
;
6228 filterStr
= export_filter_crl
;
6230 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6231 baseID
= IDS_EXPORT_FILTER_CTL
;
6232 filterStr
= export_filter_ctl
;
6234 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6235 baseID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6236 filterStr
= export_filter_sst
;
6239 baseID
= IDS_EXPORT_FILTER_CERT
;
6240 filterStr
= export_filter_cert
;
6244 baseLen
= LoadStringW(hInstance
, baseID
, (LPWSTR
)&baseFilter
, 0);
6245 totalLen
+= baseLen
+ strlenW(filterStr
) + 2;
6246 allLen
= LoadStringW(hInstance
, IDS_IMPORT_FILTER_ALL
, (LPWSTR
)&all
, 0);
6247 totalLen
+= allLen
+ strlenW(filter_all
) + 2;
6248 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
6254 memcpy(ptr
, baseFilter
, baseLen
* sizeof(WCHAR
));
6257 strcpyW(ptr
, filterStr
);
6258 ptr
+= strlenW(filterStr
) + 1;
6259 memcpy(ptr
, all
, allLen
* sizeof(WCHAR
));
6262 strcpyW(ptr
, filter_all
);
6263 ptr
+= strlenW(filter_all
) + 1;
6269 static LRESULT CALLBACK
export_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6273 struct ExportWizData
*data
;
6279 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6281 data
= (struct ExportWizData
*)page
->lParam
;
6282 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6283 if (data
->exportInfo
.pwszExportFileName
)
6284 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
, 0,
6285 (LPARAM
)data
->exportInfo
.pwszExportFileName
);
6290 NMHDR
*hdr
= (NMHDR
*)lp
;
6295 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6296 if (data
->contextInfo
.dwExportFormat
!=
6297 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
)
6299 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, IDD_EXPORT_FORMAT
);
6305 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
);
6306 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
6308 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6311 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6314 if (data
->pwszWizardTitle
)
6315 pTitle
= data
->pwszWizardTitle
;
6318 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6319 sizeof(title
) / sizeof(title
[0]));
6322 LoadStringW(hInstance
, IDS_IMPORT_EMPTY_FILE
, error
,
6323 sizeof(error
) / sizeof(error
[0]));
6324 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
6325 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6330 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
6331 (len
+ 1) * sizeof(WCHAR
));
6335 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
6337 fileName
= export_append_extension(data
, fileName
);
6338 if (!export_validate_filename(hwnd
, data
, fileName
))
6340 HeapFree(GetProcessHeap(), 0, fileName
);
6341 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6345 data
->fileName
= fileName
;
6351 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6352 PSWIZB_BACK
| PSWIZB_NEXT
);
6361 case IDC_EXPORT_BROWSE_FILE
:
6364 WCHAR fileBuf
[MAX_PATH
];
6366 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6367 memset(&ofn
, 0, sizeof(ofn
));
6368 ofn
.lStructSize
= sizeof(ofn
);
6369 ofn
.hwndOwner
= hwnd
;
6370 ofn
.lpstrFilter
= make_export_file_filter(
6371 data
->contextInfo
.dwExportFormat
,
6372 data
->exportInfo
.dwSubjectChoice
);
6373 ofn
.lpstrFile
= fileBuf
;
6374 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
6376 if (GetSaveFileNameW(&ofn
))
6377 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
,
6378 0, (LPARAM
)ofn
.lpstrFile
);
6379 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
6388 static void show_export_details(HWND lv
, const struct ExportWizData
*data
)
6390 WCHAR text
[MAX_STRING_LEN
];
6394 item
.mask
= LVIF_TEXT
;
6397 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6399 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
6400 sizeof(text
)/ sizeof(text
[0]));
6401 item
.pszText
= text
;
6402 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6404 item
.pszText
= data
->fileName
;
6405 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6408 item
.pszText
= text
;
6409 switch (data
->exportInfo
.dwSubjectChoice
)
6411 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6412 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6413 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6414 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6419 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6421 LoadStringW(hInstance
, IDS_EXPORT_INCLUDE_CHAIN
, text
,
6422 sizeof(text
) / sizeof(text
[0]));
6423 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6425 LoadStringW(hInstance
,
6426 data
->contextInfo
.fExportChain
? IDS_YES
: IDS_NO
, text
,
6427 sizeof(text
) / sizeof(text
[0]));
6428 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6430 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6432 LoadStringW(hInstance
, IDS_EXPORT_KEYS
, text
,
6433 sizeof(text
) / sizeof(text
[0]));
6434 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6436 LoadStringW(hInstance
,
6437 data
->contextInfo
.fExportPrivateKeys
? IDS_YES
: IDS_NO
, text
,
6438 sizeof(text
) / sizeof(text
[0]));
6439 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6443 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6445 LoadStringW(hInstance
, IDS_EXPORT_FORMAT
, text
,
6446 sizeof(text
)/ sizeof(text
[0]));
6447 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6450 switch (data
->exportInfo
.dwSubjectChoice
)
6452 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6453 contentID
= IDS_EXPORT_FILTER_CRL
;
6455 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6456 contentID
= IDS_EXPORT_FILTER_CTL
;
6458 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6459 contentID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6462 switch (data
->contextInfo
.dwExportFormat
)
6464 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6465 contentID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6467 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6468 contentID
= IDS_EXPORT_FILTER_CMS
;
6470 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6471 contentID
= IDS_EXPORT_FILTER_PFX
;
6474 contentID
= IDS_EXPORT_FILTER_CERT
;
6477 LoadStringW(hInstance
, contentID
, text
, sizeof(text
) / sizeof(text
[0]));
6478 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6481 static inline BOOL
save_der(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6485 return WriteFile(file
, pb
, cb
, &bytesWritten
, NULL
);
6488 static BOOL
save_base64(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6493 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, NULL
, &size
)))
6495 LPSTR buf
= HeapAlloc(GetProcessHeap(), 0, size
);
6499 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, buf
,
6501 ret
= WriteFile(file
, buf
, size
, &size
, NULL
);
6502 HeapFree(GetProcessHeap(), 0, buf
);
6506 SetLastError(ERROR_OUTOFMEMORY
);
6513 static inline BOOL
save_store_as_cms(HANDLE file
, HCERTSTORE store
)
6515 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6516 CERT_STORE_SAVE_AS_PKCS7
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6519 static BOOL
save_cert_as_cms(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6523 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
6524 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6530 HCERTSTORE addlStore
= CertOpenStore(CERT_STORE_PROV_COLLECTION
,
6531 0, 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6538 for (i
= 0; ret
&& i
< pExportInfo
->cStores
; i
++)
6539 ret
= CertAddStoreToCollection(addlStore
,
6540 pExportInfo
->rghStores
, 0, 0);
6543 PCCERT_CHAIN_CONTEXT chain
;
6545 ret
= CertGetCertificateChain(NULL
,
6546 pExportInfo
->u
.pCertContext
, NULL
, addlStore
, NULL
, 0,
6552 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6553 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6555 ret
= CertAddCertificateContextToStore(store
,
6556 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6557 CERT_STORE_ADD_ALWAYS
, NULL
);
6558 CertFreeCertificateChain(chain
);
6562 /* No chain could be created, just add the individual
6563 * cert to the message.
6565 ret
= CertAddCertificateContextToStore(store
,
6566 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
,
6570 CertCloseStore(addlStore
, 0);
6576 ret
= CertAddCertificateContextToStore(store
,
6577 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, NULL
);
6579 ret
= save_store_as_cms(file
, store
);
6580 CertCloseStore(store
, 0);
6587 static BOOL
save_serialized_store(HANDLE file
, HCERTSTORE store
)
6589 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6590 CERT_STORE_SAVE_AS_STORE
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6593 static BOOL
save_pfx(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6594 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6595 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6597 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, X509_ASN_ENCODING
,
6598 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6603 CRYPT_DATA_BLOB pfxBlob
= { 0, NULL
};
6604 PCCERT_CONTEXT cert
= NULL
;
6605 BOOL freeKeyProvInfo
= FALSE
;
6607 if (pContextInfo
->fExportChain
)
6609 HCERTCHAINENGINE engine
= NULL
;
6611 if (pExportInfo
->cStores
)
6613 CERT_CHAIN_ENGINE_CONFIG config
;
6615 memset(&config
, 0, sizeof(config
));
6616 config
.cbSize
= sizeof(config
);
6617 config
.cAdditionalStore
= pExportInfo
->cStores
;
6618 config
.rghAdditionalStore
= pExportInfo
->rghStores
;
6619 ret
= CertCreateCertificateChainEngine(&config
, &engine
);
6625 CERT_CHAIN_PARA chainPara
;
6626 PCCERT_CHAIN_CONTEXT chain
;
6628 memset(&chainPara
, 0, sizeof(chainPara
));
6629 chainPara
.cbSize
= sizeof(chainPara
);
6630 ret
= CertGetCertificateChain(engine
,
6631 pExportInfo
->u
.pCertContext
, NULL
, NULL
, &chainPara
, 0, NULL
,
6637 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6638 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6641 if (i
== 0 && j
== 0)
6642 ret
= CertAddCertificateContextToStore(store
,
6643 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6644 CERT_STORE_ADD_ALWAYS
, &cert
);
6646 ret
= CertAddCertificateContextToStore(store
,
6647 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6648 CERT_STORE_ADD_ALWAYS
, NULL
);
6650 CertFreeCertificateChain(chain
);
6654 CertFreeCertificateChainEngine(engine
);
6657 ret
= CertAddCertificateContextToStore(store
,
6658 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, &cert
);
6659 /* Copy private key info to newly created cert, so it'll get exported
6660 * along with the cert.
6662 if (ret
&& pContextInfo
->fExportPrivateKeys
)
6665 ret
= CertSetCertificateContextProperty(cert
,
6666 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6669 if (!(keyProvInfo
= export_get_private_key_info(cert
)))
6673 ret
= CertSetCertificateContextProperty(cert
,
6674 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6675 freeKeyProvInfo
= TRUE
;
6682 REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
| EXPORT_PRIVATE_KEYS
;
6684 ret
= PFXExportCertStore(store
, &pfxBlob
,
6685 pContextInfo
->pwszPassword
, exportFlags
);
6688 pfxBlob
.pbData
= HeapAlloc(GetProcessHeap(), 0, pfxBlob
.cbData
);
6691 ret
= PFXExportCertStore(store
, &pfxBlob
,
6692 pContextInfo
->pwszPassword
, exportFlags
);
6697 ret
= WriteFile(file
, pfxBlob
.pbData
, pfxBlob
.cbData
,
6698 &bytesWritten
, NULL
);
6703 SetLastError(ERROR_OUTOFMEMORY
);
6708 if (ret
&& deleteKeys
)
6712 CryptAcquireContextW(&prov
, keyProvInfo
->pwszContainerName
,
6713 keyProvInfo
->pwszProvName
, keyProvInfo
->dwProvType
,
6714 CRYPT_DELETEKEYSET
);
6716 if (freeKeyProvInfo
)
6717 HeapFree(GetProcessHeap(), 0, keyProvInfo
);
6718 CertFreeCertificateContext(cert
);
6719 CertCloseStore(store
, 0);
6724 static BOOL
do_export(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6725 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6726 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6730 if (pContextInfo
->dwSize
!= sizeof(CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
))
6732 SetLastError(E_INVALIDARG
);
6735 switch (pExportInfo
->dwSubjectChoice
)
6737 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6738 ret
= save_der(file
,
6739 pExportInfo
->u
.pCRLContext
->pbCrlEncoded
,
6740 pExportInfo
->u
.pCRLContext
->cbCrlEncoded
);
6742 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6743 ret
= save_der(file
,
6744 pExportInfo
->u
.pCTLContext
->pbCtlEncoded
,
6745 pExportInfo
->u
.pCTLContext
->cbCtlEncoded
);
6747 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6748 ret
= save_serialized_store(file
, pExportInfo
->u
.hCertStore
);
6750 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6751 ret
= save_store_as_cms(file
, pExportInfo
->u
.hCertStore
);
6754 switch (pContextInfo
->dwExportFormat
)
6756 case CRYPTUI_WIZ_EXPORT_FORMAT_DER
:
6757 ret
= save_der(file
, pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6758 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6760 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6761 ret
= save_base64(file
,
6762 pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6763 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6765 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6766 ret
= save_cert_as_cms(file
, pExportInfo
,
6767 pContextInfo
->fExportChain
);
6769 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6770 ret
= save_pfx(file
, pExportInfo
, pContextInfo
, keyProvInfo
,
6774 SetLastError(E_FAIL
);
6781 static LRESULT CALLBACK
export_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6785 struct ExportWizData
*data
;
6791 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6792 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6796 data
= (struct ExportWizData
*)page
->lParam
;
6797 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6798 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
6799 (WPARAM
)data
->titleFont
, TRUE
);
6800 GetWindowRect(lv
, &rc
);
6801 column
.mask
= LVCF_WIDTH
;
6802 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
6803 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
6804 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
6805 show_export_details(lv
, data
);
6810 NMHDR
*hdr
= (NMHDR
*)lp
;
6816 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6818 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6819 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
6820 show_export_details(lv
, data
);
6821 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6822 PSWIZB_BACK
| PSWIZB_FINISH
);
6829 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
6833 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6834 if ((data
->success
= do_export(data
->file
, &data
->exportInfo
,
6835 &data
->contextInfo
, data
->keyProvInfo
, data
->deleteKeys
)))
6837 messageID
= IDS_EXPORT_SUCCEEDED
;
6842 messageID
= IDS_EXPORT_FAILED
;
6843 mbFlags
= MB_OK
| MB_ICONERROR
;
6845 if (data
->pwszWizardTitle
)
6846 pTitle
= data
->pwszWizardTitle
;
6849 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
,
6850 sizeof(title
) / sizeof(title
[0]));
6853 LoadStringW(hInstance
, messageID
, message
,
6854 sizeof(message
) / sizeof(message
[0]));
6855 MessageBoxW(hwnd
, message
, pTitle
, mbFlags
);
6865 static BOOL
show_export_ui(DWORD dwFlags
, HWND hwndParent
,
6866 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, const void *pvoid
)
6868 PROPSHEETHEADERW hdr
;
6869 PROPSHEETPAGEW pages
[6];
6870 struct ExportWizData data
;
6872 BOOL hasPrivateKey
, showFormatPage
= TRUE
;
6875 data
.dwFlags
= dwFlags
;
6876 data
.pwszWizardTitle
= pwszWizardTitle
;
6877 memset(&data
.exportInfo
, 0, sizeof(data
.exportInfo
));
6878 memcpy(&data
.exportInfo
, pExportInfo
,
6879 min(sizeof(data
.exportInfo
), pExportInfo
->dwSize
));
6880 if (pExportInfo
->dwSize
> sizeof(data
.exportInfo
))
6881 data
.exportInfo
.dwSize
= sizeof(data
.exportInfo
);
6882 data
.contextInfo
.dwSize
= sizeof(data
.contextInfo
);
6883 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6884 data
.contextInfo
.fExportChain
= FALSE
;
6885 data
.contextInfo
.fStrongEncryption
= FALSE
;
6886 data
.contextInfo
.fExportPrivateKeys
= FALSE
;
6887 data
.contextInfo
.pwszPassword
= NULL
;
6888 data
.freePassword
= FALSE
;
6889 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
&&
6891 memcpy(&data
.contextInfo
, pvoid
,
6892 min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
)pvoid
)->dwSize
,
6893 sizeof(data
.contextInfo
)));
6894 data
.keyProvInfo
= NULL
;
6895 data
.deleteKeys
= FALSE
;
6896 data
.fileName
= NULL
;
6897 data
.file
= INVALID_HANDLE_VALUE
;
6898 data
.success
= FALSE
;
6900 memset(&pages
, 0, sizeof(pages
));
6902 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6903 pages
[nPages
].hInstance
= hInstance
;
6904 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_WELCOME
);
6905 pages
[nPages
].pfnDlgProc
= export_welcome_dlg_proc
;
6906 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6907 pages
[nPages
].lParam
= (LPARAM
)&data
;
6910 hasPrivateKey
= export_info_has_private_key(pExportInfo
);
6911 switch (pExportInfo
->dwSubjectChoice
)
6913 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6914 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6915 showFormatPage
= FALSE
;
6916 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6918 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6919 showFormatPage
= FALSE
;
6920 data
.contextInfo
.dwExportFormat
=
6921 CRYPTUI_WIZ_EXPORT_FORMAT_SERIALIZED_CERT_STORE
;
6923 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6924 showFormatPage
= FALSE
;
6925 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
6929 if (hasPrivateKey
&& showFormatPage
)
6931 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6932 pages
[nPages
].hInstance
= hInstance
;
6933 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY
);
6934 pages
[nPages
].pfnDlgProc
= export_private_key_dlg_proc
;
6935 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6936 pages
[nPages
].pszHeaderTitle
=
6937 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE
);
6938 pages
[nPages
].pszHeaderSubTitle
=
6939 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE
);
6940 pages
[nPages
].lParam
= (LPARAM
)&data
;
6945 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6946 pages
[nPages
].hInstance
= hInstance
;
6947 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FORMAT
);
6948 pages
[nPages
].pfnDlgProc
= export_format_dlg_proc
;
6949 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6950 pages
[nPages
].pszHeaderTitle
=
6951 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_TITLE
);
6952 pages
[nPages
].pszHeaderSubTitle
=
6953 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_SUBTITLE
);
6954 pages
[nPages
].lParam
= (LPARAM
)&data
;
6957 if (hasPrivateKey
&& showFormatPage
)
6959 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6960 pages
[nPages
].hInstance
= hInstance
;
6961 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD
);
6962 pages
[nPages
].pfnDlgProc
= export_password_dlg_proc
;
6963 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6964 pages
[nPages
].pszHeaderTitle
=
6965 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE
);
6966 pages
[nPages
].pszHeaderSubTitle
=
6967 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE
);
6968 pages
[nPages
].lParam
= (LPARAM
)&data
;
6972 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6973 pages
[nPages
].hInstance
= hInstance
;
6974 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FILE
);
6975 pages
[nPages
].pfnDlgProc
= export_file_dlg_proc
;
6976 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6977 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_EXPORT_FILE_TITLE
);
6978 pages
[nPages
].pszHeaderSubTitle
=
6979 MAKEINTRESOURCEW(IDS_EXPORT_FILE_SUBTITLE
);
6980 pages
[nPages
].lParam
= (LPARAM
)&data
;
6983 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6984 pages
[nPages
].hInstance
= hInstance
;
6985 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FINISH
);
6986 pages
[nPages
].pfnDlgProc
= export_finish_dlg_proc
;
6987 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6988 pages
[nPages
].lParam
= (LPARAM
)&data
;
6991 memset(&hdr
, 0, sizeof(hdr
));
6992 hdr
.dwSize
= sizeof(hdr
);
6993 hdr
.hwndParent
= hwndParent
;
6994 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
6996 hdr
.hInstance
= hInstance
;
6997 if (pwszWizardTitle
)
6998 hdr
.pszCaption
= pwszWizardTitle
;
7000 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_EXPORT_WIZARD
);
7001 hdr
.u3
.ppsp
= pages
;
7002 hdr
.nPages
= nPages
;
7003 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
7004 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
7005 l
= PropertySheetW(&hdr
);
7006 DeleteObject(data
.titleFont
);
7007 if (data
.freePassword
)
7008 HeapFree(GetProcessHeap(), 0,
7009 (LPWSTR
)data
.contextInfo
.pwszPassword
);
7010 HeapFree(GetProcessHeap(), 0, data
.keyProvInfo
);
7011 CloseHandle(data
.file
);
7012 HeapFree(GetProcessHeap(), 0, data
.fileName
);
7015 SetLastError(ERROR_CANCELLED
);
7019 return data
.success
;
7022 BOOL WINAPI
CryptUIWizExport(DWORD dwFlags
, HWND hwndParent
,
7023 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, void *pvoid
)
7027 TRACE("(%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
,
7028 debugstr_w(pwszWizardTitle
), pExportInfo
, pvoid
);
7030 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
7031 ret
= show_export_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pExportInfo
,
7035 HANDLE file
= CreateFileW(pExportInfo
->pwszExportFileName
,
7036 GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
7037 CREATE_ALWAYS
, 0, NULL
);
7039 if (file
!= INVALID_HANDLE_VALUE
)
7041 ret
= do_export(file
, pExportInfo
, pvoid
, NULL
, FALSE
);