mirror of
https://github.com/henrypp/simplewall.git
synced 2026-10-22 19:12:58 -05:00
2166 lines
49 KiB
C
2166 lines
49 KiB
C
// simplewall
|
|
// Copyright (c) 2016-2023 Henry++
|
|
|
|
#include "global.h"
|
|
|
|
VOID NTAPI _app_dereferenceapp (
|
|
_In_ PVOID entry
|
|
)
|
|
{
|
|
PITEM_APP ptr_item;
|
|
|
|
ptr_item = entry;
|
|
|
|
if (ptr_item->display_name)
|
|
_r_obj_dereference (ptr_item->display_name);
|
|
|
|
if (ptr_item->real_path)
|
|
_r_obj_dereference (ptr_item->real_path);
|
|
|
|
if (ptr_item->short_name)
|
|
_r_obj_dereference (ptr_item->short_name);
|
|
|
|
if (ptr_item->original_path)
|
|
_r_obj_dereference (ptr_item->original_path);
|
|
|
|
if (ptr_item->notification)
|
|
_r_obj_dereference (ptr_item->notification);
|
|
|
|
if (ptr_item->guids)
|
|
_r_obj_dereference (ptr_item->guids);
|
|
}
|
|
|
|
VOID NTAPI _app_dereferenceappinfo (
|
|
_In_ PVOID entry
|
|
)
|
|
{
|
|
PITEM_APP_INFO ptr_item;
|
|
|
|
ptr_item = entry;
|
|
|
|
if (ptr_item->path)
|
|
_r_obj_dereference (ptr_item->path);
|
|
|
|
if (ptr_item->signature_info)
|
|
_r_obj_dereference (ptr_item->signature_info);
|
|
|
|
if (ptr_item->version_info)
|
|
_r_obj_dereference (ptr_item->version_info);
|
|
}
|
|
|
|
VOID NTAPI _app_dereferenceruleconfig (
|
|
_In_ PVOID entry
|
|
)
|
|
{
|
|
PITEM_RULE_CONFIG ptr_item;
|
|
|
|
ptr_item = entry;
|
|
|
|
if (ptr_item->name)
|
|
_r_obj_dereference (ptr_item->name);
|
|
|
|
if (ptr_item->apps)
|
|
_r_obj_dereference (ptr_item->apps);
|
|
}
|
|
|
|
VOID NTAPI _app_dereferencelog (
|
|
_In_ PVOID entry
|
|
)
|
|
{
|
|
PITEM_LOG ptr_item;
|
|
|
|
ptr_item = entry;
|
|
|
|
if (ptr_item->path)
|
|
_r_obj_dereference (ptr_item->path);
|
|
|
|
if (ptr_item->filter_name)
|
|
_r_obj_dereference (ptr_item->filter_name);
|
|
|
|
if (ptr_item->layer_name)
|
|
_r_obj_dereference (ptr_item->layer_name);
|
|
|
|
if (ptr_item->username)
|
|
_r_obj_dereference (ptr_item->username);
|
|
|
|
if (ptr_item->protocol_str)
|
|
_r_obj_dereference (ptr_item->protocol_str);
|
|
|
|
if (ptr_item->local_addr_str)
|
|
_r_obj_dereference (ptr_item->local_addr_str);
|
|
|
|
if (ptr_item->remote_addr_str)
|
|
_r_obj_dereference (ptr_item->remote_addr_str);
|
|
|
|
if (ptr_item->local_host_str)
|
|
_r_obj_dereference (ptr_item->local_host_str);
|
|
|
|
if (ptr_item->remote_host_str)
|
|
_r_obj_dereference (ptr_item->remote_host_str);
|
|
}
|
|
|
|
VOID NTAPI _app_dereferencenetwork (
|
|
_In_ PVOID entry
|
|
)
|
|
{
|
|
PITEM_NETWORK ptr_item;
|
|
|
|
ptr_item = entry;
|
|
|
|
if (ptr_item->path)
|
|
_r_obj_dereference (ptr_item->path);
|
|
|
|
if (ptr_item->protocol_str)
|
|
_r_obj_dereference (ptr_item->protocol_str);
|
|
|
|
if (ptr_item->local_addr_str)
|
|
_r_obj_dereference (ptr_item->local_addr_str);
|
|
|
|
if (ptr_item->remote_addr_str)
|
|
_r_obj_dereference (ptr_item->remote_addr_str);
|
|
|
|
if (ptr_item->local_host_str)
|
|
_r_obj_dereference (ptr_item->local_host_str);
|
|
|
|
if (ptr_item->remote_host_str)
|
|
_r_obj_dereference (ptr_item->remote_host_str);
|
|
}
|
|
|
|
VOID NTAPI _app_dereferencerule (
|
|
_In_ PVOID entry
|
|
)
|
|
{
|
|
PITEM_RULE ptr_item;
|
|
|
|
ptr_item = entry;
|
|
|
|
if (ptr_item->apps)
|
|
_r_obj_dereference (ptr_item->apps);
|
|
|
|
if (ptr_item->name)
|
|
_r_obj_dereference (ptr_item->name);
|
|
|
|
if (ptr_item->rule_remote)
|
|
_r_obj_dereference (ptr_item->rule_remote);
|
|
|
|
if (ptr_item->rule_local)
|
|
_r_obj_dereference (ptr_item->rule_local);
|
|
|
|
if (ptr_item->protocol_str)
|
|
_r_obj_dereference (ptr_item->protocol_str);
|
|
|
|
if (ptr_item->guids)
|
|
_r_obj_dereference (ptr_item->guids);
|
|
}
|
|
|
|
VOID _app_addcachetable (
|
|
_Inout_ PR_HASHTABLE hashtable,
|
|
_In_ ULONG_PTR hash_code,
|
|
_In_ PR_QUEUED_LOCK spin_lock,
|
|
_In_opt_ PR_STRING string
|
|
)
|
|
{
|
|
BOOLEAN is_exceed;
|
|
|
|
// check overflow and do nothing
|
|
_r_queuedlock_acquireshared (spin_lock);
|
|
is_exceed = (_r_obj_gethashtablesize (hashtable) >= MAP_CACHE_MAX);
|
|
_r_queuedlock_releaseshared (spin_lock);
|
|
|
|
if (is_exceed)
|
|
return;
|
|
|
|
_r_queuedlock_acquireexclusive (spin_lock);
|
|
_r_obj_addhashtablepointer (hashtable, hash_code, string);
|
|
_r_queuedlock_releaseexclusive (spin_lock);
|
|
}
|
|
|
|
BOOLEAN _app_getcachetable (
|
|
_Inout_ PR_HASHTABLE cache_table,
|
|
_In_ ULONG_PTR hash_code,
|
|
_In_ PR_QUEUED_LOCK spin_lock,
|
|
_Out_ PR_STRING_PTR string
|
|
)
|
|
{
|
|
PR_OBJECT_POINTER object_ptr;
|
|
|
|
_r_queuedlock_acquireshared (spin_lock);
|
|
object_ptr = _r_obj_findhashtable (cache_table, hash_code);
|
|
_r_queuedlock_releaseshared (spin_lock);
|
|
|
|
if (object_ptr)
|
|
{
|
|
*string = _r_obj_referencesafe (object_ptr->object_body);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
*string = NULL;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
PR_STRING _app_formatarpa (
|
|
_In_ ADDRESS_FAMILY af,
|
|
_In_ LPCVOID address
|
|
)
|
|
{
|
|
R_STRINGBUILDER formatted_address;
|
|
PIN_ADDR p4addr;
|
|
PIN6_ADDR p6addr;
|
|
|
|
_r_obj_initializestringbuilder (&formatted_address, 256);
|
|
|
|
switch (af)
|
|
{
|
|
case AF_INET:
|
|
{
|
|
p4addr = (PIN_ADDR)address;
|
|
|
|
_r_obj_appendstringbuilderformat (
|
|
&formatted_address,
|
|
L"%hhu.%hhu.%hhu.%hhu.%s",
|
|
p4addr->s_impno,
|
|
p4addr->s_lh,
|
|
p4addr->s_host,
|
|
p4addr->s_net,
|
|
DNS_IP4_REVERSE_DOMAIN_STRING_W
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case AF_INET6:
|
|
{
|
|
p6addr = (PIN6_ADDR)address;
|
|
|
|
for (INT i = sizeof (IN6_ADDR) - 1; i >= 0; i--)
|
|
{
|
|
_r_obj_appendstringbuilderformat (
|
|
&formatted_address,
|
|
L"%hhx.%hhx.",
|
|
p6addr->s6_addr[i] & 0xF,
|
|
(p6addr->s6_addr[i] >> 4) & 0xF
|
|
);
|
|
}
|
|
|
|
_r_obj_appendstringbuilder (&formatted_address, DNS_IP6_REVERSE_DOMAIN_STRING_W);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return _r_obj_finalstringbuilder (&formatted_address);
|
|
}
|
|
|
|
_Ret_maybenull_
|
|
PR_STRING _app_formataddress (
|
|
_In_ ADDRESS_FAMILY af,
|
|
_In_ UINT8 proto,
|
|
_In_ LPCVOID address,
|
|
_In_opt_ UINT16 port,
|
|
_In_ ULONG flags
|
|
)
|
|
{
|
|
WCHAR addr_str[DNS_MAX_NAME_BUFFER_LENGTH];
|
|
R_STRINGBUILDER formatted_address;
|
|
PR_STRING string;
|
|
NTSTATUS status;
|
|
|
|
_r_obj_initializestringbuilder (&formatted_address, 256);
|
|
|
|
if (flags & FMTADDR_USE_PROTOCOL)
|
|
{
|
|
string = _app_db_getprotoname (proto, af, FALSE);
|
|
|
|
if (string)
|
|
{
|
|
_r_obj_appendstringbuilder2 (&formatted_address, string);
|
|
_r_obj_appendstringbuilder (&formatted_address, L"://");
|
|
|
|
_r_obj_dereference (string);
|
|
}
|
|
}
|
|
|
|
status = _app_formatip (af, address, addr_str, RTL_NUMBER_OF (addr_str), !!(flags & FMTADDR_AS_RULE));
|
|
|
|
if (NT_SUCCESS (status))
|
|
{
|
|
if (af == AF_INET6 && port)
|
|
{
|
|
_r_obj_appendstringbuilderformat (&formatted_address, L"[%s]", addr_str);
|
|
}
|
|
else
|
|
{
|
|
_r_obj_appendstringbuilder (&formatted_address, addr_str);
|
|
}
|
|
}
|
|
|
|
if (port && !(flags & FMTADDR_USE_PROTOCOL))
|
|
{
|
|
_r_obj_appendstringbuilderformat (&formatted_address, NT_SUCCESS (status) ? L":%" TEXT (PRIu16) : L"%" TEXT (PRIu16), port);
|
|
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if (NT_SUCCESS (status))
|
|
return _r_obj_finalstringbuilder (&formatted_address);
|
|
|
|
_r_obj_deletestringbuilder (&formatted_address);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PR_STRING _app_formataddress_interlocked (
|
|
_In_ PVOID volatile *string,
|
|
_In_ ADDRESS_FAMILY af,
|
|
_In_ LPCVOID address
|
|
)
|
|
{
|
|
PR_STRING current_string;
|
|
PR_STRING new_string;
|
|
|
|
current_string = _InterlockedCompareExchangePointer (string, NULL, NULL);
|
|
|
|
if (current_string)
|
|
return current_string;
|
|
|
|
new_string = _app_formataddress (af, 0, address, 0, 0);
|
|
|
|
current_string = _InterlockedCompareExchangePointer (string, new_string, NULL);
|
|
|
|
if (!current_string)
|
|
{
|
|
current_string = new_string;
|
|
}
|
|
else
|
|
{
|
|
if (new_string)
|
|
_r_obj_dereference (new_string);
|
|
}
|
|
|
|
return current_string;
|
|
}
|
|
|
|
_Success_ (NT_SUCCESS (return))
|
|
NTSTATUS _app_formatip (
|
|
_In_ ADDRESS_FAMILY af,
|
|
_In_ LPCVOID address,
|
|
_Out_writes_to_ (buffer_length, buffer_length) LPWSTR buffer,
|
|
_In_ ULONG buffer_length,
|
|
_In_ BOOLEAN is_checkempty
|
|
)
|
|
{
|
|
PIN_ADDR p4addr;
|
|
PIN6_ADDR p6addr;
|
|
NTSTATUS status;
|
|
|
|
switch (af)
|
|
{
|
|
case AF_INET:
|
|
{
|
|
p4addr = (PIN_ADDR)address;
|
|
|
|
if (is_checkempty)
|
|
{
|
|
if (IN4_IS_ADDR_UNSPECIFIED (p4addr))
|
|
return STATUS_INVALID_ADDRESS_COMPONENT;
|
|
}
|
|
|
|
status = RtlIpv4AddressToStringEx (p4addr, 0, buffer, &buffer_length);
|
|
|
|
return status;
|
|
}
|
|
|
|
case AF_INET6:
|
|
{
|
|
p6addr = (PIN6_ADDR)address;
|
|
|
|
if (is_checkempty)
|
|
{
|
|
if (IN6_IS_ADDR_UNSPECIFIED (p6addr))
|
|
return STATUS_INVALID_ADDRESS_COMPONENT;
|
|
}
|
|
|
|
status = RtlIpv6AddressToStringEx (p6addr, 0, 0, buffer, &buffer_length);
|
|
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
PR_STRING _app_formatport (
|
|
_In_ UINT16 port,
|
|
_In_ UINT8 proto
|
|
)
|
|
{
|
|
LPCWSTR service_string;
|
|
|
|
service_string = _app_db_getservicename (port, proto, NULL);
|
|
|
|
if (service_string)
|
|
return _r_format_string (L"%" TEXT (PRIu16) L" (%s)", port, service_string);
|
|
|
|
return _r_format_string (L"%" TEXT (PRIu16), port);
|
|
}
|
|
|
|
_Ret_maybenull_
|
|
PITEM_APP_INFO _app_getappinfobyhash2 (
|
|
_In_ ULONG_PTR app_hash
|
|
)
|
|
{
|
|
PITEM_APP_INFO ptr_app_info;
|
|
|
|
_r_queuedlock_acquireshared (&lock_cache_information);
|
|
ptr_app_info = _r_obj_findhashtablepointer (cache_information, app_hash);
|
|
_r_queuedlock_releaseshared (&lock_cache_information);
|
|
|
|
return ptr_app_info;
|
|
}
|
|
|
|
_Success_ (return)
|
|
BOOLEAN _app_getappinfoparam2 (
|
|
_In_ ULONG_PTR app_hash,
|
|
_In_opt_ INT listview_id,
|
|
_In_ ENUM_INFO_DATA2 info_data,
|
|
_Out_writes_bytes_all_ (size) PVOID buffer,
|
|
_In_ ULONG_PTR size
|
|
)
|
|
{
|
|
PITEM_APP_INFO ptr_app_info;
|
|
|
|
ptr_app_info = _app_getappinfobyhash2 (app_hash);
|
|
|
|
switch (info_data)
|
|
{
|
|
case INFO_ICON_ID:
|
|
{
|
|
LONG icon_id = 0;
|
|
|
|
if (size != sizeof (LONG))
|
|
{
|
|
if (ptr_app_info)
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (ptr_app_info)
|
|
icon_id = ptr_app_info->icon_id;
|
|
|
|
if (!icon_id)
|
|
icon_id = _app_icons_getdefaultapp_id ((listview_id == IDC_APPS_UWP) ? DATA_APP_UWP : DATA_APP_REGULAR);
|
|
|
|
if (icon_id)
|
|
{
|
|
RtlCopyMemory (buffer, &icon_id, size);
|
|
|
|
if (ptr_app_info)
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INFO_SIGNATURE_STRING:
|
|
{
|
|
PVOID ptr;
|
|
|
|
if (size != sizeof (PVOID))
|
|
{
|
|
if (ptr_app_info)
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (ptr_app_info && !_r_obj_isstringempty (ptr_app_info->signature_info))
|
|
{
|
|
ptr = _r_obj_reference (ptr_app_info->signature_info);
|
|
|
|
RtlCopyMemory (buffer, &ptr, size);
|
|
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INFO_VERSION_STRING:
|
|
{
|
|
PVOID ptr;
|
|
|
|
if (size != sizeof (PVOID))
|
|
{
|
|
if (ptr_app_info)
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (ptr_app_info && !_r_obj_isstringempty (ptr_app_info->version_info))
|
|
{
|
|
ptr = _r_obj_reference (ptr_app_info->version_info);
|
|
|
|
RtlCopyMemory (buffer, &ptr, size);
|
|
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ptr_app_info)
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN _app_isappsigned (
|
|
_In_ ULONG_PTR app_hash
|
|
)
|
|
{
|
|
PR_STRING string = NULL;
|
|
BOOLEAN is_signed;
|
|
|
|
if (_app_getappinfoparam2 (app_hash, 0, INFO_SIGNATURE_STRING, &string, sizeof (string)))
|
|
{
|
|
is_signed = !_r_obj_isstringempty2 (string);
|
|
|
|
_r_obj_dereference (string);
|
|
|
|
return is_signed;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN _app_isappvalidbinary (
|
|
_In_ ENUM_TYPE_DATA type,
|
|
_In_opt_ PR_STRING path
|
|
)
|
|
{
|
|
static R_STRINGREF valid_exts = PR_STRINGREF_INIT (L".exe");
|
|
|
|
if (type != DATA_APP_REGULAR && type != DATA_APP_SERVICE && type != DATA_APP_UWP)
|
|
return FALSE;
|
|
|
|
if (!path)
|
|
return FALSE;
|
|
|
|
if (!_app_isappvalidpath (path))
|
|
return FALSE;
|
|
|
|
if (_r_str_isendsswith (&path->sr, &valid_exts, TRUE))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN _app_isappvalidpath (
|
|
_In_opt_ PR_STRING path
|
|
)
|
|
{
|
|
if (!path)
|
|
return FALSE;
|
|
|
|
if (path->length <= (3 * sizeof (WCHAR)))
|
|
return FALSE;
|
|
|
|
if (path->buffer[1] != L':' || path->buffer[2] != L'\\')
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
_Ret_maybenull_
|
|
PR_STRING _app_getappdisplayname (
|
|
_In_ PITEM_APP ptr_app,
|
|
_In_ BOOLEAN is_shortened
|
|
)
|
|
{
|
|
if (ptr_app->app_hash == config.ntoskrnl_hash)
|
|
{
|
|
if (ptr_app->original_path)
|
|
return _r_obj_reference (ptr_app->original_path);
|
|
}
|
|
|
|
if (ptr_app->type == DATA_APP_SERVICE)
|
|
{
|
|
if (ptr_app->original_path)
|
|
return _r_obj_reference (ptr_app->original_path);
|
|
}
|
|
else if (ptr_app->type == DATA_APP_UWP)
|
|
{
|
|
if (ptr_app->display_name)
|
|
return _r_obj_reference (ptr_app->display_name);
|
|
|
|
if (ptr_app->real_path)
|
|
return _r_obj_reference (ptr_app->real_path);
|
|
|
|
if (ptr_app->original_path)
|
|
return _r_obj_reference (ptr_app->original_path);
|
|
}
|
|
|
|
if (is_shortened || _r_config_getboolean (L"ShowFilenames", TRUE))
|
|
{
|
|
if (ptr_app->short_name)
|
|
return _r_obj_reference (ptr_app->short_name);
|
|
}
|
|
|
|
if (ptr_app->real_path)
|
|
return _r_obj_reference (ptr_app->real_path);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
_Ret_maybenull_
|
|
PR_STRING _app_getappname (
|
|
_In_ PITEM_APP ptr_app
|
|
)
|
|
{
|
|
if (ptr_app->type == DATA_APP_UWP || ptr_app->type == DATA_APP_SERVICE)
|
|
{
|
|
if (ptr_app->real_path)
|
|
return _r_obj_reference (ptr_app->real_path);
|
|
|
|
if (ptr_app->display_name)
|
|
return _r_obj_reference (ptr_app->display_name);
|
|
}
|
|
|
|
if (ptr_app->original_path)
|
|
return _r_obj_reference (ptr_app->original_path);
|
|
|
|
if (ptr_app->real_path)
|
|
return _r_obj_reference (ptr_app->real_path);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
VOID _app_getfileicon (
|
|
_Inout_ PITEM_APP_INFO ptr_app_info
|
|
)
|
|
{
|
|
LONG icon_id = 0;
|
|
BOOLEAN is_iconshidded;
|
|
|
|
is_iconshidded = _r_config_getboolean (L"IsIconsHidden", FALSE);
|
|
|
|
if (is_iconshidded || !_app_isappvalidbinary (ptr_app_info->type, ptr_app_info->path))
|
|
{
|
|
_app_icons_loadfromfile (NULL, ptr_app_info->type, &icon_id, NULL, TRUE);
|
|
}
|
|
else
|
|
{
|
|
_app_icons_loadfromfile (ptr_app_info->path, ptr_app_info->type, &icon_id, NULL, TRUE);
|
|
}
|
|
|
|
ptr_app_info->icon_id = icon_id;
|
|
}
|
|
|
|
_Success_ (return)
|
|
BOOLEAN _app_calculatefilehash (
|
|
_In_ HANDLE hfile,
|
|
_In_opt_ LPCWSTR algorithm_id,
|
|
_Out_ PVOID_PTR file_hash_ptr,
|
|
_Out_ PULONG file_hash_length_ptr,
|
|
_Out_ HCATADMIN * hcat_admin_ptr
|
|
)
|
|
{
|
|
const GUID DriverActionVerify = DRIVER_ACTION_VERIFY;
|
|
|
|
HCATADMIN hcat_admin;
|
|
PBYTE file_hash;
|
|
ULONG file_hash_length;
|
|
|
|
if (!CryptCATAdminAcquireContext2 (&hcat_admin, &DriverActionVerify, algorithm_id, NULL, 0))
|
|
return FALSE;
|
|
|
|
file_hash_length = 32;
|
|
file_hash = _r_mem_allocate (file_hash_length);
|
|
|
|
if (!CryptCATAdminCalcHashFromFileHandle2 (hcat_admin, hfile, &file_hash_length, file_hash, 0))
|
|
{
|
|
file_hash = _r_mem_reallocate (file_hash, file_hash_length);
|
|
|
|
if (!CryptCATAdminCalcHashFromFileHandle2 (hcat_admin, hfile, &file_hash_length, file_hash, 0))
|
|
{
|
|
CryptCATAdminReleaseContext (hcat_admin, 0);
|
|
_r_mem_free (file_hash);
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
*file_hash_ptr = file_hash;
|
|
*file_hash_length_ptr = file_hash_length;
|
|
*hcat_admin_ptr = hcat_admin;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
_Ret_maybenull_
|
|
PR_STRING _app_verifygetstring (
|
|
_In_ HANDLE state_data
|
|
)
|
|
{
|
|
PCRYPT_PROVIDER_DATA prov_data;
|
|
PCRYPT_PROVIDER_SGNR prov_signer;
|
|
PCRYPT_PROVIDER_CERT prov_cert;
|
|
PR_STRING string;
|
|
ULONG length;
|
|
ULONG idx = 0;
|
|
|
|
prov_data = WTHelperProvDataFromStateData (state_data);
|
|
|
|
if (prov_data)
|
|
{
|
|
while (TRUE)
|
|
{
|
|
prov_signer = WTHelperGetProvSignerFromChain (prov_data, idx, FALSE, 0);
|
|
|
|
if (!prov_signer)
|
|
break;
|
|
|
|
prov_cert = WTHelperGetProvCertFromChain (prov_signer, idx);
|
|
|
|
if (!prov_cert)
|
|
break;
|
|
|
|
length = CertGetNameString (prov_cert->pCert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0) - 1;
|
|
|
|
if (length > 1)
|
|
{
|
|
string = _r_obj_createstring_ex (NULL, length * sizeof (WCHAR));
|
|
|
|
CertGetNameString (prov_cert->pCert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, string->buffer, length + 1);
|
|
|
|
_r_obj_trimstringtonullterminator (string);
|
|
|
|
return string;
|
|
}
|
|
|
|
idx += 1;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
LONG _app_verifyfromfile (
|
|
_In_ ULONG union_choice,
|
|
_In_ PVOID union_data,
|
|
_In_ LPGUID action_id,
|
|
_In_opt_ PVOID policy_callback,
|
|
_Out_ PR_STRING_PTR signature_string
|
|
)
|
|
{
|
|
WINTRUST_DATA trust_data = {0};
|
|
LONG status;
|
|
|
|
trust_data.cbStruct = sizeof (trust_data);
|
|
trust_data.dwUIChoice = WTD_UI_NONE;
|
|
trust_data.pPolicyCallbackData = policy_callback;
|
|
trust_data.dwUnionChoice = union_choice;
|
|
|
|
if (union_choice == WTD_CHOICE_CATALOG)
|
|
{
|
|
trust_data.pCatalog = union_data;
|
|
}
|
|
else
|
|
{
|
|
trust_data.pFile = union_data;
|
|
}
|
|
|
|
if (_r_config_getboolean (L"IsOCSPEnabled", FALSE))
|
|
{
|
|
trust_data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
|
|
trust_data.dwProvFlags = WTD_SAFER_FLAG;
|
|
}
|
|
else
|
|
{
|
|
trust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
|
|
trust_data.dwProvFlags = WTD_SAFER_FLAG | WTD_CACHE_ONLY_URL_RETRIEVAL;
|
|
}
|
|
|
|
trust_data.dwStateAction = WTD_STATEACTION_VERIFY;
|
|
status = WinVerifyTrust (INVALID_HANDLE_VALUE, action_id, &trust_data);
|
|
|
|
if (status == ERROR_SUCCESS && trust_data.hWVTStateData)
|
|
{
|
|
*signature_string = _app_verifygetstring (trust_data.hWVTStateData);
|
|
}
|
|
else
|
|
{
|
|
*signature_string = NULL;
|
|
}
|
|
|
|
// Close state data
|
|
trust_data.dwStateAction = WTD_STATEACTION_CLOSE;
|
|
WinVerifyTrust (INVALID_HANDLE_VALUE, action_id, &trust_data);
|
|
|
|
return status;
|
|
}
|
|
|
|
LONG _app_verifyfilefromcatalog (
|
|
_In_ HANDLE hfile,
|
|
_In_ LPCWSTR file_path,
|
|
_In_opt_ LPCWSTR algorithm_id,
|
|
_Out_ PR_STRING_PTR signature_string
|
|
)
|
|
{
|
|
static GUID DriverActionVerify = DRIVER_ACTION_VERIFY;
|
|
|
|
WINTRUST_CATALOG_INFO catalog_info = {0};
|
|
DRIVER_VER_INFO ver_info = {0};
|
|
LARGE_INTEGER file_size;
|
|
CATALOG_INFO ci = {0};
|
|
HCATADMIN hcat_admin;
|
|
HCATINFO hcat_info;
|
|
PR_STRING string = NULL;
|
|
PR_STRING file_hash_tag;
|
|
PVOID file_hash;
|
|
ULONG file_hash_length;
|
|
LONG status = TRUST_E_FAIL;
|
|
|
|
*signature_string = NULL;
|
|
|
|
status = _r_fs_getsize (hfile, &file_size);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
return status;
|
|
|
|
if (!file_size.QuadPart || file_size.QuadPart > _r_calc_megabytes2bytes64 (32))
|
|
return STATUS_FILE_TOO_LARGE;
|
|
|
|
if (_app_calculatefilehash (hfile, algorithm_id, &file_hash, &file_hash_length, &hcat_admin))
|
|
{
|
|
hcat_info = CryptCATAdminEnumCatalogFromHash (hcat_admin, file_hash, file_hash_length, 0, NULL);
|
|
|
|
if (hcat_info)
|
|
{
|
|
file_hash_tag = _r_str_fromhex (file_hash, file_hash_length, TRUE);
|
|
|
|
if (CryptCATCatalogInfoFromContext (hcat_info, &ci, 0))
|
|
{
|
|
// Disable OS version checking by passing in a DRIVER_VER_INFO structure.
|
|
ver_info.cbStruct = sizeof (DRIVER_VER_INFO);
|
|
|
|
catalog_info.cbStruct = sizeof (catalog_info);
|
|
catalog_info.pcwszCatalogFilePath = ci.wszCatalogFile;
|
|
catalog_info.pcwszMemberFilePath = file_path;
|
|
catalog_info.hMemberFile = hfile;
|
|
catalog_info.pcwszMemberTag = file_hash_tag->buffer;
|
|
catalog_info.pbCalculatedFileHash = file_hash;
|
|
catalog_info.cbCalculatedFileHash = file_hash_length;
|
|
catalog_info.hCatAdmin = hcat_admin;
|
|
|
|
status = _app_verifyfromfile (WTD_CHOICE_CATALOG, &catalog_info, &DriverActionVerify, &ver_info, &string);
|
|
|
|
if (ver_info.pcSignerCertContext)
|
|
CertFreeCertificateContext (ver_info.pcSignerCertContext);
|
|
}
|
|
|
|
CryptCATAdminReleaseCatalogContext (hcat_admin, hcat_info, 0);
|
|
|
|
_r_obj_dereference (file_hash_tag);
|
|
}
|
|
|
|
CryptCATAdminReleaseContext (hcat_admin, 0);
|
|
|
|
_r_mem_free (file_hash);
|
|
}
|
|
|
|
*signature_string = string;
|
|
|
|
return status;
|
|
}
|
|
|
|
VOID _app_getfilesignatureinfo (
|
|
_In_ HANDLE hfile,
|
|
_Inout_ PITEM_APP_INFO ptr_app_info
|
|
)
|
|
{
|
|
static GUID WinTrustActionGenericVerifyV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
|
|
|
WINTRUST_FILE_INFO file_info = {0};
|
|
PR_STRING string;
|
|
LONG status;
|
|
|
|
file_info.cbStruct = sizeof (file_info);
|
|
file_info.pcwszFilePath = ptr_app_info->path->buffer;
|
|
file_info.hFile = hfile;
|
|
|
|
status = _app_verifyfromfile (WTD_CHOICE_FILE, &file_info, &WinTrustActionGenericVerifyV2, NULL, &string);
|
|
|
|
if (status == TRUST_E_NOSIGNATURE)
|
|
{
|
|
status = _app_verifyfilefromcatalog (hfile, ptr_app_info->path->buffer, BCRYPT_SHA256_ALGORITHM, &string);
|
|
|
|
if (status == TRUST_E_NOSIGNATURE)
|
|
_app_verifyfilefromcatalog (hfile, ptr_app_info->path->buffer, BCRYPT_SHA1_ALGORITHM, &string);
|
|
}
|
|
|
|
_r_obj_movereference (&ptr_app_info->signature_info, string);
|
|
}
|
|
|
|
VOID _app_getfileversioninfo (
|
|
_Inout_ PITEM_APP_INFO ptr_app_info
|
|
)
|
|
{
|
|
VS_FIXEDFILEINFO *ver_info = NULL;
|
|
PR_STRING version_string = NULL;
|
|
R_STRINGBUILDER sb;
|
|
R_STORAGE ver_block;
|
|
PR_STRING string;
|
|
PVOID hlib;
|
|
ULONG lcid;
|
|
NTSTATUS status;
|
|
|
|
hlib = LoadLibraryEx (ptr_app_info->path->buffer, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
|
|
|
|
if (!hlib)
|
|
goto CleanupExit;
|
|
|
|
status = _r_res_loadresource (hlib, RT_VERSION, MAKEINTRESOURCE (VS_VERSION_INFO), &ver_block);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
goto CleanupExit;
|
|
|
|
_r_obj_initializestringbuilder (&sb, 256);
|
|
|
|
lcid = _r_res_querytranslation (ver_block.buffer);
|
|
|
|
// get file description
|
|
string = _r_res_querystring (ver_block.buffer, L"FileDescription", lcid);
|
|
|
|
if (string)
|
|
{
|
|
_r_obj_appendstringbuilder (&sb, SZ_TAB);
|
|
_r_obj_appendstringbuilder2 (&sb, string);
|
|
|
|
_r_obj_dereference (string);
|
|
}
|
|
|
|
// get file version
|
|
if (_r_res_queryversion (ver_block.buffer, &ver_info))
|
|
{
|
|
if (_r_obj_isstringempty2 (sb.string))
|
|
{
|
|
_r_obj_appendstringbuilder (&sb, SZ_TAB);
|
|
}
|
|
else
|
|
{
|
|
_r_obj_appendstringbuilder (&sb, L" ");
|
|
}
|
|
|
|
_r_obj_appendstringbuilderformat (&sb, L"%d.%d", HIWORD (ver_info->dwFileVersionMS), LOWORD (ver_info->dwFileVersionMS));
|
|
|
|
if (HIWORD (ver_info->dwFileVersionLS) || LOWORD (ver_info->dwFileVersionLS))
|
|
{
|
|
_r_obj_appendstringbuilderformat (&sb, L".%d", HIWORD (ver_info->dwFileVersionLS));
|
|
|
|
if (LOWORD (ver_info->dwFileVersionLS))
|
|
_r_obj_appendstringbuilderformat (&sb, L".%d", LOWORD (ver_info->dwFileVersionLS));
|
|
}
|
|
}
|
|
|
|
if (!_r_obj_isstringempty2 (sb.string))
|
|
_r_obj_appendstringbuilder (&sb, SZ_CRLF);
|
|
|
|
// get file company
|
|
string = _r_res_querystring (ver_block.buffer, L"CompanyName", lcid);
|
|
|
|
if (string)
|
|
{
|
|
_r_obj_appendstringbuilder (&sb, SZ_TAB);
|
|
_r_obj_appendstringbuilder2 (&sb, string);
|
|
_r_obj_appendstringbuilder (&sb, SZ_CRLF);
|
|
|
|
_r_obj_dereference (string);
|
|
}
|
|
|
|
version_string = _r_obj_finalstringbuilder (&sb);
|
|
|
|
_r_str_trimstring2 (version_string, DIVIDER_TRIM, 0);
|
|
|
|
if (_r_obj_isstringempty2 (version_string))
|
|
_r_obj_clearreference (&version_string);
|
|
|
|
CleanupExit:
|
|
|
|
_r_obj_movereference (&ptr_app_info->version_info, version_string);
|
|
|
|
if (hlib)
|
|
FreeLibrary (hlib);
|
|
}
|
|
|
|
VOID _app_getfilehashinfo (
|
|
_In_ HANDLE hfile,
|
|
_Inout_ PITEM_APP_INFO ptr_app_info
|
|
)
|
|
{
|
|
PITEM_APP ptr_app;
|
|
PR_STRING string;
|
|
NTSTATUS status;
|
|
|
|
ptr_app = _app_getappitem (ptr_app_info->app_hash);
|
|
|
|
if (!ptr_app)
|
|
return;
|
|
|
|
status = _r_crypt_getfilehash (BCRYPT_SHA256_ALGORITHM, NULL, hfile, &string);
|
|
|
|
if (NT_SUCCESS (status))
|
|
_r_obj_movereference (&ptr_app->hash, string);
|
|
}
|
|
|
|
ULONG_PTR _app_addcolor (
|
|
_In_ UINT locale_id,
|
|
_In_ LPCWSTR config_name,
|
|
_In_ BOOLEAN is_enabled,
|
|
_In_ LPCWSTR config_value,
|
|
_In_ COLORREF default_clr
|
|
)
|
|
{
|
|
ITEM_COLOR ptr_clr = {0};
|
|
ULONG hash_code;
|
|
|
|
ptr_clr.config_name = _r_obj_createstring (config_name);
|
|
ptr_clr.config_value = _r_obj_createstring (config_value);
|
|
ptr_clr.new_clr = _r_config_getulong_ex (config_value, default_clr, L"colors");
|
|
|
|
ptr_clr.default_clr = default_clr;
|
|
ptr_clr.locale_id = locale_id;
|
|
ptr_clr.is_enabled = is_enabled;
|
|
|
|
hash_code = _r_str_gethash2 (ptr_clr.config_name, TRUE);
|
|
|
|
_r_obj_addhashtableitem (colors_table, hash_code, &ptr_clr);
|
|
|
|
return hash_code;
|
|
}
|
|
|
|
COLORREF _app_getcolorvalue (
|
|
_In_ ULONG_PTR color_hash
|
|
)
|
|
{
|
|
PITEM_COLOR ptr_clr;
|
|
|
|
ptr_clr = _r_obj_findhashtable (colors_table, color_hash);
|
|
|
|
if (ptr_clr)
|
|
return ptr_clr->new_clr ? ptr_clr->new_clr : ptr_clr->default_clr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID _app_generate_rulescontrol (
|
|
_In_ HMENU hsubmenu,
|
|
_In_ ULONG_PTR app_hash,
|
|
_In_opt_ PITEM_LOG ptr_log
|
|
)
|
|
{
|
|
ITEM_STATUS status;
|
|
WCHAR buffer[128];
|
|
PITEM_RULE ptr_rule;
|
|
ULONG_PTR limit_group;
|
|
UINT i;
|
|
BOOLEAN is_global;
|
|
BOOLEAN is_enabled;
|
|
|
|
_app_getcount (&status);
|
|
|
|
if (!status.rules_count)
|
|
{
|
|
_r_menu_additem_ex (hsubmenu, IDX_RULES_SPECIAL, SZ_EMPTY, MF_DISABLED);
|
|
}
|
|
else
|
|
{
|
|
for (UINT8 type = 0; type < 2; type++)
|
|
{
|
|
if (type == 0)
|
|
{
|
|
if (!status.rules_predefined_count)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (!status.rules_user_count)
|
|
continue;
|
|
}
|
|
|
|
for (UINT8 loop = 0; loop < 2; loop++)
|
|
{
|
|
limit_group = 14; // limit rules
|
|
|
|
_r_queuedlock_acquireshared (&lock_rules);
|
|
|
|
for (i = 0; i < (UINT)_r_obj_getlistsize (rules_list) && limit_group; i++)
|
|
{
|
|
ptr_rule = _r_obj_getlistitem (rules_list, i);
|
|
|
|
if (!ptr_rule)
|
|
continue;
|
|
|
|
is_global = (ptr_rule->is_enabled && _r_obj_ishashtableempty (ptr_rule->apps));
|
|
is_enabled = is_global || (ptr_rule->is_enabled && (_r_obj_findhashtable (ptr_rule->apps, app_hash)));
|
|
|
|
if (ptr_rule->type != DATA_RULE_USER)
|
|
continue;
|
|
|
|
if ((type == 0 && (!ptr_rule->is_readonly || is_global)) || (type == 1 && (ptr_rule->is_readonly || is_global)))
|
|
continue;
|
|
|
|
if ((loop == 0 && !is_enabled) || (loop == 1 && is_enabled))
|
|
continue;
|
|
|
|
_r_str_printf (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (IDS_RULE_APPLY_2), _r_obj_getstring (ptr_rule->name));
|
|
|
|
if (ptr_rule->is_readonly)
|
|
_r_str_append (buffer, RTL_NUMBER_OF (buffer), SZ_RULE_INTERNAL_MENU);
|
|
|
|
_r_menu_additem_ex (hsubmenu, IDX_RULES_SPECIAL + i, buffer, is_enabled ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
limit_group -= 1;
|
|
}
|
|
|
|
_r_queuedlock_releaseshared (&lock_rules);
|
|
}
|
|
|
|
if (!type)
|
|
_r_menu_additem (hsubmenu, 0, NULL);
|
|
}
|
|
|
|
if (ptr_log)
|
|
{
|
|
_r_menu_additem (hsubmenu, 0, NULL);
|
|
|
|
_r_str_printf (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (IDS_RULE_APPLY_2), _r_obj_getstring (ptr_log->remote_addr_str));
|
|
|
|
_r_menu_additem (hsubmenu, IDX_RULES_SPECIAL + i + 1, buffer);
|
|
}
|
|
}
|
|
|
|
_r_menu_additem (hsubmenu, 0, NULL);
|
|
_r_menu_additem (hsubmenu, IDM_OPENRULESEDITOR, _r_locale_getstring (IDS_OPENRULESEDITOR));
|
|
}
|
|
|
|
VOID _app_generate_timerscontrol (
|
|
_In_ HMENU hsubmenu,
|
|
_In_ ULONG_PTR app_hash
|
|
)
|
|
{
|
|
LONG64 current_time;
|
|
LONG64 app_time = 0;
|
|
LONG64 timestamp;
|
|
PR_STRING interval_string;
|
|
UINT index;
|
|
BOOLEAN is_checked;
|
|
|
|
current_time = _r_unixtime_now ();
|
|
|
|
is_checked = FALSE;
|
|
|
|
_app_getappinfobyhash (app_hash, INFO_TIMER, &app_time, sizeof (app_time));
|
|
|
|
for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (timer_array); i++)
|
|
{
|
|
timestamp = timer_array[i];
|
|
|
|
interval_string = _r_format_interval (timestamp, 3);
|
|
|
|
if (!interval_string)
|
|
continue;
|
|
|
|
index = IDX_TIMER + (UINT)i;
|
|
|
|
_r_menu_additem (hsubmenu, index, interval_string->buffer);
|
|
|
|
if (!is_checked && (app_time > current_time) && (app_time <= (current_time + timestamp)))
|
|
{
|
|
_r_menu_checkitem (hsubmenu, IDX_TIMER, index, MF_BYCOMMAND, index);
|
|
is_checked = TRUE;
|
|
}
|
|
|
|
_r_obj_dereference (interval_string);
|
|
}
|
|
|
|
if (!is_checked)
|
|
_r_menu_checkitem (hsubmenu, IDM_DISABLETIMER, IDM_DISABLETIMER, MF_BYCOMMAND, IDM_DISABLETIMER);
|
|
}
|
|
|
|
BOOLEAN _app_setruletoapp (
|
|
_In_ HWND hwnd,
|
|
_Inout_ PITEM_RULE ptr_rule,
|
|
_In_ INT item_id,
|
|
_In_ PITEM_APP ptr_app,
|
|
_In_ BOOLEAN is_enable
|
|
)
|
|
{
|
|
INT listview_id;
|
|
|
|
if (ptr_rule->is_forservices && _app_issystemhash (ptr_app->app_hash))
|
|
return FALSE;
|
|
|
|
if (is_enable == (_r_obj_findhashtable (ptr_rule->apps, ptr_app->app_hash) != NULL))
|
|
return FALSE;
|
|
|
|
if (is_enable)
|
|
{
|
|
_r_obj_addhashtableitem (ptr_rule->apps, ptr_app->app_hash, NULL);
|
|
|
|
_app_ruleenable (ptr_rule, TRUE, TRUE);
|
|
}
|
|
else
|
|
{
|
|
_r_obj_removehashtableitem (ptr_rule->apps, ptr_app->app_hash);
|
|
|
|
if (_r_obj_ishashtableempty (ptr_rule->apps))
|
|
_app_ruleenable (ptr_rule, FALSE, TRUE);
|
|
}
|
|
|
|
if (item_id != -1)
|
|
{
|
|
listview_id = _app_listview_getbytype (ptr_rule->type);
|
|
|
|
_app_listview_updateitemby_param (hwnd, _app_listview_getitemcontext (hwnd, listview_id, item_id), FALSE);
|
|
}
|
|
|
|
_app_listview_updateitemby_param (hwnd, ptr_app->app_hash, TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
_Success_ (return)
|
|
BOOLEAN _app_parsenetworkstring (
|
|
_In_ LPCWSTR network_string,
|
|
_Inout_ PITEM_ADDRESS address
|
|
)
|
|
{
|
|
NET_ADDRESS_INFO ni;
|
|
NET_ADDRESS_INFO ni_end;
|
|
ULONG mask;
|
|
ULONG types;
|
|
ULONG status;
|
|
USHORT range_port1;
|
|
USHORT range_port2;
|
|
USHORT port;
|
|
BYTE prefix_length;
|
|
|
|
types = NET_STRING_IP_ADDRESS_NO_SCOPE | NET_STRING_IP_SERVICE | NET_STRING_IP_NETWORK | NET_STRING_IP_ADDRESS_NO_SCOPE | NET_STRING_IP_ADDRESS;
|
|
|
|
if (address->is_range)
|
|
{
|
|
range_port1 = 0;
|
|
range_port2 = 0;
|
|
|
|
status = ParseNetworkString (address->range_start, types, &ni, &range_port1, NULL);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
goto CleanupExit;
|
|
|
|
status = ParseNetworkString (address->range_end, types, &ni_end, &range_port2, NULL);
|
|
|
|
if (range_port2)
|
|
{
|
|
port = range_port2;
|
|
}
|
|
else if (range_port1)
|
|
{
|
|
port = range_port1;
|
|
}
|
|
else
|
|
{
|
|
port = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status = ParseNetworkString (network_string, types, &ni, &port, &prefix_length);
|
|
}
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
goto CleanupExit;
|
|
|
|
address->format = ni.Format;
|
|
address->port = port;
|
|
|
|
if (ni.Format == NET_ADDRESS_IPV4)
|
|
{
|
|
if (address->is_range)
|
|
{
|
|
address->range.valueLow.type = FWP_UINT32;
|
|
address->range.valueLow.uint32 = _r_byteswap_ulong (ni.Ipv4Address.sin_addr.S_un.S_addr);
|
|
|
|
address->range.valueHigh.type = FWP_UINT32;
|
|
address->range.valueHigh.uint32 = _r_byteswap_ulong (ni_end.Ipv4Address.sin_addr.S_un.S_addr);
|
|
}
|
|
else
|
|
{
|
|
mask = 0;
|
|
|
|
if (ConvertLengthToIpv4Mask (prefix_length, &mask) == NOERROR)
|
|
mask = _r_byteswap_ulong (mask);
|
|
|
|
address->addr4.addr = _r_byteswap_ulong (ni.Ipv4Address.sin_addr.S_un.S_addr);
|
|
address->addr4.mask = mask;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else if (ni.Format == NET_ADDRESS_IPV6)
|
|
{
|
|
if (address->is_range)
|
|
{
|
|
address->range.valueLow.type = FWP_BYTE_ARRAY16_TYPE;
|
|
|
|
RtlCopyMemory (address->addr6_low, ni.Ipv6Address.sin6_addr.u.Byte, FWP_V6_ADDR_SIZE);
|
|
address->range.valueLow.byteArray16 = (FWP_BYTE_ARRAY16 *)address->addr6_low;
|
|
|
|
address->range.valueHigh.type = FWP_BYTE_ARRAY16_TYPE;
|
|
|
|
RtlCopyMemory (address->addr6_high, ni_end.Ipv6Address.sin6_addr.u.Byte, FWP_V6_ADDR_SIZE);
|
|
address->range.valueHigh.byteArray16 = (FWP_BYTE_ARRAY16 *)address->addr6_high;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory (address->addr6.addr, ni.Ipv6Address.sin6_addr.u.Byte, FWP_V6_ADDR_SIZE);
|
|
address->addr6.prefixLength = min (prefix_length, 128);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CleanupExit:
|
|
|
|
_r_log (LOG_LEVEL_INFO, NULL, L"ParseNetworkString", status, network_string);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
_Success_ (return)
|
|
BOOLEAN _app_preparserulestring (
|
|
_In_ PR_STRINGREF rule,
|
|
_Out_ PITEM_ADDRESS address
|
|
)
|
|
{
|
|
static WCHAR valid_chars[] = {
|
|
L'.',
|
|
L':',
|
|
L'[',
|
|
L']',
|
|
L'/',
|
|
L'-',
|
|
L'_',
|
|
};
|
|
|
|
R_STRINGREF range_start_part;
|
|
R_STRINGREF range_end_part;
|
|
WCHAR rule_string[256];
|
|
ULONG_PTR length;
|
|
ULONG types;
|
|
BOOLEAN is_valid;
|
|
|
|
length = _r_str_getlength3 (rule);
|
|
|
|
for (ULONG_PTR i = 0; i < length; i++)
|
|
{
|
|
if (IsCharAlphaNumeric (rule->buffer[i]))
|
|
continue;
|
|
|
|
is_valid = FALSE;
|
|
|
|
for (ULONG_PTR j = 0; j < RTL_NUMBER_OF (valid_chars); j++)
|
|
{
|
|
if (rule->buffer[i] == valid_chars[j])
|
|
{
|
|
is_valid = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!is_valid)
|
|
return FALSE;
|
|
}
|
|
|
|
// parse rule range
|
|
address->is_range = _r_str_splitatchar (rule, DIVIDER_RULE_RANGE, &range_start_part, &range_end_part);
|
|
|
|
// extract start and end position of rule
|
|
if (address->is_range)
|
|
{
|
|
// there is incorrect range syntax
|
|
if (_r_obj_isstringempty2 (&range_start_part) || _r_obj_isstringempty2 (&range_end_part))
|
|
return FALSE;
|
|
|
|
_r_str_copystring (address->range_start, RTL_NUMBER_OF (address->range_start), &range_start_part);
|
|
_r_str_copystring (address->range_end, RTL_NUMBER_OF (address->range_end), &range_end_part);
|
|
}
|
|
|
|
// check rule for port
|
|
if (address->type == DATA_UNKNOWN)
|
|
{
|
|
address->type = DATA_TYPE_PORT;
|
|
|
|
for (ULONG_PTR i = 0; i < length; i++)
|
|
{
|
|
if (!_r_str_isdigit (rule->buffer[i]) && rule->buffer[i] != DIVIDER_RULE_RANGE)
|
|
{
|
|
address->type = DATA_UNKNOWN;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (address->type != DATA_UNKNOWN)
|
|
return TRUE;
|
|
|
|
_r_str_copystring (rule_string, RTL_NUMBER_OF (rule_string), rule);
|
|
|
|
types = NET_STRING_IP_ADDRESS | NET_STRING_IP_SERVICE | NET_STRING_IP_NETWORK | NET_STRING_IP_ADDRESS_NO_SCOPE | NET_STRING_IP_SERVICE_NO_SCOPE;
|
|
|
|
// check rule for ip address
|
|
if (address->is_range)
|
|
{
|
|
if (ParseNetworkString (address->range_start, types, NULL, NULL, NULL) == ERROR_SUCCESS &&
|
|
ParseNetworkString (address->range_end, types, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
{
|
|
address->type = DATA_TYPE_IP;
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ParseNetworkString (rule_string, types, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
{
|
|
address->type = DATA_TYPE_IP;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
_Success_ (return)
|
|
BOOLEAN _app_parserulestring (
|
|
_In_opt_ PR_STRINGREF rule,
|
|
_Out_ PITEM_ADDRESS address
|
|
)
|
|
{
|
|
WCHAR rule_string[256];
|
|
R_STRINGREF sr;
|
|
|
|
RtlZeroMemory (address, sizeof (ITEM_ADDRESS));
|
|
|
|
if (_r_obj_isstringempty (rule))
|
|
return TRUE;
|
|
|
|
// parse rule type
|
|
if (!_app_preparserulestring (rule, address))
|
|
return FALSE;
|
|
|
|
if (address->type == DATA_TYPE_PORT)
|
|
{
|
|
if (address->is_range)
|
|
{
|
|
// ...port range
|
|
_r_obj_initializestringref (&sr, address->range_start);
|
|
|
|
address->range.valueLow.type = FWP_UINT16;
|
|
address->range.valueLow.uint16 = (UINT16)_r_str_toulong (&sr);
|
|
|
|
_r_obj_initializestringref (&sr, address->range_end);
|
|
|
|
address->range.valueHigh.type = FWP_UINT16;
|
|
address->range.valueHigh.uint16 = (UINT16)_r_str_toulong (&sr);
|
|
|
|
if (address->range.valueLow.uint16 < 1)
|
|
return FALSE;
|
|
|
|
if (address->range.valueHigh.uint16 > 65535)
|
|
return FALSE;
|
|
|
|
if (address->range.valueLow.uint16 >= address->range.valueHigh.uint16)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// ...port
|
|
address->port = (UINT16)_r_str_toulong (rule);
|
|
|
|
if (address->port < 1)
|
|
return FALSE;
|
|
|
|
if (address->port > 65535)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (address->type == DATA_TYPE_IP)
|
|
{
|
|
_r_str_copystring (rule_string, RTL_NUMBER_OF (rule_string), rule);
|
|
|
|
if (!_app_parsenetworkstring (rule_string, address))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
_Ret_maybenull_
|
|
PR_STRING _app_resolveaddress (
|
|
_In_ ADDRESS_FAMILY af,
|
|
_In_ LPCVOID address
|
|
)
|
|
{
|
|
PDNS_RECORD dns_records = NULL;
|
|
PR_STRING arpa_string;
|
|
PR_STRING string = NULL;
|
|
ULONG_PTR arpa_hash;
|
|
DNS_STATUS status;
|
|
|
|
arpa_string = _app_formatarpa (af, address);
|
|
arpa_hash = _r_str_gethash2 (arpa_string, TRUE);
|
|
|
|
if (_app_getcachetable (cache_resolution, arpa_hash, &lock_cache_resolution, &string))
|
|
{
|
|
_r_obj_dereference (arpa_string);
|
|
|
|
return string;
|
|
}
|
|
|
|
status = DnsQuery_W (arpa_string->buffer, DNS_TYPE_PTR, DNS_QUERY_NO_HOSTS_FILE, NULL, &dns_records, NULL);
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
if (dns_records)
|
|
{
|
|
for (PDNS_RECORD dns_record = dns_records; dns_record; dns_record = dns_record->pNext)
|
|
{
|
|
if (dns_record->wType == DNS_TYPE_PTR)
|
|
{
|
|
string = _r_obj_createstring (dns_record->Data.PTR.pNameHost);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
DnsRecordListFree (dns_records, DnsFreeRecordList);
|
|
}
|
|
}
|
|
|
|
_app_addcachetable (cache_resolution, arpa_hash, &lock_cache_resolution, _r_obj_referencesafe (string));
|
|
|
|
_r_obj_dereference (arpa_string);
|
|
|
|
return string;
|
|
}
|
|
|
|
PR_STRING _app_resolveaddress_interlocked (
|
|
_In_ PVOID volatile *string,
|
|
_In_ ADDRESS_FAMILY af,
|
|
_In_ LPCVOID address,
|
|
_In_ BOOLEAN is_resolutionenabled
|
|
)
|
|
{
|
|
PR_STRING current_string;
|
|
PR_STRING new_string;
|
|
|
|
current_string = _InterlockedCompareExchangePointer (string, NULL, NULL);
|
|
|
|
if (current_string)
|
|
return current_string;
|
|
|
|
if (is_resolutionenabled)
|
|
{
|
|
new_string = _app_resolveaddress (af, address);
|
|
|
|
if (!new_string)
|
|
new_string = _r_obj_referenceemptystring ();
|
|
}
|
|
else
|
|
{
|
|
new_string = _r_obj_referenceemptystring ();
|
|
}
|
|
|
|
current_string = _InterlockedCompareExchangePointer (string, new_string, NULL);
|
|
|
|
if (!current_string)
|
|
{
|
|
current_string = new_string;
|
|
}
|
|
else
|
|
{
|
|
_r_obj_dereference (new_string);
|
|
}
|
|
|
|
return current_string;
|
|
}
|
|
|
|
VOID _app_fileloggingenable ()
|
|
{
|
|
BOOLEAN is_enable;
|
|
NTSTATUS status;
|
|
|
|
is_enable = _r_config_getboolean (L"IsEnableAppMonitor", FALSE);
|
|
|
|
if (is_enable)
|
|
{
|
|
status = _r_sys_createthread (&_app_timercallback, NULL, &config.hmonitor_thread, NULL, L"FileMonitor");
|
|
|
|
if (NT_SUCCESS (status))
|
|
NtResumeThread (config.hmonitor_thread, NULL);
|
|
}
|
|
else
|
|
{
|
|
if (config.hmonitor_thread)
|
|
{
|
|
NtTerminateThread (config.hmonitor_thread, 0);
|
|
NtClose (config.hmonitor_thread);
|
|
|
|
config.hmonitor_thread = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS _app_timercallback (
|
|
_In_ PVOID context
|
|
)
|
|
{
|
|
LARGE_INTEGER timeout;
|
|
PITEM_APP ptr_app = NULL;
|
|
PR_STRING hash;
|
|
ULONG_PTR enum_key;
|
|
NTSTATUS status;
|
|
|
|
_r_calc_millisecondstolargeinteger (&timeout, _r_calc_minutes2milliseconds (10));
|
|
|
|
while (TRUE)
|
|
{
|
|
NtWaitForSingleObject (NtCurrentThread (), FALSE, &timeout);
|
|
|
|
_r_queuedlock_acquireshared (&lock_apps);
|
|
|
|
enum_key = 0;
|
|
|
|
while (_r_obj_enumhashtablepointer (apps_table, &ptr_app, NULL, &enum_key))
|
|
{
|
|
if (!ptr_app->hash || !_app_isappvalidbinary (ptr_app->type, ptr_app->real_path))
|
|
continue;
|
|
|
|
if (!_app_isappused (ptr_app, FALSE))
|
|
continue;
|
|
|
|
status = _r_crypt_getfilehash (BCRYPT_SHA256_ALGORITHM, ptr_app->real_path->buffer, NULL, &hash);
|
|
|
|
if (NT_SUCCESS (status))
|
|
{
|
|
if (!_r_str_isequal (&ptr_app->hash->sr, &hash->sr, TRUE))
|
|
{
|
|
_r_obj_movereference (&ptr_app->hash, hash);
|
|
|
|
if (_r_config_getboolean (L"IsEnableAppMonitor", FALSE))
|
|
{
|
|
_app_setappinfo (ptr_app, INFO_DISABLE, IntToPtr (0));
|
|
|
|
_r_obj_cleararray (ptr_app->guids);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_r_obj_dereference (hash);
|
|
}
|
|
}
|
|
}
|
|
|
|
_r_queuedlock_releaseshared (&lock_apps);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID _app_queue_fileinformation (
|
|
_In_ PR_STRING path,
|
|
_In_ ULONG_PTR app_hash,
|
|
_In_ ENUM_TYPE_DATA type,
|
|
_In_ INT listview_id
|
|
)
|
|
{
|
|
PITEM_APP_INFO ptr_app_info;
|
|
|
|
ptr_app_info = _app_getappinfobyhash2 (app_hash);
|
|
|
|
if (ptr_app_info)
|
|
{
|
|
// all information is already set
|
|
if (ptr_app_info->is_loaded)
|
|
{
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ptr_app_info = _r_obj_allocate (sizeof (ITEM_APP_INFO), &_app_dereferenceappinfo);
|
|
|
|
RtlSecureZeroMemory (ptr_app_info, sizeof (ITEM_APP_INFO));
|
|
|
|
ptr_app_info->path = _r_obj_reference (path);
|
|
ptr_app_info->app_hash = app_hash;
|
|
ptr_app_info->type = type;
|
|
ptr_app_info->listview_id = listview_id;
|
|
|
|
_r_queuedlock_acquireexclusive (&lock_cache_information);
|
|
_r_obj_addhashtablepointer (cache_information, app_hash, _r_obj_reference (ptr_app_info));
|
|
_r_queuedlock_releaseexclusive (&lock_cache_information);
|
|
}
|
|
|
|
_r_workqueue_queueitem (&file_queue, &_app_queuefileinformation, ptr_app_info);
|
|
}
|
|
|
|
VOID _app_queue_resolver (
|
|
_In_ HWND hwnd,
|
|
_In_ INT listview_id,
|
|
_In_ ULONG_PTR hash_code,
|
|
_In_ PVOID base_address
|
|
)
|
|
{
|
|
PITEM_CONTEXT context;
|
|
|
|
context = _r_freelist_allocateitem (&context_free_list);
|
|
|
|
context->hwnd = hwnd;
|
|
context->listview_id = listview_id;
|
|
context->lparam = hash_code;
|
|
context->base_address = _r_obj_reference (base_address);
|
|
|
|
_r_workqueue_queueitem (&resolver_queue, &_app_queueresolveinformation, context);
|
|
}
|
|
|
|
VOID NTAPI _app_queuefileinformation (
|
|
_In_ PVOID arglist,
|
|
_In_ ULONG busy_count
|
|
)
|
|
{
|
|
PITEM_APP_INFO ptr_app_info;
|
|
HANDLE hfile;
|
|
HWND hwnd;
|
|
NTSTATUS status;
|
|
|
|
ptr_app_info = arglist;
|
|
hwnd = _r_app_gethwnd ();
|
|
|
|
// check for binary path is valid
|
|
if (!_app_isappvalidbinary (ptr_app_info->type, ptr_app_info->path))
|
|
return;
|
|
|
|
status = _r_fs_createfile (
|
|
ptr_app_info->path->buffer,
|
|
FILE_OPEN,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0,
|
|
FALSE,
|
|
NULL,
|
|
&hfile
|
|
);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
{
|
|
if (status != STATUS_OBJECT_NAME_NOT_FOUND && status != STATUS_OBJECT_PATH_NOT_FOUND && status != STATUS_ACCESS_DENIED)
|
|
_r_log (LOG_LEVEL_ERROR, NULL, L"_r_fs_createfile", status, ptr_app_info->path->buffer);
|
|
|
|
return;
|
|
}
|
|
|
|
// query app icon
|
|
_app_getfileicon (ptr_app_info);
|
|
|
|
// query certificate information
|
|
_app_getfilesignatureinfo (hfile, ptr_app_info);
|
|
|
|
// query version info
|
|
_app_getfileversioninfo (ptr_app_info);
|
|
|
|
// query sha256 info
|
|
_app_getfilehashinfo (hfile, ptr_app_info);
|
|
|
|
// redraw listview
|
|
if (!(busy_count % 4)) // lol, hack!!!
|
|
{
|
|
if (_r_wnd_isvisible (hwnd))
|
|
{
|
|
if (ptr_app_info->listview_id == _app_listview_getcurrent (hwnd))
|
|
_r_listview_redraw (hwnd, ptr_app_info->listview_id, -1);
|
|
}
|
|
}
|
|
|
|
ptr_app_info->is_loaded = TRUE;
|
|
|
|
_r_obj_dereference (ptr_app_info);
|
|
|
|
NtClose (hfile);
|
|
}
|
|
|
|
VOID NTAPI _app_queuenotifyinformation (
|
|
_In_ PVOID arglist,
|
|
_In_ ULONG busy_count
|
|
)
|
|
{
|
|
PITEM_CONTEXT context;
|
|
PITEM_APP_INFO ptr_app_info;
|
|
PITEM_LOG ptr_log;
|
|
PR_STRING address_str;
|
|
PR_STRING host_str = NULL;
|
|
PR_STRING signature_str = NULL;
|
|
PR_STRING localized_string;
|
|
HANDLE hfile;
|
|
HICON hicon;
|
|
HDWP hdefer;
|
|
BOOLEAN is_iconset = FALSE;
|
|
NTSTATUS status;
|
|
|
|
context = arglist;
|
|
|
|
ptr_log = context->base_address;
|
|
|
|
// query address string
|
|
address_str = _app_formataddress (ptr_log->af, ptr_log->protocol, &ptr_log->remote_addr, 0, FMTADDR_USE_PROTOCOL);
|
|
|
|
// query notification host name
|
|
if (_r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE))
|
|
{
|
|
host_str = _app_resolveaddress_interlocked (&ptr_log->remote_host_str, ptr_log->af, &ptr_log->remote_addr, TRUE);
|
|
|
|
if (host_str)
|
|
host_str = _r_obj_reference (host_str);
|
|
}
|
|
|
|
// query signature
|
|
ptr_app_info = _app_getappinfobyhash2 (ptr_log->app_hash);
|
|
|
|
if (ptr_app_info)
|
|
{
|
|
if (_app_isappvalidbinary (ptr_app_info->type, ptr_app_info->path))
|
|
{
|
|
status = _r_fs_createfile (
|
|
ptr_app_info->path->buffer,
|
|
FILE_OPEN,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0,
|
|
FALSE,
|
|
NULL,
|
|
&hfile
|
|
);
|
|
|
|
if (NT_SUCCESS (status))
|
|
{
|
|
if (!ptr_app_info->is_loaded)
|
|
_app_getfilesignatureinfo (hfile, ptr_app_info);
|
|
|
|
NtClose (hfile);
|
|
}
|
|
}
|
|
|
|
_r_obj_dereference (ptr_app_info);
|
|
}
|
|
|
|
// query file icon
|
|
hicon = _app_icons_getsafeapp_hicon (ptr_log->app_hash);
|
|
|
|
if (_r_wnd_isvisible (context->hwnd))
|
|
{
|
|
if (ptr_log->app_hash == _app_notify_getapp_id (context->hwnd))
|
|
{
|
|
// set file icon
|
|
_app_notify_setapp_icon (context->hwnd, hicon, TRUE);
|
|
is_iconset = TRUE;
|
|
|
|
// set signature information
|
|
localized_string = _r_obj_concatstrings (
|
|
2,
|
|
_r_locale_getstring (IDS_SIGNATURE),
|
|
L":"
|
|
);
|
|
|
|
if (!_app_getappinfoparam2 (ptr_log->app_hash, 0, INFO_SIGNATURE_STRING, &signature_str, sizeof (signature_str)))
|
|
_r_obj_movereference (&signature_str, _r_locale_getstring_ex (IDS_SIGN_UNSIGNED));
|
|
|
|
hdefer = BeginDeferWindowPos (2);
|
|
|
|
// set signature string
|
|
_r_ctrl_settablestring (context->hwnd, &hdefer, IDC_SIGNATURE_ID, &localized_string->sr, IDC_SIGNATURE_TEXT, &signature_str->sr);
|
|
|
|
// set address string
|
|
_r_obj_movereference (&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_ADDRESS), L":"));
|
|
|
|
if (_r_obj_isstringempty (address_str))
|
|
_r_obj_movereference (&address_str, _r_obj_createstring (SZ_EMPTY));
|
|
|
|
_r_ctrl_settablestring (context->hwnd, &hdefer, IDC_ADDRESS_ID, &localized_string->sr, IDC_ADDRESS_TEXT, &address_str->sr);
|
|
|
|
// set host string
|
|
_r_obj_movereference (&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_HOST), L":"));
|
|
|
|
if (_r_obj_isstringempty (host_str))
|
|
_r_obj_movereference (&host_str, _r_obj_createstring (SZ_EMPTY));
|
|
|
|
_r_ctrl_settablestring (context->hwnd, &hdefer, IDC_HOST_ID, &localized_string->sr, IDC_HOST_TEXT, &host_str->sr);
|
|
|
|
_r_obj_dereference (localized_string);
|
|
|
|
if (hdefer)
|
|
EndDeferWindowPos (hdefer);
|
|
}
|
|
}
|
|
|
|
_r_freelist_deleteitem (&context_free_list, context);
|
|
|
|
if (!is_iconset && hicon)
|
|
DestroyIcon (hicon);
|
|
|
|
if (signature_str)
|
|
_r_obj_dereference (signature_str);
|
|
|
|
if (address_str)
|
|
_r_obj_dereference (address_str);
|
|
|
|
if (host_str)
|
|
_r_obj_dereference (host_str);
|
|
|
|
_r_obj_dereference (ptr_log);
|
|
}
|
|
|
|
VOID NTAPI _app_queueresolveinformation (
|
|
_In_ PVOID arglist,
|
|
_In_ ULONG busy_count
|
|
)
|
|
{
|
|
PITEM_CONTEXT context;
|
|
PITEM_NETWORK ptr_network;
|
|
PITEM_LOG ptr_log;
|
|
BOOLEAN is_resolutionenabled;
|
|
|
|
context = arglist;
|
|
|
|
is_resolutionenabled = _r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE);
|
|
|
|
switch (context->listview_id)
|
|
{
|
|
case IDC_LOG:
|
|
{
|
|
ptr_log = context->base_address;
|
|
|
|
_app_resolveaddress_interlocked (&ptr_log->local_host_str, ptr_log->af, &ptr_log->local_addr, is_resolutionenabled);
|
|
_app_resolveaddress_interlocked (&ptr_log->remote_host_str, ptr_log->af, &ptr_log->remote_addr, is_resolutionenabled);
|
|
|
|
break;
|
|
}
|
|
|
|
case IDC_NETWORK:
|
|
{
|
|
ptr_network = context->base_address;
|
|
|
|
_app_formataddress_interlocked (&ptr_network->local_addr_str, ptr_network->af, &ptr_network->local_addr);
|
|
_app_formataddress_interlocked (&ptr_network->remote_addr_str, ptr_network->af, &ptr_network->remote_addr);
|
|
|
|
_app_resolveaddress_interlocked (&ptr_network->local_host_str, ptr_network->af, &ptr_network->local_addr, is_resolutionenabled);
|
|
_app_resolveaddress_interlocked (&ptr_network->remote_host_str, ptr_network->af, &ptr_network->remote_addr, is_resolutionenabled);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// redraw listview
|
|
if (!(busy_count % 4)) // lol, hack!!!
|
|
{
|
|
if (_r_wnd_isvisible (context->hwnd))
|
|
{
|
|
if (_app_listview_getcurrent (context->hwnd) == context->listview_id)
|
|
_r_listview_redraw (context->hwnd, context->listview_id, -1);
|
|
}
|
|
}
|
|
|
|
_r_obj_dereference (context->base_address);
|
|
|
|
_r_freelist_deleteitem (&context_free_list, context);
|
|
}
|
|
|
|
_Ret_maybenull_
|
|
HBITMAP _app_bitmapfrompng (
|
|
_In_ PVOID hinst,
|
|
_In_ LPCWSTR name,
|
|
_In_ LONG width
|
|
)
|
|
{
|
|
R_STORAGE buffer;
|
|
HBITMAP result;
|
|
NTSTATUS status;
|
|
|
|
status = _r_res_loadresource (hinst, L"PNG", name, &buffer);
|
|
|
|
if (!NT_SUCCESS (status))
|
|
return NULL;
|
|
|
|
status = _r_dc_imagetobitmap (&GUID_ContainerFormatPng, buffer.buffer, (ULONG)buffer.length, width, width, &result);
|
|
|
|
if (SUCCEEDED (status))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
VOID _app_wufixhelper (
|
|
_In_ SC_HANDLE hsvcmgr,
|
|
_In_ LPCWSTR service_name,
|
|
_In_ LPCWSTR k_value,
|
|
_In_ BOOLEAN is_enable
|
|
)
|
|
{
|
|
SERVICE_STATUS svc_status;
|
|
WCHAR reg_key[128];
|
|
WCHAR reg_value[128];
|
|
SC_HANDLE hsvc;
|
|
PR_STRING image_path;
|
|
HANDLE hkey;
|
|
NTSTATUS status;
|
|
BOOLEAN is_enabled;
|
|
|
|
_r_str_printf (
|
|
reg_key,
|
|
RTL_NUMBER_OF (reg_key),
|
|
L"SYSTEM\\CurrentControlSet\\Services\\%s",
|
|
service_name
|
|
);
|
|
|
|
status = _r_reg_openkey (HKEY_LOCAL_MACHINE, reg_key, KEY_READ | KEY_WRITE, &hkey);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
return;
|
|
|
|
// query service path
|
|
is_enabled = FALSE;
|
|
|
|
status = _r_reg_querystring (hkey, L"ImagePath", &image_path);
|
|
|
|
if (NT_SUCCESS (status))
|
|
{
|
|
if (_r_str_isstartswith2 (&image_path->sr, is_enable ? L"%systemroot%\\system32\\wusvc.exe" : L"%systemroot%\\system32\\svchost.exe", TRUE))
|
|
is_enabled = TRUE;
|
|
|
|
_r_obj_dereference (image_path);
|
|
}
|
|
|
|
// set new image path
|
|
_r_str_printf (reg_value, RTL_NUMBER_OF (reg_value), L"%%systemroot%%\\system32\\%s -k %s -p", is_enable ? L"wusvc.exe" : L"svchost.exe", k_value);
|
|
|
|
status = _r_reg_setvalue (
|
|
hkey,
|
|
L"ImagePath",
|
|
REG_EXPAND_SZ,
|
|
reg_value,
|
|
(ULONG)(_r_str_getlength (reg_value) * sizeof (WCHAR) + sizeof (UNICODE_NULL))
|
|
);
|
|
|
|
// restart service
|
|
if (is_enable != is_enabled)
|
|
{
|
|
hsvc = OpenService (hsvcmgr, service_name, SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS);
|
|
|
|
if (hsvc)
|
|
{
|
|
if (QueryServiceStatus (hsvc, &svc_status))
|
|
{
|
|
if (svc_status.dwCurrentState != SERVICE_STOPPED)
|
|
ControlService (hsvc, SERVICE_CONTROL_STOP, &svc_status);
|
|
}
|
|
|
|
CloseServiceHandle (hsvc);
|
|
}
|
|
}
|
|
|
|
NtClose (hkey);
|
|
}
|
|
|
|
VOID _app_wufixenable (
|
|
_In_ HWND hwnd,
|
|
_In_ BOOLEAN is_enable
|
|
)
|
|
{
|
|
SC_HANDLE hsvcmgr;
|
|
PR_STRING service_path;
|
|
WCHAR buffer1[MAX_PATH];
|
|
WCHAR buffer2[MAX_PATH];
|
|
ULONG_PTR app_hash;
|
|
|
|
_r_str_printf (buffer1, RTL_NUMBER_OF (buffer1), L"%s\\svchost.exe", _r_sys_getsystemdirectory ()->buffer);
|
|
_r_str_printf (buffer2, RTL_NUMBER_OF (buffer2), L"%s\\wusvc.exe", _r_sys_getsystemdirectory ()->buffer);
|
|
|
|
hsvcmgr = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT | SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS);
|
|
|
|
if (!hsvcmgr)
|
|
return;
|
|
|
|
_app_wufixhelper (hsvcmgr, L"wuauserv", L"netsvcs", is_enable);
|
|
_app_wufixhelper (hsvcmgr, L"DoSvc", L"NetworkService", is_enable);
|
|
_app_wufixhelper (hsvcmgr, L"UsoSvc", L"netsvcs", is_enable);
|
|
|
|
if (is_enable)
|
|
{
|
|
if (_r_fs_exists (buffer2))
|
|
_r_fs_deletefile (buffer2);
|
|
|
|
_r_fs_copyfile (buffer1, buffer2);
|
|
|
|
service_path = _r_obj_createstring (buffer2);
|
|
|
|
app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, service_path, NULL, NULL);
|
|
|
|
if (app_hash)
|
|
{
|
|
_app_setappinfobyhash (app_hash, INFO_IS_ENABLED, IntToPtr (TRUE));
|
|
_app_setappinfobyhash (app_hash, INFO_IS_UNDELETABLE, IntToPtr (TRUE));
|
|
}
|
|
|
|
_r_obj_dereference (service_path);
|
|
}
|
|
else
|
|
{
|
|
if (_r_fs_exists (buffer2))
|
|
{
|
|
app_hash = _r_str_gethash (buffer2, TRUE);
|
|
|
|
if (app_hash)
|
|
{
|
|
_app_setappinfobyhash (app_hash, INFO_IS_ENABLED, IntToPtr (FALSE));
|
|
_app_setappinfobyhash (app_hash, INFO_IS_UNDELETABLE, IntToPtr (FALSE));
|
|
}
|
|
|
|
_r_fs_deletefile (buffer2);
|
|
}
|
|
}
|
|
|
|
_r_config_setboolean (L"IsWUFixEnabled", is_enable);
|
|
|
|
CloseServiceHandle (hsvcmgr);
|
|
}
|