mirror of
https://github.com/henrypp/simplewall.git
synced 2026-10-22 02:52:54 -05:00
1136 lines
23 KiB
C
1136 lines
23 KiB
C
// simplewall
|
|
// Copyright (c) 2016-2023 Henry++
|
|
|
|
#include "global.h"
|
|
|
|
INT _app_listview_getcurrent (
|
|
_In_ HWND hwnd
|
|
)
|
|
{
|
|
INT listview_id;
|
|
|
|
listview_id = _app_listview_getbytab (hwnd, -1);
|
|
|
|
return listview_id;
|
|
}
|
|
|
|
INT _app_listview_getbytab (
|
|
_In_ HWND hwnd,
|
|
_In_ INT tab_id
|
|
)
|
|
{
|
|
INT listview_id;
|
|
|
|
if (tab_id == -1)
|
|
tab_id = _r_tab_getcurrentitem (hwnd, IDC_TAB);
|
|
|
|
listview_id = (INT)_r_tab_getitemlparam (hwnd, IDC_TAB, tab_id);
|
|
|
|
return listview_id;
|
|
}
|
|
|
|
_Success_ (return != 0)
|
|
INT _app_listview_getbytype (
|
|
_In_ ENUM_TYPE_DATA type
|
|
)
|
|
{
|
|
switch (type)
|
|
{
|
|
case DATA_APP_REGULAR:
|
|
case DATA_APP_DEVICE:
|
|
case DATA_APP_NETWORK:
|
|
case DATA_APP_PICO:
|
|
{
|
|
return IDC_APPS_PROFILE;
|
|
}
|
|
|
|
case DATA_APP_SERVICE:
|
|
{
|
|
return IDC_APPS_SERVICE;
|
|
}
|
|
|
|
case DATA_APP_UWP:
|
|
{
|
|
return IDC_APPS_UWP;
|
|
}
|
|
|
|
case DATA_RULE_BLOCKLIST:
|
|
{
|
|
return IDC_RULES_BLOCKLIST;
|
|
}
|
|
|
|
case DATA_RULE_SYSTEM:
|
|
{
|
|
return IDC_RULES_SYSTEM;
|
|
}
|
|
|
|
case DATA_RULE_SYSTEM_USER:
|
|
case DATA_RULE_USER:
|
|
{
|
|
return IDC_RULES_CUSTOM;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID _app_listview_additems (
|
|
_In_ HWND hwnd
|
|
)
|
|
{
|
|
PITEM_APP ptr_app = NULL;
|
|
PITEM_RULE ptr_rule;
|
|
LONG64 current_time;
|
|
ULONG_PTR enum_key = 0;
|
|
|
|
current_time = _r_unixtime_now ();
|
|
|
|
// add apps
|
|
_r_queuedlock_acquireshared (&lock_apps);
|
|
|
|
while (_r_obj_enumhashtablepointer (apps_table, &ptr_app, NULL, &enum_key))
|
|
{
|
|
_app_listview_addappitem (hwnd, ptr_app);
|
|
|
|
// install timer
|
|
if (ptr_app->timer)
|
|
_app_timer_set (hwnd, ptr_app, ptr_app->timer - current_time);
|
|
}
|
|
|
|
_r_queuedlock_releaseshared (&lock_apps);
|
|
|
|
// add rules
|
|
_r_queuedlock_acquireshared (&lock_rules);
|
|
|
|
for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++)
|
|
{
|
|
ptr_rule = _r_obj_getlistitem (rules_list, i);
|
|
|
|
if (ptr_rule)
|
|
_app_listview_addruleitem (hwnd, ptr_rule, i, FALSE);
|
|
}
|
|
|
|
_r_queuedlock_releaseshared (&lock_rules);
|
|
}
|
|
|
|
VOID _app_listview_clearitems (
|
|
_In_ HWND hwnd
|
|
)
|
|
{
|
|
for (INT i = IDC_APPS_PROFILE; i <= IDC_RULES_CUSTOM; i++)
|
|
{
|
|
_r_listview_deleteallitems (hwnd, i);
|
|
}
|
|
}
|
|
|
|
VOID _app_listview_addappitem (
|
|
_In_ HWND hwnd,
|
|
_In_ PITEM_APP ptr_app
|
|
)
|
|
{
|
|
LPARAM listview_context;
|
|
INT listview_id;
|
|
INT item_id;
|
|
|
|
listview_id = _app_listview_getbytype (ptr_app->type);
|
|
|
|
if (!listview_id)
|
|
return;
|
|
|
|
item_id = _r_listview_getitemcount (hwnd, listview_id);
|
|
|
|
_app_listview_lock (hwnd, listview_id, TRUE);
|
|
|
|
listview_context = _app_listview_createcontext (ptr_app->app_hash);
|
|
|
|
_r_listview_additem_ex (hwnd, listview_id, item_id, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, listview_context);
|
|
|
|
_app_setappiteminfo (hwnd, listview_id, item_id, ptr_app);
|
|
|
|
_app_listview_lock (hwnd, listview_id, FALSE);
|
|
}
|
|
|
|
VOID _app_listview_addruleitem (
|
|
_In_ HWND hwnd,
|
|
_In_ PITEM_RULE ptr_rule,
|
|
_In_ ULONG_PTR rule_idx,
|
|
_In_ BOOLEAN is_forapp
|
|
)
|
|
{
|
|
LPARAM listview_context;
|
|
INT listview_id;
|
|
INT item_id;
|
|
|
|
listview_id = _app_listview_getbytype (ptr_rule->type);
|
|
|
|
if (!listview_id)
|
|
return;
|
|
|
|
item_id = _r_listview_getitemcount (hwnd, listview_id);
|
|
|
|
_app_listview_lock (hwnd, listview_id, TRUE);
|
|
|
|
listview_context = _app_listview_createcontext (rule_idx);
|
|
|
|
_r_listview_additem_ex (hwnd, listview_id, item_id, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, listview_context);
|
|
|
|
_app_setruleiteminfo (hwnd, listview_id, item_id, ptr_rule, is_forapp);
|
|
|
|
_app_listview_lock (hwnd, listview_id, FALSE);
|
|
}
|
|
|
|
VOID _app_listview_addnetworkitem (
|
|
_In_ HWND hwnd,
|
|
_In_ ULONG_PTR network_hash
|
|
)
|
|
{
|
|
LPARAM listview_context;
|
|
INT item_id;
|
|
|
|
item_id = _r_listview_getitemcount (hwnd, IDC_NETWORK);
|
|
|
|
listview_context = _app_listview_createcontext (network_hash);
|
|
|
|
_r_listview_additem_ex (hwnd, IDC_NETWORK, item_id, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, listview_context);
|
|
}
|
|
|
|
VOID _app_listview_addlogitem (
|
|
_In_ HWND hwnd,
|
|
_In_ ULONG_PTR log_hash
|
|
)
|
|
{
|
|
LPARAM listview_context;
|
|
INT item_id;
|
|
|
|
item_id = _r_listview_getitemcount (hwnd, IDC_LOG);
|
|
|
|
listview_context = _app_listview_createcontext (log_hash);
|
|
|
|
_r_listview_additem_ex (hwnd, IDC_LOG, item_id, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, 0, listview_context);
|
|
|
|
//_r_listview_ensurevisible (hwnd, IDC_LOG, item_id);
|
|
}
|
|
|
|
BOOLEAN _app_listview_islocked (
|
|
_In_ HWND hwnd,
|
|
_In_ INT ctrl_id
|
|
)
|
|
{
|
|
PVOID context;
|
|
ULONG property_id;
|
|
|
|
property_id = (USHORT_MAX - ctrl_id);
|
|
|
|
context = _r_wnd_getcontext (hwnd, property_id);
|
|
|
|
return (context != NULL);
|
|
}
|
|
|
|
VOID _app_listview_lock (
|
|
_In_ HWND hwnd,
|
|
_In_ INT ctrl_id,
|
|
_In_ BOOLEAN is_lock
|
|
)
|
|
{
|
|
ULONG property_id;
|
|
|
|
property_id = (USHORT_MAX - ctrl_id);
|
|
|
|
if (is_lock)
|
|
{
|
|
_r_wnd_setcontext (hwnd, property_id, INVALID_HANDLE_VALUE);
|
|
}
|
|
else
|
|
{
|
|
_r_wnd_removecontext (hwnd, property_id);
|
|
}
|
|
}
|
|
|
|
LPARAM _app_listview_createcontext (
|
|
_In_ ULONG_PTR id_code
|
|
)
|
|
{
|
|
PITEM_LISTVIEW_CONTEXT context;
|
|
|
|
context = _r_freelist_allocateitem (&listview_free_list);
|
|
|
|
context->id_code = id_code;
|
|
|
|
return (LPARAM)context;
|
|
}
|
|
|
|
VOID _app_listview_destroycontext (
|
|
_In_ PITEM_LISTVIEW_CONTEXT context
|
|
)
|
|
{
|
|
_r_freelist_deleteitem (&listview_free_list, context);
|
|
}
|
|
|
|
ULONG_PTR _app_listview_getcontextcode (
|
|
_In_ LPARAM lparam
|
|
)
|
|
{
|
|
PITEM_LISTVIEW_CONTEXT context;
|
|
|
|
context = (PITEM_LISTVIEW_CONTEXT)lparam;
|
|
|
|
return context->id_code;
|
|
}
|
|
|
|
ULONG_PTR _app_listview_getitemcontext (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id,
|
|
_In_ INT item_id
|
|
)
|
|
{
|
|
LPARAM lparam;
|
|
|
|
lparam = _r_listview_getitemlparam (hwnd, listview_id, item_id);
|
|
|
|
if (!lparam)
|
|
return 0;
|
|
|
|
return _app_listview_getcontextcode (lparam);
|
|
}
|
|
|
|
BOOLEAN _app_listview_isitemhidden (
|
|
_In_ LPARAM lparam
|
|
)
|
|
{
|
|
PITEM_LISTVIEW_CONTEXT context;
|
|
|
|
context = (PITEM_LISTVIEW_CONTEXT)lparam;
|
|
|
|
if (!context)
|
|
return FALSE;
|
|
|
|
return !!context->is_hidden;
|
|
}
|
|
|
|
_Success_ (return != -1)
|
|
INT _app_listview_finditem (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id,
|
|
_In_ ULONG_PTR id_code
|
|
)
|
|
{
|
|
ULONG_PTR current_code;
|
|
INT item_count;
|
|
|
|
if ((listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG) || listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID)
|
|
{
|
|
item_count = _r_listview_getitemcount (hwnd, listview_id);
|
|
|
|
for (INT i = 0; i < item_count; i++)
|
|
{
|
|
current_code = _app_listview_getitemcontext (hwnd, listview_id, i);
|
|
|
|
if (current_code == id_code)
|
|
return i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return _r_listview_finditem (hwnd, listview_id, -1, id_code);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
VOID _app_listview_removeitem (
|
|
_In_ HWND hwnd,
|
|
_In_ ULONG_PTR id_code,
|
|
_In_ ENUM_TYPE_DATA type
|
|
)
|
|
{
|
|
INT listview_id;
|
|
INT item_id;
|
|
|
|
if (!hwnd)
|
|
return;
|
|
|
|
listview_id = _app_listview_getbytype (type);
|
|
|
|
if (!listview_id)
|
|
return;
|
|
|
|
item_id = _app_listview_finditem (hwnd, listview_id, id_code);
|
|
|
|
if (item_id != -1)
|
|
_r_listview_deleteitem (hwnd, listview_id, item_id);
|
|
}
|
|
|
|
VOID _app_listview_showitemby_id (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id,
|
|
_In_ INT item_id,
|
|
_In_ INT scroll_pos
|
|
)
|
|
{
|
|
INT total_count;
|
|
|
|
_app_settab_id (hwnd, listview_id);
|
|
|
|
total_count = _r_listview_getitemcount (hwnd, listview_id);
|
|
|
|
if (!total_count)
|
|
return;
|
|
|
|
if (item_id != -1)
|
|
{
|
|
item_id = _r_calc_clamp (item_id, 0, total_count - 1);
|
|
|
|
_r_listview_setitemvisible (hwnd, listview_id, item_id);
|
|
}
|
|
|
|
// restore scroll position
|
|
if (scroll_pos > 0)
|
|
SendDlgItemMessageW (hwnd, listview_id, LVM_SCROLL, 0, (LPARAM)scroll_pos);
|
|
}
|
|
|
|
VOID _app_listview_showitemby_param (
|
|
_In_ HWND hwnd,
|
|
_In_ ULONG_PTR lparam,
|
|
_In_ BOOLEAN is_app
|
|
)
|
|
{
|
|
INT listview_id = 0;
|
|
INT item_id;
|
|
|
|
if (is_app)
|
|
{
|
|
_app_getappinfobyhash (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (listview_id));
|
|
}
|
|
else
|
|
{
|
|
_app_getruleinfobyid (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (listview_id));
|
|
}
|
|
|
|
if (!listview_id)
|
|
return;
|
|
|
|
if (listview_id != _app_listview_getcurrent (hwnd))
|
|
{
|
|
_app_listview_sort (hwnd, listview_id);
|
|
|
|
_app_listview_resize (hwnd, listview_id);
|
|
}
|
|
|
|
item_id = _app_listview_finditem (hwnd, listview_id, lparam);
|
|
|
|
if (item_id != -1)
|
|
{
|
|
_app_listview_showitemby_id (hwnd, listview_id, item_id, -1);
|
|
|
|
_r_wnd_toggle (hwnd, TRUE);
|
|
}
|
|
}
|
|
|
|
VOID _app_listview_updateby_id (
|
|
_In_ HWND hwnd,
|
|
_In_ INT lparam,
|
|
_In_ ULONG flags
|
|
)
|
|
{
|
|
INT listview_id;
|
|
ENUM_TYPE_DATA type;
|
|
|
|
if (flags & PR_UPDATE_TYPE)
|
|
{
|
|
type = lparam;
|
|
|
|
if (type == DATA_LISTVIEW_CURRENT)
|
|
{
|
|
listview_id = _app_listview_getcurrent (hwnd);
|
|
}
|
|
else
|
|
{
|
|
listview_id = _app_listview_getbytype (type);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
listview_id = lparam;
|
|
}
|
|
|
|
if ((flags & PR_UPDATE_FORCE) || (listview_id == _app_listview_getcurrent (hwnd)))
|
|
{
|
|
if (!(flags & PR_UPDATE_NOREDRAW))
|
|
_r_listview_redraw (hwnd, listview_id);
|
|
|
|
if (!(flags & PR_UPDATE_NOSETVIEW))
|
|
{
|
|
_app_listview_setfont (hwnd, listview_id);
|
|
|
|
_app_listview_setview (hwnd, listview_id);
|
|
}
|
|
|
|
if (!(flags & PR_UPDATE_NOREFRESH))
|
|
_app_listview_refreshgroups (hwnd, listview_id);
|
|
|
|
if (!(flags & PR_UPDATE_NOSORT))
|
|
_app_listview_sort (hwnd, listview_id);
|
|
|
|
if (!(flags & PR_UPDATE_NORESIZE))
|
|
_app_listview_resize (hwnd, listview_id);
|
|
}
|
|
|
|
_app_refreshstatus (hwnd);
|
|
}
|
|
|
|
VOID _app_listview_updateby_param (
|
|
_In_ HWND hwnd,
|
|
_In_ ULONG_PTR lparam,
|
|
_In_ ULONG flags,
|
|
_In_ BOOLEAN is_app
|
|
)
|
|
{
|
|
INT listview_id = 0;
|
|
|
|
if (is_app)
|
|
{
|
|
_app_getappinfobyhash (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (listview_id));
|
|
}
|
|
else
|
|
{
|
|
_app_getruleinfobyid (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (listview_id));
|
|
}
|
|
|
|
if (!listview_id)
|
|
return;
|
|
|
|
if ((flags & PR_SETITEM_UPDATE))
|
|
_app_listview_updateby_id (hwnd, listview_id, 0);
|
|
|
|
if ((flags & PR_SETITEM_REDRAW))
|
|
{
|
|
if (listview_id == _app_listview_getcurrent (hwnd))
|
|
_r_listview_redraw (hwnd, listview_id);
|
|
}
|
|
}
|
|
|
|
VOID _app_listview_updateitemby_param (
|
|
_In_ HWND hwnd,
|
|
_In_ ULONG_PTR lparam,
|
|
_In_ BOOLEAN is_app
|
|
)
|
|
{
|
|
PITEM_RULE ptr_rule;
|
|
PITEM_APP ptr_app;
|
|
INT listview_id = 0;
|
|
INT item_id;
|
|
|
|
if (is_app)
|
|
{
|
|
_app_getappinfobyhash (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (listview_id));
|
|
}
|
|
else
|
|
{
|
|
_app_getruleinfobyid (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (listview_id));
|
|
}
|
|
|
|
if (!listview_id)
|
|
return;
|
|
|
|
item_id = _app_listview_finditem (hwnd, listview_id, lparam);
|
|
|
|
if (item_id == -1)
|
|
return;
|
|
|
|
if (is_app)
|
|
{
|
|
ptr_app = _app_getappitem (lparam);
|
|
|
|
if (!ptr_app)
|
|
return;
|
|
|
|
_app_listview_lock (hwnd, listview_id, TRUE);
|
|
_app_setappiteminfo (hwnd, listview_id, item_id, ptr_app);
|
|
_app_listview_lock (hwnd, listview_id, FALSE);
|
|
|
|
_r_obj_dereference (ptr_app);
|
|
}
|
|
else
|
|
{
|
|
ptr_rule = _app_getrulebyid (lparam);
|
|
|
|
if (!ptr_rule)
|
|
return;
|
|
|
|
_app_listview_lock (hwnd, listview_id, TRUE);
|
|
_app_setruleiteminfo (hwnd, listview_id, item_id, ptr_rule, FALSE);
|
|
_app_listview_lock (hwnd, listview_id, FALSE);
|
|
|
|
_r_obj_dereference (ptr_rule);
|
|
}
|
|
}
|
|
|
|
VOID _app_listview_updateitemby_id (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id,
|
|
_In_ INT item_id
|
|
)
|
|
{
|
|
_r_listview_setitem_ex (hwnd, listview_id, item_id, 0, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, 0);
|
|
}
|
|
|
|
VOID _app_listview_loadfont (
|
|
_In_ LONG dpi_value,
|
|
_In_ BOOLEAN is_forced
|
|
)
|
|
{
|
|
LOGFONT logfont = {0};
|
|
|
|
if (is_forced || !config.hfont)
|
|
{
|
|
SAFE_DELETE_OBJECT (config.hfont);
|
|
|
|
_r_config_getfont (L"Font", &logfont, dpi_value);
|
|
|
|
config.hfont = _app_createfont (&logfont, 0, FALSE, 0);
|
|
}
|
|
}
|
|
|
|
VOID _app_listview_refreshgroups (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id
|
|
)
|
|
{
|
|
WCHAR buffer[128];
|
|
UINT group1_title;
|
|
UINT group2_title;
|
|
UINT group3_title;
|
|
UINT group4_title;
|
|
UINT group5_title;
|
|
INT total_count;
|
|
INT group1_count = 0;
|
|
INT group2_count = 0;
|
|
INT group3_count = 0;
|
|
INT group4_count = 0;
|
|
INT group5_count = 0;
|
|
INT group_id;
|
|
BOOLEAN is_rules;
|
|
|
|
if (!_r_listview_isgroupviewenabled (hwnd, listview_id))
|
|
return;
|
|
|
|
is_rules = (listview_id >= IDC_RULES_BLOCKLIST && listview_id <= IDC_RULES_CUSTOM);
|
|
|
|
if (listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_APPS_UWP)
|
|
{
|
|
group1_title = IDS_GROUP_ALLOWED;
|
|
group2_title = IDS_GROUP_TIMER;
|
|
group3_title = IDS_GROUP_SPECIAL_APPS;
|
|
group4_title = IDS_GROUP_BLOCKED;
|
|
group5_title = IDS_GROUP_BLOCKED;
|
|
}
|
|
else if (is_rules)
|
|
{
|
|
group1_title = IDS_GROUP_ENABLED;
|
|
group2_title = IDS_GROUP_ENABLED;
|
|
group3_title = IDS_GROUP_DISABLED;
|
|
group4_title = 0;
|
|
group5_title = 0;
|
|
}
|
|
else if (listview_id == IDC_RULE_APPS_ID || listview_id == IDC_NETWORK)
|
|
{
|
|
group1_title = IDS_TAB_APPS;
|
|
group2_title = IDS_TAB_SERVICES;
|
|
group3_title = IDS_TAB_PACKAGES;
|
|
group4_title = 0;
|
|
group5_title = 0;
|
|
}
|
|
else if (listview_id == IDC_APP_RULES_ID)
|
|
{
|
|
group1_title = IDS_TRAY_SYSTEM_RULES;
|
|
group2_title = IDS_TRAY_USER_RULES;
|
|
group3_title = 0;
|
|
group4_title = 0;
|
|
group5_title = 0;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
total_count = _r_listview_getitemcount (hwnd, listview_id);
|
|
|
|
for (INT i = 0; i < total_count; i++)
|
|
{
|
|
if (listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID)
|
|
{
|
|
if (_r_listview_isitemchecked (hwnd, listview_id, i))
|
|
group1_count = group2_count = group3_count += 1;
|
|
}
|
|
else
|
|
{
|
|
group_id = _r_listview_getitemgroup (hwnd, listview_id, i);
|
|
|
|
if (group_id == 4)
|
|
{
|
|
group5_count += 1;
|
|
}
|
|
else if (group_id == 3)
|
|
{
|
|
group4_count += 1;
|
|
}
|
|
else if (group_id == 2)
|
|
{
|
|
group3_count += 1;
|
|
}
|
|
else if (group_id == 1)
|
|
{
|
|
group2_count += 1;
|
|
}
|
|
else if (group_id == 0)
|
|
{
|
|
group1_count += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (total_count)
|
|
{
|
|
// set group #1 title
|
|
_r_str_printf (
|
|
buffer,
|
|
RTL_NUMBER_OF (buffer),
|
|
is_rules ? L"%s (%d/%d) [for all]" : L"%s (%d/%d)",
|
|
_r_locale_getstring (group1_title),
|
|
group1_count,
|
|
total_count
|
|
);
|
|
|
|
_r_listview_setgroup (hwnd, listview_id, 0, buffer, 0, 0);
|
|
|
|
// set group #2 title
|
|
_r_str_printf (
|
|
buffer,
|
|
RTL_NUMBER_OF (buffer),
|
|
is_rules ? L"%s (%d/%d) [for apps]" : L"%s (%d/%d)",
|
|
_r_locale_getstring (group2_title),
|
|
group2_count,
|
|
total_count
|
|
);
|
|
|
|
_r_listview_setgroup (hwnd, listview_id, 1, buffer, 0, 0);
|
|
|
|
// set group #3 title
|
|
if (group3_title)
|
|
{
|
|
_r_str_printf (
|
|
buffer,
|
|
RTL_NUMBER_OF (buffer),
|
|
L"%s (%d/%d)",
|
|
_r_locale_getstring (group3_title),
|
|
group3_count,
|
|
total_count
|
|
);
|
|
|
|
_r_listview_setgroup (hwnd, listview_id, 2, buffer, 0, 0);
|
|
}
|
|
|
|
// set group #4 title
|
|
if (group4_title)
|
|
{
|
|
_r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s (%d/%d)", _r_locale_getstring (group4_title), group4_count, total_count);
|
|
|
|
_r_listview_setgroup (hwnd, listview_id, 3, buffer, 0, 0);
|
|
}
|
|
|
|
// set group #5 title
|
|
if (group5_title)
|
|
{
|
|
_r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s (%d/%d) [silent]", _r_locale_getstring (group5_title), group5_count, total_count);
|
|
|
|
_r_listview_setgroup (hwnd, listview_id, 4, buffer, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID _app_listview_resize_ex (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id,
|
|
_In_ BOOLEAN is_forced
|
|
)
|
|
{
|
|
PR_STRING column_text;
|
|
PR_STRING item_text;
|
|
HWND hlistview;
|
|
HWND hheader = NULL;
|
|
HDC hdc_listview = NULL;
|
|
HDC hdc_header = NULL;
|
|
LONG dpi_value;
|
|
INT column_count;
|
|
INT item_count;
|
|
INT column_width;
|
|
INT text_width;
|
|
INT calculated_width = 0;
|
|
INT column_general_id = 0; // set general column id
|
|
INT total_width;
|
|
INT max_width;
|
|
INT spacing;
|
|
BOOLEAN is_tableview;
|
|
|
|
if (!is_forced && !_r_config_getboolean (L"AutoSizeColumns", TRUE))
|
|
return;
|
|
|
|
hlistview = GetDlgItem (hwnd, listview_id);
|
|
|
|
if (!hlistview)
|
|
return;
|
|
|
|
column_count = _r_listview_getcolumncount (hwnd, listview_id);
|
|
|
|
if (!column_count)
|
|
return;
|
|
|
|
// get device context and fix font set
|
|
hdc_listview = GetDC (hlistview);
|
|
|
|
if (!hdc_listview)
|
|
goto CleanupExit;
|
|
|
|
hheader = (HWND)SendMessageW (hlistview, LVM_GETHEADER, 0, 0);
|
|
|
|
hdc_header = GetDC (hheader);
|
|
|
|
if (!hdc_header)
|
|
goto CleanupExit;
|
|
|
|
_r_dc_fixfont (hdc_listview, hlistview, 0); // fix
|
|
_r_dc_fixfont (hdc_header, hheader, 0); // fix
|
|
|
|
is_tableview = (_r_listview_getview (hwnd, listview_id) == LV_VIEW_DETAILS);
|
|
|
|
dpi_value = _r_dc_getwindowdpi (hwnd);
|
|
|
|
max_width = _r_dc_getdpi (158, dpi_value);
|
|
spacing = _r_dc_getsystemmetrics (SM_CXSMICON, dpi_value);
|
|
|
|
total_width = _r_ctrl_getwidth (hwnd, listview_id);
|
|
item_count = _r_listview_getitemcount (hwnd, listview_id);
|
|
|
|
for (INT i = 0; i < column_count; i++)
|
|
{
|
|
if (i == column_general_id)
|
|
continue;
|
|
|
|
// get column text width
|
|
column_text = _r_listview_getcolumntext (hwnd, listview_id, i);
|
|
|
|
if (!column_text)
|
|
continue;
|
|
|
|
column_width = _r_dc_getfontwidth (hdc_header, &column_text->sr) + spacing;
|
|
|
|
if (column_width >= max_width)
|
|
{
|
|
column_width = max_width;
|
|
}
|
|
else
|
|
{
|
|
// calculate max width of listview subitems (only for details view)
|
|
if (is_tableview)
|
|
{
|
|
for (INT j = 0; j < item_count; j++)
|
|
{
|
|
item_text = _r_listview_getitemtext (hwnd, listview_id, j, i);
|
|
|
|
if (!item_text)
|
|
continue;
|
|
|
|
text_width = _r_dc_getfontwidth (hdc_listview, &item_text->sr) + spacing;
|
|
|
|
_r_obj_dereference (item_text);
|
|
|
|
// do not continue reaching higher and higher values for performance reason!
|
|
if (text_width >= max_width)
|
|
{
|
|
column_width = max_width;
|
|
|
|
break;
|
|
}
|
|
|
|
if (text_width > column_width)
|
|
column_width = text_width;
|
|
}
|
|
}
|
|
}
|
|
|
|
_r_listview_setcolumn (hwnd, listview_id, i, NULL, column_width);
|
|
|
|
calculated_width += column_width;
|
|
|
|
_r_obj_dereference (column_text);
|
|
}
|
|
|
|
// set general column width
|
|
_r_listview_setcolumn (hwnd, listview_id, column_general_id, NULL, max (total_width - calculated_width, max_width));
|
|
|
|
CleanupExit:
|
|
|
|
if (hdc_listview)
|
|
ReleaseDC (hlistview, hdc_listview);
|
|
|
|
if (hdc_header)
|
|
ReleaseDC (hheader, hdc_header);
|
|
}
|
|
|
|
VOID _app_listview_resize (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id
|
|
)
|
|
{
|
|
_app_listview_resize_ex (hwnd, listview_id, FALSE);
|
|
}
|
|
|
|
VOID _app_listview_setfont (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id
|
|
)
|
|
{
|
|
if (config.hfont)
|
|
SendDlgItemMessageW (hwnd, listview_id, WM_SETFONT, (WPARAM)config.hfont, TRUE);
|
|
}
|
|
|
|
VOID _app_listview_setview (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id
|
|
)
|
|
{
|
|
HIMAGELIST himg;
|
|
LONG view_type;
|
|
LONG icons_size;
|
|
BOOLEAN is_mainview;
|
|
|
|
is_mainview = (listview_id >= IDC_APPS_PROFILE) && (listview_id <= IDC_RULES_CUSTOM);
|
|
|
|
if (is_mainview)
|
|
{
|
|
view_type = _r_calc_clamp (_r_config_getlong (L"ViewType", LV_VIEW_DETAILS), LV_VIEW_ICON, LV_VIEW_MAX);
|
|
}
|
|
else
|
|
{
|
|
view_type = LV_VIEW_DETAILS;
|
|
}
|
|
|
|
if (is_mainview)
|
|
{
|
|
icons_size = _r_calc_clamp (_r_config_getlong (L"IconSize", SHIL_SMALL), SHIL_LARGE, SHIL_LAST);
|
|
}
|
|
else
|
|
{
|
|
icons_size = SHIL_SMALL;
|
|
}
|
|
|
|
if ((listview_id >= IDC_RULES_BLOCKLIST && listview_id <= IDC_RULES_CUSTOM) || listview_id == IDC_APP_RULES_ID)
|
|
{
|
|
if (icons_size == SHIL_SMALL || icons_size == SHIL_SYSSMALL)
|
|
{
|
|
himg = config.himg_rules_small;
|
|
}
|
|
else
|
|
{
|
|
himg = config.himg_rules_large;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SHGetImageList (icons_size, &IID_IImageList2, &himg);
|
|
}
|
|
|
|
if (himg)
|
|
_r_listview_setimagelist (hwnd, listview_id, himg);
|
|
|
|
_r_listview_setview (hwnd, listview_id, view_type);
|
|
}
|
|
|
|
INT CALLBACK _app_listview_compare_callback (
|
|
_In_ LPARAM lparam1,
|
|
_In_ LPARAM lparam2,
|
|
_In_ LPARAM lparam
|
|
)
|
|
{
|
|
WCHAR config_name[128];
|
|
HWND hwnd;
|
|
ULONG_PTR context1;
|
|
ULONG_PTR context2;
|
|
LONG column_id;
|
|
INT listview_id;
|
|
INT result = 0;
|
|
INT item_id1;
|
|
INT item_id2;
|
|
PR_STRING item_text_1;
|
|
PR_STRING item_text_2;
|
|
PITEM_LOG ptr_log1;
|
|
PITEM_LOG ptr_log2;
|
|
LONG64 timestamp1 = 0;
|
|
LONG64 timestamp2 = 0;
|
|
BOOLEAN is_success1;
|
|
BOOLEAN is_success2;
|
|
BOOLEAN is_checked1;
|
|
BOOLEAN is_checked2;
|
|
BOOLEAN is_descend;
|
|
|
|
hwnd = GetParent ((HWND)lparam);
|
|
|
|
if (!hwnd)
|
|
return 0;
|
|
|
|
listview_id = GetDlgCtrlID ((HWND)lparam);
|
|
|
|
if (!listview_id)
|
|
return 0;
|
|
|
|
item_id1 = (INT)(INT_PTR)lparam1;
|
|
item_id2 = (INT)(INT_PTR)lparam2;
|
|
|
|
_r_str_printf (config_name, RTL_NUMBER_OF (config_name), L"listview\\%04" TEXT (PRIX32), listview_id);
|
|
|
|
column_id = _r_config_getlong_ex (L"SortColumn", 0, config_name);
|
|
is_descend = _r_config_getboolean_ex (L"SortIsDescending", FALSE, config_name);
|
|
|
|
if ((_r_listview_getstyle_ex (hwnd, listview_id) & LVS_EX_CHECKBOXES) != 0)
|
|
{
|
|
is_checked1 = _r_listview_isitemchecked (hwnd, listview_id, item_id1);
|
|
is_checked2 = _r_listview_isitemchecked (hwnd, listview_id, item_id2);
|
|
|
|
if (is_checked1 != is_checked2)
|
|
{
|
|
if (is_checked1 && !is_checked2)
|
|
{
|
|
result = is_descend ? 1 : -1;
|
|
}
|
|
else if (!is_checked1 && is_checked2)
|
|
{
|
|
result = is_descend ? -1 : 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
context1 = _app_listview_getitemcontext (hwnd, listview_id, item_id1);
|
|
context2 = _app_listview_getitemcontext (hwnd, listview_id, item_id2);
|
|
|
|
if (!result)
|
|
{
|
|
// timestamp sorting
|
|
if ((listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_APPS_UWP) && column_id == 1)
|
|
{
|
|
is_success1 = _app_getappinfobyhash (context1, INFO_TIMESTAMP, ×tamp1, sizeof (timestamp1));
|
|
is_success2 = _app_getappinfobyhash (context2, INFO_TIMESTAMP, ×tamp2, sizeof (timestamp2));
|
|
|
|
if (is_success1 && is_success2)
|
|
{
|
|
if (timestamp1 < timestamp2)
|
|
{
|
|
result = -1;
|
|
}
|
|
else if (timestamp1 > timestamp2)
|
|
{
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
else if (listview_id == IDC_LOG && column_id == 11)
|
|
{
|
|
ptr_log1 = _app_getlogitem (context1);
|
|
ptr_log2 = _app_getlogitem (context2);
|
|
|
|
if (ptr_log1 && ptr_log2)
|
|
{
|
|
if (ptr_log1->timestamp < ptr_log2->timestamp)
|
|
{
|
|
result = -1;
|
|
}
|
|
else if (ptr_log1->timestamp > ptr_log2->timestamp)
|
|
{
|
|
result = 1;
|
|
}
|
|
}
|
|
|
|
if (ptr_log1)
|
|
_r_obj_dereference (ptr_log1);
|
|
|
|
if (ptr_log2)
|
|
_r_obj_dereference (ptr_log2);
|
|
}
|
|
}
|
|
|
|
if (!result)
|
|
{
|
|
item_text_1 = _r_listview_getitemtext (hwnd, listview_id, item_id1, column_id);
|
|
item_text_2 = _r_listview_getitemtext (hwnd, listview_id, item_id2, column_id);
|
|
|
|
if (item_text_1 && item_text_2)
|
|
result = _r_str_compare_logical (item_text_1, item_text_2);
|
|
|
|
if (item_text_1)
|
|
_r_obj_dereference (item_text_1);
|
|
|
|
if (item_text_2)
|
|
_r_obj_dereference (item_text_2);
|
|
}
|
|
|
|
return is_descend ? -result : result;
|
|
}
|
|
|
|
VOID _app_listview_sort_ex (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id,
|
|
_In_ LONG column_id,
|
|
_In_ BOOLEAN is_notifycode
|
|
)
|
|
{
|
|
WCHAR config_name[128];
|
|
HWND hlistview;
|
|
INT column_count;
|
|
BOOLEAN is_descend;
|
|
|
|
hlistview = GetDlgItem (hwnd, listview_id);
|
|
|
|
if (!hlistview)
|
|
return;
|
|
|
|
if ((GetWindowLongPtrW (hlistview, GWL_STYLE) & (LVS_NOSORTHEADER | LVS_OWNERDATA)) != 0)
|
|
return;
|
|
|
|
column_count = _r_listview_getcolumncount (hwnd, listview_id);
|
|
|
|
if (!column_count)
|
|
return;
|
|
|
|
_r_str_printf (config_name, RTL_NUMBER_OF (config_name), L"listview\\%04" TEXT (PRIX32), listview_id);
|
|
|
|
is_descend = _r_config_getboolean_ex (L"SortIsDescending", FALSE, config_name);
|
|
|
|
if (is_notifycode)
|
|
is_descend = !is_descend;
|
|
|
|
if (column_id == -1)
|
|
column_id = _r_config_getlong_ex (L"SortColumn", 0, config_name);
|
|
|
|
column_id = _r_calc_clamp (column_id, 0, column_count - 1); // set range
|
|
|
|
if (is_notifycode)
|
|
{
|
|
_r_config_setboolean_ex (L"SortIsDescending", is_descend, config_name);
|
|
_r_config_setlong_ex (L"SortColumn", column_id, config_name);
|
|
}
|
|
|
|
for (INT i = 0; i < column_count; i++)
|
|
_r_listview_setcolumnsortindex (hwnd, listview_id, i, 0);
|
|
|
|
_r_listview_setcolumnsortindex (hwnd, listview_id, column_id, is_descend ? -1 : 1);
|
|
|
|
SendMessageW (hlistview, LVM_SORTITEMSEX, (WPARAM)hlistview, (LPARAM)&_app_listview_compare_callback);
|
|
}
|
|
|
|
VOID _app_listview_sort (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id
|
|
)
|
|
{
|
|
_app_listview_sort_ex (hwnd, listview_id, -1, FALSE);
|
|
}
|