1 /* 2 * Internet control panel applet: security propsheet 3 * 4 * Copyright 2011 Detlef Riekenberg 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * 20 */ 21 22 #include "inetcpl.h" 23 24 typedef struct secdlg_data_s { 25 HWND hsec; /* security propsheet */ 26 HWND hlv; /* listview */ 27 HWND htb; /* trackbar */ 28 IInternetSecurityManager *sec_mgr; 29 IInternetZoneManager *zone_mgr; 30 DWORD zone_enumerator; 31 DWORD num_zones; 32 ZONEATTRIBUTES *zone_attr; 33 DWORD *zones; 34 DWORD *levels; 35 HIMAGELIST himages; 36 DWORD last_lv_index; 37 DWORD last_level; 38 } secdlg_data; 39 40 #define NUM_TRACKBAR_POS 5 41 42 static DWORD url_templates[] = {URLTEMPLATE_CUSTOM, 43 URLTEMPLATE_LOW, 44 URLTEMPLATE_MEDLOW, 45 URLTEMPLATE_MEDIUM, 46 URLTEMPLATE_MEDHIGH, 47 URLTEMPLATE_HIGH}; 48 49 /********************************************************************* 50 * index_from_urltemplate [internal] 51 * 52 */ 53 static DWORD index_from_urltemplate(URLTEMPLATE value) 54 { 55 56 DWORD index = sizeof(url_templates) / sizeof(url_templates[0]); 57 58 while((index > 0) && (url_templates[index-1] != value)) 59 index--; 60 61 index--; /* table entries are 0 based */ 62 if (!index && value) 63 FIXME("URLTEMPLATE 0x%x not supported\n", value); 64 65 TRACE("URLTEMPLATE 0x%08x=> Level %d\n", value, index); 66 return index; 67 } 68 69 /********************************************************************* 70 * update_security_level [internal] 71 * 72 */ 73 static void update_security_level(secdlg_data *sd, DWORD lv_index, DWORD tb_index) 74 { 75 WCHAR name[512]; 76 DWORD current_index; 77 78 TRACE("(%p, lv_index: %u, tb_index: %u)\n", sd, lv_index, tb_index); 79 80 if ((sd->levels[lv_index] != sd->last_level) || (tb_index > 0)) { 81 /* show or hide the trackbar */ 82 if (!sd->levels[lv_index] || !sd->last_level) 83 ShowWindow(sd->htb, sd->levels[lv_index] ? SW_NORMAL : SW_HIDE); 84 85 current_index = (tb_index > 0) ? tb_index : index_from_urltemplate(sd->levels[lv_index]); 86 87 name[0] = 0; 88 LoadStringW(hcpl, IDS_SEC_LEVEL0 + current_index, name, sizeof(name)/sizeof(name[0])); 89 TRACE("new level #%d: %s\n", current_index, debugstr_w(name)); 90 SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_LEVEL), name); 91 92 name[0] = 0; 93 LoadStringW(hcpl, IDS_SEC_LEVEL0_INFO + (current_index * 0x10), name, sizeof(name)/sizeof(name[0])); 94 TRACE("new level info: %s\n", debugstr_w(name)); 95 SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_LEVEL_INFO), name); 96 97 if (current_index) 98 SendMessageW(sd->htb, TBM_SETPOS, TRUE, NUM_TRACKBAR_POS - current_index); 99 100 sd->last_level = sd->levels[lv_index]; 101 102 } 103 } 104 105 /********************************************************************* 106 * update_zone_info [internal] 107 * 108 */ 109 static void update_zone_info(secdlg_data *sd, DWORD lv_index) 110 { 111 ZONEATTRIBUTES *za = &sd->zone_attr[lv_index]; 112 WCHAR name[MAX_PATH]; 113 DWORD len; 114 115 SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_ZONE_INFO), za->szDescription); 116 117 len = LoadStringW(hcpl, IDS_SEC_SETTINGS, name, sizeof(name)/sizeof(*name)); 118 lstrcpynW(&name[len], za->szDisplayName, sizeof(name)/sizeof(*name) - len - 1); 119 120 TRACE("new title: %s\n", debugstr_w(name)); 121 SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_GROUP), name); 122 123 update_security_level(sd, lv_index, 0); 124 sd->last_lv_index = lv_index; 125 } 126 127 /********************************************************************* 128 * add_zone_to_listview [internal] 129 * 130 */ 131 static void add_zone_to_listview(secdlg_data *sd, DWORD *pindex, DWORD zone) 132 { 133 DWORD lv_index = *pindex; 134 ZONEATTRIBUTES *za = &sd->zone_attr[lv_index]; 135 LVITEMW lvitem; 136 HRESULT hr; 137 INT iconid = 0; 138 HMODULE hdll = NULL; 139 WCHAR * ptr; 140 HICON icon; 141 142 TRACE("item %d (zone %d)\n", lv_index, zone); 143 144 sd->zones[lv_index] = zone; 145 146 memset(&lvitem, 0, sizeof(LVITEMW)); 147 memset(za, 0, sizeof(ZONEATTRIBUTES)); 148 za->cbSize = sizeof(ZONEATTRIBUTES); 149 hr = IInternetZoneManager_GetZoneAttributes(sd->zone_mgr, zone, za); 150 if (SUCCEEDED(hr)) { 151 TRACE("displayname: %s\n", debugstr_w(za->szDisplayName)); 152 TRACE("description: %s\n", debugstr_w(za->szDescription)); 153 TRACE("minlevel: 0x%x, recommended: 0x%x, current: 0x%x (flags: 0x%x)\n", za->dwTemplateMinLevel, 154 za->dwTemplateRecommended, za->dwTemplateCurrentLevel, za->dwFlags); 155 156 if (za->dwFlags & ZAFLAGS_NO_UI ) { 157 TRACE("item %d (zone %d): UI disabled for %s\n", lv_index, zone, debugstr_w(za->szDisplayName)); 158 return; 159 } 160 161 sd->levels[lv_index] = za->dwTemplateCurrentLevel; 162 163 lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; 164 lvitem.iItem = lv_index; 165 lvitem.iSubItem = 0; 166 lvitem.pszText = za->szDisplayName; 167 lvitem.lParam = (LPARAM) zone; 168 169 /* format is "filename.ext#iconid" */ 170 ptr = StrChrW(za->szIconPath, '#'); 171 if (ptr) { 172 *ptr = 0; 173 ptr++; 174 iconid = StrToIntW(ptr); 175 hdll = LoadLibraryExW(za->szIconPath, NULL, LOAD_LIBRARY_AS_DATAFILE); 176 TRACE("%p: icon #%d from %s\n", hdll, iconid, debugstr_w(za->szIconPath)); 177 178 icon = LoadImageW(hdll, MAKEINTRESOURCEW(iconid), IMAGE_ICON, GetSystemMetrics(SM_CXICON), 179 GetSystemMetrics(SM_CYICON), LR_SHARED); 180 181 if (!icon) { 182 FIXME("item %d (zone %d): missing icon #%d in %s\n", lv_index, zone, iconid, debugstr_w(za->szIconPath)); 183 } 184 185 /* the failure result (NULL) from LoadImageW let ImageList_AddIcon fail 186 with -1, which is reused in ListView_InsertItemW to disable the image */ 187 lvitem.iImage = ImageList_AddIcon(sd->himages, icon); 188 } 189 else 190 FIXME("item %d (zone %d): malformed szIconPath %s\n", lv_index, zone, debugstr_w(za->szIconPath)); 191 192 if (ListView_InsertItemW(sd->hlv, &lvitem) >= 0) { 193 /* activate first item in the listview */ 194 if (! lv_index) { 195 lvitem.state = LVIS_FOCUSED | LVIS_SELECTED; 196 lvitem.stateMask = LVIS_FOCUSED | LVIS_SELECTED; 197 SendMessageW(sd->hlv, LVM_SETITEMSTATE, 0, (LPARAM) &lvitem); 198 sd->last_level = ~0; 199 update_zone_info(sd, lv_index); 200 } 201 (*pindex)++; 202 } 203 FreeLibrary(hdll); 204 } 205 else 206 FIXME("item %d (zone %d): GetZoneAttributes failed with 0x%x\n", lv_index, zone, hr); 207 } 208 209 /********************************************************************* 210 * security_cleanup_zones [internal] 211 * 212 */ 213 static void security_cleanup_zones(secdlg_data *sd) 214 { 215 if (sd->zone_enumerator) { 216 IInternetZoneManager_DestroyZoneEnumerator(sd->zone_mgr, sd->zone_enumerator); 217 } 218 219 if (sd->zone_mgr) { 220 IInternetZoneManager_Release(sd->zone_mgr); 221 } 222 223 if (sd->sec_mgr) { 224 IInternetSecurityManager_Release(sd->sec_mgr); 225 } 226 } 227 228 /********************************************************************* 229 * security_enum_zones [internal] 230 * 231 */ 232 static HRESULT security_enum_zones(secdlg_data * sd) 233 { 234 HRESULT hr; 235 236 hr = CoInternetCreateSecurityManager(NULL, &sd->sec_mgr, 0); 237 if (SUCCEEDED(hr)) { 238 hr = CoInternetCreateZoneManager(NULL, &sd->zone_mgr, 0); 239 if (SUCCEEDED(hr)) { 240 hr = IInternetZoneManager_CreateZoneEnumerator(sd->zone_mgr, &sd->zone_enumerator, &sd->num_zones, 0); 241 } 242 } 243 return hr; 244 } 245 246 /********************************************************************* 247 * security_on_destroy [internal] 248 * 249 * handle WM_NCDESTROY 250 * 251 */ 252 static INT_PTR security_on_destroy(secdlg_data * sd) 253 { 254 TRACE("(%p)\n", sd); 255 256 heap_free(sd->zone_attr); 257 heap_free(sd->zones); 258 if (sd->himages) { 259 SendMessageW(sd->hlv, LVM_SETIMAGELIST, LVSIL_NORMAL, 0); 260 ImageList_Destroy(sd->himages); 261 } 262 263 security_cleanup_zones(sd); 264 SetWindowLongPtrW(sd->hsec, DWLP_USER, 0); 265 heap_free(sd); 266 return TRUE; 267 } 268 269 /********************************************************************* 270 * security_on_initdialog [internal] 271 * 272 * handle WM_INITDIALOG 273 * 274 */ 275 static INT_PTR security_on_initdialog(HWND hsec) 276 { 277 secdlg_data *sd; 278 HRESULT hr; 279 DWORD current_zone; 280 DWORD lv_index = 0; 281 DWORD i; 282 283 sd = heap_alloc_zero(sizeof(secdlg_data)); 284 SetWindowLongPtrW(hsec, DWLP_USER, (LONG_PTR) sd); 285 if (!sd) { 286 return FALSE; 287 } 288 289 sd->hsec = hsec; 290 sd->hlv = GetDlgItem(hsec, IDC_SEC_LISTVIEW); 291 sd->htb = GetDlgItem(hsec, IDC_SEC_TRACKBAR); 292 293 EnableWindow(sd->htb, FALSE); /* not changeable yet */ 294 295 TRACE("(%p) (data: %p, listview: %p, trackbar: %p)\n", hsec, sd, sd->hlv, sd->htb); 296 297 SendMessageW(sd->htb, TBM_SETRANGE, FALSE, MAKELONG(0, NUM_TRACKBAR_POS - 1)); 298 SendMessageW(sd->htb, TBM_SETTICFREQ, 1, 0 ); 299 300 /* Create the image lists for the listview */ 301 sd->himages = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_COLOR32 | ILC_MASK, 1, 1); 302 303 TRACE("using imagelist: %p\n", sd->himages); 304 if (!sd->himages) { 305 ERR("ImageList_Create failed!\n"); 306 return FALSE; 307 } 308 SendMessageW(sd->hlv, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)sd->himages); 309 310 hr = security_enum_zones(sd); 311 if (FAILED(hr)) { 312 ERR("got 0x%x\n", hr); 313 security_on_destroy(sd); 314 return FALSE; 315 } 316 317 TRACE("found %d zones\n", sd->num_zones); 318 319 /* remember ZONEATTRIBUTES for a listview entry */ 320 sd->zone_attr = heap_alloc(sizeof(ZONEATTRIBUTES) * sd->num_zones); 321 if (!sd->zone_attr) { 322 security_on_destroy(sd); 323 return FALSE; 324 } 325 326 /* remember zone number and current security level for a listview entry */ 327 sd->zones = heap_alloc((sizeof(DWORD) + sizeof(DWORD)) * sd->num_zones); 328 if (!sd->zones) { 329 security_on_destroy(sd); 330 return FALSE; 331 } 332 sd->levels = &sd->zones[sd->num_zones]; 333 334 /* use the same order as visible with native inetcpl.cpl */ 335 add_zone_to_listview(sd, &lv_index, URLZONE_INTERNET); 336 add_zone_to_listview(sd, &lv_index, URLZONE_INTRANET); 337 add_zone_to_listview(sd, &lv_index, URLZONE_TRUSTED); 338 add_zone_to_listview(sd, &lv_index, URLZONE_UNTRUSTED); 339 340 for (i = 0; i < sd->num_zones; i++) 341 { 342 hr = IInternetZoneManager_GetZoneAt(sd->zone_mgr, sd->zone_enumerator, i, ¤t_zone); 343 if (SUCCEEDED(hr) && (current_zone != (DWORD)URLZONE_INVALID)) { 344 if (!current_zone || (current_zone > URLZONE_UNTRUSTED)) { 345 add_zone_to_listview(sd, &lv_index, current_zone); 346 } 347 } 348 } 349 return TRUE; 350 } 351 352 /********************************************************************* 353 * security_on_notify [internal] 354 * 355 * handle WM_NOTIFY 356 * 357 */ 358 static INT_PTR security_on_notify(secdlg_data *sd, WPARAM wparam, LPARAM lparam) 359 { 360 NMLISTVIEW *nm; 361 362 nm = (NMLISTVIEW *) lparam; 363 switch (nm->hdr.code) 364 { 365 case LVN_ITEMCHANGED: 366 TRACE("LVN_ITEMCHANGED (0x%lx, 0x%lx) from %p with code: %d (item: %d, uNewState: %u)\n", 367 wparam, lparam, nm->hdr.hwndFrom, nm->hdr.code, nm->iItem, nm->uNewState); 368 if ((nm->uNewState & LVIS_SELECTED) == LVIS_SELECTED) { 369 update_zone_info(sd, nm->iItem); 370 } 371 break; 372 373 case PSN_APPLY: 374 TRACE("PSN_APPLY (0x%lx, 0x%lx) from %p with code: %d\n", wparam, lparam, 375 nm->hdr.hwndFrom, nm->hdr.code); 376 break; 377 378 default: 379 TRACE("WM_NOTIFY (0x%lx, 0x%lx) from %p with code: %d\n", wparam, lparam, 380 nm->hdr.hwndFrom, nm->hdr.code); 381 382 } 383 return FALSE; 384 } 385 386 /********************************************************************* 387 * security_dlgproc [internal] 388 * 389 */ 390 INT_PTR CALLBACK security_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 391 { 392 secdlg_data *sd; 393 394 if (msg == WM_INITDIALOG) { 395 return security_on_initdialog(hwnd); 396 } 397 398 sd = (secdlg_data *)GetWindowLongPtrW(hwnd, DWLP_USER); 399 if (sd) { 400 switch (msg) 401 { 402 case WM_NOTIFY: 403 return security_on_notify(sd, wparam, lparam); 404 405 case WM_NCDESTROY: 406 return security_on_destroy(sd); 407 408 default: 409 /* do not flood the log */ 410 if ((msg == WM_SETCURSOR) || (msg == WM_NCHITTEST) || 411 (msg == WM_MOUSEMOVE) || (msg == WM_MOUSEACTIVATE) || (msg == WM_PARENTNOTIFY)) 412 return FALSE; 413 414 TRACE("(%p, 0x%08x/%03d, 0x%08lx, 0x%08lx)\n", hwnd, msg, msg, wparam, lparam); 415 } 416 } 417 return FALSE; 418 } 419