2 * Copyright 2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
37 #include "cryptuiapi.h"
38 #include "cryptuires.h"
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
47 static HINSTANCE hInstance
;
49 static const WCHAR empty
[] = {0};
51 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
53 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
57 case DLL_WINE_PREATTACH
:
58 return FALSE
; /* prefer native version */
59 case DLL_PROCESS_ATTACH
:
61 DisableThreadLibraryCalls(hinstDLL
);
67 static WCHAR
*strdupAtoW( const char *str
)
69 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
70 WCHAR
*ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
71 if (ret
) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
75 #define MAX_STRING_LEN 512
77 static void add_cert_columns(HWND hwnd
)
79 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
81 WCHAR buf
[MAX_STRING_LEN
];
84 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
85 GetWindowRect(lv
, &rc
);
86 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
, ARRAY_SIZE(buf
));
87 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
88 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
90 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
91 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
, ARRAY_SIZE(buf
));
92 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
93 column
.cx
= (rc
.right
- rc
.left
) * 16 / 100 - 2;
94 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
95 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
96 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
97 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
, ARRAY_SIZE(buf
));
98 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 3, (LPARAM
)&column
);
101 static void add_cert_to_view(HWND lv
, PCCERT_CONTEXT cert
, DWORD
*allocatedLen
,
106 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
111 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
112 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
115 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
116 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
118 if (len
> *allocatedLen
)
120 HeapFree(GetProcessHeap(), 0, *str
);
121 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
127 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
130 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
133 item
.mask
= LVIF_TEXT
;
134 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
135 CERT_NAME_ISSUER_FLAG
, NULL
, NULL
, 0);
136 if (len
> *allocatedLen
)
138 HeapFree(GetProcessHeap(), 0, *str
);
139 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
145 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
146 CERT_NAME_ISSUER_FLAG
, NULL
, *str
, len
);
149 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
152 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
153 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
154 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
, ARRAY_SIZE(date
));
157 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
159 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
161 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
162 if (len
> *allocatedLen
)
164 HeapFree(GetProcessHeap(), 0, *str
);
165 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
171 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
177 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
181 static LPSTR
get_cert_mgr_usages(void)
183 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
184 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
185 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
186 'r','p','o','s','e',0 };
190 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
196 rc
= RegQueryValueExA(key
, "Purpose", NULL
, &type
, NULL
, &size
);
197 if ((!rc
|| rc
== ERROR_MORE_DATA
) && type
== REG_SZ
)
199 str
= HeapAlloc(GetProcessHeap(), 0, size
);
202 rc
= RegQueryValueExA(key
, "Purpose", NULL
, NULL
, (LPBYTE
)str
,
206 HeapFree(GetProcessHeap(), 0, str
);
217 PurposeFilterShowAll
= 0,
218 PurposeFilterShowAdvanced
= 1,
219 PurposeFilterShowOID
= 2
222 static void initialize_purpose_selection(HWND hwnd
)
224 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
225 WCHAR buf
[MAX_STRING_LEN
];
229 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
, ARRAY_SIZE(buf
));
230 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
231 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAll
);
232 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
, ARRAY_SIZE(buf
));
233 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
234 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAdvanced
);
235 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
236 if ((usages
= get_cert_mgr_usages()))
240 for (ptr
= usages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
241 ptr
= comma
? comma
+ 1 : NULL
,
242 comma
= ptr
? strchr(ptr
, ',') : NULL
)
244 PCCRYPT_OID_INFO info
;
248 if ((info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, ptr
, 0)))
250 index
= SendMessageW(cb
, CB_INSERTSTRING
, 0,
251 (LPARAM
)info
->pwszName
);
252 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)info
);
255 HeapFree(GetProcessHeap(), 0, usages
);
259 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
260 PCCRYPT_OID_INFO
**usages
);
262 static CERT_ENHKEY_USAGE
*add_oid_to_usage(CERT_ENHKEY_USAGE
*usage
, LPSTR oid
)
264 if (!usage
->cUsageIdentifier
)
265 usage
->rgpszUsageIdentifier
= HeapAlloc(GetProcessHeap(), 0,
268 usage
->rgpszUsageIdentifier
= HeapReAlloc(GetProcessHeap(), 0,
269 usage
->rgpszUsageIdentifier
,
270 (usage
->cUsageIdentifier
+ 1) * sizeof(LPSTR
));
271 if (usage
->rgpszUsageIdentifier
)
272 usage
->rgpszUsageIdentifier
[usage
->cUsageIdentifier
++] = oid
;
275 HeapFree(GetProcessHeap(), 0, usage
);
281 static CERT_ENHKEY_USAGE
*convert_usages_str_to_usage(LPSTR usageStr
)
283 CERT_ENHKEY_USAGE
*usage
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
284 sizeof(CERT_ENHKEY_USAGE
));
290 for (ptr
= usageStr
, comma
= strchr(ptr
, ','); usage
&& ptr
&& *ptr
;
291 ptr
= comma
? comma
+ 1 : NULL
,
292 comma
= ptr
? strchr(ptr
, ',') : NULL
)
296 usage
= add_oid_to_usage(usage
, ptr
);
302 static CERT_ENHKEY_USAGE
*create_advanced_filter(void)
304 CERT_ENHKEY_USAGE
*advancedUsage
= HeapAlloc(GetProcessHeap(),
305 HEAP_ZERO_MEMORY
, sizeof(CERT_ENHKEY_USAGE
));
309 PCCRYPT_OID_INFO
*usages
;
311 if (WTHelperGetKnownUsages(1, &usages
))
313 LPSTR disabledUsagesStr
;
315 if ((disabledUsagesStr
= get_cert_mgr_usages()))
317 CERT_ENHKEY_USAGE
*disabledUsages
=
318 convert_usages_str_to_usage(disabledUsagesStr
);
322 PCCRYPT_OID_INFO
*ptr
;
324 for (ptr
= usages
; advancedUsage
&& *ptr
; ptr
++)
327 BOOL disabled
= FALSE
;
329 for (i
= 0; !disabled
&&
330 i
< disabledUsages
->cUsageIdentifier
; i
++)
331 if (!strcmp(disabledUsages
->rgpszUsageIdentifier
[i
],
335 advancedUsage
= add_oid_to_usage(advancedUsage
,
336 (LPSTR
)(*ptr
)->pszOID
);
338 /* The individual strings are pointers to disabledUsagesStr,
339 * so they're freed when it is.
341 HeapFree(GetProcessHeap(), 0,
342 disabledUsages
->rgpszUsageIdentifier
);
343 HeapFree(GetProcessHeap(), 0, disabledUsages
);
345 HeapFree(GetProcessHeap(), 0, disabledUsagesStr
);
347 WTHelperGetKnownUsages(2, &usages
);
350 return advancedUsage
;
353 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
);
355 static void show_store_certs(HWND hwnd
, HCERTSTORE store
)
357 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
358 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
359 PCCERT_CONTEXT cert
= NULL
;
360 DWORD allocatedLen
= 0;
363 PurposeFilter filter
= PurposeFilterShowAll
;
365 CERT_ENHKEY_USAGE
*advanced
= NULL
;
367 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
370 INT_PTR data
= SendMessageW(cb
, CB_GETITEMDATA
, index
, 0);
376 PCCRYPT_OID_INFO info
= (PCCRYPT_OID_INFO
)data
;
378 filter
= PurposeFilterShowOID
;
382 if (filter
== PurposeFilterShowAdvanced
)
383 advanced
= create_advanced_filter();
385 cert
= CertEnumCertificatesInStore(store
, cert
);
390 if (filter
== PurposeFilterShowAll
)
397 if (CertGetValidUsages(1, &cert
, &numOIDs
, NULL
, &cbOIDs
))
401 /* -1 implies all usages are valid */
406 LPSTR
*oids
= HeapAlloc(GetProcessHeap(), 0, cbOIDs
);
410 if (CertGetValidUsages(1, &cert
, &numOIDs
, oids
,
415 if (filter
== PurposeFilterShowOID
)
417 for (i
= 0; !show
&& i
< numOIDs
; i
++)
418 if (!strcmp(oids
[i
], oid
))
423 for (i
= 0; !show
&& i
< numOIDs
; i
++)
428 j
< advanced
->cUsageIdentifier
; j
++)
430 advanced
->rgpszUsageIdentifier
[j
]))
435 HeapFree(GetProcessHeap(), 0, oids
);
441 add_cert_to_view(lv
, cert
, &allocatedLen
, &str
);
444 HeapFree(GetProcessHeap(), 0, str
);
447 HeapFree(GetProcessHeap(), 0, advanced
->rgpszUsageIdentifier
);
448 HeapFree(GetProcessHeap(), 0, advanced
);
450 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
451 (LPARAM
)cert_mgr_sort_by_subject
);
454 static const WCHAR my
[] = { 'M','y',0 };
455 static const WCHAR addressBook
[] = {
456 'A','d','d','r','e','s','s','B','o','o','k',0 };
457 static const WCHAR ca
[] = { 'C','A',0 };
458 static const WCHAR root
[] = { 'R','o','o','t',0 };
459 static const WCHAR trustedPublisher
[] = {
460 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
461 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
463 struct CertMgrStoreInfo
467 int removePluralWarning
;
470 static const struct CertMgrStoreInfo defaultStoreList
[] = {
471 { my
, IDS_WARN_REMOVE_MY
, IDS_WARN_REMOVE_PLURAL_MY
},
472 { addressBook
, IDS_WARN_REMOVE_ADDRESSBOOK
,
473 IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK
},
474 { ca
, IDS_WARN_REMOVE_CA
, IDS_WARN_REMOVE_PLURAL_CA
},
475 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
476 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
477 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
478 { disallowed
, IDS_WARN_REMOVE_DEFAULT
},
481 static const struct CertMgrStoreInfo publisherStoreList
[] = {
482 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
483 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
484 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
485 { disallowed
, IDS_WARN_REMOVE_PLURAL_DEFAULT
},
490 HIMAGELIST imageList
;
493 const struct CertMgrStoreInfo
*stores
;
496 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
, struct CertMgrData
*data
)
498 const struct CertMgrStoreInfo
*storeList
;
500 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
502 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
504 storeList
= publisherStoreList
;
505 cStores
= ARRAY_SIZE(publisherStoreList
);
509 storeList
= defaultStoreList
;
510 cStores
= ARRAY_SIZE(defaultStoreList
);
512 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
514 data
->nStores
= cStores
;
515 data
->stores
= storeList
;
516 for (i
= 0; i
< cStores
; i
++)
522 if (!(name
= CryptFindLocalizedName(storeList
[i
].name
)))
523 name
= storeList
[i
].name
;
524 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
525 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
].name
);
526 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
527 item
.pszText
= (LPWSTR
)name
;
528 item
.lParam
= (LPARAM
)store
;
529 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
533 static void free_certs(HWND lv
)
536 int items
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
538 for (i
= 0; i
< items
; i
++)
540 item
.mask
= LVIF_PARAM
;
543 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
544 CertFreeCertificateContext((PCCERT_CONTEXT
)item
.lParam
);
548 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
552 item
.mask
= TCIF_PARAM
;
553 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
554 return (HCERTSTORE
)item
.lParam
;
557 static HCERTSTORE
cert_mgr_current_store(HWND hwnd
)
559 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
561 return cert_mgr_index_to_store(tab
, SendMessageW(tab
, TCM_GETCURSEL
, 0, 0));
564 static void close_stores(HWND tab
)
566 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
568 for (i
= 0; i
< tabs
; i
++)
569 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
572 static void refresh_store_certs(HWND hwnd
)
574 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
577 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
578 show_store_certs(hwnd
, cert_mgr_current_store(hwnd
));
582 CheckBitmapIndexUnchecked
= 1,
583 CheckBitmapIndexChecked
= 2,
584 CheckBitmapIndexDisabledUnchecked
= 3,
585 CheckBitmapIndexDisabledChecked
= 4
588 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
,
589 CheckBitmapIndex state
)
593 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
594 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
595 item
.stateMask
= LVIS_STATEIMAGEMASK
;
596 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
598 item
.lParam
= (LPARAM
)info
;
599 item
.pszText
= (LPWSTR
)info
->pwszName
;
600 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
603 static void add_known_usages_to_list(HWND lv
, CheckBitmapIndex state
)
605 PCCRYPT_OID_INFO
*usages
;
607 if (WTHelperGetKnownUsages(1, &usages
))
609 PCCRYPT_OID_INFO
*ptr
;
611 for (ptr
= usages
; *ptr
; ptr
++)
612 add_known_usage(lv
, *ptr
, state
);
613 WTHelperGetKnownUsages(2, &usages
);
617 static void toggle_usage(HWND hwnd
, int iItem
)
621 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
623 item
.mask
= LVIF_STATE
;
626 item
.stateMask
= LVIS_STATEIMAGEMASK
;
627 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
630 int state
= item
.state
>> 12;
632 item
.state
= INDEXTOSTATEIMAGEMASK(
633 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
634 CheckBitmapIndexChecked
);
635 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
639 static LONG_PTR
find_oid_in_list(HWND lv
, LPCSTR oid
)
641 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
642 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
647 LVFINDINFOW findInfo
;
649 findInfo
.flags
= LVFI_PARAM
;
650 findInfo
.lParam
= (LPARAM
)oidInfo
;
651 ret
= SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
);
655 LVFINDINFOA findInfo
;
657 findInfo
.flags
= LVFI_STRING
;
659 ret
= SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
);
664 static void save_cert_mgr_usages(HWND hwnd
)
666 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
667 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
668 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
669 'r','p','o','s','e',0 };
671 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
672 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
676 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
678 item
.stateMask
= LVIS_STATEIMAGEMASK
;
679 for (i
= 0; i
< purposes
; i
++)
682 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
684 int state
= item
.state
>> 12;
686 if (state
== CheckBitmapIndexUnchecked
)
688 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
689 BOOL firstString
= TRUE
;
692 str
= HeapAlloc(GetProcessHeap(), 0,
693 strlen(info
->pszOID
) + 1);
696 str
= HeapReAlloc(GetProcessHeap(), 0, str
,
697 strlen(str
) + 1 + strlen(info
->pszOID
) + 1);
702 LPSTR ptr
= firstString
? str
: str
+ strlen(str
);
706 strcpy(ptr
, info
->pszOID
);
711 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_ALL_ACCESS
,
715 RegSetValueExA(key
, "Purpose", 0, REG_SZ
, (const BYTE
*)str
,
718 RegDeleteValueA(key
, "Purpose");
721 HeapFree(GetProcessHeap(), 0, str
);
724 static LRESULT CALLBACK
cert_mgr_advanced_dlg_proc(HWND hwnd
, UINT msg
,
725 WPARAM wp
, LPARAM lp
)
733 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
734 HIMAGELIST imageList
;
735 LPSTR disabledUsages
;
737 GetWindowRect(lv
, &rc
);
738 column
.mask
= LVCF_WIDTH
;
739 column
.cx
= rc
.right
- rc
.left
;
740 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
741 imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 4, 0);
745 COLORREF backColor
= RGB(255, 0, 255);
747 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
748 ImageList_AddMasked(imageList
, bmp
, backColor
);
750 ImageList_SetBkColor(imageList
, CLR_NONE
);
751 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)imageList
);
752 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)imageList
);
754 add_known_usages_to_list(lv
, CheckBitmapIndexChecked
);
755 if ((disabledUsages
= get_cert_mgr_usages()))
759 for (ptr
= disabledUsages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
760 ptr
= comma
? comma
+ 1 : NULL
,
761 comma
= ptr
? strchr(ptr
, ',') : NULL
)
767 if ((index
= find_oid_in_list(lv
, ptr
)) != -1)
768 toggle_usage(hwnd
, index
);
770 HeapFree(GetProcessHeap(), 0, disabledUsages
);
776 NMHDR
*hdr
= (NMHDR
*)lp
;
782 nm
= (NMITEMACTIVATE
*)lp
;
783 toggle_usage(hwnd
, nm
->iItem
);
784 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
793 save_cert_mgr_usages(hwnd
);
794 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
795 EndDialog(hwnd
, IDOK
);
798 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
799 EndDialog(hwnd
, IDCANCEL
);
807 static void cert_mgr_clear_cert_selection(HWND hwnd
)
809 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), FALSE
);
810 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), FALSE
);
811 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), FALSE
);
812 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
814 refresh_store_certs(hwnd
);
817 static PCCERT_CONTEXT
cert_mgr_index_to_cert(HWND hwnd
, int index
)
819 PCCERT_CONTEXT cert
= NULL
;
822 item
.mask
= LVIF_PARAM
;
825 if (SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_GETITEMW
, 0,
827 cert
= (PCCERT_CONTEXT
)item
.lParam
;
831 static void show_selected_cert(HWND hwnd
, int index
)
833 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
837 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
839 memset(&viewInfo
, 0, sizeof(viewInfo
));
840 viewInfo
.dwSize
= sizeof(viewInfo
);
841 viewInfo
.hwndParent
= hwnd
;
842 viewInfo
.pCertContext
= cert
;
843 /* FIXME: this should be modal */
844 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
848 static void get_cert_usages(PCCERT_CONTEXT cert
, LPWSTR
*str
)
850 PCERT_ENHKEY_USAGE usage
;
853 /* Get enhanced key usage. Have to check for a property and an extension
854 * separately, because CertGetEnhancedKeyUsage will succeed and return an
855 * empty usage if neither is set. Unfortunately an empty usage implies
856 * no usage is allowed, so we have to distinguish between the two cases.
858 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
861 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
862 if (!CertGetEnhancedKeyUsage(cert
,
863 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
865 HeapFree(GetProcessHeap(), 0, usage
);
869 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
872 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
873 if (!CertGetEnhancedKeyUsage(cert
,
874 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
876 HeapFree(GetProcessHeap(), 0, usage
);
884 if (usage
->cUsageIdentifier
)
886 static const WCHAR commaSpace
[] = { ',',' ',0 };
890 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
892 PCCRYPT_OID_INFO info
=
893 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
894 usage
->rgpszUsageIdentifier
[i
],
895 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
898 len
+= strlenW(info
->pwszName
);
900 len
+= strlen(usage
->rgpszUsageIdentifier
[i
]);
901 if (i
< usage
->cUsageIdentifier
- 1)
902 len
+= strlenW(commaSpace
);
904 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
907 for (i
= 0, ptr
= *str
; i
< usage
->cUsageIdentifier
; i
++)
909 PCCRYPT_OID_INFO info
=
910 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
911 usage
->rgpszUsageIdentifier
[i
],
912 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
916 strcpyW(ptr
, info
->pwszName
);
917 ptr
+= strlenW(info
->pwszName
);
921 LPCSTR src
= usage
->rgpszUsageIdentifier
[i
];
923 for (; *src
; ptr
++, src
++)
927 if (i
< usage
->cUsageIdentifier
- 1)
929 strcpyW(ptr
, commaSpace
);
930 ptr
+= strlenW(commaSpace
);
935 HeapFree(GetProcessHeap(), 0, usage
);
939 size
= MAX_STRING_LEN
* sizeof(WCHAR
);
940 *str
= HeapAlloc(GetProcessHeap(), 0, size
);
942 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_NONE
, *str
, size
);
947 size
= MAX_STRING_LEN
* sizeof(WCHAR
);
948 *str
= HeapAlloc(GetProcessHeap(), 0, size
);
950 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_ALL
, *str
, size
);
954 static void cert_mgr_show_cert_usages(HWND hwnd
, int index
)
956 HWND text
= GetDlgItem(hwnd
, IDC_MGR_PURPOSES
);
957 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
960 get_cert_usages(cert
, &str
);
963 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)str
);
964 HeapFree(GetProcessHeap(), 0, str
);
968 static void cert_mgr_do_remove(HWND hwnd
)
970 int tabIndex
= SendMessageW(GetDlgItem(hwnd
, IDC_MGR_STORES
),
971 TCM_GETCURSEL
, 0, 0);
972 struct CertMgrData
*data
=
973 (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
975 if (tabIndex
< data
->nStores
)
977 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
978 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
982 if (SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0) > 1)
983 warningID
= data
->stores
[tabIndex
].removePluralWarning
;
985 warningID
= data
->stores
[tabIndex
].removeWarning
;
987 pTitle
= data
->title
;
990 LoadStringW(hInstance
, IDS_CERT_MGR
, title
, ARRAY_SIZE(title
));
993 LoadStringW(hInstance
, warningID
, warning
, ARRAY_SIZE(warning
));
994 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
999 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1003 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1006 CertDeleteCertificateFromStore(cert
);
1008 } while (selection
>= 0);
1009 cert_mgr_clear_cert_selection(hwnd
);
1014 static void cert_mgr_do_export(HWND hwnd
)
1016 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1017 int selectionCount
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1019 if (selectionCount
== 1)
1021 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1026 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, selection
);
1030 CRYPTUI_WIZ_EXPORT_INFO info
;
1032 info
.dwSize
= sizeof(info
);
1033 info
.pwszExportFileName
= NULL
;
1034 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
1035 info
.u
.pCertContext
= cert
;
1037 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1041 else if (selectionCount
> 1)
1043 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1044 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1048 CRYPTUI_WIZ_EXPORT_INFO info
;
1051 info
.dwSize
= sizeof(info
);
1052 info
.pwszExportFileName
= NULL
;
1053 info
.dwSubjectChoice
=
1054 CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
;
1055 info
.u
.hCertStore
= store
;
1058 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1062 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1065 CertAddCertificateContextToStore(store
, cert
,
1066 CERT_STORE_ADD_ALWAYS
, NULL
);
1068 } while (selection
>= 0);
1069 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1070 CertCloseStore(store
, 0);
1075 static int cert_mgr_sort_by_text(HWND lv
, int col
, int index1
, int index2
)
1078 WCHAR buf1
[MAX_STRING_LEN
];
1079 WCHAR buf2
[MAX_STRING_LEN
];
1081 item
.cchTextMax
= ARRAY_SIZE(buf1
);
1082 item
.mask
= LVIF_TEXT
;
1083 item
.pszText
= buf1
;
1084 item
.iItem
= index1
;
1085 item
.iSubItem
= col
;
1086 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1087 item
.pszText
= buf2
;
1088 item
.iItem
= index2
;
1089 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1090 return strcmpW(buf1
, buf2
);
1093 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1095 return cert_mgr_sort_by_text((HWND
)lp
, 0, lp1
, lp2
);
1098 static int CALLBACK
cert_mgr_sort_by_issuer(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1100 return cert_mgr_sort_by_text((HWND
)lp
, 1, lp1
, lp2
);
1103 static int CALLBACK
cert_mgr_sort_by_date(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1105 PCCERT_CONTEXT cert1
= (PCCERT_CONTEXT
)lp1
;
1106 PCCERT_CONTEXT cert2
= (PCCERT_CONTEXT
)lp2
;
1107 return CompareFileTime(&cert1
->pCertInfo
->NotAfter
,
1108 &cert2
->pCertInfo
->NotAfter
);
1111 static int CALLBACK
cert_mgr_sort_by_friendly_name(LPARAM lp1
, LPARAM lp2
,
1114 return cert_mgr_sort_by_text((HWND
)lp
, 3, lp1
, lp2
);
1117 static LRESULT CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1120 struct CertMgrData
*data
;
1126 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
1127 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
1128 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
1130 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData
));
1133 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
1134 if (data
->imageList
)
1137 COLORREF backColor
= RGB(255, 0, 255);
1139 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
1140 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
1142 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
1143 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_SETIMAGELIST
,
1144 LVSIL_SMALL
, (LPARAM
)data
->imageList
);
1146 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
1147 data
->title
= pCryptUICertMgr
->pwszTitle
;
1149 initialize_purpose_selection(hwnd
);
1150 add_cert_columns(hwnd
);
1151 if (pCryptUICertMgr
->pwszTitle
)
1152 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1153 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
1154 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
, data
);
1155 show_store_certs(hwnd
, cert_mgr_index_to_store(tab
, 0));
1160 NMHDR
*hdr
= (NMHDR
*)lp
;
1165 cert_mgr_clear_cert_selection(hwnd
);
1167 case LVN_ITEMCHANGED
:
1169 NMITEMACTIVATE
*nm
= (NMITEMACTIVATE
*)lp
;
1170 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1171 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1173 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), numSelected
> 0);
1174 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), numSelected
> 0);
1175 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), numSelected
== 1);
1176 if (numSelected
== 1)
1177 cert_mgr_show_cert_usages(hwnd
, nm
->iItem
);
1179 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
1184 show_selected_cert(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
1188 NMLVKEYDOWN
*lvk
= (NMLVKEYDOWN
*)lp
;
1190 if (lvk
->wVKey
== VK_DELETE
)
1191 cert_mgr_do_remove(hwnd
);
1194 case LVN_COLUMNCLICK
:
1196 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
1197 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1199 /* FIXME: doesn't support swapping sort order between ascending
1202 switch (nmlv
->iSubItem
)
1205 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1206 (LPARAM
)cert_mgr_sort_by_subject
);
1209 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1210 (LPARAM
)cert_mgr_sort_by_issuer
);
1213 SendMessageW(lv
, LVM_SORTITEMS
, 0,
1214 (LPARAM
)cert_mgr_sort_by_date
);
1217 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1218 (LPARAM
)cert_mgr_sort_by_friendly_name
);
1229 case ((CBN_SELCHANGE
<< 16) | IDC_MGR_PURPOSE_SELECTION
):
1230 cert_mgr_clear_cert_selection(hwnd
);
1232 case IDC_MGR_IMPORT
:
1233 if (CryptUIWizImport(0, hwnd
, NULL
, NULL
,
1234 cert_mgr_current_store(hwnd
)))
1235 refresh_store_certs(hwnd
);
1237 case IDC_MGR_ADVANCED
:
1238 if (DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR_ADVANCED
),
1239 hwnd
, cert_mgr_advanced_dlg_proc
) == IDOK
)
1241 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
1243 LPWSTR curString
= NULL
;
1245 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
1248 len
= SendMessageW(cb
, CB_GETLBTEXTLEN
, index
, 0);
1249 curString
= HeapAlloc(GetProcessHeap(), 0,
1250 (len
+ 1) * sizeof(WCHAR
));
1251 SendMessageW(cb
, CB_GETLBTEXT
, index
, (LPARAM
)curString
);
1253 SendMessageW(cb
, CB_RESETCONTENT
, 0, 0);
1254 initialize_purpose_selection(hwnd
);
1257 index
= SendMessageW(cb
, CB_FINDSTRINGEXACT
, -1,
1260 SendMessageW(cb
, CB_SETCURSEL
, index
, 0);
1261 HeapFree(GetProcessHeap(), 0, curString
);
1263 refresh_store_certs(hwnd
);
1268 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1269 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1273 show_selected_cert(hwnd
, selection
);
1276 case IDC_MGR_EXPORT
:
1277 cert_mgr_do_export(hwnd
);
1279 case IDC_MGR_REMOVE
:
1280 cert_mgr_do_remove(hwnd
);
1283 free_certs(GetDlgItem(hwnd
, IDC_MGR_CERTS
));
1284 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1285 data
= (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1286 ImageList_Destroy(data
->imageList
);
1287 HeapFree(GetProcessHeap(), 0, data
);
1288 EndDialog(hwnd
, IDCANCEL
);
1296 /***********************************************************************
1297 * CryptUIDlgCertMgr (CRYPTUI.@)
1299 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
1301 TRACE("(%p)\n", pCryptUICertMgr
);
1303 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
1305 WARN("unexpected size %d\n", pCryptUICertMgr
->dwSize
);
1306 SetLastError(E_INVALIDARG
);
1309 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
1310 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
1314 /* FIXME: real names are unknown, functions are undocumented */
1315 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
1318 void *pvSystemStoreLocationPara
;
1319 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
1321 typedef struct _CRYPTUI_ENUM_DATA
1324 HCERTSTORE
*rghStore
;
1326 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
1327 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
1329 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
1332 /* Values for dwFlags */
1333 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
1335 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
1342 CRYPTUI_ENUM_DATA
*pEnumData
;
1343 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1345 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
1347 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
1354 CRYPTUI_ENUM_DATA
*pEnumData
;
1355 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1357 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
1371 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
1372 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
1375 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
1376 TVINSERTSTRUCTW tvis
;
1377 LPCWSTR localizedName
;
1380 tvis
.hParent
= NULL
;
1381 tvis
.hInsertAfter
= TVI_LAST
;
1382 tvis
.u
.item
.mask
= TVIF_TEXT
;
1383 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
1385 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(), 0,
1386 sizeof(struct StoreInfo
));
1390 storeInfo
->type
= SystemStore
;
1391 storeInfo
->u
.name
= HeapAlloc(GetProcessHeap(), 0,
1392 (strlenW(pvSystemStore
) + 1) * sizeof(WCHAR
));
1393 if (storeInfo
->u
.name
)
1395 tvis
.u
.item
.mask
|= TVIF_PARAM
;
1396 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1397 strcpyW(storeInfo
->u
.name
, pvSystemStore
);
1401 HeapFree(GetProcessHeap(), 0, storeInfo
);
1407 tvis
.u
.item
.pszText
= (LPWSTR
)localizedName
;
1410 tvis
.u
.item
.pszText
= (LPWSTR
)pvSystemStore
;
1411 /* FIXME: need a folder icon for the store too */
1413 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1417 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
1420 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1422 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
1423 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
1424 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
1425 hwnd
, enum_store_callback
);
1426 for (i
= 0; i
< pEnumData
->cStores
; i
++)
1430 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1431 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
1433 LPWSTR name
= HeapAlloc(GetProcessHeap(), 0, size
);
1437 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1438 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
1440 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(),
1441 0, sizeof(struct StoreInfo
));
1445 TVINSERTSTRUCTW tvis
;
1447 storeInfo
->type
= StoreHandle
;
1448 storeInfo
->u
.store
= pEnumData
->rghStore
[i
];
1449 tvis
.hParent
= NULL
;
1450 tvis
.hInsertAfter
= TVI_LAST
;
1451 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
1452 tvis
.u
.item
.pszText
= name
;
1453 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1454 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1457 HeapFree(GetProcessHeap(), 0, name
);
1463 static void free_store_info(HWND tree
)
1465 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
1472 memset(&item
, 0, sizeof(item
));
1473 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
1475 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1478 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1480 if (storeInfo
->type
== SystemStore
)
1481 HeapFree(GetProcessHeap(), 0, storeInfo
->u
.name
);
1482 HeapFree(GetProcessHeap(), 0, storeInfo
);
1484 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
1489 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
1491 WCHAR buf
[MAX_STRING_LEN
];
1495 memset(&item
, 0, sizeof(item
));
1496 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
1498 item
.cchTextMax
= ARRAY_SIZE(buf
);
1500 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1503 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1505 if (storeInfo
->type
== StoreHandle
)
1506 store
= storeInfo
->u
.store
;
1508 store
= CertOpenSystemStoreW(0, storeInfo
->u
.name
);
1512 /* It's implicitly a system store */
1513 store
= CertOpenSystemStoreW(0, buf
);
1518 struct SelectStoreInfo
1520 PCRYPTUI_SELECTSTORE_INFO_W info
;
1524 static LRESULT CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1527 struct SelectStoreInfo
*selectInfo
;
1534 selectInfo
= (struct SelectStoreInfo
*)lp
;
1535 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
1536 if (selectInfo
->info
->pwszTitle
)
1537 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1538 (LPARAM
)selectInfo
->info
->pwszTitle
);
1539 if (selectInfo
->info
->pwszText
)
1540 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
1541 (LPARAM
)selectInfo
->info
->pwszText
);
1542 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
1543 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
1544 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
1552 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1553 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
1554 TVM_GETNEXTITEM
, TVGN_CARET
, 0);
1556 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
1560 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
1562 if (selectInfo
->info
->pwszTitle
)
1563 pTitle
= selectInfo
->info
->pwszTitle
;
1566 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
, ARRAY_SIZE(title
));
1569 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
, ARRAY_SIZE(error
));
1570 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
1574 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
1576 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
1577 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
1578 selectInfo
->info
->pvArg
))
1580 selectInfo
->store
= store
;
1581 free_store_info(tree
);
1582 EndDialog(hwnd
, IDOK
);
1585 CertCloseStore(store
, 0);
1591 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
1592 EndDialog(hwnd
, IDCANCEL
);
1601 /***********************************************************************
1602 * CryptUIDlgSelectStoreW (CRYPTUI.@)
1604 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
1606 struct SelectStoreInfo selectInfo
= { info
, NULL
};
1608 TRACE("(%p)\n", info
);
1610 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
1612 WARN("unexpected size %d\n", info
->dwSize
);
1613 SetLastError(E_INVALIDARG
);
1616 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
1617 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
1618 return selectInfo
.store
;
1621 /***********************************************************************
1622 * CryptUIDlgSelectStoreA (CRYPTUI.@)
1624 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
1626 CRYPTUI_SELECTSTORE_INFO_W infoW
;
1630 TRACE("(%p)\n", info
);
1632 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
1634 WARN("unexpected size %d\n", info
->dwSize
);
1635 SetLastError(E_INVALIDARG
);
1638 memcpy(&infoW
, info
, sizeof(*info
));
1641 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
1642 infoW
.pwszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1643 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
1648 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
1649 infoW
.pwszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1650 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
1652 ret
= CryptUIDlgSelectStoreW(&infoW
);
1653 HeapFree(GetProcessHeap(), 0, infoW
.pwszText
);
1654 HeapFree(GetProcessHeap(), 0, infoW
.pwszTitle
);
1658 /***********************************************************************
1659 * CryptUIDlgViewCertificateA (CRYPTUI.@)
1661 BOOL WINAPI
CryptUIDlgViewCertificateA(
1662 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
1664 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
1665 LPWSTR title
= NULL
;
1668 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
1670 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
1671 if (pCertViewInfo
->szTitle
)
1673 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
1676 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1679 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
1681 viewInfo
.szTitle
= title
;
1689 if (pCertViewInfo
->cPropSheetPages
)
1691 FIXME("ignoring additional prop sheet pages\n");
1692 viewInfo
.cPropSheetPages
= 0;
1694 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
1695 HeapFree(GetProcessHeap(), 0, title
);
1700 struct ReadStringStruct
1707 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
1710 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
1711 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
1713 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
1715 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
1717 *pcb
= cch
* sizeof(WCHAR
);
1721 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
1723 struct ReadStringStruct string
;
1724 EDITSTREAM editstream
;
1726 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
1731 editstream
.dwCookie
= (DWORD_PTR
)&string
;
1732 editstream
.dwError
= 0;
1733 editstream
.pfnCallback
= read_text_callback
;
1734 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
1735 (LPARAM
)&editstream
);
1738 static void add_string_resource_to_control(HWND hwnd
, int id
)
1743 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1744 add_unformatted_text_to_control(hwnd
, str
, len
);
1747 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
1748 LONG len
, const PARAFORMAT2
*fmt
)
1750 add_unformatted_text_to_control(hwnd
, text
, len
);
1751 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
1754 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
1755 const PARAFORMAT2
*fmt
)
1760 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1761 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
1764 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
1770 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
1773 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1775 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
1780 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
1781 DWORD dwType
, DWORD dwFlags
)
1783 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
1787 /* Don't include NULL-terminator in output */
1788 DWORD len
= lstrlenW(name
);
1790 add_unformatted_text_to_control(hwnd
, name
, len
);
1791 HeapFree(GetProcessHeap(), 0, name
);
1795 static void add_icon_to_control(HWND hwnd
, int id
)
1798 IRichEditOle
*richEditOle
= NULL
;
1799 IOleObject
*object
= NULL
;
1801 LPOLECACHE oleCache
= NULL
;
1802 FORMATETC formatEtc
;
1804 IDataObject
*dataObject
= NULL
;
1805 HBITMAP bitmap
= NULL
;
1807 IOleClientSite
*clientSite
= NULL
;
1810 TRACE("(%p, %d)\n", hwnd
, id
);
1812 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
1815 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
1819 hr
= IOleObject_GetUserClassID(object
, &clsid
);
1822 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
1825 formatEtc
.cfFormat
= CF_BITMAP
;
1826 formatEtc
.ptd
= NULL
;
1827 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
1828 formatEtc
.lindex
= -1;
1829 formatEtc
.tymed
= TYMED_GDI
;
1830 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
1833 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
1834 (void**)&dataObject
);
1837 hr
= IRichEditOle_GetClientSite(richEditOle
, &clientSite
);
1840 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
1841 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
1844 stgm
.tymed
= TYMED_GDI
;
1845 stgm
.u
.hBitmap
= bitmap
;
1846 stgm
.pUnkForRelease
= NULL
;
1847 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
1851 reObject
.cbStruct
= sizeof(reObject
);
1852 reObject
.cp
= REO_CP_SELECTION
;
1853 reObject
.clsid
= clsid
;
1854 reObject
.poleobj
= object
;
1855 reObject
.pstg
= NULL
;
1856 reObject
.polesite
= clientSite
;
1857 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
1858 reObject
.dvaspect
= DVASPECT_CONTENT
;
1859 reObject
.dwFlags
= 0;
1860 reObject
.dwUser
= 0;
1862 IRichEditOle_InsertObject(richEditOle
, &reObject
);
1866 IOleClientSite_Release(clientSite
);
1868 IDataObject_Release(dataObject
);
1870 IOleCache_Release(oleCache
);
1872 IOleObject_Release(object
);
1874 IRichEditOle_Release(richEditOle
);
1877 #define MY_INDENT 200
1879 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
1882 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
1885 parFmt
.cbSize
= sizeof(parFmt
);
1886 parFmt
.dwMask
= PFM_STARTINDENT
;
1887 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1890 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
1891 lstrlenW(oidInfo
->pwszName
), &parFmt
);
1892 add_unformatted_text_to_control(hwnd
, &nl
, 1);
1902 /* The following list MUST be lexicographically sorted by OID */
1903 static struct OIDToString oidMap
[] = {
1904 /* 1.3.6.1.4.1.311.10.3.1 */
1905 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
1906 /* 1.3.6.1.4.1.311.10.3.4 */
1907 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
1908 /* 1.3.6.1.4.1.311.10.3.4.1 */
1909 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
1910 /* 1.3.6.1.4.1.311.10.3.5 */
1911 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
1912 /* 1.3.6.1.4.1.311.10.3.6 */
1913 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
1914 /* 1.3.6.1.4.1.311.10.3.7 */
1915 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
1916 /* 1.3.6.1.4.1.311.10.3.8 */
1917 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
1918 /* 1.3.6.1.4.1.311.10.3.9 */
1919 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
1920 /* 1.3.6.1.4.1.311.10.3.10 */
1921 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
1922 /* 1.3.6.1.4.1.311.10.3.11 */
1923 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
1924 /* 1.3.6.1.4.1.311.10.3.12 */
1925 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
1926 /* 1.3.6.1.4.1.311.10.3.13 */
1927 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
1928 /* 1.3.6.1.4.1.311.10.5.1 */
1929 { szOID_DRM
, IDS_PURPOSE_DRM
},
1930 /* 1.3.6.1.4.1.311.10.6.1 */
1931 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
1932 /* 1.3.6.1.4.1.311.10.6.2 */
1933 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
1934 /* 1.3.6.1.4.1.311.20.2.1 */
1935 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
1936 /* 1.3.6.1.4.1.311.20.2.2 */
1937 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
1938 /* 1.3.6.1.4.1.311.21.5 */
1939 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
1940 /* 1.3.6.1.4.1.311.21.6 */
1941 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
1942 /* 1.3.6.1.4.1.311.21.19 */
1943 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
1944 /* 1.3.6.1.5.5.7.3.1 */
1945 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
1946 /* 1.3.6.1.5.5.7.3.2 */
1947 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
1948 /* 1.3.6.1.5.5.7.3.3 */
1949 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
1950 /* 1.3.6.1.5.5.7.3.4 */
1951 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
1952 /* 1.3.6.1.5.5.7.3.5 */
1953 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
1954 /* 1.3.6.1.5.5.7.3.6 */
1955 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
1956 /* 1.3.6.1.5.5.7.3.7 */
1957 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
1958 /* 1.3.6.1.5.5.7.3.8 */
1959 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
1962 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
1964 int indexHigh
= ARRAY_SIZE(oidMap
) - 1, indexLow
= 0;
1966 while (indexLow
<= indexHigh
)
1968 int cmp
, i
= (indexLow
+ indexHigh
) / 2;
1969 if (!(cmp
= strcmp(oid
, oidMap
[i
].oid
)))
1979 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
1981 struct OIDToString
*entry
;
1985 parFmt
.cbSize
= sizeof(parFmt
);
1986 parFmt
.dwMask
= PFM_STARTINDENT
;
1987 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1988 if ((entry
= findSupportedOID(oid
)))
1990 WCHAR
*str
, *linebreak
, *ptr
;
1991 BOOL multiline
= FALSE
;
1994 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
1997 if ((linebreak
= memchrW(ptr
, '\n', len
)))
1999 WCHAR copy
[MAX_STRING_LEN
];
2002 /* The source string contains a newline, which the richedit
2003 * control won't find since it's interpreted as a paragraph
2004 * break. Therefore copy up to the newline. lstrcpynW always
2005 * NULL-terminates, so pass one more than the length of the
2006 * source line so the copy includes the entire line and the
2009 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
2010 add_text_with_paraformat_to_control(text
, copy
,
2011 linebreak
- ptr
, &parFmt
);
2012 ptr
= linebreak
+ 1;
2013 add_unformatted_text_to_control(text
, &nl
, 1);
2015 else if (multiline
&& *ptr
)
2017 /* Add the last line */
2018 add_text_with_paraformat_to_control(text
, ptr
,
2019 len
- (ptr
- str
), &parFmt
);
2020 add_unformatted_text_to_control(text
, &nl
, 1);
2022 } while (linebreak
);
2025 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
2026 add_unformatted_text_to_control(text
, &nl
, 1);
2031 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
2032 (strlen(oid
) + 1) * sizeof(WCHAR
));
2039 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
2042 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
2044 add_unformatted_text_to_control(text
, &nl
, 1);
2045 HeapFree(GetProcessHeap(), 0, oidW
);
2050 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
2051 BOOL
*anyUsageAdded
)
2053 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
2055 CHARFORMATW charFmt
;
2056 PCERT_EXTENSION policyExt
;
2057 if (!*anyUsageAdded
)
2061 parFmt
.cbSize
= sizeof(parFmt
);
2062 parFmt
.dwMask
= PFM_STARTINDENT
;
2063 parFmt
.dxStartIndent
= MY_INDENT
;
2064 add_string_resource_with_paraformat_to_control(text
,
2065 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2066 add_unformatted_text_to_control(text
, &nl
, 1);
2067 *anyUsageAdded
= TRUE
;
2069 memset(&charFmt
, 0, sizeof(charFmt
));
2070 charFmt
.cbSize
= sizeof(charFmt
);
2071 charFmt
.dwMask
= CFM_BOLD
;
2072 charFmt
.dwEffects
= 0;
2073 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2074 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
2075 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
2077 CERT_POLICIES_INFO
*policies
;
2080 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
2081 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2082 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2086 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
2090 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2091 add_local_oid_text_to_control(text
,
2092 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2093 pszPolicyQualifierId
);
2095 LocalFree(policies
);
2099 add_oid_text_to_control(text
, any_app_policy
);
2102 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
2103 BOOL
*anyUsageAdded
)
2107 BOOL badUsages
= FALSE
;
2109 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
2111 CHARFORMATW charFmt
;
2112 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
2113 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
2117 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
2121 if (!*anyUsageAdded
)
2125 parFmt
.cbSize
= sizeof(parFmt
);
2126 parFmt
.dwMask
= PFM_STARTINDENT
;
2127 parFmt
.dxStartIndent
= MY_INDENT
;
2128 add_string_resource_with_paraformat_to_control(text
,
2129 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2130 add_unformatted_text_to_control(text
, &nl
, 1);
2131 *anyUsageAdded
= TRUE
;
2133 memset(&charFmt
, 0, sizeof(charFmt
));
2134 charFmt
.cbSize
= sizeof(charFmt
);
2135 charFmt
.dwMask
= CFM_BOLD
;
2136 charFmt
.dwEffects
= 0;
2137 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
2139 if (!usage
->cUsageIdentifier
)
2140 add_oid_text_to_control(text
, any_cert_policy
);
2142 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2143 add_local_oid_text_to_control(text
,
2144 usage
->rgpszUsageIdentifier
[i
]);
2148 HeapFree(GetProcessHeap(), 0, usage
);
2158 static void set_policy_text(HWND text
,
2159 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2161 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
2162 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
2164 if (pCertViewInfo
->cPurposes
)
2168 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
2170 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
2171 includeCertUsages
= TRUE
;
2172 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
2173 szOID_ANY_APPLICATION_POLICY
))
2174 includeAppUsages
= TRUE
;
2180 includeAppUsages
= includeCertUsages
= TRUE
;
2181 if (includeAppUsages
)
2182 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
2183 if (includeCertUsages
)
2184 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
2190 parFmt
.cbSize
= sizeof(parFmt
);
2191 parFmt
.dwMask
= PFM_STARTINDENT
;
2192 parFmt
.dxStartIndent
= MY_INDENT
;
2193 add_string_resource_with_paraformat_to_control(text
,
2194 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
2198 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
2201 CRYPT_OBJID_BLOB
*ret
= NULL
;
2204 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
2208 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2209 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2210 pszPolicyQualifierId
, policyOid
))
2211 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2217 static WCHAR
*get_cps_str_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2219 LPWSTR qualifierStr
= NULL
;
2220 CERT_NAME_VALUE
*qualifierValue
;
2223 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
2224 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2225 &qualifierValue
, &size
))
2227 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
2228 &qualifierValue
->Value
, NULL
, 0);
2229 qualifierStr
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
2231 CertRDNValueToStrW(qualifierValue
->dwValueType
,
2232 &qualifierValue
->Value
, qualifierStr
, size
);
2233 LocalFree(qualifierValue
);
2235 return qualifierStr
;
2238 static WCHAR
*get_user_notice_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2241 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
2244 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
2245 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
2246 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2247 &qualifierValue
, &size
))
2249 str
= HeapAlloc(GetProcessHeap(), 0,
2250 (strlenW(qualifierValue
->pszDisplayText
) + 1) * sizeof(WCHAR
));
2252 strcpyW(str
, qualifierValue
->pszDisplayText
);
2253 LocalFree(qualifierValue
);
2258 struct IssuerStatement
2264 static void set_issuer_statement(HWND hwnd
,
2265 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2267 PCERT_EXTENSION policyExt
;
2269 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
2270 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
2271 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
2272 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
2274 CERT_POLICIES_INFO
*policies
;
2277 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
2278 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2279 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2281 CRYPT_OBJID_BLOB
*qualifier
;
2282 LPWSTR cps
= NULL
, userNotice
= NULL
;
2284 if ((qualifier
= find_policy_qualifier(policies
,
2285 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
2286 cps
= get_cps_str_from_qualifier(qualifier
);
2287 if ((qualifier
= find_policy_qualifier(policies
,
2288 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
2289 userNotice
= get_user_notice_from_qualifier(qualifier
);
2290 if (cps
|| userNotice
)
2292 struct IssuerStatement
*issuerStatement
=
2293 HeapAlloc(GetProcessHeap(), 0, sizeof(struct IssuerStatement
));
2295 if (issuerStatement
)
2297 issuerStatement
->cps
= cps
;
2298 issuerStatement
->userNotice
= userNotice
;
2299 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
2300 SetWindowLongPtrW(hwnd
, DWLP_USER
,
2301 (ULONG_PTR
)issuerStatement
);
2304 LocalFree(policies
);
2309 static void set_cert_info(HWND hwnd
,
2310 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2312 CHARFORMATW charFmt
;
2314 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
2315 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
2316 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2317 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
2318 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
2319 pCertViewInfo
->idxCounterSigner
);
2320 CRYPT_PROVIDER_CERT
*root
=
2321 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
2323 if (!provSigner
->pChainContext
||
2324 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2325 CERT_TRUST_IS_PARTIAL_CHAIN
))
2326 add_icon_to_control(icon
, IDB_CERT_WARNING
);
2327 else if (!root
->fTrustedRoot
)
2328 add_icon_to_control(icon
, IDB_CERT_ERROR
);
2330 add_icon_to_control(icon
, IDB_CERT
);
2332 memset(&charFmt
, 0, sizeof(charFmt
));
2333 charFmt
.cbSize
= sizeof(charFmt
);
2334 charFmt
.dwMask
= CFM_BOLD
;
2335 charFmt
.dwEffects
= CFE_BOLD
;
2336 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2337 /* FIXME: vertically center text */
2338 parFmt
.cbSize
= sizeof(parFmt
);
2339 parFmt
.dwMask
= PFM_STARTINDENT
;
2340 parFmt
.dxStartIndent
= MY_INDENT
;
2341 add_string_resource_with_paraformat_to_control(text
,
2342 IDS_CERTIFICATEINFORMATION
, &parFmt
);
2344 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
2345 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2346 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
2347 add_string_resource_with_paraformat_to_control(text
,
2348 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
2349 else if (!provSigner
->pChainContext
||
2350 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2351 CERT_TRUST_IS_PARTIAL_CHAIN
))
2352 add_string_resource_with_paraformat_to_control(text
,
2353 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
2354 else if (!root
->fTrustedRoot
)
2356 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
2357 add_string_resource_with_paraformat_to_control(text
,
2358 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
2360 add_string_resource_with_paraformat_to_control(text
,
2361 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
2365 set_policy_text(text
, pCertViewInfo
);
2366 set_issuer_statement(hwnd
, pCertViewInfo
);
2370 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
2371 DWORD nameFlags
, int heading
)
2374 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2375 CHARFORMATW charFmt
;
2378 memset(&charFmt
, 0, sizeof(charFmt
));
2379 charFmt
.cbSize
= sizeof(charFmt
);
2380 charFmt
.dwMask
= CFM_BOLD
;
2381 charFmt
.dwEffects
= CFE_BOLD
;
2382 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2383 parFmt
.cbSize
= sizeof(parFmt
);
2384 parFmt
.dwMask
= PFM_STARTINDENT
;
2385 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2386 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
2387 charFmt
.dwEffects
= 0;
2388 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2389 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2391 add_unformatted_text_to_control(text
, &nl
, 1);
2392 add_unformatted_text_to_control(text
, &nl
, 1);
2393 add_unformatted_text_to_control(text
, &nl
, 1);
2397 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
2399 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
2403 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
2404 FileTimeToSystemTime(fileTime
, &sysTime
);
2405 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
, ARRAY_SIZE(date
));
2406 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
2409 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
2412 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2413 CHARFORMATW charFmt
;
2416 memset(&charFmt
, 0, sizeof(charFmt
));
2417 charFmt
.cbSize
= sizeof(charFmt
);
2418 charFmt
.dwMask
= CFM_BOLD
;
2419 charFmt
.dwEffects
= CFE_BOLD
;
2420 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2421 parFmt
.cbSize
= sizeof(parFmt
);
2422 parFmt
.dwMask
= PFM_STARTINDENT
;
2423 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2424 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
2426 charFmt
.dwEffects
= 0;
2427 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2428 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
2429 charFmt
.dwEffects
= CFE_BOLD
;
2430 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2431 add_string_resource_to_control(text
, IDS_VALID_TO
);
2432 charFmt
.dwEffects
= 0;
2433 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2434 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
2435 add_unformatted_text_to_control(text
, &nl
, 1);
2438 static void set_general_info(HWND hwnd
,
2439 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2441 set_cert_info(hwnd
, pCertViewInfo
);
2442 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
2443 IDS_SUBJECT_HEADING
);
2444 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
2445 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
2446 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
2449 static LRESULT CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2454 struct IssuerStatement
*issuerStatement
;
2459 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
2460 issuerStatement
= (struct IssuerStatement
*)lp
;
2461 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
2462 strlenW(issuerStatement
->userNotice
));
2463 if (issuerStatement
->cps
)
2464 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
2466 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
2472 EndDialog(hwnd
, IDOK
);
2477 IBindCtx
*bctx
= NULL
;
2480 CreateBindCtx(0, &bctx
);
2481 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2482 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
2483 HLNF_OPENINNEWWINDOW
, 0);
2484 IBindCtx_Release(bctx
);
2492 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
2494 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
2495 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
2498 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2501 PROPSHEETPAGEW
*page
;
2502 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2504 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2509 page
= (PROPSHEETPAGEW
*)lp
;
2510 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
2511 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
2512 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
2513 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
2514 set_general_info(hwnd
, pCertViewInfo
);
2519 case IDC_ADDTOSTORE
:
2520 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
2522 case IDC_ISSUERSTATEMENT
:
2524 struct IssuerStatement
*issuerStatement
=
2525 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2527 if (issuerStatement
)
2529 if (issuerStatement
->userNotice
)
2530 show_user_notice(hwnd
, issuerStatement
);
2531 else if (issuerStatement
->cps
)
2533 IBindCtx
*bctx
= NULL
;
2535 CreateBindCtx(0, &bctx
);
2536 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
2537 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
2538 IBindCtx_Release(bctx
);
2549 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
2550 PROPSHEETPAGEW
*page
)
2552 struct IssuerStatement
*issuerStatement
;
2558 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2559 if (issuerStatement
)
2561 HeapFree(GetProcessHeap(), 0, issuerStatement
->cps
);
2562 HeapFree(GetProcessHeap(), 0, issuerStatement
->userNotice
);
2563 HeapFree(GetProcessHeap(), 0, issuerStatement
);
2570 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2571 PROPSHEETPAGEW
*page
)
2573 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2574 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2575 page
->dwFlags
= PSP_USECALLBACK
;
2576 page
->pfnCallback
= general_callback_proc
;
2577 page
->hInstance
= hInstance
;
2578 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
2579 page
->pfnDlgProc
= general_dlg_proc
;
2580 page
->lParam
= (LPARAM
)pCertViewInfo
;
2583 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
2585 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
2587 static const WCHAR fmt
[] = { 'V','%','d',0 };
2588 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, 12 * sizeof(WCHAR
));
2591 sprintfW(buf
, fmt
, cert
->pCertInfo
->dwVersion
);
2595 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
2597 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, (cb
* 3 + 1) * sizeof(WCHAR
));
2601 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2605 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
2606 sprintfW(ptr
, fmt
, ((BYTE
*)pb
)[i
]);
2611 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
2613 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
2614 cert
->pCertInfo
->SerialNumber
.cbData
);
2617 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
2619 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2620 CERT_NAME_ISSUER_FLAG
);
2623 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
2626 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
2627 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, NULL
, 0);
2631 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2633 CertNameToStrW(X509_ASN_ENCODING
, name
,
2634 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, str
, len
);
2639 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
2641 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
2644 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
2646 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2649 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
2651 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
2654 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
2656 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
2661 /* FIXME: format isn't quite right, want time too */
2662 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
2663 FileTimeToSystemTime(fileTime
, &sysTime
);
2664 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
2667 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2669 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
2675 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
2677 return format_long_date(&cert
->pCertInfo
->NotBefore
);
2680 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
2682 return format_long_date(&cert
->pCertInfo
->NotAfter
);
2685 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
2687 PCCRYPT_OID_INFO oidInfo
;
2690 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2691 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
2694 WCHAR fmt
[MAX_STRING_LEN
];
2696 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
, ARRAY_SIZE(fmt
)))
2700 /* Allocate the output buffer. Use the number of bytes in the
2701 * public key as a conservative (high) estimate for the number of
2702 * digits in its output.
2703 * The output is of the form (in English)
2704 * "<public key algorithm> (<public key bit length> bits)".
2705 * Ordinarily having two positional parameters in a string is not a
2706 * good idea, but as this isn't a sentence fragment, it shouldn't
2707 * be word-order dependent.
2709 len
= strlenW(fmt
) + strlenW(oidInfo
->pwszName
) +
2710 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8;
2711 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(*buf
));
2715 args
[0] = (DWORD_PTR
)oidInfo
->pwszName
;
2716 args
[1] = CertGetPublicKeyLength(X509_ASN_ENCODING
,
2717 &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2718 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
2719 fmt
, 0, 0, buf
, len
, (__ms_va_list
*)args
);
2726 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
2728 return format_hex_string(
2729 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
2730 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
2733 struct field_value_data
;
2736 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2737 BOOL
*pfPropertiesChanged
;
2739 struct field_value_data
*fields
;
2742 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
2744 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
2746 struct field_value_data
2748 create_detailed_value_func create
;
2749 LPWSTR detailed_value
;
2753 static void add_field_value_data(struct detail_data
*data
,
2754 create_detailed_value_func create
, void *param
)
2757 data
->fields
= HeapReAlloc(GetProcessHeap(), 0, data
->fields
,
2758 (data
->cFields
+ 1) * sizeof(struct field_value_data
));
2760 data
->fields
= HeapAlloc(GetProcessHeap(), 0,
2761 sizeof(struct field_value_data
));
2764 data
->fields
[data
->cFields
].create
= create
;
2765 data
->fields
[data
->cFields
].detailed_value
= NULL
;
2766 data
->fields
[data
->cFields
].param
= param
;
2771 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2772 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2775 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2777 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
2780 item
.pszText
= field
;
2781 item
.lParam
= (LPARAM
)data
;
2782 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2785 item
.pszText
= value
;
2787 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
2789 add_field_value_data(data
, create
, param
);
2792 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2793 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2795 WCHAR buf
[MAX_STRING_LEN
];
2797 LoadStringW(hInstance
, id
, buf
, ARRAY_SIZE(buf
));
2798 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
2804 field_format_func format
;
2805 create_detailed_value_func create_detailed_value
;
2808 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
2809 const struct v1_field
*field
)
2811 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
2815 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
2816 field
->create_detailed_value
, NULL
);
2817 HeapFree(GetProcessHeap(), 0, val
);
2821 static const struct v1_field v1_fields
[] = {
2822 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
2823 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
2824 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
2825 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
2826 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
2827 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
2828 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
2829 field_format_detailed_public_key
}
2832 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
2835 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2837 /* The last item in v1_fields is the public key, which is not in the loop
2838 * because it's a special case.
2840 for (i
= 0; i
< ARRAY_SIZE(v1_fields
) - 1; i
++)
2841 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2842 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
2843 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2846 static WCHAR
*crypt_format_extension(const CERT_EXTENSION
*ext
, DWORD formatStrType
)
2851 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2852 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
2854 str
= HeapAlloc(GetProcessHeap(), 0, size
);
2855 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2856 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
2861 static WCHAR
*field_format_extension_hex_with_ascii(const CERT_EXTENSION
*ext
)
2865 if (ext
->Value
.cbData
)
2867 /* The output is formatted as:
2868 * <hex bytes> <ascii bytes>\n
2869 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
2870 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
2871 * the byte is not printable.
2872 * So, for example, the extension value consisting of the following
2874 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
2875 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
2877 * 30 14 31 12 30 10 06 03 0.1.0...
2878 * 55 04 03 13 09 4a 75 61 U....Jua
2879 * 6e 20 4c 61 6e 67 n Lang
2880 * The allocation size therefore requires:
2881 * - 4 characters per character in an 8-byte line
2882 * (2 for the hex format, one for the space, one for the ASCII value)
2883 * - 3 more characters per 8-byte line (two spaces and a newline)
2884 * - 1 character for the terminating nul
2885 * FIXME: should use a fixed-width font for this
2887 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
2889 str
= HeapAlloc(GetProcessHeap(), 0,
2890 (lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
2893 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2897 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
2899 /* Output as hex bytes first */
2900 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
2901 sprintfW(ptr
, fmt
, ext
->Value
.pbData
[j
]);
2902 /* Pad the hex output with spaces for alignment */
2903 if (j
== ext
->Value
.cbData
&& j
% 8)
2905 static const WCHAR pad
[] = { ' ',' ',' ' };
2907 for (; j
% 8; j
++, ptr
+= ARRAY_SIZE(pad
))
2908 memcpy(ptr
, pad
, sizeof(pad
));
2910 /* The last sprintfW included a space, so just insert one
2911 * more space between the hex bytes and the ASCII output
2914 /* Output as ASCII bytes */
2915 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
2917 if (isprintW(ext
->Value
.pbData
[j
]) &&
2918 !isspaceW(ext
->Value
.pbData
[j
]))
2919 *ptr
= ext
->Value
.pbData
[j
];
2931 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
2933 PCERT_EXTENSION ext
= param
;
2934 LPWSTR str
= crypt_format_extension(ext
,
2935 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
2938 str
= field_format_extension_hex_with_ascii(ext
);
2942 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
2943 PCERT_EXTENSION ext
)
2945 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2947 LPWSTR val
= crypt_format_extension(ext
, 0);
2950 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
2951 val
, field_format_detailed_extension
, ext
);
2954 DWORD len
= strlen(ext
->pszObjId
);
2955 LPWSTR oidW
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
2961 for (i
= 0; i
<= len
; i
++)
2962 oidW
[i
] = ext
->pszObjId
[i
];
2963 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
2964 field_format_detailed_extension
, ext
);
2965 HeapFree(GetProcessHeap(), 0, oidW
);
2968 HeapFree(GetProcessHeap(), 0, val
);
2971 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
2974 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2976 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2977 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
2980 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
2983 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2985 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2986 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
2987 add_cert_extension_detail(hwnd
, data
,
2988 &cert
->pCertInfo
->rgExtension
[i
]);
2991 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
2993 struct prop_id_to_string_id
2997 BOOL prop_is_string
;
2998 prop_to_value_func prop_to_value
;
3001 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
3005 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
3006 ext
.fCritical
= FALSE
;
3007 ext
.Value
.pbData
= pb
;
3008 ext
.Value
.cbData
= cb
;
3009 return crypt_format_extension(&ext
, 0);
3012 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
3013 * disabled for read-only certificates, but native doesn't appear to do that.
3015 static const struct prop_id_to_string_id prop_id_map
[] = {
3016 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
3017 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
3018 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
3019 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
3020 format_enhanced_key_usage_value
},
3023 static void add_properties(HWND hwnd
, struct detail_data
*data
)
3026 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
3028 for (i
= 0; i
< ARRAY_SIZE(prop_id_map
); i
++)
3032 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
3038 /* FIXME: MS adds a separate value for the signature hash
3041 pb
= HeapAlloc(GetProcessHeap(), 0, cb
);
3044 if (CertGetCertificateContextProperty(cert
,
3045 prop_id_map
[i
].prop
, pb
, &cb
))
3047 if (prop_id_map
[i
].prop_is_string
)
3050 /* Don't double-free pb */
3054 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
3056 HeapFree(GetProcessHeap(), 0, pb
);
3058 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
3064 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
3066 add_v1_fields(hwnd
, data
);
3067 add_all_extensions(hwnd
, data
);
3068 add_properties(hwnd
, data
);
3071 struct selection_list_item
3074 add_fields_func add
;
3077 static const struct selection_list_item listItems
[] = {
3078 { IDS_FIELDS_ALL
, add_all_fields
},
3079 { IDS_FIELDS_V1
, add_v1_fields
},
3080 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
3081 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
3082 { IDS_FIELDS_PROPERTIES
, add_properties
},
3085 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
3087 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3088 WCHAR buf
[MAX_STRING_LEN
];
3091 for (i
= 0; i
< ARRAY_SIZE(listItems
); i
++)
3095 LoadStringW(hInstance
, listItems
[i
].id
, buf
, ARRAY_SIZE(buf
));
3096 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
3097 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
3099 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
3102 static void create_listview_columns(HWND hwnd
)
3104 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3106 WCHAR buf
[MAX_STRING_LEN
];
3109 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
3110 GetWindowRect(lv
, &rc
);
3111 LoadStringW(hInstance
, IDS_FIELD
, buf
, ARRAY_SIZE(buf
));
3112 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
3113 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
3114 column
.pszText
= buf
;
3115 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3116 LoadStringW(hInstance
, IDS_VALUE
, buf
, ARRAY_SIZE(buf
));
3117 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
3120 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
3122 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3124 if (sel
>= 0 && sel
< ARRAY_SIZE(listItems
))
3126 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
3127 listItems
[sel
].add(list
, data
);
3131 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
3133 create_show_list(hwnd
, data
);
3134 create_listview_columns(hwnd
);
3135 set_fields_selection(hwnd
, data
, 0);
3138 static void add_purpose(HWND hwnd
, LPCSTR oid
)
3140 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3141 PCRYPT_OID_INFO info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3142 sizeof(CRYPT_OID_INFO
));
3146 char *oidCopy
= HeapAlloc(GetProcessHeap(), 0, strlen(oid
) + 1);
3152 strcpy(oidCopy
, oid
);
3153 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
3154 info
->pszOID
= oidCopy
;
3155 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
3156 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
3157 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3158 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3160 item
.lParam
= (LPARAM
)info
;
3161 item
.pszText
= oidCopy
;
3162 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3165 HeapFree(GetProcessHeap(), 0, info
);
3169 static BOOL
is_valid_oid(LPCSTR oid
)
3173 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
3175 else if (oid
[1] != '.')
3182 BOOL expectNum
= TRUE
;
3184 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
3190 else if (*(ptr
+ 1) == '.')
3197 else if (!(*(ptr
+ 1)))
3207 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
3209 return find_oid_in_list(GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
), oid
)
3213 #define MAX_PURPOSE 255
3215 static LRESULT CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
3216 WPARAM wp
, LPARAM lp
)
3219 char buf
[MAX_PURPOSE
+ 1];
3224 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
3226 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
3227 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
3233 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
3235 /* Show/hide scroll bar on description depending on how much
3238 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
3239 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3241 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3248 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
, ARRAY_SIZE(buf
),
3252 /* An empty purpose is the same as cancelling */
3253 EndDialog(hwnd
, IDCANCEL
);
3256 else if (!is_valid_oid(buf
))
3258 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3260 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
, ARRAY_SIZE(error
));
3261 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
, ARRAY_SIZE(title
));
3262 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
3264 else if (is_oid_in_list(
3265 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
3267 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3269 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
, error
,
3271 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
, ARRAY_SIZE(title
));
3272 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
3276 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3278 add_purpose(parent
, buf
);
3279 EndDialog(hwnd
, wp
);
3284 EndDialog(hwnd
, wp
);
3295 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
3300 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
3302 name
= HeapAlloc(GetProcessHeap(), 0, cb
);
3305 if (!CertGetCertificateContextProperty(cert
, prop
, name
, &cb
))
3307 HeapFree(GetProcessHeap(), 0, name
);
3315 static void redraw_states(HWND list
, BOOL enabled
)
3317 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
3319 for (i
= 0; i
< items
; i
++)
3321 BOOL change
= FALSE
;
3324 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
3325 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
3326 * to be a handy macro for it.
3331 if (state
== CheckBitmapIndexDisabledChecked
)
3333 state
= CheckBitmapIndexChecked
;
3336 if (state
== CheckBitmapIndexDisabledUnchecked
)
3338 state
= CheckBitmapIndexUnchecked
;
3344 if (state
== CheckBitmapIndexChecked
)
3346 state
= CheckBitmapIndexDisabledChecked
;
3349 if (state
== CheckBitmapIndexUnchecked
)
3351 state
= CheckBitmapIndexDisabledUnchecked
;
3359 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
3360 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3361 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
3367 PurposeEnableAll
= 0,
3369 PurposeEnableSelected
3372 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
3374 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3378 case PurposeEnableAll
:
3379 case PurposeDisableAll
:
3380 EnableWindow(lv
, FALSE
);
3381 redraw_states(lv
, FALSE
);
3382 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
3384 case PurposeEnableSelected
:
3385 EnableWindow(lv
, TRUE
);
3386 redraw_states(lv
, TRUE
);
3387 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
3391 struct edit_cert_data
3393 PCCERT_CONTEXT cert
;
3394 BOOL
*pfPropertiesChanged
;
3395 HIMAGELIST imageList
;
3398 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
3400 PCCERT_CONTEXT cert
= data
->cert
;
3401 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3402 PCERT_ENHKEY_USAGE usage
;
3406 PurposeSelection purposeSelection
= PurposeEnableAll
;
3408 GetWindowRect(lv
, &rc
);
3409 column
.mask
= LVCF_WIDTH
;
3410 column
.cx
= rc
.right
- rc
.left
;
3411 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3412 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
3414 /* Get enhanced key usage. Have to check for a property and an extension
3415 * separately, because CertGetEnhancedKeyUsage will succeed and return an
3416 * empty usage if neither is set. Unfortunately an empty usage implies
3417 * no usage is allowed, so we have to distinguish between the two cases.
3419 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
3422 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3423 if (!CertGetEnhancedKeyUsage(cert
,
3424 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3426 HeapFree(GetProcessHeap(), 0, usage
);
3429 else if (usage
->cUsageIdentifier
)
3430 purposeSelection
= PurposeEnableSelected
;
3432 purposeSelection
= PurposeDisableAll
;
3434 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
3437 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3438 if (!CertGetEnhancedKeyUsage(cert
,
3439 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3441 HeapFree(GetProcessHeap(), 0, usage
);
3444 else if (usage
->cUsageIdentifier
)
3445 purposeSelection
= PurposeEnableAll
;
3447 purposeSelection
= PurposeDisableAll
;
3451 purposeSelection
= PurposeEnableAll
;
3458 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
3460 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
3461 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
3464 add_known_usage(lv
, info
, CheckBitmapIndexDisabledChecked
);
3466 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
3468 HeapFree(GetProcessHeap(), 0, usage
);
3471 add_known_usages_to_list(lv
, CheckBitmapIndexDisabledChecked
);
3472 select_purposes(hwnd
, purposeSelection
);
3473 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
3477 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
3479 PCCERT_CONTEXT cert
= data
->cert
;
3482 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
3484 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
3486 HeapFree(GetProcessHeap(), 0, str
);
3488 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
3490 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
3492 HeapFree(GetProcessHeap(), 0, str
);
3494 show_cert_usages(hwnd
, data
);
3497 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
3502 CRYPT_DATA_BLOB blob
;
3504 blob
.pbData
= (BYTE
*)str
;
3505 blob
.cbData
= (strlenW(str
) + 1) * sizeof(WCHAR
);
3506 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
3509 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
3512 #define WM_REFRESH_VIEW WM_USER + 0
3514 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
3516 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
3517 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
3521 #define MAX_FRIENDLY_NAME 40
3522 #define MAX_DESCRIPTION 255
3524 static void apply_general_changes(HWND hwnd
)
3526 WCHAR buf
[MAX_DESCRIPTION
+ 1];
3527 struct edit_cert_data
*data
=
3528 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3530 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
3531 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
3532 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
3533 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
3534 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
3536 /* Setting a NULL usage removes the enhanced key usage property. */
3537 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
3539 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
3541 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3543 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3545 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
3547 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3548 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3549 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
3552 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3554 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3555 for (i
= 0; i
< purposes
; i
++)
3558 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
3560 int state
= item
.state
>> 12;
3562 if (state
== CheckBitmapIndexChecked
)
3564 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
3566 if (usage
.cUsageIdentifier
)
3567 usage
.rgpszUsageIdentifier
=
3568 HeapReAlloc(GetProcessHeap(), 0,
3569 usage
.rgpszUsageIdentifier
,
3570 (usage
.cUsageIdentifier
+ 1) * sizeof(LPSTR
));
3572 usage
.rgpszUsageIdentifier
=
3573 HeapAlloc(GetProcessHeap(), 0, sizeof(LPSTR
));
3574 if (usage
.rgpszUsageIdentifier
)
3575 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
3576 (LPSTR
)info
->pszOID
;
3580 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3581 HeapFree(GetProcessHeap(), 0, usage
.rgpszUsageIdentifier
);
3583 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
3584 if (data
->pfPropertiesChanged
)
3585 *data
->pfPropertiesChanged
= TRUE
;
3588 static LRESULT CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
3589 WPARAM wp
, LPARAM lp
)
3591 PROPSHEETPAGEW
*page
;
3593 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3599 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3600 struct detail_data
*detailData
;
3601 struct edit_cert_data
*editData
;
3603 page
= (PROPSHEETPAGEW
*)lp
;
3604 detailData
= (struct detail_data
*)page
->lParam
;
3605 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
3606 MAX_FRIENDLY_NAME
, 0);
3607 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
3608 ShowScrollBar(description
, SB_VERT
, FALSE
);
3609 editData
= HeapAlloc(GetProcessHeap(), 0,
3610 sizeof(struct edit_cert_data
));
3613 editData
->imageList
= ImageList_Create(16, 16,
3614 ILC_COLOR4
| ILC_MASK
, 4, 0);
3615 if (editData
->imageList
)
3618 COLORREF backColor
= RGB(255, 0, 255);
3620 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
3621 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
3623 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
3625 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
3626 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
3627 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
3628 set_general_cert_properties(hwnd
, editData
);
3634 NMHDR
*hdr
= (NMHDR
*)lp
;
3640 nm
= (NMITEMACTIVATE
*)lp
;
3641 toggle_usage(hwnd
, nm
->iItem
);
3642 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3645 apply_general_changes(hwnd
);
3654 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3655 if (LOWORD(wp
) == IDC_DESCRIPTION
)
3657 /* Show/hide scroll bar on description depending on how much
3660 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3661 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3663 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3669 case IDC_ADD_PURPOSE
:
3670 if (DialogBoxParamW(hInstance
,
3671 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
3672 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
3673 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3675 case IDC_ENABLE_ALL_PURPOSES
:
3676 case IDC_DISABLE_ALL_PURPOSES
:
3677 case IDC_ENABLE_SELECTED_PURPOSES
:
3678 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3679 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
3689 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
3690 PROPSHEETPAGEW
*page
)
3694 struct edit_cert_data
*data
;
3699 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3700 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3701 for (i
= 0; i
< cItem
; i
++)
3705 item
.mask
= LVIF_PARAM
;
3708 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
3710 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
3712 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
3714 HeapFree(GetProcessHeap(), 0, (LPSTR
)info
->pszOID
);
3715 HeapFree(GetProcessHeap(), 0, info
);
3719 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3722 ImageList_Destroy(data
->imageList
);
3723 HeapFree(GetProcessHeap(), 0, data
);
3730 static void show_edit_cert_properties_dialog(HWND parent
,
3731 struct detail_data
*data
)
3733 PROPSHEETHEADERW hdr
;
3734 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
3736 TRACE("(%p)\n", data
);
3738 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
3739 page
.dwSize
= sizeof(page
);
3740 page
.dwFlags
= PSP_USECALLBACK
;
3741 page
.pfnCallback
= cert_properties_general_callback
;
3742 page
.hInstance
= hInstance
;
3743 page
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
3744 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
3745 page
.lParam
= (LPARAM
)data
;
3747 memset(&hdr
, 0, sizeof(hdr
));
3748 hdr
.dwSize
= sizeof(hdr
);
3749 hdr
.hwndParent
= parent
;
3750 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
3751 hdr
.hInstance
= hInstance
;
3752 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
3753 hdr
.u3
.ppsp
= &page
;
3755 PropertySheetW(&hdr
);
3758 static void free_detail_fields(struct detail_data
*data
)
3762 for (i
= 0; i
< data
->cFields
; i
++)
3763 HeapFree(GetProcessHeap(), 0, data
->fields
[i
].detailed_value
);
3764 HeapFree(GetProcessHeap(), 0, data
->fields
);
3765 data
->fields
= NULL
;
3769 static void refresh_details_view(HWND hwnd
)
3771 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3773 struct detail_data
*data
;
3775 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3776 /* Actually, any index will do, since they all store the same data value */
3777 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
3778 free_detail_fields(data
);
3779 set_fields_selection(hwnd
, data
, curSel
);
3782 static LRESULT CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3785 PROPSHEETPAGEW
*page
;
3786 struct detail_data
*data
;
3788 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3793 page
= (PROPSHEETPAGEW
*)lp
;
3794 data
= (struct detail_data
*)page
->lParam
;
3795 create_cert_details_list(hwnd
, data
);
3796 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
3797 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
3798 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
3799 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
3804 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3806 nm
= (NMITEMACTIVATE
*)lp
;
3807 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
3808 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
3810 data
= (struct detail_data
*)nm
->lParam
;
3811 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
3813 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
3814 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
3816 if (data
->fields
[nm
->iItem
].create
)
3817 val
= data
->fields
[nm
->iItem
].create(
3818 data
->pCertViewInfo
->pCertContext
,
3819 data
->fields
[nm
->iItem
].param
);
3825 item
.cchTextMax
= ARRAY_SIZE(buf
);
3826 item
.mask
= LVIF_TEXT
;
3828 item
.iItem
= nm
->iItem
;
3830 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
3834 /* Select all the text in the control, the next update will
3837 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
3838 add_unformatted_text_to_control(valueCtl
, val
,
3839 val
? strlenW(val
) : 0);
3841 HeapFree(GetProcessHeap(), 0, val
);
3851 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3852 CRYPTUI_WIZ_EXPORT_INFO info
;
3854 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, 0, 0);
3855 info
.dwSize
= sizeof(info
);
3856 info
.pwszExportFileName
= NULL
;
3857 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
3858 info
.u
.pCertContext
= data
->pCertViewInfo
->pCertContext
;
3860 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
3863 case IDC_EDITPROPERTIES
:
3865 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3868 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3869 /* Actually, any index will do, since they all store the same
3872 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
3874 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
3877 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
3878 refresh_details_view(hwnd
);
3882 case WM_REFRESH_VIEW
:
3883 refresh_details_view(hwnd
);
3889 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
3890 PROPSHEETPAGEW
*page
)
3892 struct detail_data
*data
;
3897 data
= (struct detail_data
*)page
->lParam
;
3898 free_detail_fields(data
);
3899 HeapFree(GetProcessHeap(), 0, data
);
3905 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3906 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
3909 struct detail_data
*data
= HeapAlloc(GetProcessHeap(), 0,
3910 sizeof(struct detail_data
));
3914 data
->pCertViewInfo
= pCertViewInfo
;
3915 data
->pfPropertiesChanged
= pfPropertiesChanged
;
3917 data
->fields
= NULL
;
3918 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3919 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3920 page
->dwFlags
= PSP_USECALLBACK
;
3921 page
->pfnCallback
= detail_callback
;
3922 page
->hInstance
= hInstance
;
3923 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
3924 page
->pfnDlgProc
= detail_dlg_proc
;
3925 page
->lParam
= (LPARAM
)data
;
3933 struct hierarchy_data
3935 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
3936 HIMAGELIST imageList
;
3940 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
3942 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3943 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3944 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3945 data
->pCertViewInfo
->idxCounterSigner
);
3947 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
3948 * therefore always even.
3950 if (index
== provSigner
->csCertChain
- 1)
3951 return (LPARAM
)data
;
3952 return index
<< 1 | 1;
3955 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
3957 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3958 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3959 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3960 data
->pCertViewInfo
->idxCounterSigner
);
3963 return provSigner
->csCertChain
- 1;
3967 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
3970 struct hierarchy_data
*data
= NULL
;
3971 HTREEITEM root
= NULL
;
3974 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
3975 TVGN_PARENT
, (LPARAM
)hItem
);
3985 item
.mask
= TVIF_PARAM
;
3987 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
3988 data
= (struct hierarchy_data
*)item
.lParam
;
3993 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
3995 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
3998 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
4002 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
4004 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4005 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4006 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4007 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
4008 data
->pCertViewInfo
->idxCounterSigner
);
4010 HTREEITEM parent
= NULL
;
4012 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
4013 for (i
= provSigner
->csCertChain
; i
; i
--)
4017 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
4020 TVINSERTSTRUCTW tvis
;
4022 tvis
.hParent
= parent
;
4023 tvis
.hInsertAfter
= TVI_LAST
;
4024 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
4025 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
4026 tvis
.u
.item
.pszText
= name
;
4027 tvis
.u
.item
.state
= TVIS_EXPANDED
;
4028 tvis
.u
.item
.stateMask
= TVIS_EXPANDED
;
4029 if (i
== 1 && (!provSigner
->pChainContext
||
4030 provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
4031 CERT_TRUST_IS_PARTIAL_CHAIN
))
4033 /* The root of the chain has a special case: if the chain is
4034 * a partial chain, the icon is a warning icon rather than an
4037 tvis
.u
.item
.iImage
= 2;
4039 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
4041 tvis
.u
.item
.iImage
= 0;
4043 tvis
.u
.item
.iImage
= 1;
4044 tvis
.u
.item
.iSelectedImage
= tvis
.u
.item
.iImage
;
4045 tvis
.u
.item
.lParam
= index_to_lparam(data
, i
- 1);
4046 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
4048 HeapFree(GetProcessHeap(), 0, name
);
4053 static void set_certificate_status(HWND hwnd
, const CRYPT_PROVIDER_CERT
*cert
)
4055 /* Select all the text in the control, the next update will replace it */
4056 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
4057 /* Set the highest priority error messages first. */
4058 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
4059 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
4060 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
4061 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
4062 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
4063 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
4064 else if (cert
->dwRevokedReason
)
4065 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
4067 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
4070 static void set_certificate_status_for_end_cert(HWND hwnd
,
4071 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
4073 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
4074 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4075 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
4076 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
4077 pCertViewInfo
->idxCounterSigner
);
4078 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
4079 pCertViewInfo
->idxCert
);
4081 set_certificate_status(status
, provCert
);
4084 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
4086 /* Disable view certificate button until a certificate is selected */
4087 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
4088 show_cert_chain(hwnd
, data
);
4089 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
4092 static void show_dialog_for_selected_cert(HWND hwnd
)
4094 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4096 struct hierarchy_data
*data
;
4099 memset(&item
, 0, sizeof(item
));
4100 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4101 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
, 0);
4102 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4103 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4104 selection
= lparam_to_index(data
, item
.lParam
);
4107 CRYPT_PROVIDER_SGNR
*provSigner
;
4108 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4109 BOOL changed
= FALSE
;
4111 provSigner
= WTHelperGetProvSignerFromChain(
4112 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4113 data
->pCertViewInfo
->idxSigner
,
4114 data
->pCertViewInfo
->fCounterSigner
,
4115 data
->pCertViewInfo
->idxCounterSigner
);
4116 memset(&viewInfo
, 0, sizeof(viewInfo
));
4117 viewInfo
.dwSize
= sizeof(viewInfo
);
4118 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
4119 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
4120 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
4121 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
4122 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
4123 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
4124 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
4125 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
4126 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
4129 /* Delete the contents of the tree */
4130 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4131 /* Reinitialize the tree */
4132 show_cert_hierarchy(hwnd
, data
);
4137 static LRESULT CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4140 PROPSHEETPAGEW
*page
;
4141 struct hierarchy_data
*data
;
4143 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4145 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
4150 page
= (PROPSHEETPAGEW
*)lp
;
4151 data
= (struct hierarchy_data
*)page
->lParam
;
4152 show_cert_hierarchy(hwnd
, data
);
4161 case TVN_SELCHANGEDW
:
4163 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
4165 CRYPT_PROVIDER_SGNR
*provSigner
;
4167 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
4168 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
4169 provSigner
= WTHelperGetProvSignerFromChain(
4170 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4171 data
->pCertViewInfo
->idxSigner
,
4172 data
->pCertViewInfo
->fCounterSigner
,
4173 data
->pCertViewInfo
->idxCounterSigner
);
4174 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
4175 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
4176 &provSigner
->pasCertChain
[selection
]);
4180 show_dialog_for_selected_cert(hwnd
);
4181 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4190 case IDC_VIEWCERTIFICATE
:
4191 show_dialog_for_selected_cert(hwnd
);
4195 case WM_REFRESH_VIEW
:
4199 /* Get hierarchy data */
4200 memset(&item
, 0, sizeof(item
));
4201 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4202 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
4204 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4205 /* Delete the contents of the tree */
4206 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4207 /* Reinitialize the tree */
4208 show_cert_hierarchy(hwnd
, data
);
4215 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
4216 PROPSHEETPAGEW
*page
)
4218 struct hierarchy_data
*data
;
4223 data
= (struct hierarchy_data
*)page
->lParam
;
4224 ImageList_Destroy(data
->imageList
);
4225 HeapFree(GetProcessHeap(), 0, data
);
4231 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4232 PROPSHEETPAGEW
*page
)
4234 struct hierarchy_data
*data
= HeapAlloc(GetProcessHeap(), 0,
4235 sizeof(struct hierarchy_data
));
4240 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
4241 if (data
->imageList
)
4244 COLORREF backColor
= RGB(255, 0, 255);
4246 data
->pCertViewInfo
= pCertViewInfo
;
4247 data
->selectedCert
= 0xffffffff;
4249 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
4250 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
4252 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
4254 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
4255 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
4256 page
->dwFlags
= PSP_USECALLBACK
;
4257 page
->hInstance
= hInstance
;
4258 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
4259 page
->pfnDlgProc
= hierarchy_dlg_proc
;
4260 page
->lParam
= (LPARAM
)data
;
4261 page
->pfnCallback
= hierarchy_callback
;
4265 HeapFree(GetProcessHeap(), 0, data
);
4270 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
4274 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
4278 case PSCB_INITIALIZED
:
4279 /* Get cancel button's position.. */
4280 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
4281 MapWindowPoints( 0, hwnd
, (POINT
*)&rc
, 2 );
4282 /* hide the cancel button.. */
4283 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
4284 /* and move the OK button to the cancel button's original position. */
4285 SetWindowPos(GetDlgItem(hwnd
, IDOK
), 0, rc
.left
, rc
.top
, 0, 0,
4286 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
4292 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4293 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
4295 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
4297 PROPSHEETPAGEW
*pages
;
4299 HMODULE lib
= LoadLibraryW(riched
);
4301 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
4302 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4304 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4306 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
4309 PROPSHEETHEADERW hdr
;
4310 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
4313 memset(&hdr
, 0, sizeof(hdr
));
4314 hdr
.dwSize
= sizeof(hdr
);
4315 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
4316 hdr
.hInstance
= hInstance
;
4317 if (pCertViewInfo
->szTitle
)
4318 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
4320 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
4321 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
4322 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4324 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
4325 &pages
[hdr
.nPages
]))
4328 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4330 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
4333 /* Copy each additional page, and create the init dialog struct for it
4335 if (pCertViewInfo
->cPropSheetPages
)
4337 init
= HeapAlloc(GetProcessHeap(), 0,
4338 pCertViewInfo
->cPropSheetPages
*
4339 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
4342 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
4344 memcpy(&pages
[hdr
.nPages
+ i
],
4345 &pCertViewInfo
->rgPropSheetPages
[i
],
4346 sizeof(PROPSHEETPAGEW
));
4347 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
4348 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
4349 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
4351 if (pCertViewInfo
->nStartPage
& 0x8000)
4353 /* Start page index is relative to the number of default
4356 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
4359 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
4360 hdr
.nPages
= nPages
;
4364 SetLastError(ERROR_OUTOFMEMORY
);
4368 /* Ignore the relative flag if there aren't any additional pages */
4369 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
4376 hdr
.u3
.ppsp
= pages
;
4377 hdr
.pfnCallback
= cert_prop_sheet_proc
;
4378 l
= PropertySheetW(&hdr
);
4381 SetLastError(ERROR_CANCELLED
);
4385 HeapFree(GetProcessHeap(), 0, init
);
4386 HeapFree(GetProcessHeap(), 0, pages
);
4389 SetLastError(ERROR_OUTOFMEMORY
);
4394 /***********************************************************************
4395 * CryptUIDlgViewCertificateW (CRYPTUI.@)
4397 BOOL WINAPI
CryptUIDlgViewCertificateW(
4398 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
4400 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
4401 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4403 WINTRUST_CERT_INFO cert
;
4405 CRYPT_PROVIDER_SGNR
*signer
;
4406 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
4408 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
4410 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
4412 SetLastError(ERROR_INVALID_PARAMETER
);
4415 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
4416 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
4417 if (!pCertViewInfo
->u
.hWVTStateData
)
4419 memset(&wvt
, 0, sizeof(wvt
));
4420 wvt
.cbStruct
= sizeof(wvt
);
4421 wvt
.dwUIChoice
= WTD_UI_NONE
;
4422 if (viewInfo
.dwFlags
&
4423 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
4424 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
4425 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
4426 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
4427 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
4428 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
4429 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
4430 memset(&cert
, 0, sizeof(cert
));
4431 cert
.cbStruct
= sizeof(cert
);
4432 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
4433 cert
.chStores
= viewInfo
.cStores
;
4434 cert
.pahStores
= viewInfo
.rghStores
;
4435 wvt
.u
.pCert
= &cert
;
4436 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
4437 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4438 viewInfo
.u
.pCryptProviderData
=
4439 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
4440 signer
= WTHelperGetProvSignerFromChain(
4441 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
4442 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
4447 viewInfo
.u
.pCryptProviderData
=
4448 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
4449 signer
= WTHelperGetProvSignerFromChain(
4450 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
4451 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
4452 viewInfo
.idxCounterSigner
);
4453 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
4458 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
4459 if (!pCertViewInfo
->u
.hWVTStateData
)
4461 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
4462 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4468 /***********************************************************************
4469 * CryptUIDlgViewContext (CRYPTUI.@)
4471 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
4472 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
4476 TRACE("(%d, %p, %p, %s, %08x, %p)\n", dwContextType
, pvContext
, hwnd
,
4477 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
4479 switch (dwContextType
)
4481 case CERT_STORE_CERTIFICATE_CONTEXT
:
4483 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4485 memset(&viewInfo
, 0, sizeof(viewInfo
));
4486 viewInfo
.dwSize
= sizeof(viewInfo
);
4487 viewInfo
.hwndParent
= hwnd
;
4488 viewInfo
.szTitle
= pwszTitle
;
4489 viewInfo
.pCertContext
= pvContext
;
4490 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
4494 FIXME("unimplemented for context type %d\n", dwContextType
);
4495 SetLastError(E_INVALIDARG
);
4501 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
4502 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
4503 * should be a CA. If neither extension is present, returns
4504 * defaultIfNotSpecified.
4506 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
4508 BOOL isCA
= defaultIfNotSpecified
;
4509 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
4510 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4514 CERT_BASIC_CONSTRAINTS_INFO
*info
;
4517 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
4518 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
4519 NULL
, &info
, &size
))
4521 if (info
->SubjectType
.cbData
== 1)
4522 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
4528 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
4529 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4532 CERT_BASIC_CONSTRAINTS2_INFO info
;
4533 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4535 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
4536 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
4537 0, NULL
, &info
, &size
))
4544 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
4548 if (is_ca_cert(cert
, TRUE
))
4551 storeName
= addressBook
;
4552 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4553 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
4556 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
4563 SetLastError(E_INVALIDARG
);
4566 if (hDestCertStore
) store
= hDestCertStore
;
4569 if (!(store
= choose_store_for_cert(cert
)))
4571 WARN("unable to open certificate store\n");
4575 ret
= CertAddCertificateContextToStore(store
, cert
,
4576 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4577 if (!hDestCertStore
) CertCloseStore(store
, 0);
4581 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
4588 SetLastError(E_INVALIDARG
);
4591 if (hDestCertStore
) store
= hDestCertStore
;
4594 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4595 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
4597 WARN("unable to open certificate store\n");
4601 ret
= CertAddCRLContextToStore(store
, crl
,
4602 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4603 if (!hDestCertStore
) CertCloseStore(store
, 0);
4607 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
4614 SetLastError(E_INVALIDARG
);
4617 if (hDestCertStore
) store
= hDestCertStore
;
4620 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
4622 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4623 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
4625 WARN("unable to open certificate store\n");
4629 ret
= CertAddCTLContextToStore(store
, ctl
,
4630 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4631 if (!hDestCertStore
) CertCloseStore(store
, 0);
4635 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
4636 * CryptQueryObject, against the allowed types. Returns TRUE if the
4637 * type is allowed, FALSE otherwise.
4639 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
4644 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4645 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4649 case CERT_QUERY_CONTENT_CERT
:
4650 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4651 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
4653 case CERT_QUERY_CONTENT_CRL
:
4654 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4655 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
4657 case CERT_QUERY_CONTENT_CTL
:
4658 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4659 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
4662 /* The remaining types contain more than one type, so allow
4670 /* No allowed types specified, so any type is allowed */
4674 SetLastError(E_INVALIDARG
);
4679 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4682 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4684 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4691 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
4694 LoadStringW(hInstance
, warningID
, error
, ARRAY_SIZE(error
));
4695 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
4699 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
4701 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
4704 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
4709 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4710 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4712 PCCERT_CONTEXT cert
;
4717 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
4719 CertFreeCertificateContext(cert
);
4720 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
4723 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
4725 CertFreeCRLContext(crl
);
4726 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
4729 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
4731 CertFreeCTLContext(ctl
);
4732 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4739 SetLastError(E_INVALIDARG
);
4743 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4744 HCERTSTORE source
, HCERTSTORE dest
)
4748 if ((ret
= check_store_context_type(dwFlags
, source
)))
4750 PCCERT_CONTEXT cert
= NULL
;
4751 PCCRL_CONTEXT crl
= NULL
;
4752 PCCTL_CONTEXT ctl
= NULL
;
4755 cert
= CertEnumCertificatesInStore(source
, cert
);
4757 ret
= import_cert(cert
, dest
);
4758 } while (ret
&& cert
);
4760 crl
= CertEnumCRLsInStore(source
, crl
);
4762 ret
= import_crl(crl
, dest
);
4763 } while (ret
&& crl
);
4765 ctl
= CertEnumCTLsInStore(source
, ctl
);
4767 ret
= import_ctl(ctl
, dest
);
4768 } while (ret
&& ctl
);
4771 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
4775 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
4776 DWORD
*pContentType
)
4778 HCERTSTORE store
= NULL
;
4779 DWORD contentType
= 0, expectedContentTypeFlags
;
4782 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4783 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4785 expectedContentTypeFlags
=
4786 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4787 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4788 CERT_QUERY_CONTENT_FLAG_PFX
;
4789 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
4790 expectedContentTypeFlags
|=
4791 CERT_QUERY_CONTENT_FLAG_CERT
|
4792 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
4793 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
4794 expectedContentTypeFlags
|=
4795 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4796 CERT_QUERY_CONTENT_FLAG_CRL
;
4797 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
4798 expectedContentTypeFlags
|=
4799 CERT_QUERY_CONTENT_FLAG_CTL
|
4800 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
4803 expectedContentTypeFlags
=
4804 CERT_QUERY_CONTENT_FLAG_CERT
|
4805 CERT_QUERY_CONTENT_FLAG_CTL
|
4806 CERT_QUERY_CONTENT_FLAG_CRL
|
4807 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4808 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
4809 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
4810 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4811 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4812 CERT_QUERY_CONTENT_FLAG_PFX
;
4814 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
4815 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
4816 &contentType
, NULL
, &store
, NULL
, NULL
);
4818 *pContentType
= contentType
;
4822 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4823 LPCWSTR fileName
, HCERTSTORE dest
)
4828 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
4830 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
4831 CertCloseStore(source
, 0);
4838 struct ImportWizData
4842 LPCWSTR pwszWizardTitle
;
4843 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
4847 HCERTSTORE hDestCertStore
;
4853 static LRESULT CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4862 struct ImportWizData
*data
;
4863 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4864 WCHAR fontFace
[MAX_STRING_LEN
];
4865 HDC hDC
= GetDC(hwnd
);
4868 data
= (struct ImportWizData
*)page
->lParam
;
4869 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
, ARRAY_SIZE(fontFace
));
4870 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
4871 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
4872 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
4873 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
4874 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4875 (WPARAM
)data
->titleFont
, TRUE
);
4876 ReleaseDC(hwnd
, hDC
);
4881 NMHDR
*hdr
= (NMHDR
*)lp
;
4886 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
4896 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
4898 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
4900 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
4901 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
4902 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
4903 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
4905 static const WCHAR filter_all
[] = { '*','.','*',0 };
4912 } import_filters
[] = {
4913 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
4914 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
4915 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
4916 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
4917 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
4918 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
4919 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
4922 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
4925 int len
, totalLen
= 2;
4926 LPWSTR filter
= NULL
, str
;
4928 for (i
= 0; i
< ARRAY_SIZE(import_filters
); i
++)
4930 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4931 (dwFlags
& import_filters
[i
].allowFlags
))
4933 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
4934 totalLen
+= len
+ strlenW(import_filters
[i
].filter
) + 2;
4937 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
4943 for (i
= 0; i
< ARRAY_SIZE(import_filters
); i
++)
4945 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4946 (dwFlags
& import_filters
[i
].allowFlags
))
4948 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
4950 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
4953 strcpyW(ptr
, import_filters
[i
].filter
);
4954 ptr
+= strlenW(import_filters
[i
].filter
) + 1;
4962 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
4968 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
4969 OPEN_EXISTING
, 0, NULL
);
4970 if (file
!= INVALID_HANDLE_VALUE
)
4972 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
4973 &data
->contentType
);
4977 warningID
= IDS_IMPORT_BAD_FORMAT
;
4978 else if (!check_store_context_type(data
->dwFlags
, source
))
4979 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
4982 data
->importSrc
.dwSubjectChoice
=
4983 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
4984 data
->importSrc
.u
.hCertStore
= source
;
4985 data
->freeSource
= TRUE
;
4990 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4997 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4999 LPWSTR msgBuf
, fullError
;
5001 if (data
->pwszWizardTitle
)
5002 pTitle
= data
->pwszWizardTitle
;
5005 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5008 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
, ARRAY_SIZE(error
));
5010 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
5011 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
5012 fullError
= HeapAlloc(GetProcessHeap(), 0,
5013 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
5017 LPWSTR ptr
= fullError
;
5019 strcpyW(ptr
, error
);
5020 ptr
+= strlenW(error
);
5021 strcpyW(ptr
, fileName
);
5022 ptr
+= strlenW(fileName
);
5025 strcpyW(ptr
, msgBuf
);
5026 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
5027 HeapFree(GetProcessHeap(), 0, fullError
);
5034 static LRESULT CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5038 struct ImportWizData
*data
;
5044 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5046 data
= (struct ImportWizData
*)page
->lParam
;
5047 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5050 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5052 SendMessageW(fileNameEdit
, WM_SETTEXT
, 0, (LPARAM
)data
->fileName
);
5058 NMHDR
*hdr
= (NMHDR
*)lp
;
5063 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5064 PSWIZB_BACK
| PSWIZB_NEXT
);
5069 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5070 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
5072 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5075 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5076 IDS_IMPORT_EMPTY_FILE
);
5077 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5082 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
5083 (len
+ 1) * sizeof(WCHAR
));
5087 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
5089 if (!import_validate_filename(hwnd
, data
, fileName
))
5091 HeapFree(GetProcessHeap(), 0, fileName
);
5092 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5096 data
->fileName
= fileName
;
5107 case IDC_IMPORT_BROWSE_FILE
:
5110 WCHAR fileBuf
[MAX_PATH
];
5112 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5113 memset(&ofn
, 0, sizeof(ofn
));
5114 ofn
.lStructSize
= sizeof(ofn
);
5115 ofn
.hwndOwner
= hwnd
;
5116 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
5117 ofn
.lpstrFile
= fileBuf
;
5118 ofn
.nMaxFile
= ARRAY_SIZE(fileBuf
);
5120 if (GetOpenFileNameW(&ofn
))
5121 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
5122 0, (LPARAM
)ofn
.lpstrFile
);
5123 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
5132 static LRESULT CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5136 struct ImportWizData
*data
;
5142 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5144 data
= (struct ImportWizData
*)page
->lParam
;
5145 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5146 if (!data
->hDestCertStore
)
5148 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
,
5150 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5151 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5152 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
5156 WCHAR storeTitle
[MAX_STRING_LEN
];
5158 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), BM_CLICK
,
5160 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5161 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5162 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
),
5163 !(data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
));
5164 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, storeTitle
, ARRAY_SIZE(storeTitle
));
5165 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5166 0, (LPARAM
)storeTitle
);
5172 NMHDR
*hdr
= (NMHDR
*)lp
;
5177 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5178 PSWIZB_BACK
| PSWIZB_NEXT
);
5183 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5184 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
5185 !data
->hDestCertStore
)
5187 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5188 IDS_IMPORT_SELECT_STORE
);
5189 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5200 case IDC_IMPORT_AUTO_STORE
:
5201 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5202 data
->autoDest
= TRUE
;
5203 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5204 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5206 case IDC_IMPORT_SPECIFY_STORE
:
5207 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5208 data
->autoDest
= FALSE
;
5209 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5210 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5212 case IDC_IMPORT_BROWSE_STORE
:
5214 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
5215 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
5216 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
5217 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
5220 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5221 selectInfo
.dwSize
= sizeof(selectInfo
);
5222 selectInfo
.parent
= hwnd
;
5223 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
5224 selectInfo
.pwszTitle
= NULL
;
5225 selectInfo
.pwszText
= NULL
;
5226 selectInfo
.pEnumData
= &enumData
;
5227 selectInfo
.pfnSelectedStoreCallback
= NULL
;
5228 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
5230 WCHAR storeTitle
[MAX_STRING_LEN
];
5232 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, storeTitle
,
5233 ARRAY_SIZE(storeTitle
));
5234 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5235 0, (LPARAM
)storeTitle
);
5236 data
->hDestCertStore
= store
;
5237 data
->freeDest
= TRUE
;
5247 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
5249 WCHAR text
[MAX_STRING_LEN
];
5253 item
.mask
= LVIF_TEXT
;
5254 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5256 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
, ARRAY_SIZE(text
));
5257 item
.pszText
= text
;
5258 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5261 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
, ARRAY_SIZE(text
));
5263 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
, ARRAY_SIZE(text
));
5264 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5265 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5267 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
, ARRAY_SIZE(text
));
5268 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5269 switch (data
->contentType
)
5271 case CERT_QUERY_CONTENT_CERT
:
5272 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
5273 contentID
= IDS_IMPORT_CONTENT_CERT
;
5275 case CERT_QUERY_CONTENT_CRL
:
5276 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
5277 contentID
= IDS_IMPORT_CONTENT_CRL
;
5279 case CERT_QUERY_CONTENT_CTL
:
5280 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
5281 contentID
= IDS_IMPORT_CONTENT_CTL
;
5283 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
5284 contentID
= IDS_IMPORT_CONTENT_CMS
;
5286 case CERT_QUERY_CONTENT_FLAG_PFX
:
5287 contentID
= IDS_IMPORT_CONTENT_PFX
;
5290 contentID
= IDS_IMPORT_CONTENT_STORE
;
5293 LoadStringW(hInstance
, contentID
, text
, ARRAY_SIZE(text
));
5295 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5298 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5300 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
, ARRAY_SIZE(text
));
5301 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5303 item
.pszText
= data
->fileName
;
5304 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5308 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5309 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5313 switch (pImportSrc
->dwSubjectChoice
)
5315 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
5316 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
5317 pImportSrc
->u
.pwszFileName
, hDestCertStore
);
5319 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5320 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
5321 ret
= import_cert(pImportSrc
->u
.pCertContext
, hDestCertStore
);
5323 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5325 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5326 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
5327 ret
= import_crl(pImportSrc
->u
.pCRLContext
, hDestCertStore
);
5329 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5331 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5332 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
5333 ret
= import_ctl(pImportSrc
->u
.pCTLContext
, hDestCertStore
);
5335 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5337 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5338 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
5339 pImportSrc
->u
.hCertStore
, hDestCertStore
);
5342 WARN("unknown source type: %u\n", pImportSrc
->dwSubjectChoice
);
5343 SetLastError(E_INVALIDARG
);
5349 static LRESULT CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5353 struct ImportWizData
*data
;
5359 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5360 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5364 data
= (struct ImportWizData
*)page
->lParam
;
5365 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5366 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
5367 (WPARAM
)data
->titleFont
, TRUE
);
5368 GetWindowRect(lv
, &rc
);
5369 column
.mask
= LVCF_WIDTH
;
5370 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
5371 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
5372 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
5373 show_import_details(lv
, data
);
5378 NMHDR
*hdr
= (NMHDR
*)lp
;
5384 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5386 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5387 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
5388 show_import_details(lv
, data
);
5389 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5390 PSWIZB_BACK
| PSWIZB_FINISH
);
5396 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5397 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
5398 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
5400 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
5403 if (data
->pwszWizardTitle
)
5404 pTitle
= data
->pwszWizardTitle
;
5407 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5410 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
, ARRAY_SIZE(message
));
5411 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
5414 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5425 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
5426 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
5427 HCERTSTORE hDestCertStore
)
5429 PROPSHEETHEADERW hdr
;
5430 PROPSHEETPAGEW pages
[4];
5431 struct ImportWizData data
;
5434 data
.dwFlags
= dwFlags
;
5435 data
.pwszWizardTitle
= pwszWizardTitle
;
5438 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
5439 data
.fileName
= (LPWSTR
)pImportSrc
->u
.pwszFileName
;
5443 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
5444 data
.fileName
= NULL
;
5446 data
.freeSource
= FALSE
;
5447 data
.hDestCertStore
= hDestCertStore
;
5448 data
.freeDest
= FALSE
;
5449 data
.autoDest
= TRUE
;
5450 data
.success
= TRUE
;
5452 memset(pages
, 0, sizeof(pages
));
5454 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5455 pages
[nPages
].hInstance
= hInstance
;
5456 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
5457 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
5458 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5459 pages
[nPages
].lParam
= (LPARAM
)&data
;
5463 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
5465 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5466 pages
[nPages
].hInstance
= hInstance
;
5467 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
5468 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
5469 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5470 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
5471 pages
[nPages
].pszHeaderSubTitle
=
5472 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
5473 pages
[nPages
].lParam
= (LPARAM
)&data
;
5478 switch (pImportSrc
->dwSubjectChoice
)
5480 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5481 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
5483 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5484 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
5486 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5487 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
5489 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5490 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
5495 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5496 pages
[nPages
].hInstance
= hInstance
;
5497 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
5498 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
5499 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5500 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
5501 pages
[nPages
].pszHeaderSubTitle
=
5502 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
5503 pages
[nPages
].lParam
= (LPARAM
)&data
;
5506 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5507 pages
[nPages
].hInstance
= hInstance
;
5508 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
5509 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
5510 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5511 pages
[nPages
].lParam
= (LPARAM
)&data
;
5514 memset(&hdr
, 0, sizeof(hdr
));
5515 hdr
.dwSize
= sizeof(hdr
);
5516 hdr
.hwndParent
= hwndParent
;
5517 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
5519 hdr
.hInstance
= hInstance
;
5520 if (pwszWizardTitle
)
5521 hdr
.pszCaption
= pwszWizardTitle
;
5523 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
5524 hdr
.u3
.ppsp
= pages
;
5525 hdr
.nPages
= nPages
;
5526 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
5527 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
5528 PropertySheetW(&hdr
);
5529 if (data
.fileName
!= data
.importSrc
.u
.pwszFileName
)
5530 HeapFree(GetProcessHeap(), 0, data
.fileName
);
5531 if (data
.freeSource
&&
5532 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
5533 CertCloseStore(data
.importSrc
.u
.hCertStore
, 0);
5534 DeleteObject(data
.titleFont
);
5535 return data
.success
;
5538 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5539 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5543 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
5544 pImportSrc
, hDestCertStore
);
5547 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
5549 SetLastError(E_INVALIDARG
);
5553 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
5554 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5556 else if (pImportSrc
)
5557 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5561 /* Can't have no UI without specifying source */
5562 SetLastError(E_INVALIDARG
);
5569 struct ExportWizData
5573 LPCWSTR pwszWizardTitle
;
5574 CRYPTUI_WIZ_EXPORT_INFO exportInfo
;
5575 CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo
;
5577 PCRYPT_KEY_PROV_INFO keyProvInfo
;
5584 static LRESULT CALLBACK
export_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5593 struct ExportWizData
*data
;
5594 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5595 WCHAR fontFace
[MAX_STRING_LEN
];
5596 HDC hDC
= GetDC(hwnd
);
5599 data
= (struct ExportWizData
*)page
->lParam
;
5600 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
, ARRAY_SIZE(fontFace
));
5601 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
5602 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
5603 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
5604 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
5605 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
5606 (WPARAM
)data
->titleFont
, TRUE
);
5607 ReleaseDC(hwnd
, hDC
);
5612 NMHDR
*hdr
= (NMHDR
*)lp
;
5617 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
5627 static PCRYPT_KEY_PROV_INFO
export_get_private_key_info(PCCERT_CONTEXT cert
)
5629 PCRYPT_KEY_PROV_INFO info
= NULL
;
5632 if (CertGetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
,
5635 info
= HeapAlloc(GetProcessHeap(), 0, size
);
5638 if (!CertGetCertificateContextProperty(cert
,
5639 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
))
5641 HeapFree(GetProcessHeap(), 0, info
);
5649 static BOOL
export_acquire_private_key(const CRYPT_KEY_PROV_INFO
*info
,
5654 ret
= CryptAcquireContextW(phProv
, info
->pwszContainerName
,
5655 info
->pwszProvName
, info
->dwProvType
, 0);
5660 for (i
= 0; i
< info
->cProvParam
; i
++)
5661 CryptSetProvParam(*phProv
, info
->rgProvParam
[i
].dwParam
,
5662 info
->rgProvParam
[i
].pbData
, info
->rgProvParam
[i
].dwFlags
);
5667 static BOOL
export_is_key_exportable(HCRYPTPROV hProv
, DWORD keySpec
)
5672 if ((ret
= CryptGetUserKey(hProv
, keySpec
, &key
)))
5674 DWORD permissions
, size
= sizeof(permissions
);
5676 if ((ret
= CryptGetKeyParam(key
, KP_PERMISSIONS
, (BYTE
*)&permissions
,
5677 &size
, 0)) && !(permissions
& CRYPT_EXPORT
))
5679 CryptDestroyKey(key
);
5684 static LRESULT CALLBACK
export_private_key_dlg_proc(HWND hwnd
, UINT msg
,
5685 WPARAM wp
, LPARAM lp
)
5688 struct ExportWizData
*data
;
5694 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5695 PCRYPT_KEY_PROV_INFO info
;
5696 HCRYPTPROV hProv
= 0;
5699 data
= (struct ExportWizData
*)page
->lParam
;
5700 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5701 /* Get enough information about a key to see whether it's exportable.
5703 if (!(info
= export_get_private_key_info(
5704 data
->exportInfo
.u
.pCertContext
)))
5705 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5706 else if (!export_acquire_private_key(info
, &hProv
))
5707 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5708 else if (!export_is_key_exportable(hProv
, info
->dwKeySpec
))
5709 errorID
= IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE
;
5713 WCHAR error
[MAX_STRING_LEN
];
5715 LoadStringW(hInstance
, errorID
, error
, ARRAY_SIZE(error
));
5716 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE
),
5717 WM_SETTEXT
, 0, (LPARAM
)error
);
5718 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_YES
), FALSE
);
5721 data
->keyProvInfo
= info
;
5723 CryptReleaseContext(hProv
, 0);
5724 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
), BM_CLICK
,
5730 NMHDR
*hdr
= (NMHDR
*)lp
;
5735 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5736 PSWIZB_BACK
| PSWIZB_NEXT
);
5740 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5741 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
))
5743 data
->contextInfo
.dwExportFormat
=
5744 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5745 data
->contextInfo
.fExportPrivateKeys
= FALSE
;
5749 data
->contextInfo
.dwExportFormat
=
5750 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5751 data
->contextInfo
.fExportPrivateKeys
= TRUE
;
5761 static BOOL
export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
)
5765 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
)
5769 /* If there's a CRYPT_KEY_PROV_INFO set for this cert, assume the
5770 * cert has a private key.
5772 if (CertGetCertificateContextProperty(pExportInfo
->u
.pCertContext
,
5773 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
))
5779 static void export_format_enable_controls(HWND hwnd
, const struct ExportWizData
*data
)
5781 int defaultFormatID
;
5783 switch (data
->contextInfo
.dwExportFormat
)
5785 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
5786 defaultFormatID
= IDC_EXPORT_FORMAT_BASE64
;
5788 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
5789 defaultFormatID
= IDC_EXPORT_FORMAT_CMS
;
5791 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
5792 defaultFormatID
= IDC_EXPORT_FORMAT_PFX
;
5795 defaultFormatID
= IDC_EXPORT_FORMAT_DER
;
5797 SendMessageW(GetDlgItem(hwnd
, defaultFormatID
), BM_CLICK
, 0, 0);
5798 if (defaultFormatID
== IDC_EXPORT_FORMAT_PFX
)
5800 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), FALSE
);
5801 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), FALSE
);
5802 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), FALSE
);
5803 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), TRUE
);
5807 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), TRUE
);
5808 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), TRUE
);
5809 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), TRUE
);
5810 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), FALSE
);
5814 static LRESULT CALLBACK
export_format_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5818 struct ExportWizData
*data
;
5824 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5826 data
= (struct ExportWizData
*)page
->lParam
;
5827 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5828 export_format_enable_controls(hwnd
, data
);
5833 NMHDR
*hdr
= (NMHDR
*)lp
;
5838 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5839 PSWIZB_BACK
| PSWIZB_NEXT
);
5840 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5841 export_format_enable_controls(hwnd
, data
);
5846 BOOL skipPasswordPage
= TRUE
;
5848 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5849 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_DER
))
5850 data
->contextInfo
.dwExportFormat
=
5851 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5852 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_BASE64
))
5853 data
->contextInfo
.dwExportFormat
=
5854 CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
;
5855 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_CMS
))
5857 data
->contextInfo
.dwExportFormat
=
5858 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5859 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
))
5860 data
->contextInfo
.fExportChain
=
5861 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5865 data
->contextInfo
.dwExportFormat
=
5866 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5867 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
))
5868 data
->contextInfo
.fExportChain
= TRUE
;
5869 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
))
5870 data
->contextInfo
.fStrongEncryption
= TRUE
;
5871 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
))
5872 data
->deleteKeys
= TRUE
;
5873 skipPasswordPage
= FALSE
;
5875 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
,
5876 skipPasswordPage
? IDD_EXPORT_FILE
: 0);
5889 case IDC_EXPORT_FORMAT_DER
:
5890 case IDC_EXPORT_FORMAT_BASE64
:
5891 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5893 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5895 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5897 EnableWindow(GetDlgItem(hwnd
,
5898 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), FALSE
);
5900 case IDC_EXPORT_FORMAT_CMS
:
5901 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5904 case IDC_EXPORT_FORMAT_PFX
:
5905 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5907 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5909 EnableWindow(GetDlgItem(hwnd
,
5910 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), TRUE
);
5920 static void export_password_mismatch(HWND hwnd
, const struct ExportWizData
*data
)
5922 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5925 if (data
->pwszWizardTitle
)
5926 pTitle
= data
->pwszWizardTitle
;
5929 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5932 LoadStringW(hInstance
, IDS_EXPORT_PASSWORD_MISMATCH
, error
, ARRAY_SIZE(error
));
5933 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
5934 SetFocus(GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
));
5937 static LRESULT CALLBACK
export_password_dlg_proc(HWND hwnd
, UINT msg
,
5938 WPARAM wp
, LPARAM lp
)
5941 struct ExportWizData
*data
;
5947 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5949 data
= (struct ExportWizData
*)page
->lParam
;
5950 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5955 NMHDR
*hdr
= (NMHDR
*)lp
;
5960 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5961 PSWIZB_BACK
| PSWIZB_NEXT
);
5966 HWND passwordEdit
= GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
);
5967 HWND passwordConfirmEdit
= GetDlgItem(hwnd
,
5968 IDC_EXPORT_PASSWORD_CONFIRM
);
5969 DWORD passwordLen
= SendMessageW(passwordEdit
, WM_GETTEXTLENGTH
,
5971 DWORD passwordConfirmLen
= SendMessageW(passwordConfirmEdit
,
5972 WM_GETTEXTLENGTH
, 0, 0);
5974 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5975 if (!passwordLen
&& !passwordConfirmLen
)
5976 data
->contextInfo
.pwszPassword
= NULL
;
5977 else if (passwordLen
!= passwordConfirmLen
)
5979 export_password_mismatch(hwnd
, data
);
5980 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5985 LPWSTR password
= HeapAlloc(GetProcessHeap(), 0,
5986 (passwordLen
+ 1) * sizeof(WCHAR
));
5987 LPWSTR passwordConfirm
= HeapAlloc(GetProcessHeap(), 0,
5988 (passwordConfirmLen
+ 1) * sizeof(WCHAR
));
5989 BOOL freePassword
= TRUE
;
5991 if (password
&& passwordConfirm
)
5993 SendMessageW(passwordEdit
, WM_GETTEXT
, passwordLen
+ 1,
5995 SendMessageW(passwordConfirmEdit
, WM_GETTEXT
,
5996 passwordConfirmLen
+ 1, (LPARAM
)passwordConfirm
);
5997 if (strcmpW(password
, passwordConfirm
))
5999 export_password_mismatch(hwnd
, data
);
6000 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6005 data
->contextInfo
.pwszPassword
= password
;
6006 freePassword
= FALSE
;
6007 data
->freePassword
= TRUE
;
6011 HeapFree(GetProcessHeap(), 0, password
);
6012 HeapFree(GetProcessHeap(), 0, passwordConfirm
);
6023 static LPWSTR
export_append_extension(const struct ExportWizData
*data
,
6026 static const WCHAR cer
[] = { '.','c','e','r',0 };
6027 static const WCHAR crl
[] = { '.','c','r','l',0 };
6028 static const WCHAR ctl
[] = { '.','c','t','l',0 };
6029 static const WCHAR p7b
[] = { '.','p','7','b',0 };
6030 static const WCHAR pfx
[] = { '.','p','f','x',0 };
6031 static const WCHAR sst
[] = { '.','s','s','t',0 };
6034 BOOL appendExtension
;
6036 switch (data
->contextInfo
.dwExportFormat
)
6038 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6041 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6045 switch (data
->exportInfo
.dwSubjectChoice
)
6047 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6050 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6053 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6060 dot
= strrchrW(fileName
, '.');
6062 appendExtension
= strcmpiW(dot
, extension
) != 0;
6064 appendExtension
= TRUE
;
6065 if (appendExtension
)
6067 fileName
= HeapReAlloc(GetProcessHeap(), 0, fileName
,
6068 (strlenW(fileName
) + strlenW(extension
) + 1) * sizeof(WCHAR
));
6070 strcatW(fileName
, extension
);
6075 static BOOL
export_validate_filename(HWND hwnd
, struct ExportWizData
*data
,
6079 BOOL tryCreate
= TRUE
, forceCreate
= FALSE
, ret
= FALSE
;
6081 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6082 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, NULL
);
6083 if (file
!= INVALID_HANDLE_VALUE
)
6085 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
6088 if (data
->pwszWizardTitle
)
6089 pTitle
= data
->pwszWizardTitle
;
6092 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6095 LoadStringW(hInstance
, IDS_EXPORT_FILE_EXISTS
, warning
, ARRAY_SIZE(warning
));
6096 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
6104 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6105 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6106 forceCreate
? CREATE_ALWAYS
: CREATE_NEW
,
6108 if (file
!= INVALID_HANDLE_VALUE
)
6115 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6117 LPWSTR msgBuf
, fullError
;
6119 if (data
->pwszWizardTitle
)
6120 pTitle
= data
->pwszWizardTitle
;
6123 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6126 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
, ARRAY_SIZE(error
));
6128 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
6129 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
6130 fullError
= HeapAlloc(GetProcessHeap(), 0,
6131 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
6135 LPWSTR ptr
= fullError
;
6137 strcpyW(ptr
, error
);
6138 ptr
+= strlenW(error
);
6139 strcpyW(ptr
, fileName
);
6140 ptr
+= strlenW(fileName
);
6143 strcpyW(ptr
, msgBuf
);
6144 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
6145 HeapFree(GetProcessHeap(), 0, fullError
);
6153 static const WCHAR export_filter_cert
[] = { '*','.','c','e','r',0 };
6154 static const WCHAR export_filter_crl
[] = { '*','.','c','r','l',0 };
6155 static const WCHAR export_filter_ctl
[] = { '*','.','s','t','l',0 };
6156 static const WCHAR export_filter_cms
[] = { '*','.','p','7','b',0 };
6157 static const WCHAR export_filter_pfx
[] = { '*','.','p','f','x',0 };
6158 static const WCHAR export_filter_sst
[] = { '*','.','s','s','t',0 };
6160 static WCHAR
*make_export_file_filter(DWORD exportFormat
, DWORD subjectChoice
)
6162 int baseLen
, allLen
, totalLen
= 2, baseID
;
6163 LPWSTR filter
= NULL
, baseFilter
, all
;
6166 switch (exportFormat
)
6168 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6169 baseID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6170 filterStr
= export_filter_cert
;
6172 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6173 baseID
= IDS_EXPORT_FILTER_PFX
;
6174 filterStr
= export_filter_pfx
;
6176 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6177 baseID
= IDS_EXPORT_FILTER_CMS
;
6178 filterStr
= export_filter_cms
;
6181 switch (subjectChoice
)
6183 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6184 baseID
= IDS_EXPORT_FILTER_CRL
;
6185 filterStr
= export_filter_crl
;
6187 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6188 baseID
= IDS_EXPORT_FILTER_CTL
;
6189 filterStr
= export_filter_ctl
;
6191 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6192 baseID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6193 filterStr
= export_filter_sst
;
6196 baseID
= IDS_EXPORT_FILTER_CERT
;
6197 filterStr
= export_filter_cert
;
6201 baseLen
= LoadStringW(hInstance
, baseID
, (LPWSTR
)&baseFilter
, 0);
6202 totalLen
+= baseLen
+ strlenW(filterStr
) + 2;
6203 allLen
= LoadStringW(hInstance
, IDS_IMPORT_FILTER_ALL
, (LPWSTR
)&all
, 0);
6204 totalLen
+= allLen
+ strlenW(filter_all
) + 2;
6205 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
6211 memcpy(ptr
, baseFilter
, baseLen
* sizeof(WCHAR
));
6214 strcpyW(ptr
, filterStr
);
6215 ptr
+= strlenW(filterStr
) + 1;
6216 memcpy(ptr
, all
, allLen
* sizeof(WCHAR
));
6219 strcpyW(ptr
, filter_all
);
6220 ptr
+= strlenW(filter_all
) + 1;
6226 static LRESULT CALLBACK
export_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6230 struct ExportWizData
*data
;
6236 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6238 data
= (struct ExportWizData
*)page
->lParam
;
6239 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6240 if (data
->exportInfo
.pwszExportFileName
)
6241 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
, 0,
6242 (LPARAM
)data
->exportInfo
.pwszExportFileName
);
6247 NMHDR
*hdr
= (NMHDR
*)lp
;
6252 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6253 if (data
->contextInfo
.dwExportFormat
!=
6254 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
)
6256 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, IDD_EXPORT_FORMAT
);
6262 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
);
6263 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
6265 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6268 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6271 if (data
->pwszWizardTitle
)
6272 pTitle
= data
->pwszWizardTitle
;
6275 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6278 LoadStringW(hInstance
, IDS_IMPORT_EMPTY_FILE
, error
, ARRAY_SIZE(error
));
6279 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
6280 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6285 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
6286 (len
+ 1) * sizeof(WCHAR
));
6290 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
6292 fileName
= export_append_extension(data
, fileName
);
6293 if (!export_validate_filename(hwnd
, data
, fileName
))
6295 HeapFree(GetProcessHeap(), 0, fileName
);
6296 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6300 data
->fileName
= fileName
;
6306 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6307 PSWIZB_BACK
| PSWIZB_NEXT
);
6316 case IDC_EXPORT_BROWSE_FILE
:
6319 WCHAR fileBuf
[MAX_PATH
];
6321 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6322 memset(&ofn
, 0, sizeof(ofn
));
6323 ofn
.lStructSize
= sizeof(ofn
);
6324 ofn
.hwndOwner
= hwnd
;
6325 ofn
.lpstrFilter
= make_export_file_filter(
6326 data
->contextInfo
.dwExportFormat
,
6327 data
->exportInfo
.dwSubjectChoice
);
6328 ofn
.lpstrFile
= fileBuf
;
6329 ofn
.nMaxFile
= ARRAY_SIZE(fileBuf
);
6331 if (GetSaveFileNameW(&ofn
))
6332 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
,
6333 0, (LPARAM
)ofn
.lpstrFile
);
6334 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
6343 static void show_export_details(HWND lv
, const struct ExportWizData
*data
)
6345 WCHAR text
[MAX_STRING_LEN
];
6349 item
.mask
= LVIF_TEXT
;
6352 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6354 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
, ARRAY_SIZE(text
));
6355 item
.pszText
= text
;
6356 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6358 item
.pszText
= data
->fileName
;
6359 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6362 item
.pszText
= text
;
6363 switch (data
->exportInfo
.dwSubjectChoice
)
6365 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6366 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6367 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6368 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6373 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6375 LoadStringW(hInstance
, IDS_EXPORT_INCLUDE_CHAIN
, text
, ARRAY_SIZE(text
));
6376 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6378 LoadStringW(hInstance
, data
->contextInfo
.fExportChain
? IDS_YES
: IDS_NO
, text
,
6380 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6382 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6384 LoadStringW(hInstance
, IDS_EXPORT_KEYS
, text
, ARRAY_SIZE(text
));
6385 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6387 LoadStringW(hInstance
, data
->contextInfo
.fExportPrivateKeys
? IDS_YES
: IDS_NO
, text
,
6389 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6393 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6395 LoadStringW(hInstance
, IDS_EXPORT_FORMAT
, text
, ARRAY_SIZE(text
));
6396 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6399 switch (data
->exportInfo
.dwSubjectChoice
)
6401 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6402 contentID
= IDS_EXPORT_FILTER_CRL
;
6404 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6405 contentID
= IDS_EXPORT_FILTER_CTL
;
6407 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6408 contentID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6411 switch (data
->contextInfo
.dwExportFormat
)
6413 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6414 contentID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6416 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6417 contentID
= IDS_EXPORT_FILTER_CMS
;
6419 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6420 contentID
= IDS_EXPORT_FILTER_PFX
;
6423 contentID
= IDS_EXPORT_FILTER_CERT
;
6426 LoadStringW(hInstance
, contentID
, text
, ARRAY_SIZE(text
));
6427 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6430 static inline BOOL
save_der(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6434 return WriteFile(file
, pb
, cb
, &bytesWritten
, NULL
);
6437 static BOOL
save_base64(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6442 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, NULL
, &size
)))
6444 LPSTR buf
= HeapAlloc(GetProcessHeap(), 0, size
);
6448 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, buf
,
6450 ret
= WriteFile(file
, buf
, size
, &size
, NULL
);
6451 HeapFree(GetProcessHeap(), 0, buf
);
6455 SetLastError(ERROR_OUTOFMEMORY
);
6462 static inline BOOL
save_store_as_cms(HANDLE file
, HCERTSTORE store
)
6464 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6465 CERT_STORE_SAVE_AS_PKCS7
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6468 static BOOL
save_cert_as_cms(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6472 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
6473 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6479 HCERTSTORE addlStore
= CertOpenStore(CERT_STORE_PROV_COLLECTION
,
6480 0, 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6487 for (i
= 0; ret
&& i
< pExportInfo
->cStores
; i
++)
6488 ret
= CertAddStoreToCollection(addlStore
,
6489 pExportInfo
->rghStores
, 0, 0);
6492 PCCERT_CHAIN_CONTEXT chain
;
6494 ret
= CertGetCertificateChain(NULL
,
6495 pExportInfo
->u
.pCertContext
, NULL
, addlStore
, NULL
, 0,
6501 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6502 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6504 ret
= CertAddCertificateContextToStore(store
,
6505 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6506 CERT_STORE_ADD_ALWAYS
, NULL
);
6507 CertFreeCertificateChain(chain
);
6511 /* No chain could be created, just add the individual
6512 * cert to the message.
6514 ret
= CertAddCertificateContextToStore(store
,
6515 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
,
6519 CertCloseStore(addlStore
, 0);
6525 ret
= CertAddCertificateContextToStore(store
,
6526 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, NULL
);
6528 ret
= save_store_as_cms(file
, store
);
6529 CertCloseStore(store
, 0);
6536 static BOOL
save_serialized_store(HANDLE file
, HCERTSTORE store
)
6538 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6539 CERT_STORE_SAVE_AS_STORE
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6542 static BOOL
save_pfx(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6543 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6544 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6546 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, X509_ASN_ENCODING
,
6547 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6552 CRYPT_DATA_BLOB pfxBlob
= { 0, NULL
};
6553 PCCERT_CONTEXT cert
= NULL
;
6554 BOOL freeKeyProvInfo
= FALSE
;
6556 if (pContextInfo
->fExportChain
)
6558 HCERTCHAINENGINE engine
= NULL
;
6560 if (pExportInfo
->cStores
)
6562 CERT_CHAIN_ENGINE_CONFIG config
;
6564 memset(&config
, 0, sizeof(config
));
6565 config
.cbSize
= sizeof(config
);
6566 config
.cAdditionalStore
= pExportInfo
->cStores
;
6567 config
.rghAdditionalStore
= pExportInfo
->rghStores
;
6568 ret
= CertCreateCertificateChainEngine(&config
, &engine
);
6574 CERT_CHAIN_PARA chainPara
;
6575 PCCERT_CHAIN_CONTEXT chain
;
6577 memset(&chainPara
, 0, sizeof(chainPara
));
6578 chainPara
.cbSize
= sizeof(chainPara
);
6579 ret
= CertGetCertificateChain(engine
,
6580 pExportInfo
->u
.pCertContext
, NULL
, NULL
, &chainPara
, 0, NULL
,
6586 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6587 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6590 if (i
== 0 && j
== 0)
6591 ret
= CertAddCertificateContextToStore(store
,
6592 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6593 CERT_STORE_ADD_ALWAYS
, &cert
);
6595 ret
= CertAddCertificateContextToStore(store
,
6596 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6597 CERT_STORE_ADD_ALWAYS
, NULL
);
6599 CertFreeCertificateChain(chain
);
6603 CertFreeCertificateChainEngine(engine
);
6606 ret
= CertAddCertificateContextToStore(store
,
6607 pExportInfo
->u
.pCertContext
, CERT_STORE_ADD_ALWAYS
, &cert
);
6608 /* Copy private key info to newly created cert, so it'll get exported
6609 * along with the cert.
6611 if (ret
&& pContextInfo
->fExportPrivateKeys
)
6614 ret
= CertSetCertificateContextProperty(cert
,
6615 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6618 if (!(keyProvInfo
= export_get_private_key_info(cert
)))
6622 ret
= CertSetCertificateContextProperty(cert
,
6623 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6624 freeKeyProvInfo
= TRUE
;
6631 REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
| EXPORT_PRIVATE_KEYS
;
6633 ret
= PFXExportCertStore(store
, &pfxBlob
,
6634 pContextInfo
->pwszPassword
, exportFlags
);
6637 pfxBlob
.pbData
= HeapAlloc(GetProcessHeap(), 0, pfxBlob
.cbData
);
6640 ret
= PFXExportCertStore(store
, &pfxBlob
,
6641 pContextInfo
->pwszPassword
, exportFlags
);
6646 ret
= WriteFile(file
, pfxBlob
.pbData
, pfxBlob
.cbData
,
6647 &bytesWritten
, NULL
);
6652 SetLastError(ERROR_OUTOFMEMORY
);
6657 if (ret
&& deleteKeys
)
6661 CryptAcquireContextW(&prov
, keyProvInfo
->pwszContainerName
,
6662 keyProvInfo
->pwszProvName
, keyProvInfo
->dwProvType
,
6663 CRYPT_DELETEKEYSET
);
6665 if (freeKeyProvInfo
)
6666 HeapFree(GetProcessHeap(), 0, keyProvInfo
);
6667 CertFreeCertificateContext(cert
);
6668 CertCloseStore(store
, 0);
6673 static BOOL
do_export(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6674 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6675 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6679 if (pContextInfo
->dwSize
!= sizeof(CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
))
6681 SetLastError(E_INVALIDARG
);
6684 switch (pExportInfo
->dwSubjectChoice
)
6686 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6687 ret
= save_der(file
,
6688 pExportInfo
->u
.pCRLContext
->pbCrlEncoded
,
6689 pExportInfo
->u
.pCRLContext
->cbCrlEncoded
);
6691 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6692 ret
= save_der(file
,
6693 pExportInfo
->u
.pCTLContext
->pbCtlEncoded
,
6694 pExportInfo
->u
.pCTLContext
->cbCtlEncoded
);
6696 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6697 ret
= save_serialized_store(file
, pExportInfo
->u
.hCertStore
);
6699 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6700 ret
= save_store_as_cms(file
, pExportInfo
->u
.hCertStore
);
6703 switch (pContextInfo
->dwExportFormat
)
6705 case CRYPTUI_WIZ_EXPORT_FORMAT_DER
:
6706 ret
= save_der(file
, pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6707 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6709 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6710 ret
= save_base64(file
,
6711 pExportInfo
->u
.pCertContext
->pbCertEncoded
,
6712 pExportInfo
->u
.pCertContext
->cbCertEncoded
);
6714 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6715 ret
= save_cert_as_cms(file
, pExportInfo
,
6716 pContextInfo
->fExportChain
);
6718 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6719 ret
= save_pfx(file
, pExportInfo
, pContextInfo
, keyProvInfo
,
6723 SetLastError(E_FAIL
);
6730 static LRESULT CALLBACK
export_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6734 struct ExportWizData
*data
;
6740 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6741 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6745 data
= (struct ExportWizData
*)page
->lParam
;
6746 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6747 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
6748 (WPARAM
)data
->titleFont
, TRUE
);
6749 GetWindowRect(lv
, &rc
);
6750 column
.mask
= LVCF_WIDTH
;
6751 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
6752 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
6753 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
6754 show_export_details(lv
, data
);
6759 NMHDR
*hdr
= (NMHDR
*)lp
;
6765 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6767 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6768 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
6769 show_export_details(lv
, data
);
6770 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6771 PSWIZB_BACK
| PSWIZB_FINISH
);
6778 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
6782 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6783 if ((data
->success
= do_export(data
->file
, &data
->exportInfo
,
6784 &data
->contextInfo
, data
->keyProvInfo
, data
->deleteKeys
)))
6786 messageID
= IDS_EXPORT_SUCCEEDED
;
6791 messageID
= IDS_EXPORT_FAILED
;
6792 mbFlags
= MB_OK
| MB_ICONERROR
;
6794 if (data
->pwszWizardTitle
)
6795 pTitle
= data
->pwszWizardTitle
;
6798 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6801 LoadStringW(hInstance
, messageID
, message
, ARRAY_SIZE(message
));
6802 MessageBoxW(hwnd
, message
, pTitle
, mbFlags
);
6812 static BOOL
show_export_ui(DWORD dwFlags
, HWND hwndParent
,
6813 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, const void *pvoid
)
6815 PROPSHEETHEADERW hdr
;
6816 PROPSHEETPAGEW pages
[6];
6817 struct ExportWizData data
;
6819 BOOL hasPrivateKey
, showFormatPage
= TRUE
;
6822 data
.dwFlags
= dwFlags
;
6823 data
.pwszWizardTitle
= pwszWizardTitle
;
6824 memset(&data
.exportInfo
, 0, sizeof(data
.exportInfo
));
6825 memcpy(&data
.exportInfo
, pExportInfo
,
6826 min(sizeof(data
.exportInfo
), pExportInfo
->dwSize
));
6827 if (pExportInfo
->dwSize
> sizeof(data
.exportInfo
))
6828 data
.exportInfo
.dwSize
= sizeof(data
.exportInfo
);
6829 data
.contextInfo
.dwSize
= sizeof(data
.contextInfo
);
6830 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6831 data
.contextInfo
.fExportChain
= FALSE
;
6832 data
.contextInfo
.fStrongEncryption
= FALSE
;
6833 data
.contextInfo
.fExportPrivateKeys
= FALSE
;
6834 data
.contextInfo
.pwszPassword
= NULL
;
6835 data
.freePassword
= FALSE
;
6836 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
&&
6838 memcpy(&data
.contextInfo
, pvoid
,
6839 min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
)pvoid
)->dwSize
,
6840 sizeof(data
.contextInfo
)));
6841 data
.keyProvInfo
= NULL
;
6842 data
.deleteKeys
= FALSE
;
6843 data
.fileName
= NULL
;
6844 data
.file
= INVALID_HANDLE_VALUE
;
6845 data
.success
= FALSE
;
6847 memset(pages
, 0, sizeof(pages
));
6849 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6850 pages
[nPages
].hInstance
= hInstance
;
6851 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_WELCOME
);
6852 pages
[nPages
].pfnDlgProc
= export_welcome_dlg_proc
;
6853 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6854 pages
[nPages
].lParam
= (LPARAM
)&data
;
6857 hasPrivateKey
= export_info_has_private_key(pExportInfo
);
6858 switch (pExportInfo
->dwSubjectChoice
)
6860 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6861 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6862 showFormatPage
= FALSE
;
6863 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6865 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6866 showFormatPage
= FALSE
;
6867 data
.contextInfo
.dwExportFormat
=
6868 CRYPTUI_WIZ_EXPORT_FORMAT_SERIALIZED_CERT_STORE
;
6870 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6871 showFormatPage
= FALSE
;
6872 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
6876 if (hasPrivateKey
&& showFormatPage
)
6878 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6879 pages
[nPages
].hInstance
= hInstance
;
6880 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY
);
6881 pages
[nPages
].pfnDlgProc
= export_private_key_dlg_proc
;
6882 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6883 pages
[nPages
].pszHeaderTitle
=
6884 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE
);
6885 pages
[nPages
].pszHeaderSubTitle
=
6886 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE
);
6887 pages
[nPages
].lParam
= (LPARAM
)&data
;
6892 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6893 pages
[nPages
].hInstance
= hInstance
;
6894 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FORMAT
);
6895 pages
[nPages
].pfnDlgProc
= export_format_dlg_proc
;
6896 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6897 pages
[nPages
].pszHeaderTitle
=
6898 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_TITLE
);
6899 pages
[nPages
].pszHeaderSubTitle
=
6900 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_SUBTITLE
);
6901 pages
[nPages
].lParam
= (LPARAM
)&data
;
6904 if (hasPrivateKey
&& showFormatPage
)
6906 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6907 pages
[nPages
].hInstance
= hInstance
;
6908 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD
);
6909 pages
[nPages
].pfnDlgProc
= export_password_dlg_proc
;
6910 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6911 pages
[nPages
].pszHeaderTitle
=
6912 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE
);
6913 pages
[nPages
].pszHeaderSubTitle
=
6914 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE
);
6915 pages
[nPages
].lParam
= (LPARAM
)&data
;
6919 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6920 pages
[nPages
].hInstance
= hInstance
;
6921 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FILE
);
6922 pages
[nPages
].pfnDlgProc
= export_file_dlg_proc
;
6923 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6924 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_EXPORT_FILE_TITLE
);
6925 pages
[nPages
].pszHeaderSubTitle
=
6926 MAKEINTRESOURCEW(IDS_EXPORT_FILE_SUBTITLE
);
6927 pages
[nPages
].lParam
= (LPARAM
)&data
;
6930 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6931 pages
[nPages
].hInstance
= hInstance
;
6932 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FINISH
);
6933 pages
[nPages
].pfnDlgProc
= export_finish_dlg_proc
;
6934 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6935 pages
[nPages
].lParam
= (LPARAM
)&data
;
6938 memset(&hdr
, 0, sizeof(hdr
));
6939 hdr
.dwSize
= sizeof(hdr
);
6940 hdr
.hwndParent
= hwndParent
;
6941 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
6943 hdr
.hInstance
= hInstance
;
6944 if (pwszWizardTitle
)
6945 hdr
.pszCaption
= pwszWizardTitle
;
6947 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_EXPORT_WIZARD
);
6948 hdr
.u3
.ppsp
= pages
;
6949 hdr
.nPages
= nPages
;
6950 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
6951 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
6952 l
= PropertySheetW(&hdr
);
6953 DeleteObject(data
.titleFont
);
6954 if (data
.freePassword
)
6955 HeapFree(GetProcessHeap(), 0,
6956 (LPWSTR
)data
.contextInfo
.pwszPassword
);
6957 HeapFree(GetProcessHeap(), 0, data
.keyProvInfo
);
6958 CloseHandle(data
.file
);
6959 HeapFree(GetProcessHeap(), 0, data
.fileName
);
6962 SetLastError(ERROR_CANCELLED
);
6966 return data
.success
;
6969 BOOL WINAPI
CryptUIWizExport(DWORD dwFlags
, HWND hwndParent
,
6970 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, void *pvoid
)
6974 TRACE("(%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
,
6975 debugstr_w(pwszWizardTitle
), pExportInfo
, pvoid
);
6977 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
6978 ret
= show_export_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pExportInfo
,
6982 HANDLE file
= CreateFileW(pExportInfo
->pwszExportFileName
,
6983 GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6984 CREATE_ALWAYS
, 0, NULL
);
6986 if (file
!= INVALID_HANDLE_VALUE
)
6988 ret
= do_export(file
, pExportInfo
, pvoid
, NULL
, FALSE
);
6997 BOOL WINAPI
CryptUIDlgViewSignerInfoA(CRYPTUI_VIEWSIGNERINFO_STRUCTA
*pcvsi
)
6999 FIXME("%p: stub\n", pcvsi
);
7003 static void init_columns(HWND lv
, DWORD flags
)
7005 WCHAR buf
[MAX_STRING_LEN
];
7009 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
7010 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
7012 column
.pszText
= buf
;
7013 if (!(flags
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
))
7015 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
, ARRAY_SIZE(buf
));
7016 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7018 if (!(flags
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
))
7020 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
, ARRAY_SIZE(buf
));
7021 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7023 if (!(flags
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
))
7025 LoadStringW(hInstance
, IDS_INTENDED_USE_COLUMN
, buf
, ARRAY_SIZE(buf
));
7026 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7028 if (!(flags
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
))
7030 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
, ARRAY_SIZE(buf
));
7031 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7033 if (!(flags
& CRYPTUI_SELECT_EXPIRATION_COLUMN
))
7035 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
7036 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7038 if (!(flags
& CRYPTUI_SELECT_LOCATION_COLUMN
))
7040 LoadStringW(hInstance
, IDS_LOCATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
7041 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
7045 static void add_cert_to_list(HWND lv
, PCCERT_CONTEXT cert
, DWORD flags
, DWORD
*allocatedLen
,
7050 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
7053 LPWSTR none
, usages
;
7055 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
7056 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
7059 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
7062 item
.mask
|= LVIF_STATE
;
7063 item
.state
= LVIS_SELECTED
;
7064 item
.stateMask
= -1;
7066 if (!(flags
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
))
7068 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
, NULL
, 0);
7069 if (len
> *allocatedLen
)
7071 HeapFree(GetProcessHeap(), 0, *str
);
7072 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
7074 *allocatedLen
= len
;
7078 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
, *str
, len
);
7079 item
.pszText
= *str
;
7080 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7082 item
.mask
= LVIF_TEXT
;
7085 if (!(flags
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
))
7087 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, CERT_NAME_ISSUER_FLAG
, NULL
,
7089 if (len
> *allocatedLen
)
7091 HeapFree(GetProcessHeap(), 0, *str
);
7092 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
7094 *allocatedLen
= len
;
7098 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, CERT_NAME_ISSUER_FLAG
, NULL
,
7100 item
.pszText
= *str
;
7102 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7104 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7106 item
.mask
= LVIF_TEXT
;
7109 if (!(flags
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
))
7111 get_cert_usages(cert
, &usages
);
7114 item
.pszText
= usages
;
7116 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7118 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7119 HeapFree(GetProcessHeap(), 0, usages
);
7121 item
.mask
= LVIF_TEXT
;
7124 if (!(flags
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
))
7126 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
, NULL
, &len
))
7127 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
7128 if (len
> *allocatedLen
)
7130 HeapFree(GetProcessHeap(), 0, *str
);
7131 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
7133 *allocatedLen
= len
;
7137 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
, *str
, &len
))
7138 item
.pszText
= none
;
7140 item
.pszText
= *str
;
7142 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7144 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7146 item
.mask
= LVIF_TEXT
;
7149 if (!(flags
& CRYPTUI_SELECT_EXPIRATION_COLUMN
))
7151 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
7152 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
7153 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
, ARRAY_SIZE(buf
));
7156 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7158 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7159 item
.mask
= LVIF_TEXT
;
7162 if (!(flags
& CRYPTUI_SELECT_LOCATION_COLUMN
))
7164 static int show_fixme
;
7166 FIXME("showing location is not implemented\n");
7167 LoadStringW(hInstance
, IDS_NO_IMPL
, buf
, ARRAY_SIZE(buf
));
7169 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7171 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7175 static void add_store_certs(HWND lv
, HCERTSTORE store
, DWORD flags
, PFNCFILTERPROC filter
,
7176 void *callback_data
)
7178 PCCERT_CONTEXT cert
= NULL
;
7179 BOOL select
= FALSE
;
7180 DWORD allocatedLen
= 0;
7184 cert
= CertEnumCertificatesInStore(store
, cert
);
7185 if (cert
&& (!filter
|| filter(cert
, &select
, callback_data
)))
7186 add_cert_to_list(lv
, cert
, flags
, &allocatedLen
, &str
);
7188 HeapFree(GetProcessHeap(), 0, str
);
7191 static PCCERT_CONTEXT
select_cert_get_selected(HWND hwnd
, int selection
)
7193 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7194 PCCERT_CONTEXT cert
= NULL
;
7198 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1, LVNI_SELECTED
);
7201 item
.mask
= LVIF_PARAM
;
7202 item
.iItem
= selection
;
7204 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
7205 cert
= (PCCERT_CONTEXT
)item
.lParam
;
7209 static void select_cert_update_view_button(HWND hwnd
)
7211 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7212 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
7214 EnableWindow(GetDlgItem(hwnd
, IDC_SELECT_VIEW_CERT
), numSelected
== 1);
7217 struct SelectCertData
7219 PCCERT_CONTEXT
*cert
;
7221 HIMAGELIST imageList
;
7224 HCERTSTORE
*rghStores
;
7225 DWORD cPropSheetPages
;
7226 LPCPROPSHEETPAGEW rgPropSheetPages
;
7227 PFNCCERTDISPLAYPROC displayProc
;
7231 static void select_cert_view(HWND hwnd
, PCCERT_CONTEXT cert
, struct SelectCertData
*data
)
7233 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
7235 if (data
->displayProc
&& data
->displayProc(cert
, hwnd
, data
->callbackData
))
7237 memset(&viewInfo
, 0, sizeof(viewInfo
));
7238 viewInfo
.dwSize
= sizeof(viewInfo
);
7239 viewInfo
.hwndParent
= hwnd
;
7240 viewInfo
.pCertContext
= cert
;
7241 viewInfo
.cStores
= data
->cStores
;
7242 viewInfo
.rghStores
= data
->rghStores
;
7243 viewInfo
.cPropSheetPages
= data
->cPropSheetPages
;
7244 viewInfo
.rgPropSheetPages
= data
->rgPropSheetPages
;
7245 /* FIXME: this should be modal */
7246 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
7255 static int CALLBACK
select_cert_sort_by_text(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
7257 struct SortData
*data
= (struct SortData
*)lp
;
7258 return cert_mgr_sort_by_text(data
->hwnd
, data
->column
, lp1
, lp2
);
7261 struct SelectCertParam
7263 PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
;
7264 PCCERT_CONTEXT cert
;
7267 static LRESULT CALLBACK
select_cert_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
7269 struct SelectCertData
*data
;
7275 struct SelectCertParam
*param
= (struct SelectCertParam
*)lp
;
7276 PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
= param
->pcsc
;
7277 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7280 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
7283 data
->cert
= ¶m
->cert
;
7284 data
->dateColumn
= 4 -
7285 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
) ? 1 : 0) -
7286 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
) ? 1 : 0) -
7287 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
) ? 1 : 0) -
7288 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
) ? 1 : 0);
7289 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
7290 if (data
->imageList
)
7293 COLORREF backColor
= RGB(255, 0, 255);
7295 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
7296 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
7298 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
7299 SendMessageW(GetDlgItem(hwnd
, IDC_SELECT_CERTS
), LVM_SETIMAGELIST
, LVSIL_SMALL
,
7300 (LPARAM
)data
->imageList
);
7302 data
->title
= pcsc
->szTitle
;
7303 data
->cStores
= pcsc
->cStores
;
7304 data
->rghStores
= pcsc
->rghStores
;
7305 data
->cPropSheetPages
= pcsc
->cPropSheetPages
;
7306 data
->rgPropSheetPages
= pcsc
->rgPropSheetPages
;
7307 data
->displayProc
= pcsc
->pDisplayCallback
;
7308 data
->callbackData
= pcsc
->pvCallbackData
;
7309 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
7312 SendMessageW(hwnd
, WM_SETTEXT
, 0, (LPARAM
)pcsc
->szTitle
);
7313 if (pcsc
->szDisplayString
)
7314 SendMessageW(GetDlgItem(hwnd
, IDC_SELECT_DISPLAY_STRING
), WM_SETTEXT
, 0,
7315 (LPARAM
)pcsc
->szDisplayString
);
7316 init_columns(lv
, pcsc
->dwDontUseColumn
);
7317 while (i
< pcsc
->cDisplayStores
)
7318 add_store_certs(lv
, pcsc
->rghDisplayStores
[i
++], pcsc
->dwDontUseColumn
,
7319 pcsc
->pFilterCallback
, pcsc
->pvCallbackData
);
7320 select_cert_update_view_button(hwnd
);
7325 NMHDR
*hdr
= (NMHDR
*)lp
;
7331 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
7333 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7335 select_cert_view(hwnd
, cert
, data
);
7338 case LVN_COLUMNCLICK
:
7340 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
7341 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7343 /* FIXME: doesn't support swapping sort order between ascending and descending. */
7344 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7345 if (nmlv
->iSubItem
== data
->dateColumn
)
7346 SendMessageW(lv
, LVM_SORTITEMS
, 0, (LPARAM
)cert_mgr_sort_by_date
);
7349 struct SortData sortData
;
7352 sortData
.column
= nmlv
->iSubItem
;
7353 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)&sortData
,
7354 (LPARAM
)select_cert_sort_by_text
);
7366 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, -1);
7368 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7371 WCHAR buf
[40], title
[40];
7373 LoadStringW(hInstance
, IDS_SELECT_CERT
, buf
, ARRAY_SIZE(buf
));
7375 LoadStringW(hInstance
, IDS_SELECT_CERT_TITLE
, title
, ARRAY_SIZE(title
));
7376 MessageBoxW(hwnd
, buf
, data
->title
? data
->title
: title
, MB_OK
| MB_ICONWARNING
);
7379 *data
->cert
= CertDuplicateCertificateContext(cert
);
7380 free_certs(GetDlgItem(hwnd
, IDC_SELECT_CERTS
));
7381 ImageList_Destroy(data
->imageList
);
7382 HeapFree(GetProcessHeap(), 0, data
);
7383 EndDialog(hwnd
, IDOK
);
7387 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7388 free_certs(GetDlgItem(hwnd
, IDC_SELECT_CERTS
));
7389 ImageList_Destroy(data
->imageList
);
7390 HeapFree(GetProcessHeap(), 0, data
);
7391 EndDialog(hwnd
, IDCANCEL
);
7393 case IDC_SELECT_VIEW_CERT
:
7395 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, -1);
7397 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7399 select_cert_view(hwnd
, cert
, data
);
7408 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateW(PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
)
7410 struct SelectCertParam param
;
7412 TRACE("%p\n", pcsc
);
7414 if (pcsc
->dwSize
!= sizeof(*pcsc
) && pcsc
->dwSize
!= sizeof(*pcsc
) - sizeof(HCERTSTORE
))
7416 WARN("unexpected size %d\n", pcsc
->dwSize
);
7417 SetLastError(E_INVALIDARG
);
7420 if (pcsc
->dwFlags
& CRYPTUI_SELECTCERT_MULTISELECT
)
7421 FIXME("ignoring CRYPTUI_SELECTCERT_MULTISELECT\n");
7424 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_CERT
), pcsc
->hwndParent
,
7425 select_cert_dlg_proc
, (LPARAM
)¶m
);
7429 static void free_prop_sheet_pages(PROPSHEETPAGEW
*pages
, DWORD num
)
7433 for (i
= 0; i
< num
; i
++)
7435 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].u
.pszTemplate
))
7436 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].u
.pszTemplate
);
7437 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].u2
.pszIcon
))
7438 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].u2
.pszIcon
);
7439 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7440 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].pszTitle
);
7441 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7442 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].pszHeaderTitle
);
7443 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7444 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7445 HeapFree(GetProcessHeap(), 0, (void *)pages
[i
].pszHeaderSubTitle
);
7447 HeapFree(GetProcessHeap(), 0, pages
);
7450 static PROPSHEETPAGEW
*prop_sheet_pages_AtoW(LPCPROPSHEETPAGEA pages
, DWORD num
)
7452 PROPSHEETPAGEW
*psp
;
7453 DWORD i
, size
= sizeof(*psp
) * num
;
7455 psp
= HeapAlloc(GetProcessHeap(), 0, size
);
7458 memcpy(psp
, pages
, size
);
7459 for (i
= 0; i
< num
; i
++)
7461 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].u
.pszTemplate
))
7462 psp
[i
].u
.pszTemplate
= NULL
;
7463 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].u2
.pszIcon
))
7464 psp
[i
].u2
.pszIcon
= NULL
;
7465 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7466 psp
[i
].pszTitle
= NULL
;
7467 if (pages
[i
].dwFlags
& PSP_USECALLBACK
)
7468 psp
[i
].pfnCallback
= NULL
;
7469 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7470 psp
[i
].pszHeaderTitle
= NULL
;
7471 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7472 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7473 psp
[i
].pszHeaderSubTitle
= NULL
;
7475 for (i
= 0; i
< num
; i
++)
7477 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].u
.pszTemplate
))
7479 if (!(psp
[i
].u
.pszTemplate
= strdupAtoW( pages
[i
].u
.pszTemplate
))) goto error
;
7481 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].u2
.pszIcon
))
7483 if (!(psp
[i
].u2
.pszIcon
= strdupAtoW( pages
[i
].u2
.pszIcon
))) goto error
;
7485 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7487 if (!(psp
[i
].pszTitle
= strdupAtoW( pages
[i
].pszTitle
))) goto error
;
7489 if (pages
[i
].dwFlags
& PSP_USECALLBACK
)
7490 FIXME("ignoring pfnCallback\n");
7491 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7493 if (!(psp
[i
].pszHeaderTitle
= strdupAtoW( pages
[i
].pszHeaderTitle
))) goto error
;
7495 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7496 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7498 if (!(psp
[i
].pszHeaderSubTitle
= strdupAtoW( pages
[i
].pszHeaderSubTitle
))) goto error
;
7503 free_prop_sheet_pages(psp
, num
);
7507 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateA(PCCRYPTUI_SELECTCERTIFICATE_STRUCTA pcsc
)
7509 PCCERT_CONTEXT cert
= NULL
;
7510 CRYPTUI_SELECTCERTIFICATE_STRUCTW selCertInfo
;
7511 LPWSTR title
= NULL
, display_str
= NULL
;
7512 PROPSHEETPAGEW
*pages
= NULL
;
7514 TRACE("%p\n", pcsc
);
7516 if (pcsc
->dwSize
!= sizeof(*pcsc
) && pcsc
->dwSize
!= sizeof(*pcsc
) - sizeof(HCERTSTORE
))
7518 WARN("unexpected size %d\n", pcsc
->dwSize
);
7519 SetLastError(E_INVALIDARG
);
7522 memcpy(&selCertInfo
, pcsc
, pcsc
->dwSize
);
7525 if (!(title
= strdupAtoW( pcsc
->szTitle
))) goto error
;
7526 selCertInfo
.szTitle
= title
;
7528 if (pcsc
->szDisplayString
)
7530 if (!(display_str
= strdupAtoW( pcsc
->szDisplayString
))) goto error
;
7531 selCertInfo
.szDisplayString
= display_str
;
7533 if (pcsc
->cPropSheetPages
)
7535 pages
= prop_sheet_pages_AtoW(pcsc
->rgPropSheetPages
, pcsc
->cPropSheetPages
);
7538 selCertInfo
.rgPropSheetPages
= pages
;
7540 cert
= CryptUIDlgSelectCertificateW(&selCertInfo
);
7542 HeapFree(GetProcessHeap(), 0, title
);
7543 HeapFree(GetProcessHeap(), 0, display_str
);
7544 if (pcsc
->cPropSheetPages
)
7545 free_prop_sheet_pages(pages
, pcsc
->cPropSheetPages
);
7549 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateFromStore(HCERTSTORE hCertStore
, HWND hwnd
, LPCWSTR pwszTitle
,
7550 LPCWSTR pwszDisplayString
, DWORD dwDontUseColumn
,
7551 DWORD dwFlags
, void *pvReserved
)
7553 FIXME("%p %p %s %s %d %d %p: stub\n", hCertStore
, hwnd
, debugstr_w(pwszTitle
), debugstr_w(pwszDisplayString
), dwDontUseColumn
, dwFlags
, pvReserved
);
7557 BOOL WINAPI
CryptUIWizDigitalSign(DWORD flags
, HWND parent
, LPCWSTR title
, PCCRYPTUI_WIZ_DIGITAL_SIGN_INFO info
,
7558 PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
*context
)
7560 FIXME("%d %p %s %p %p: stub\n", flags
, parent
, debugstr_w(title
), info
, context
);