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
23 #define NONAMELESSUNION
36 #include "cryptuiapi.h"
37 #include "cryptuires.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
45 static HINSTANCE hInstance
;
47 static const WCHAR empty
[] = {0};
49 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
51 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
55 case DLL_PROCESS_ATTACH
:
57 DisableThreadLibraryCalls(hinstDLL
);
63 static WCHAR
*strdupAtoW( const char *str
)
65 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
66 WCHAR
*ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
67 if (ret
) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
71 #define MAX_STRING_LEN 512
73 static void add_cert_columns(HWND hwnd
)
75 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
77 WCHAR buf
[MAX_STRING_LEN
];
80 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
81 GetWindowRect(lv
, &rc
);
82 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
, ARRAY_SIZE(buf
));
83 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
84 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
86 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
87 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
, ARRAY_SIZE(buf
));
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
, ARRAY_SIZE(buf
));
91 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
92 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
93 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
, ARRAY_SIZE(buf
));
94 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 3, (LPARAM
)&column
);
97 static void add_cert_to_view(HWND lv
, PCCERT_CONTEXT cert
, DWORD
*allocatedLen
,
102 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
107 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
108 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
111 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
112 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
114 if (len
> *allocatedLen
)
116 HeapFree(GetProcessHeap(), 0, *str
);
117 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
123 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
126 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
129 item
.mask
= LVIF_TEXT
;
130 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
131 CERT_NAME_ISSUER_FLAG
, NULL
, NULL
, 0);
132 if (len
> *allocatedLen
)
134 HeapFree(GetProcessHeap(), 0, *str
);
135 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
141 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
142 CERT_NAME_ISSUER_FLAG
, NULL
, *str
, len
);
145 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
148 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
149 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
150 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
, ARRAY_SIZE(date
));
153 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
155 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
157 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
158 if (len
> *allocatedLen
)
160 HeapFree(GetProcessHeap(), 0, *str
);
161 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
167 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
173 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
177 static LPSTR
get_cert_mgr_usages(void)
179 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
180 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
181 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
182 'r','p','o','s','e',0 };
186 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
192 rc
= RegQueryValueExA(key
, "Purpose", NULL
, &type
, NULL
, &size
);
193 if ((!rc
|| rc
== ERROR_MORE_DATA
) && type
== REG_SZ
)
195 str
= HeapAlloc(GetProcessHeap(), 0, size
);
198 rc
= RegQueryValueExA(key
, "Purpose", NULL
, NULL
, (LPBYTE
)str
,
202 HeapFree(GetProcessHeap(), 0, str
);
213 PurposeFilterShowAll
= 0,
214 PurposeFilterShowAdvanced
= 1,
215 PurposeFilterShowOID
= 2
218 static void initialize_purpose_selection(HWND hwnd
)
220 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
221 WCHAR buf
[MAX_STRING_LEN
];
225 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
, ARRAY_SIZE(buf
));
226 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
227 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAll
);
228 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
, ARRAY_SIZE(buf
));
229 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
230 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAdvanced
);
231 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
232 if ((usages
= get_cert_mgr_usages()))
236 for (ptr
= usages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
237 ptr
= comma
? comma
+ 1 : NULL
,
238 comma
= ptr
? strchr(ptr
, ',') : NULL
)
240 PCCRYPT_OID_INFO info
;
244 if ((info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, ptr
, 0)))
246 index
= SendMessageW(cb
, CB_INSERTSTRING
, 0,
247 (LPARAM
)info
->pwszName
);
248 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)info
);
251 HeapFree(GetProcessHeap(), 0, usages
);
255 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
256 PCCRYPT_OID_INFO
**usages
);
258 static CERT_ENHKEY_USAGE
*add_oid_to_usage(CERT_ENHKEY_USAGE
*usage
, LPSTR oid
)
260 if (!usage
->cUsageIdentifier
)
261 usage
->rgpszUsageIdentifier
= HeapAlloc(GetProcessHeap(), 0,
264 usage
->rgpszUsageIdentifier
= HeapReAlloc(GetProcessHeap(), 0,
265 usage
->rgpszUsageIdentifier
,
266 (usage
->cUsageIdentifier
+ 1) * sizeof(LPSTR
));
267 if (usage
->rgpszUsageIdentifier
)
268 usage
->rgpszUsageIdentifier
[usage
->cUsageIdentifier
++] = oid
;
271 HeapFree(GetProcessHeap(), 0, usage
);
277 static CERT_ENHKEY_USAGE
*convert_usages_str_to_usage(LPSTR usageStr
)
279 CERT_ENHKEY_USAGE
*usage
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
280 sizeof(CERT_ENHKEY_USAGE
));
286 for (ptr
= usageStr
, comma
= strchr(ptr
, ','); usage
&& ptr
&& *ptr
;
287 ptr
= comma
? comma
+ 1 : NULL
,
288 comma
= ptr
? strchr(ptr
, ',') : NULL
)
292 usage
= add_oid_to_usage(usage
, ptr
);
298 static CERT_ENHKEY_USAGE
*create_advanced_filter(void)
300 CERT_ENHKEY_USAGE
*advancedUsage
= HeapAlloc(GetProcessHeap(),
301 HEAP_ZERO_MEMORY
, sizeof(CERT_ENHKEY_USAGE
));
305 PCCRYPT_OID_INFO
*usages
;
307 if (WTHelperGetKnownUsages(1, &usages
))
309 LPSTR disabledUsagesStr
;
311 if ((disabledUsagesStr
= get_cert_mgr_usages()))
313 CERT_ENHKEY_USAGE
*disabledUsages
=
314 convert_usages_str_to_usage(disabledUsagesStr
);
318 PCCRYPT_OID_INFO
*ptr
;
320 for (ptr
= usages
; advancedUsage
&& *ptr
; ptr
++)
323 BOOL disabled
= FALSE
;
325 for (i
= 0; !disabled
&&
326 i
< disabledUsages
->cUsageIdentifier
; i
++)
327 if (!strcmp(disabledUsages
->rgpszUsageIdentifier
[i
],
331 advancedUsage
= add_oid_to_usage(advancedUsage
,
332 (LPSTR
)(*ptr
)->pszOID
);
334 /* The individual strings are pointers to disabledUsagesStr,
335 * so they're freed when it is.
337 HeapFree(GetProcessHeap(), 0,
338 disabledUsages
->rgpszUsageIdentifier
);
339 HeapFree(GetProcessHeap(), 0, disabledUsages
);
341 HeapFree(GetProcessHeap(), 0, disabledUsagesStr
);
343 WTHelperGetKnownUsages(2, &usages
);
346 return advancedUsage
;
349 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
);
351 static void show_store_certs(HWND hwnd
, HCERTSTORE store
)
353 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
354 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
355 PCCERT_CONTEXT cert
= NULL
;
356 DWORD allocatedLen
= 0;
359 PurposeFilter filter
= PurposeFilterShowAll
;
361 CERT_ENHKEY_USAGE
*advanced
= NULL
;
363 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
366 INT_PTR data
= SendMessageW(cb
, CB_GETITEMDATA
, index
, 0);
372 PCCRYPT_OID_INFO info
= (PCCRYPT_OID_INFO
)data
;
374 filter
= PurposeFilterShowOID
;
378 if (filter
== PurposeFilterShowAdvanced
)
379 advanced
= create_advanced_filter();
381 cert
= CertEnumCertificatesInStore(store
, cert
);
386 if (filter
== PurposeFilterShowAll
)
393 if (CertGetValidUsages(1, &cert
, &numOIDs
, NULL
, &cbOIDs
))
397 /* -1 implies all usages are valid */
402 LPSTR
*oids
= HeapAlloc(GetProcessHeap(), 0, cbOIDs
);
406 if (CertGetValidUsages(1, &cert
, &numOIDs
, oids
,
411 if (filter
== PurposeFilterShowOID
)
413 for (i
= 0; !show
&& i
< numOIDs
; i
++)
414 if (!strcmp(oids
[i
], oid
))
419 for (i
= 0; !show
&& i
< numOIDs
; i
++)
424 j
< advanced
->cUsageIdentifier
; j
++)
426 advanced
->rgpszUsageIdentifier
[j
]))
431 HeapFree(GetProcessHeap(), 0, oids
);
437 add_cert_to_view(lv
, cert
, &allocatedLen
, &str
);
440 HeapFree(GetProcessHeap(), 0, str
);
443 HeapFree(GetProcessHeap(), 0, advanced
->rgpszUsageIdentifier
);
444 HeapFree(GetProcessHeap(), 0, advanced
);
446 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
447 (LPARAM
)cert_mgr_sort_by_subject
);
450 static const WCHAR my
[] = { 'M','y',0 };
451 static const WCHAR addressBook
[] = {
452 'A','d','d','r','e','s','s','B','o','o','k',0 };
453 static const WCHAR ca
[] = { 'C','A',0 };
454 static const WCHAR root
[] = { 'R','o','o','t',0 };
455 static const WCHAR trustedPublisher
[] = {
456 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
457 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
459 struct CertMgrStoreInfo
463 int removePluralWarning
;
466 static const struct CertMgrStoreInfo defaultStoreList
[] = {
467 { my
, IDS_WARN_REMOVE_MY
, IDS_WARN_REMOVE_PLURAL_MY
},
468 { addressBook
, IDS_WARN_REMOVE_ADDRESSBOOK
,
469 IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK
},
470 { ca
, IDS_WARN_REMOVE_CA
, IDS_WARN_REMOVE_PLURAL_CA
},
471 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
472 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
473 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
474 { disallowed
, IDS_WARN_REMOVE_DEFAULT
},
477 static const struct CertMgrStoreInfo publisherStoreList
[] = {
478 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
479 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
480 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
481 { disallowed
, IDS_WARN_REMOVE_PLURAL_DEFAULT
},
486 HIMAGELIST imageList
;
489 const struct CertMgrStoreInfo
*stores
;
492 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
, struct CertMgrData
*data
)
494 const struct CertMgrStoreInfo
*storeList
;
496 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
498 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
500 storeList
= publisherStoreList
;
501 cStores
= ARRAY_SIZE(publisherStoreList
);
505 storeList
= defaultStoreList
;
506 cStores
= ARRAY_SIZE(defaultStoreList
);
508 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
510 data
->nStores
= cStores
;
511 data
->stores
= storeList
;
512 for (i
= 0; i
< cStores
; i
++)
518 if (!(name
= CryptFindLocalizedName(storeList
[i
].name
)))
519 name
= storeList
[i
].name
;
520 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
521 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
].name
);
522 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
523 item
.pszText
= (LPWSTR
)name
;
524 item
.lParam
= (LPARAM
)store
;
525 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
529 static void free_certs(HWND lv
)
532 int items
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
534 for (i
= 0; i
< items
; i
++)
536 item
.mask
= LVIF_PARAM
;
539 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
540 CertFreeCertificateContext((PCCERT_CONTEXT
)item
.lParam
);
544 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
548 item
.mask
= TCIF_PARAM
;
549 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
550 return (HCERTSTORE
)item
.lParam
;
553 static HCERTSTORE
cert_mgr_current_store(HWND hwnd
)
555 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
557 return cert_mgr_index_to_store(tab
, SendMessageW(tab
, TCM_GETCURSEL
, 0, 0));
560 static void close_stores(HWND tab
)
562 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
564 for (i
= 0; i
< tabs
; i
++)
565 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
568 static void refresh_store_certs(HWND hwnd
)
570 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
573 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
574 show_store_certs(hwnd
, cert_mgr_current_store(hwnd
));
578 CheckBitmapIndexUnchecked
= 1,
579 CheckBitmapIndexChecked
= 2,
580 CheckBitmapIndexDisabledUnchecked
= 3,
581 CheckBitmapIndexDisabledChecked
= 4
584 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
,
585 CheckBitmapIndex state
)
589 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
590 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
591 item
.stateMask
= LVIS_STATEIMAGEMASK
;
592 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
594 item
.lParam
= (LPARAM
)info
;
595 item
.pszText
= (LPWSTR
)info
->pwszName
;
596 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
599 static void add_known_usages_to_list(HWND lv
, CheckBitmapIndex state
)
601 PCCRYPT_OID_INFO
*usages
;
603 if (WTHelperGetKnownUsages(1, &usages
))
605 PCCRYPT_OID_INFO
*ptr
;
607 for (ptr
= usages
; *ptr
; ptr
++)
608 add_known_usage(lv
, *ptr
, state
);
609 WTHelperGetKnownUsages(2, &usages
);
613 static void toggle_usage(HWND hwnd
, int iItem
)
617 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
619 item
.mask
= LVIF_STATE
;
622 item
.stateMask
= LVIS_STATEIMAGEMASK
;
623 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
626 int state
= item
.state
>> 12;
628 item
.state
= INDEXTOSTATEIMAGEMASK(
629 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
630 CheckBitmapIndexChecked
);
631 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
635 static LONG_PTR
find_oid_in_list(HWND lv
, LPCSTR oid
)
637 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
638 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
643 LVFINDINFOW findInfo
;
645 findInfo
.flags
= LVFI_PARAM
;
646 findInfo
.lParam
= (LPARAM
)oidInfo
;
647 ret
= SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
);
651 LVFINDINFOA findInfo
;
653 findInfo
.flags
= LVFI_STRING
;
655 ret
= SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
);
660 static void save_cert_mgr_usages(HWND hwnd
)
662 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
663 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
664 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
665 'r','p','o','s','e',0 };
667 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
668 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
672 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
674 item
.stateMask
= LVIS_STATEIMAGEMASK
;
675 for (i
= 0; i
< purposes
; i
++)
678 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
680 int state
= item
.state
>> 12;
682 if (state
== CheckBitmapIndexUnchecked
)
684 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
685 BOOL firstString
= TRUE
;
688 str
= HeapAlloc(GetProcessHeap(), 0,
689 strlen(info
->pszOID
) + 1);
692 str
= HeapReAlloc(GetProcessHeap(), 0, str
,
693 strlen(str
) + 1 + strlen(info
->pszOID
) + 1);
698 LPSTR ptr
= firstString
? str
: str
+ strlen(str
);
702 strcpy(ptr
, info
->pszOID
);
707 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_ALL_ACCESS
,
711 RegSetValueExA(key
, "Purpose", 0, REG_SZ
, (const BYTE
*)str
,
714 RegDeleteValueA(key
, "Purpose");
717 HeapFree(GetProcessHeap(), 0, str
);
720 static LRESULT CALLBACK
cert_mgr_advanced_dlg_proc(HWND hwnd
, UINT msg
,
721 WPARAM wp
, LPARAM lp
)
729 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
730 HIMAGELIST imageList
;
731 LPSTR disabledUsages
;
733 GetWindowRect(lv
, &rc
);
734 column
.mask
= LVCF_WIDTH
;
735 column
.cx
= rc
.right
- rc
.left
;
736 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
737 imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 4, 0);
741 COLORREF backColor
= RGB(255, 0, 255);
743 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
744 ImageList_AddMasked(imageList
, bmp
, backColor
);
746 ImageList_SetBkColor(imageList
, CLR_NONE
);
747 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)imageList
);
748 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)imageList
);
750 add_known_usages_to_list(lv
, CheckBitmapIndexChecked
);
751 if ((disabledUsages
= get_cert_mgr_usages()))
755 for (ptr
= disabledUsages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
756 ptr
= comma
? comma
+ 1 : NULL
,
757 comma
= ptr
? strchr(ptr
, ',') : NULL
)
763 if ((index
= find_oid_in_list(lv
, ptr
)) != -1)
764 toggle_usage(hwnd
, index
);
766 HeapFree(GetProcessHeap(), 0, disabledUsages
);
772 NMHDR
*hdr
= (NMHDR
*)lp
;
778 nm
= (NMITEMACTIVATE
*)lp
;
779 toggle_usage(hwnd
, nm
->iItem
);
780 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
789 save_cert_mgr_usages(hwnd
);
790 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
791 EndDialog(hwnd
, IDOK
);
794 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
795 EndDialog(hwnd
, IDCANCEL
);
803 static void cert_mgr_clear_cert_selection(HWND hwnd
)
805 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), FALSE
);
806 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), FALSE
);
807 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), FALSE
);
808 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
810 refresh_store_certs(hwnd
);
813 static PCCERT_CONTEXT
cert_mgr_index_to_cert(HWND hwnd
, int index
)
815 PCCERT_CONTEXT cert
= NULL
;
818 item
.mask
= LVIF_PARAM
;
821 if (SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_GETITEMW
, 0,
823 cert
= (PCCERT_CONTEXT
)item
.lParam
;
827 static void show_selected_cert(HWND hwnd
, int index
)
829 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
833 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
835 memset(&viewInfo
, 0, sizeof(viewInfo
));
836 viewInfo
.dwSize
= sizeof(viewInfo
);
837 viewInfo
.hwndParent
= hwnd
;
838 viewInfo
.pCertContext
= cert
;
839 /* FIXME: this should be modal */
840 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
844 static void get_cert_usages(PCCERT_CONTEXT cert
, LPWSTR
*str
)
846 PCERT_ENHKEY_USAGE usage
;
849 /* Get enhanced key usage. Have to check for a property and an extension
850 * separately, because CertGetEnhancedKeyUsage will succeed and return an
851 * empty usage if neither is set. Unfortunately an empty usage implies
852 * no usage is allowed, so we have to distinguish between the two cases.
854 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
857 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
858 if (!CertGetEnhancedKeyUsage(cert
,
859 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
861 HeapFree(GetProcessHeap(), 0, usage
);
865 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
868 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
869 if (!CertGetEnhancedKeyUsage(cert
,
870 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
872 HeapFree(GetProcessHeap(), 0, usage
);
880 if (usage
->cUsageIdentifier
)
882 static const WCHAR commaSpace
[] = { ',',' ',0 };
886 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
888 PCCRYPT_OID_INFO info
=
889 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
890 usage
->rgpszUsageIdentifier
[i
],
891 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
894 len
+= lstrlenW(info
->pwszName
);
896 len
+= strlen(usage
->rgpszUsageIdentifier
[i
]);
897 if (i
< usage
->cUsageIdentifier
- 1)
898 len
+= lstrlenW(commaSpace
);
900 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
903 for (i
= 0, ptr
= *str
; i
< usage
->cUsageIdentifier
; i
++)
905 PCCRYPT_OID_INFO info
=
906 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
907 usage
->rgpszUsageIdentifier
[i
],
908 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
912 lstrcpyW(ptr
, info
->pwszName
);
913 ptr
+= lstrlenW(info
->pwszName
);
917 LPCSTR src
= usage
->rgpszUsageIdentifier
[i
];
919 for (; *src
; ptr
++, src
++)
923 if (i
< usage
->cUsageIdentifier
- 1)
925 lstrcpyW(ptr
, commaSpace
);
926 ptr
+= lstrlenW(commaSpace
);
931 HeapFree(GetProcessHeap(), 0, usage
);
935 size
= MAX_STRING_LEN
* sizeof(WCHAR
);
936 *str
= HeapAlloc(GetProcessHeap(), 0, size
);
938 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_NONE
, *str
, size
);
943 size
= MAX_STRING_LEN
* sizeof(WCHAR
);
944 *str
= HeapAlloc(GetProcessHeap(), 0, size
);
946 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_ALL
, *str
, size
);
950 static void cert_mgr_show_cert_usages(HWND hwnd
, int index
)
952 HWND text
= GetDlgItem(hwnd
, IDC_MGR_PURPOSES
);
953 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
956 get_cert_usages(cert
, &str
);
959 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)str
);
960 HeapFree(GetProcessHeap(), 0, str
);
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
, ARRAY_SIZE(title
));
989 LoadStringW(hInstance
, warningID
, warning
, ARRAY_SIZE(warning
));
990 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
995 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
999 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1002 CertDeleteCertificateFromStore(cert
);
1004 } while (selection
>= 0);
1005 cert_mgr_clear_cert_selection(hwnd
);
1010 static void cert_mgr_do_export(HWND hwnd
)
1012 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1013 int selectionCount
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1015 if (selectionCount
== 1)
1017 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1022 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, selection
);
1026 CRYPTUI_WIZ_EXPORT_INFO info
;
1028 info
.dwSize
= sizeof(info
);
1029 info
.pwszExportFileName
= NULL
;
1030 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
1031 info
.u
.pCertContext
= cert
;
1033 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1037 else if (selectionCount
> 1)
1039 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1040 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1044 CRYPTUI_WIZ_EXPORT_INFO info
;
1047 info
.dwSize
= sizeof(info
);
1048 info
.pwszExportFileName
= NULL
;
1049 info
.dwSubjectChoice
=
1050 CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
;
1051 info
.u
.hCertStore
= store
;
1054 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1058 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1061 CertAddCertificateContextToStore(store
, cert
,
1062 CERT_STORE_ADD_ALWAYS
, NULL
);
1064 } while (selection
>= 0);
1065 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1066 CertCloseStore(store
, 0);
1071 static int cert_mgr_sort_by_text(HWND lv
, int col
, int index1
, int index2
)
1074 WCHAR buf1
[MAX_STRING_LEN
];
1075 WCHAR buf2
[MAX_STRING_LEN
];
1077 item
.cchTextMax
= ARRAY_SIZE(buf1
);
1078 item
.mask
= LVIF_TEXT
;
1079 item
.pszText
= buf1
;
1080 item
.iItem
= index1
;
1081 item
.iSubItem
= col
;
1082 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1083 item
.pszText
= buf2
;
1084 item
.iItem
= index2
;
1085 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1086 return lstrcmpW(buf1
, buf2
);
1089 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1091 return cert_mgr_sort_by_text((HWND
)lp
, 0, lp1
, lp2
);
1094 static int CALLBACK
cert_mgr_sort_by_issuer(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1096 return cert_mgr_sort_by_text((HWND
)lp
, 1, lp1
, lp2
);
1099 static int CALLBACK
cert_mgr_sort_by_date(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1101 PCCERT_CONTEXT cert1
= (PCCERT_CONTEXT
)lp1
;
1102 PCCERT_CONTEXT cert2
= (PCCERT_CONTEXT
)lp2
;
1103 return CompareFileTime(&cert1
->pCertInfo
->NotAfter
,
1104 &cert2
->pCertInfo
->NotAfter
);
1107 static int CALLBACK
cert_mgr_sort_by_friendly_name(LPARAM lp1
, LPARAM lp2
,
1110 return cert_mgr_sort_by_text((HWND
)lp
, 3, lp1
, lp2
);
1113 static LRESULT CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1116 struct CertMgrData
*data
;
1122 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
1123 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
1124 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
1126 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData
));
1129 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
1130 if (data
->imageList
)
1133 COLORREF backColor
= RGB(255, 0, 255);
1135 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
1136 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
1138 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
1139 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_SETIMAGELIST
,
1140 LVSIL_SMALL
, (LPARAM
)data
->imageList
);
1142 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
1143 data
->title
= pCryptUICertMgr
->pwszTitle
;
1145 initialize_purpose_selection(hwnd
);
1146 add_cert_columns(hwnd
);
1147 if (pCryptUICertMgr
->pwszTitle
)
1148 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1149 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
1150 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
, data
);
1151 show_store_certs(hwnd
, cert_mgr_index_to_store(tab
, 0));
1156 NMHDR
*hdr
= (NMHDR
*)lp
;
1161 cert_mgr_clear_cert_selection(hwnd
);
1163 case LVN_ITEMCHANGED
:
1165 NMITEMACTIVATE
*nm
= (NMITEMACTIVATE
*)lp
;
1166 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1167 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1169 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), numSelected
> 0);
1170 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), numSelected
> 0);
1171 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), numSelected
== 1);
1172 if (numSelected
== 1)
1173 cert_mgr_show_cert_usages(hwnd
, nm
->iItem
);
1175 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
1180 show_selected_cert(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
1184 NMLVKEYDOWN
*lvk
= (NMLVKEYDOWN
*)lp
;
1186 if (lvk
->wVKey
== VK_DELETE
)
1187 cert_mgr_do_remove(hwnd
);
1190 case LVN_COLUMNCLICK
:
1192 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
1193 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1195 /* FIXME: doesn't support swapping sort order between ascending
1198 switch (nmlv
->iSubItem
)
1201 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1202 (LPARAM
)cert_mgr_sort_by_subject
);
1205 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1206 (LPARAM
)cert_mgr_sort_by_issuer
);
1209 SendMessageW(lv
, LVM_SORTITEMS
, 0,
1210 (LPARAM
)cert_mgr_sort_by_date
);
1213 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1214 (LPARAM
)cert_mgr_sort_by_friendly_name
);
1225 case ((CBN_SELCHANGE
<< 16) | IDC_MGR_PURPOSE_SELECTION
):
1226 cert_mgr_clear_cert_selection(hwnd
);
1228 case IDC_MGR_IMPORT
:
1229 if (CryptUIWizImport(0, hwnd
, NULL
, NULL
,
1230 cert_mgr_current_store(hwnd
)))
1231 refresh_store_certs(hwnd
);
1233 case IDC_MGR_ADVANCED
:
1234 if (DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR_ADVANCED
),
1235 hwnd
, cert_mgr_advanced_dlg_proc
) == IDOK
)
1237 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
1239 LPWSTR curString
= NULL
;
1241 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
1244 len
= SendMessageW(cb
, CB_GETLBTEXTLEN
, index
, 0);
1245 curString
= HeapAlloc(GetProcessHeap(), 0,
1246 (len
+ 1) * sizeof(WCHAR
));
1247 SendMessageW(cb
, CB_GETLBTEXT
, index
, (LPARAM
)curString
);
1249 SendMessageW(cb
, CB_RESETCONTENT
, 0, 0);
1250 initialize_purpose_selection(hwnd
);
1253 index
= SendMessageW(cb
, CB_FINDSTRINGEXACT
, -1,
1256 SendMessageW(cb
, CB_SETCURSEL
, index
, 0);
1257 HeapFree(GetProcessHeap(), 0, curString
);
1259 refresh_store_certs(hwnd
);
1264 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1265 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1269 show_selected_cert(hwnd
, selection
);
1272 case IDC_MGR_EXPORT
:
1273 cert_mgr_do_export(hwnd
);
1275 case IDC_MGR_REMOVE
:
1276 cert_mgr_do_remove(hwnd
);
1279 free_certs(GetDlgItem(hwnd
, IDC_MGR_CERTS
));
1280 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1281 data
= (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1282 ImageList_Destroy(data
->imageList
);
1283 HeapFree(GetProcessHeap(), 0, data
);
1284 EndDialog(hwnd
, IDCANCEL
);
1292 /***********************************************************************
1293 * CryptUIDlgCertMgr (CRYPTUI.@)
1295 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
1297 TRACE("(%p)\n", pCryptUICertMgr
);
1299 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
1301 WARN("unexpected size %d\n", pCryptUICertMgr
->dwSize
);
1302 SetLastError(E_INVALIDARG
);
1305 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
1306 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
1310 /* FIXME: real names are unknown, functions are undocumented */
1311 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
1314 void *pvSystemStoreLocationPara
;
1315 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
1317 typedef struct _CRYPTUI_ENUM_DATA
1320 HCERTSTORE
*rghStore
;
1322 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
1323 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
1325 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
1328 /* Values for dwFlags */
1329 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
1331 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
1338 CRYPTUI_ENUM_DATA
*pEnumData
;
1339 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1341 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
1343 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
1350 CRYPTUI_ENUM_DATA
*pEnumData
;
1351 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1353 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
1367 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
1368 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
1371 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
1372 TVINSERTSTRUCTW tvis
;
1373 LPCWSTR localizedName
;
1376 tvis
.hParent
= NULL
;
1377 tvis
.hInsertAfter
= TVI_LAST
;
1378 tvis
.u
.item
.mask
= TVIF_TEXT
;
1379 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
1381 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(), 0,
1382 sizeof(struct StoreInfo
));
1386 storeInfo
->type
= SystemStore
;
1387 storeInfo
->u
.name
= HeapAlloc(GetProcessHeap(), 0,
1388 (lstrlenW(pvSystemStore
) + 1) * sizeof(WCHAR
));
1389 if (storeInfo
->u
.name
)
1391 tvis
.u
.item
.mask
|= TVIF_PARAM
;
1392 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1393 lstrcpyW(storeInfo
->u
.name
, pvSystemStore
);
1397 HeapFree(GetProcessHeap(), 0, storeInfo
);
1403 tvis
.u
.item
.pszText
= (LPWSTR
)localizedName
;
1406 tvis
.u
.item
.pszText
= (LPWSTR
)pvSystemStore
;
1407 /* FIXME: need a folder icon for the store too */
1409 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1413 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
1416 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1418 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
1419 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
1420 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
1421 hwnd
, enum_store_callback
);
1422 for (i
= 0; i
< pEnumData
->cStores
; i
++)
1426 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1427 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
1429 LPWSTR name
= HeapAlloc(GetProcessHeap(), 0, size
);
1433 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1434 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
1436 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(),
1437 0, sizeof(struct StoreInfo
));
1441 TVINSERTSTRUCTW tvis
;
1443 storeInfo
->type
= StoreHandle
;
1444 storeInfo
->u
.store
= pEnumData
->rghStore
[i
];
1445 tvis
.hParent
= NULL
;
1446 tvis
.hInsertAfter
= TVI_LAST
;
1447 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
1448 tvis
.u
.item
.pszText
= name
;
1449 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1450 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1453 HeapFree(GetProcessHeap(), 0, name
);
1459 static void free_store_info(HWND tree
)
1461 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
1468 memset(&item
, 0, sizeof(item
));
1469 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
1471 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1474 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1476 if (storeInfo
->type
== SystemStore
)
1477 HeapFree(GetProcessHeap(), 0, storeInfo
->u
.name
);
1478 HeapFree(GetProcessHeap(), 0, storeInfo
);
1480 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
1485 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
1487 WCHAR buf
[MAX_STRING_LEN
];
1491 memset(&item
, 0, sizeof(item
));
1492 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
1494 item
.cchTextMax
= ARRAY_SIZE(buf
);
1496 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1499 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1501 if (storeInfo
->type
== StoreHandle
)
1502 store
= storeInfo
->u
.store
;
1504 store
= CertOpenSystemStoreW(0, storeInfo
->u
.name
);
1508 /* It's implicitly a system store */
1509 store
= CertOpenSystemStoreW(0, buf
);
1514 struct SelectStoreInfo
1516 PCRYPTUI_SELECTSTORE_INFO_W info
;
1520 static LRESULT CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1523 struct SelectStoreInfo
*selectInfo
;
1530 selectInfo
= (struct SelectStoreInfo
*)lp
;
1531 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
1532 if (selectInfo
->info
->pwszTitle
)
1533 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1534 (LPARAM
)selectInfo
->info
->pwszTitle
);
1535 if (selectInfo
->info
->pwszText
)
1536 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
1537 (LPARAM
)selectInfo
->info
->pwszText
);
1538 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
1539 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
1540 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
1548 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1549 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
1550 TVM_GETNEXTITEM
, TVGN_CARET
, 0);
1552 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
1556 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
1558 if (selectInfo
->info
->pwszTitle
)
1559 pTitle
= selectInfo
->info
->pwszTitle
;
1562 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
, ARRAY_SIZE(title
));
1565 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
, ARRAY_SIZE(error
));
1566 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
1570 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
1572 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
1573 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
1574 selectInfo
->info
->pvArg
))
1576 selectInfo
->store
= store
;
1577 free_store_info(tree
);
1578 EndDialog(hwnd
, IDOK
);
1581 CertCloseStore(store
, 0);
1587 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
1588 EndDialog(hwnd
, IDCANCEL
);
1597 /***********************************************************************
1598 * CryptUIDlgSelectStoreW (CRYPTUI.@)
1600 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
1602 struct SelectStoreInfo selectInfo
= { info
, NULL
};
1604 TRACE("(%p)\n", info
);
1606 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
1608 WARN("unexpected size %d\n", info
->dwSize
);
1609 SetLastError(E_INVALIDARG
);
1612 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
1613 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
1614 return selectInfo
.store
;
1617 /***********************************************************************
1618 * CryptUIDlgSelectStoreA (CRYPTUI.@)
1620 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
1622 CRYPTUI_SELECTSTORE_INFO_W infoW
;
1626 TRACE("(%p)\n", info
);
1628 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
1630 WARN("unexpected size %d\n", info
->dwSize
);
1631 SetLastError(E_INVALIDARG
);
1634 memcpy(&infoW
, info
, sizeof(*info
));
1637 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
1638 infoW
.pwszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1639 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
1644 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
1645 infoW
.pwszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1646 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
1648 ret
= CryptUIDlgSelectStoreW(&infoW
);
1649 HeapFree(GetProcessHeap(), 0, infoW
.pwszText
);
1650 HeapFree(GetProcessHeap(), 0, infoW
.pwszTitle
);
1654 /***********************************************************************
1655 * CryptUIDlgViewCertificateA (CRYPTUI.@)
1657 BOOL WINAPI
CryptUIDlgViewCertificateA(
1658 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
1660 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
1661 LPWSTR title
= NULL
;
1664 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
1666 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
1667 if (pCertViewInfo
->szTitle
)
1669 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
1672 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1675 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
1677 viewInfo
.szTitle
= title
;
1685 if (pCertViewInfo
->cPropSheetPages
)
1687 FIXME("ignoring additional prop sheet pages\n");
1688 viewInfo
.cPropSheetPages
= 0;
1690 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
1691 HeapFree(GetProcessHeap(), 0, title
);
1696 struct ReadStringStruct
1703 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
1706 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
1707 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
1709 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
1711 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
1713 *pcb
= cch
* sizeof(WCHAR
);
1717 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
1719 struct ReadStringStruct string
;
1720 EDITSTREAM editstream
;
1722 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
1727 editstream
.dwCookie
= (DWORD_PTR
)&string
;
1728 editstream
.dwError
= 0;
1729 editstream
.pfnCallback
= read_text_callback
;
1730 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
1731 (LPARAM
)&editstream
);
1734 static void add_string_resource_to_control(HWND hwnd
, int id
)
1739 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1740 add_unformatted_text_to_control(hwnd
, str
, len
);
1743 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
1744 LONG len
, const PARAFORMAT2
*fmt
)
1746 add_unformatted_text_to_control(hwnd
, text
, len
);
1747 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
1750 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
1751 const PARAFORMAT2
*fmt
)
1756 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1757 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
1760 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
1766 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
1769 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1771 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
1776 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
1777 DWORD dwType
, DWORD dwFlags
)
1779 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
1783 /* Don't include NULL-terminator in output */
1784 DWORD len
= lstrlenW(name
);
1786 add_unformatted_text_to_control(hwnd
, name
, len
);
1787 HeapFree(GetProcessHeap(), 0, name
);
1791 static void add_icon_to_control(HWND hwnd
, int id
)
1794 IRichEditOle
*richEditOle
= NULL
;
1795 IOleObject
*object
= NULL
;
1797 LPOLECACHE oleCache
= NULL
;
1798 FORMATETC formatEtc
;
1800 IDataObject
*dataObject
= NULL
;
1801 HBITMAP bitmap
= NULL
;
1803 IOleClientSite
*clientSite
= NULL
;
1806 TRACE("(%p, %d)\n", hwnd
, id
);
1808 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
1811 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
1815 hr
= IOleObject_GetUserClassID(object
, &clsid
);
1818 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
1821 formatEtc
.cfFormat
= CF_BITMAP
;
1822 formatEtc
.ptd
= NULL
;
1823 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
1824 formatEtc
.lindex
= -1;
1825 formatEtc
.tymed
= TYMED_GDI
;
1826 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
1829 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
1830 (void**)&dataObject
);
1833 hr
= IRichEditOle_GetClientSite(richEditOle
, &clientSite
);
1836 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
1837 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
1840 stgm
.tymed
= TYMED_GDI
;
1841 stgm
.u
.hBitmap
= bitmap
;
1842 stgm
.pUnkForRelease
= NULL
;
1843 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
1847 reObject
.cbStruct
= sizeof(reObject
);
1848 reObject
.cp
= REO_CP_SELECTION
;
1849 reObject
.clsid
= clsid
;
1850 reObject
.poleobj
= object
;
1851 reObject
.pstg
= NULL
;
1852 reObject
.polesite
= clientSite
;
1853 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
1854 reObject
.dvaspect
= DVASPECT_CONTENT
;
1855 reObject
.dwFlags
= 0;
1856 reObject
.dwUser
= 0;
1858 IRichEditOle_InsertObject(richEditOle
, &reObject
);
1862 IOleClientSite_Release(clientSite
);
1864 IDataObject_Release(dataObject
);
1866 IOleCache_Release(oleCache
);
1868 IOleObject_Release(object
);
1870 IRichEditOle_Release(richEditOle
);
1873 #define MY_INDENT 200
1875 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
1878 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
1881 parFmt
.cbSize
= sizeof(parFmt
);
1882 parFmt
.dwMask
= PFM_STARTINDENT
;
1883 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1886 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
1887 lstrlenW(oidInfo
->pwszName
), &parFmt
);
1888 add_unformatted_text_to_control(hwnd
, &nl
, 1);
1898 /* The following list MUST be lexicographically sorted by OID */
1899 static struct OIDToString oidMap
[] = {
1900 /* 1.3.6.1.4.1.311.10.3.1 */
1901 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
1902 /* 1.3.6.1.4.1.311.10.3.4 */
1903 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
1904 /* 1.3.6.1.4.1.311.10.3.4.1 */
1905 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
1906 /* 1.3.6.1.4.1.311.10.3.5 */
1907 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
1908 /* 1.3.6.1.4.1.311.10.3.6 */
1909 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
1910 /* 1.3.6.1.4.1.311.10.3.7 */
1911 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
1912 /* 1.3.6.1.4.1.311.10.3.8 */
1913 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
1914 /* 1.3.6.1.4.1.311.10.3.9 */
1915 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
1916 /* 1.3.6.1.4.1.311.10.3.10 */
1917 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
1918 /* 1.3.6.1.4.1.311.10.3.11 */
1919 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
1920 /* 1.3.6.1.4.1.311.10.3.12 */
1921 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
1922 /* 1.3.6.1.4.1.311.10.3.13 */
1923 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
1924 /* 1.3.6.1.4.1.311.10.5.1 */
1925 { szOID_DRM
, IDS_PURPOSE_DRM
},
1926 /* 1.3.6.1.4.1.311.10.6.1 */
1927 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
1928 /* 1.3.6.1.4.1.311.10.6.2 */
1929 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
1930 /* 1.3.6.1.4.1.311.20.2.1 */
1931 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
1932 /* 1.3.6.1.4.1.311.20.2.2 */
1933 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
1934 /* 1.3.6.1.4.1.311.21.5 */
1935 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
1936 /* 1.3.6.1.4.1.311.21.6 */
1937 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
1938 /* 1.3.6.1.4.1.311.21.19 */
1939 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
1940 /* 1.3.6.1.5.5.7.3.1 */
1941 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
1942 /* 1.3.6.1.5.5.7.3.2 */
1943 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
1944 /* 1.3.6.1.5.5.7.3.3 */
1945 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
1946 /* 1.3.6.1.5.5.7.3.4 */
1947 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
1948 /* 1.3.6.1.5.5.7.3.5 */
1949 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
1950 /* 1.3.6.1.5.5.7.3.6 */
1951 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
1952 /* 1.3.6.1.5.5.7.3.7 */
1953 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
1954 /* 1.3.6.1.5.5.7.3.8 */
1955 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
1958 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
1960 int indexHigh
= ARRAY_SIZE(oidMap
) - 1, indexLow
= 0;
1962 while (indexLow
<= indexHigh
)
1964 int cmp
, i
= (indexLow
+ indexHigh
) / 2;
1965 if (!(cmp
= strcmp(oid
, oidMap
[i
].oid
)))
1975 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
1977 struct OIDToString
*entry
;
1981 parFmt
.cbSize
= sizeof(parFmt
);
1982 parFmt
.dwMask
= PFM_STARTINDENT
;
1983 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1984 if ((entry
= findSupportedOID(oid
)))
1986 WCHAR
*str
, *linebreak
, *ptr
;
1987 BOOL multiline
= FALSE
;
1990 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
1993 if ((linebreak
= wmemchr(ptr
, '\n', len
)))
1995 WCHAR copy
[MAX_STRING_LEN
];
1998 /* The source string contains a newline, which the richedit
1999 * control won't find since it's interpreted as a paragraph
2000 * break. Therefore copy up to the newline. lstrcpynW always
2001 * NULL-terminates, so pass one more than the length of the
2002 * source line so the copy includes the entire line and the
2005 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
2006 add_text_with_paraformat_to_control(text
, copy
,
2007 linebreak
- ptr
, &parFmt
);
2008 ptr
= linebreak
+ 1;
2009 add_unformatted_text_to_control(text
, &nl
, 1);
2011 else if (multiline
&& *ptr
)
2013 /* Add the last line */
2014 add_text_with_paraformat_to_control(text
, ptr
,
2015 len
- (ptr
- str
), &parFmt
);
2016 add_unformatted_text_to_control(text
, &nl
, 1);
2018 } while (linebreak
);
2021 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
2022 add_unformatted_text_to_control(text
, &nl
, 1);
2027 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
2028 (strlen(oid
) + 1) * sizeof(WCHAR
));
2035 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
2038 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
2040 add_unformatted_text_to_control(text
, &nl
, 1);
2041 HeapFree(GetProcessHeap(), 0, oidW
);
2046 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
2047 BOOL
*anyUsageAdded
)
2049 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
2051 CHARFORMATW charFmt
;
2052 PCERT_EXTENSION policyExt
;
2053 if (!*anyUsageAdded
)
2057 parFmt
.cbSize
= sizeof(parFmt
);
2058 parFmt
.dwMask
= PFM_STARTINDENT
;
2059 parFmt
.dxStartIndent
= MY_INDENT
;
2060 add_string_resource_with_paraformat_to_control(text
,
2061 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2062 add_unformatted_text_to_control(text
, &nl
, 1);
2063 *anyUsageAdded
= TRUE
;
2065 memset(&charFmt
, 0, sizeof(charFmt
));
2066 charFmt
.cbSize
= sizeof(charFmt
);
2067 charFmt
.dwMask
= CFM_BOLD
;
2068 charFmt
.dwEffects
= 0;
2069 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2070 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
2071 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
2073 CERT_POLICIES_INFO
*policies
;
2076 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
2077 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2078 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2082 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
2086 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2087 add_local_oid_text_to_control(text
,
2088 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2089 pszPolicyQualifierId
);
2091 LocalFree(policies
);
2095 add_oid_text_to_control(text
, any_app_policy
);
2098 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
2099 BOOL
*anyUsageAdded
)
2103 BOOL badUsages
= FALSE
;
2105 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
2107 CHARFORMATW charFmt
;
2108 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
2109 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
2113 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
2117 if (!*anyUsageAdded
)
2121 parFmt
.cbSize
= sizeof(parFmt
);
2122 parFmt
.dwMask
= PFM_STARTINDENT
;
2123 parFmt
.dxStartIndent
= MY_INDENT
;
2124 add_string_resource_with_paraformat_to_control(text
,
2125 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2126 add_unformatted_text_to_control(text
, &nl
, 1);
2127 *anyUsageAdded
= TRUE
;
2129 memset(&charFmt
, 0, sizeof(charFmt
));
2130 charFmt
.cbSize
= sizeof(charFmt
);
2131 charFmt
.dwMask
= CFM_BOLD
;
2132 charFmt
.dwEffects
= 0;
2133 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
2135 if (!usage
->cUsageIdentifier
)
2136 add_oid_text_to_control(text
, any_cert_policy
);
2138 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2139 add_local_oid_text_to_control(text
,
2140 usage
->rgpszUsageIdentifier
[i
]);
2144 HeapFree(GetProcessHeap(), 0, usage
);
2154 static void set_policy_text(HWND text
,
2155 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2157 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
2158 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
2160 if (pCertViewInfo
->cPurposes
)
2164 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
2166 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
2167 includeCertUsages
= TRUE
;
2168 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
2169 szOID_ANY_APPLICATION_POLICY
))
2170 includeAppUsages
= TRUE
;
2176 includeAppUsages
= includeCertUsages
= TRUE
;
2177 if (includeAppUsages
)
2178 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
2179 if (includeCertUsages
)
2180 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
2186 parFmt
.cbSize
= sizeof(parFmt
);
2187 parFmt
.dwMask
= PFM_STARTINDENT
;
2188 parFmt
.dxStartIndent
= MY_INDENT
;
2189 add_string_resource_with_paraformat_to_control(text
,
2190 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
2194 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
2197 CRYPT_OBJID_BLOB
*ret
= NULL
;
2200 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
2204 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2205 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2206 pszPolicyQualifierId
, policyOid
))
2207 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2213 static WCHAR
*get_cps_str_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2215 LPWSTR qualifierStr
= NULL
;
2216 CERT_NAME_VALUE
*qualifierValue
;
2219 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
2220 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2221 &qualifierValue
, &size
))
2223 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
2224 &qualifierValue
->Value
, NULL
, 0);
2225 qualifierStr
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
2227 CertRDNValueToStrW(qualifierValue
->dwValueType
,
2228 &qualifierValue
->Value
, qualifierStr
, size
);
2229 LocalFree(qualifierValue
);
2231 return qualifierStr
;
2234 static WCHAR
*get_user_notice_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2237 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
2240 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
2241 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
2242 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2243 &qualifierValue
, &size
))
2245 str
= HeapAlloc(GetProcessHeap(), 0,
2246 (lstrlenW(qualifierValue
->pszDisplayText
) + 1) * sizeof(WCHAR
));
2248 lstrcpyW(str
, qualifierValue
->pszDisplayText
);
2249 LocalFree(qualifierValue
);
2254 struct IssuerStatement
2260 static void set_issuer_statement(HWND hwnd
,
2261 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2263 PCERT_EXTENSION policyExt
;
2265 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
2266 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
2267 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
2268 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
2270 CERT_POLICIES_INFO
*policies
;
2273 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
2274 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2275 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2277 CRYPT_OBJID_BLOB
*qualifier
;
2278 LPWSTR cps
= NULL
, userNotice
= NULL
;
2280 if ((qualifier
= find_policy_qualifier(policies
,
2281 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
2282 cps
= get_cps_str_from_qualifier(qualifier
);
2283 if ((qualifier
= find_policy_qualifier(policies
,
2284 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
2285 userNotice
= get_user_notice_from_qualifier(qualifier
);
2286 if (cps
|| userNotice
)
2288 struct IssuerStatement
*issuerStatement
=
2289 HeapAlloc(GetProcessHeap(), 0, sizeof(struct IssuerStatement
));
2291 if (issuerStatement
)
2293 issuerStatement
->cps
= cps
;
2294 issuerStatement
->userNotice
= userNotice
;
2295 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
2296 SetWindowLongPtrW(hwnd
, DWLP_USER
,
2297 (ULONG_PTR
)issuerStatement
);
2300 LocalFree(policies
);
2305 static void set_cert_info(HWND hwnd
,
2306 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2308 CHARFORMATW charFmt
;
2310 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
2311 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
2312 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2313 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
2314 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
2315 pCertViewInfo
->idxCounterSigner
);
2316 CRYPT_PROVIDER_CERT
*root
=
2317 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
2319 if (!provSigner
->pChainContext
||
2320 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2321 CERT_TRUST_IS_PARTIAL_CHAIN
))
2322 add_icon_to_control(icon
, IDB_CERT_WARNING
);
2323 else if (!root
->fTrustedRoot
)
2324 add_icon_to_control(icon
, IDB_CERT_ERROR
);
2326 add_icon_to_control(icon
, IDB_CERT
);
2328 memset(&charFmt
, 0, sizeof(charFmt
));
2329 charFmt
.cbSize
= sizeof(charFmt
);
2330 charFmt
.dwMask
= CFM_BOLD
;
2331 charFmt
.dwEffects
= CFE_BOLD
;
2332 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2333 /* FIXME: vertically center text */
2334 parFmt
.cbSize
= sizeof(parFmt
);
2335 parFmt
.dwMask
= PFM_STARTINDENT
;
2336 parFmt
.dxStartIndent
= MY_INDENT
;
2337 add_string_resource_with_paraformat_to_control(text
,
2338 IDS_CERTIFICATEINFORMATION
, &parFmt
);
2340 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
2341 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2342 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
2343 add_string_resource_with_paraformat_to_control(text
,
2344 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
2345 else if (!provSigner
->pChainContext
||
2346 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2347 CERT_TRUST_IS_PARTIAL_CHAIN
))
2348 add_string_resource_with_paraformat_to_control(text
,
2349 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
2350 else if (!root
->fTrustedRoot
)
2352 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
2353 add_string_resource_with_paraformat_to_control(text
,
2354 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
2356 add_string_resource_with_paraformat_to_control(text
,
2357 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
2361 set_policy_text(text
, pCertViewInfo
);
2362 set_issuer_statement(hwnd
, pCertViewInfo
);
2366 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
2367 DWORD nameFlags
, int heading
)
2370 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2371 CHARFORMATW charFmt
;
2374 memset(&charFmt
, 0, sizeof(charFmt
));
2375 charFmt
.cbSize
= sizeof(charFmt
);
2376 charFmt
.dwMask
= CFM_BOLD
;
2377 charFmt
.dwEffects
= CFE_BOLD
;
2378 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2379 parFmt
.cbSize
= sizeof(parFmt
);
2380 parFmt
.dwMask
= PFM_STARTINDENT
;
2381 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2382 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
2383 charFmt
.dwEffects
= 0;
2384 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2385 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2387 add_unformatted_text_to_control(text
, &nl
, 1);
2388 add_unformatted_text_to_control(text
, &nl
, 1);
2389 add_unformatted_text_to_control(text
, &nl
, 1);
2393 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
2395 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
2399 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
2400 FileTimeToSystemTime(fileTime
, &sysTime
);
2401 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
, ARRAY_SIZE(date
));
2402 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
2405 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
2408 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2409 CHARFORMATW charFmt
;
2412 memset(&charFmt
, 0, sizeof(charFmt
));
2413 charFmt
.cbSize
= sizeof(charFmt
);
2414 charFmt
.dwMask
= CFM_BOLD
;
2415 charFmt
.dwEffects
= CFE_BOLD
;
2416 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2417 parFmt
.cbSize
= sizeof(parFmt
);
2418 parFmt
.dwMask
= PFM_STARTINDENT
;
2419 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2420 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
2422 charFmt
.dwEffects
= 0;
2423 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2424 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
2425 charFmt
.dwEffects
= CFE_BOLD
;
2426 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2427 add_string_resource_to_control(text
, IDS_VALID_TO
);
2428 charFmt
.dwEffects
= 0;
2429 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2430 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
2431 add_unformatted_text_to_control(text
, &nl
, 1);
2434 static void set_general_info(HWND hwnd
,
2435 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2437 set_cert_info(hwnd
, pCertViewInfo
);
2438 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
2439 IDS_SUBJECT_HEADING
);
2440 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
2441 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
2442 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
2445 static LRESULT CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2450 struct IssuerStatement
*issuerStatement
;
2455 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
2456 issuerStatement
= (struct IssuerStatement
*)lp
;
2457 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
2458 lstrlenW(issuerStatement
->userNotice
));
2459 if (issuerStatement
->cps
)
2460 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
2462 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
2468 EndDialog(hwnd
, IDOK
);
2473 IBindCtx
*bctx
= NULL
;
2476 CreateBindCtx(0, &bctx
);
2477 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2478 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
2479 HLNF_OPENINNEWWINDOW
, 0);
2480 IBindCtx_Release(bctx
);
2488 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
2490 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
2491 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
2494 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2497 PROPSHEETPAGEW
*page
;
2498 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2500 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2505 page
= (PROPSHEETPAGEW
*)lp
;
2506 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
2507 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
2508 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
2509 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
2510 set_general_info(hwnd
, pCertViewInfo
);
2515 case IDC_ADDTOSTORE
:
2516 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
2518 case IDC_ISSUERSTATEMENT
:
2520 struct IssuerStatement
*issuerStatement
=
2521 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2523 if (issuerStatement
)
2525 if (issuerStatement
->userNotice
)
2526 show_user_notice(hwnd
, issuerStatement
);
2527 else if (issuerStatement
->cps
)
2529 IBindCtx
*bctx
= NULL
;
2531 CreateBindCtx(0, &bctx
);
2532 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
2533 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
2534 IBindCtx_Release(bctx
);
2545 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
2546 PROPSHEETPAGEW
*page
)
2548 struct IssuerStatement
*issuerStatement
;
2554 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2555 if (issuerStatement
)
2557 HeapFree(GetProcessHeap(), 0, issuerStatement
->cps
);
2558 HeapFree(GetProcessHeap(), 0, issuerStatement
->userNotice
);
2559 HeapFree(GetProcessHeap(), 0, issuerStatement
);
2566 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2567 PROPSHEETPAGEW
*page
)
2569 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2570 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2571 page
->dwFlags
= PSP_USECALLBACK
;
2572 page
->pfnCallback
= general_callback_proc
;
2573 page
->hInstance
= hInstance
;
2574 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
2575 page
->pfnDlgProc
= general_dlg_proc
;
2576 page
->lParam
= (LPARAM
)pCertViewInfo
;
2579 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
2581 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
2583 static const WCHAR fmt
[] = { 'V','%','d',0 };
2584 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, 12 * sizeof(WCHAR
));
2587 swprintf(buf
, 12, fmt
, cert
->pCertInfo
->dwVersion
);
2591 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
2593 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, (cb
* 3 + 1) * sizeof(WCHAR
));
2597 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2601 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
2602 swprintf(ptr
, 4, fmt
, ((BYTE
*)pb
)[i
]);
2607 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
2609 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
2610 cert
->pCertInfo
->SerialNumber
.cbData
);
2613 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
2615 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2616 CERT_NAME_ISSUER_FLAG
);
2619 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
2622 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
2623 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, NULL
, 0);
2627 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2629 CertNameToStrW(X509_ASN_ENCODING
, name
,
2630 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, str
, len
);
2635 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
2637 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
2640 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
2642 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2645 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
2647 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
2650 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
2652 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
2657 /* FIXME: format isn't quite right, want time too */
2658 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
2659 FileTimeToSystemTime(fileTime
, &sysTime
);
2660 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
2663 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2665 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
2671 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
2673 return format_long_date(&cert
->pCertInfo
->NotBefore
);
2676 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
2678 return format_long_date(&cert
->pCertInfo
->NotAfter
);
2681 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
2683 PCCRYPT_OID_INFO oidInfo
;
2686 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2687 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
2690 WCHAR fmt
[MAX_STRING_LEN
];
2692 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
, ARRAY_SIZE(fmt
)))
2696 /* Allocate the output buffer. Use the number of bytes in the
2697 * public key as a conservative (high) estimate for the number of
2698 * digits in its output.
2699 * The output is of the form (in English)
2700 * "<public key algorithm> (<public key bit length> bits)".
2701 * Ordinarily having two positional parameters in a string is not a
2702 * good idea, but as this isn't a sentence fragment, it shouldn't
2703 * be word-order dependent.
2705 len
= lstrlenW(fmt
) + lstrlenW(oidInfo
->pwszName
) +
2706 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8;
2707 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(*buf
));
2711 args
[0] = (DWORD_PTR
)oidInfo
->pwszName
;
2712 args
[1] = CertGetPublicKeyLength(X509_ASN_ENCODING
,
2713 &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2714 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
2715 fmt
, 0, 0, buf
, len
, (__ms_va_list
*)args
);
2722 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
2724 return format_hex_string(
2725 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
2726 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
2729 struct field_value_data
;
2732 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2733 BOOL
*pfPropertiesChanged
;
2735 struct field_value_data
*fields
;
2738 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
2740 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
2742 struct field_value_data
2744 create_detailed_value_func create
;
2745 LPWSTR detailed_value
;
2749 static void add_field_value_data(struct detail_data
*data
,
2750 create_detailed_value_func create
, void *param
)
2753 data
->fields
= HeapReAlloc(GetProcessHeap(), 0, data
->fields
,
2754 (data
->cFields
+ 1) * sizeof(struct field_value_data
));
2756 data
->fields
= HeapAlloc(GetProcessHeap(), 0,
2757 sizeof(struct field_value_data
));
2760 data
->fields
[data
->cFields
].create
= create
;
2761 data
->fields
[data
->cFields
].detailed_value
= NULL
;
2762 data
->fields
[data
->cFields
].param
= param
;
2767 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2768 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2771 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2773 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
2776 item
.pszText
= field
;
2777 item
.lParam
= (LPARAM
)data
;
2778 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2781 item
.pszText
= value
;
2783 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
2785 add_field_value_data(data
, create
, param
);
2788 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2789 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2791 WCHAR buf
[MAX_STRING_LEN
];
2793 LoadStringW(hInstance
, id
, buf
, ARRAY_SIZE(buf
));
2794 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
2800 field_format_func format
;
2801 create_detailed_value_func create_detailed_value
;
2804 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
2805 const struct v1_field
*field
)
2807 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
2811 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
2812 field
->create_detailed_value
, NULL
);
2813 HeapFree(GetProcessHeap(), 0, val
);
2817 static const struct v1_field v1_fields
[] = {
2818 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
2819 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
2820 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
2821 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
2822 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
2823 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
2824 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
2825 field_format_detailed_public_key
}
2828 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
2831 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2833 /* The last item in v1_fields is the public key, which is not in the loop
2834 * because it's a special case.
2836 for (i
= 0; i
< ARRAY_SIZE(v1_fields
) - 1; i
++)
2837 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2838 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
2839 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2842 static WCHAR
*crypt_format_extension(const CERT_EXTENSION
*ext
, DWORD formatStrType
)
2847 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2848 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
2850 str
= HeapAlloc(GetProcessHeap(), 0, size
);
2851 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2852 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
2857 static WCHAR
*field_format_extension_hex_with_ascii(const CERT_EXTENSION
*ext
)
2861 if (ext
->Value
.cbData
)
2863 /* The output is formatted as:
2864 * <hex bytes> <ascii bytes>\n
2865 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
2866 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
2867 * the byte is not printable.
2868 * So, for example, the extension value consisting of the following
2870 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
2871 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
2873 * 30 14 31 12 30 10 06 03 0.1.0...
2874 * 55 04 03 13 09 4a 75 61 U....Jua
2875 * 6e 20 4c 61 6e 67 n Lang
2876 * The allocation size therefore requires:
2877 * - 4 characters per character in an 8-byte line
2878 * (2 for the hex format, one for the space, one for the ASCII value)
2879 * - 3 more characters per 8-byte line (two spaces and a newline)
2880 * - 1 character for the terminating nul
2881 * FIXME: should use a fixed-width font for this
2883 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
2885 str
= HeapAlloc(GetProcessHeap(), 0,
2886 (lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
2889 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2893 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
2895 /* Output as hex bytes first */
2896 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
2897 swprintf(ptr
, 4, fmt
, ext
->Value
.pbData
[j
]);
2898 /* Pad the hex output with spaces for alignment */
2899 if (j
== ext
->Value
.cbData
&& j
% 8)
2901 static const WCHAR pad
[] = { ' ',' ',' ' };
2903 for (; j
% 8; j
++, ptr
+= ARRAY_SIZE(pad
))
2904 memcpy(ptr
, pad
, sizeof(pad
));
2906 /* The last swprintf included a space, so just insert one
2907 * more space between the hex bytes and the ASCII output
2910 /* Output as ASCII bytes */
2911 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
2913 if (iswprint(ext
->Value
.pbData
[j
]) &&
2914 !iswspace(ext
->Value
.pbData
[j
]))
2915 *ptr
= ext
->Value
.pbData
[j
];
2927 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
2929 PCERT_EXTENSION ext
= param
;
2930 LPWSTR str
= crypt_format_extension(ext
,
2931 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
2934 str
= field_format_extension_hex_with_ascii(ext
);
2938 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
2939 PCERT_EXTENSION ext
)
2941 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2943 LPWSTR val
= crypt_format_extension(ext
, 0);
2946 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
2947 val
, field_format_detailed_extension
, ext
);
2950 DWORD len
= strlen(ext
->pszObjId
);
2951 LPWSTR oidW
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
2957 for (i
= 0; i
<= len
; i
++)
2958 oidW
[i
] = ext
->pszObjId
[i
];
2959 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
2960 field_format_detailed_extension
, ext
);
2961 HeapFree(GetProcessHeap(), 0, oidW
);
2964 HeapFree(GetProcessHeap(), 0, val
);
2967 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
2970 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2972 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2973 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
2976 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
2979 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2981 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2982 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
2983 add_cert_extension_detail(hwnd
, data
,
2984 &cert
->pCertInfo
->rgExtension
[i
]);
2987 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
2989 struct prop_id_to_string_id
2993 BOOL prop_is_string
;
2994 prop_to_value_func prop_to_value
;
2997 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
3001 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
3002 ext
.fCritical
= FALSE
;
3003 ext
.Value
.pbData
= pb
;
3004 ext
.Value
.cbData
= cb
;
3005 return crypt_format_extension(&ext
, 0);
3008 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
3009 * disabled for read-only certificates, but native doesn't appear to do that.
3011 static const struct prop_id_to_string_id prop_id_map
[] = {
3012 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
3013 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
3014 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
3015 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
3016 format_enhanced_key_usage_value
},
3019 static void add_properties(HWND hwnd
, struct detail_data
*data
)
3022 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
3024 for (i
= 0; i
< ARRAY_SIZE(prop_id_map
); i
++)
3028 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
3034 /* FIXME: MS adds a separate value for the signature hash
3037 pb
= HeapAlloc(GetProcessHeap(), 0, cb
);
3040 if (CertGetCertificateContextProperty(cert
,
3041 prop_id_map
[i
].prop
, pb
, &cb
))
3043 if (prop_id_map
[i
].prop_is_string
)
3046 /* Don't double-free pb */
3050 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
3052 HeapFree(GetProcessHeap(), 0, pb
);
3054 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
3060 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
3062 add_v1_fields(hwnd
, data
);
3063 add_all_extensions(hwnd
, data
);
3064 add_properties(hwnd
, data
);
3067 struct selection_list_item
3070 add_fields_func add
;
3073 static const struct selection_list_item listItems
[] = {
3074 { IDS_FIELDS_ALL
, add_all_fields
},
3075 { IDS_FIELDS_V1
, add_v1_fields
},
3076 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
3077 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
3078 { IDS_FIELDS_PROPERTIES
, add_properties
},
3081 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
3083 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3084 WCHAR buf
[MAX_STRING_LEN
];
3087 for (i
= 0; i
< ARRAY_SIZE(listItems
); i
++)
3091 LoadStringW(hInstance
, listItems
[i
].id
, buf
, ARRAY_SIZE(buf
));
3092 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
3093 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
3095 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
3098 static void create_listview_columns(HWND hwnd
)
3100 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3102 WCHAR buf
[MAX_STRING_LEN
];
3105 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
3106 GetWindowRect(lv
, &rc
);
3107 LoadStringW(hInstance
, IDS_FIELD
, buf
, ARRAY_SIZE(buf
));
3108 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
3109 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
3110 column
.pszText
= buf
;
3111 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3112 LoadStringW(hInstance
, IDS_VALUE
, buf
, ARRAY_SIZE(buf
));
3113 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
3116 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
3118 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3120 if (sel
>= 0 && sel
< ARRAY_SIZE(listItems
))
3122 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
3123 listItems
[sel
].add(list
, data
);
3127 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
3129 create_show_list(hwnd
, data
);
3130 create_listview_columns(hwnd
);
3131 set_fields_selection(hwnd
, data
, 0);
3134 static void add_purpose(HWND hwnd
, LPCSTR oid
)
3136 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3137 PCRYPT_OID_INFO info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3138 sizeof(CRYPT_OID_INFO
));
3142 char *oidCopy
= HeapAlloc(GetProcessHeap(), 0, strlen(oid
) + 1);
3148 strcpy(oidCopy
, oid
);
3149 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
3150 info
->pszOID
= oidCopy
;
3151 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
3152 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
3153 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3154 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3156 item
.lParam
= (LPARAM
)info
;
3157 item
.pszText
= oidCopy
;
3158 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3161 HeapFree(GetProcessHeap(), 0, info
);
3165 static BOOL
is_valid_oid(LPCSTR oid
)
3169 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
3171 else if (oid
[1] != '.')
3178 BOOL expectNum
= TRUE
;
3180 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
3186 else if (*(ptr
+ 1) == '.')
3193 else if (!(*(ptr
+ 1)))
3203 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
3205 return find_oid_in_list(GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
), oid
)
3209 #define MAX_PURPOSE 255
3211 static LRESULT CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
3212 WPARAM wp
, LPARAM lp
)
3215 char buf
[MAX_PURPOSE
+ 1];
3220 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
3222 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
3223 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
3229 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
3231 /* Show/hide scroll bar on description depending on how much
3234 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
3235 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3237 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3244 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
, ARRAY_SIZE(buf
),
3248 /* An empty purpose is the same as cancelling */
3249 EndDialog(hwnd
, IDCANCEL
);
3252 else if (!is_valid_oid(buf
))
3254 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3256 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
, ARRAY_SIZE(error
));
3257 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
, ARRAY_SIZE(title
));
3258 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
3260 else if (is_oid_in_list(
3261 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
3263 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3265 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
, error
,
3267 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
, ARRAY_SIZE(title
));
3268 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
3272 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3274 add_purpose(parent
, buf
);
3275 EndDialog(hwnd
, wp
);
3280 EndDialog(hwnd
, wp
);
3291 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
3296 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
3298 name
= HeapAlloc(GetProcessHeap(), 0, cb
);
3301 if (!CertGetCertificateContextProperty(cert
, prop
, name
, &cb
))
3303 HeapFree(GetProcessHeap(), 0, name
);
3311 static void redraw_states(HWND list
, BOOL enabled
)
3313 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
3315 for (i
= 0; i
< items
; i
++)
3317 BOOL change
= FALSE
;
3320 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
3321 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
3322 * to be a handy macro for it.
3327 if (state
== CheckBitmapIndexDisabledChecked
)
3329 state
= CheckBitmapIndexChecked
;
3332 if (state
== CheckBitmapIndexDisabledUnchecked
)
3334 state
= CheckBitmapIndexUnchecked
;
3340 if (state
== CheckBitmapIndexChecked
)
3342 state
= CheckBitmapIndexDisabledChecked
;
3345 if (state
== CheckBitmapIndexUnchecked
)
3347 state
= CheckBitmapIndexDisabledUnchecked
;
3355 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
3356 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3357 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
3363 PurposeEnableAll
= 0,
3365 PurposeEnableSelected
3368 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
3370 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3374 case PurposeEnableAll
:
3375 case PurposeDisableAll
:
3376 EnableWindow(lv
, FALSE
);
3377 redraw_states(lv
, FALSE
);
3378 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
3380 case PurposeEnableSelected
:
3381 EnableWindow(lv
, TRUE
);
3382 redraw_states(lv
, TRUE
);
3383 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
3387 struct edit_cert_data
3389 PCCERT_CONTEXT cert
;
3390 BOOL
*pfPropertiesChanged
;
3391 HIMAGELIST imageList
;
3394 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
3396 PCCERT_CONTEXT cert
= data
->cert
;
3397 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3398 PCERT_ENHKEY_USAGE usage
;
3402 PurposeSelection purposeSelection
= PurposeEnableAll
;
3404 GetWindowRect(lv
, &rc
);
3405 column
.mask
= LVCF_WIDTH
;
3406 column
.cx
= rc
.right
- rc
.left
;
3407 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3408 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
3410 /* Get enhanced key usage. Have to check for a property and an extension
3411 * separately, because CertGetEnhancedKeyUsage will succeed and return an
3412 * empty usage if neither is set. Unfortunately an empty usage implies
3413 * no usage is allowed, so we have to distinguish between the two cases.
3415 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
3418 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3419 if (!CertGetEnhancedKeyUsage(cert
,
3420 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3422 HeapFree(GetProcessHeap(), 0, usage
);
3425 else if (usage
->cUsageIdentifier
)
3426 purposeSelection
= PurposeEnableSelected
;
3428 purposeSelection
= PurposeDisableAll
;
3430 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
3433 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3434 if (!CertGetEnhancedKeyUsage(cert
,
3435 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3437 HeapFree(GetProcessHeap(), 0, usage
);
3440 else if (usage
->cUsageIdentifier
)
3441 purposeSelection
= PurposeEnableAll
;
3443 purposeSelection
= PurposeDisableAll
;
3447 purposeSelection
= PurposeEnableAll
;
3454 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
3456 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
3457 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
3460 add_known_usage(lv
, info
, CheckBitmapIndexDisabledChecked
);
3462 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
3464 HeapFree(GetProcessHeap(), 0, usage
);
3467 add_known_usages_to_list(lv
, CheckBitmapIndexDisabledChecked
);
3468 select_purposes(hwnd
, purposeSelection
);
3469 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
3473 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
3475 PCCERT_CONTEXT cert
= data
->cert
;
3478 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
3480 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
3482 HeapFree(GetProcessHeap(), 0, str
);
3484 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
3486 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
3488 HeapFree(GetProcessHeap(), 0, str
);
3490 show_cert_usages(hwnd
, data
);
3493 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
3498 CRYPT_DATA_BLOB blob
;
3500 blob
.pbData
= (BYTE
*)str
;
3501 blob
.cbData
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
3502 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
3505 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
3508 #define WM_REFRESH_VIEW WM_USER + 0
3510 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
3512 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
3513 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
3517 #define MAX_FRIENDLY_NAME 40
3518 #define MAX_DESCRIPTION 255
3520 static void apply_general_changes(HWND hwnd
)
3522 WCHAR buf
[MAX_DESCRIPTION
+ 1];
3523 struct edit_cert_data
*data
=
3524 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3526 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
3527 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
3528 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
3529 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
3530 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
3532 /* Setting a NULL usage removes the enhanced key usage property. */
3533 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
3535 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
3537 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3539 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3541 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
3543 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3544 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3545 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
3548 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3550 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3551 for (i
= 0; i
< purposes
; i
++)
3554 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
3556 int state
= item
.state
>> 12;
3558 if (state
== CheckBitmapIndexChecked
)
3560 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
3562 if (usage
.cUsageIdentifier
)
3563 usage
.rgpszUsageIdentifier
=
3564 HeapReAlloc(GetProcessHeap(), 0,
3565 usage
.rgpszUsageIdentifier
,
3566 (usage
.cUsageIdentifier
+ 1) * sizeof(LPSTR
));
3568 usage
.rgpszUsageIdentifier
=
3569 HeapAlloc(GetProcessHeap(), 0, sizeof(LPSTR
));
3570 if (usage
.rgpszUsageIdentifier
)
3571 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
3572 (LPSTR
)info
->pszOID
;
3576 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3577 HeapFree(GetProcessHeap(), 0, usage
.rgpszUsageIdentifier
);
3579 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
3580 if (data
->pfPropertiesChanged
)
3581 *data
->pfPropertiesChanged
= TRUE
;
3584 static LRESULT CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
3585 WPARAM wp
, LPARAM lp
)
3587 PROPSHEETPAGEW
*page
;
3589 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3595 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3596 struct detail_data
*detailData
;
3597 struct edit_cert_data
*editData
;
3599 page
= (PROPSHEETPAGEW
*)lp
;
3600 detailData
= (struct detail_data
*)page
->lParam
;
3601 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
3602 MAX_FRIENDLY_NAME
, 0);
3603 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
3604 ShowScrollBar(description
, SB_VERT
, FALSE
);
3605 editData
= HeapAlloc(GetProcessHeap(), 0,
3606 sizeof(struct edit_cert_data
));
3609 editData
->imageList
= ImageList_Create(16, 16,
3610 ILC_COLOR4
| ILC_MASK
, 4, 0);
3611 if (editData
->imageList
)
3614 COLORREF backColor
= RGB(255, 0, 255);
3616 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
3617 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
3619 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
3621 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
3622 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
3623 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
3624 set_general_cert_properties(hwnd
, editData
);
3630 NMHDR
*hdr
= (NMHDR
*)lp
;
3636 nm
= (NMITEMACTIVATE
*)lp
;
3637 toggle_usage(hwnd
, nm
->iItem
);
3638 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3641 apply_general_changes(hwnd
);
3650 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3651 if (LOWORD(wp
) == IDC_DESCRIPTION
)
3653 /* Show/hide scroll bar on description depending on how much
3656 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3657 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3659 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3665 case IDC_ADD_PURPOSE
:
3666 if (DialogBoxParamW(hInstance
,
3667 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
3668 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
3669 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3671 case IDC_ENABLE_ALL_PURPOSES
:
3672 case IDC_DISABLE_ALL_PURPOSES
:
3673 case IDC_ENABLE_SELECTED_PURPOSES
:
3674 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3675 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
3685 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
3686 PROPSHEETPAGEW
*page
)
3690 struct edit_cert_data
*data
;
3695 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3696 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3697 for (i
= 0; i
< cItem
; i
++)
3701 item
.mask
= LVIF_PARAM
;
3704 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
3706 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
3708 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
3710 HeapFree(GetProcessHeap(), 0, (LPSTR
)info
->pszOID
);
3711 HeapFree(GetProcessHeap(), 0, info
);
3715 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3718 ImageList_Destroy(data
->imageList
);
3719 HeapFree(GetProcessHeap(), 0, data
);
3726 static void show_edit_cert_properties_dialog(HWND parent
,
3727 struct detail_data
*data
)
3729 PROPSHEETHEADERW hdr
;
3730 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
3732 TRACE("(%p)\n", data
);
3734 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
3735 page
.dwSize
= sizeof(page
);
3736 page
.dwFlags
= PSP_USECALLBACK
;
3737 page
.pfnCallback
= cert_properties_general_callback
;
3738 page
.hInstance
= hInstance
;
3739 page
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
3740 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
3741 page
.lParam
= (LPARAM
)data
;
3743 memset(&hdr
, 0, sizeof(hdr
));
3744 hdr
.dwSize
= sizeof(hdr
);
3745 hdr
.hwndParent
= parent
;
3746 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
3747 hdr
.hInstance
= hInstance
;
3748 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
3749 hdr
.u3
.ppsp
= &page
;
3751 PropertySheetW(&hdr
);
3754 static void free_detail_fields(struct detail_data
*data
)
3758 for (i
= 0; i
< data
->cFields
; i
++)
3759 HeapFree(GetProcessHeap(), 0, data
->fields
[i
].detailed_value
);
3760 HeapFree(GetProcessHeap(), 0, data
->fields
);
3761 data
->fields
= NULL
;
3765 static void refresh_details_view(HWND hwnd
)
3767 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3769 struct detail_data
*data
;
3771 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3772 /* Actually, any index will do, since they all store the same data value */
3773 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
3774 free_detail_fields(data
);
3775 set_fields_selection(hwnd
, data
, curSel
);
3778 static LRESULT CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3781 PROPSHEETPAGEW
*page
;
3782 struct detail_data
*data
;
3784 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3789 page
= (PROPSHEETPAGEW
*)lp
;
3790 data
= (struct detail_data
*)page
->lParam
;
3791 create_cert_details_list(hwnd
, data
);
3792 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
3793 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
3794 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
3795 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
3800 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3802 nm
= (NMITEMACTIVATE
*)lp
;
3803 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
3804 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
3806 data
= (struct detail_data
*)nm
->lParam
;
3807 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
3809 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
3810 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
3812 if (data
->fields
[nm
->iItem
].create
)
3813 val
= data
->fields
[nm
->iItem
].create(
3814 data
->pCertViewInfo
->pCertContext
,
3815 data
->fields
[nm
->iItem
].param
);
3821 item
.cchTextMax
= ARRAY_SIZE(buf
);
3822 item
.mask
= LVIF_TEXT
;
3824 item
.iItem
= nm
->iItem
;
3826 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
3830 /* Select all the text in the control, the next update will
3833 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
3834 add_unformatted_text_to_control(valueCtl
, val
,
3835 val
? lstrlenW(val
) : 0);
3837 HeapFree(GetProcessHeap(), 0, val
);
3847 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3848 CRYPTUI_WIZ_EXPORT_INFO info
;
3850 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, 0, 0);
3851 info
.dwSize
= sizeof(info
);
3852 info
.pwszExportFileName
= NULL
;
3853 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
3854 info
.u
.pCertContext
= data
->pCertViewInfo
->pCertContext
;
3856 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
3859 case IDC_EDITPROPERTIES
:
3861 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3864 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3865 /* Actually, any index will do, since they all store the same
3868 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
3870 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
3873 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
3874 refresh_details_view(hwnd
);
3878 case WM_REFRESH_VIEW
:
3879 refresh_details_view(hwnd
);
3885 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
3886 PROPSHEETPAGEW
*page
)
3888 struct detail_data
*data
;
3893 data
= (struct detail_data
*)page
->lParam
;
3894 free_detail_fields(data
);
3895 HeapFree(GetProcessHeap(), 0, data
);
3901 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3902 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
3905 struct detail_data
*data
= HeapAlloc(GetProcessHeap(), 0,
3906 sizeof(struct detail_data
));
3910 data
->pCertViewInfo
= pCertViewInfo
;
3911 data
->pfPropertiesChanged
= pfPropertiesChanged
;
3913 data
->fields
= NULL
;
3914 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3915 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3916 page
->dwFlags
= PSP_USECALLBACK
;
3917 page
->pfnCallback
= detail_callback
;
3918 page
->hInstance
= hInstance
;
3919 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
3920 page
->pfnDlgProc
= detail_dlg_proc
;
3921 page
->lParam
= (LPARAM
)data
;
3929 struct hierarchy_data
3931 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
3932 HIMAGELIST imageList
;
3936 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
3938 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3939 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3940 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3941 data
->pCertViewInfo
->idxCounterSigner
);
3943 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
3944 * therefore always even.
3946 if (index
== provSigner
->csCertChain
- 1)
3947 return (LPARAM
)data
;
3948 return index
<< 1 | 1;
3951 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
3953 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3954 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3955 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3956 data
->pCertViewInfo
->idxCounterSigner
);
3959 return provSigner
->csCertChain
- 1;
3963 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
3966 struct hierarchy_data
*data
= NULL
;
3967 HTREEITEM root
= NULL
;
3970 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
3971 TVGN_PARENT
, (LPARAM
)hItem
);
3981 item
.mask
= TVIF_PARAM
;
3983 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
3984 data
= (struct hierarchy_data
*)item
.lParam
;
3989 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
3991 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
3994 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
3998 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
4000 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4001 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4002 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4003 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
4004 data
->pCertViewInfo
->idxCounterSigner
);
4006 HTREEITEM parent
= NULL
;
4008 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
4009 for (i
= provSigner
->csCertChain
; i
; i
--)
4013 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
4016 TVINSERTSTRUCTW tvis
;
4018 tvis
.hParent
= parent
;
4019 tvis
.hInsertAfter
= TVI_LAST
;
4020 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
4021 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
4022 tvis
.u
.item
.pszText
= name
;
4023 tvis
.u
.item
.state
= TVIS_EXPANDED
;
4024 tvis
.u
.item
.stateMask
= TVIS_EXPANDED
;
4025 if (i
== 1 && (!provSigner
->pChainContext
||
4026 provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
4027 CERT_TRUST_IS_PARTIAL_CHAIN
))
4029 /* The root of the chain has a special case: if the chain is
4030 * a partial chain, the icon is a warning icon rather than an
4033 tvis
.u
.item
.iImage
= 2;
4035 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
4037 tvis
.u
.item
.iImage
= 0;
4039 tvis
.u
.item
.iImage
= 1;
4040 tvis
.u
.item
.iSelectedImage
= tvis
.u
.item
.iImage
;
4041 tvis
.u
.item
.lParam
= index_to_lparam(data
, i
- 1);
4042 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
4044 HeapFree(GetProcessHeap(), 0, name
);
4049 static void set_certificate_status(HWND hwnd
, const CRYPT_PROVIDER_CERT
*cert
)
4051 /* Select all the text in the control, the next update will replace it */
4052 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
4053 /* Set the highest priority error messages first. */
4054 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
4055 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
4056 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
4057 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
4058 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
4059 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
4060 else if (cert
->dwRevokedReason
)
4061 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
4063 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
4066 static void set_certificate_status_for_end_cert(HWND hwnd
,
4067 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
4069 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
4070 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4071 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
4072 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
4073 pCertViewInfo
->idxCounterSigner
);
4074 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
4075 pCertViewInfo
->idxCert
);
4077 set_certificate_status(status
, provCert
);
4080 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
4082 /* Disable view certificate button until a certificate is selected */
4083 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
4084 show_cert_chain(hwnd
, data
);
4085 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
4088 static void show_dialog_for_selected_cert(HWND hwnd
)
4090 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4092 struct hierarchy_data
*data
;
4095 memset(&item
, 0, sizeof(item
));
4096 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4097 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
, 0);
4098 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4099 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4100 selection
= lparam_to_index(data
, item
.lParam
);
4103 CRYPT_PROVIDER_SGNR
*provSigner
;
4104 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4105 BOOL changed
= FALSE
;
4107 provSigner
= WTHelperGetProvSignerFromChain(
4108 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4109 data
->pCertViewInfo
->idxSigner
,
4110 data
->pCertViewInfo
->fCounterSigner
,
4111 data
->pCertViewInfo
->idxCounterSigner
);
4112 memset(&viewInfo
, 0, sizeof(viewInfo
));
4113 viewInfo
.dwSize
= sizeof(viewInfo
);
4114 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
4115 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
4116 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
4117 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
4118 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
4119 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
4120 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
4121 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
4122 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
4125 /* Delete the contents of the tree */
4126 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4127 /* Reinitialize the tree */
4128 show_cert_hierarchy(hwnd
, data
);
4133 static LRESULT CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4136 PROPSHEETPAGEW
*page
;
4137 struct hierarchy_data
*data
;
4139 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4141 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
4146 page
= (PROPSHEETPAGEW
*)lp
;
4147 data
= (struct hierarchy_data
*)page
->lParam
;
4148 show_cert_hierarchy(hwnd
, data
);
4157 case TVN_SELCHANGEDW
:
4159 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
4161 CRYPT_PROVIDER_SGNR
*provSigner
;
4163 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
4164 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
4165 provSigner
= WTHelperGetProvSignerFromChain(
4166 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4167 data
->pCertViewInfo
->idxSigner
,
4168 data
->pCertViewInfo
->fCounterSigner
,
4169 data
->pCertViewInfo
->idxCounterSigner
);
4170 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
4171 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
4172 &provSigner
->pasCertChain
[selection
]);
4176 show_dialog_for_selected_cert(hwnd
);
4177 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4186 case IDC_VIEWCERTIFICATE
:
4187 show_dialog_for_selected_cert(hwnd
);
4191 case WM_REFRESH_VIEW
:
4195 /* Get hierarchy data */
4196 memset(&item
, 0, sizeof(item
));
4197 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4198 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
4200 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4201 /* Delete the contents of the tree */
4202 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4203 /* Reinitialize the tree */
4204 show_cert_hierarchy(hwnd
, data
);
4211 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
4212 PROPSHEETPAGEW
*page
)
4214 struct hierarchy_data
*data
;
4219 data
= (struct hierarchy_data
*)page
->lParam
;
4220 ImageList_Destroy(data
->imageList
);
4221 HeapFree(GetProcessHeap(), 0, data
);
4227 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4228 PROPSHEETPAGEW
*page
)
4230 struct hierarchy_data
*data
= HeapAlloc(GetProcessHeap(), 0,
4231 sizeof(struct hierarchy_data
));
4236 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
4237 if (data
->imageList
)
4240 COLORREF backColor
= RGB(255, 0, 255);
4242 data
->pCertViewInfo
= pCertViewInfo
;
4243 data
->selectedCert
= 0xffffffff;
4245 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
4246 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
4248 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
4250 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
4251 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
4252 page
->dwFlags
= PSP_USECALLBACK
;
4253 page
->hInstance
= hInstance
;
4254 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
4255 page
->pfnDlgProc
= hierarchy_dlg_proc
;
4256 page
->lParam
= (LPARAM
)data
;
4257 page
->pfnCallback
= hierarchy_callback
;
4261 HeapFree(GetProcessHeap(), 0, data
);
4266 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
4270 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
4274 case PSCB_INITIALIZED
:
4275 /* Get cancel button's position.. */
4276 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
4277 MapWindowPoints( 0, hwnd
, (POINT
*)&rc
, 2 );
4278 /* hide the cancel button.. */
4279 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
4280 /* and move the OK button to the cancel button's original position. */
4281 SetWindowPos(GetDlgItem(hwnd
, IDOK
), 0, rc
.left
, rc
.top
, 0, 0,
4282 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
4288 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4289 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
4291 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
4293 PROPSHEETPAGEW
*pages
;
4295 HMODULE lib
= LoadLibraryW(riched
);
4297 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
4298 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4300 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4302 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
4305 PROPSHEETHEADERW hdr
;
4306 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
4309 memset(&hdr
, 0, sizeof(hdr
));
4310 hdr
.dwSize
= sizeof(hdr
);
4311 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
4312 hdr
.hInstance
= hInstance
;
4313 if (pCertViewInfo
->szTitle
)
4314 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
4316 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
4317 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
4318 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4320 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
4321 &pages
[hdr
.nPages
]))
4324 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4326 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
4329 /* Copy each additional page, and create the init dialog struct for it
4331 if (pCertViewInfo
->cPropSheetPages
)
4333 init
= HeapAlloc(GetProcessHeap(), 0,
4334 pCertViewInfo
->cPropSheetPages
*
4335 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
4338 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
4340 memcpy(&pages
[hdr
.nPages
+ i
],
4341 &pCertViewInfo
->rgPropSheetPages
[i
],
4342 sizeof(PROPSHEETPAGEW
));
4343 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
4344 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
4345 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
4347 if (pCertViewInfo
->nStartPage
& 0x8000)
4349 /* Start page index is relative to the number of default
4352 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
4355 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
4356 hdr
.nPages
= nPages
;
4360 SetLastError(ERROR_OUTOFMEMORY
);
4364 /* Ignore the relative flag if there aren't any additional pages */
4365 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
4372 hdr
.u3
.ppsp
= pages
;
4373 hdr
.pfnCallback
= cert_prop_sheet_proc
;
4374 l
= PropertySheetW(&hdr
);
4377 SetLastError(ERROR_CANCELLED
);
4381 HeapFree(GetProcessHeap(), 0, init
);
4382 HeapFree(GetProcessHeap(), 0, pages
);
4385 SetLastError(ERROR_OUTOFMEMORY
);
4390 /***********************************************************************
4391 * CryptUIDlgViewCertificateW (CRYPTUI.@)
4393 BOOL WINAPI
CryptUIDlgViewCertificateW(
4394 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
4396 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
4397 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4399 WINTRUST_CERT_INFO cert
;
4401 CRYPT_PROVIDER_SGNR
*signer
;
4402 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
4404 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
4406 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
4408 SetLastError(ERROR_INVALID_PARAMETER
);
4411 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
4412 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
4413 if (!pCertViewInfo
->u
.hWVTStateData
)
4415 memset(&wvt
, 0, sizeof(wvt
));
4416 wvt
.cbStruct
= sizeof(wvt
);
4417 wvt
.dwUIChoice
= WTD_UI_NONE
;
4418 if (viewInfo
.dwFlags
&
4419 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
4420 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
4421 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
4422 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
4423 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
4424 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
4425 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
4426 memset(&cert
, 0, sizeof(cert
));
4427 cert
.cbStruct
= sizeof(cert
);
4428 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
4429 cert
.chStores
= viewInfo
.cStores
;
4430 cert
.pahStores
= viewInfo
.rghStores
;
4431 wvt
.u
.pCert
= &cert
;
4432 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
4433 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4434 viewInfo
.u
.pCryptProviderData
=
4435 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
4436 signer
= WTHelperGetProvSignerFromChain(
4437 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
4438 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
4443 viewInfo
.u
.pCryptProviderData
=
4444 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
4445 signer
= WTHelperGetProvSignerFromChain(
4446 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
4447 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
4448 viewInfo
.idxCounterSigner
);
4449 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
4454 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
4455 if (!pCertViewInfo
->u
.hWVTStateData
)
4457 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
4458 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4464 /***********************************************************************
4465 * CryptUIDlgViewContext (CRYPTUI.@)
4467 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
4468 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
4472 TRACE("(%d, %p, %p, %s, %08x, %p)\n", dwContextType
, pvContext
, hwnd
,
4473 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
4475 switch (dwContextType
)
4477 case CERT_STORE_CERTIFICATE_CONTEXT
:
4479 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4481 memset(&viewInfo
, 0, sizeof(viewInfo
));
4482 viewInfo
.dwSize
= sizeof(viewInfo
);
4483 viewInfo
.hwndParent
= hwnd
;
4484 viewInfo
.szTitle
= pwszTitle
;
4485 viewInfo
.pCertContext
= pvContext
;
4486 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
4490 FIXME("unimplemented for context type %d\n", dwContextType
);
4491 SetLastError(E_INVALIDARG
);
4497 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
4498 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
4499 * should be a CA. If neither extension is present, returns
4500 * defaultIfNotSpecified.
4502 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
4504 BOOL isCA
= defaultIfNotSpecified
;
4505 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
4506 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4510 CERT_BASIC_CONSTRAINTS_INFO
*info
;
4513 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
4514 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
4515 NULL
, &info
, &size
))
4517 if (info
->SubjectType
.cbData
== 1)
4518 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
4524 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
4525 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4528 CERT_BASIC_CONSTRAINTS2_INFO info
;
4529 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4531 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
4532 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
4533 0, NULL
, &info
, &size
))
4540 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
4544 if (is_ca_cert(cert
, TRUE
))
4547 storeName
= addressBook
;
4548 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4549 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
4552 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
4559 SetLastError(E_INVALIDARG
);
4562 if (hDestCertStore
) store
= hDestCertStore
;
4565 if (!(store
= choose_store_for_cert(cert
)))
4567 WARN("unable to open certificate store\n");
4571 ret
= CertAddCertificateContextToStore(store
, cert
,
4572 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4573 if (!hDestCertStore
) CertCloseStore(store
, 0);
4577 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
4584 SetLastError(E_INVALIDARG
);
4587 if (hDestCertStore
) store
= hDestCertStore
;
4590 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4591 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
4593 WARN("unable to open certificate store\n");
4597 ret
= CertAddCRLContextToStore(store
, crl
,
4598 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4599 if (!hDestCertStore
) CertCloseStore(store
, 0);
4603 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
4610 SetLastError(E_INVALIDARG
);
4613 if (hDestCertStore
) store
= hDestCertStore
;
4616 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
4618 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4619 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
4621 WARN("unable to open certificate store\n");
4625 ret
= CertAddCTLContextToStore(store
, ctl
,
4626 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4627 if (!hDestCertStore
) CertCloseStore(store
, 0);
4631 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
4632 * CryptQueryObject, against the allowed types. Returns TRUE if the
4633 * type is allowed, FALSE otherwise.
4635 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
4640 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4641 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4645 case CERT_QUERY_CONTENT_CERT
:
4646 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4647 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
4649 case CERT_QUERY_CONTENT_CRL
:
4650 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4651 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
4653 case CERT_QUERY_CONTENT_CTL
:
4654 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4655 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
4658 /* The remaining types contain more than one type, so allow
4666 /* No allowed types specified, so any type is allowed */
4670 SetLastError(E_INVALIDARG
);
4675 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4678 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4680 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4687 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
4690 LoadStringW(hInstance
, warningID
, error
, ARRAY_SIZE(error
));
4691 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
4695 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
4697 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
4700 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
4705 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4706 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4708 PCCERT_CONTEXT cert
;
4713 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
4715 CertFreeCertificateContext(cert
);
4716 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
4719 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
4721 CertFreeCRLContext(crl
);
4722 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
4725 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
4727 CertFreeCTLContext(ctl
);
4728 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4735 SetLastError(E_INVALIDARG
);
4739 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4740 HCERTSTORE source
, HCERTSTORE dest
)
4744 if ((ret
= check_store_context_type(dwFlags
, source
)))
4746 PCCERT_CONTEXT cert
= NULL
;
4747 PCCRL_CONTEXT crl
= NULL
;
4748 PCCTL_CONTEXT ctl
= NULL
;
4751 cert
= CertEnumCertificatesInStore(source
, cert
);
4753 ret
= import_cert(cert
, dest
);
4754 } while (ret
&& cert
);
4756 crl
= CertEnumCRLsInStore(source
, crl
);
4758 ret
= import_crl(crl
, dest
);
4759 } while (ret
&& crl
);
4761 ctl
= CertEnumCTLsInStore(source
, ctl
);
4763 ret
= import_ctl(ctl
, dest
);
4764 } while (ret
&& ctl
);
4767 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
4771 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
4772 DWORD
*pContentType
)
4774 HCERTSTORE store
= NULL
;
4775 DWORD contentType
= 0, expectedContentTypeFlags
;
4778 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4779 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4781 expectedContentTypeFlags
=
4782 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4783 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4784 CERT_QUERY_CONTENT_FLAG_PFX
;
4785 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
4786 expectedContentTypeFlags
|=
4787 CERT_QUERY_CONTENT_FLAG_CERT
|
4788 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
4789 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
4790 expectedContentTypeFlags
|=
4791 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4792 CERT_QUERY_CONTENT_FLAG_CRL
;
4793 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
4794 expectedContentTypeFlags
|=
4795 CERT_QUERY_CONTENT_FLAG_CTL
|
4796 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
4799 expectedContentTypeFlags
=
4800 CERT_QUERY_CONTENT_FLAG_CERT
|
4801 CERT_QUERY_CONTENT_FLAG_CTL
|
4802 CERT_QUERY_CONTENT_FLAG_CRL
|
4803 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4804 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
4805 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
4806 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4807 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4808 CERT_QUERY_CONTENT_FLAG_PFX
;
4810 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
4811 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
4812 &contentType
, NULL
, &store
, NULL
, NULL
);
4814 *pContentType
= contentType
;
4818 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4819 LPCWSTR fileName
, HCERTSTORE dest
)
4824 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
4826 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
4827 CertCloseStore(source
, 0);
4834 struct ImportWizData
4838 LPCWSTR pwszWizardTitle
;
4839 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
4843 HCERTSTORE hDestCertStore
;
4849 static LRESULT CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4858 struct ImportWizData
*data
;
4859 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4860 WCHAR fontFace
[MAX_STRING_LEN
];
4861 HDC hDC
= GetDC(hwnd
);
4864 data
= (struct ImportWizData
*)page
->lParam
;
4865 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
, ARRAY_SIZE(fontFace
));
4866 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
4867 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
4868 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
4869 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
4870 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4871 (WPARAM
)data
->titleFont
, TRUE
);
4872 ReleaseDC(hwnd
, hDC
);
4877 NMHDR
*hdr
= (NMHDR
*)lp
;
4882 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
4892 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
4894 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
4896 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
4897 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
4898 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
4899 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
4901 static const WCHAR filter_all
[] = { '*','.','*',0 };
4908 } import_filters
[] = {
4909 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
4910 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
4911 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
4912 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
4913 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
4914 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
4915 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
4918 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
4921 int len
, totalLen
= 2;
4922 LPWSTR filter
= NULL
, str
;
4924 for (i
= 0; i
< ARRAY_SIZE(import_filters
); i
++)
4926 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4927 (dwFlags
& import_filters
[i
].allowFlags
))
4929 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
4930 totalLen
+= len
+ lstrlenW(import_filters
[i
].filter
) + 2;
4933 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
4939 for (i
= 0; i
< ARRAY_SIZE(import_filters
); i
++)
4941 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4942 (dwFlags
& import_filters
[i
].allowFlags
))
4944 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
4946 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
4949 lstrcpyW(ptr
, import_filters
[i
].filter
);
4950 ptr
+= lstrlenW(import_filters
[i
].filter
) + 1;
4958 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
4964 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
4965 OPEN_EXISTING
, 0, NULL
);
4966 if (file
!= INVALID_HANDLE_VALUE
)
4968 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
4969 &data
->contentType
);
4973 warningID
= IDS_IMPORT_BAD_FORMAT
;
4974 else if (!check_store_context_type(data
->dwFlags
, source
))
4975 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
4978 data
->importSrc
.dwSubjectChoice
=
4979 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
4980 data
->importSrc
.u
.hCertStore
= source
;
4981 data
->freeSource
= TRUE
;
4986 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4993 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4995 LPWSTR msgBuf
, fullError
;
4997 if (data
->pwszWizardTitle
)
4998 pTitle
= data
->pwszWizardTitle
;
5001 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5004 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
, ARRAY_SIZE(error
));
5006 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
5007 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
5008 fullError
= HeapAlloc(GetProcessHeap(), 0,
5009 (lstrlenW(error
) + lstrlenW(fileName
) + lstrlenW(msgBuf
) + 3)
5013 LPWSTR ptr
= fullError
;
5015 lstrcpyW(ptr
, error
);
5016 ptr
+= lstrlenW(error
);
5017 lstrcpyW(ptr
, fileName
);
5018 ptr
+= lstrlenW(fileName
);
5021 lstrcpyW(ptr
, msgBuf
);
5022 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
5023 HeapFree(GetProcessHeap(), 0, fullError
);
5030 static LRESULT CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5034 struct ImportWizData
*data
;
5040 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5042 data
= (struct ImportWizData
*)page
->lParam
;
5043 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5046 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5048 SendMessageW(fileNameEdit
, WM_SETTEXT
, 0, (LPARAM
)data
->fileName
);
5054 NMHDR
*hdr
= (NMHDR
*)lp
;
5059 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5060 PSWIZB_BACK
| PSWIZB_NEXT
);
5065 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5066 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
5068 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5071 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5072 IDS_IMPORT_EMPTY_FILE
);
5073 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5078 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
5079 (len
+ 1) * sizeof(WCHAR
));
5083 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
5085 if (!import_validate_filename(hwnd
, data
, fileName
))
5087 HeapFree(GetProcessHeap(), 0, fileName
);
5088 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5092 data
->fileName
= fileName
;
5103 case IDC_IMPORT_BROWSE_FILE
:
5106 WCHAR fileBuf
[MAX_PATH
];
5108 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5109 memset(&ofn
, 0, sizeof(ofn
));
5110 ofn
.lStructSize
= sizeof(ofn
);
5111 ofn
.hwndOwner
= hwnd
;
5112 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
5113 ofn
.lpstrFile
= fileBuf
;
5114 ofn
.nMaxFile
= ARRAY_SIZE(fileBuf
);
5116 if (GetOpenFileNameW(&ofn
))
5117 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
5118 0, (LPARAM
)ofn
.lpstrFile
);
5119 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
5128 static LRESULT CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5132 struct ImportWizData
*data
;
5138 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5140 data
= (struct ImportWizData
*)page
->lParam
;
5141 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5142 if (!data
->hDestCertStore
)
5144 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
,
5146 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5147 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5148 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
5152 WCHAR storeTitle
[MAX_STRING_LEN
];
5154 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), BM_CLICK
,
5156 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5157 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5158 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
),
5159 !(data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
));
5160 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, storeTitle
, ARRAY_SIZE(storeTitle
));
5161 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5162 0, (LPARAM
)storeTitle
);
5168 NMHDR
*hdr
= (NMHDR
*)lp
;
5173 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5174 PSWIZB_BACK
| PSWIZB_NEXT
);
5179 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5180 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
5181 !data
->hDestCertStore
)
5183 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5184 IDS_IMPORT_SELECT_STORE
);
5185 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5196 case IDC_IMPORT_AUTO_STORE
:
5197 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5198 data
->autoDest
= TRUE
;
5199 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5200 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5202 case IDC_IMPORT_SPECIFY_STORE
:
5203 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5204 data
->autoDest
= FALSE
;
5205 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5206 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5208 case IDC_IMPORT_BROWSE_STORE
:
5210 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
5211 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
5212 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
5213 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
5216 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5217 selectInfo
.dwSize
= sizeof(selectInfo
);
5218 selectInfo
.parent
= hwnd
;
5219 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
5220 selectInfo
.pwszTitle
= NULL
;
5221 selectInfo
.pwszText
= NULL
;
5222 selectInfo
.pEnumData
= &enumData
;
5223 selectInfo
.pfnSelectedStoreCallback
= NULL
;
5224 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
5226 WCHAR storeTitle
[MAX_STRING_LEN
];
5228 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, storeTitle
,
5229 ARRAY_SIZE(storeTitle
));
5230 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5231 0, (LPARAM
)storeTitle
);
5232 data
->hDestCertStore
= store
;
5233 data
->freeDest
= TRUE
;
5243 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
5245 WCHAR text
[MAX_STRING_LEN
];
5249 item
.mask
= LVIF_TEXT
;
5250 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5252 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
, ARRAY_SIZE(text
));
5253 item
.pszText
= text
;
5254 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5257 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
, ARRAY_SIZE(text
));
5259 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
, ARRAY_SIZE(text
));
5260 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5261 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5263 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
, ARRAY_SIZE(text
));
5264 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5265 switch (data
->contentType
)
5267 case CERT_QUERY_CONTENT_CERT
:
5268 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
5269 contentID
= IDS_IMPORT_CONTENT_CERT
;
5271 case CERT_QUERY_CONTENT_CRL
:
5272 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
5273 contentID
= IDS_IMPORT_CONTENT_CRL
;
5275 case CERT_QUERY_CONTENT_CTL
:
5276 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
5277 contentID
= IDS_IMPORT_CONTENT_CTL
;
5279 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
5280 contentID
= IDS_IMPORT_CONTENT_CMS
;
5282 case CERT_QUERY_CONTENT_FLAG_PFX
:
5283 contentID
= IDS_IMPORT_CONTENT_PFX
;
5286 contentID
= IDS_IMPORT_CONTENT_STORE
;
5289 LoadStringW(hInstance
, contentID
, text
, ARRAY_SIZE(text
));
5291 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5294 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5296 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
, ARRAY_SIZE(text
));
5297 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5299 item
.pszText
= data
->fileName
;
5300 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5304 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5305 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5309 switch (pImportSrc
->dwSubjectChoice
)
5311 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
5312 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
5313 pImportSrc
->u
.pwszFileName
, hDestCertStore
);
5315 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5316 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
5317 ret
= import_cert(pImportSrc
->u
.pCertContext
, hDestCertStore
);
5319 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5321 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5322 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
5323 ret
= import_crl(pImportSrc
->u
.pCRLContext
, hDestCertStore
);
5325 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5327 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5328 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
5329 ret
= import_ctl(pImportSrc
->u
.pCTLContext
, hDestCertStore
);
5331 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5333 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5334 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
5335 pImportSrc
->u
.hCertStore
, hDestCertStore
);
5338 WARN("unknown source type: %u\n", pImportSrc
->dwSubjectChoice
);
5339 SetLastError(E_INVALIDARG
);
5345 static LRESULT CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5349 struct ImportWizData
*data
;
5355 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5356 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5360 data
= (struct ImportWizData
*)page
->lParam
;
5361 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5362 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
5363 (WPARAM
)data
->titleFont
, TRUE
);
5364 GetWindowRect(lv
, &rc
);
5365 column
.mask
= LVCF_WIDTH
;
5366 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
5367 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
5368 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
5369 show_import_details(lv
, data
);
5374 NMHDR
*hdr
= (NMHDR
*)lp
;
5380 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5382 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5383 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
5384 show_import_details(lv
, data
);
5385 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5386 PSWIZB_BACK
| PSWIZB_FINISH
);
5392 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5393 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
5394 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
5396 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
5399 if (data
->pwszWizardTitle
)
5400 pTitle
= data
->pwszWizardTitle
;
5403 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5406 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
, ARRAY_SIZE(message
));
5407 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
5410 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5421 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
5422 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
5423 HCERTSTORE hDestCertStore
)
5425 PROPSHEETHEADERW hdr
;
5426 PROPSHEETPAGEW pages
[4];
5427 struct ImportWizData data
;
5430 data
.dwFlags
= dwFlags
;
5431 data
.pwszWizardTitle
= pwszWizardTitle
;
5434 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
5435 data
.fileName
= (LPWSTR
)pImportSrc
->u
.pwszFileName
;
5439 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
5440 data
.fileName
= NULL
;
5442 data
.freeSource
= FALSE
;
5443 data
.hDestCertStore
= hDestCertStore
;
5444 data
.freeDest
= FALSE
;
5445 data
.autoDest
= TRUE
;
5446 data
.success
= TRUE
;
5448 memset(pages
, 0, sizeof(pages
));
5450 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5451 pages
[nPages
].hInstance
= hInstance
;
5452 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
5453 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
5454 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5455 pages
[nPages
].lParam
= (LPARAM
)&data
;
5459 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
5461 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5462 pages
[nPages
].hInstance
= hInstance
;
5463 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
5464 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
5465 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5466 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
5467 pages
[nPages
].pszHeaderSubTitle
=
5468 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
5469 pages
[nPages
].lParam
= (LPARAM
)&data
;
5474 switch (pImportSrc
->dwSubjectChoice
)
5476 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5477 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
5479 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5480 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
5482 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5483 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
5485 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5486 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
5491 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5492 pages
[nPages
].hInstance
= hInstance
;
5493 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
5494 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
5495 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5496 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
5497 pages
[nPages
].pszHeaderSubTitle
=
5498 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
5499 pages
[nPages
].lParam
= (LPARAM
)&data
;
5502 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5503 pages
[nPages
].hInstance
= hInstance
;
5504 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
5505 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
5506 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5507 pages
[nPages
].lParam
= (LPARAM
)&data
;
5510 memset(&hdr
, 0, sizeof(hdr
));
5511 hdr
.dwSize
= sizeof(hdr
);
5512 hdr
.hwndParent
= hwndParent
;
5513 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
5515 hdr
.hInstance
= hInstance
;
5516 if (pwszWizardTitle
)
5517 hdr
.pszCaption
= pwszWizardTitle
;
5519 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
5520 hdr
.u3
.ppsp
= pages
;
5521 hdr
.nPages
= nPages
;
5522 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
5523 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
5524 PropertySheetW(&hdr
);
5525 if (data
.fileName
!= data
.importSrc
.u
.pwszFileName
)
5526 HeapFree(GetProcessHeap(), 0, data
.fileName
);
5527 if (data
.freeSource
&&
5528 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
5529 CertCloseStore(data
.importSrc
.u
.hCertStore
, 0);
5530 DeleteObject(data
.titleFont
);
5531 return data
.success
;
5534 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5535 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5539 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
5540 pImportSrc
, hDestCertStore
);
5543 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
5545 SetLastError(E_INVALIDARG
);
5549 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
5550 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5552 else if (pImportSrc
)
5553 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5557 /* Can't have no UI without specifying source */
5558 SetLastError(E_INVALIDARG
);
5565 struct ExportWizData
5569 LPCWSTR pwszWizardTitle
;
5570 CRYPTUI_WIZ_EXPORT_INFO exportInfo
;
5571 CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo
;
5573 PCRYPT_KEY_PROV_INFO keyProvInfo
;
5580 static LRESULT CALLBACK
export_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5589 struct ExportWizData
*data
;
5590 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5591 WCHAR fontFace
[MAX_STRING_LEN
];
5592 HDC hDC
= GetDC(hwnd
);
5595 data
= (struct ExportWizData
*)page
->lParam
;
5596 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
, ARRAY_SIZE(fontFace
));
5597 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
5598 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
5599 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
5600 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
5601 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
5602 (WPARAM
)data
->titleFont
, TRUE
);
5603 ReleaseDC(hwnd
, hDC
);
5608 NMHDR
*hdr
= (NMHDR
*)lp
;
5613 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
5623 static PCRYPT_KEY_PROV_INFO
export_get_private_key_info(PCCERT_CONTEXT cert
)
5625 PCRYPT_KEY_PROV_INFO info
= NULL
;
5628 if (CertGetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
,
5631 info
= HeapAlloc(GetProcessHeap(), 0, size
);
5634 if (!CertGetCertificateContextProperty(cert
,
5635 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
))
5637 HeapFree(GetProcessHeap(), 0, info
);
5645 static BOOL
export_acquire_private_key(const CRYPT_KEY_PROV_INFO
*info
,
5650 ret
= CryptAcquireContextW(phProv
, info
->pwszContainerName
,
5651 info
->pwszProvName
, info
->dwProvType
, 0);
5656 for (i
= 0; i
< info
->cProvParam
; i
++)
5657 CryptSetProvParam(*phProv
, info
->rgProvParam
[i
].dwParam
,
5658 info
->rgProvParam
[i
].pbData
, info
->rgProvParam
[i
].dwFlags
);
5663 static BOOL
export_is_key_exportable(HCRYPTPROV hProv
, DWORD keySpec
)
5668 if ((ret
= CryptGetUserKey(hProv
, keySpec
, &key
)))
5670 DWORD permissions
, size
= sizeof(permissions
);
5672 if ((ret
= CryptGetKeyParam(key
, KP_PERMISSIONS
, (BYTE
*)&permissions
,
5673 &size
, 0)) && !(permissions
& CRYPT_EXPORT
))
5675 CryptDestroyKey(key
);
5680 static LRESULT CALLBACK
export_private_key_dlg_proc(HWND hwnd
, UINT msg
,
5681 WPARAM wp
, LPARAM lp
)
5684 struct ExportWizData
*data
;
5690 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5691 PCRYPT_KEY_PROV_INFO info
;
5692 HCRYPTPROV hProv
= 0;
5695 data
= (struct ExportWizData
*)page
->lParam
;
5696 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5697 /* Get enough information about a key to see whether it's exportable.
5699 if (!(info
= export_get_private_key_info(
5700 data
->exportInfo
.u
.pCertContext
)))
5701 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5702 else if (!export_acquire_private_key(info
, &hProv
))
5703 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5704 else if (!export_is_key_exportable(hProv
, info
->dwKeySpec
))
5705 errorID
= IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE
;
5709 WCHAR error
[MAX_STRING_LEN
];
5711 LoadStringW(hInstance
, errorID
, error
, ARRAY_SIZE(error
));
5712 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE
),
5713 WM_SETTEXT
, 0, (LPARAM
)error
);
5714 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_YES
), FALSE
);
5717 data
->keyProvInfo
= info
;
5719 CryptReleaseContext(hProv
, 0);
5720 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
), BM_CLICK
,
5726 NMHDR
*hdr
= (NMHDR
*)lp
;
5731 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5732 PSWIZB_BACK
| PSWIZB_NEXT
);
5736 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5737 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
))
5739 data
->contextInfo
.dwExportFormat
=
5740 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5741 data
->contextInfo
.fExportPrivateKeys
= FALSE
;
5745 data
->contextInfo
.dwExportFormat
=
5746 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5747 data
->contextInfo
.fExportPrivateKeys
= TRUE
;
5757 static BOOL
export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
)
5761 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
)
5765 /* If there's a CRYPT_KEY_PROV_INFO set for this cert, assume the
5766 * cert has a private key.
5768 if (CertGetCertificateContextProperty(pExportInfo
->u
.pCertContext
,
5769 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
))
5775 static void export_format_enable_controls(HWND hwnd
, const struct ExportWizData
*data
)
5777 int defaultFormatID
;
5779 switch (data
->contextInfo
.dwExportFormat
)
5781 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
5782 defaultFormatID
= IDC_EXPORT_FORMAT_BASE64
;
5784 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
5785 defaultFormatID
= IDC_EXPORT_FORMAT_CMS
;
5787 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
5788 defaultFormatID
= IDC_EXPORT_FORMAT_PFX
;
5791 defaultFormatID
= IDC_EXPORT_FORMAT_DER
;
5793 SendMessageW(GetDlgItem(hwnd
, defaultFormatID
), BM_CLICK
, 0, 0);
5794 if (defaultFormatID
== IDC_EXPORT_FORMAT_PFX
)
5796 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), FALSE
);
5797 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), FALSE
);
5798 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), FALSE
);
5799 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), TRUE
);
5803 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), TRUE
);
5804 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), TRUE
);
5805 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), TRUE
);
5806 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), FALSE
);
5810 static LRESULT CALLBACK
export_format_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5814 struct ExportWizData
*data
;
5820 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5822 data
= (struct ExportWizData
*)page
->lParam
;
5823 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5824 export_format_enable_controls(hwnd
, data
);
5829 NMHDR
*hdr
= (NMHDR
*)lp
;
5834 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5835 PSWIZB_BACK
| PSWIZB_NEXT
);
5836 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5837 export_format_enable_controls(hwnd
, data
);
5842 BOOL skipPasswordPage
= TRUE
;
5844 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5845 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_DER
))
5846 data
->contextInfo
.dwExportFormat
=
5847 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5848 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_BASE64
))
5849 data
->contextInfo
.dwExportFormat
=
5850 CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
;
5851 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_CMS
))
5853 data
->contextInfo
.dwExportFormat
=
5854 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5855 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
))
5856 data
->contextInfo
.fExportChain
=
5857 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5861 data
->contextInfo
.dwExportFormat
=
5862 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5863 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
))
5864 data
->contextInfo
.fExportChain
= TRUE
;
5865 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
))
5866 data
->contextInfo
.fStrongEncryption
= TRUE
;
5867 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
))
5868 data
->deleteKeys
= TRUE
;
5869 skipPasswordPage
= FALSE
;
5871 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
,
5872 skipPasswordPage
? IDD_EXPORT_FILE
: 0);
5885 case IDC_EXPORT_FORMAT_DER
:
5886 case IDC_EXPORT_FORMAT_BASE64
:
5887 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5889 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5891 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5893 EnableWindow(GetDlgItem(hwnd
,
5894 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), FALSE
);
5896 case IDC_EXPORT_FORMAT_CMS
:
5897 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5900 case IDC_EXPORT_FORMAT_PFX
:
5901 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5903 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5905 EnableWindow(GetDlgItem(hwnd
,
5906 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), TRUE
);
5916 static void export_password_mismatch(HWND hwnd
, const struct ExportWizData
*data
)
5918 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5921 if (data
->pwszWizardTitle
)
5922 pTitle
= data
->pwszWizardTitle
;
5925 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5928 LoadStringW(hInstance
, IDS_EXPORT_PASSWORD_MISMATCH
, error
, ARRAY_SIZE(error
));
5929 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
5930 SetFocus(GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
));
5933 static LRESULT CALLBACK
export_password_dlg_proc(HWND hwnd
, UINT msg
,
5934 WPARAM wp
, LPARAM lp
)
5937 struct ExportWizData
*data
;
5943 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5945 data
= (struct ExportWizData
*)page
->lParam
;
5946 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5951 NMHDR
*hdr
= (NMHDR
*)lp
;
5956 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5957 PSWIZB_BACK
| PSWIZB_NEXT
);
5962 HWND passwordEdit
= GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
);
5963 HWND passwordConfirmEdit
= GetDlgItem(hwnd
,
5964 IDC_EXPORT_PASSWORD_CONFIRM
);
5965 DWORD passwordLen
= SendMessageW(passwordEdit
, WM_GETTEXTLENGTH
,
5967 DWORD passwordConfirmLen
= SendMessageW(passwordConfirmEdit
,
5968 WM_GETTEXTLENGTH
, 0, 0);
5970 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5971 if (!passwordLen
&& !passwordConfirmLen
)
5972 data
->contextInfo
.pwszPassword
= NULL
;
5973 else if (passwordLen
!= passwordConfirmLen
)
5975 export_password_mismatch(hwnd
, data
);
5976 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5981 LPWSTR password
= HeapAlloc(GetProcessHeap(), 0,
5982 (passwordLen
+ 1) * sizeof(WCHAR
));
5983 LPWSTR passwordConfirm
= HeapAlloc(GetProcessHeap(), 0,
5984 (passwordConfirmLen
+ 1) * sizeof(WCHAR
));
5985 BOOL freePassword
= TRUE
;
5987 if (password
&& passwordConfirm
)
5989 SendMessageW(passwordEdit
, WM_GETTEXT
, passwordLen
+ 1,
5991 SendMessageW(passwordConfirmEdit
, WM_GETTEXT
,
5992 passwordConfirmLen
+ 1, (LPARAM
)passwordConfirm
);
5993 if (lstrcmpW(password
, passwordConfirm
))
5995 export_password_mismatch(hwnd
, data
);
5996 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6001 data
->contextInfo
.pwszPassword
= password
;
6002 freePassword
= FALSE
;
6003 data
->freePassword
= TRUE
;
6007 HeapFree(GetProcessHeap(), 0, password
);
6008 HeapFree(GetProcessHeap(), 0, passwordConfirm
);
6019 static LPWSTR
export_append_extension(const struct ExportWizData
*data
,
6022 static const WCHAR cer
[] = { '.','c','e','r',0 };
6023 static const WCHAR crl
[] = { '.','c','r','l',0 };
6024 static const WCHAR ctl
[] = { '.','c','t','l',0 };
6025 static const WCHAR p7b
[] = { '.','p','7','b',0 };
6026 static const WCHAR pfx
[] = { '.','p','f','x',0 };
6027 static const WCHAR sst
[] = { '.','s','s','t',0 };
6030 BOOL appendExtension
;
6032 switch (data
->contextInfo
.dwExportFormat
)
6034 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6037 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6041 switch (data
->exportInfo
.dwSubjectChoice
)
6043 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6046 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6049 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6056 dot
= wcsrchr(fileName
, '.');
6058 appendExtension
= wcsicmp(dot
, extension
) != 0;
6060 appendExtension
= TRUE
;
6061 if (appendExtension
)
6063 fileName
= HeapReAlloc(GetProcessHeap(), 0, fileName
,
6064 (lstrlenW(fileName
) + lstrlenW(extension
) + 1) * sizeof(WCHAR
));
6066 lstrcatW(fileName
, extension
);
6071 static BOOL
export_validate_filename(HWND hwnd
, struct ExportWizData
*data
,
6075 BOOL tryCreate
= TRUE
, forceCreate
= FALSE
, ret
= FALSE
;
6077 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6078 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, NULL
);
6079 if (file
!= INVALID_HANDLE_VALUE
)
6081 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
6084 if (data
->pwszWizardTitle
)
6085 pTitle
= data
->pwszWizardTitle
;
6088 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6091 LoadStringW(hInstance
, IDS_EXPORT_FILE_EXISTS
, warning
, ARRAY_SIZE(warning
));
6092 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
6100 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6101 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6102 forceCreate
? CREATE_ALWAYS
: CREATE_NEW
,
6104 if (file
!= INVALID_HANDLE_VALUE
)
6111 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6113 LPWSTR msgBuf
, fullError
;
6115 if (data
->pwszWizardTitle
)
6116 pTitle
= data
->pwszWizardTitle
;
6119 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6122 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
, ARRAY_SIZE(error
));
6124 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
6125 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
6126 fullError
= HeapAlloc(GetProcessHeap(), 0,
6127 (lstrlenW(error
) + lstrlenW(fileName
) + lstrlenW(msgBuf
) + 3)
6131 LPWSTR ptr
= fullError
;
6133 lstrcpyW(ptr
, error
);
6134 ptr
+= lstrlenW(error
);
6135 lstrcpyW(ptr
, fileName
);
6136 ptr
+= lstrlenW(fileName
);
6139 lstrcpyW(ptr
, msgBuf
);
6140 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
6141 HeapFree(GetProcessHeap(), 0, fullError
);
6149 static const WCHAR export_filter_cert
[] = { '*','.','c','e','r',0 };
6150 static const WCHAR export_filter_crl
[] = { '*','.','c','r','l',0 };
6151 static const WCHAR export_filter_ctl
[] = { '*','.','s','t','l',0 };
6152 static const WCHAR export_filter_cms
[] = { '*','.','p','7','b',0 };
6153 static const WCHAR export_filter_pfx
[] = { '*','.','p','f','x',0 };
6154 static const WCHAR export_filter_sst
[] = { '*','.','s','s','t',0 };
6156 static WCHAR
*make_export_file_filter(DWORD exportFormat
, DWORD subjectChoice
)
6158 int baseLen
, allLen
, totalLen
= 2, baseID
;
6159 LPWSTR filter
= NULL
, baseFilter
, all
;
6162 switch (exportFormat
)
6164 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6165 baseID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6166 filterStr
= export_filter_cert
;
6168 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6169 baseID
= IDS_EXPORT_FILTER_PFX
;
6170 filterStr
= export_filter_pfx
;
6172 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6173 baseID
= IDS_EXPORT_FILTER_CMS
;
6174 filterStr
= export_filter_cms
;
6177 switch (subjectChoice
)
6179 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6180 baseID
= IDS_EXPORT_FILTER_CRL
;
6181 filterStr
= export_filter_crl
;
6183 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6184 baseID
= IDS_EXPORT_FILTER_CTL
;
6185 filterStr
= export_filter_ctl
;
6187 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6188 baseID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6189 filterStr
= export_filter_sst
;
6192 baseID
= IDS_EXPORT_FILTER_CERT
;
6193 filterStr
= export_filter_cert
;
6197 baseLen
= LoadStringW(hInstance
, baseID
, (LPWSTR
)&baseFilter
, 0);
6198 totalLen
+= baseLen
+ lstrlenW(filterStr
) + 2;
6199 allLen
= LoadStringW(hInstance
, IDS_IMPORT_FILTER_ALL
, (LPWSTR
)&all
, 0);
6200 totalLen
+= allLen
+ lstrlenW(filter_all
) + 2;
6201 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
6207 memcpy(ptr
, baseFilter
, baseLen
* sizeof(WCHAR
));
6210 lstrcpyW(ptr
, filterStr
);
6211 ptr
+= lstrlenW(filterStr
) + 1;
6212 memcpy(ptr
, all
, allLen
* sizeof(WCHAR
));
6215 lstrcpyW(ptr
, filter_all
);
6216 ptr
+= lstrlenW(filter_all
) + 1;
6222 static LRESULT CALLBACK
export_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6226 struct ExportWizData
*data
;
6232 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6234 data
= (struct ExportWizData
*)page
->lParam
;
6235 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6236 if (data
->exportInfo
.pwszExportFileName
)
6237 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
, 0,
6238 (LPARAM
)data
->exportInfo
.pwszExportFileName
);
6243 NMHDR
*hdr
= (NMHDR
*)lp
;
6248 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6249 if (data
->contextInfo
.dwExportFormat
!=
6250 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
)
6252 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, IDD_EXPORT_FORMAT
);
6258 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
);
6259 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
6261 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6264 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6267 if (data
->pwszWizardTitle
)
6268 pTitle
= data
->pwszWizardTitle
;
6271 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6274 LoadStringW(hInstance
, IDS_IMPORT_EMPTY_FILE
, error
, ARRAY_SIZE(error
));
6275 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
6276 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6281 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
6282 (len
+ 1) * sizeof(WCHAR
));
6286 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
6288 fileName
= export_append_extension(data
, fileName
);
6289 if (!export_validate_filename(hwnd
, data
, fileName
))
6291 HeapFree(GetProcessHeap(), 0, fileName
);
6292 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6296 data
->fileName
= fileName
;
6302 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6303 PSWIZB_BACK
| PSWIZB_NEXT
);
6312 case IDC_EXPORT_BROWSE_FILE
:
6315 WCHAR fileBuf
[MAX_PATH
];
6317 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6318 memset(&ofn
, 0, sizeof(ofn
));
6319 ofn
.lStructSize
= sizeof(ofn
);
6320 ofn
.hwndOwner
= hwnd
;
6321 ofn
.lpstrFilter
= make_export_file_filter(
6322 data
->contextInfo
.dwExportFormat
,
6323 data
->exportInfo
.dwSubjectChoice
);
6324 ofn
.lpstrFile
= fileBuf
;
6325 ofn
.nMaxFile
= ARRAY_SIZE(fileBuf
);
6327 if (GetSaveFileNameW(&ofn
))
6328 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
,
6329 0, (LPARAM
)ofn
.lpstrFile
);
6330 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
6339 static void show_export_details(HWND lv
, const struct ExportWizData
*data
)
6341 WCHAR text
[MAX_STRING_LEN
];
6345 item
.mask
= LVIF_TEXT
;
6348 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6350 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
, ARRAY_SIZE(text
));
6351 item
.pszText
= text
;
6352 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6354 item
.pszText
= data
->fileName
;
6355 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6358 item
.pszText
= text
;
6359 switch (data
->exportInfo
.dwSubjectChoice
)
6361 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6362 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6363 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6364 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6369 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6371 LoadStringW(hInstance
, IDS_EXPORT_INCLUDE_CHAIN
, text
, ARRAY_SIZE(text
));
6372 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6374 LoadStringW(hInstance
, data
->contextInfo
.fExportChain
? IDS_YES
: IDS_NO
, text
,
6376 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6378 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6380 LoadStringW(hInstance
, IDS_EXPORT_KEYS
, text
, ARRAY_SIZE(text
));
6381 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6383 LoadStringW(hInstance
, data
->contextInfo
.fExportPrivateKeys
? IDS_YES
: IDS_NO
, text
,
6385 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6389 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6391 LoadStringW(hInstance
, IDS_EXPORT_FORMAT
, text
, ARRAY_SIZE(text
));
6392 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6395 switch (data
->exportInfo
.dwSubjectChoice
)
6397 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6398 contentID
= IDS_EXPORT_FILTER_CRL
;
6400 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6401 contentID
= IDS_EXPORT_FILTER_CTL
;
6403 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6404 contentID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6407 switch (data
->contextInfo
.dwExportFormat
)
6409 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6410 contentID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6412 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6413 contentID
= IDS_EXPORT_FILTER_CMS
;
6415 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6416 contentID
= IDS_EXPORT_FILTER_PFX
;
6419 contentID
= IDS_EXPORT_FILTER_CERT
;
6422 LoadStringW(hInstance
, contentID
, text
, ARRAY_SIZE(text
));
6423 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6426 static inline BOOL
save_der(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6430 return WriteFile(file
, pb
, cb
, &bytesWritten
, NULL
);
6433 static BOOL
save_base64(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6438 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, NULL
, &size
)))
6440 LPSTR buf
= HeapAlloc(GetProcessHeap(), 0, size
);
6444 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, buf
,
6446 ret
= WriteFile(file
, buf
, size
, &size
, NULL
);
6447 HeapFree(GetProcessHeap(), 0, buf
);
6451 SetLastError(ERROR_OUTOFMEMORY
);
6458 static inline BOOL
save_store_as_cms(HANDLE file
, HCERTSTORE store
)
6460 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6461 CERT_STORE_SAVE_AS_PKCS7
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6464 static BOOL
save_cert_as_cms(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6468 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
6469 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6475 HCERTSTORE addlStore
= CertOpenStore(CERT_STORE_PROV_COLLECTION
,
6476 0, 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6483 for (i
= 0; ret
&& i
< pExportInfo
->cStores
; i
++)
6484 ret
= CertAddStoreToCollection(addlStore
,
6485 pExportInfo
->rghStores
, 0, 0);
6488 PCCERT_CHAIN_CONTEXT chain
;
6490 ret
= CertGetCertificateChain(NULL
,
6491 pExportInfo
->u
.pCertContext
, NULL
, addlStore
, NULL
, 0,
6497 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6498 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6500 ret
= CertAddCertificateContextToStore(store
,
6501 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6502 CERT_STORE_ADD_ALWAYS
, NULL
);
6503 CertFreeCertificateChain(chain
);
6507 /* No chain could be created, just add the individual
6508 * cert to the message.
6510 ret
= CertAddCertificateContextToStore(store
,
6511 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
,
6515 CertCloseStore(addlStore
, 0);
6521 ret
= CertAddCertificateContextToStore(store
,
6522 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, NULL
);
6524 ret
= save_store_as_cms(file
, store
);
6525 CertCloseStore(store
, 0);
6532 static BOOL
save_serialized_store(HANDLE file
, HCERTSTORE store
)
6534 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6535 CERT_STORE_SAVE_AS_STORE
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6538 static BOOL
save_pfx(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6539 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6540 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6542 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, X509_ASN_ENCODING
,
6543 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6548 CRYPT_DATA_BLOB pfxBlob
= { 0, NULL
};
6549 PCCERT_CONTEXT cert
= NULL
;
6550 BOOL freeKeyProvInfo
= FALSE
;
6552 if (pContextInfo
->fExportChain
)
6554 HCERTCHAINENGINE engine
= NULL
;
6556 if (pExportInfo
->cStores
)
6558 CERT_CHAIN_ENGINE_CONFIG config
;
6560 memset(&config
, 0, sizeof(config
));
6561 config
.cbSize
= sizeof(config
);
6562 config
.cAdditionalStore
= pExportInfo
->cStores
;
6563 config
.rghAdditionalStore
= pExportInfo
->rghStores
;
6564 ret
= CertCreateCertificateChainEngine(&config
, &engine
);
6570 CERT_CHAIN_PARA chainPara
;
6571 PCCERT_CHAIN_CONTEXT chain
;
6573 memset(&chainPara
, 0, sizeof(chainPara
));
6574 chainPara
.cbSize
= sizeof(chainPara
);
6575 ret
= CertGetCertificateChain(engine
,
6576 pExportInfo
->u
.pCertContext
, NULL
, NULL
, &chainPara
, 0, NULL
,
6582 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6583 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6586 if (i
== 0 && j
== 0)
6587 ret
= CertAddCertificateContextToStore(store
,
6588 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6589 CERT_STORE_ADD_ALWAYS
, &cert
);
6591 ret
= CertAddCertificateContextToStore(store
,
6592 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6593 CERT_STORE_ADD_ALWAYS
, NULL
);
6595 CertFreeCertificateChain(chain
);
6599 CertFreeCertificateChainEngine(engine
);
6602 ret
= CertAddCertificateContextToStore(store
,
6603 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, &cert
);
6604 /* Copy private key info to newly created cert, so it'll get exported
6605 * along with the cert.
6607 if (ret
&& pContextInfo
->fExportPrivateKeys
)
6610 ret
= CertSetCertificateContextProperty(cert
,
6611 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6614 if (!(keyProvInfo
= export_get_private_key_info(cert
)))
6618 ret
= CertSetCertificateContextProperty(cert
,
6619 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6620 freeKeyProvInfo
= TRUE
;
6627 REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
| EXPORT_PRIVATE_KEYS
;
6629 ret
= PFXExportCertStore(store
, &pfxBlob
,
6630 pContextInfo
->pwszPassword
, exportFlags
);
6633 pfxBlob
.pbData
= HeapAlloc(GetProcessHeap(), 0, pfxBlob
.cbData
);
6636 ret
= PFXExportCertStore(store
, &pfxBlob
,
6637 pContextInfo
->pwszPassword
, exportFlags
);
6642 ret
= WriteFile(file
, pfxBlob
.pbData
, pfxBlob
.cbData
,
6643 &bytesWritten
, NULL
);
6648 SetLastError(ERROR_OUTOFMEMORY
);
6653 if (ret
&& deleteKeys
)
6657 CryptAcquireContextW(&prov
, keyProvInfo
->pwszContainerName
,
6658 keyProvInfo
->pwszProvName
, keyProvInfo
->dwProvType
,
6659 CRYPT_DELETEKEYSET
);
6661 if (freeKeyProvInfo
)
6662 HeapFree(GetProcessHeap(), 0, keyProvInfo
);
6663 CertFreeCertificateContext(cert
);
6664 CertCloseStore(store
, 0);
6669 static BOOL
do_export(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6670 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6671 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6675 if (pContextInfo
->dwSize
!= sizeof(CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
))
6677 SetLastError(E_INVALIDARG
);
6680 switch (pExportInfo
->dwSubjectChoice
)
6682 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6683 ret
= save_der(file
,
6684 pExportInfo
->u
.pCRLContext
->pbCrlEncoded
,
6685 pExportInfo
->u
.pCRLContext
->cbCrlEncoded
);
6687 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6688 ret
= save_der(file
,
6689 pExportInfo
->u
.pCTLContext
->pbCtlEncoded
,
6690 pExportInfo
->u
.pCTLContext
->cbCtlEncoded
);
6692 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6693 ret
= save_serialized_store(file
, pExportInfo
->u
.hCertStore
);
6695 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6696 ret
= save_store_as_cms(file
, pExportInfo
->u
.hCertStore
);
6699 switch (pContextInfo
->dwExportFormat
)
6701 case CRYPTUI_WIZ_EXPORT_FORMAT_DER
:
6702 ret
= save_der(file
, pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6703 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6705 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6706 ret
= save_base64(file
,
6707 pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6708 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6710 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6711 ret
= save_cert_as_cms(file
, pExportInfo
,
6712 pContextInfo
->fExportChain
);
6714 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6715 ret
= save_pfx(file
, pExportInfo
, pContextInfo
, keyProvInfo
,
6719 SetLastError(E_FAIL
);
6726 static LRESULT CALLBACK
export_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6730 struct ExportWizData
*data
;
6736 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6737 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6741 data
= (struct ExportWizData
*)page
->lParam
;
6742 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6743 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
6744 (WPARAM
)data
->titleFont
, TRUE
);
6745 GetWindowRect(lv
, &rc
);
6746 column
.mask
= LVCF_WIDTH
;
6747 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
6748 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
6749 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
6750 show_export_details(lv
, data
);
6755 NMHDR
*hdr
= (NMHDR
*)lp
;
6761 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6763 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6764 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
6765 show_export_details(lv
, data
);
6766 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6767 PSWIZB_BACK
| PSWIZB_FINISH
);
6774 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
6778 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6779 if ((data
->success
= do_export(data
->file
, &data
->exportInfo
,
6780 &data
->contextInfo
, data
->keyProvInfo
, data
->deleteKeys
)))
6782 messageID
= IDS_EXPORT_SUCCEEDED
;
6787 messageID
= IDS_EXPORT_FAILED
;
6788 mbFlags
= MB_OK
| MB_ICONERROR
;
6790 if (data
->pwszWizardTitle
)
6791 pTitle
= data
->pwszWizardTitle
;
6794 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6797 LoadStringW(hInstance
, messageID
, message
, ARRAY_SIZE(message
));
6798 MessageBoxW(hwnd
, message
, pTitle
, mbFlags
);
6808 static BOOL
show_export_ui(DWORD dwFlags
, HWND hwndParent
,
6809 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, const void *pvoid
)
6811 PROPSHEETHEADERW hdr
;
6812 PROPSHEETPAGEW pages
[6];
6813 struct ExportWizData data
;
6815 BOOL hasPrivateKey
, showFormatPage
= TRUE
;
6818 data
.dwFlags
= dwFlags
;
6819 data
.pwszWizardTitle
= pwszWizardTitle
;
6820 memset(&data
.exportInfo
, 0, sizeof(data
.exportInfo
));
6821 memcpy(&data
.exportInfo
, pExportInfo
,
6822 min(sizeof(data
.exportInfo
), pExportInfo
->dwSize
));
6823 if (pExportInfo
->dwSize
> sizeof(data
.exportInfo
))
6824 data
.exportInfo
.dwSize
= sizeof(data
.exportInfo
);
6825 data
.contextInfo
.dwSize
= sizeof(data
.contextInfo
);
6826 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6827 data
.contextInfo
.fExportChain
= FALSE
;
6828 data
.contextInfo
.fStrongEncryption
= FALSE
;
6829 data
.contextInfo
.fExportPrivateKeys
= FALSE
;
6830 data
.contextInfo
.pwszPassword
= NULL
;
6831 data
.freePassword
= FALSE
;
6832 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
&&
6834 memcpy(&data
.contextInfo
, pvoid
,
6835 min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
)pvoid
)->dwSize
,
6836 sizeof(data
.contextInfo
)));
6837 data
.keyProvInfo
= NULL
;
6838 data
.deleteKeys
= FALSE
;
6839 data
.fileName
= NULL
;
6840 data
.file
= INVALID_HANDLE_VALUE
;
6841 data
.success
= FALSE
;
6843 memset(pages
, 0, sizeof(pages
));
6845 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6846 pages
[nPages
].hInstance
= hInstance
;
6847 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_WELCOME
);
6848 pages
[nPages
].pfnDlgProc
= export_welcome_dlg_proc
;
6849 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6850 pages
[nPages
].lParam
= (LPARAM
)&data
;
6853 hasPrivateKey
= export_info_has_private_key(pExportInfo
);
6854 switch (pExportInfo
->dwSubjectChoice
)
6856 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6857 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6858 showFormatPage
= FALSE
;
6859 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6861 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6862 showFormatPage
= FALSE
;
6863 data
.contextInfo
.dwExportFormat
=
6864 CRYPTUI_WIZ_EXPORT_FORMAT_SERIALIZED_CERT_STORE
;
6866 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6867 showFormatPage
= FALSE
;
6868 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
6872 if (hasPrivateKey
&& showFormatPage
)
6874 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6875 pages
[nPages
].hInstance
= hInstance
;
6876 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY
);
6877 pages
[nPages
].pfnDlgProc
= export_private_key_dlg_proc
;
6878 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6879 pages
[nPages
].pszHeaderTitle
=
6880 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE
);
6881 pages
[nPages
].pszHeaderSubTitle
=
6882 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE
);
6883 pages
[nPages
].lParam
= (LPARAM
)&data
;
6888 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6889 pages
[nPages
].hInstance
= hInstance
;
6890 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FORMAT
);
6891 pages
[nPages
].pfnDlgProc
= export_format_dlg_proc
;
6892 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6893 pages
[nPages
].pszHeaderTitle
=
6894 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_TITLE
);
6895 pages
[nPages
].pszHeaderSubTitle
=
6896 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_SUBTITLE
);
6897 pages
[nPages
].lParam
= (LPARAM
)&data
;
6900 if (hasPrivateKey
&& showFormatPage
)
6902 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6903 pages
[nPages
].hInstance
= hInstance
;
6904 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD
);
6905 pages
[nPages
].pfnDlgProc
= export_password_dlg_proc
;
6906 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6907 pages
[nPages
].pszHeaderTitle
=
6908 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE
);
6909 pages
[nPages
].pszHeaderSubTitle
=
6910 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE
);
6911 pages
[nPages
].lParam
= (LPARAM
)&data
;
6915 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6916 pages
[nPages
].hInstance
= hInstance
;
6917 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FILE
);
6918 pages
[nPages
].pfnDlgProc
= export_file_dlg_proc
;
6919 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6920 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_EXPORT_FILE_TITLE
);
6921 pages
[nPages
].pszHeaderSubTitle
=
6922 MAKEINTRESOURCEW(IDS_EXPORT_FILE_SUBTITLE
);
6923 pages
[nPages
].lParam
= (LPARAM
)&data
;
6926 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6927 pages
[nPages
].hInstance
= hInstance
;
6928 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FINISH
);
6929 pages
[nPages
].pfnDlgProc
= export_finish_dlg_proc
;
6930 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6931 pages
[nPages
].lParam
= (LPARAM
)&data
;
6934 memset(&hdr
, 0, sizeof(hdr
));
6935 hdr
.dwSize
= sizeof(hdr
);
6936 hdr
.hwndParent
= hwndParent
;
6937 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
6939 hdr
.hInstance
= hInstance
;
6940 if (pwszWizardTitle
)
6941 hdr
.pszCaption
= pwszWizardTitle
;
6943 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_EXPORT_WIZARD
);
6944 hdr
.u3
.ppsp
= pages
;
6945 hdr
.nPages
= nPages
;
6946 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
6947 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
6948 l
= PropertySheetW(&hdr
);
6949 DeleteObject(data
.titleFont
);
6950 if (data
.freePassword
)
6951 HeapFree(GetProcessHeap(), 0,
6952 (LPWSTR
)data
.contextInfo
.pwszPassword
);
6953 HeapFree(GetProcessHeap(), 0, data
.keyProvInfo
);
6954 CloseHandle(data
.file
);
6955 HeapFree(GetProcessHeap(), 0, data
.fileName
);
6958 SetLastError(ERROR_CANCELLED
);
6962 return data
.success
;
6965 BOOL WINAPI
CryptUIWizExport(DWORD dwFlags
, HWND hwndParent
,
6966 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, void *pvoid
)
6970 TRACE("(%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
,
6971 debugstr_w(pwszWizardTitle
), pExportInfo
, pvoid
);
6973 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
6974 ret
= show_export_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pExportInfo
,
6978 HANDLE file
= CreateFileW(pExportInfo
->pwszExportFileName
,
6979 GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6980 CREATE_ALWAYS
, 0, NULL
);
6982 if (file
!= INVALID_HANDLE_VALUE
)
6984 ret
= do_export(file
, pExportInfo
, pvoid
, NULL
, FALSE
);
6993 BOOL WINAPI
CryptUIDlgViewSignerInfoA(CRYPTUI_VIEWSIGNERINFO_STRUCTA
*pcvsi
)
6995 FIXME("%p: stub\n", pcvsi
);
6999 static void init_columns(HWND lv
, DWORD flags
)
7001 WCHAR buf
[MAX_STRING_LEN
];
7005 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
7006 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
7008 column
.pszText
= buf
;
7009 if (!(flags
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
))
7011 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
, ARRAY_SIZE(buf
));
7012 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7014 if (!(flags
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
))
7016 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
, ARRAY_SIZE(buf
));
7017 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7019 if (!(flags
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
))
7021 LoadStringW(hInstance
, IDS_INTENDED_USE_COLUMN
, buf
, ARRAY_SIZE(buf
));
7022 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7024 if (!(flags
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
))
7026 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
, ARRAY_SIZE(buf
));
7027 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7029 if (!(flags
& CRYPTUI_SELECT_EXPIRATION_COLUMN
))
7031 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
7032 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7034 if (!(flags
& CRYPTUI_SELECT_LOCATION_COLUMN
))
7036 LoadStringW(hInstance
, IDS_LOCATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
7037 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7041 static void add_cert_to_list(HWND lv
, PCCERT_CONTEXT cert
, DWORD flags
, DWORD
*allocatedLen
,
7046 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
7049 LPWSTR none
, usages
;
7051 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
7052 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
7055 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
7058 item
.mask
|= LVIF_STATE
;
7059 item
.state
= LVIS_SELECTED
;
7060 item
.stateMask
= -1;
7062 if (!(flags
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
))
7064 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
, NULL
, 0);
7065 if (len
> *allocatedLen
)
7067 HeapFree(GetProcessHeap(), 0, *str
);
7068 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
7070 *allocatedLen
= len
;
7074 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
, *str
, len
);
7075 item
.pszText
= *str
;
7076 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7078 item
.mask
= LVIF_TEXT
;
7081 if (!(flags
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
))
7083 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, CERT_NAME_ISSUER_FLAG
, NULL
,
7085 if (len
> *allocatedLen
)
7087 HeapFree(GetProcessHeap(), 0, *str
);
7088 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
7090 *allocatedLen
= len
;
7094 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, CERT_NAME_ISSUER_FLAG
, NULL
,
7096 item
.pszText
= *str
;
7098 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7100 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7102 item
.mask
= LVIF_TEXT
;
7105 if (!(flags
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
))
7107 get_cert_usages(cert
, &usages
);
7110 item
.pszText
= usages
;
7112 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7114 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7115 HeapFree(GetProcessHeap(), 0, usages
);
7117 item
.mask
= LVIF_TEXT
;
7120 if (!(flags
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
))
7122 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
, NULL
, &len
))
7123 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
7124 if (len
> *allocatedLen
)
7126 HeapFree(GetProcessHeap(), 0, *str
);
7127 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
7129 *allocatedLen
= len
;
7133 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
, *str
, &len
))
7134 item
.pszText
= none
;
7136 item
.pszText
= *str
;
7138 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7140 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7142 item
.mask
= LVIF_TEXT
;
7145 if (!(flags
& CRYPTUI_SELECT_EXPIRATION_COLUMN
))
7147 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
7148 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
7149 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
, ARRAY_SIZE(buf
));
7152 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7154 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7155 item
.mask
= LVIF_TEXT
;
7158 if (!(flags
& CRYPTUI_SELECT_LOCATION_COLUMN
))
7160 static int show_fixme
;
7162 FIXME("showing location is not implemented\n");
7163 LoadStringW(hInstance
, IDS_NO_IMPL
, buf
, ARRAY_SIZE(buf
));
7165 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7167 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7171 static void add_store_certs(HWND lv
, HCERTSTORE store
, DWORD flags
, PFNCFILTERPROC filter
,
7172 void *callback_data
)
7174 PCCERT_CONTEXT cert
= NULL
;
7175 BOOL select
= FALSE
;
7176 DWORD allocatedLen
= 0;
7180 cert
= CertEnumCertificatesInStore(store
, cert
);
7181 if (cert
&& (!filter
|| filter(cert
, &select
, callback_data
)))
7182 add_cert_to_list(lv
, cert
, flags
, &allocatedLen
, &str
);
7184 HeapFree(GetProcessHeap(), 0, str
);
7187 static PCCERT_CONTEXT
select_cert_get_selected(HWND hwnd
, int selection
)
7189 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7190 PCCERT_CONTEXT cert
= NULL
;
7194 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1, LVNI_SELECTED
);
7197 item
.mask
= LVIF_PARAM
;
7198 item
.iItem
= selection
;
7200 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
7201 cert
= (PCCERT_CONTEXT
)item
.lParam
;
7205 static void select_cert_update_view_button(HWND hwnd
)
7207 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7208 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
7210 EnableWindow(GetDlgItem(hwnd
, IDC_SELECT_VIEW_CERT
), numSelected
== 1);
7213 struct SelectCertData
7215 PCCERT_CONTEXT
*cert
;
7217 HIMAGELIST imageList
;
7220 HCERTSTORE
*rghStores
;
7221 DWORD cPropSheetPages
;
7222 LPCPROPSHEETPAGEW rgPropSheetPages
;
7223 PFNCCERTDISPLAYPROC displayProc
;
7227 static void select_cert_view(HWND hwnd
, PCCERT_CONTEXT cert
, struct SelectCertData
*data
)
7229 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
7231 if (data
->displayProc
&& data
->displayProc(cert
, hwnd
, data
->callbackData
))
7233 memset(&viewInfo
, 0, sizeof(viewInfo
));
7234 viewInfo
.dwSize
= sizeof(viewInfo
);
7235 viewInfo
.hwndParent
= hwnd
;
7236 viewInfo
.pCertContext
= cert
;
7237 viewInfo
.cStores
= data
->cStores
;
7238 viewInfo
.rghStores
= data
->rghStores
;
7239 viewInfo
.cPropSheetPages
= data
->cPropSheetPages
;
7240 viewInfo
.rgPropSheetPages
= data
->rgPropSheetPages
;
7241 /* FIXME: this should be modal */
7242 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
7251 static int CALLBACK
select_cert_sort_by_text(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
7253 struct SortData
*data
= (struct SortData
*)lp
;
7254 return cert_mgr_sort_by_text(data
->hwnd
, data
->column
, lp1
, lp2
);
7257 struct SelectCertParam
7259 PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
;
7260 PCCERT_CONTEXT cert
;
7263 static LRESULT CALLBACK
select_cert_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
7265 struct SelectCertData
*data
;
7271 struct SelectCertParam
*param
= (struct SelectCertParam
*)lp
;
7272 PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
= param
->pcsc
;
7273 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7276 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
7279 data
->cert
= ¶m
->cert
;
7280 data
->dateColumn
= 4 -
7281 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
) ? 1 : 0) -
7282 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
) ? 1 : 0) -
7283 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
) ? 1 : 0) -
7284 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
) ? 1 : 0);
7285 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
7286 if (data
->imageList
)
7289 COLORREF backColor
= RGB(255, 0, 255);
7291 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
7292 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
7294 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
7295 SendMessageW(GetDlgItem(hwnd
, IDC_SELECT_CERTS
), LVM_SETIMAGELIST
, LVSIL_SMALL
,
7296 (LPARAM
)data
->imageList
);
7298 data
->title
= pcsc
->szTitle
;
7299 data
->cStores
= pcsc
->cStores
;
7300 data
->rghStores
= pcsc
->rghStores
;
7301 data
->cPropSheetPages
= pcsc
->cPropSheetPages
;
7302 data
->rgPropSheetPages
= pcsc
->rgPropSheetPages
;
7303 data
->displayProc
= pcsc
->pDisplayCallback
;
7304 data
->callbackData
= pcsc
->pvCallbackData
;
7305 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
7308 SendMessageW(hwnd
, WM_SETTEXT
, 0, (LPARAM
)pcsc
->szTitle
);
7309 if (pcsc
->szDisplayString
)
7310 SendMessageW(GetDlgItem(hwnd
, IDC_SELECT_DISPLAY_STRING
), WM_SETTEXT
, 0,
7311 (LPARAM
)pcsc
->szDisplayString
);
7312 init_columns(lv
, pcsc
->dwDontUseColumn
);
7313 while (i
< pcsc
->cDisplayStores
)
7314 add_store_certs(lv
, pcsc
->rghDisplayStores
[i
++], pcsc
->dwDontUseColumn
,
7315 pcsc
->pFilterCallback
, pcsc
->pvCallbackData
);
7316 select_cert_update_view_button(hwnd
);
7321 NMHDR
*hdr
= (NMHDR
*)lp
;
7327 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
7329 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7331 select_cert_view(hwnd
, cert
, data
);
7334 case LVN_COLUMNCLICK
:
7336 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
7337 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7339 /* FIXME: doesn't support swapping sort order between ascending and descending. */
7340 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7341 if (nmlv
->iSubItem
== data
->dateColumn
)
7342 SendMessageW(lv
, LVM_SORTITEMS
, 0, (LPARAM
)cert_mgr_sort_by_date
);
7345 struct SortData sortData
;
7348 sortData
.column
= nmlv
->iSubItem
;
7349 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)&sortData
,
7350 (LPARAM
)select_cert_sort_by_text
);
7362 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, -1);
7364 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7367 WCHAR buf
[40], title
[40];
7369 LoadStringW(hInstance
, IDS_SELECT_CERT
, buf
, ARRAY_SIZE(buf
));
7371 LoadStringW(hInstance
, IDS_SELECT_CERT_TITLE
, title
, ARRAY_SIZE(title
));
7372 MessageBoxW(hwnd
, buf
, data
->title
? data
->title
: title
, MB_OK
| MB_ICONWARNING
);
7375 *data
->cert
= CertDuplicateCertificateContext(cert
);
7376 free_certs(GetDlgItem(hwnd
, IDC_SELECT_CERTS
));
7377 ImageList_Destroy(data
->imageList
);
7378 HeapFree(GetProcessHeap(), 0, data
);
7379 EndDialog(hwnd
, IDOK
);
7383 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7384 free_certs(GetDlgItem(hwnd
, IDC_SELECT_CERTS
));
7385 ImageList_Destroy(data
->imageList
);
7386 HeapFree(GetProcessHeap(), 0, data
);
7387 EndDialog(hwnd
, IDCANCEL
);
7389 case IDC_SELECT_VIEW_CERT
:
7391 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, -1);
7393 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7395 select_cert_view(hwnd
, cert
, data
);
7404 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateW(PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
)
7406 struct SelectCertParam param
;
7408 TRACE("%p\n", pcsc
);
7410 if (pcsc
->dwSize
!= sizeof(*pcsc
) && pcsc
->dwSize
!= sizeof(*pcsc
) - sizeof(HCERTSTORE
))
7412 WARN("unexpected size %d\n", pcsc
->dwSize
);
7413 SetLastError(E_INVALIDARG
);
7416 if (pcsc
->dwFlags
& CRYPTUI_SELECTCERT_MULTISELECT
)
7417 FIXME("ignoring CRYPTUI_SELECTCERT_MULTISELECT\n");
7420 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_CERT
), pcsc
->hwndParent
,
7421 select_cert_dlg_proc
, (LPARAM
)¶m
);
7425 static void free_prop_sheet_pages(PROPSHEETPAGEW
*pages
, DWORD num
)
7429 for (i
= 0; i
< num
; i
++)
7431 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].u
.pszTemplate
))
7432 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].u
.pszTemplate
);
7433 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].u2
.pszIcon
))
7434 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].u2
.pszIcon
);
7435 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7436 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].pszTitle
);
7437 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7438 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].pszHeaderTitle
);
7439 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7440 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7441 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].pszHeaderSubTitle
);
7443 HeapFree(GetProcessHeap(), 0, pages
);
7446 static PROPSHEETPAGEW
*prop_sheet_pages_AtoW(LPCPROPSHEETPAGEA pages
, DWORD num
)
7448 PROPSHEETPAGEW
*psp
;
7449 DWORD i
, size
= sizeof(*psp
) * num
;
7451 psp
= HeapAlloc(GetProcessHeap(), 0, size
);
7454 memcpy(psp
, pages
, size
);
7455 for (i
= 0; i
< num
; i
++)
7457 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].u
.pszTemplate
))
7458 psp
[i
].u
.pszTemplate
= NULL
;
7459 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].u2
.pszIcon
))
7460 psp
[i
].u2
.pszIcon
= NULL
;
7461 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7462 psp
[i
].pszTitle
= NULL
;
7463 if (pages
[i
].dwFlags
& PSP_USECALLBACK
)
7464 psp
[i
].pfnCallback
= NULL
;
7465 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7466 psp
[i
].pszHeaderTitle
= NULL
;
7467 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7468 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7469 psp
[i
].pszHeaderSubTitle
= NULL
;
7471 for (i
= 0; i
< num
; i
++)
7473 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].u
.pszTemplate
))
7475 if (!(psp
[i
].u
.pszTemplate
= strdupAtoW( pages
[i
].u
.pszTemplate
))) goto error
;
7477 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].u2
.pszIcon
))
7479 if (!(psp
[i
].u2
.pszIcon
= strdupAtoW( pages
[i
].u2
.pszIcon
))) goto error
;
7481 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7483 if (!(psp
[i
].pszTitle
= strdupAtoW( pages
[i
].pszTitle
))) goto error
;
7485 if (pages
[i
].dwFlags
& PSP_USECALLBACK
)
7486 FIXME("ignoring pfnCallback\n");
7487 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7489 if (!(psp
[i
].pszHeaderTitle
= strdupAtoW( pages
[i
].pszHeaderTitle
))) goto error
;
7491 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7492 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7494 if (!(psp
[i
].pszHeaderSubTitle
= strdupAtoW( pages
[i
].pszHeaderSubTitle
))) goto error
;
7499 free_prop_sheet_pages(psp
, num
);
7503 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateA(PCCRYPTUI_SELECTCERTIFICATE_STRUCTA pcsc
)
7505 PCCERT_CONTEXT cert
= NULL
;
7506 CRYPTUI_SELECTCERTIFICATE_STRUCTW selCertInfo
;
7507 LPWSTR title
= NULL
, display_str
= NULL
;
7508 PROPSHEETPAGEW
*pages
= NULL
;
7510 TRACE("%p\n", pcsc
);
7512 if (pcsc
->dwSize
!= sizeof(*pcsc
) && pcsc
->dwSize
!= sizeof(*pcsc
) - sizeof(HCERTSTORE
))
7514 WARN("unexpected size %d\n", pcsc
->dwSize
);
7515 SetLastError(E_INVALIDARG
);
7518 memcpy(&selCertInfo
, pcsc
, pcsc
->dwSize
);
7521 if (!(title
= strdupAtoW( pcsc
->szTitle
))) goto error
;
7522 selCertInfo
.szTitle
= title
;
7524 if (pcsc
->szDisplayString
)
7526 if (!(display_str
= strdupAtoW( pcsc
->szDisplayString
))) goto error
;
7527 selCertInfo
.szDisplayString
= display_str
;
7529 if (pcsc
->cPropSheetPages
)
7531 pages
= prop_sheet_pages_AtoW(pcsc
->rgPropSheetPages
, pcsc
->cPropSheetPages
);
7534 selCertInfo
.rgPropSheetPages
= pages
;
7536 cert
= CryptUIDlgSelectCertificateW(&selCertInfo
);
7538 HeapFree(GetProcessHeap(), 0, title
);
7539 HeapFree(GetProcessHeap(), 0, display_str
);
7540 if (pcsc
->cPropSheetPages
)
7541 free_prop_sheet_pages(pages
, pcsc
->cPropSheetPages
);
7545 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateFromStore(HCERTSTORE hCertStore
, HWND hwnd
, LPCWSTR pwszTitle
,
7546 LPCWSTR pwszDisplayString
, DWORD dwDontUseColumn
,
7547 DWORD dwFlags
, void *pvReserved
)
7549 CRYPTUI_SELECTCERTIFICATE_STRUCTW sc
;
7551 TRACE("%p %p %s %s %x %x %p\n", hCertStore
, hwnd
, debugstr_w(pwszTitle
), debugstr_w(pwszDisplayString
), dwDontUseColumn
, dwFlags
, pvReserved
);
7553 memset(&sc
, 0, sizeof(sc
));
7555 sc
.dwSize
= sizeof(sc
);
7556 sc
.hwndParent
= hwnd
;
7557 sc
.dwFlags
= dwFlags
;
7558 sc
.szTitle
= pwszTitle
;
7559 sc
.szDisplayString
= pwszDisplayString
;
7560 sc
.dwDontUseColumn
= dwDontUseColumn
;
7561 sc
.cDisplayStores
= 1;
7562 sc
.rghDisplayStores
= &hCertStore
;
7563 return CryptUIDlgSelectCertificateW(&sc
);
7566 BOOL WINAPI
CryptUIWizDigitalSign(DWORD flags
, HWND parent
, LPCWSTR title
, PCCRYPTUI_WIZ_DIGITAL_SIGN_INFO info
,
7567 PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
*context
)
7569 FIXME("%d %p %s %p %p: stub\n", flags
, parent
, debugstr_w(title
), info
, context
);