| /* |
| * Internet control panel applet: security propsheet |
| * |
| * Copyright 2011 Detlef Riekenberg |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| * |
| */ |
| |
| #define COBJMACROS |
| #define CONST_VTABLE |
| |
| #include <stdarg.h> |
| #include <windef.h> |
| #include <winbase.h> |
| #include <winuser.h> |
| #include <prsht.h> |
| #include "commctrl.h" |
| |
| #include "ole2.h" |
| #include "urlmon.h" |
| #include "initguid.h" |
| #include "winreg.h" |
| #include "shlwapi.h" |
| |
| #include "inetcpl.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(inetcpl); |
| |
| typedef struct secdlg_data_s { |
| HWND hsec; /* security propsheet */ |
| HWND hlv; /* listview */ |
| HWND htb; /* trackbar */ |
| IInternetSecurityManager *sec_mgr; |
| IInternetZoneManager *zone_mgr; |
| DWORD zone_enumerator; |
| DWORD num_zones; |
| ZONEATTRIBUTES *zone_attr; |
| DWORD *zones; |
| DWORD *levels; |
| HIMAGELIST himages; |
| DWORD last_lv_index; |
| DWORD last_level; |
| } secdlg_data; |
| |
| #define NUM_TRACKBAR_POS 5 |
| |
| static DWORD url_templates[] = {URLTEMPLATE_CUSTOM, |
| URLTEMPLATE_LOW, |
| URLTEMPLATE_MEDLOW, |
| URLTEMPLATE_MEDIUM, |
| URLTEMPLATE_MEDHIGH, |
| URLTEMPLATE_HIGH}; |
| |
| /********************************************************************* |
| * index_from_urltemplate [internal] |
| * |
| */ |
| static DWORD index_from_urltemplate(URLTEMPLATE value) |
| { |
| |
| DWORD index = sizeof(url_templates) / sizeof(url_templates[0]); |
| |
| while((index > 0) && (url_templates[index-1] != value)) |
| index--; |
| |
| index--; /* table entries are 0 based */ |
| if (!index && value) |
| FIXME("URLTEMPLATE 0x%x not supported\n", value); |
| |
| TRACE("URLTEMPLATE 0x%08x=> Level %d\n", value, index); |
| return index; |
| } |
| |
| /********************************************************************* |
| * update_security_level [internal] |
| * |
| */ |
| static void update_security_level(secdlg_data *sd, DWORD lv_index, DWORD tb_index) |
| { |
| WCHAR name[512]; |
| DWORD current_index; |
| |
| TRACE("(%p, lv_index: %u, tb_index: %u)\n", sd, lv_index, tb_index); |
| |
| if ((sd->levels[lv_index] != sd->last_level) || (tb_index > 0)) { |
| /* show or hide the trackbar */ |
| if (!sd->levels[lv_index] || !sd->last_level) |
| ShowWindow(sd->htb, sd->levels[lv_index] ? SW_NORMAL : SW_HIDE); |
| |
| current_index = (tb_index > 0) ? tb_index : index_from_urltemplate(sd->levels[lv_index]); |
| |
| name[0] = 0; |
| LoadStringW(hcpl, IDS_SEC_LEVEL0 + current_index, name, sizeof(name)/sizeof(name[0])); |
| TRACE("new level #%d: %s\n", current_index, debugstr_w(name)); |
| SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_LEVEL), name); |
| |
| name[0] = 0; |
| LoadStringW(hcpl, IDS_SEC_LEVEL0_INFO + (current_index * 0x10), name, sizeof(name)/sizeof(name[0])); |
| TRACE("new level info: %s\n", debugstr_w(name)); |
| SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_LEVEL_INFO), name); |
| |
| if (current_index) |
| SendMessageW(sd->htb, TBM_SETPOS, TRUE, NUM_TRACKBAR_POS - current_index); |
| |
| sd->last_level = sd->levels[lv_index]; |
| |
| } |
| } |
| |
| /********************************************************************* |
| * update_zone_info [internal] |
| * |
| */ |
| static void update_zone_info(secdlg_data *sd, DWORD lv_index) |
| { |
| ZONEATTRIBUTES *za = &sd->zone_attr[lv_index]; |
| WCHAR name[MAX_PATH]; |
| DWORD len; |
| |
| SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_ZONE_INFO), za->szDescription); |
| |
| len = LoadStringW(hcpl, IDS_SEC_SETTINGS, name, sizeof(name)/sizeof(*name)); |
| lstrcpynW(&name[len], za->szDisplayName, sizeof(name)/sizeof(*name) - len - 1); |
| |
| TRACE("new title: %s\n", debugstr_w(name)); |
| SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_GROUP), name); |
| |
| update_security_level(sd, lv_index, 0); |
| sd->last_lv_index = lv_index; |
| } |
| |
| /********************************************************************* |
| * add_zone_to_listview [internal] |
| * |
| */ |
| static void add_zone_to_listview(secdlg_data *sd, DWORD *pindex, DWORD zone) |
| { |
| DWORD lv_index = *pindex; |
| ZONEATTRIBUTES *za = &sd->zone_attr[lv_index]; |
| LVITEMW lvitem; |
| HRESULT hr; |
| INT iconid = 0; |
| HMODULE hdll = NULL; |
| WCHAR * ptr; |
| HICON icon; |
| |
| TRACE("item %d (zone %d)\n", lv_index, zone); |
| |
| sd->zones[lv_index] = zone; |
| |
| memset(&lvitem, 0, sizeof(LVITEMW)); |
| memset(za, 0, sizeof(ZONEATTRIBUTES)); |
| za->cbSize = sizeof(ZONEATTRIBUTES); |
| hr = IInternetZoneManager_GetZoneAttributes(sd->zone_mgr, zone, za); |
| if (SUCCEEDED(hr)) { |
| TRACE("displayname: %s\n", debugstr_w(za->szDisplayName)); |
| TRACE("description: %s\n", debugstr_w(za->szDescription)); |
| TRACE("minlevel: 0x%x, recommended: 0x%x, current: 0x%x (flags: 0x%x)\n", za->dwTemplateMinLevel, |
| za->dwTemplateRecommended, za->dwTemplateCurrentLevel, za->dwFlags); |
| |
| if (za->dwFlags & ZAFLAGS_NO_UI ) { |
| TRACE("item %d (zone %d): UI disabled for %s\n", lv_index, zone, debugstr_w(za->szDisplayName)); |
| return; |
| } |
| |
| sd->levels[lv_index] = za->dwTemplateCurrentLevel; |
| |
| lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; |
| lvitem.iItem = lv_index; |
| lvitem.iSubItem = 0; |
| lvitem.pszText = za->szDisplayName; |
| lvitem.lParam = (LPARAM) zone; |
| |
| /* format is "filename.ext#iconid" */ |
| ptr = StrChrW(za->szIconPath, '#'); |
| if (ptr) { |
| *ptr = 0; |
| ptr++; |
| iconid = StrToIntW(ptr); |
| hdll = LoadLibraryExW(za->szIconPath, NULL, LOAD_LIBRARY_AS_DATAFILE); |
| TRACE("%p: icon #%d from %s\n", hdll, iconid, debugstr_w(za->szIconPath)); |
| |
| icon = LoadImageW(hdll, MAKEINTRESOURCEW(iconid), IMAGE_ICON, GetSystemMetrics(SM_CXICON), |
| GetSystemMetrics(SM_CYICON), LR_SHARED); |
| |
| if (!icon) { |
| FIXME("item %d (zone %d): missing icon #%d in %s\n", lv_index, zone, iconid, debugstr_w(za->szIconPath)); |
| } |
| |
| /* the failure result (NULL) from LoadImageW let ImageList_AddIcon fail |
| with -1, which is reused in ListView_InsertItemW to disable the image */ |
| lvitem.iImage = ImageList_AddIcon(sd->himages, icon); |
| } |
| else |
| FIXME("item %d (zone %d): malformed szIconPath %s\n", lv_index, zone, debugstr_w(za->szIconPath)); |
| |
| if (ListView_InsertItemW(sd->hlv, &lvitem) >= 0) { |
| /* activate first item in the listview */ |
| if (! lv_index) { |
| lvitem.state = LVIS_FOCUSED | LVIS_SELECTED; |
| lvitem.stateMask = LVIS_FOCUSED | LVIS_SELECTED; |
| SendMessageW(sd->hlv, LVM_SETITEMSTATE, 0, (LPARAM) &lvitem); |
| sd->last_level = ~0; |
| update_zone_info(sd, lv_index); |
| } |
| (*pindex)++; |
| } |
| FreeLibrary(hdll); |
| } |
| else |
| FIXME("item %d (zone %d): GetZoneAttributes failed with 0x%x\n", lv_index, zone, hr); |
| } |
| |
| /********************************************************************* |
| * security_cleanup_zones [internal] |
| * |
| */ |
| static void security_cleanup_zones(secdlg_data *sd) |
| { |
| if (sd->zone_enumerator) { |
| IInternetZoneManager_DestroyZoneEnumerator(sd->zone_mgr, sd->zone_enumerator); |
| } |
| |
| if (sd->zone_mgr) { |
| IInternetZoneManager_Release(sd->zone_mgr); |
| } |
| |
| if (sd->sec_mgr) { |
| IInternetSecurityManager_Release(sd->sec_mgr); |
| } |
| } |
| |
| /********************************************************************* |
| * security_enum_zones [internal] |
| * |
| */ |
| static HRESULT security_enum_zones(secdlg_data * sd) |
| { |
| HRESULT hr; |
| |
| hr = CoInternetCreateSecurityManager(NULL, &sd->sec_mgr, 0); |
| if (SUCCEEDED(hr)) { |
| hr = CoInternetCreateZoneManager(NULL, &sd->zone_mgr, 0); |
| if (SUCCEEDED(hr)) { |
| hr = IInternetZoneManager_CreateZoneEnumerator(sd->zone_mgr, &sd->zone_enumerator, &sd->num_zones, 0); |
| } |
| } |
| return hr; |
| } |
| |
| /********************************************************************* |
| * security_on_destroy [internal] |
| * |
| * handle WM_NCDESTROY |
| * |
| */ |
| static INT_PTR security_on_destroy(secdlg_data * sd) |
| { |
| TRACE("(%p)\n", sd); |
| |
| heap_free(sd->zone_attr); |
| heap_free(sd->zones); |
| if (sd->himages) { |
| SendMessageW(sd->hlv, LVM_SETIMAGELIST, LVSIL_NORMAL, 0); |
| ImageList_Destroy(sd->himages); |
| } |
| |
| security_cleanup_zones(sd); |
| SetWindowLongPtrW(sd->hsec, DWLP_USER, 0); |
| heap_free(sd); |
| return TRUE; |
| } |
| |
| /********************************************************************* |
| * security_on_initdialog [internal] |
| * |
| * handle WM_INITDIALOG |
| * |
| */ |
| static INT_PTR security_on_initdialog(HWND hsec) |
| { |
| secdlg_data *sd; |
| HRESULT hr; |
| DWORD current_zone; |
| DWORD lv_index = 0; |
| DWORD i; |
| |
| sd = heap_alloc_zero(sizeof(secdlg_data)); |
| SetWindowLongPtrW(hsec, DWLP_USER, (LONG_PTR) sd); |
| if (!sd) { |
| return FALSE; |
| } |
| |
| sd->hsec = hsec; |
| sd->hlv = GetDlgItem(hsec, IDC_SEC_LISTVIEW); |
| sd->htb = GetDlgItem(hsec, IDC_SEC_TRACKBAR); |
| |
| EnableWindow(sd->htb, FALSE); /* not changeable yet */ |
| |
| TRACE("(%p) (data: %p, listview: %p, trackbar: %p)\n", hsec, sd, sd->hlv, sd->htb); |
| |
| SendMessageW(sd->htb, TBM_SETRANGE, FALSE, MAKELONG(0, NUM_TRACKBAR_POS - 1)); |
| SendMessageW(sd->htb, TBM_SETTICFREQ, 1, 0 ); |
| |
| /* Create the image lists for the listview */ |
| sd->himages = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_COLOR32 | ILC_MASK, 1, 1); |
| |
| TRACE("using imagelist: %p\n", sd->himages); |
| if (!sd->himages) { |
| ERR("ImageList_Create failed!\n"); |
| return FALSE; |
| } |
| SendMessageW(sd->hlv, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)sd->himages); |
| |
| hr = security_enum_zones(sd); |
| if (FAILED(hr)) { |
| ERR("got 0x%x\n", hr); |
| security_on_destroy(sd); |
| return FALSE; |
| } |
| |
| TRACE("found %d zones\n", sd->num_zones); |
| |
| /* remember ZONEATTRIBUTES for a listview entry */ |
| sd->zone_attr = heap_alloc(sizeof(ZONEATTRIBUTES) * sd->num_zones); |
| if (!sd->zone_attr) { |
| security_on_destroy(sd); |
| return FALSE; |
| } |
| |
| /* remember zone number and current security level for a listview entry */ |
| sd->zones = heap_alloc((sizeof(DWORD) + sizeof(DWORD)) * sd->num_zones); |
| if (!sd->zones) { |
| security_on_destroy(sd); |
| return FALSE; |
| } |
| sd->levels = &sd->zones[sd->num_zones]; |
| |
| /* use the same order as visible with native inetcpl.cpl */ |
| add_zone_to_listview(sd, &lv_index, URLZONE_INTERNET); |
| add_zone_to_listview(sd, &lv_index, URLZONE_INTRANET); |
| add_zone_to_listview(sd, &lv_index, URLZONE_TRUSTED); |
| add_zone_to_listview(sd, &lv_index, URLZONE_UNTRUSTED); |
| |
| for (i = 0; i < sd->num_zones; i++) |
| { |
| hr = IInternetZoneManager_GetZoneAt(sd->zone_mgr, sd->zone_enumerator, i, ¤t_zone); |
| if (SUCCEEDED(hr) && (current_zone != (DWORD)URLZONE_INVALID)) { |
| if (!current_zone || (current_zone > URLZONE_UNTRUSTED)) { |
| add_zone_to_listview(sd, &lv_index, current_zone); |
| } |
| } |
| } |
| return TRUE; |
| } |
| |
| /********************************************************************* |
| * security_on_notify [internal] |
| * |
| * handle WM_NOTIFY |
| * |
| */ |
| static INT_PTR security_on_notify(secdlg_data *sd, WPARAM wparam, LPARAM lparam) |
| { |
| NMLISTVIEW *nm; |
| |
| nm = (NMLISTVIEW *) lparam; |
| switch (nm->hdr.code) |
| { |
| case LVN_ITEMCHANGED: |
| TRACE("LVN_ITEMCHANGED (0x%lx, 0x%lx) from %p with code: %d (item: %d, uNewState: %u)\n", |
| wparam, lparam, nm->hdr.hwndFrom, nm->hdr.code, nm->iItem, nm->uNewState); |
| if ((nm->uNewState & LVIS_SELECTED) == LVIS_SELECTED) { |
| update_zone_info(sd, nm->iItem); |
| } |
| break; |
| |
| case PSN_APPLY: |
| TRACE("PSN_APPLY (0x%lx, 0x%lx) from %p with code: %d\n", wparam, lparam, |
| nm->hdr.hwndFrom, nm->hdr.code); |
| break; |
| |
| default: |
| TRACE("WM_NOTIFY (0x%lx, 0x%lx) from %p with code: %d\n", wparam, lparam, |
| nm->hdr.hwndFrom, nm->hdr.code); |
| |
| } |
| return FALSE; |
| } |
| |
| /********************************************************************* |
| * security_dlgproc [internal] |
| * |
| */ |
| INT_PTR CALLBACK security_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) |
| { |
| secdlg_data *sd; |
| |
| if (msg == WM_INITDIALOG) { |
| return security_on_initdialog(hwnd); |
| } |
| |
| sd = (secdlg_data *)GetWindowLongPtrW(hwnd, DWLP_USER); |
| if (sd) { |
| switch (msg) |
| { |
| case WM_NOTIFY: |
| return security_on_notify(sd, wparam, lparam); |
| |
| case WM_NCDESTROY: |
| return security_on_destroy(sd); |
| |
| default: |
| /* do not flood the log */ |
| if ((msg == WM_SETCURSOR) || (msg == WM_NCHITTEST) || |
| (msg == WM_MOUSEMOVE) || (msg == WM_MOUSEACTIVATE) || (msg == WM_PARENTNOTIFY)) |
| return FALSE; |
| |
| TRACE("(%p, 0x%08x/%03d, 0x%08lx, 0x%08lx)\n", hwnd, msg, msg, wparam, lparam); |
| } |
| } |
| return FALSE; |
| } |