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