2 * Copyright 2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
37 #include "cryptuiapi.h"
38 #include "cryptuires.h"
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
47 static HINSTANCE hInstance
;
49 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
51 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
55 case DLL_WINE_PREATTACH
:
56 return FALSE
; /* prefer native version */
57 case DLL_PROCESS_ATTACH
:
59 DisableThreadLibraryCalls(hinstDLL
);
61 case DLL_PROCESS_DETACH
:
69 #define MAX_STRING_LEN 512
71 static void add_cert_columns(HWND hwnd
)
73 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
75 WCHAR buf
[MAX_STRING_LEN
];
78 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
79 GetWindowRect(lv
, &rc
);
80 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
,
81 sizeof(buf
) / sizeof(buf
[0]));
82 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
83 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
85 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
86 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
,
87 sizeof(buf
) / sizeof(buf
[0]));
88 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
89 column
.cx
= (rc
.right
- rc
.left
) * 16 / 100 - 2;
90 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
,
91 sizeof(buf
) / sizeof(buf
[0]));
92 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
93 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
94 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
,
95 sizeof(buf
) / sizeof(buf
[0]));
96 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 3, (LPARAM
)&column
);
99 static void add_cert_to_view(HWND lv
, PCCERT_CONTEXT cert
, DWORD
*allocatedLen
,
104 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
108 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
109 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
112 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
113 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
115 if (len
> *allocatedLen
)
117 HeapFree(GetProcessHeap(), 0, *str
);
118 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
124 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
127 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
130 item
.mask
= LVIF_TEXT
;
131 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
132 CERT_NAME_ISSUER_FLAG
, NULL
, NULL
, 0);
133 if (len
> *allocatedLen
)
135 HeapFree(GetProcessHeap(), 0, *str
);
136 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
142 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
143 CERT_NAME_ISSUER_FLAG
, NULL
, *str
, len
);
146 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
149 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
150 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
151 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
152 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
153 sizeof(date
) / sizeof(date
[0]));
156 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
158 len
= CertGetNameStringW(cert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
160 if (len
> *allocatedLen
)
162 HeapFree(GetProcessHeap(), 0, *str
);
163 *str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
169 CertGetNameStringW(cert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
173 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
177 static LPSTR
get_cert_mgr_usages(void)
179 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
180 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
181 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
182 'r','p','o','s','e',0 };
186 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
192 rc
= RegQueryValueExA(key
, "Purpose", NULL
, &type
, NULL
, &size
);
193 if ((!rc
|| rc
== ERROR_MORE_DATA
) && type
== REG_SZ
)
195 str
= HeapAlloc(GetProcessHeap(), 0, size
);
198 rc
= RegQueryValueExA(key
, "Purpose", NULL
, NULL
, (LPBYTE
)str
,
202 HeapFree(GetProcessHeap(), 0, str
);
213 PurposeFilterShowAll
= 0,
214 PurposeFilterShowAdvanced
= 1,
215 PurposeFilterShowOID
= 2
218 static void initialize_purpose_selection(HWND hwnd
)
220 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
221 WCHAR buf
[MAX_STRING_LEN
];
225 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
,
226 sizeof(buf
) / sizeof(buf
[0]));
227 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
228 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAll
);
229 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
,
230 sizeof(buf
) / sizeof(buf
[0]));
231 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
232 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAdvanced
);
233 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
234 if ((usages
= get_cert_mgr_usages()))
238 for (ptr
= usages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
239 ptr
= comma
? comma
+ 1 : NULL
,
240 comma
= ptr
? strchr(ptr
, ',') : NULL
)
242 PCCRYPT_OID_INFO info
;
246 if ((info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, ptr
, 0)))
248 index
= SendMessageW(cb
, CB_INSERTSTRING
, 0,
249 (LPARAM
)info
->pwszName
);
250 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)info
);
253 HeapFree(GetProcessHeap(), 0, usages
);
257 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
258 PCCRYPT_OID_INFO
**usages
);
260 static CERT_ENHKEY_USAGE
*add_oid_to_usage(CERT_ENHKEY_USAGE
*usage
, LPSTR oid
)
262 if (!usage
->cUsageIdentifier
)
263 usage
->rgpszUsageIdentifier
= HeapAlloc(GetProcessHeap(), 0,
266 usage
->rgpszUsageIdentifier
= HeapReAlloc(GetProcessHeap(), 0,
267 usage
->rgpszUsageIdentifier
,
268 (usage
->cUsageIdentifier
+ 1) * sizeof(LPSTR
));
269 if (usage
->rgpszUsageIdentifier
)
270 usage
->rgpszUsageIdentifier
[usage
->cUsageIdentifier
++] = oid
;
273 HeapFree(GetProcessHeap(), 0, usage
);
279 static CERT_ENHKEY_USAGE
*convert_usages_str_to_usage(LPSTR usageStr
)
281 CERT_ENHKEY_USAGE
*usage
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
282 sizeof(CERT_ENHKEY_USAGE
));
288 for (ptr
= usageStr
, comma
= strchr(ptr
, ','); usage
&& ptr
&& *ptr
;
289 ptr
= comma
? comma
+ 1 : NULL
,
290 comma
= ptr
? strchr(ptr
, ',') : NULL
)
294 add_oid_to_usage(usage
, ptr
);
300 static CERT_ENHKEY_USAGE
*create_advanced_filter(void)
302 CERT_ENHKEY_USAGE
*advancedUsage
= HeapAlloc(GetProcessHeap(),
303 HEAP_ZERO_MEMORY
, sizeof(CERT_ENHKEY_USAGE
));
307 PCCRYPT_OID_INFO
*usages
;
309 if (WTHelperGetKnownUsages(1, &usages
))
311 LPSTR disabledUsagesStr
;
313 if ((disabledUsagesStr
= get_cert_mgr_usages()))
315 CERT_ENHKEY_USAGE
*disabledUsages
=
316 convert_usages_str_to_usage(disabledUsagesStr
);
320 PCCRYPT_OID_INFO
*ptr
;
322 for (ptr
= usages
; *ptr
; ptr
++)
325 BOOL disabled
= FALSE
;
327 for (i
= 0; !disabled
&&
328 i
< disabledUsages
->cUsageIdentifier
; i
++)
329 if (!strcmp(disabledUsages
->rgpszUsageIdentifier
[i
],
333 add_oid_to_usage(advancedUsage
,
334 (LPSTR
)(*ptr
)->pszOID
);
336 /* The individual strings are pointers to disabledUsagesStr,
337 * so they're freed when it is.
339 HeapFree(GetProcessHeap(), 0,
340 disabledUsages
->rgpszUsageIdentifier
);
341 HeapFree(GetProcessHeap(), 0, disabledUsages
);
343 HeapFree(GetProcessHeap(), 0, disabledUsagesStr
);
345 WTHelperGetKnownUsages(2, &usages
);
348 return advancedUsage
;
351 static void show_store_certs(HWND hwnd
, HCERTSTORE store
)
353 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
354 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
355 PCCERT_CONTEXT cert
= NULL
;
356 DWORD allocatedLen
= 0;
359 PurposeFilter filter
= PurposeFilterShowAll
;
361 CERT_ENHKEY_USAGE
*advanced
= NULL
;
363 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
366 INT_PTR data
= SendMessageW(cb
, CB_GETITEMDATA
, index
, 0);
372 PCCRYPT_OID_INFO info
= (PCCRYPT_OID_INFO
)data
;
374 filter
= PurposeFilterShowOID
;
378 if (filter
== PurposeFilterShowAdvanced
)
379 advanced
= create_advanced_filter();
381 cert
= CertEnumCertificatesInStore(store
, cert
);
386 if (filter
== PurposeFilterShowAll
)
393 if (CertGetValidUsages(1, &cert
, &numOIDs
, NULL
, &cbOIDs
))
397 /* -1 implies all usages are valid */
402 LPSTR
*oids
= HeapAlloc(GetProcessHeap(), 0, cbOIDs
);
406 if (CertGetValidUsages(1, &cert
, &numOIDs
, oids
,
411 if (filter
== PurposeFilterShowOID
)
413 for (i
= 0; !show
&& i
< numOIDs
; i
++)
414 if (!strcmp(oids
[i
], oid
))
419 for (i
= 0; !show
&& i
< numOIDs
; i
++)
424 j
< advanced
->cUsageIdentifier
; j
++)
426 advanced
->rgpszUsageIdentifier
[j
]))
431 HeapFree(GetProcessHeap(), 0, oids
);
437 add_cert_to_view(lv
, cert
, &allocatedLen
, &str
);
440 HeapFree(GetProcessHeap(), 0, str
);
443 HeapFree(GetProcessHeap(), 0, advanced
->rgpszUsageIdentifier
);
444 HeapFree(GetProcessHeap(), 0, advanced
);
448 static const WCHAR my
[] = { 'M','y',0 };
449 static const WCHAR addressBook
[] = {
450 'A','d','d','r','e','s','s','B','o','o','k',0 };
451 static const WCHAR ca
[] = { 'C','A',0 };
452 static const WCHAR root
[] = { 'R','o','o','t',0 };
453 static const WCHAR trustedPublisher
[] = {
454 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
455 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
457 struct CertMgrStoreInfo
461 int removePluralWarning
;
464 static const struct CertMgrStoreInfo defaultStoreList
[] = {
465 { my
, IDS_WARN_REMOVE_MY
, IDS_WARN_REMOVE_PLURAL_MY
},
466 { addressBook
, IDS_WARN_REMOVE_ADDRESSBOOK
,
467 IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK
},
468 { ca
, IDS_WARN_REMOVE_CA
, IDS_WARN_REMOVE_PLURAL_CA
},
469 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
470 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
471 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
472 { disallowed
, IDS_WARN_REMOVE_DEFAULT
},
475 static const struct CertMgrStoreInfo publisherStoreList
[] = {
476 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
477 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
478 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
479 { disallowed
, IDS_WARN_REMOVE_PLURAL_DEFAULT
},
484 HIMAGELIST imageList
;
487 const struct CertMgrStoreInfo
*stores
;
490 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
, struct CertMgrData
*data
)
492 const struct CertMgrStoreInfo
*storeList
;
494 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
496 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
498 storeList
= publisherStoreList
;
499 cStores
= sizeof(publisherStoreList
) / sizeof(publisherStoreList
[0]);
503 storeList
= defaultStoreList
;
504 cStores
= sizeof(defaultStoreList
) / sizeof(defaultStoreList
[0]);
506 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
508 data
->nStores
= cStores
;
509 data
->stores
= storeList
;
510 for (i
= 0; i
< cStores
; i
++)
516 if (!(name
= CryptFindLocalizedName(storeList
[i
].name
)))
517 name
= storeList
[i
].name
;
518 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
519 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
].name
);
520 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
521 item
.pszText
= (LPWSTR
)name
;
522 item
.lParam
= (LPARAM
)store
;
523 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
527 static void free_certs(HWND lv
)
530 int items
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
532 for (i
= 0; i
< items
; i
++)
534 item
.mask
= LVIF_PARAM
;
537 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
538 CertFreeCertificateContext((PCCERT_CONTEXT
)item
.lParam
);
542 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
546 item
.mask
= TCIF_PARAM
;
547 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
548 return (HCERTSTORE
)item
.lParam
;
551 static HCERTSTORE
cert_mgr_current_store(HWND hwnd
)
553 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
555 return cert_mgr_index_to_store(tab
, SendMessageW(tab
, TCM_GETCURSEL
, 0, 0));
558 static void close_stores(HWND tab
)
560 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
562 for (i
= 0; i
< tabs
; i
++)
563 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
566 static void refresh_store_certs(HWND hwnd
)
568 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
571 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
572 show_store_certs(hwnd
, cert_mgr_current_store(hwnd
));
576 CheckBitmapIndexUnchecked
= 1,
577 CheckBitmapIndexChecked
= 2,
578 CheckBitmapIndexDisabledUnchecked
= 3,
579 CheckBitmapIndexDisabledChecked
= 4
582 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
,
583 CheckBitmapIndex state
)
587 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
588 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
589 item
.stateMask
= LVIS_STATEIMAGEMASK
;
590 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
592 item
.lParam
= (LPARAM
)info
;
593 item
.pszText
= (LPWSTR
)info
->pwszName
;
594 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
597 static void add_known_usages_to_list(HWND lv
, CheckBitmapIndex state
)
599 PCCRYPT_OID_INFO
*usages
;
601 if (WTHelperGetKnownUsages(1, &usages
))
603 PCCRYPT_OID_INFO
*ptr
;
605 for (ptr
= usages
; *ptr
; ptr
++)
606 add_known_usage(lv
, *ptr
, state
);
607 WTHelperGetKnownUsages(2, &usages
);
611 static void toggle_usage(HWND hwnd
, int iItem
)
615 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
617 item
.mask
= LVIF_STATE
;
620 item
.stateMask
= LVIS_STATEIMAGEMASK
;
621 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
624 int state
= item
.state
>> 12;
626 item
.state
= INDEXTOSTATEIMAGEMASK(
627 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
628 CheckBitmapIndexChecked
);
629 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
633 static LONG_PTR
find_oid_in_list(HWND lv
, LPCSTR oid
)
635 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
636 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
641 LVFINDINFOW findInfo
;
643 findInfo
.flags
= LVFI_PARAM
;
644 findInfo
.lParam
= (LPARAM
)oidInfo
;
645 ret
= SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
);
649 LVFINDINFOA findInfo
;
651 findInfo
.flags
= LVFI_STRING
;
653 ret
= SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
);
658 static void save_cert_mgr_usages(HWND hwnd
)
660 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
661 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
662 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
663 'r','p','o','s','e',0 };
665 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
666 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
670 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
672 item
.stateMask
= LVIS_STATEIMAGEMASK
;
673 for (i
= 0; i
< purposes
; i
++)
676 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
678 int state
= item
.state
>> 12;
680 if (state
== CheckBitmapIndexUnchecked
)
682 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
683 BOOL firstString
= TRUE
;
686 str
= HeapAlloc(GetProcessHeap(), 0,
687 strlen(info
->pszOID
) + 1);
690 str
= HeapReAlloc(GetProcessHeap(), 0, str
,
691 strlen(str
) + 1 + strlen(info
->pszOID
) + 1);
696 LPSTR ptr
= firstString
? str
: str
+ strlen(str
);
700 strcpy(ptr
, info
->pszOID
);
705 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_ALL_ACCESS
,
709 RegSetValueExA(key
, "Purpose", 0, REG_SZ
, (const BYTE
*)str
,
712 RegDeleteValueA(key
, "Purpose");
715 HeapFree(GetProcessHeap(), 0, str
);
718 static LRESULT CALLBACK
cert_mgr_advanced_dlg_proc(HWND hwnd
, UINT msg
,
719 WPARAM wp
, LPARAM lp
)
727 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
728 HIMAGELIST imageList
;
729 LPSTR disabledUsages
;
731 GetWindowRect(lv
, &rc
);
732 column
.mask
= LVCF_WIDTH
;
733 column
.cx
= rc
.right
- rc
.left
;
734 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
735 imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 4, 0);
739 COLORREF backColor
= RGB(255, 0, 255);
741 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
742 ImageList_AddMasked(imageList
, bmp
, backColor
);
744 ImageList_SetBkColor(imageList
, CLR_NONE
);
745 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)imageList
);
746 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)imageList
);
748 add_known_usages_to_list(lv
, CheckBitmapIndexChecked
);
749 if ((disabledUsages
= get_cert_mgr_usages()))
753 for (ptr
= disabledUsages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
754 ptr
= comma
? comma
+ 1 : NULL
,
755 comma
= ptr
? strchr(ptr
, ',') : NULL
)
761 if ((index
= find_oid_in_list(lv
, ptr
)) != -1)
762 toggle_usage(hwnd
, index
);
764 HeapFree(GetProcessHeap(), 0, disabledUsages
);
770 NMHDR
*hdr
= (NMHDR
*)lp
;
776 nm
= (NMITEMACTIVATE
*)lp
;
777 toggle_usage(hwnd
, nm
->iItem
);
778 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
787 save_cert_mgr_usages(hwnd
);
788 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
789 EndDialog(hwnd
, IDOK
);
792 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
793 EndDialog(hwnd
, IDCANCEL
);
801 static void cert_mgr_clear_cert_selection(HWND hwnd
)
803 WCHAR empty
[] = { 0 };
805 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), FALSE
);
806 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), FALSE
);
807 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), FALSE
);
808 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
810 refresh_store_certs(hwnd
);
813 static PCCERT_CONTEXT
cert_mgr_index_to_cert(HWND hwnd
, int index
)
815 PCCERT_CONTEXT cert
= NULL
;
818 item
.mask
= LVIF_PARAM
;
821 if (SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_GETITEMW
, 0,
823 cert
= (PCCERT_CONTEXT
)item
.lParam
;
827 static void show_selected_cert(HWND hwnd
, int index
)
829 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
833 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
835 memset(&viewInfo
, 0, sizeof(viewInfo
));
836 viewInfo
.dwSize
= sizeof(viewInfo
);
837 viewInfo
.hwndParent
= hwnd
;
838 viewInfo
.pCertContext
= cert
;
839 /* FIXME: this should be modal */
840 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
844 static void cert_mgr_show_cert_usages(HWND hwnd
, int index
)
846 HWND text
= GetDlgItem(hwnd
, IDC_MGR_PURPOSES
);
847 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
848 PCERT_ENHKEY_USAGE usage
;
851 /* Get enhanced key usage. Have to check for a property and an extension
852 * separately, because CertGetEnhancedKeyUsage will succeed and return an
853 * empty usage if neither is set. Unfortunately an empty usage implies
854 * no usage is allowed, so we have to distinguish between the two cases.
856 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
859 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
860 if (!CertGetEnhancedKeyUsage(cert
,
861 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
863 HeapFree(GetProcessHeap(), 0, usage
);
867 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
870 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
871 if (!CertGetEnhancedKeyUsage(cert
,
872 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
874 HeapFree(GetProcessHeap(), 0, usage
);
882 if (usage
->cUsageIdentifier
)
884 static const WCHAR commaSpace
[] = { ',',' ',0 };
888 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
890 PCCRYPT_OID_INFO info
=
891 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
892 usage
->rgpszUsageIdentifier
[i
],
893 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
896 len
+= strlenW(info
->pwszName
);
898 len
+= strlen(usage
->rgpszUsageIdentifier
[i
]);
899 if (i
< usage
->cUsageIdentifier
- 1)
900 len
+= strlenW(commaSpace
);
902 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
905 for (i
= 0, ptr
= str
; i
< usage
->cUsageIdentifier
; i
++)
907 PCCRYPT_OID_INFO info
=
908 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
909 usage
->rgpszUsageIdentifier
[i
],
910 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
914 strcpyW(ptr
, info
->pwszName
);
915 ptr
+= strlenW(info
->pwszName
);
919 LPCSTR src
= usage
->rgpszUsageIdentifier
[i
];
921 for (; *src
; ptr
++, src
++)
925 if (i
< usage
->cUsageIdentifier
- 1)
927 strcpyW(ptr
, commaSpace
);
928 ptr
+= strlenW(commaSpace
);
932 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)str
);
933 HeapFree(GetProcessHeap(), 0, str
);
935 HeapFree(GetProcessHeap(), 0, usage
);
939 WCHAR buf
[MAX_STRING_LEN
];
941 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_NONE
, buf
,
942 sizeof(buf
) / sizeof(buf
[0]));
943 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
948 WCHAR buf
[MAX_STRING_LEN
];
950 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_ALL
, buf
,
951 sizeof(buf
) / sizeof(buf
[0]));
952 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)buf
);
956 static void cert_mgr_do_remove(HWND hwnd
)
958 int tabIndex
= SendMessageW(GetDlgItem(hwnd
, IDC_MGR_STORES
),
959 TCM_GETCURSEL
, 0, 0);
960 struct CertMgrData
*data
=
961 (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
963 if (tabIndex
< data
->nStores
)
965 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
966 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
970 if (SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0) > 1)
971 warningID
= data
->stores
[tabIndex
].removePluralWarning
;
973 warningID
= data
->stores
[tabIndex
].removeWarning
;
975 pTitle
= data
->title
;
978 LoadStringW(hInstance
, IDS_CERT_MGR
, title
,
979 sizeof(title
) / sizeof(title
[0]));
982 LoadStringW(hInstance
, warningID
, warning
,
983 sizeof(warning
) / sizeof(warning
[0]));
984 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
989 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
993 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
996 CertDeleteCertificateFromStore(cert
);
998 } while (selection
>= 0);
999 cert_mgr_clear_cert_selection(hwnd
);
1004 static LRESULT CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1007 struct CertMgrData
*data
;
1013 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
1014 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
1015 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
1017 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData
));
1020 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
,
1022 if (data
->imageList
)
1025 COLORREF backColor
= RGB(255, 0, 255);
1027 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
1028 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
1030 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
1031 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_SETIMAGELIST
,
1032 LVSIL_SMALL
, (LPARAM
)data
->imageList
);
1034 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
1035 data
->title
= pCryptUICertMgr
->pwszTitle
;
1037 initialize_purpose_selection(hwnd
);
1038 add_cert_columns(hwnd
);
1039 if (pCryptUICertMgr
->pwszTitle
)
1040 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1041 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
1042 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
, data
);
1043 show_store_certs(hwnd
, cert_mgr_index_to_store(tab
, 0));
1048 NMHDR
*hdr
= (NMHDR
*)lp
;
1053 cert_mgr_clear_cert_selection(hwnd
);
1055 case LVN_ITEMCHANGED
:
1058 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1060 nm
= (NMITEMACTIVATE
*)lp
;
1061 if (nm
->uNewState
& LVN_ITEMACTIVATE
)
1063 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1065 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), numSelected
> 0);
1066 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), numSelected
> 0);
1067 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), numSelected
== 1);
1068 if (numSelected
== 1)
1069 cert_mgr_show_cert_usages(hwnd
, nm
->iItem
);
1074 show_selected_cert(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
1078 NMLVKEYDOWN
*lvk
= (NMLVKEYDOWN
*)lp
;
1080 if (lvk
->wVKey
== VK_DELETE
)
1081 cert_mgr_do_remove(hwnd
);
1090 case ((CBN_SELCHANGE
<< 16) | IDC_MGR_PURPOSE_SELECTION
):
1091 cert_mgr_clear_cert_selection(hwnd
);
1093 case IDC_MGR_IMPORT
:
1094 if (CryptUIWizImport(0, hwnd
, NULL
, NULL
,
1095 cert_mgr_current_store(hwnd
)))
1096 refresh_store_certs(hwnd
);
1098 case IDC_MGR_ADVANCED
:
1099 if (DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR_ADVANCED
),
1100 hwnd
, cert_mgr_advanced_dlg_proc
) == IDOK
)
1102 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
1104 LPWSTR curString
= NULL
;
1106 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
1109 len
= SendMessageW(cb
, CB_GETLBTEXTLEN
, index
, 0);
1110 curString
= HeapAlloc(GetProcessHeap(), 0,
1111 (len
+ 1) * sizeof(WCHAR
));
1112 SendMessageW(cb
, CB_GETLBTEXT
, index
, (LPARAM
)curString
);
1114 SendMessageW(cb
, CB_RESETCONTENT
, 0, 0);
1115 initialize_purpose_selection(hwnd
);
1118 index
= SendMessageW(cb
, CB_FINDSTRINGEXACT
, -1,
1121 SendMessageW(cb
, CB_SETCURSEL
, index
, 0);
1122 HeapFree(GetProcessHeap(), 0, curString
);
1124 refresh_store_certs(hwnd
);
1129 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1130 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1134 show_selected_cert(hwnd
, selection
);
1137 case IDC_MGR_REMOVE
:
1138 cert_mgr_do_remove(hwnd
);
1141 free_certs(GetDlgItem(hwnd
, IDC_MGR_CERTS
));
1142 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1143 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1144 data
= (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1145 ImageList_Destroy(data
->imageList
);
1146 HeapFree(GetProcessHeap(), 0, data
);
1147 EndDialog(hwnd
, IDCANCEL
);
1155 /***********************************************************************
1156 * CryptUIDlgCertMgr (CRYPTUI.@)
1158 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
1160 TRACE("(%p)\n", pCryptUICertMgr
);
1162 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
1164 WARN("unexpected size %d\n", pCryptUICertMgr
->dwSize
);
1165 SetLastError(E_INVALIDARG
);
1168 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
1169 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
1173 /* FIXME: real names are unknown, functions are undocumented */
1174 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
1177 void *pvSystemStoreLocationPara
;
1178 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
1180 typedef struct _CRYPTUI_ENUM_DATA
1183 HCERTSTORE
*rghStore
;
1185 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
1186 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
1188 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
1191 /* Values for dwFlags */
1192 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
1194 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
1201 CRYPTUI_ENUM_DATA
*pEnumData
;
1202 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1204 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
1206 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
1213 CRYPTUI_ENUM_DATA
*pEnumData
;
1214 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1216 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
1230 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
1231 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
1234 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
1235 TVINSERTSTRUCTW tvis
;
1236 LPCWSTR localizedName
;
1239 tvis
.hParent
= NULL
;
1240 tvis
.hInsertAfter
= TVI_LAST
;
1241 tvis
.u
.item
.mask
= TVIF_TEXT
;
1242 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
1244 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(), 0,
1245 sizeof(struct StoreInfo
));
1249 storeInfo
->type
= SystemStore
;
1250 storeInfo
->u
.name
= HeapAlloc(GetProcessHeap(), 0,
1251 (strlenW(pvSystemStore
) + 1) * sizeof(WCHAR
));
1252 if (storeInfo
->u
.name
)
1254 tvis
.u
.item
.mask
|= TVIF_PARAM
;
1255 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1256 strcpyW(storeInfo
->u
.name
, pvSystemStore
);
1260 HeapFree(GetProcessHeap(), 0, storeInfo
);
1266 tvis
.u
.item
.pszText
= (LPWSTR
)localizedName
;
1269 tvis
.u
.item
.pszText
= (LPWSTR
)pvSystemStore
;
1270 /* FIXME: need a folder icon for the store too */
1272 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1276 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
1279 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1281 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
1282 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
1283 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
1284 hwnd
, enum_store_callback
);
1285 for (i
= 0; i
< pEnumData
->cStores
; i
++)
1289 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1290 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
1292 LPWSTR name
= HeapAlloc(GetProcessHeap(), 0, size
);
1296 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1297 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
1299 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(),
1300 0, sizeof(struct StoreInfo
));
1304 TVINSERTSTRUCTW tvis
;
1306 storeInfo
->type
= StoreHandle
;
1307 storeInfo
->u
.store
= pEnumData
->rghStore
[i
];
1308 tvis
.hParent
= NULL
;
1309 tvis
.hInsertAfter
= TVI_LAST
;
1310 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
1311 tvis
.u
.item
.pszText
= name
;
1312 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
1313 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1316 HeapFree(GetProcessHeap(), 0, name
);
1322 static void free_store_info(HWND tree
)
1324 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
1331 memset(&item
, 0, sizeof(item
));
1332 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
1334 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1337 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1339 if (storeInfo
->type
== SystemStore
)
1340 HeapFree(GetProcessHeap(), 0, storeInfo
->u
.name
);
1341 HeapFree(GetProcessHeap(), 0, storeInfo
);
1343 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
1348 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
1350 WCHAR buf
[MAX_STRING_LEN
];
1354 memset(&item
, 0, sizeof(item
));
1355 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
1357 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
1359 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1362 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1364 if (storeInfo
->type
== StoreHandle
)
1365 store
= storeInfo
->u
.store
;
1367 store
= CertOpenSystemStoreW(0, storeInfo
->u
.name
);
1371 /* It's implicitly a system store */
1372 store
= CertOpenSystemStoreW(0, buf
);
1377 struct SelectStoreInfo
1379 PCRYPTUI_SELECTSTORE_INFO_W info
;
1383 static LRESULT CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1386 struct SelectStoreInfo
*selectInfo
;
1393 selectInfo
= (struct SelectStoreInfo
*)lp
;
1394 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
1395 if (selectInfo
->info
->pwszTitle
)
1396 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1397 (LPARAM
)selectInfo
->info
->pwszTitle
);
1398 if (selectInfo
->info
->pwszText
)
1399 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
1400 (LPARAM
)selectInfo
->info
->pwszText
);
1401 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
1402 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
1403 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
1411 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1412 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
1413 TVM_GETNEXTITEM
, TVGN_CARET
, (LPARAM
)NULL
);
1415 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
1419 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
1421 if (selectInfo
->info
->pwszTitle
)
1422 pTitle
= selectInfo
->info
->pwszTitle
;
1425 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
,
1426 sizeof(title
) / sizeof(title
[0]));
1429 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
,
1430 sizeof(error
) / sizeof(error
[0]));
1431 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
1435 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
1437 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
1438 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
1439 selectInfo
->info
->pvArg
))
1441 selectInfo
->store
= store
;
1442 free_store_info(tree
);
1443 EndDialog(hwnd
, IDOK
);
1446 CertCloseStore(store
, 0);
1452 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
1453 EndDialog(hwnd
, IDCANCEL
);
1462 /***********************************************************************
1463 * CryptUIDlgSelectStoreW (CRYPTUI.@)
1465 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
1467 struct SelectStoreInfo selectInfo
= { info
, NULL
};
1469 TRACE("(%p)\n", info
);
1471 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
1473 WARN("unexpected size %d\n", info
->dwSize
);
1474 SetLastError(E_INVALIDARG
);
1477 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
1478 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
1479 return selectInfo
.store
;
1482 /***********************************************************************
1483 * CryptUIDlgSelectStoreA (CRYPTUI.@)
1485 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
1487 CRYPTUI_SELECTSTORE_INFO_W infoW
;
1491 TRACE("(%p)\n", info
);
1493 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
1495 WARN("unexpected size %d\n", info
->dwSize
);
1496 SetLastError(E_INVALIDARG
);
1499 memcpy(&infoW
, &info
, sizeof(info
));
1502 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
1503 infoW
.pwszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1504 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
1509 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
1510 infoW
.pwszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1511 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
1513 ret
= CryptUIDlgSelectStoreW(&infoW
);
1514 HeapFree(GetProcessHeap(), 0, infoW
.pwszText
);
1515 HeapFree(GetProcessHeap(), 0, infoW
.pwszTitle
);
1519 /***********************************************************************
1520 * CryptUIDlgViewCertificateA (CRYPTUI.@)
1522 BOOL WINAPI
CryptUIDlgViewCertificateA(
1523 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
1525 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
1526 LPWSTR title
= NULL
;
1529 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
1531 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
1532 if (pCertViewInfo
->szTitle
)
1534 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
1537 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1540 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
1542 viewInfo
.szTitle
= title
;
1550 if (pCertViewInfo
->cPropSheetPages
)
1552 FIXME("ignoring additional prop sheet pages\n");
1553 viewInfo
.cPropSheetPages
= 0;
1555 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
1556 HeapFree(GetProcessHeap(), 0, title
);
1561 struct ReadStringStruct
1568 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
1571 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
1572 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
1574 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
1576 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
1578 *pcb
= cch
* sizeof(WCHAR
);
1582 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
1584 struct ReadStringStruct string
;
1585 EDITSTREAM editstream
;
1587 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
1592 editstream
.dwCookie
= (DWORD_PTR
)&string
;
1593 editstream
.dwError
= 0;
1594 editstream
.pfnCallback
= read_text_callback
;
1595 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
1596 (LPARAM
)&editstream
);
1599 static void add_string_resource_to_control(HWND hwnd
, int id
)
1604 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1605 add_unformatted_text_to_control(hwnd
, str
, len
);
1608 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
1609 LONG len
, const PARAFORMAT2
*fmt
)
1611 add_unformatted_text_to_control(hwnd
, text
, len
);
1612 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
1615 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
1616 const PARAFORMAT2
*fmt
)
1621 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1622 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
1625 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
1631 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
1634 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1636 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
1641 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
1642 DWORD dwType
, DWORD dwFlags
)
1644 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
1648 /* Don't include NULL-terminator in output */
1649 DWORD len
= lstrlenW(name
);
1651 add_unformatted_text_to_control(hwnd
, name
, len
);
1652 HeapFree(GetProcessHeap(), 0, name
);
1656 static void add_icon_to_control(HWND hwnd
, int id
)
1659 LPRICHEDITOLE richEditOle
= NULL
;
1660 LPOLEOBJECT object
= NULL
;
1662 LPOLECACHE oleCache
= NULL
;
1663 FORMATETC formatEtc
;
1665 LPDATAOBJECT dataObject
= NULL
;
1666 HBITMAP bitmap
= NULL
;
1669 LPOLECLIENTSITE clientSite
= NULL
;
1672 TRACE("(%p, %d)\n", hwnd
, id
);
1674 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
1677 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
1681 hr
= IOleObject_GetUserClassID(object
, &clsid
);
1684 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
1687 formatEtc
.cfFormat
= CF_BITMAP
;
1688 formatEtc
.ptd
= NULL
;
1689 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
1690 formatEtc
.lindex
= -1;
1691 formatEtc
.tymed
= TYMED_GDI
;
1692 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
1695 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
1696 (void**)&dataObject
);
1699 hr
= IRichEditOle_GetClientSite(richEditOle
, &clientSite
);
1702 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
1703 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
1706 rect
.left
= rect
.top
= 0;
1707 rect
.right
= GetSystemMetrics(SM_CXICON
);
1708 rect
.bottom
= GetSystemMetrics(SM_CYICON
);
1709 stgm
.tymed
= TYMED_GDI
;
1710 stgm
.u
.hBitmap
= bitmap
;
1711 stgm
.pUnkForRelease
= NULL
;
1712 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
1716 reObject
.cbStruct
= sizeof(reObject
);
1717 reObject
.cp
= REO_CP_SELECTION
;
1718 reObject
.clsid
= clsid
;
1719 reObject
.poleobj
= object
;
1720 reObject
.pstg
= NULL
;
1721 reObject
.polesite
= clientSite
;
1722 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
1723 reObject
.dvaspect
= DVASPECT_CONTENT
;
1724 reObject
.dwFlags
= 0;
1725 reObject
.dwUser
= 0;
1727 IRichEditOle_InsertObject(richEditOle
, &reObject
);
1731 IOleClientSite_Release(clientSite
);
1733 IDataObject_Release(dataObject
);
1735 IOleCache_Release(oleCache
);
1737 IOleObject_Release(object
);
1739 IRichEditOle_Release(richEditOle
);
1742 #define MY_INDENT 200
1744 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
1747 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
1750 parFmt
.cbSize
= sizeof(parFmt
);
1751 parFmt
.dwMask
= PFM_STARTINDENT
;
1752 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1755 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
1756 lstrlenW(oidInfo
->pwszName
), &parFmt
);
1757 add_unformatted_text_to_control(hwnd
, &nl
, 1);
1767 /* The following list MUST be lexicographically sorted by OID */
1768 static struct OIDToString oidMap
[] = {
1769 /* 1.3.6.1.4.1.311.10.3.1 */
1770 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
1771 /* 1.3.6.1.4.1.311.10.3.4 */
1772 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
1773 /* 1.3.6.1.4.1.311.10.3.4.1 */
1774 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
1775 /* 1.3.6.1.4.1.311.10.3.5 */
1776 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
1777 /* 1.3.6.1.4.1.311.10.3.6 */
1778 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
1779 /* 1.3.6.1.4.1.311.10.3.7 */
1780 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
1781 /* 1.3.6.1.4.1.311.10.3.8 */
1782 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
1783 /* 1.3.6.1.4.1.311.10.3.9 */
1784 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
1785 /* 1.3.6.1.4.1.311.10.3.10 */
1786 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
1787 /* 1.3.6.1.4.1.311.10.3.11 */
1788 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
1789 /* 1.3.6.1.4.1.311.10.3.12 */
1790 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
1791 /* 1.3.6.1.4.1.311.10.3.13 */
1792 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
1793 /* 1.3.6.1.4.1.311.10.5.1 */
1794 { szOID_DRM
, IDS_PURPOSE_DRM
},
1795 /* 1.3.6.1.4.1.311.10.6.1 */
1796 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
1797 /* 1.3.6.1.4.1.311.10.6.2 */
1798 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
1799 /* 1.3.6.1.4.1.311.20.2.1 */
1800 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
1801 /* 1.3.6.1.4.1.311.20.2.2 */
1802 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
1803 /* 1.3.6.1.4.1.311.21.5 */
1804 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
1805 /* 1.3.6.1.4.1.311.21.6 */
1806 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
1807 /* 1.3.6.1.4.1.311.21.19 */
1808 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
1809 /* 1.3.6.1.5.5.7.3.1 */
1810 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
1811 /* 1.3.6.1.5.5.7.3.2 */
1812 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
1813 /* 1.3.6.1.5.5.7.3.3 */
1814 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
1815 /* 1.3.6.1.5.5.7.3.4 */
1816 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
1817 /* 1.3.6.1.5.5.7.3.5 */
1818 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
1819 /* 1.3.6.1.5.5.7.3.6 */
1820 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
1821 /* 1.3.6.1.5.5.7.3.7 */
1822 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
1823 /* 1.3.6.1.5.5.7.3.8 */
1824 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
1827 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
1829 int indexHigh
= sizeof(oidMap
) / sizeof(oidMap
[0]) - 1, indexLow
= 0, i
;
1830 struct OIDToString
*ret
= NULL
;
1832 for (i
= (indexLow
+ indexHigh
) / 2; !ret
&& indexLow
<= indexHigh
;
1833 i
= (indexLow
+ indexHigh
) / 2)
1837 cmp
= strcmp(oid
, oidMap
[i
].oid
);
1848 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
1850 struct OIDToString
*entry
;
1854 parFmt
.cbSize
= sizeof(parFmt
);
1855 parFmt
.dwMask
= PFM_STARTINDENT
;
1856 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1857 if ((entry
= findSupportedOID(oid
)))
1859 WCHAR
*str
, *linebreak
, *ptr
;
1860 BOOL multiline
= FALSE
;
1863 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
1866 if ((linebreak
= memchrW(ptr
, '\n', len
)))
1868 WCHAR copy
[MAX_STRING_LEN
];
1871 /* The source string contains a newline, which the richedit
1872 * control won't find since it's interpreted as a paragraph
1873 * break. Therefore copy up to the newline. lstrcpynW always
1874 * NULL-terminates, so pass one more than the length of the
1875 * source line so the copy includes the entire line and the
1878 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
1879 add_text_with_paraformat_to_control(text
, copy
,
1880 linebreak
- ptr
, &parFmt
);
1881 ptr
= linebreak
+ 1;
1882 add_unformatted_text_to_control(text
, &nl
, 1);
1884 else if (multiline
&& *ptr
)
1886 /* Add the last line */
1887 add_text_with_paraformat_to_control(text
, ptr
,
1888 len
- (ptr
- str
), &parFmt
);
1889 add_unformatted_text_to_control(text
, &nl
, 1);
1891 } while (linebreak
);
1894 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
1895 add_unformatted_text_to_control(text
, &nl
, 1);
1900 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
1901 (strlen(oid
) + 1) * sizeof(WCHAR
));
1908 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
1911 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
1913 add_unformatted_text_to_control(text
, &nl
, 1);
1914 HeapFree(GetProcessHeap(), 0, oidW
);
1919 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
1920 BOOL
*anyUsageAdded
)
1922 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
1924 CHARFORMATW charFmt
;
1925 PCERT_EXTENSION policyExt
;
1926 if (!*anyUsageAdded
)
1930 parFmt
.cbSize
= sizeof(parFmt
);
1931 parFmt
.dwMask
= PFM_STARTINDENT
;
1932 parFmt
.dxStartIndent
= MY_INDENT
;
1933 add_string_resource_with_paraformat_to_control(text
,
1934 IDS_CERT_INFO_PURPOSES
, &parFmt
);
1935 add_unformatted_text_to_control(text
, &nl
, 1);
1936 *anyUsageAdded
= TRUE
;
1938 memset(&charFmt
, 0, sizeof(charFmt
));
1939 charFmt
.cbSize
= sizeof(charFmt
);
1940 charFmt
.dwMask
= CFM_BOLD
;
1941 charFmt
.dwEffects
= 0;
1942 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1943 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
1944 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
1946 CERT_POLICIES_INFO
*policies
;
1949 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
1950 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
1951 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
1955 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
1959 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
1960 add_local_oid_text_to_control(text
,
1961 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
1962 pszPolicyQualifierId
);
1964 LocalFree(policies
);
1968 add_oid_text_to_control(text
, any_app_policy
);
1971 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
1972 BOOL
*anyUsageAdded
)
1976 BOOL badUsages
= FALSE
;
1978 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
1980 CHARFORMATW charFmt
;
1981 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
1982 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
1986 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
1990 if (!*anyUsageAdded
)
1994 parFmt
.cbSize
= sizeof(parFmt
);
1995 parFmt
.dwMask
= PFM_STARTINDENT
;
1996 parFmt
.dxStartIndent
= MY_INDENT
;
1997 add_string_resource_with_paraformat_to_control(text
,
1998 IDS_CERT_INFO_PURPOSES
, &parFmt
);
1999 add_unformatted_text_to_control(text
, &nl
, 1);
2000 *anyUsageAdded
= TRUE
;
2002 memset(&charFmt
, 0, sizeof(charFmt
));
2003 charFmt
.cbSize
= sizeof(charFmt
);
2004 charFmt
.dwMask
= CFM_BOLD
;
2005 charFmt
.dwEffects
= 0;
2006 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
2008 if (!usage
->cUsageIdentifier
)
2009 add_oid_text_to_control(text
, any_cert_policy
);
2011 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2012 add_local_oid_text_to_control(text
,
2013 usage
->rgpszUsageIdentifier
[i
]);
2017 HeapFree(GetProcessHeap(), 0, usage
);
2027 static void set_policy_text(HWND text
,
2028 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2030 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
2031 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
2033 if (pCertViewInfo
->cPurposes
)
2037 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
2039 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
2040 includeCertUsages
= TRUE
;
2041 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
2042 szOID_ANY_APPLICATION_POLICY
))
2043 includeAppUsages
= TRUE
;
2049 includeAppUsages
= includeCertUsages
= TRUE
;
2050 if (includeAppUsages
)
2051 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
2052 if (includeCertUsages
)
2053 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
2059 parFmt
.cbSize
= sizeof(parFmt
);
2060 parFmt
.dwMask
= PFM_STARTINDENT
;
2061 parFmt
.dxStartIndent
= MY_INDENT
;
2062 add_string_resource_with_paraformat_to_control(text
,
2063 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
2067 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
2070 CRYPT_OBJID_BLOB
*ret
= NULL
;
2073 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
2077 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2078 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2079 pszPolicyQualifierId
, policyOid
))
2080 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2086 static WCHAR
*get_cps_str_from_qualifier(CRYPT_OBJID_BLOB
*qualifier
)
2088 LPWSTR qualifierStr
= NULL
;
2089 CERT_NAME_VALUE
*qualifierValue
;
2092 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
2093 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2094 &qualifierValue
, &size
))
2096 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
2097 &qualifierValue
->Value
, NULL
, 0);
2098 qualifierStr
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
2100 CertRDNValueToStrW(qualifierValue
->dwValueType
,
2101 &qualifierValue
->Value
, qualifierStr
, size
);
2102 LocalFree(qualifierValue
);
2104 return qualifierStr
;
2107 static WCHAR
*get_user_notice_from_qualifier(CRYPT_OBJID_BLOB
*qualifier
)
2110 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
2113 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
2114 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
2115 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2116 &qualifierValue
, &size
))
2118 str
= HeapAlloc(GetProcessHeap(), 0,
2119 (strlenW(qualifierValue
->pszDisplayText
) + 1) * sizeof(WCHAR
));
2121 strcpyW(str
, qualifierValue
->pszDisplayText
);
2122 LocalFree(qualifierValue
);
2127 struct IssuerStatement
2133 static void set_issuer_statement(HWND hwnd
,
2134 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2136 PCERT_EXTENSION policyExt
;
2138 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
2139 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
2140 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
2141 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
2143 CERT_POLICIES_INFO
*policies
;
2146 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
2147 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2148 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2150 CRYPT_OBJID_BLOB
*qualifier
;
2151 LPWSTR cps
= NULL
, userNotice
= NULL
;
2153 if ((qualifier
= find_policy_qualifier(policies
,
2154 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
2155 cps
= get_cps_str_from_qualifier(qualifier
);
2156 if ((qualifier
= find_policy_qualifier(policies
,
2157 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
2158 userNotice
= get_user_notice_from_qualifier(qualifier
);
2159 if (cps
|| userNotice
)
2161 struct IssuerStatement
*issuerStatement
=
2162 HeapAlloc(GetProcessHeap(), 0, sizeof(struct IssuerStatement
));
2164 if (issuerStatement
)
2166 issuerStatement
->cps
= cps
;
2167 issuerStatement
->userNotice
= userNotice
;
2168 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
2169 SetWindowLongPtrW(hwnd
, DWLP_USER
,
2170 (ULONG_PTR
)issuerStatement
);
2173 LocalFree(policies
);
2178 static void set_cert_info(HWND hwnd
,
2179 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2181 CHARFORMATW charFmt
;
2183 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
2184 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
2185 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2186 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
2187 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
2188 pCertViewInfo
->idxCounterSigner
);
2189 CRYPT_PROVIDER_CERT
*root
=
2190 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
2192 if (!provSigner
->pChainContext
||
2193 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2194 CERT_TRUST_IS_PARTIAL_CHAIN
))
2195 add_icon_to_control(icon
, IDB_CERT_WARNING
);
2196 else if (!root
->fTrustedRoot
)
2197 add_icon_to_control(icon
, IDB_CERT_ERROR
);
2199 add_icon_to_control(icon
, IDB_CERT
);
2201 memset(&charFmt
, 0, sizeof(charFmt
));
2202 charFmt
.cbSize
= sizeof(charFmt
);
2203 charFmt
.dwMask
= CFM_BOLD
;
2204 charFmt
.dwEffects
= CFE_BOLD
;
2205 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2206 /* FIXME: vertically center text */
2207 parFmt
.cbSize
= sizeof(parFmt
);
2208 parFmt
.dwMask
= PFM_STARTINDENT
;
2209 parFmt
.dxStartIndent
= MY_INDENT
;
2210 add_string_resource_with_paraformat_to_control(text
,
2211 IDS_CERTIFICATEINFORMATION
, &parFmt
);
2213 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
2214 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2215 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
2216 add_string_resource_with_paraformat_to_control(text
,
2217 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
2218 else if (!provSigner
->pChainContext
||
2219 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2220 CERT_TRUST_IS_PARTIAL_CHAIN
))
2221 add_string_resource_with_paraformat_to_control(text
,
2222 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
2223 else if (!root
->fTrustedRoot
)
2225 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
2226 add_string_resource_with_paraformat_to_control(text
,
2227 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
2229 add_string_resource_with_paraformat_to_control(text
,
2230 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
2234 set_policy_text(text
, pCertViewInfo
);
2235 set_issuer_statement(hwnd
, pCertViewInfo
);
2239 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
2240 DWORD nameFlags
, int heading
)
2243 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2244 CHARFORMATW charFmt
;
2247 memset(&charFmt
, 0, sizeof(charFmt
));
2248 charFmt
.cbSize
= sizeof(charFmt
);
2249 charFmt
.dwMask
= CFM_BOLD
;
2250 charFmt
.dwEffects
= CFE_BOLD
;
2251 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2252 parFmt
.cbSize
= sizeof(parFmt
);
2253 parFmt
.dwMask
= PFM_STARTINDENT
;
2254 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2255 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
2256 charFmt
.dwEffects
= 0;
2257 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2258 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2260 add_unformatted_text_to_control(text
, &nl
, 1);
2261 add_unformatted_text_to_control(text
, &nl
, 1);
2262 add_unformatted_text_to_control(text
, &nl
, 1);
2266 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
2268 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
2272 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
2273 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2274 FileTimeToSystemTime(fileTime
, &sysTime
);
2275 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
2276 sizeof(date
) / sizeof(date
[0]));
2277 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
2280 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
2283 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2284 CHARFORMATW charFmt
;
2287 memset(&charFmt
, 0, sizeof(charFmt
));
2288 charFmt
.cbSize
= sizeof(charFmt
);
2289 charFmt
.dwMask
= CFM_BOLD
;
2290 charFmt
.dwEffects
= CFE_BOLD
;
2291 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2292 parFmt
.cbSize
= sizeof(parFmt
);
2293 parFmt
.dwMask
= PFM_STARTINDENT
;
2294 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2295 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
2297 charFmt
.dwEffects
= 0;
2298 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2299 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
2300 charFmt
.dwEffects
= CFE_BOLD
;
2301 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2302 add_string_resource_to_control(text
, IDS_VALID_TO
);
2303 charFmt
.dwEffects
= 0;
2304 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2305 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
2306 add_unformatted_text_to_control(text
, &nl
, 1);
2309 static void set_general_info(HWND hwnd
,
2310 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2312 set_cert_info(hwnd
, pCertViewInfo
);
2313 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
2314 IDS_SUBJECT_HEADING
);
2315 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
2316 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
2317 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
2320 static LRESULT CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2325 struct IssuerStatement
*issuerStatement
;
2330 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
2331 issuerStatement
= (struct IssuerStatement
*)lp
;
2332 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
2333 strlenW(issuerStatement
->userNotice
));
2334 if (issuerStatement
->cps
)
2335 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
2337 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
2343 EndDialog(hwnd
, IDOK
);
2348 IBindCtx
*bctx
= NULL
;
2351 CreateBindCtx(0, &bctx
);
2352 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2353 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
2354 HLNF_OPENINNEWWINDOW
, 0);
2355 IBindCtx_Release(bctx
);
2363 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
2365 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
2366 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
2369 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2372 PROPSHEETPAGEW
*page
;
2373 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2375 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2380 page
= (PROPSHEETPAGEW
*)lp
;
2381 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
2382 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
2383 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
2384 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
2385 set_general_info(hwnd
, pCertViewInfo
);
2390 case IDC_ADDTOSTORE
:
2391 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
2393 case IDC_ISSUERSTATEMENT
:
2395 struct IssuerStatement
*issuerStatement
=
2396 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2398 if (issuerStatement
)
2400 if (issuerStatement
->userNotice
)
2401 show_user_notice(hwnd
, issuerStatement
);
2402 else if (issuerStatement
->cps
)
2404 IBindCtx
*bctx
= NULL
;
2406 CreateBindCtx(0, &bctx
);
2407 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
2408 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
2409 IBindCtx_Release(bctx
);
2420 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
2421 PROPSHEETPAGEW
*page
)
2423 struct IssuerStatement
*issuerStatement
;
2429 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2430 if (issuerStatement
)
2432 HeapFree(GetProcessHeap(), 0, issuerStatement
->cps
);
2433 HeapFree(GetProcessHeap(), 0, issuerStatement
->userNotice
);
2434 HeapFree(GetProcessHeap(), 0, issuerStatement
);
2441 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2442 PROPSHEETPAGEW
*page
)
2444 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2445 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2446 page
->dwFlags
= PSP_USECALLBACK
;
2447 page
->pfnCallback
= general_callback_proc
;
2448 page
->hInstance
= hInstance
;
2449 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
2450 page
->pfnDlgProc
= general_dlg_proc
;
2451 page
->lParam
= (LPARAM
)pCertViewInfo
;
2454 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
2456 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
2458 static const WCHAR fmt
[] = { 'V','%','d',0 };
2459 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, 12 * sizeof(WCHAR
));
2462 sprintfW(buf
, fmt
, cert
->pCertInfo
->dwVersion
);
2466 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
2468 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, (cb
* 3 + 1) * sizeof(WCHAR
));
2472 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2476 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
2477 sprintfW(ptr
, fmt
, ((BYTE
*)pb
)[i
]);
2482 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
2484 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
2485 cert
->pCertInfo
->SerialNumber
.cbData
);
2488 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
2490 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2491 CERT_NAME_ISSUER_FLAG
);
2494 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
2497 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
2498 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, NULL
, 0);
2502 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2504 CertNameToStrW(X509_ASN_ENCODING
, name
,
2505 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, str
, len
);
2510 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
2512 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
2515 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
2517 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2520 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
2522 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
2525 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
2527 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
2532 /* FIXME: format isn't quite right, want time too */
2533 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
,
2534 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
2535 FileTimeToSystemTime(fileTime
, &sysTime
);
2536 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
2539 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2541 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
2547 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
2549 return format_long_date(&cert
->pCertInfo
->NotBefore
);
2552 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
2554 return format_long_date(&cert
->pCertInfo
->NotAfter
);
2557 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
2559 PCCRYPT_OID_INFO oidInfo
;
2562 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2563 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
2566 WCHAR fmt
[MAX_STRING_LEN
];
2568 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
,
2569 sizeof(fmt
) / sizeof(fmt
[0])))
2571 /* Allocate the output buffer. Use the number of bytes in the
2572 * public key as a conservative (high) estimate for the number of
2573 * digits in its output.
2574 * The output is of the form (in English)
2575 * "<public key algorithm> (<public key bit length> bits)".
2576 * Ordinarily having two positional parameters in a string is not a
2577 * good idea, but as this isn't a sentence fragment, it shouldn't
2578 * be word-order dependent.
2580 buf
= HeapAlloc(GetProcessHeap(), 0,
2581 (strlenW(fmt
) + strlenW(oidInfo
->pwszName
) +
2582 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8)
2585 sprintfW(buf
, fmt
, oidInfo
->pwszName
,
2586 CertGetPublicKeyLength(X509_ASN_ENCODING
,
2587 &cert
->pCertInfo
->SubjectPublicKeyInfo
));
2593 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
2595 return format_hex_string(
2596 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
2597 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
2600 struct field_value_data
;
2603 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2604 BOOL
*pfPropertiesChanged
;
2606 struct field_value_data
*fields
;
2609 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
2611 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
2613 struct field_value_data
2615 create_detailed_value_func create
;
2616 LPWSTR detailed_value
;
2620 static void add_field_value_data(struct detail_data
*data
,
2621 create_detailed_value_func create
, void *param
)
2624 data
->fields
= HeapReAlloc(GetProcessHeap(), 0, data
->fields
,
2625 (data
->cFields
+ 1) * sizeof(struct field_value_data
));
2627 data
->fields
= HeapAlloc(GetProcessHeap(), 0,
2628 sizeof(struct field_value_data
));
2631 data
->fields
[data
->cFields
].create
= create
;
2632 data
->fields
[data
->cFields
].detailed_value
= NULL
;
2633 data
->fields
[data
->cFields
].param
= param
;
2638 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2639 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2642 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2644 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
2647 item
.pszText
= field
;
2648 item
.lParam
= (LPARAM
)data
;
2649 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2652 item
.pszText
= value
;
2654 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
2656 add_field_value_data(data
, create
, param
);
2659 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2660 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2662 WCHAR buf
[MAX_STRING_LEN
];
2664 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2665 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
2671 field_format_func format
;
2672 create_detailed_value_func create_detailed_value
;
2675 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
2676 const struct v1_field
*field
)
2678 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
2682 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
2683 field
->create_detailed_value
, NULL
);
2684 HeapFree(GetProcessHeap(), 0, val
);
2688 static const struct v1_field v1_fields
[] = {
2689 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
2690 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
2691 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
2692 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
2693 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
2694 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
2695 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
2696 field_format_detailed_public_key
}
2699 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
2702 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2704 /* The last item in v1_fields is the public key, which is not in the loop
2705 * because it's a special case.
2707 for (i
= 0; i
< sizeof(v1_fields
) / sizeof(v1_fields
[0]) - 1; i
++)
2708 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2709 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
2710 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2713 static WCHAR
*crypt_format_extension(PCERT_EXTENSION ext
, DWORD formatStrType
)
2718 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2719 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
2721 str
= HeapAlloc(GetProcessHeap(), 0, size
);
2722 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2723 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
2728 static WCHAR
*field_format_extension_hex_with_ascii(PCERT_EXTENSION ext
)
2732 if (ext
->Value
.cbData
)
2734 /* The output is formatted as:
2735 * <hex bytes> <ascii bytes>\n
2736 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
2737 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
2738 * the byte is not printable.
2739 * So, for example, the extension value consisting of the following
2741 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
2742 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
2744 * 30 14 31 12 30 10 06 03 0.1.0...
2745 * 55 04 03 13 09 4a 75 61 U....Jua
2746 * 6e 20 4c 61 6e 67 n Lang
2747 * The allocation size therefore requires:
2748 * - 4 characters per character in an 8-byte line
2749 * (2 for the hex format, one for the space, one for the ASCII value)
2750 * - 3 more characters per 8-byte line (two spaces and a newline)
2751 * - 1 character for the terminating nul
2752 * FIXME: should use a fixed-width font for this
2754 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
2756 str
= HeapAlloc(GetProcessHeap(), 0,
2757 (lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
2760 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2764 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
2766 /* Output as hex bytes first */
2767 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
2768 sprintfW(ptr
, fmt
, ext
->Value
.pbData
[j
]);
2769 /* Pad the hex output with spaces for alignment */
2770 if (j
== ext
->Value
.cbData
&& j
% 8)
2772 static const WCHAR pad
[] = { ' ',' ',' ' };
2774 for (; j
% 8; j
++, ptr
+= sizeof(pad
) / sizeof(pad
[0]))
2775 memcpy(ptr
, pad
, sizeof(pad
));
2777 /* The last sprintfW included a space, so just insert one
2778 * more space between the hex bytes and the ASCII output
2781 /* Output as ASCII bytes */
2782 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
2784 if (isprintW(ext
->Value
.pbData
[j
]) &&
2785 !isspaceW(ext
->Value
.pbData
[j
]))
2786 *ptr
= ext
->Value
.pbData
[j
];
2798 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
2800 PCERT_EXTENSION ext
= param
;
2801 LPWSTR str
= crypt_format_extension(ext
,
2802 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
2805 str
= field_format_extension_hex_with_ascii(ext
);
2809 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
2810 PCERT_EXTENSION ext
)
2812 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2814 LPWSTR val
= crypt_format_extension(ext
, 0);
2817 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
2818 val
, field_format_detailed_extension
, ext
);
2821 DWORD len
= strlen(ext
->pszObjId
);
2822 LPWSTR oidW
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
2828 for (i
= 0; i
<= len
; i
++)
2829 oidW
[i
] = ext
->pszObjId
[i
];
2830 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
2831 field_format_detailed_extension
, ext
);
2832 HeapFree(GetProcessHeap(), 0, oidW
);
2835 HeapFree(GetProcessHeap(), 0, val
);
2838 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
2841 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2843 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2844 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
2847 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
2850 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2852 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2853 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
2854 add_cert_extension_detail(hwnd
, data
,
2855 &cert
->pCertInfo
->rgExtension
[i
]);
2858 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
2860 struct prop_id_to_string_id
2864 BOOL prop_is_string
;
2865 prop_to_value_func prop_to_value
;
2868 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
2872 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
2873 ext
.fCritical
= FALSE
;
2874 ext
.Value
.pbData
= pb
;
2875 ext
.Value
.cbData
= cb
;
2876 return crypt_format_extension(&ext
, 0);
2879 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
2880 * disabled for read-only certificates, but native doesn't appear to do that.
2882 static const struct prop_id_to_string_id prop_id_map
[] = {
2883 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
2884 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
2885 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
2886 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
2887 format_enhanced_key_usage_value
},
2890 static void add_properties(HWND hwnd
, struct detail_data
*data
)
2893 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2895 for (i
= 0; i
< sizeof(prop_id_map
) / sizeof(prop_id_map
[0]); i
++)
2899 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
2905 /* FIXME: MS adds a separate value for the signature hash
2908 pb
= HeapAlloc(GetProcessHeap(), 0, cb
);
2911 if (CertGetCertificateContextProperty(cert
,
2912 prop_id_map
[i
].prop
, pb
, &cb
))
2914 if (prop_id_map
[i
].prop_is_string
)
2917 /* Don't double-free pb */
2921 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
2923 HeapFree(GetProcessHeap(), 0, pb
);
2925 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
2931 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
2933 add_v1_fields(hwnd
, data
);
2934 add_all_extensions(hwnd
, data
);
2935 add_properties(hwnd
, data
);
2938 struct selection_list_item
2941 add_fields_func add
;
2944 const struct selection_list_item listItems
[] = {
2945 { IDS_FIELDS_ALL
, add_all_fields
},
2946 { IDS_FIELDS_V1
, add_v1_fields
},
2947 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
2948 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
2949 { IDS_FIELDS_PROPERTIES
, add_properties
},
2952 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
2954 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
2955 WCHAR buf
[MAX_STRING_LEN
];
2958 for (i
= 0; i
< sizeof(listItems
) / sizeof(listItems
[0]); i
++)
2962 LoadStringW(hInstance
, listItems
[i
].id
, buf
,
2963 sizeof(buf
) / sizeof(buf
[0]));
2964 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
2965 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
2967 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
2970 static void create_listview_columns(HWND hwnd
)
2972 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
2974 WCHAR buf
[MAX_STRING_LEN
];
2977 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
2978 GetWindowRect(lv
, &rc
);
2979 LoadStringW(hInstance
, IDS_FIELD
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2980 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
2981 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
2982 column
.pszText
= buf
;
2983 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
2984 LoadStringW(hInstance
, IDS_VALUE
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2985 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
2988 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
2990 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
2992 if (sel
>= 0 && sel
< sizeof(listItems
) / sizeof(listItems
[0]))
2994 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
2995 listItems
[sel
].add(list
, data
);
2999 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
3001 create_show_list(hwnd
, data
);
3002 create_listview_columns(hwnd
);
3003 set_fields_selection(hwnd
, data
, 0);
3006 static void add_purpose(HWND hwnd
, LPCSTR oid
)
3008 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3009 PCRYPT_OID_INFO info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3010 sizeof(CRYPT_OID_INFO
));
3014 char *oidCopy
= HeapAlloc(GetProcessHeap(), 0, strlen(oid
) + 1);
3020 strcpy(oidCopy
, oid
);
3021 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
3022 info
->pszOID
= oidCopy
;
3023 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
3024 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
3025 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3026 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3028 item
.lParam
= (LPARAM
)info
;
3029 item
.pszText
= oidCopy
;
3030 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3033 HeapFree(GetProcessHeap(), 0, info
);
3037 static BOOL
is_valid_oid(LPCSTR oid
)
3041 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
3043 else if (oid
[1] != '.')
3050 BOOL expectNum
= TRUE
;
3052 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
3058 else if (*(ptr
+ 1) == '.')
3065 else if (!(*(ptr
+ 1)))
3075 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
3077 return find_oid_in_list(GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
), oid
)
3081 #define MAX_PURPOSE 255
3083 static LRESULT CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
3084 WPARAM wp
, LPARAM lp
)
3087 char buf
[MAX_PURPOSE
+ 1];
3092 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
3094 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
3095 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
3101 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
3103 /* Show/hide scroll bar on description depending on how much
3106 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
3107 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3109 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3116 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
,
3117 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3120 /* An empty purpose is the same as cancelling */
3121 EndDialog(hwnd
, IDCANCEL
);
3124 else if (!is_valid_oid(buf
))
3126 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3128 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
,
3129 sizeof(error
) / sizeof(error
[0]));
3130 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3131 sizeof(title
) / sizeof(title
[0]));
3132 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
3134 else if (is_oid_in_list(
3135 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
3137 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3139 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
,
3140 error
, sizeof(error
) / sizeof(error
[0]));
3141 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
3142 sizeof(title
) / sizeof(title
[0]));
3143 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
3147 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3149 add_purpose(parent
, buf
);
3150 EndDialog(hwnd
, wp
);
3155 EndDialog(hwnd
, wp
);
3166 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
3171 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
3173 name
= HeapAlloc(GetProcessHeap(), 0, cb
);
3176 if (!CertGetCertificateContextProperty(cert
, prop
, (LPBYTE
)name
,
3179 HeapFree(GetProcessHeap(), 0, name
);
3187 static void redraw_states(HWND list
, BOOL enabled
)
3189 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
3191 for (i
= 0; i
< items
; i
++)
3193 BOOL change
= FALSE
;
3196 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
3197 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
3198 * to be a handy macro for it.
3203 if (state
== CheckBitmapIndexDisabledChecked
)
3205 state
= CheckBitmapIndexChecked
;
3208 if (state
== CheckBitmapIndexDisabledUnchecked
)
3210 state
= CheckBitmapIndexUnchecked
;
3216 if (state
== CheckBitmapIndexChecked
)
3218 state
= CheckBitmapIndexDisabledChecked
;
3221 if (state
== CheckBitmapIndexUnchecked
)
3223 state
= CheckBitmapIndexDisabledUnchecked
;
3231 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
3232 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3233 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
3239 PurposeEnableAll
= 0,
3241 PurposeEnableSelected
3244 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
3246 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3250 case PurposeEnableAll
:
3251 case PurposeDisableAll
:
3252 EnableWindow(lv
, FALSE
);
3253 redraw_states(lv
, FALSE
);
3254 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
3256 case PurposeEnableSelected
:
3257 EnableWindow(lv
, TRUE
);
3258 redraw_states(lv
, TRUE
);
3259 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
3263 struct edit_cert_data
3265 PCCERT_CONTEXT cert
;
3266 BOOL
*pfPropertiesChanged
;
3267 HIMAGELIST imageList
;
3270 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
3272 PCCERT_CONTEXT cert
= data
->cert
;
3273 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3274 PCERT_ENHKEY_USAGE usage
;
3278 PurposeSelection purposeSelection
;
3280 GetWindowRect(lv
, &rc
);
3281 column
.mask
= LVCF_WIDTH
;
3282 column
.cx
= rc
.right
- rc
.left
;
3283 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3284 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
3286 /* Get enhanced key usage. Have to check for a property and an extension
3287 * separately, because CertGetEnhancedKeyUsage will succeed and return an
3288 * empty usage if neither is set. Unfortunately an empty usage implies
3289 * no usage is allowed, so we have to distinguish between the two cases.
3291 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
3294 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3295 if (!CertGetEnhancedKeyUsage(cert
,
3296 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3298 HeapFree(GetProcessHeap(), 0, usage
);
3301 else if (usage
->cUsageIdentifier
)
3302 purposeSelection
= PurposeEnableSelected
;
3304 purposeSelection
= PurposeDisableAll
;
3306 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
3309 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
3310 if (!CertGetEnhancedKeyUsage(cert
,
3311 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3313 HeapFree(GetProcessHeap(), 0, usage
);
3316 else if (usage
->cUsageIdentifier
)
3317 purposeSelection
= PurposeEnableAll
;
3319 purposeSelection
= PurposeDisableAll
;
3323 purposeSelection
= PurposeEnableAll
;
3330 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
3332 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
3333 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
3336 add_known_usage(lv
, info
, CheckBitmapIndexDisabledChecked
);
3338 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
3340 HeapFree(GetProcessHeap(), 0, usage
);
3343 add_known_usages_to_list(lv
, CheckBitmapIndexDisabledChecked
);
3344 select_purposes(hwnd
, purposeSelection
);
3345 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
3349 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
3351 PCCERT_CONTEXT cert
= data
->cert
;
3354 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
3356 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
3358 HeapFree(GetProcessHeap(), 0, str
);
3360 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
3362 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
3364 HeapFree(GetProcessHeap(), 0, str
);
3366 show_cert_usages(hwnd
, data
);
3369 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
3372 if (str
&& strlenW(str
))
3374 CRYPT_DATA_BLOB blob
;
3376 blob
.pbData
= (BYTE
*)str
;
3377 blob
.cbData
= (strlenW(str
) + 1) * sizeof(WCHAR
);
3378 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
3381 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
3384 #define WM_REFRESH_VIEW WM_USER + 0
3386 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
3388 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
3389 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
3393 #define MAX_FRIENDLY_NAME 40
3394 #define MAX_DESCRIPTION 255
3396 static void apply_general_changes(HWND hwnd
)
3398 WCHAR buf
[MAX_DESCRIPTION
+ 1];
3399 struct edit_cert_data
*data
=
3400 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3402 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
,
3403 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3404 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
3405 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
,
3406 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
3407 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
3408 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
3410 /* Setting a NULL usage removes the enhanced key usage property. */
3411 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
3413 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
3415 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3417 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3419 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
3421 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3422 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3423 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
3426 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3428 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3429 for (i
= 0; i
< purposes
; i
++)
3432 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
3434 int state
= item
.state
>> 12;
3436 if (state
== CheckBitmapIndexChecked
)
3438 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
3440 if (usage
.cUsageIdentifier
)
3441 usage
.rgpszUsageIdentifier
=
3442 HeapReAlloc(GetProcessHeap(), 0,
3443 usage
.rgpszUsageIdentifier
,
3444 (usage
.cUsageIdentifier
+ 1) * sizeof(LPSTR
));
3446 usage
.rgpszUsageIdentifier
=
3447 HeapAlloc(GetProcessHeap(), 0, sizeof(LPSTR
));
3448 if (usage
.rgpszUsageIdentifier
)
3449 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
3450 (LPSTR
)info
->pszOID
;
3454 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3455 HeapFree(GetProcessHeap(), 0, usage
.rgpszUsageIdentifier
);
3457 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
3458 if (data
->pfPropertiesChanged
)
3459 *data
->pfPropertiesChanged
= TRUE
;
3462 static LRESULT CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
3463 WPARAM wp
, LPARAM lp
)
3465 PROPSHEETPAGEW
*page
;
3467 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3473 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3474 struct detail_data
*detailData
;
3475 struct edit_cert_data
*editData
;
3477 page
= (PROPSHEETPAGEW
*)lp
;
3478 detailData
= (struct detail_data
*)page
->lParam
;
3479 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
3480 MAX_FRIENDLY_NAME
, 0);
3481 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
3482 ShowScrollBar(description
, SB_VERT
, FALSE
);
3483 editData
= HeapAlloc(GetProcessHeap(), 0,
3484 sizeof(struct edit_cert_data
));
3487 editData
->imageList
= ImageList_Create(16, 16,
3488 ILC_COLOR4
| ILC_MASK
, 4, 0);
3489 if (editData
->imageList
)
3492 COLORREF backColor
= RGB(255, 0, 255);
3494 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
3495 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
3497 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
3499 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
3500 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
3501 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
3502 set_general_cert_properties(hwnd
, editData
);
3508 NMHDR
*hdr
= (NMHDR
*)lp
;
3514 nm
= (NMITEMACTIVATE
*)lp
;
3515 toggle_usage(hwnd
, nm
->iItem
);
3516 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3519 apply_general_changes(hwnd
);
3528 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3529 if (LOWORD(wp
) == IDC_DESCRIPTION
)
3531 /* Show/hide scroll bar on description depending on how much
3534 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3535 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3537 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3543 case IDC_ADD_PURPOSE
:
3544 if (DialogBoxParamW(hInstance
,
3545 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
3546 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
3547 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3549 case IDC_ENABLE_ALL_PURPOSES
:
3550 case IDC_DISABLE_ALL_PURPOSES
:
3551 case IDC_ENABLE_SELECTED_PURPOSES
:
3552 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3553 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
3563 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
3564 PROPSHEETPAGEW
*page
)
3568 struct edit_cert_data
*data
;
3573 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3574 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3575 for (i
= 0; i
< cItem
; i
++)
3579 item
.mask
= LVIF_PARAM
;
3582 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
3584 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
3586 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
3588 HeapFree(GetProcessHeap(), 0, (LPSTR
)info
->pszOID
);
3589 HeapFree(GetProcessHeap(), 0, info
);
3593 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3596 ImageList_Destroy(data
->imageList
);
3597 HeapFree(GetProcessHeap(), 0, data
);
3604 static void show_edit_cert_properties_dialog(HWND parent
,
3605 struct detail_data
*data
)
3607 PROPSHEETHEADERW hdr
;
3608 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
3610 TRACE("(%p)\n", data
);
3612 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
3613 page
.dwSize
= sizeof(page
);
3614 page
.dwFlags
= PSP_USECALLBACK
;
3615 page
.pfnCallback
= cert_properties_general_callback
;
3616 page
.hInstance
= hInstance
;
3617 page
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
3618 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
3619 page
.lParam
= (LPARAM
)data
;
3621 memset(&hdr
, 0, sizeof(hdr
));
3622 hdr
.dwSize
= sizeof(hdr
);
3623 hdr
.hwndParent
= parent
;
3624 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
3625 hdr
.hInstance
= hInstance
;
3626 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
3627 hdr
.u3
.ppsp
= &page
;
3629 PropertySheetW(&hdr
);
3632 static void free_detail_fields(struct detail_data
*data
)
3636 for (i
= 0; i
< data
->cFields
; i
++)
3637 HeapFree(GetProcessHeap(), 0, data
->fields
[i
].detailed_value
);
3638 HeapFree(GetProcessHeap(), 0, data
->fields
);
3639 data
->fields
= NULL
;
3643 static void refresh_details_view(HWND hwnd
)
3645 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3647 struct detail_data
*data
;
3649 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3650 /* Actually, any index will do, since they all store the same data value */
3651 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
3652 free_detail_fields(data
);
3653 set_fields_selection(hwnd
, data
, curSel
);
3656 static LRESULT CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3659 PROPSHEETPAGEW
*page
;
3660 struct detail_data
*data
;
3662 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3667 page
= (PROPSHEETPAGEW
*)lp
;
3668 data
= (struct detail_data
*)page
->lParam
;
3669 create_cert_details_list(hwnd
, data
);
3670 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
3671 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
3672 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
3673 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
3678 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3680 nm
= (NMITEMACTIVATE
*)lp
;
3681 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
3682 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
3684 data
= (struct detail_data
*)nm
->lParam
;
3685 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
3687 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
3688 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
3690 if (data
->fields
[nm
->iItem
].create
)
3691 val
= data
->fields
[nm
->iItem
].create(
3692 data
->pCertViewInfo
->pCertContext
,
3693 data
->fields
[nm
->iItem
].param
);
3699 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
3700 item
.mask
= LVIF_TEXT
;
3702 item
.iItem
= nm
->iItem
;
3704 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
3708 /* Select all the text in the control, the next update will
3711 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
3712 add_unformatted_text_to_control(valueCtl
, val
,
3713 val
? strlenW(val
) : 0);
3715 HeapFree(GetProcessHeap(), 0, val
);
3724 FIXME("call CryptUIWizExport\n");
3726 case IDC_EDITPROPERTIES
:
3728 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3731 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3732 /* Actually, any index will do, since they all store the same
3735 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
3737 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
3740 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
3741 refresh_details_view(hwnd
);
3745 case WM_REFRESH_VIEW
:
3746 refresh_details_view(hwnd
);
3752 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
3753 PROPSHEETPAGEW
*page
)
3755 struct detail_data
*data
;
3760 data
= (struct detail_data
*)page
->lParam
;
3761 free_detail_fields(data
);
3762 HeapFree(GetProcessHeap(), 0, data
);
3768 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3769 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
3772 struct detail_data
*data
= HeapAlloc(GetProcessHeap(), 0,
3773 sizeof(struct detail_data
));
3777 data
->pCertViewInfo
= pCertViewInfo
;
3778 data
->pfPropertiesChanged
= pfPropertiesChanged
;
3780 data
->fields
= NULL
;
3781 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3782 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3783 page
->dwFlags
= PSP_USECALLBACK
;
3784 page
->pfnCallback
= detail_callback
;
3785 page
->hInstance
= hInstance
;
3786 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
3787 page
->pfnDlgProc
= detail_dlg_proc
;
3788 page
->lParam
= (LPARAM
)data
;
3796 struct hierarchy_data
3798 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
3799 HIMAGELIST imageList
;
3803 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
3805 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3806 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3807 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3808 data
->pCertViewInfo
->idxCounterSigner
);
3810 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
3811 * therefore always even.
3813 if (index
== provSigner
->csCertChain
- 1)
3814 return (LPARAM
)data
;
3815 return index
<< 1 | 1;
3818 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
3820 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3821 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3822 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3823 data
->pCertViewInfo
->idxCounterSigner
);
3826 return provSigner
->csCertChain
- 1;
3830 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
3833 struct hierarchy_data
*data
= NULL
;
3834 HTREEITEM root
= NULL
;
3837 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
3838 TVGN_PARENT
, (LPARAM
)hItem
);
3848 item
.mask
= TVIF_PARAM
;
3850 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
3851 data
= (struct hierarchy_data
*)item
.lParam
;
3856 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
3858 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
3861 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
3865 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
3867 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
3868 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3869 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3870 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3871 data
->pCertViewInfo
->idxCounterSigner
);
3873 HTREEITEM parent
= NULL
;
3875 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
3876 for (i
= provSigner
->csCertChain
; i
; i
--)
3880 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
3883 TVINSERTSTRUCTW tvis
;
3885 tvis
.hParent
= parent
;
3886 tvis
.hInsertAfter
= TVI_LAST
;
3887 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
3888 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
3889 tvis
.u
.item
.pszText
= name
;
3890 tvis
.u
.item
.state
= TVIS_EXPANDED
;
3891 tvis
.u
.item
.stateMask
= TVIS_EXPANDED
;
3893 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
3894 CERT_TRUST_IS_PARTIAL_CHAIN
))
3896 /* The root of the chain has a special case: if the chain is
3897 * a partial chain, the icon is a warning icon rather than an
3900 tvis
.u
.item
.iImage
= 2;
3902 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
3904 tvis
.u
.item
.iImage
= 0;
3906 tvis
.u
.item
.iImage
= 1;
3907 tvis
.u
.item
.iSelectedImage
= tvis
.u
.item
.iImage
;
3908 tvis
.u
.item
.lParam
= index_to_lparam(data
, i
- 1);
3909 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
3911 HeapFree(GetProcessHeap(), 0, name
);
3916 static void set_certificate_status(HWND hwnd
, CRYPT_PROVIDER_CERT
*cert
)
3918 /* Select all the text in the control, the next update will replace it */
3919 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
3920 /* Set the highest priority error messages first. */
3921 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
3922 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
3923 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
3924 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
3925 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
3926 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
3927 else if (cert
->dwRevokedReason
)
3928 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
3930 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
3933 static void set_certificate_status_for_end_cert(HWND hwnd
,
3934 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
3936 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
3937 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3938 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
3939 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
3940 pCertViewInfo
->idxCounterSigner
);
3941 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
3942 pCertViewInfo
->idxCert
);
3944 set_certificate_status(status
, provCert
);
3947 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
3949 /* Disable view certificate button until a certificate is selected */
3950 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
3951 show_cert_chain(hwnd
, data
);
3952 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
3955 static void show_dialog_for_selected_cert(HWND hwnd
)
3957 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
3959 struct hierarchy_data
*data
;
3962 memset(&item
, 0, sizeof(item
));
3963 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
3964 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
,
3966 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
3967 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
3968 selection
= lparam_to_index(data
, item
.lParam
);
3971 CRYPT_PROVIDER_SGNR
*provSigner
;
3972 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
3973 BOOL changed
= FALSE
;
3975 provSigner
= WTHelperGetProvSignerFromChain(
3976 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3977 data
->pCertViewInfo
->idxSigner
,
3978 data
->pCertViewInfo
->fCounterSigner
,
3979 data
->pCertViewInfo
->idxCounterSigner
);
3980 memset(&viewInfo
, 0, sizeof(viewInfo
));
3981 viewInfo
.dwSize
= sizeof(viewInfo
);
3982 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
3983 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
3984 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
3985 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
3986 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
3987 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
3988 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
3989 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
3990 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
3993 /* Delete the contents of the tree */
3994 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
3995 /* Reinitialize the tree */
3996 show_cert_hierarchy(hwnd
, data
);
4001 static LRESULT CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4004 PROPSHEETPAGEW
*page
;
4005 struct hierarchy_data
*data
;
4007 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4009 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
4014 page
= (PROPSHEETPAGEW
*)lp
;
4015 data
= (struct hierarchy_data
*)page
->lParam
;
4016 show_cert_hierarchy(hwnd
, data
);
4025 case TVN_SELCHANGEDW
:
4027 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
4029 CRYPT_PROVIDER_SGNR
*provSigner
;
4031 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
4032 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
4033 provSigner
= WTHelperGetProvSignerFromChain(
4034 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
4035 data
->pCertViewInfo
->idxSigner
,
4036 data
->pCertViewInfo
->fCounterSigner
,
4037 data
->pCertViewInfo
->idxCounterSigner
);
4038 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
4039 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
4040 &provSigner
->pasCertChain
[selection
]);
4044 show_dialog_for_selected_cert(hwnd
);
4045 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4054 case IDC_VIEWCERTIFICATE
:
4055 show_dialog_for_selected_cert(hwnd
);
4059 case WM_REFRESH_VIEW
:
4063 /* Get hierarchy data */
4064 memset(&item
, 0, sizeof(item
));
4065 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4066 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
4068 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4069 /* Delete the contents of the tree */
4070 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4071 /* Reinitialize the tree */
4072 show_cert_hierarchy(hwnd
, data
);
4079 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
4080 PROPSHEETPAGEW
*page
)
4082 struct hierarchy_data
*data
;
4087 data
= (struct hierarchy_data
*)page
->lParam
;
4088 ImageList_Destroy(data
->imageList
);
4089 HeapFree(GetProcessHeap(), 0, data
);
4095 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4096 PROPSHEETPAGEW
*page
)
4098 struct hierarchy_data
*data
= HeapAlloc(GetProcessHeap(), 0,
4099 sizeof(struct hierarchy_data
));
4104 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
4105 if (data
->imageList
)
4108 COLORREF backColor
= RGB(255, 0, 255);
4110 data
->pCertViewInfo
= pCertViewInfo
;
4111 data
->selectedCert
= 0xffffffff;
4113 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
4114 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
4116 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
4118 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
4119 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
4120 page
->dwFlags
= PSP_USECALLBACK
;
4121 page
->hInstance
= hInstance
;
4122 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
4123 page
->pfnDlgProc
= hierarchy_dlg_proc
;
4124 page
->lParam
= (LPARAM
)data
;
4125 page
->pfnCallback
= hierarchy_callback
;
4129 HeapFree(GetProcessHeap(), 0, data
);
4134 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
4139 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
4143 case PSCB_INITIALIZED
:
4144 /* Get cancel button's position.. */
4145 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
4146 topLeft
.x
= rc
.left
;
4148 ScreenToClient(hwnd
, &topLeft
);
4149 /* hide the cancel button.. */
4150 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
4151 /* get the OK button's size.. */
4152 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
4153 /* and move the OK button to the cancel button's original position. */
4154 MoveWindow(GetDlgItem(hwnd
, IDOK
), topLeft
.x
, topLeft
.y
,
4155 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, FALSE
);
4156 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
4162 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4163 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
4165 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
4167 PROPSHEETPAGEW
*pages
;
4169 HMODULE lib
= LoadLibraryW(riched
);
4171 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
4172 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4174 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4176 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
4179 PROPSHEETHEADERW hdr
;
4180 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
4183 memset(&hdr
, 0, sizeof(hdr
));
4184 hdr
.dwSize
= sizeof(hdr
);
4185 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
4186 hdr
.hInstance
= hInstance
;
4187 if (pCertViewInfo
->szTitle
)
4188 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
4190 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
4191 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
4192 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4194 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
4195 &pages
[hdr
.nPages
]))
4198 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4200 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
4203 /* Copy each additional page, and create the init dialog struct for it
4205 if (pCertViewInfo
->cPropSheetPages
)
4207 init
= HeapAlloc(GetProcessHeap(), 0,
4208 pCertViewInfo
->cPropSheetPages
*
4209 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
4212 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
4214 memcpy(&pages
[hdr
.nPages
+ i
],
4215 &pCertViewInfo
->rgPropSheetPages
[i
],
4216 sizeof(PROPSHEETPAGEW
));
4217 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
4218 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
4219 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
4221 if (pCertViewInfo
->nStartPage
& 0x8000)
4223 /* Start page index is relative to the number of default
4226 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
4229 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
4230 hdr
.nPages
= nPages
;
4234 SetLastError(ERROR_OUTOFMEMORY
);
4238 /* Ignore the relative flag if there aren't any additional pages */
4239 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
4246 hdr
.u3
.ppsp
= pages
;
4247 hdr
.pfnCallback
= cert_prop_sheet_proc
;
4248 l
= PropertySheetW(&hdr
);
4251 SetLastError(ERROR_CANCELLED
);
4255 HeapFree(GetProcessHeap(), 0, init
);
4256 HeapFree(GetProcessHeap(), 0, pages
);
4259 SetLastError(ERROR_OUTOFMEMORY
);
4264 /***********************************************************************
4265 * CryptUIDlgViewCertificateW (CRYPTUI.@)
4267 BOOL WINAPI
CryptUIDlgViewCertificateW(
4268 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
4270 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
4271 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4273 WINTRUST_CERT_INFO cert
;
4275 CRYPT_PROVIDER_SGNR
*signer
;
4276 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
4278 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
4280 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
4282 SetLastError(ERROR_INVALID_PARAMETER
);
4285 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
4286 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
4287 if (!viewInfo
.u
.hWVTStateData
)
4289 memset(&wvt
, 0, sizeof(wvt
));
4290 wvt
.cbStruct
= sizeof(wvt
);
4291 wvt
.dwUIChoice
= WTD_UI_NONE
;
4292 if (viewInfo
.dwFlags
&
4293 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
4294 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
4295 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
4296 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
4297 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
4298 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
4299 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
4300 memset(&cert
, 0, sizeof(cert
));
4301 cert
.cbStruct
= sizeof(cert
);
4302 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
4303 cert
.chStores
= viewInfo
.cStores
;
4304 cert
.pahStores
= viewInfo
.rghStores
;
4305 wvt
.u
.pCert
= &cert
;
4306 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
4307 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4308 viewInfo
.u
.pCryptProviderData
=
4309 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
4310 signer
= WTHelperGetProvSignerFromChain(
4311 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
4312 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
4317 viewInfo
.u
.pCryptProviderData
=
4318 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
4319 signer
= WTHelperGetProvSignerFromChain(
4320 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
4321 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
4322 viewInfo
.idxCounterSigner
);
4323 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
4328 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
4329 if (!viewInfo
.u
.hWVTStateData
)
4331 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
4332 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4338 /***********************************************************************
4339 * CryptUIDlgViewContext (CRYPTUI.@)
4341 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
4342 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
4346 TRACE("(%d, %p, %p, %s, %08x, %p)\n", dwContextType
, pvContext
, hwnd
,
4347 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
4349 switch (dwContextType
)
4351 case CERT_STORE_CERTIFICATE_CONTEXT
:
4353 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4355 memset(&viewInfo
, 0, sizeof(viewInfo
));
4356 viewInfo
.dwSize
= sizeof(viewInfo
);
4357 viewInfo
.hwndParent
= hwnd
;
4358 viewInfo
.szTitle
= pwszTitle
;
4359 viewInfo
.pCertContext
= pvContext
;
4360 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
4364 FIXME("unimplemented for context type %d\n", dwContextType
);
4365 SetLastError(E_INVALIDARG
);
4371 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
4372 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
4373 * should be a CA. If neither extension is present, returns
4374 * defaultIfNotSpecified.
4376 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
4378 BOOL isCA
= defaultIfNotSpecified
;
4379 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
4380 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4384 CERT_BASIC_CONSTRAINTS_INFO
*info
;
4387 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
4388 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
4389 NULL
, (LPBYTE
)&info
, &size
))
4391 if (info
->SubjectType
.cbData
== 1)
4392 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
4398 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
4399 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4402 CERT_BASIC_CONSTRAINTS2_INFO info
;
4403 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4405 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
4406 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
4407 0, NULL
, &info
, &size
))
4414 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
4418 if (is_ca_cert(cert
, TRUE
))
4421 storeName
= addressBook
;
4422 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4423 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
4426 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
4433 SetLastError(E_INVALIDARG
);
4436 if (hDestCertStore
) store
= hDestCertStore
;
4439 if (!(store
= choose_store_for_cert(cert
)))
4441 WARN("unable to open certificate store\n");
4445 ret
= CertAddCertificateContextToStore(store
, cert
,
4446 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4447 if (!hDestCertStore
) CertCloseStore(store
, 0);
4451 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
4458 SetLastError(E_INVALIDARG
);
4461 if (hDestCertStore
) store
= hDestCertStore
;
4464 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4465 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
4467 WARN("unable to open certificate store\n");
4471 ret
= CertAddCRLContextToStore(store
, crl
,
4472 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4473 if (!hDestCertStore
) CertCloseStore(store
, 0);
4477 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
4484 SetLastError(E_INVALIDARG
);
4487 if (hDestCertStore
) store
= hDestCertStore
;
4490 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
4492 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4493 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
4495 WARN("unable to open certificate store\n");
4499 ret
= CertAddCTLContextToStore(store
, ctl
,
4500 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4501 if (!hDestCertStore
) CertCloseStore(store
, 0);
4505 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
4506 * CryptQueryObject, against the allowed types. Returns TRUE if the
4507 * type is allowed, FALSE otherwise.
4509 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
4514 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4515 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4519 case CERT_QUERY_CONTENT_CERT
:
4520 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4521 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
4523 case CERT_QUERY_CONTENT_CRL
:
4524 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4525 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
4527 case CERT_QUERY_CONTENT_CTL
:
4528 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4529 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
4532 /* The remaining types contain more than one type, so allow
4540 /* No allowed types specified, so any type is allowed */
4544 SetLastError(E_INVALIDARG
);
4549 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4552 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4554 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4561 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
4562 sizeof(title
) / sizeof(title
[0]));
4565 LoadStringW(hInstance
, warningID
, error
,
4566 sizeof(error
) / sizeof(error
[0]));
4567 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
4571 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
4573 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
4576 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
4581 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4582 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4584 PCCERT_CONTEXT cert
;
4589 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
4591 CertFreeCertificateContext(cert
);
4592 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
4595 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
4597 CertFreeCRLContext(crl
);
4598 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
4601 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
4603 CertFreeCTLContext(ctl
);
4604 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4611 SetLastError(E_INVALIDARG
);
4615 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4616 HCERTSTORE source
, HCERTSTORE dest
)
4620 if ((ret
= check_store_context_type(dwFlags
, source
)))
4622 PCCERT_CONTEXT cert
= NULL
;
4623 PCCRL_CONTEXT crl
= NULL
;
4624 PCCTL_CONTEXT ctl
= NULL
;
4627 cert
= CertEnumCertificatesInStore(source
, cert
);
4629 ret
= import_cert(cert
, dest
);
4630 } while (ret
&& cert
);
4632 crl
= CertEnumCRLsInStore(source
, crl
);
4634 ret
= import_crl(crl
, dest
);
4635 } while (ret
&& crl
);
4637 ctl
= CertEnumCTLsInStore(source
, ctl
);
4639 ret
= import_ctl(ctl
, dest
);
4640 } while (ret
&& ctl
);
4643 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
4647 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
4648 DWORD
*pContentType
)
4650 HCERTSTORE store
= NULL
;
4651 DWORD contentType
= 0, expectedContentTypeFlags
;
4654 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4655 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4657 expectedContentTypeFlags
=
4658 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4659 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4660 CERT_QUERY_CONTENT_FLAG_PFX
;
4661 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
4662 expectedContentTypeFlags
|=
4663 CERT_QUERY_CONTENT_FLAG_CERT
|
4664 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
4665 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
4666 expectedContentTypeFlags
|=
4667 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4668 CERT_QUERY_CONTENT_FLAG_CRL
;
4669 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
4670 expectedContentTypeFlags
|=
4671 CERT_QUERY_CONTENT_FLAG_CTL
|
4672 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
4675 expectedContentTypeFlags
=
4676 CERT_QUERY_CONTENT_FLAG_CERT
|
4677 CERT_QUERY_CONTENT_FLAG_CTL
|
4678 CERT_QUERY_CONTENT_FLAG_CRL
|
4679 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4680 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
4681 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
4682 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4683 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4684 CERT_QUERY_CONTENT_FLAG_PFX
;
4686 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
4687 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
4688 &contentType
, NULL
, &store
, NULL
, NULL
);
4690 *pContentType
= contentType
;
4694 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4695 LPCWSTR fileName
, HCERTSTORE dest
)
4700 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
4702 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
4703 CertCloseStore(source
, 0);
4710 struct ImportWizData
4714 LPCWSTR pwszWizardTitle
;
4715 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
4719 HCERTSTORE hDestCertStore
;
4725 static LRESULT CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4734 struct ImportWizData
*data
;
4735 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4736 WCHAR fontFace
[MAX_STRING_LEN
];
4737 HDC hDC
= GetDC(hwnd
);
4740 data
= (struct ImportWizData
*)page
->lParam
;
4741 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
4742 sizeof(fontFace
) / sizeof(fontFace
[0]));
4743 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
4744 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
4745 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
4746 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
4747 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4748 (WPARAM
)data
->titleFont
, TRUE
);
4749 ReleaseDC(hwnd
, hDC
);
4754 NMHDR
*hdr
= (NMHDR
*)lp
;
4759 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
4769 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
4771 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
4773 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
4774 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
4775 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
4776 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
4778 static const WCHAR filter_all
[] = { '*','.','*',0 };
4780 struct StringToFilter
4785 } import_filters
[] = {
4786 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
4787 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
4788 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
4789 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
4790 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
4791 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
4792 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
4795 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
4798 int len
, totalLen
= 2;
4799 LPWSTR filter
= NULL
, str
;
4801 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4803 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4804 (dwFlags
& import_filters
[i
].allowFlags
))
4806 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
4807 totalLen
+= len
+ strlenW(import_filters
[i
].filter
) + 2;
4810 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
4816 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
4818 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4819 (dwFlags
& import_filters
[i
].allowFlags
))
4821 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
4823 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
4826 strcpyW(ptr
, import_filters
[i
].filter
);
4827 ptr
+= strlenW(import_filters
[i
].filter
) + 1;
4835 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
4841 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
4842 OPEN_EXISTING
, 0, NULL
);
4843 if (file
!= INVALID_HANDLE_VALUE
)
4845 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
4846 &data
->contentType
);
4850 warningID
= IDS_IMPORT_BAD_FORMAT
;
4851 else if (!check_store_context_type(data
->dwFlags
, source
))
4852 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
4855 data
->importSrc
.dwSubjectChoice
=
4856 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
4857 data
->importSrc
.u
.hCertStore
= source
;
4858 data
->freeSource
= TRUE
;
4863 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4870 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4872 LPWSTR msgBuf
, fullError
;
4874 if (data
->pwszWizardTitle
)
4875 pTitle
= data
->pwszWizardTitle
;
4878 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
4879 sizeof(title
) / sizeof(title
[0]));
4882 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
4883 sizeof(error
) / sizeof(error
[0]));
4885 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
4886 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
4887 fullError
= HeapAlloc(GetProcessHeap(), 0,
4888 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
4892 LPWSTR ptr
= fullError
;
4894 strcpyW(ptr
, error
);
4895 ptr
+= strlenW(error
);
4896 strcpyW(ptr
, fileName
);
4897 ptr
+= strlenW(fileName
);
4900 strcpyW(ptr
, msgBuf
);
4901 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
4902 HeapFree(GetProcessHeap(), 0, fullError
);
4909 static LRESULT CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4913 struct ImportWizData
*data
;
4919 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4921 data
= (struct ImportWizData
*)page
->lParam
;
4922 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
4927 NMHDR
*hdr
= (NMHDR
*)lp
;
4932 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
4933 PSWIZB_BACK
| PSWIZB_NEXT
);
4938 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
4939 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
4941 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4944 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4945 IDS_IMPORT_EMPTY_FILE
);
4946 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4951 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
4952 (len
+ 1) * sizeof(WCHAR
));
4956 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
4958 if (!import_validate_filename(hwnd
, data
, fileName
))
4960 HeapFree(GetProcessHeap(), 0, fileName
);
4961 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4965 data
->fileName
= fileName
;
4976 case IDC_IMPORT_BROWSE_FILE
:
4979 WCHAR fileBuf
[MAX_PATH
];
4981 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4982 memset(&ofn
, 0, sizeof(ofn
));
4983 ofn
.lStructSize
= sizeof(ofn
);
4984 ofn
.hwndOwner
= hwnd
;
4985 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
4986 ofn
.lpstrFile
= fileBuf
;
4987 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
4989 if (GetOpenFileNameW(&ofn
))
4990 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
4991 0, (LPARAM
)ofn
.lpstrFile
);
4992 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
5001 static LRESULT CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5005 struct ImportWizData
*data
;
5011 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5013 data
= (struct ImportWizData
*)page
->lParam
;
5014 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5015 if (!data
->hDestCertStore
)
5017 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
,
5019 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5020 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5021 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
5025 WCHAR storeTitle
[MAX_STRING_LEN
];
5027 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), BM_CLICK
,
5029 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5030 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5031 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
),
5032 !(data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
));
5033 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5034 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5035 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5036 0, (LPARAM
)storeTitle
);
5042 NMHDR
*hdr
= (NMHDR
*)lp
;
5047 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5048 PSWIZB_BACK
| PSWIZB_NEXT
);
5053 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5054 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
5055 !data
->hDestCertStore
)
5057 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5058 IDS_IMPORT_SELECT_STORE
);
5059 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5070 case IDC_IMPORT_AUTO_STORE
:
5071 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5072 data
->autoDest
= TRUE
;
5073 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5074 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5076 case IDC_IMPORT_SPECIFY_STORE
:
5077 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5078 data
->autoDest
= FALSE
;
5079 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5080 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5082 case IDC_IMPORT_BROWSE_STORE
:
5084 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
5085 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
5086 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
5087 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
5090 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5091 selectInfo
.dwSize
= sizeof(selectInfo
);
5092 selectInfo
.parent
= hwnd
;
5093 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
5094 selectInfo
.pwszTitle
= selectInfo
.pwszTitle
= NULL
;
5095 selectInfo
.pEnumData
= &enumData
;
5096 selectInfo
.pfnSelectedStoreCallback
= NULL
;
5097 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
5099 WCHAR storeTitle
[MAX_STRING_LEN
];
5101 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
5102 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
5103 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5104 0, (LPARAM
)storeTitle
);
5105 data
->hDestCertStore
= store
;
5106 data
->freeDest
= TRUE
;
5116 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
5118 WCHAR text
[MAX_STRING_LEN
];
5122 item
.mask
= LVIF_TEXT
;
5123 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5125 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
,
5126 sizeof(text
)/ sizeof(text
[0]));
5127 item
.pszText
= text
;
5128 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5131 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
,
5132 sizeof(text
)/ sizeof(text
[0]));
5134 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
,
5135 sizeof(text
)/ sizeof(text
[0]));
5136 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5137 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5139 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
,
5140 sizeof(text
)/ sizeof(text
[0]));
5141 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5142 switch (data
->contentType
)
5144 case CERT_QUERY_CONTENT_CERT
:
5145 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
5146 contentID
= IDS_IMPORT_CONTENT_CERT
;
5148 case CERT_QUERY_CONTENT_CRL
:
5149 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
5150 contentID
= IDS_IMPORT_CONTENT_CRL
;
5152 case CERT_QUERY_CONTENT_CTL
:
5153 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
5154 contentID
= IDS_IMPORT_CONTENT_CTL
;
5156 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
5157 contentID
= IDS_IMPORT_CONTENT_CMS
;
5159 case CERT_QUERY_CONTENT_FLAG_PFX
:
5160 contentID
= IDS_IMPORT_CONTENT_PFX
;
5163 contentID
= IDS_IMPORT_CONTENT_STORE
;
5166 LoadStringW(hInstance
, contentID
, text
, sizeof(text
)/ sizeof(text
[0]));
5168 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5171 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5173 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
5174 sizeof(text
)/ sizeof(text
[0]));
5175 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5177 item
.pszText
= data
->fileName
;
5178 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5182 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5183 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5187 switch (pImportSrc
->dwSubjectChoice
)
5189 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
5190 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
5191 pImportSrc
->u
.pwszFileName
, hDestCertStore
);
5193 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5194 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
5195 ret
= import_cert(pImportSrc
->u
.pCertContext
, hDestCertStore
);
5197 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5199 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5200 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
5201 ret
= import_crl(pImportSrc
->u
.pCRLContext
, hDestCertStore
);
5203 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5205 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5206 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
5207 ret
= import_ctl(pImportSrc
->u
.pCTLContext
, hDestCertStore
);
5209 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5211 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5212 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
5213 pImportSrc
->u
.hCertStore
, hDestCertStore
);
5216 WARN("unknown source type: %u\n", pImportSrc
->dwSubjectChoice
);
5217 SetLastError(E_INVALIDARG
);
5223 static LRESULT CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5227 struct ImportWizData
*data
;
5233 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5234 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5238 data
= (struct ImportWizData
*)page
->lParam
;
5239 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5240 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
5241 (WPARAM
)data
->titleFont
, TRUE
);
5242 GetWindowRect(lv
, &rc
);
5243 column
.mask
= LVCF_WIDTH
;
5244 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
5245 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
5246 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
5247 show_import_details(lv
, data
);
5252 NMHDR
*hdr
= (NMHDR
*)lp
;
5258 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5260 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5261 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
5262 show_import_details(lv
, data
);
5263 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5264 PSWIZB_BACK
| PSWIZB_FINISH
);
5270 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5271 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
5272 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
5274 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
5277 if (data
->pwszWizardTitle
)
5278 pTitle
= data
->pwszWizardTitle
;
5281 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
5282 sizeof(title
) / sizeof(title
[0]));
5285 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
,
5286 sizeof(message
) / sizeof(message
[0]));
5287 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
5290 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5291 IDS_IMPORT_SUCCEEDED
);
5301 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
5302 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
5303 HCERTSTORE hDestCertStore
)
5305 PROPSHEETHEADERW hdr
;
5306 PROPSHEETPAGEW pages
[4];
5307 struct ImportWizData data
;
5310 data
.dwFlags
= dwFlags
;
5311 data
.pwszWizardTitle
= pwszWizardTitle
;
5313 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
5315 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
5316 data
.fileName
= NULL
;
5317 data
.freeSource
= FALSE
;
5318 data
.hDestCertStore
= hDestCertStore
;
5319 data
.freeDest
= FALSE
;
5320 data
.autoDest
= TRUE
;
5321 data
.success
= TRUE
;
5323 memset(&pages
, 0, sizeof(pages
));
5325 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5326 pages
[nPages
].hInstance
= hInstance
;
5327 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
5328 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
5329 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5330 pages
[nPages
].lParam
= (LPARAM
)&data
;
5334 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
5336 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5337 pages
[nPages
].hInstance
= hInstance
;
5338 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
5339 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
5340 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5341 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
5342 pages
[nPages
].pszHeaderSubTitle
=
5343 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
5344 pages
[nPages
].lParam
= (LPARAM
)&data
;
5349 switch (pImportSrc
->dwSubjectChoice
)
5351 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5352 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
5354 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5355 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
5357 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5358 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
5360 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5361 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
5366 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5367 pages
[nPages
].hInstance
= hInstance
;
5368 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
5369 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
5370 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5371 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
5372 pages
[nPages
].pszHeaderSubTitle
=
5373 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
5374 pages
[nPages
].lParam
= (LPARAM
)&data
;
5377 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5378 pages
[nPages
].hInstance
= hInstance
;
5379 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
5380 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
5381 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5382 pages
[nPages
].lParam
= (LPARAM
)&data
;
5385 memset(&hdr
, 0, sizeof(hdr
));
5386 hdr
.dwSize
= sizeof(hdr
);
5387 hdr
.hwndParent
= hwndParent
;
5388 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
5390 hdr
.hInstance
= hInstance
;
5391 if (pwszWizardTitle
)
5392 hdr
.pszCaption
= pwszWizardTitle
;
5394 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
5395 hdr
.u3
.ppsp
= pages
;
5396 hdr
.nPages
= nPages
;
5397 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
5398 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
5399 PropertySheetW(&hdr
);
5400 HeapFree(GetProcessHeap(), 0, data
.fileName
);
5401 if (data
.freeSource
&&
5402 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
5403 CertCloseStore(data
.importSrc
.u
.hCertStore
, 0);
5404 DeleteObject(data
.titleFont
);
5405 return data
.success
;
5408 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5409 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5413 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
5414 pImportSrc
, hDestCertStore
);
5417 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
5419 SetLastError(E_INVALIDARG
);
5423 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
5424 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5426 else if (pImportSrc
)
5427 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5431 /* Can't have no UI without specifying source */
5432 SetLastError(E_INVALIDARG
);