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"
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
46 static HINSTANCE hInstance
;
48 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
50 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
54 case DLL_WINE_PREATTACH
:
55 return FALSE
; /* prefer native version */
56 case DLL_PROCESS_ATTACH
:
58 DisableThreadLibraryCalls(hinstDLL
);
60 case DLL_PROCESS_DETACH
:
68 #define MAX_STRING_LEN 512
70 static void add_cert_columns(HWND hwnd
)
72 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
74 WCHAR buf
[MAX_STRING_LEN
];
77 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
78 GetWindowRect(lv
, &rc
);
79 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
,
80 sizeof(buf
) / sizeof(buf
[0]));
81 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
82 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
84 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
85 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
,
86 sizeof(buf
) / sizeof(buf
[0]));
87 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
88 column
.cx
= (rc
.right
- rc
.left
) * 16 / 100 - 2;
89 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
,
90 sizeof(buf
) / sizeof(buf
[0]));
91 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
92 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
93 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
,
94 sizeof(buf
) / sizeof(buf
[0]));
95 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 3, (LPARAM
)&column
);
98 static void initialize_purpose_selection(HWND hwnd
)
100 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
101 WCHAR buf
[MAX_STRING_LEN
];
103 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
,
104 sizeof(buf
) / sizeof(buf
[0]));
105 SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
106 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
,
107 sizeof(buf
) / sizeof(buf
[0]));
108 SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
109 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
112 static const WCHAR my
[] = { 'M','y',0 };
113 static const WCHAR addressBook
[] = {
114 'A','d','d','r','e','s','s','B','o','o','k',0 };
115 static const WCHAR ca
[] = { 'C','A',0 };
116 static const WCHAR root
[] = { 'R','o','o','t',0 };
117 static const WCHAR trustedPublisher
[] = {
118 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
119 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
121 static LPCWSTR defaultStoreList
[] = {
122 my
, addressBook
, ca
, root
, trustedPublisher
, disallowed
};
123 static LPCWSTR publisherStoreList
[] = { root
, trustedPublisher
, disallowed
};
125 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
)
129 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
131 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
133 storeList
= publisherStoreList
;
134 cStores
= sizeof(publisherStoreList
) / sizeof(publisherStoreList
[0]);
138 storeList
= defaultStoreList
;
139 cStores
= sizeof(defaultStoreList
) / sizeof(defaultStoreList
[0]);
141 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
143 for (i
= 0; i
< cStores
; i
++)
149 if (!(name
= CryptFindLocalizedName(storeList
[i
])))
151 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
152 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
]);
153 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
154 item
.pszText
= (LPWSTR
)name
;
155 item
.lParam
= (LPARAM
)store
;
156 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
160 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
164 item
.mask
= TCIF_PARAM
;
165 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
166 return (HCERTSTORE
)item
.lParam
;
169 static void close_stores(HWND tab
)
171 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
173 for (i
= 0; i
< tabs
; i
++)
174 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
177 static LRESULT CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
184 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
185 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
187 initialize_purpose_selection(hwnd
);
188 add_cert_columns(hwnd
);
189 if (pCryptUICertMgr
->pwszTitle
)
190 SendMessageW(hwnd
, WM_SETTEXT
, 0,
191 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
192 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
);
199 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
200 EndDialog(hwnd
, IDCANCEL
);
208 /***********************************************************************
209 * CryptUIDlgCertMgr (CRYPTUI.@)
211 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
213 TRACE("(%p)\n", pCryptUICertMgr
);
215 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
217 WARN("unexpected size %d\n", pCryptUICertMgr
->dwSize
);
218 SetLastError(E_INVALIDARG
);
221 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
222 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
226 /* FIXME: real names are unknown, functions are undocumented */
227 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
230 void *pvSystemStoreLocationPara
;
231 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
233 typedef struct _CRYPTUI_ENUM_DATA
236 HCERTSTORE
*rghStore
;
238 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
239 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
241 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
244 /* Values for dwFlags */
245 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
247 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
254 CRYPTUI_ENUM_DATA
*pEnumData
;
255 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
257 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
259 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
266 CRYPTUI_ENUM_DATA
*pEnumData
;
267 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
269 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
283 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
284 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
287 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
288 TVINSERTSTRUCTW tvis
;
289 LPCWSTR localizedName
;
293 tvis
.hInsertAfter
= TVI_LAST
;
294 tvis
.u
.item
.mask
= TVIF_TEXT
;
295 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
297 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(), 0,
298 sizeof(struct StoreInfo
));
302 storeInfo
->type
= SystemStore
;
303 storeInfo
->u
.name
= HeapAlloc(GetProcessHeap(), 0,
304 (strlenW(pvSystemStore
) + 1) * sizeof(WCHAR
));
305 if (storeInfo
->u
.name
)
307 tvis
.u
.item
.mask
|= TVIF_PARAM
;
308 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
309 strcpyW(storeInfo
->u
.name
, pvSystemStore
);
313 HeapFree(GetProcessHeap(), 0, storeInfo
);
319 tvis
.u
.item
.pszText
= (LPWSTR
)localizedName
;
322 tvis
.u
.item
.pszText
= (LPWSTR
)pvSystemStore
;
323 /* FIXME: need a folder icon for the store too */
325 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
329 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
332 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
334 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
335 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
336 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
337 hwnd
, enum_store_callback
);
338 for (i
= 0; i
< pEnumData
->cStores
; i
++)
342 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
343 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
345 LPWSTR name
= HeapAlloc(GetProcessHeap(), 0, size
);
349 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
350 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
352 struct StoreInfo
*storeInfo
= HeapAlloc(GetProcessHeap(),
353 0, sizeof(struct StoreInfo
));
357 TVINSERTSTRUCTW tvis
;
359 storeInfo
->type
= StoreHandle
;
360 storeInfo
->u
.store
= pEnumData
->rghStore
[i
];
362 tvis
.hInsertAfter
= TVI_LAST
;
363 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
364 tvis
.u
.item
.pszText
= name
;
365 tvis
.u
.item
.lParam
= (LPARAM
)storeInfo
;
366 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
369 HeapFree(GetProcessHeap(), 0, name
);
375 static void free_store_info(HWND tree
)
377 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
384 memset(&item
, 0, sizeof(item
));
385 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
387 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
390 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
392 if (storeInfo
->type
== SystemStore
)
393 HeapFree(GetProcessHeap(), 0, storeInfo
->u
.name
);
394 HeapFree(GetProcessHeap(), 0, storeInfo
);
396 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
401 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
403 WCHAR buf
[MAX_STRING_LEN
];
407 memset(&item
, 0, sizeof(item
));
408 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
410 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
412 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
415 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
417 if (storeInfo
->type
== StoreHandle
)
418 store
= storeInfo
->u
.store
;
420 store
= CertOpenSystemStoreW(0, storeInfo
->u
.name
);
424 /* It's implicitly a system store */
425 store
= CertOpenSystemStoreW(0, buf
);
430 struct SelectStoreInfo
432 PCRYPTUI_SELECTSTORE_INFO_W info
;
436 static LRESULT CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
439 struct SelectStoreInfo
*selectInfo
;
446 selectInfo
= (struct SelectStoreInfo
*)lp
;
447 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
448 if (selectInfo
->info
->pwszTitle
)
449 SendMessageW(hwnd
, WM_SETTEXT
, 0,
450 (LPARAM
)selectInfo
->info
->pwszTitle
);
451 if (selectInfo
->info
->pwszText
)
452 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
453 (LPARAM
)selectInfo
->info
->pwszText
);
454 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
455 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
456 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
464 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
465 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
466 TVM_GETNEXTITEM
, TVGN_CARET
, (LPARAM
)NULL
);
468 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
472 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
474 if (selectInfo
->info
->pwszTitle
)
475 pTitle
= selectInfo
->info
->pwszTitle
;
478 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
,
479 sizeof(title
) / sizeof(title
[0]));
482 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
,
483 sizeof(error
) / sizeof(error
[0]));
484 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
488 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
490 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
491 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
492 selectInfo
->info
->pvArg
))
494 selectInfo
->store
= store
;
495 free_store_info(tree
);
496 EndDialog(hwnd
, IDOK
);
499 CertCloseStore(store
, 0);
505 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
506 EndDialog(hwnd
, IDCANCEL
);
515 /***********************************************************************
516 * CryptUIDlgSelectStoreW (CRYPTUI.@)
518 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
520 struct SelectStoreInfo selectInfo
= { info
, NULL
};
522 TRACE("(%p)\n", info
);
524 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
526 WARN("unexpected size %d\n", info
->dwSize
);
527 SetLastError(E_INVALIDARG
);
530 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
531 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
532 return selectInfo
.store
;
535 /***********************************************************************
536 * CryptUIDlgSelectStoreA (CRYPTUI.@)
538 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
540 CRYPTUI_SELECTSTORE_INFO_W infoW
;
544 TRACE("(%p)\n", info
);
546 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
548 WARN("unexpected size %d\n", info
->dwSize
);
549 SetLastError(E_INVALIDARG
);
552 memcpy(&infoW
, &info
, sizeof(info
));
555 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
556 infoW
.pwszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
557 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
562 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
563 infoW
.pwszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
564 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
566 ret
= CryptUIDlgSelectStoreW(&infoW
);
567 HeapFree(GetProcessHeap(), 0, infoW
.pwszText
);
568 HeapFree(GetProcessHeap(), 0, infoW
.pwszTitle
);
572 /***********************************************************************
573 * CryptUIDlgViewCertificateA (CRYPTUI.@)
575 BOOL WINAPI
CryptUIDlgViewCertificateA(
576 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
578 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
582 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
584 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
585 if (pCertViewInfo
->szTitle
)
587 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
590 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
593 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
595 viewInfo
.szTitle
= title
;
603 if (pCertViewInfo
->cPropSheetPages
)
605 FIXME("ignoring additional prop sheet pages\n");
606 viewInfo
.cPropSheetPages
= 0;
608 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
609 HeapFree(GetProcessHeap(), 0, title
);
614 struct ReadStringStruct
621 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
624 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
625 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
627 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
629 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
631 *pcb
= cch
* sizeof(WCHAR
);
635 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
637 struct ReadStringStruct string
;
638 EDITSTREAM editstream
;
640 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
645 editstream
.dwCookie
= (DWORD_PTR
)&string
;
646 editstream
.dwError
= 0;
647 editstream
.pfnCallback
= read_text_callback
;
648 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
649 (LPARAM
)&editstream
);
652 static void add_string_resource_to_control(HWND hwnd
, int id
)
657 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
658 add_unformatted_text_to_control(hwnd
, str
, len
);
661 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
662 LONG len
, const PARAFORMAT2
*fmt
)
664 add_unformatted_text_to_control(hwnd
, text
, len
);
665 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
668 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
669 const PARAFORMAT2
*fmt
)
674 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
675 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
678 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
684 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
687 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
689 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
694 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
695 DWORD dwType
, DWORD dwFlags
)
697 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
701 /* Don't include NULL-terminator in output */
702 DWORD len
= lstrlenW(name
);
704 add_unformatted_text_to_control(hwnd
, name
, len
);
705 HeapFree(GetProcessHeap(), 0, name
);
709 static void add_icon_to_control(HWND hwnd
, int id
)
712 LPRICHEDITOLE richEditOle
= NULL
;
713 LPOLEOBJECT object
= NULL
;
715 LPOLECACHE oleCache
= NULL
;
718 LPDATAOBJECT dataObject
= NULL
;
719 HBITMAP bitmap
= NULL
;
724 TRACE("(%p, %d)\n", hwnd
, id
);
726 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
729 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
733 hr
= IOleObject_GetUserClassID(object
, &clsid
);
736 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
739 formatEtc
.cfFormat
= CF_BITMAP
;
740 formatEtc
.ptd
= NULL
;
741 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
742 formatEtc
.lindex
= -1;
743 formatEtc
.tymed
= TYMED_GDI
;
744 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
747 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
748 (void**)&dataObject
);
751 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
752 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
755 rect
.left
= rect
.top
= 0;
756 rect
.right
= GetSystemMetrics(SM_CXICON
);
757 rect
.bottom
= GetSystemMetrics(SM_CYICON
);
758 stgm
.tymed
= TYMED_GDI
;
759 stgm
.u
.hBitmap
= bitmap
;
760 stgm
.pUnkForRelease
= NULL
;
761 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
765 reObject
.cbStruct
= sizeof(reObject
);
766 reObject
.cp
= REO_CP_SELECTION
;
767 reObject
.clsid
= clsid
;
768 reObject
.poleobj
= object
;
769 reObject
.pstg
= NULL
;
770 reObject
.polesite
= NULL
;
771 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
772 reObject
.dvaspect
= DVASPECT_CONTENT
;
773 reObject
.dwFlags
= 0;
776 IRichEditOle_InsertObject(richEditOle
, &reObject
);
780 IDataObject_Release(dataObject
);
782 IOleCache_Release(oleCache
);
784 IOleObject_Release(object
);
786 IRichEditOle_Release(richEditOle
);
789 #define MY_INDENT 200
791 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
794 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
797 parFmt
.cbSize
= sizeof(parFmt
);
798 parFmt
.dwMask
= PFM_STARTINDENT
;
799 parFmt
.dxStartIndent
= MY_INDENT
* 3;
802 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
803 lstrlenW(oidInfo
->pwszName
), &parFmt
);
804 add_unformatted_text_to_control(hwnd
, &nl
, 1);
814 /* The following list MUST be lexicographically sorted by OID */
815 static struct OIDToString oidMap
[] = {
816 /* 1.3.6.1.4.1.311.10.3.1 */
817 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
818 /* 1.3.6.1.4.1.311.10.3.4 */
819 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
820 /* 1.3.6.1.4.1.311.10.3.4.1 */
821 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
822 /* 1.3.6.1.4.1.311.10.3.5 */
823 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
824 /* 1.3.6.1.4.1.311.10.3.6 */
825 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
826 /* 1.3.6.1.4.1.311.10.3.7 */
827 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
828 /* 1.3.6.1.4.1.311.10.3.8 */
829 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
830 /* 1.3.6.1.4.1.311.10.3.9 */
831 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
832 /* 1.3.6.1.4.1.311.10.3.10 */
833 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
834 /* 1.3.6.1.4.1.311.10.3.11 */
835 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
836 /* 1.3.6.1.4.1.311.10.3.12 */
837 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
838 /* 1.3.6.1.4.1.311.10.3.13 */
839 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
840 /* 1.3.6.1.4.1.311.10.5.1 */
841 { szOID_DRM
, IDS_PURPOSE_DRM
},
842 /* 1.3.6.1.4.1.311.10.6.1 */
843 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
844 /* 1.3.6.1.4.1.311.10.6.2 */
845 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
846 /* 1.3.6.1.4.1.311.20.2.1 */
847 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
848 /* 1.3.6.1.4.1.311.20.2.2 */
849 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
850 /* 1.3.6.1.4.1.311.21.5 */
851 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
852 /* 1.3.6.1.4.1.311.21.6 */
853 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
854 /* 1.3.6.1.4.1.311.21.19 */
855 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
856 /* 1.3.6.1.5.5.7.3.1 */
857 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
858 /* 1.3.6.1.5.5.7.3.2 */
859 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
860 /* 1.3.6.1.5.5.7.3.3 */
861 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
862 /* 1.3.6.1.5.5.7.3.4 */
863 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
864 /* 1.3.6.1.5.5.7.3.5 */
865 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
866 /* 1.3.6.1.5.5.7.3.6 */
867 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
868 /* 1.3.6.1.5.5.7.3.7 */
869 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
870 /* 1.3.6.1.5.5.7.3.8 */
871 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
874 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
876 int indexHigh
= sizeof(oidMap
) / sizeof(oidMap
[0]) - 1, indexLow
= 0, i
;
877 struct OIDToString
*ret
= NULL
;
879 for (i
= (indexLow
+ indexHigh
) / 2; !ret
&& indexLow
<= indexHigh
;
880 i
= (indexLow
+ indexHigh
) / 2)
884 cmp
= strcmp(oid
, oidMap
[i
].oid
);
895 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
897 struct OIDToString
*entry
;
901 parFmt
.cbSize
= sizeof(parFmt
);
902 parFmt
.dwMask
= PFM_STARTINDENT
;
903 parFmt
.dxStartIndent
= MY_INDENT
* 3;
904 if ((entry
= findSupportedOID(oid
)))
906 WCHAR
*str
, *linebreak
, *ptr
;
907 BOOL multiline
= FALSE
;
910 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
913 if ((linebreak
= memchrW(ptr
, '\n', len
)))
915 WCHAR copy
[MAX_STRING_LEN
];
918 /* The source string contains a newline, which the richedit
919 * control won't find since it's interpreted as a paragraph
920 * break. Therefore copy up to the newline. lstrcpynW always
921 * NULL-terminates, so pass one more than the length of the
922 * source line so the copy includes the entire line and the
925 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
926 add_text_with_paraformat_to_control(text
, copy
,
927 linebreak
- ptr
, &parFmt
);
929 add_unformatted_text_to_control(text
, &nl
, 1);
931 else if (multiline
&& *ptr
)
933 /* Add the last line */
934 add_text_with_paraformat_to_control(text
, ptr
,
935 len
- (ptr
- str
), &parFmt
);
936 add_unformatted_text_to_control(text
, &nl
, 1);
941 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
942 add_unformatted_text_to_control(text
, &nl
, 1);
947 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
948 (strlen(oid
) + 1) * sizeof(WCHAR
));
955 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
958 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
960 add_unformatted_text_to_control(text
, &nl
, 1);
961 HeapFree(GetProcessHeap(), 0, oidW
);
966 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
969 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
972 PCERT_EXTENSION policyExt
;
977 parFmt
.cbSize
= sizeof(parFmt
);
978 parFmt
.dwMask
= PFM_STARTINDENT
;
979 parFmt
.dxStartIndent
= MY_INDENT
;
980 add_string_resource_with_paraformat_to_control(text
,
981 IDS_CERT_INFO_PURPOSES
, &parFmt
);
982 add_unformatted_text_to_control(text
, &nl
, 1);
983 *anyUsageAdded
= TRUE
;
985 memset(&charFmt
, 0, sizeof(charFmt
));
986 charFmt
.cbSize
= sizeof(charFmt
);
987 charFmt
.dwMask
= CFM_BOLD
;
988 charFmt
.dwEffects
= 0;
989 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
990 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
991 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
993 CERT_POLICIES_INFO
*policies
;
996 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
997 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
998 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
1002 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
1006 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
1007 add_local_oid_text_to_control(text
,
1008 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
1009 pszPolicyQualifierId
);
1011 LocalFree(policies
);
1015 add_oid_text_to_control(text
, any_app_policy
);
1018 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
1019 BOOL
*anyUsageAdded
)
1023 BOOL badUsages
= FALSE
;
1025 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
1027 CHARFORMATW charFmt
;
1028 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
1029 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
1033 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
1037 if (!*anyUsageAdded
)
1041 parFmt
.cbSize
= sizeof(parFmt
);
1042 parFmt
.dwMask
= PFM_STARTINDENT
;
1043 parFmt
.dxStartIndent
= MY_INDENT
;
1044 add_string_resource_with_paraformat_to_control(text
,
1045 IDS_CERT_INFO_PURPOSES
, &parFmt
);
1046 add_unformatted_text_to_control(text
, &nl
, 1);
1047 *anyUsageAdded
= TRUE
;
1049 memset(&charFmt
, 0, sizeof(charFmt
));
1050 charFmt
.cbSize
= sizeof(charFmt
);
1051 charFmt
.dwMask
= CFM_BOLD
;
1052 charFmt
.dwEffects
= 0;
1053 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
1055 if (!usage
->cUsageIdentifier
)
1056 add_oid_text_to_control(text
, any_cert_policy
);
1058 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
1059 add_local_oid_text_to_control(text
,
1060 usage
->rgpszUsageIdentifier
[i
]);
1064 HeapFree(GetProcessHeap(), 0, usage
);
1074 static void set_policy_text(HWND text
,
1075 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
1077 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
1078 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
1080 if (pCertViewInfo
->cPurposes
)
1084 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
1086 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
1087 includeCertUsages
= TRUE
;
1088 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
1089 szOID_ANY_APPLICATION_POLICY
))
1090 includeAppUsages
= TRUE
;
1096 includeAppUsages
= includeCertUsages
= TRUE
;
1097 if (includeAppUsages
)
1098 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
1099 if (includeCertUsages
)
1100 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
1106 parFmt
.cbSize
= sizeof(parFmt
);
1107 parFmt
.dwMask
= PFM_STARTINDENT
;
1108 parFmt
.dxStartIndent
= MY_INDENT
;
1109 add_string_resource_with_paraformat_to_control(text
,
1110 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
1114 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
1117 CRYPT_OBJID_BLOB
*ret
= NULL
;
1120 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
1124 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
1125 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
1126 pszPolicyQualifierId
, policyOid
))
1127 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
1133 static WCHAR
*get_cps_str_from_qualifier(CRYPT_OBJID_BLOB
*qualifier
)
1135 LPWSTR qualifierStr
= NULL
;
1136 CERT_NAME_VALUE
*qualifierValue
;
1139 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
1140 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
1141 &qualifierValue
, &size
))
1143 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
1144 &qualifierValue
->Value
, NULL
, 0);
1145 qualifierStr
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1147 CertRDNValueToStrW(qualifierValue
->dwValueType
,
1148 &qualifierValue
->Value
, qualifierStr
, size
);
1149 LocalFree(qualifierValue
);
1151 return qualifierStr
;
1154 static WCHAR
*get_user_notice_from_qualifier(CRYPT_OBJID_BLOB
*qualifier
)
1157 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
1160 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
1161 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
1162 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
1163 &qualifierValue
, &size
))
1165 str
= HeapAlloc(GetProcessHeap(), 0,
1166 (strlenW(qualifierValue
->pszDisplayText
) + 1) * sizeof(WCHAR
));
1168 strcpyW(str
, qualifierValue
->pszDisplayText
);
1169 LocalFree(qualifierValue
);
1174 struct IssuerStatement
1180 static void set_issuer_statement(HWND hwnd
,
1181 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
1183 PCERT_EXTENSION policyExt
;
1185 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
1186 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
1187 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
1188 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
1190 CERT_POLICIES_INFO
*policies
;
1193 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
1194 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
1195 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
1197 CRYPT_OBJID_BLOB
*qualifier
;
1198 LPWSTR cps
= NULL
, userNotice
= NULL
;
1200 if ((qualifier
= find_policy_qualifier(policies
,
1201 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
1202 cps
= get_cps_str_from_qualifier(qualifier
);
1203 if ((qualifier
= find_policy_qualifier(policies
,
1204 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
1205 userNotice
= get_user_notice_from_qualifier(qualifier
);
1206 if (cps
|| userNotice
)
1208 struct IssuerStatement
*issuerStatement
=
1209 HeapAlloc(GetProcessHeap(), 0, sizeof(struct IssuerStatement
));
1211 if (issuerStatement
)
1213 issuerStatement
->cps
= cps
;
1214 issuerStatement
->userNotice
= userNotice
;
1215 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
1216 SetWindowLongPtrW(hwnd
, DWLP_USER
,
1217 (ULONG_PTR
)issuerStatement
);
1220 LocalFree(policies
);
1225 static void set_cert_info(HWND hwnd
,
1226 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
1228 CHARFORMATW charFmt
;
1230 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
1231 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
1232 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
1233 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
1234 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
1235 pCertViewInfo
->idxCounterSigner
);
1236 CRYPT_PROVIDER_CERT
*root
=
1237 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
1239 if (!provSigner
->pChainContext
||
1240 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
1241 CERT_TRUST_IS_PARTIAL_CHAIN
))
1242 add_icon_to_control(icon
, IDB_CERT_WARNING
);
1243 else if (!root
->fTrustedRoot
)
1244 add_icon_to_control(icon
, IDB_CERT_ERROR
);
1246 add_icon_to_control(icon
, IDB_CERT
);
1248 memset(&charFmt
, 0, sizeof(charFmt
));
1249 charFmt
.cbSize
= sizeof(charFmt
);
1250 charFmt
.dwMask
= CFM_BOLD
;
1251 charFmt
.dwEffects
= CFE_BOLD
;
1252 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1253 /* FIXME: vertically center text */
1254 parFmt
.cbSize
= sizeof(parFmt
);
1255 parFmt
.dwMask
= PFM_STARTINDENT
;
1256 parFmt
.dxStartIndent
= MY_INDENT
;
1257 add_string_resource_with_paraformat_to_control(text
,
1258 IDS_CERTIFICATEINFORMATION
, &parFmt
);
1260 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
1261 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1262 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
1263 add_string_resource_with_paraformat_to_control(text
,
1264 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
1265 else if (!provSigner
->pChainContext
||
1266 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
1267 CERT_TRUST_IS_PARTIAL_CHAIN
))
1268 add_string_resource_with_paraformat_to_control(text
,
1269 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
1270 else if (!root
->fTrustedRoot
)
1272 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
1273 add_string_resource_with_paraformat_to_control(text
,
1274 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
1276 add_string_resource_with_paraformat_to_control(text
,
1277 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
1281 set_policy_text(text
, pCertViewInfo
);
1282 set_issuer_statement(hwnd
, pCertViewInfo
);
1286 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
1287 DWORD nameFlags
, int heading
)
1290 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
1291 CHARFORMATW charFmt
;
1294 memset(&charFmt
, 0, sizeof(charFmt
));
1295 charFmt
.cbSize
= sizeof(charFmt
);
1296 charFmt
.dwMask
= CFM_BOLD
;
1297 charFmt
.dwEffects
= CFE_BOLD
;
1298 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1299 parFmt
.cbSize
= sizeof(parFmt
);
1300 parFmt
.dwMask
= PFM_STARTINDENT
;
1301 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1302 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
1303 charFmt
.dwEffects
= 0;
1304 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1305 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
1307 add_unformatted_text_to_control(text
, &nl
, 1);
1308 add_unformatted_text_to_control(text
, &nl
, 1);
1309 add_unformatted_text_to_control(text
, &nl
, 1);
1313 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
1315 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
1319 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
1320 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
1321 FileTimeToSystemTime(fileTime
, &sysTime
);
1322 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
1323 sizeof(date
) / sizeof(date
[0]));
1324 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
1327 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
1330 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
1331 CHARFORMATW charFmt
;
1334 memset(&charFmt
, 0, sizeof(charFmt
));
1335 charFmt
.cbSize
= sizeof(charFmt
);
1336 charFmt
.dwMask
= CFM_BOLD
;
1337 charFmt
.dwEffects
= CFE_BOLD
;
1338 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1339 parFmt
.cbSize
= sizeof(parFmt
);
1340 parFmt
.dwMask
= PFM_STARTINDENT
;
1341 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1342 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
1344 charFmt
.dwEffects
= 0;
1345 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1346 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
1347 charFmt
.dwEffects
= CFE_BOLD
;
1348 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1349 add_string_resource_to_control(text
, IDS_VALID_TO
);
1350 charFmt
.dwEffects
= 0;
1351 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
1352 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
1353 add_unformatted_text_to_control(text
, &nl
, 1);
1356 static void set_general_info(HWND hwnd
,
1357 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
1359 set_cert_info(hwnd
, pCertViewInfo
);
1360 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
1361 IDS_SUBJECT_HEADING
);
1362 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
1363 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
1364 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
1367 static LRESULT CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1372 struct IssuerStatement
*issuerStatement
;
1377 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
1378 issuerStatement
= (struct IssuerStatement
*)lp
;
1379 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
1380 strlenW(issuerStatement
->userNotice
));
1381 if (issuerStatement
->cps
)
1382 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
1384 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
1390 EndDialog(hwnd
, IDOK
);
1395 IBindCtx
*bctx
= NULL
;
1398 CreateBindCtx(0, &bctx
);
1399 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1400 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
1401 HLNF_OPENINNEWWINDOW
, 0);
1402 IBindCtx_Release(bctx
);
1410 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
1412 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
1413 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
1416 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1419 PROPSHEETPAGEW
*page
;
1420 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
1422 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
1427 page
= (PROPSHEETPAGEW
*)lp
;
1428 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
1429 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
1430 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
1431 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
1432 set_general_info(hwnd
, pCertViewInfo
);
1437 case IDC_ADDTOSTORE
:
1438 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
1440 case IDC_ISSUERSTATEMENT
:
1442 struct IssuerStatement
*issuerStatement
=
1443 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1445 if (issuerStatement
)
1447 if (issuerStatement
->userNotice
)
1448 show_user_notice(hwnd
, issuerStatement
);
1449 else if (issuerStatement
->cps
)
1451 IBindCtx
*bctx
= NULL
;
1453 CreateBindCtx(0, &bctx
);
1454 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
1455 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
1456 IBindCtx_Release(bctx
);
1467 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
1468 PROPSHEETPAGEW
*page
)
1470 struct IssuerStatement
*issuerStatement
;
1476 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1477 if (issuerStatement
)
1479 HeapFree(GetProcessHeap(), 0, issuerStatement
->cps
);
1480 HeapFree(GetProcessHeap(), 0, issuerStatement
->userNotice
);
1481 HeapFree(GetProcessHeap(), 0, issuerStatement
);
1488 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
1489 PROPSHEETPAGEW
*page
)
1491 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
1492 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
1493 page
->dwFlags
= PSP_USECALLBACK
;
1494 page
->pfnCallback
= general_callback_proc
;
1495 page
->hInstance
= hInstance
;
1496 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
1497 page
->pfnDlgProc
= general_dlg_proc
;
1498 page
->lParam
= (LPARAM
)pCertViewInfo
;
1501 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
1503 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
1505 static const WCHAR fmt
[] = { 'V','%','d',0 };
1506 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, 12 * sizeof(WCHAR
));
1509 sprintfW(buf
, fmt
, cert
->pCertInfo
->dwVersion
);
1513 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
1515 WCHAR
*buf
= HeapAlloc(GetProcessHeap(), 0, (cb
* 3 + 1) * sizeof(WCHAR
));
1519 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
1523 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
1524 sprintfW(ptr
, fmt
, ((BYTE
*)pb
)[i
]);
1529 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
1531 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
1532 cert
->pCertInfo
->SerialNumber
.cbData
);
1535 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
1537 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
1538 CERT_NAME_ISSUER_FLAG
);
1541 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
1544 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
1545 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, NULL
, 0);
1549 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1551 CertNameToStrW(X509_ASN_ENCODING
, name
,
1552 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
, str
, len
);
1557 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
1559 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
1562 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
1564 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
1567 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
1569 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
1572 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
1574 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
1579 /* FIXME: format isn't quite right, want time too */
1580 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
,
1581 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
1582 FileTimeToSystemTime(fileTime
, &sysTime
);
1583 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
1586 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1588 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
1594 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
1596 return format_long_date(&cert
->pCertInfo
->NotBefore
);
1599 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
1601 return format_long_date(&cert
->pCertInfo
->NotAfter
);
1604 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
1606 PCCRYPT_OID_INFO oidInfo
;
1609 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
1610 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
1613 WCHAR fmt
[MAX_STRING_LEN
];
1615 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
,
1616 sizeof(fmt
) / sizeof(fmt
[0])))
1618 /* Allocate the output buffer. Use the number of bytes in the
1619 * public key as a conservative (high) estimate for the number of
1620 * digits in its output.
1621 * The output is of the form (in English)
1622 * "<public key algorithm> (<public key bit length> bits)".
1623 * Ordinarily having two positional parameters in a string is not a
1624 * good idea, but as this isn't a sentence fragment, it shouldn't
1625 * be word-order dependent.
1627 buf
= HeapAlloc(GetProcessHeap(), 0,
1628 (strlenW(fmt
) + strlenW(oidInfo
->pwszName
) +
1629 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8)
1632 sprintfW(buf
, fmt
, oidInfo
->pwszName
,
1633 CertGetPublicKeyLength(X509_ASN_ENCODING
,
1634 &cert
->pCertInfo
->SubjectPublicKeyInfo
));
1640 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
1642 return format_hex_string(
1643 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
1644 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
1647 struct field_value_data
;
1650 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
1651 BOOL
*pfPropertiesChanged
;
1653 struct field_value_data
*fields
;
1656 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
1658 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
1660 struct field_value_data
1662 create_detailed_value_func create
;
1663 LPWSTR detailed_value
;
1667 static void add_field_value_data(struct detail_data
*data
,
1668 create_detailed_value_func create
, void *param
)
1671 data
->fields
= HeapReAlloc(GetProcessHeap(), 0, data
->fields
,
1672 (data
->cFields
+ 1) * sizeof(struct field_value_data
));
1674 data
->fields
= HeapAlloc(GetProcessHeap(), 0,
1675 sizeof(struct field_value_data
));
1678 data
->fields
[data
->cFields
].create
= create
;
1679 data
->fields
[data
->cFields
].detailed_value
= NULL
;
1680 data
->fields
[data
->cFields
].param
= param
;
1685 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
1686 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
1689 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1691 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
1694 item
.pszText
= field
;
1695 item
.lParam
= (LPARAM
)data
;
1696 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
1699 item
.pszText
= value
;
1701 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
1703 add_field_value_data(data
, create
, param
);
1706 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
1707 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
1709 WCHAR buf
[MAX_STRING_LEN
];
1711 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1712 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
1718 field_format_func format
;
1719 create_detailed_value_func create_detailed_value
;
1722 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
1723 const struct v1_field
*field
)
1725 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
1729 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
1730 field
->create_detailed_value
, NULL
);
1731 HeapFree(GetProcessHeap(), 0, val
);
1735 static const struct v1_field v1_fields
[] = {
1736 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
1737 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
1738 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
1739 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
1740 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
1741 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
1742 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
1743 field_format_detailed_public_key
}
1746 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
1749 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
1751 /* The last item in v1_fields is the public key, which is not in the loop
1752 * because it's a special case.
1754 for (i
= 0; i
< sizeof(v1_fields
) / sizeof(v1_fields
[0]) - 1; i
++)
1755 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
1756 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
1757 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
1760 static WCHAR
*crypt_format_extension(PCERT_EXTENSION ext
, DWORD formatStrType
)
1765 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
1766 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
1768 str
= HeapAlloc(GetProcessHeap(), 0, size
);
1769 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
1770 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
1775 static WCHAR
*field_format_extension_hex_with_ascii(PCERT_EXTENSION ext
)
1779 if (ext
->Value
.cbData
)
1781 /* The output is formatted as:
1782 * <hex bytes> <ascii bytes>\n
1783 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
1784 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
1785 * the byte is not printable.
1786 * So, for example, the extension value consisting of the following
1788 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
1789 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
1791 * 30 14 31 12 30 10 06 03 0.1.0...
1792 * 55 04 03 13 09 4a 75 61 U....Jua
1793 * 6e 20 4c 61 6e 67 n Lang
1794 * The allocation size therefore requires:
1795 * - 4 characters per character in an 8-byte line
1796 * (2 for the hex format, one for the space, one for the ASCII value)
1797 * - 3 more characters per 8-byte line (two spaces and a newline)
1798 * - 1 character for the terminating nul
1799 * FIXME: should use a fixed-width font for this
1801 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
1803 str
= HeapAlloc(GetProcessHeap(), 0,
1804 (lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
1807 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
1811 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
1813 /* Output as hex bytes first */
1814 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
1815 sprintfW(ptr
, fmt
, ext
->Value
.pbData
[j
]);
1816 /* Pad the hex output with spaces for alignment */
1817 if (j
== ext
->Value
.cbData
&& j
% 8)
1819 static const WCHAR pad
[] = { ' ',' ',' ' };
1821 for (; j
% 8; j
++, ptr
+= sizeof(pad
) / sizeof(pad
[0]))
1822 memcpy(ptr
, pad
, sizeof(pad
));
1824 /* The last sprintfW included a space, so just insert one
1825 * more space between the hex bytes and the ASCII output
1828 /* Output as ASCII bytes */
1829 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
1831 if (isprintW(ext
->Value
.pbData
[j
]) &&
1832 !isspaceW(ext
->Value
.pbData
[j
]))
1833 *ptr
= ext
->Value
.pbData
[j
];
1845 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
1847 PCERT_EXTENSION ext
= param
;
1848 LPWSTR str
= crypt_format_extension(ext
,
1849 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
1852 str
= field_format_extension_hex_with_ascii(ext
);
1856 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
1857 PCERT_EXTENSION ext
)
1859 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
1861 LPWSTR val
= crypt_format_extension(ext
, 0);
1864 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
1865 val
, field_format_detailed_extension
, ext
);
1868 DWORD len
= strlen(ext
->pszObjId
);
1869 LPWSTR oidW
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
1875 for (i
= 0; i
<= len
; i
++)
1876 oidW
[i
] = ext
->pszObjId
[i
];
1877 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
1878 field_format_detailed_extension
, ext
);
1879 HeapFree(GetProcessHeap(), 0, oidW
);
1882 HeapFree(GetProcessHeap(), 0, val
);
1885 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
1888 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
1890 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
1891 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
1894 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
1897 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
1899 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
1900 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
1901 add_cert_extension_detail(hwnd
, data
,
1902 &cert
->pCertInfo
->rgExtension
[i
]);
1905 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
1907 struct prop_id_to_string_id
1911 BOOL prop_is_string
;
1912 prop_to_value_func prop_to_value
;
1915 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
1919 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
1920 ext
.fCritical
= FALSE
;
1921 ext
.Value
.pbData
= pb
;
1922 ext
.Value
.cbData
= cb
;
1923 return crypt_format_extension(&ext
, 0);
1926 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
1927 * disabled for read-only certificates, but native doesn't appear to do that.
1929 static const struct prop_id_to_string_id prop_id_map
[] = {
1930 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
1931 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
1932 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
1933 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
1934 format_enhanced_key_usage_value
},
1937 static void add_properties(HWND hwnd
, struct detail_data
*data
)
1940 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
1942 for (i
= 0; i
< sizeof(prop_id_map
) / sizeof(prop_id_map
[0]); i
++)
1946 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
1952 /* FIXME: MS adds a separate value for the signature hash
1955 pb
= HeapAlloc(GetProcessHeap(), 0, cb
);
1958 if (CertGetCertificateContextProperty(cert
,
1959 prop_id_map
[i
].prop
, pb
, &cb
))
1961 if (prop_id_map
[i
].prop_is_string
)
1964 /* Don't double-free pb */
1968 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
1970 HeapFree(GetProcessHeap(), 0, pb
);
1972 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
1978 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
1980 add_v1_fields(hwnd
, data
);
1981 add_all_extensions(hwnd
, data
);
1982 add_properties(hwnd
, data
);
1985 struct selection_list_item
1988 add_fields_func add
;
1991 const struct selection_list_item listItems
[] = {
1992 { IDS_FIELDS_ALL
, add_all_fields
},
1993 { IDS_FIELDS_V1
, add_v1_fields
},
1994 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
1995 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
1996 { IDS_FIELDS_PROPERTIES
, add_properties
},
1999 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
2001 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
2002 WCHAR buf
[MAX_STRING_LEN
];
2005 for (i
= 0; i
< sizeof(listItems
) / sizeof(listItems
[0]); i
++)
2009 LoadStringW(hInstance
, listItems
[i
].id
, buf
,
2010 sizeof(buf
) / sizeof(buf
[0]));
2011 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
2012 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
2014 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
2017 static void create_listview_columns(HWND hwnd
)
2019 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
2021 WCHAR buf
[MAX_STRING_LEN
];
2024 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
2025 GetWindowRect(lv
, &rc
);
2026 LoadStringW(hInstance
, IDS_FIELD
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2027 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
2028 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
2029 column
.pszText
= buf
;
2030 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
2031 LoadStringW(hInstance
, IDS_VALUE
, buf
, sizeof(buf
) / sizeof(buf
[0]));
2032 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
2035 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
2037 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
2039 if (sel
>= 0 && sel
< sizeof(listItems
) / sizeof(listItems
[0]))
2041 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
2042 listItems
[sel
].add(list
, data
);
2046 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
2048 create_show_list(hwnd
, data
);
2049 create_listview_columns(hwnd
);
2050 set_fields_selection(hwnd
, data
, 0);
2054 CheckBitmapIndexUnchecked
= 1,
2055 CheckBitmapIndexChecked
= 2,
2056 CheckBitmapIndexDisabledUnchecked
= 3,
2057 CheckBitmapIndexDisabledChecked
= 4
2060 static void add_purpose(HWND hwnd
, LPCSTR oid
)
2062 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
2063 PCRYPT_OID_INFO info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2064 sizeof(CRYPT_OID_INFO
));
2068 char *oidCopy
= HeapAlloc(GetProcessHeap(), 0, strlen(oid
) + 1);
2074 strcpy(oidCopy
, oid
);
2075 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
2076 info
->pszOID
= oidCopy
;
2077 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
2078 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
2079 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2080 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
2082 item
.lParam
= (LPARAM
)info
;
2083 item
.pszText
= oidCopy
;
2084 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
2087 HeapFree(GetProcessHeap(), 0, info
);
2091 static BOOL
is_valid_oid(LPCSTR oid
)
2095 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
2097 else if (oid
[1] != '.')
2104 BOOL expectNum
= TRUE
;
2106 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
2112 else if (*(ptr
+ 1) == '.')
2119 else if (!(*(ptr
+ 1)))
2129 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
2131 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
2132 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2133 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2138 LVFINDINFOW findInfo
;
2140 findInfo
.flags
= LVFI_PARAM
;
2141 findInfo
.lParam
= (LPARAM
)oidInfo
;
2142 if (SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
) != -1)
2147 LVFINDINFOA findInfo
;
2149 findInfo
.flags
= LVFI_STRING
;
2151 if (SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
) != -1)
2157 #define MAX_PURPOSE 255
2159 static LRESULT CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
2160 WPARAM wp
, LPARAM lp
)
2163 char buf
[MAX_PURPOSE
+ 1];
2168 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
2170 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
2171 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
2177 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
2179 /* Show/hide scroll bar on description depending on how much
2182 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
2183 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
2185 ShowScrollBar(description
, SB_VERT
, lines
> 1);
2192 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
,
2193 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
2196 /* An empty purpose is the same as cancelling */
2197 EndDialog(hwnd
, IDCANCEL
);
2200 else if (!is_valid_oid(buf
))
2202 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
2204 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
,
2205 sizeof(error
) / sizeof(error
[0]));
2206 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
2207 sizeof(title
) / sizeof(title
[0]));
2208 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
2210 else if (is_oid_in_list(
2211 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
2213 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
2215 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
,
2216 error
, sizeof(error
) / sizeof(error
[0]));
2217 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
,
2218 sizeof(title
) / sizeof(title
[0]));
2219 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
2223 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2225 add_purpose(parent
, buf
);
2226 EndDialog(hwnd
, wp
);
2231 EndDialog(hwnd
, wp
);
2242 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
2247 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
2249 name
= HeapAlloc(GetProcessHeap(), 0, cb
);
2252 if (!CertGetCertificateContextProperty(cert
, prop
, (LPBYTE
)name
,
2255 HeapFree(GetProcessHeap(), 0, name
);
2263 static void redraw_states(HWND list
, BOOL enabled
)
2265 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
2267 for (i
= 0; i
< items
; i
++)
2269 BOOL change
= FALSE
;
2272 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
2273 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
2274 * to be a handy macro for it.
2279 if (state
== CheckBitmapIndexDisabledChecked
)
2281 state
= CheckBitmapIndexChecked
;
2284 if (state
== CheckBitmapIndexDisabledUnchecked
)
2286 state
= CheckBitmapIndexUnchecked
;
2292 if (state
== CheckBitmapIndexChecked
)
2294 state
= CheckBitmapIndexDisabledChecked
;
2297 if (state
== CheckBitmapIndexUnchecked
)
2299 state
= CheckBitmapIndexDisabledUnchecked
;
2307 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
2308 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2309 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
2315 PurposeEnableAll
= 0,
2317 PurposeEnableSelected
2320 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
2322 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
2326 case PurposeEnableAll
:
2327 case PurposeDisableAll
:
2328 EnableWindow(lv
, FALSE
);
2329 redraw_states(lv
, FALSE
);
2330 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
2332 case PurposeEnableSelected
:
2333 EnableWindow(lv
, TRUE
);
2334 redraw_states(lv
, TRUE
);
2335 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
2339 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
2340 PCCRYPT_OID_INFO
**usages
);
2342 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
)
2346 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
2347 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexDisabledChecked
);
2348 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2349 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
2351 item
.lParam
= (LPARAM
)info
;
2352 item
.pszText
= (LPWSTR
)info
->pwszName
;
2353 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2356 struct edit_cert_data
2358 PCCERT_CONTEXT cert
;
2359 BOOL
*pfPropertiesChanged
;
2360 HIMAGELIST imageList
;
2363 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
2365 PCCERT_CONTEXT cert
= data
->cert
;
2366 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
2367 PCERT_ENHKEY_USAGE usage
;
2369 PCCRYPT_OID_INFO
*usages
;
2372 PurposeSelection purposeSelection
;
2374 GetWindowRect(lv
, &rc
);
2375 column
.mask
= LVCF_WIDTH
;
2376 column
.cx
= rc
.right
- rc
.left
;
2377 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
2378 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
2380 /* Get enhanced key usage. Have to check for a property and an extension
2381 * separately, because CertGetEnhancedKeyUsage will succeed and return an
2382 * empty usage if neither is set. Unfortunately an empty usage implies
2383 * no usage is allowed, so we have to distinguish between the two cases.
2385 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
2388 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
2389 if (!CertGetEnhancedKeyUsage(cert
,
2390 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
2392 HeapFree(GetProcessHeap(), 0, usage
);
2395 else if (usage
->cUsageIdentifier
)
2396 purposeSelection
= PurposeEnableSelected
;
2398 purposeSelection
= PurposeDisableAll
;
2400 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
2403 usage
= HeapAlloc(GetProcessHeap(), 0, size
);
2404 if (!CertGetEnhancedKeyUsage(cert
,
2405 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
2407 HeapFree(GetProcessHeap(), 0, usage
);
2410 else if (usage
->cUsageIdentifier
)
2411 purposeSelection
= PurposeEnableAll
;
2413 purposeSelection
= PurposeDisableAll
;
2417 purposeSelection
= PurposeEnableAll
;
2424 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2426 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2427 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2430 add_known_usage(lv
, info
);
2432 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
2434 HeapFree(GetProcessHeap(), 0, usage
);
2438 if (WTHelperGetKnownUsages(1, &usages
))
2440 PCCRYPT_OID_INFO
*ptr
;
2442 for (ptr
= usages
; *ptr
; ptr
++)
2443 add_known_usage(lv
, *ptr
);
2444 WTHelperGetKnownUsages(2, &usages
);
2447 select_purposes(hwnd
, purposeSelection
);
2448 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
2452 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
2454 PCCERT_CONTEXT cert
= data
->cert
;
2457 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
2459 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
2461 HeapFree(GetProcessHeap(), 0, str
);
2463 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
2465 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
2467 HeapFree(GetProcessHeap(), 0, str
);
2469 show_cert_usages(hwnd
, data
);
2472 static void toggle_usage(HWND hwnd
, int iItem
)
2476 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
2478 item
.mask
= LVIF_STATE
;
2481 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2482 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
2485 int state
= item
.state
>> 12;
2487 item
.state
= INDEXTOSTATEIMAGEMASK(
2488 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
2489 CheckBitmapIndexChecked
);
2490 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
2494 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
2497 if (str
&& strlenW(str
))
2499 CRYPT_DATA_BLOB blob
;
2501 blob
.pbData
= (BYTE
*)str
;
2502 blob
.cbData
= (strlenW(str
) + 1) * sizeof(WCHAR
);
2503 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
2506 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
2509 #define WM_REFRESH_VIEW WM_USER + 0
2511 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
2513 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
2514 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
2518 #define MAX_FRIENDLY_NAME 40
2519 #define MAX_DESCRIPTION 255
2521 static void apply_general_changes(HWND hwnd
)
2523 WCHAR buf
[MAX_DESCRIPTION
+ 1];
2524 struct edit_cert_data
*data
=
2525 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2527 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
,
2528 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
2529 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
2530 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
,
2531 sizeof(buf
) / sizeof(buf
[0]), (LPARAM
)buf
);
2532 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
2533 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
2535 /* Setting a NULL usage removes the enhanced key usage property. */
2536 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
2538 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
2540 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
2542 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
2544 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
2546 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
2547 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
2548 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
2551 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
2553 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2554 for (i
= 0; i
< purposes
; i
++)
2557 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
2559 int state
= item
.state
>> 12;
2561 if (state
== CheckBitmapIndexChecked
)
2563 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
2565 if (usage
.cUsageIdentifier
)
2566 usage
.rgpszUsageIdentifier
=
2567 HeapReAlloc(GetProcessHeap(), 0,
2568 usage
.rgpszUsageIdentifier
,
2569 (usage
.cUsageIdentifier
+ 1) * sizeof(LPSTR
));
2571 usage
.rgpszUsageIdentifier
=
2572 HeapAlloc(GetProcessHeap(), 0, sizeof(LPSTR
));
2573 if (usage
.rgpszUsageIdentifier
)
2574 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
2575 (LPSTR
)info
->pszOID
;
2579 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
2580 HeapFree(GetProcessHeap(), 0, usage
.rgpszUsageIdentifier
);
2582 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
2583 if (data
->pfPropertiesChanged
)
2584 *data
->pfPropertiesChanged
= TRUE
;
2587 static LRESULT CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
2588 WPARAM wp
, LPARAM lp
)
2590 PROPSHEETPAGEW
*page
;
2592 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2598 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
2599 struct detail_data
*detailData
;
2600 struct edit_cert_data
*editData
;
2602 page
= (PROPSHEETPAGEW
*)lp
;
2603 detailData
= (struct detail_data
*)page
->lParam
;
2604 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
2605 MAX_FRIENDLY_NAME
, 0);
2606 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
2607 ShowScrollBar(description
, SB_VERT
, FALSE
);
2608 editData
= HeapAlloc(GetProcessHeap(), 0,
2609 sizeof(struct edit_cert_data
));
2612 editData
->imageList
= ImageList_Create(16, 16,
2613 ILC_COLOR4
| ILC_MASK
, 4, 0);
2614 if (editData
->imageList
)
2617 COLORREF backColor
= RGB(255, 0, 255);
2619 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
2620 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
2622 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
2624 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
2625 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
2626 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
2627 set_general_cert_properties(hwnd
, editData
);
2633 NMHDR
*hdr
= (NMHDR
*)lp
;
2639 nm
= (NMITEMACTIVATE
*)lp
;
2640 toggle_usage(hwnd
, nm
->iItem
);
2641 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
2644 apply_general_changes(hwnd
);
2653 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
2654 if (LOWORD(wp
) == IDC_DESCRIPTION
)
2656 /* Show/hide scroll bar on description depending on how much
2659 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
2660 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
2662 ShowScrollBar(description
, SB_VERT
, lines
> 1);
2668 case IDC_ADD_PURPOSE
:
2669 if (DialogBoxParamW(hInstance
,
2670 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
2671 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
2672 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
2674 case IDC_ENABLE_ALL_PURPOSES
:
2675 case IDC_DISABLE_ALL_PURPOSES
:
2676 case IDC_ENABLE_SELECTED_PURPOSES
:
2677 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
2678 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
2688 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
2689 PROPSHEETPAGEW
*page
)
2693 struct edit_cert_data
*data
;
2698 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
2699 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
2700 for (i
= 0; i
< cItem
; i
++)
2704 item
.mask
= LVIF_PARAM
;
2707 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
2709 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
2711 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
2713 HeapFree(GetProcessHeap(), 0, (LPSTR
)info
->pszOID
);
2714 HeapFree(GetProcessHeap(), 0, info
);
2718 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2721 ImageList_Destroy(data
->imageList
);
2722 HeapFree(GetProcessHeap(), 0, data
);
2729 static void show_edit_cert_properties_dialog(HWND parent
,
2730 struct detail_data
*data
)
2732 PROPSHEETHEADERW hdr
;
2733 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
2735 TRACE("(%p)\n", data
);
2737 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
2738 page
.dwSize
= sizeof(page
);
2739 page
.dwFlags
= PSP_USECALLBACK
;
2740 page
.pfnCallback
= cert_properties_general_callback
;
2741 page
.hInstance
= hInstance
;
2742 page
.u
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
2743 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
2744 page
.lParam
= (LPARAM
)data
;
2746 memset(&hdr
, 0, sizeof(hdr
));
2747 hdr
.dwSize
= sizeof(hdr
);
2748 hdr
.hwndParent
= parent
;
2749 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
2750 hdr
.hInstance
= hInstance
;
2751 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
2752 hdr
.u3
.ppsp
= &page
;
2754 PropertySheetW(&hdr
);
2757 static void free_detail_fields(struct detail_data
*data
)
2761 for (i
= 0; i
< data
->cFields
; i
++)
2762 HeapFree(GetProcessHeap(), 0, data
->fields
[i
].detailed_value
);
2763 HeapFree(GetProcessHeap(), 0, data
->fields
);
2764 data
->fields
= NULL
;
2768 static void refresh_details_view(HWND hwnd
)
2770 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
2772 struct detail_data
*data
;
2774 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
2775 /* Actually, any index will do, since they all store the same data value */
2776 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
2777 free_detail_fields(data
);
2778 set_fields_selection(hwnd
, data
, curSel
);
2781 static LRESULT CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2784 PROPSHEETPAGEW
*page
;
2785 struct detail_data
*data
;
2787 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
2792 page
= (PROPSHEETPAGEW
*)lp
;
2793 data
= (struct detail_data
*)page
->lParam
;
2794 create_cert_details_list(hwnd
, data
);
2795 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
2796 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
2797 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
2798 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
2803 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
2805 nm
= (NMITEMACTIVATE
*)lp
;
2806 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
2807 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
2809 data
= (struct detail_data
*)nm
->lParam
;
2810 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
2812 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
2813 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
2815 if (data
->fields
[nm
->iItem
].create
)
2816 val
= data
->fields
[nm
->iItem
].create(
2817 data
->pCertViewInfo
->pCertContext
,
2818 data
->fields
[nm
->iItem
].param
);
2824 item
.cchTextMax
= sizeof(buf
) / sizeof(buf
[0]);
2825 item
.mask
= LVIF_TEXT
;
2827 item
.iItem
= nm
->iItem
;
2829 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
2833 /* Select all the text in the control, the next update will
2836 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
2837 add_unformatted_text_to_control(valueCtl
, val
,
2838 val
? strlenW(val
) : 0);
2840 HeapFree(GetProcessHeap(), 0, val
);
2849 FIXME("call CryptUIWizExport\n");
2851 case IDC_EDITPROPERTIES
:
2853 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
2856 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
2857 /* Actually, any index will do, since they all store the same
2860 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
2862 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
2865 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
2866 refresh_details_view(hwnd
);
2870 case WM_REFRESH_VIEW
:
2871 refresh_details_view(hwnd
);
2877 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
2878 PROPSHEETPAGEW
*page
)
2880 struct detail_data
*data
;
2885 data
= (struct detail_data
*)page
->lParam
;
2886 free_detail_fields(data
);
2887 HeapFree(GetProcessHeap(), 0, data
);
2893 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2894 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
2897 struct detail_data
*data
= HeapAlloc(GetProcessHeap(), 0,
2898 sizeof(struct detail_data
));
2902 data
->pCertViewInfo
= pCertViewInfo
;
2903 data
->pfPropertiesChanged
= pfPropertiesChanged
;
2905 data
->fields
= NULL
;
2906 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2907 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2908 page
->dwFlags
= PSP_USECALLBACK
;
2909 page
->pfnCallback
= detail_callback
;
2910 page
->hInstance
= hInstance
;
2911 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
2912 page
->pfnDlgProc
= detail_dlg_proc
;
2913 page
->lParam
= (LPARAM
)data
;
2921 struct hierarchy_data
2923 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2924 HIMAGELIST imageList
;
2928 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
2930 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2931 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
2932 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
2933 data
->pCertViewInfo
->idxCounterSigner
);
2935 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
2936 * therefore always even.
2938 if (index
== provSigner
->csCertChain
- 1)
2939 return (LPARAM
)data
;
2940 return index
<< 1 | 1;
2943 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
2945 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2946 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
2947 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
2948 data
->pCertViewInfo
->idxCounterSigner
);
2951 return provSigner
->csCertChain
- 1;
2955 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
2958 struct hierarchy_data
*data
= NULL
;
2959 HTREEITEM root
= NULL
;
2962 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
2963 TVGN_PARENT
, (LPARAM
)hItem
);
2973 item
.mask
= TVIF_PARAM
;
2975 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
2976 data
= (struct hierarchy_data
*)item
.lParam
;
2981 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
2983 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
2986 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2990 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
2992 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
2993 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2994 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
2995 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
2996 data
->pCertViewInfo
->idxCounterSigner
);
2998 HTREEITEM parent
= NULL
;
3000 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
3001 for (i
= provSigner
->csCertChain
; i
; i
--)
3005 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
3008 TVINSERTSTRUCTW tvis
;
3010 tvis
.hParent
= parent
;
3011 tvis
.hInsertAfter
= TVI_LAST
;
3012 tvis
.u
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
3013 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
3014 tvis
.u
.item
.pszText
= name
;
3015 tvis
.u
.item
.state
= TVIS_EXPANDED
;
3016 tvis
.u
.item
.stateMask
= TVIS_EXPANDED
;
3018 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
3019 CERT_TRUST_IS_PARTIAL_CHAIN
))
3021 /* The root of the chain has a special case: if the chain is
3022 * a partial chain, the icon is a warning icon rather than an
3025 tvis
.u
.item
.iImage
= 2;
3027 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
3029 tvis
.u
.item
.iImage
= 0;
3031 tvis
.u
.item
.iImage
= 1;
3032 tvis
.u
.item
.iSelectedImage
= tvis
.u
.item
.iImage
;
3033 tvis
.u
.item
.lParam
= index_to_lparam(data
, i
- 1);
3034 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
3036 HeapFree(GetProcessHeap(), 0, name
);
3041 static void set_certificate_status(HWND hwnd
, CRYPT_PROVIDER_CERT
*cert
)
3043 /* Select all the text in the control, the next update will replace it */
3044 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
3045 /* Set the highest priority error messages first. */
3046 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
3047 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
3048 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
3049 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
3050 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
3051 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
3052 else if (cert
->dwRevokedReason
)
3053 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
3055 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
3058 static void set_certificate_status_for_end_cert(HWND hwnd
,
3059 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
3061 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
3062 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3063 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
3064 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
3065 pCertViewInfo
->idxCounterSigner
);
3066 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
3067 pCertViewInfo
->idxCert
);
3069 set_certificate_status(status
, provCert
);
3072 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
3074 /* Disable view certificate button until a certificate is selected */
3075 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
3076 show_cert_chain(hwnd
, data
);
3077 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
3080 static void show_dialog_for_selected_cert(HWND hwnd
)
3082 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
3084 struct hierarchy_data
*data
;
3087 memset(&item
, 0, sizeof(item
));
3088 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
3089 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
,
3091 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
3092 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
3093 selection
= lparam_to_index(data
, item
.lParam
);
3096 CRYPT_PROVIDER_SGNR
*provSigner
;
3097 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
3098 BOOL changed
= FALSE
;
3100 provSigner
= WTHelperGetProvSignerFromChain(
3101 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3102 data
->pCertViewInfo
->idxSigner
,
3103 data
->pCertViewInfo
->fCounterSigner
,
3104 data
->pCertViewInfo
->idxCounterSigner
);
3105 memset(&viewInfo
, 0, sizeof(viewInfo
));
3106 viewInfo
.dwSize
= sizeof(viewInfo
);
3107 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
3108 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
3109 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
3110 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
3111 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
3112 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
3113 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
3114 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
3115 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
3118 /* Delete the contents of the tree */
3119 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
3120 /* Reinitialize the tree */
3121 show_cert_hierarchy(hwnd
, data
);
3126 static LRESULT CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3129 PROPSHEETPAGEW
*page
;
3130 struct hierarchy_data
*data
;
3132 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
3134 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
3139 page
= (PROPSHEETPAGEW
*)lp
;
3140 data
= (struct hierarchy_data
*)page
->lParam
;
3141 show_cert_hierarchy(hwnd
, data
);
3150 case TVN_SELCHANGEDW
:
3152 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
3154 CRYPT_PROVIDER_SGNR
*provSigner
;
3156 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
3157 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
3158 provSigner
= WTHelperGetProvSignerFromChain(
3159 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->u
.pCryptProviderData
,
3160 data
->pCertViewInfo
->idxSigner
,
3161 data
->pCertViewInfo
->fCounterSigner
,
3162 data
->pCertViewInfo
->idxCounterSigner
);
3163 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
3164 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
3165 &provSigner
->pasCertChain
[selection
]);
3169 show_dialog_for_selected_cert(hwnd
);
3170 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
3179 case IDC_VIEWCERTIFICATE
:
3180 show_dialog_for_selected_cert(hwnd
);
3184 case WM_REFRESH_VIEW
:
3188 /* Get hierarchy data */
3189 memset(&item
, 0, sizeof(item
));
3190 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
3191 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
3193 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
3194 /* Delete the contents of the tree */
3195 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
3196 /* Reinitialize the tree */
3197 show_cert_hierarchy(hwnd
, data
);
3204 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
3205 PROPSHEETPAGEW
*page
)
3207 struct hierarchy_data
*data
;
3212 data
= (struct hierarchy_data
*)page
->lParam
;
3213 ImageList_Destroy(data
->imageList
);
3214 HeapFree(GetProcessHeap(), 0, data
);
3220 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3221 PROPSHEETPAGEW
*page
)
3223 struct hierarchy_data
*data
= HeapAlloc(GetProcessHeap(), 0,
3224 sizeof(struct hierarchy_data
));
3229 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
3230 if (data
->imageList
)
3233 COLORREF backColor
= RGB(255, 0, 255);
3235 data
->pCertViewInfo
= pCertViewInfo
;
3236 data
->selectedCert
= 0xffffffff;
3238 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
3239 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
3241 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
3243 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3244 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3245 page
->dwFlags
= PSP_USECALLBACK
;
3246 page
->hInstance
= hInstance
;
3247 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
3248 page
->pfnDlgProc
= hierarchy_dlg_proc
;
3249 page
->lParam
= (LPARAM
)data
;
3250 page
->pfnCallback
= hierarchy_callback
;
3254 HeapFree(GetProcessHeap(), 0, data
);
3259 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
3264 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
3268 case PSCB_INITIALIZED
:
3269 /* Get cancel button's position.. */
3270 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
3271 topLeft
.x
= rc
.left
;
3273 ScreenToClient(hwnd
, &topLeft
);
3274 /* hide the cancel button.. */
3275 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
3276 /* get the OK button's size.. */
3277 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
3278 /* and move the OK button to the cancel button's original position. */
3279 MoveWindow(GetDlgItem(hwnd
, IDOK
), topLeft
.x
, topLeft
.y
,
3280 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, FALSE
);
3281 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
3287 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3288 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
3290 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
3292 PROPSHEETPAGEW
*pages
;
3294 HMODULE lib
= LoadLibraryW(riched
);
3296 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
3297 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
3299 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
3301 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
3304 PROPSHEETHEADERW hdr
;
3305 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
3308 memset(&hdr
, 0, sizeof(hdr
));
3309 hdr
.dwSize
= sizeof(hdr
);
3310 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
3311 hdr
.hInstance
= hInstance
;
3312 if (pCertViewInfo
->szTitle
)
3313 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
3315 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
3316 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
3317 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
3319 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
3320 &pages
[hdr
.nPages
]))
3323 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
3325 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
3328 /* Copy each additional page, and create the init dialog struct for it
3330 if (pCertViewInfo
->cPropSheetPages
)
3332 init
= HeapAlloc(GetProcessHeap(), 0,
3333 pCertViewInfo
->cPropSheetPages
*
3334 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
3337 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
3339 memcpy(&pages
[hdr
.nPages
+ i
],
3340 &pCertViewInfo
->rgPropSheetPages
[i
],
3341 sizeof(PROPSHEETPAGEW
));
3342 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
3343 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
3344 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
3346 if (pCertViewInfo
->nStartPage
& 0x8000)
3348 /* Start page index is relative to the number of default
3351 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
3354 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
3355 hdr
.nPages
= nPages
;
3359 SetLastError(ERROR_OUTOFMEMORY
);
3363 /* Ignore the relative flag if there aren't any additional pages */
3364 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
3371 hdr
.u3
.ppsp
= pages
;
3372 hdr
.pfnCallback
= cert_prop_sheet_proc
;
3373 l
= PropertySheetW(&hdr
);
3376 SetLastError(ERROR_CANCELLED
);
3380 HeapFree(GetProcessHeap(), 0, init
);
3381 HeapFree(GetProcessHeap(), 0, pages
);
3384 SetLastError(ERROR_OUTOFMEMORY
);
3389 /***********************************************************************
3390 * CryptUIDlgViewCertificateW (CRYPTUI.@)
3392 BOOL WINAPI
CryptUIDlgViewCertificateW(
3393 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
3395 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
3396 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
3398 WINTRUST_CERT_INFO cert
;
3400 CRYPT_PROVIDER_SGNR
*signer
;
3401 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
3403 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
3405 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
3407 SetLastError(ERROR_INVALID_PARAMETER
);
3410 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
3411 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
3412 if (!viewInfo
.u
.hWVTStateData
)
3414 memset(&wvt
, 0, sizeof(wvt
));
3415 wvt
.cbStruct
= sizeof(wvt
);
3416 wvt
.dwUIChoice
= WTD_UI_NONE
;
3417 if (viewInfo
.dwFlags
&
3418 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
3419 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
3420 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
3421 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
3422 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
3423 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
3424 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
3425 memset(&cert
, 0, sizeof(cert
));
3426 cert
.cbStruct
= sizeof(cert
);
3427 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
3428 cert
.chStores
= viewInfo
.cStores
;
3429 cert
.pahStores
= viewInfo
.rghStores
;
3430 wvt
.u
.pCert
= &cert
;
3431 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
3432 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
3433 viewInfo
.u
.pCryptProviderData
=
3434 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
3435 signer
= WTHelperGetProvSignerFromChain(
3436 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
3437 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
3442 viewInfo
.u
.pCryptProviderData
=
3443 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
3444 signer
= WTHelperGetProvSignerFromChain(
3445 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
3446 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
3447 viewInfo
.idxCounterSigner
);
3448 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
3453 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
3454 if (!viewInfo
.u
.hWVTStateData
)
3456 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
3457 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
3463 /***********************************************************************
3464 * CryptUIDlgViewContext (CRYPTUI.@)
3466 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
3467 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
3471 TRACE("(%d, %p, %p, %s, %08x, %p)\n", dwContextType
, pvContext
, hwnd
,
3472 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
3474 switch (dwContextType
)
3476 case CERT_STORE_CERTIFICATE_CONTEXT
:
3478 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
3480 memset(&viewInfo
, 0, sizeof(viewInfo
));
3481 viewInfo
.dwSize
= sizeof(viewInfo
);
3482 viewInfo
.hwndParent
= hwnd
;
3483 viewInfo
.szTitle
= pwszTitle
;
3484 viewInfo
.pCertContext
= pvContext
;
3485 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
3489 FIXME("unimplemented for context type %d\n", dwContextType
);
3490 SetLastError(E_INVALIDARG
);
3496 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
3497 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
3498 * should be a CA. If neither extension is present, returns
3499 * defaultIfNotSpecified.
3501 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
3503 BOOL isCA
= defaultIfNotSpecified
;
3504 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
3505 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
3509 CERT_BASIC_CONSTRAINTS_INFO
*info
;
3512 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
3513 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
3514 NULL
, (LPBYTE
)&info
, &size
))
3516 if (info
->SubjectType
.cbData
== 1)
3517 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
3523 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
3524 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
3527 CERT_BASIC_CONSTRAINTS2_INFO info
;
3528 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
3530 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
3531 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
3532 0, NULL
, &info
, &size
))
3539 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
3543 if (is_ca_cert(cert
, TRUE
))
3546 storeName
= addressBook
;
3547 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
3548 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
3551 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
3558 SetLastError(E_INVALIDARG
);
3561 if (hDestCertStore
) store
= hDestCertStore
;
3564 if (!(store
= choose_store_for_cert(cert
)))
3566 WARN("unable to open certificate store\n");
3570 ret
= CertAddCertificateContextToStore(store
, cert
,
3571 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
3572 if (!hDestCertStore
) CertCloseStore(store
, 0);
3576 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
3583 SetLastError(E_INVALIDARG
);
3586 if (hDestCertStore
) store
= hDestCertStore
;
3589 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
3590 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
3592 WARN("unable to open certificate store\n");
3596 ret
= CertAddCRLContextToStore(store
, crl
,
3597 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
3598 if (!hDestCertStore
) CertCloseStore(store
, 0);
3602 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
3609 SetLastError(E_INVALIDARG
);
3612 if (hDestCertStore
) store
= hDestCertStore
;
3615 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
3617 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
3618 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
3620 WARN("unable to open certificate store\n");
3624 ret
= CertAddCTLContextToStore(store
, ctl
,
3625 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
3626 if (!hDestCertStore
) CertCloseStore(store
, 0);
3630 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
3631 * CryptQueryObject, against the allowed types. Returns TRUE if the
3632 * type is allowed, FALSE otherwise.
3634 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
3639 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
3640 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
3644 case CERT_QUERY_CONTENT_CERT
:
3645 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
3646 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
3648 case CERT_QUERY_CONTENT_CRL
:
3649 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
3650 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
3652 case CERT_QUERY_CONTENT_CTL
:
3653 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
3654 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
3657 /* The remaining types contain more than one type, so allow
3665 /* No allowed types specified, so any type is allowed */
3669 SetLastError(E_INVALIDARG
);
3674 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
3677 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
3679 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3686 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
3687 sizeof(title
) / sizeof(title
[0]));
3690 LoadStringW(hInstance
, warningID
, error
,
3691 sizeof(error
) / sizeof(error
[0]));
3692 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
3696 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
3698 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
3701 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
3706 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
3707 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
3709 PCCERT_CONTEXT cert
;
3714 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
3716 CertFreeCertificateContext(cert
);
3717 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
3720 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
3722 CertFreeCRLContext(crl
);
3723 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
3726 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
3728 CertFreeCTLContext(ctl
);
3729 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
3736 SetLastError(E_INVALIDARG
);
3740 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
3741 HCERTSTORE source
, HCERTSTORE dest
)
3745 if ((ret
= check_store_context_type(dwFlags
, source
)))
3747 PCCERT_CONTEXT cert
= NULL
;
3748 PCCRL_CONTEXT crl
= NULL
;
3749 PCCTL_CONTEXT ctl
= NULL
;
3752 cert
= CertEnumCertificatesInStore(source
, cert
);
3754 ret
= import_cert(cert
, dest
);
3755 } while (ret
&& cert
);
3757 crl
= CertEnumCRLsInStore(source
, crl
);
3759 ret
= import_crl(crl
, dest
);
3760 } while (ret
&& crl
);
3762 ctl
= CertEnumCTLsInStore(source
, ctl
);
3764 ret
= import_ctl(ctl
, dest
);
3765 } while (ret
&& ctl
);
3768 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
3772 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
3773 DWORD
*pContentType
)
3775 HCERTSTORE store
= NULL
;
3776 DWORD contentType
= 0, expectedContentTypeFlags
;
3779 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
3780 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
3782 expectedContentTypeFlags
=
3783 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
3784 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
3785 CERT_QUERY_CONTENT_FLAG_PFX
;
3786 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
3787 expectedContentTypeFlags
|=
3788 CERT_QUERY_CONTENT_FLAG_CERT
|
3789 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
3790 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
3791 expectedContentTypeFlags
|=
3792 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
3793 CERT_QUERY_CONTENT_FLAG_CRL
;
3794 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
3795 expectedContentTypeFlags
|=
3796 CERT_QUERY_CONTENT_FLAG_CTL
|
3797 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
3800 expectedContentTypeFlags
=
3801 CERT_QUERY_CONTENT_FLAG_CERT
|
3802 CERT_QUERY_CONTENT_FLAG_CTL
|
3803 CERT_QUERY_CONTENT_FLAG_CRL
|
3804 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
3805 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
3806 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
3807 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
3808 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
3809 CERT_QUERY_CONTENT_FLAG_PFX
;
3811 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
3812 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
3813 &contentType
, NULL
, &store
, NULL
, NULL
);
3815 *pContentType
= contentType
;
3819 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
3820 LPCWSTR fileName
, HCERTSTORE dest
)
3825 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
3827 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
3828 CertCloseStore(source
, 0);
3835 struct ImportWizData
3839 LPCWSTR pwszWizardTitle
;
3840 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
3844 HCERTSTORE hDestCertStore
;
3850 static LRESULT CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3859 struct ImportWizData
*data
;
3860 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
3861 WCHAR fontFace
[MAX_STRING_LEN
];
3862 HDC hDC
= GetDC(hwnd
);
3865 data
= (struct ImportWizData
*)page
->lParam
;
3866 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
,
3867 sizeof(fontFace
) / sizeof(fontFace
[0]));
3868 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
3869 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
3870 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
3871 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
3872 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
3873 (WPARAM
)data
->titleFont
, TRUE
);
3874 ReleaseDC(hwnd
, hDC
);
3879 NMHDR
*hdr
= (NMHDR
*)lp
;
3884 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
3894 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
3896 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
3898 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
3899 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
3900 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
3901 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
3903 static const WCHAR filter_all
[] = { '*','.','*',0 };
3905 struct StringToFilter
3910 } import_filters
[] = {
3911 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
3912 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
3913 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
3914 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
3915 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
3916 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
3917 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
3920 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
3923 int len
, totalLen
= 2;
3924 LPWSTR filter
= NULL
, str
;
3926 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
3928 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
3929 (dwFlags
& import_filters
[i
].allowFlags
))
3931 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
3932 totalLen
+= len
+ strlenW(import_filters
[i
].filter
) + 2;
3935 filter
= HeapAlloc(GetProcessHeap(), 0, totalLen
* sizeof(WCHAR
));
3941 for (i
= 0; i
< sizeof(import_filters
) / sizeof(import_filters
[0]); i
++)
3943 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
3944 (dwFlags
& import_filters
[i
].allowFlags
))
3946 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
3948 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
3951 strcpyW(ptr
, import_filters
[i
].filter
);
3952 ptr
+= strlenW(import_filters
[i
].filter
) + 1;
3960 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
3966 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
3967 OPEN_EXISTING
, 0, NULL
);
3968 if (file
!= INVALID_HANDLE_VALUE
)
3970 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
3971 &data
->contentType
);
3975 warningID
= IDS_IMPORT_BAD_FORMAT
;
3976 else if (!check_store_context_type(data
->dwFlags
, source
))
3977 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
3980 data
->importSrc
.dwSubjectChoice
=
3981 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
3982 data
->importSrc
.u
.hCertStore
= source
;
3983 data
->freeSource
= TRUE
;
3988 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
3995 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3997 LPWSTR msgBuf
, fullError
;
3999 if (data
->pwszWizardTitle
)
4000 pTitle
= data
->pwszWizardTitle
;
4003 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
4004 sizeof(title
) / sizeof(title
[0]));
4007 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
,
4008 sizeof(error
) / sizeof(error
[0]));
4010 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
4011 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
4012 fullError
= HeapAlloc(GetProcessHeap(), 0,
4013 (strlenW(error
) + strlenW(fileName
) + strlenW(msgBuf
) + 3)
4017 LPWSTR ptr
= fullError
;
4019 strcpyW(ptr
, error
);
4020 ptr
+= strlenW(error
);
4021 strcpyW(ptr
, fileName
);
4022 ptr
+= strlenW(fileName
);
4025 strcpyW(ptr
, msgBuf
);
4026 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
4027 HeapFree(GetProcessHeap(), 0, fullError
);
4034 static LRESULT CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4038 struct ImportWizData
*data
;
4044 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4046 data
= (struct ImportWizData
*)page
->lParam
;
4047 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
4052 NMHDR
*hdr
= (NMHDR
*)lp
;
4057 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
4058 PSWIZB_BACK
| PSWIZB_NEXT
);
4063 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
4064 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
4066 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4069 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4070 IDS_IMPORT_EMPTY_FILE
);
4071 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4076 LPWSTR fileName
= HeapAlloc(GetProcessHeap(), 0,
4077 (len
+ 1) * sizeof(WCHAR
));
4081 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
4083 if (!import_validate_filename(hwnd
, data
, fileName
))
4085 HeapFree(GetProcessHeap(), 0, fileName
);
4086 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4090 data
->fileName
= fileName
;
4101 case IDC_IMPORT_BROWSE_FILE
:
4104 WCHAR fileBuf
[MAX_PATH
];
4106 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4107 memset(&ofn
, 0, sizeof(ofn
));
4108 ofn
.lStructSize
= sizeof(ofn
);
4109 ofn
.hwndOwner
= hwnd
;
4110 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
4111 ofn
.lpstrFile
= fileBuf
;
4112 ofn
.nMaxFile
= sizeof(fileBuf
) / sizeof(fileBuf
[0]);
4114 if (GetOpenFileNameW(&ofn
))
4115 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
4116 0, (LPARAM
)ofn
.lpstrFile
);
4117 HeapFree(GetProcessHeap(), 0, (LPWSTR
)ofn
.lpstrFilter
);
4126 static LRESULT CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4130 struct ImportWizData
*data
;
4136 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4138 data
= (struct ImportWizData
*)page
->lParam
;
4139 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
4140 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
, 0, 0);
4141 if (data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
)
4142 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
4143 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
4144 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
4149 NMHDR
*hdr
= (NMHDR
*)lp
;
4154 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
4155 PSWIZB_BACK
| PSWIZB_NEXT
);
4160 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4161 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
4162 !data
->hDestCertStore
)
4164 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4165 IDS_IMPORT_SELECT_STORE
);
4166 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4177 case IDC_IMPORT_AUTO_STORE
:
4178 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4179 data
->autoDest
= TRUE
;
4180 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
4181 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
4183 case IDC_IMPORT_SPECIFY_STORE
:
4184 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4185 data
->autoDest
= FALSE
;
4186 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
4187 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
4189 case IDC_IMPORT_BROWSE_STORE
:
4191 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
4192 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
4193 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
4194 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
4197 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4198 selectInfo
.dwSize
= sizeof(selectInfo
);
4199 selectInfo
.parent
= hwnd
;
4200 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
4201 selectInfo
.pwszTitle
= selectInfo
.pwszTitle
= NULL
;
4202 selectInfo
.pEnumData
= &enumData
;
4203 selectInfo
.pfnSelectedStoreCallback
= NULL
;
4204 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
4206 WCHAR storeTitle
[MAX_STRING_LEN
];
4208 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
,
4209 storeTitle
, sizeof(storeTitle
) / sizeof(storeTitle
[0]));
4210 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
4211 0, (LPARAM
)storeTitle
);
4212 data
->hDestCertStore
= store
;
4213 data
->freeDest
= TRUE
;
4223 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
4225 WCHAR text
[MAX_STRING_LEN
];
4229 item
.mask
= LVIF_TEXT
;
4230 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
4232 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
,
4233 sizeof(text
)/ sizeof(text
[0]));
4234 item
.pszText
= text
;
4235 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
4238 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
,
4239 sizeof(text
)/ sizeof(text
[0]));
4241 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
,
4242 sizeof(text
)/ sizeof(text
[0]));
4243 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
4244 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
4246 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
,
4247 sizeof(text
)/ sizeof(text
[0]));
4248 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
4249 switch (data
->contentType
)
4251 case CERT_QUERY_CONTENT_CERT
:
4252 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4253 contentID
= IDS_IMPORT_CONTENT_CERT
;
4255 case CERT_QUERY_CONTENT_CRL
:
4256 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4257 contentID
= IDS_IMPORT_CONTENT_CRL
;
4259 case CERT_QUERY_CONTENT_CTL
:
4260 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4261 contentID
= IDS_IMPORT_CONTENT_CTL
;
4263 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
4264 contentID
= IDS_IMPORT_CONTENT_CMS
;
4266 case CERT_QUERY_CONTENT_FLAG_PFX
:
4267 contentID
= IDS_IMPORT_CONTENT_PFX
;
4270 contentID
= IDS_IMPORT_CONTENT_STORE
;
4273 LoadStringW(hInstance
, contentID
, text
, sizeof(text
)/ sizeof(text
[0]));
4275 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
4278 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
4280 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
,
4281 sizeof(text
)/ sizeof(text
[0]));
4282 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
4284 item
.pszText
= data
->fileName
;
4285 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
4289 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
4290 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
4294 switch (pImportSrc
->dwSubjectChoice
)
4296 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
4297 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
4298 pImportSrc
->u
.pwszFileName
, hDestCertStore
);
4300 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
4301 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
4302 ret
= import_cert(pImportSrc
->u
.pCertContext
, hDestCertStore
);
4304 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
4306 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
4307 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
4308 ret
= import_crl(pImportSrc
->u
.pCRLContext
, hDestCertStore
);
4310 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
4312 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
4313 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
4314 ret
= import_ctl(pImportSrc
->u
.pCTLContext
, hDestCertStore
);
4316 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
4318 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
4319 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
4320 pImportSrc
->u
.hCertStore
, hDestCertStore
);
4323 WARN("unknown source type: %u\n", pImportSrc
->dwSubjectChoice
);
4324 SetLastError(E_INVALIDARG
);
4330 static LRESULT CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4334 struct ImportWizData
*data
;
4340 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4341 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
4345 data
= (struct ImportWizData
*)page
->lParam
;
4346 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
4347 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4348 (WPARAM
)data
->titleFont
, TRUE
);
4349 GetWindowRect(lv
, &rc
);
4350 column
.mask
= LVCF_WIDTH
;
4351 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
4352 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
4353 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
4354 show_import_details(lv
, data
);
4359 NMHDR
*hdr
= (NMHDR
*)lp
;
4365 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
4367 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4368 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
4369 show_import_details(lv
, data
);
4370 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
4371 PSWIZB_BACK
| PSWIZB_FINISH
);
4377 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
4378 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
4379 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
4381 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
4384 if (data
->pwszWizardTitle
)
4385 pTitle
= data
->pwszWizardTitle
;
4388 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
,
4389 sizeof(title
) / sizeof(title
[0]));
4392 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
,
4393 sizeof(message
) / sizeof(message
[0]));
4394 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
4397 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4398 IDS_IMPORT_SUCCEEDED
);
4408 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
4409 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
4410 HCERTSTORE hDestCertStore
)
4412 PROPSHEETHEADERW hdr
;
4413 PROPSHEETPAGEW pages
[4];
4414 struct ImportWizData data
;
4417 data
.dwFlags
= dwFlags
;
4418 data
.pwszWizardTitle
= pwszWizardTitle
;
4420 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
4422 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
4423 data
.fileName
= NULL
;
4424 data
.freeSource
= FALSE
;
4425 data
.hDestCertStore
= hDestCertStore
;
4426 data
.freeDest
= FALSE
;
4427 data
.autoDest
= TRUE
;
4428 data
.success
= TRUE
;
4430 memset(&pages
, 0, sizeof(pages
));
4432 pages
[nPages
].dwSize
= sizeof(pages
[0]);
4433 pages
[nPages
].hInstance
= hInstance
;
4434 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
4435 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
4436 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
4437 pages
[nPages
].lParam
= (LPARAM
)&data
;
4441 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
4443 pages
[nPages
].dwSize
= sizeof(pages
[0]);
4444 pages
[nPages
].hInstance
= hInstance
;
4445 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
4446 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
4447 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
4448 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
4449 pages
[nPages
].pszHeaderSubTitle
=
4450 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
4451 pages
[nPages
].lParam
= (LPARAM
)&data
;
4456 switch (pImportSrc
->dwSubjectChoice
)
4458 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
4459 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
4461 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
4462 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
4464 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
4465 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
4467 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
4468 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
4473 pages
[nPages
].dwSize
= sizeof(pages
[0]);
4474 pages
[nPages
].hInstance
= hInstance
;
4475 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
4476 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
4477 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
4478 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
4479 pages
[nPages
].pszHeaderSubTitle
=
4480 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
4481 pages
[nPages
].lParam
= (LPARAM
)&data
;
4484 pages
[nPages
].dwSize
= sizeof(pages
[0]);
4485 pages
[nPages
].hInstance
= hInstance
;
4486 pages
[nPages
].u
.pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
4487 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
4488 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
4489 pages
[nPages
].lParam
= (LPARAM
)&data
;
4492 memset(&hdr
, 0, sizeof(hdr
));
4493 hdr
.dwSize
= sizeof(hdr
);
4494 hdr
.hwndParent
= hwndParent
;
4495 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
4497 hdr
.hInstance
= hInstance
;
4498 if (pwszWizardTitle
)
4499 hdr
.pszCaption
= pwszWizardTitle
;
4501 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
4502 hdr
.u3
.ppsp
= pages
;
4503 hdr
.nPages
= nPages
;
4504 hdr
.u4
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
4505 hdr
.u5
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
4506 PropertySheetW(&hdr
);
4507 HeapFree(GetProcessHeap(), 0, data
.fileName
);
4508 if (data
.freeSource
&&
4509 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
4510 CertCloseStore(data
.importSrc
.u
.hCertStore
, 0);
4511 DeleteObject(data
.titleFont
);
4512 return data
.success
;
4515 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
4516 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
4520 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
4521 pImportSrc
, hDestCertStore
);
4524 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
4526 SetLastError(E_INVALIDARG
);
4530 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4531 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
4533 else if (pImportSrc
)
4534 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
4538 /* Can't have no UI without specifying source */
4539 SetLastError(E_INVALIDARG
);