wineps: Handle EMR_INVERTRGN record in spool files.
[wine.git] / dlls / inetcpl.cpl / security.c
bloba6e8c03d50599d378ddd895c979d51244733b710
1 /*
2 * Internet control panel applet: security propsheet
4 * Copyright 2011 Detlef Riekenberg
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.
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.
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
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include <stdarg.h>
26 #include <windef.h>
27 #include <winbase.h>
28 #include <winuser.h>
29 #include <prsht.h>
30 #include "commctrl.h"
32 #include "ole2.h"
33 #include "urlmon.h"
34 #include "initguid.h"
35 #include "winreg.h"
36 #include "shlwapi.h"
38 #include "inetcpl.h"
39 #include "wine/debug.h"
40 #include "wine/heap.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(inetcpl);
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;
60 #define NUM_TRACKBAR_POS 5
62 static DWORD url_templates[] = {URLTEMPLATE_CUSTOM,
63 URLTEMPLATE_LOW,
64 URLTEMPLATE_MEDLOW,
65 URLTEMPLATE_MEDIUM,
66 URLTEMPLATE_MEDHIGH,
67 URLTEMPLATE_HIGH};
69 /*********************************************************************
70 * index_from_urltemplate [internal]
73 static DWORD index_from_urltemplate(URLTEMPLATE value)
76 DWORD index = ARRAY_SIZE(url_templates);
78 while((index > 0) && (url_templates[index-1] != value))
79 index--;
81 index--; /* table entries are 0 based */
82 if (!index && value)
83 FIXME("URLTEMPLATE 0x%x not supported\n", value);
85 TRACE("URLTEMPLATE 0x%08x=> Level %ld\n", value, index);
86 return index;
89 /*********************************************************************
90 * update_security_level [internal]
93 static void update_security_level(secdlg_data *sd, DWORD lv_index, DWORD tb_index)
95 WCHAR name[512];
96 DWORD current_index;
98 TRACE("(%p, lv_index: %lu, tb_index: %lu)\n", sd, lv_index, tb_index);
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);
105 current_index = (tb_index > 0) ? tb_index : index_from_urltemplate(sd->levels[lv_index]);
107 name[0] = 0;
108 LoadStringW(hcpl, IDS_SEC_LEVEL0 + current_index, name, ARRAY_SIZE(name));
109 TRACE("new level #%ld: %s\n", current_index, debugstr_w(name));
110 SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_LEVEL), name);
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);
117 if (current_index)
118 SendMessageW(sd->htb, TBM_SETPOS, TRUE, NUM_TRACKBAR_POS - current_index);
120 sd->last_level = sd->levels[lv_index];
125 /*********************************************************************
126 * update_zone_info [internal]
129 static void update_zone_info(secdlg_data *sd, DWORD lv_index)
131 ZONEATTRIBUTES *za = &sd->zone_attr[lv_index];
132 WCHAR name[MAX_PATH];
133 DWORD len;
135 SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_ZONE_INFO), za->szDescription);
137 len = LoadStringW(hcpl, IDS_SEC_SETTINGS, name, ARRAY_SIZE(name));
138 lstrcpynW(&name[len], za->szDisplayName, ARRAY_SIZE(name) - len - 1);
140 TRACE("new title: %s\n", debugstr_w(name));
141 SetWindowTextW(GetDlgItem(sd->hsec, IDC_SEC_GROUP), name);
143 update_security_level(sd, lv_index, 0);
144 sd->last_lv_index = lv_index;
147 /*********************************************************************
148 * add_zone_to_listview [internal]
151 static void add_zone_to_listview(secdlg_data *sd, DWORD *pindex, DWORD zone)
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;
162 TRACE("item %ld (zone %ld)\n", lv_index, zone);
164 sd->zones[lv_index] = zone;
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%lx, recommended: 0x%lx, current: 0x%lx (flags: 0x%lx)\n", za->dwTemplateMinLevel,
174 za->dwTemplateRecommended, za->dwTemplateCurrentLevel, za->dwFlags);
176 if (za->dwFlags & ZAFLAGS_NO_UI ) {
177 TRACE("item %ld (zone %ld): UI disabled for %s\n", lv_index, zone, debugstr_w(za->szDisplayName));
178 return;
181 sd->levels[lv_index] = za->dwTemplateCurrentLevel;
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;
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));
198 icon = LoadImageW(hdll, MAKEINTRESOURCEW(iconid), IMAGE_ICON, GetSystemMetrics(SM_CXICON),
199 GetSystemMetrics(SM_CYICON), LR_SHARED);
201 if (!icon) {
202 FIXME("item %ld (zone %ld): missing icon #%d in %s\n", lv_index, zone, iconid, debugstr_w(za->szIconPath));
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);
209 else
210 FIXME("item %ld (zone %ld): malformed szIconPath %s\n", lv_index, zone, debugstr_w(za->szIconPath));
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);
221 (*pindex)++;
223 FreeLibrary(hdll);
225 else
226 FIXME("item %ld (zone %ld): GetZoneAttributes failed with 0x%lx\n", lv_index, zone, hr);
229 /*********************************************************************
230 * security_cleanup_zones [internal]
233 static void security_cleanup_zones(secdlg_data *sd)
235 if (sd->zone_enumerator) {
236 IInternetZoneManager_DestroyZoneEnumerator(sd->zone_mgr, sd->zone_enumerator);
239 if (sd->zone_mgr) {
240 IInternetZoneManager_Release(sd->zone_mgr);
243 if (sd->sec_mgr) {
244 IInternetSecurityManager_Release(sd->sec_mgr);
248 /*********************************************************************
249 * security_enum_zones [internal]
252 static HRESULT security_enum_zones(secdlg_data * sd)
254 HRESULT hr;
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);
263 return hr;
266 /*********************************************************************
267 * security_on_destroy [internal]
269 * handle WM_NCDESTROY
272 static INT_PTR security_on_destroy(secdlg_data * sd)
274 TRACE("(%p)\n", sd);
276 heap_free(sd->zone_attr);
277 heap_free(sd->zones);
278 if (sd->himages) {
279 SendMessageW(sd->hlv, LVM_SETIMAGELIST, LVSIL_NORMAL, 0);
280 ImageList_Destroy(sd->himages);
283 security_cleanup_zones(sd);
284 SetWindowLongPtrW(sd->hsec, DWLP_USER, 0);
285 heap_free(sd);
286 return TRUE;
289 /*********************************************************************
290 * security_on_initdialog [internal]
292 * handle WM_INITDIALOG
295 static INT_PTR security_on_initdialog(HWND hsec)
297 secdlg_data *sd;
298 HRESULT hr;
299 DWORD current_zone;
300 DWORD lv_index = 0;
301 DWORD i;
303 sd = heap_alloc_zero(sizeof(secdlg_data));
304 SetWindowLongPtrW(hsec, DWLP_USER, (LONG_PTR) sd);
305 if (!sd) {
306 return FALSE;
309 sd->hsec = hsec;
310 sd->hlv = GetDlgItem(hsec, IDC_SEC_LISTVIEW);
311 sd->htb = GetDlgItem(hsec, IDC_SEC_TRACKBAR);
313 EnableWindow(sd->htb, FALSE); /* not changeable yet */
315 TRACE("(%p) (data: %p, listview: %p, trackbar: %p)\n", hsec, sd, sd->hlv, sd->htb);
317 SendMessageW(sd->htb, TBM_SETRANGE, FALSE, MAKELONG(0, NUM_TRACKBAR_POS - 1));
318 SendMessageW(sd->htb, TBM_SETTICFREQ, 1, 0 );
320 /* Create the image lists for the listview */
321 sd->himages = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_COLOR32 | ILC_MASK, 1, 1);
323 TRACE("using imagelist: %p\n", sd->himages);
324 if (!sd->himages) {
325 ERR("ImageList_Create failed!\n");
326 security_on_destroy(sd);
327 return FALSE;
329 SendMessageW(sd->hlv, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)sd->himages);
331 hr = security_enum_zones(sd);
332 if (FAILED(hr)) {
333 ERR("got 0x%lx\n", hr);
334 security_on_destroy(sd);
335 return FALSE;
338 TRACE("found %ld zones\n", sd->num_zones);
340 /* remember ZONEATTRIBUTES for a listview entry */
341 sd->zone_attr = heap_alloc(sizeof(ZONEATTRIBUTES) * sd->num_zones);
342 if (!sd->zone_attr) {
343 security_on_destroy(sd);
344 return FALSE;
347 /* remember zone number and current security level for a listview entry */
348 sd->zones = heap_alloc((sizeof(DWORD) + sizeof(DWORD)) * sd->num_zones);
349 if (!sd->zones) {
350 security_on_destroy(sd);
351 return FALSE;
353 sd->levels = &sd->zones[sd->num_zones];
355 /* use the same order as visible with native inetcpl.cpl */
356 add_zone_to_listview(sd, &lv_index, URLZONE_INTERNET);
357 add_zone_to_listview(sd, &lv_index, URLZONE_INTRANET);
358 add_zone_to_listview(sd, &lv_index, URLZONE_TRUSTED);
359 add_zone_to_listview(sd, &lv_index, URLZONE_UNTRUSTED);
361 for (i = 0; i < sd->num_zones; i++)
363 hr = IInternetZoneManager_GetZoneAt(sd->zone_mgr, sd->zone_enumerator, i, &current_zone);
364 if (SUCCEEDED(hr) && (current_zone != (DWORD)URLZONE_INVALID)) {
365 if (!current_zone || (current_zone > URLZONE_UNTRUSTED)) {
366 add_zone_to_listview(sd, &lv_index, current_zone);
370 return TRUE;
373 /*********************************************************************
374 * security_on_notify [internal]
376 * handle WM_NOTIFY
379 static INT_PTR security_on_notify(secdlg_data *sd, WPARAM wparam, LPARAM lparam)
381 NMLISTVIEW *nm;
383 nm = (NMLISTVIEW *) lparam;
384 switch (nm->hdr.code)
386 case LVN_ITEMCHANGED:
387 TRACE("LVN_ITEMCHANGED (0x%Ix, 0x%Ix) from %p with code: %d (item: %d, uNewState: %u)\n",
388 wparam, lparam, nm->hdr.hwndFrom, nm->hdr.code, nm->iItem, nm->uNewState);
389 if ((nm->uNewState & LVIS_SELECTED) == LVIS_SELECTED) {
390 update_zone_info(sd, nm->iItem);
392 break;
394 case PSN_APPLY:
395 TRACE("PSN_APPLY (0x%Ix, 0x%Ix) from %p with code: %d\n", wparam, lparam,
396 nm->hdr.hwndFrom, nm->hdr.code);
397 break;
399 default:
400 TRACE("WM_NOTIFY (0x%Ix, 0x%Ix) from %p with code: %d\n", wparam, lparam,
401 nm->hdr.hwndFrom, nm->hdr.code);
404 return FALSE;
407 /*********************************************************************
408 * security_dlgproc [internal]
411 INT_PTR CALLBACK security_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
413 secdlg_data *sd;
415 if (msg == WM_INITDIALOG) {
416 return security_on_initdialog(hwnd);
419 sd = (secdlg_data *)GetWindowLongPtrW(hwnd, DWLP_USER);
420 if (sd) {
421 switch (msg)
423 case WM_NOTIFY:
424 return security_on_notify(sd, wparam, lparam);
426 case WM_NCDESTROY:
427 return security_on_destroy(sd);
429 default:
430 /* do not flood the log */
431 if ((msg == WM_SETCURSOR) || (msg == WM_NCHITTEST) ||
432 (msg == WM_MOUSEMOVE) || (msg == WM_MOUSEACTIVATE) || (msg == WM_PARENTNOTIFY))
433 return FALSE;
435 TRACE("(%p, 0x%08x/%03d, 0x%08Ix, 0x%08Ix)\n", hwnd, msg, msg, wparam, lparam);
438 return FALSE;