// simplewall // Copyright (c) 2016-2020 Henry++ #include "global.hpp" VOID NTAPI _app_dereferenceapp (PVOID pdata) { PITEM_APP ptr_item = (PITEM_APP)pdata; SAFE_DELETE_REFERENCE (ptr_item->display_name); SAFE_DELETE_REFERENCE (ptr_item->real_path); SAFE_DELETE_REFERENCE (ptr_item->original_path); SAFE_DELETE_REFERENCE (ptr_item->pnotification); delete ptr_item->guids; } VOID NTAPI _app_dereferenceappshelper (PVOID pdata) { PITEM_APP_HELPER ptr_item = (PITEM_APP_HELPER)pdata; SAFE_DELETE_REFERENCE (ptr_item->display_name); SAFE_DELETE_REFERENCE (ptr_item->real_path); SAFE_DELETE_REFERENCE (ptr_item->internal_name); SAFE_DELETE_REFERENCE (ptr_item->pbytes); } VOID NTAPI _app_dereferencelog (PVOID pdata) { PITEM_LOG ptr_item = (PITEM_LOG)pdata; SAFE_DELETE_REFERENCE (ptr_item->path); SAFE_DELETE_REFERENCE (ptr_item->provider_name); SAFE_DELETE_REFERENCE (ptr_item->filter_name); SAFE_DELETE_REFERENCE (ptr_item->username); SAFE_DELETE_ICON (ptr_item->hicon); } VOID NTAPI _app_dereferencenetwork (PVOID pdata) { PITEM_NETWORK ptr_item = (PITEM_NETWORK)pdata; SAFE_DELETE_REFERENCE (ptr_item->path); } VOID NTAPI _app_dereferencerule (PVOID pdata) { PITEM_RULE ptr_item = (PITEM_RULE)pdata; SAFE_DELETE_REFERENCE (ptr_item->name); SAFE_DELETE_REFERENCE (ptr_item->rule_remote); SAFE_DELETE_REFERENCE (ptr_item->rule_local); delete ptr_item->apps; delete ptr_item->guids; } VOID NTAPI _app_dereferenceruleconfig (PVOID pdata) { PITEM_RULE_CONFIG ptr_item = (PITEM_RULE_CONFIG)pdata; SAFE_DELETE_REFERENCE (ptr_item->name); SAFE_DELETE_REFERENCE (ptr_item->apps); } PR_STRING _app_resolveaddress (ADDRESS_FAMILY af, LPCVOID paddr) { PR_STRING arpaString = _app_formataddress (af, 0, paddr, 0, FMTADDR_AS_ARPA); PR_STRING domainString = NULL; if (arpaString) { SIZE_T arpa_hash = _r_str_hash (arpaString); BOOLEAN is_exists = cache_arpa.find (arpa_hash) != cache_arpa.end (); if (is_exists) { PR_STRING pdata = cache_arpa[arpa_hash]; if (pdata) domainString = _r_obj_reference (pdata); } else { cache_arpa[arpa_hash] = NULL; PDNS_RECORD ppQueryResultsSet = NULL; DNS_STATUS dnsStatus = DnsQuery (_r_obj_getstring (arpaString), DNS_TYPE_PTR, DNS_QUERY_NO_HOSTS_FILE, NULL, &ppQueryResultsSet, NULL); if (dnsStatus == DNS_ERROR_RCODE_NO_ERROR) { if (ppQueryResultsSet) { if (!_r_str_isempty (ppQueryResultsSet->Data.PTR.pNameHost)) { domainString = _r_obj_createstring (ppQueryResultsSet->Data.PTR.pNameHost); PR_STRING arpaCacheString = _r_obj_createstring2 (domainString); _app_freestrings_map (&cache_arpa, MAP_CACHE_MAX); cache_arpa[arpa_hash] = arpaCacheString; } DnsRecordListFree (ppQueryResultsSet, DnsFreeRecordList); } } } } SAFE_DELETE_REFERENCE (arpaString); return domainString; } PR_STRING _app_formataddress (ADDRESS_FAMILY af, UINT8 proto, LPCVOID paddr, UINT16 port, DWORD flags) { BOOLEAN is_success = FALSE; WCHAR formatted_address[DNS_MAX_NAME_BUFFER_LENGTH] = {0}; PIN_ADDR p4addr = (PIN_ADDR)paddr; PIN6_ADDR p6addr = (PIN6_ADDR)paddr; if ((flags & FMTADDR_AS_ARPA) != 0) { if (af == AF_INET) { _r_str_appendformat (formatted_address, RTL_NUMBER_OF (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); } else if (af == AF_INET6) { for (INT i = sizeof (IN6_ADDR) - 1; i >= 0; i--) _r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L"%hhx.%hhx.", p6addr->s6_addr[i] & 0xF, (p6addr->s6_addr[i] >> 4) & 0xF); _r_str_append (formatted_address, RTL_NUMBER_OF (formatted_address), DNS_IP6_REVERSE_DOMAIN_STRING_W); } is_success = TRUE; } else { if ((flags & FMTADDR_USE_PROTOCOL) != 0) { _r_str_printf (formatted_address, RTL_NUMBER_OF (formatted_address), L"%s://", _app_getprotoname (proto, AF_UNSPEC, SZ_UNKNOWN)); } WCHAR addr_str[DNS_MAX_NAME_BUFFER_LENGTH] = {0}; if (_app_formatip (af, paddr, addr_str, RTL_NUMBER_OF (addr_str), (flags & FMTADDR_AS_RULE) != 0)) { if (af == AF_INET6 && port) { _r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L"[%s]", addr_str); } else { _r_str_append (formatted_address, RTL_NUMBER_OF (formatted_address), addr_str); } is_success = TRUE; } if (port && (flags & FMTADDR_USE_PROTOCOL) == 0) { _r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), !_r_str_isempty (formatted_address) ? L":%" TEXT (PRIu16) : L"%" TEXT (PRIu16), port); is_success = TRUE; } } if ((flags & FMTADDR_RESOLVE_HOST) != 0) { if (is_success && _r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE)) { SIZE_T addr_hash = _r_str_hash (formatted_address); BOOLEAN is_exists = cache_hosts.find (addr_hash) != cache_hosts.end (); if (is_exists) { PR_STRING pdata = cache_hosts[addr_hash]; if (pdata) { PR_STRING addressString = _r_obj_reference (pdata); _r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L" (%s)", _r_obj_getstring (addressString)); _r_obj_dereference (addressString); } } else { cache_hosts[addr_hash] = NULL; PR_STRING domainString = _app_resolveaddress (af, paddr); if (domainString) { _app_freestrings_map (&cache_hosts, MAP_CACHE_MAX); _r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L" (%s)", _r_obj_getstring (domainString)); _r_obj_movereference (&cache_hosts[addr_hash], domainString); } } } } if (is_success) return _r_obj_createstring (formatted_address); return NULL; } BOOLEAN _app_formatip (ADDRESS_FAMILY af, LPCVOID paddr, LPWSTR out_buffer, ULONG buffer_size, BOOLEAN is_checkempty) { PIN_ADDR p4addr; PIN6_ADDR p6addr; if (af == AF_INET) { p4addr = (PIN_ADDR)paddr; if (is_checkempty) { if (IN4_IS_ADDR_UNSPECIFIED (p4addr)) return FALSE; } if (NT_SUCCESS (RtlIpv4AddressToStringEx (p4addr, 0, out_buffer, &buffer_size))) return TRUE; } else if (af == AF_INET6) { p6addr = (PIN6_ADDR)paddr; if (is_checkempty) { if (IN6_IS_ADDR_UNSPECIFIED (p6addr)) return FALSE; } if (NT_SUCCESS (RtlIpv6AddressToStringEx (p6addr, 0, 0, out_buffer, &buffer_size))) return TRUE; } return FALSE; } PR_STRING _app_formatport (UINT16 port, BOOLEAN is_noempty) { PR_STRING string; if (!port) return NULL; if (is_noempty) { string = _r_format_string (L"%" TEXT (PRIu16), port); LPCWSTR seviceString = _app_getservicename (port, NULL); if (seviceString) _r_string_appendformat (&string, L" (%s)", seviceString); } else { string = _r_format_string (L"%" TEXT (PRIu16) L" (%s)", port, _app_getservicename (port, SZ_UNKNOWN)); } return string; } VOID _app_freestrings_map (OBJECTS_STRINGS_MAP* ptr_map, SIZE_T max_size) { if (max_size && ptr_map->size () <= max_size) return; PVOID pdata; for (auto it = ptr_map->begin (); it != ptr_map->end ();) { pdata = it->second; it = ptr_map->erase (it); if (pdata) _r_obj_dereference (pdata); if (max_size && ptr_map->size () <= max_size) break; } } VOID _app_freeapps_map (OBJECTS_APP_MAP* ptr_map) { PVOID pdata; for (auto it = ptr_map->begin (); it != ptr_map->end ();) { pdata = it->second; it = ptr_map->erase (it); if (pdata) _r_obj_dereference (pdata); } } VOID _app_freeappshelper_map (OBJECTS_APP_HELPER_MAP* ptr_map) { PVOID pdata; for (auto it = ptr_map->begin (); it != ptr_map->end ();) { pdata = it->second; it = ptr_map->erase (it); if (pdata) _r_obj_dereference (pdata); } } VOID _app_freerulesconfig_map (OBJECTS_RULE_CONFIG_MAP* ptr_map) { PVOID pdata; for (auto it = ptr_map->begin (); it != ptr_map->end ();) { pdata = it->second; it = ptr_map->erase (it); if (pdata) _r_obj_dereference (pdata); } } VOID _app_freeapps_vec (OBJECTS_APP_VECTOR* ptr_vec) { PVOID pdata; for (auto it = ptr_vec->begin (); it != ptr_vec->end ();) { pdata = *it; it = ptr_vec->erase (it); if (pdata) _r_obj_dereference (pdata); } } VOID _app_freerules_vec (OBJECTS_RULE_VECTOR* ptr_vec) { PVOID pdata; for (auto it = ptr_vec->begin (); it != ptr_vec->end ();) { pdata = *it; it = ptr_vec->erase (it); if (pdata) _r_obj_dereference (pdata); } } VOID _app_freelogobjects_vec (OBJECTS_LOG_VECTOR* ptr_vec) { PVOID pdata; for (auto it = ptr_vec->begin (); it != ptr_vec->end ();) { pdata = *it; it = ptr_vec->erase (it); if (pdata) _r_obj_dereference (pdata); } } VOID _app_freethreadpool (THREADS_VEC* ptr_vec) { HANDLE hthread; for (auto it = ptr_vec->begin (); it != ptr_vec->end ();) { hthread = *it; if (_r_fs_isvalidhandle (hthread)) { if (WaitForSingleObjectEx (hthread, 0, FALSE) != WAIT_OBJECT_0) { ++it; continue; } CloseHandle (hthread); } it = ptr_vec->erase (it); } } VOID _app_freelogstack () { PSLIST_ENTRY listEntry; PITEM_LOG_LISTENTRY ptr_entry; while (TRUE) { listEntry = RtlInterlockedPopEntrySList (&log_stack.ListHead); if (!listEntry) break; InterlockedDecrement (&log_stack.item_count); ptr_entry = CONTAINING_RECORD (listEntry, ITEM_LOG_LISTENTRY, ListEntry); if (ptr_entry->Body) _r_obj_dereference (ptr_entry->Body); _aligned_free (ptr_entry); } } VOID _app_getappicon (const PITEM_APP ptr_app, BOOLEAN is_small, PINT picon_id, HICON* picon) { BOOLEAN is_iconshidden = _r_config_getboolean (L"IsIconsHidden", FALSE); if (ptr_app->type == DataAppRegular || ptr_app->type == DataAppService) { if (is_iconshidden || !_app_getfileicon (_r_obj_getstring (ptr_app->real_path), is_small, picon_id, picon)) { if (picon_id) *picon_id = (ptr_app->type == DataAppService) ? config.icon_service_id : config.icon_id; if (picon) *picon = CopyIcon (is_small ? config.hicon_small : config.hicon_large); } if (ptr_app->type == DataAppService) { if (picon_id && *picon_id == config.icon_id) *picon_id = config.icon_service_id; } } else if (ptr_app->type == DataAppUWP) { if (picon_id) *picon_id = config.icon_uwp_id; if (picon) *picon = CopyIcon (is_small ? config.hicon_uwp : config.hicon_large); // small-only! } else { if (picon_id) *picon_id = config.icon_id; if (picon) *picon = CopyIcon (is_small ? config.hicon_small : config.hicon_large); } } PR_STRING _app_getdisplayname (SIZE_T app_hash, PITEM_APP ptr_app, BOOLEAN is_shortened) { PR_STRING string = NULL; if (ptr_app->type == DataAppService) { if (ptr_app->original_path) return _r_obj_createstring2 (ptr_app->original_path); } else if (ptr_app->type == DataAppUWP) { if (_app_item_get (ptr_app->type, app_hash, &string, NULL, NULL, NULL)) { if (string) return string; } } string = ((app_hash == config.ntoskrnl_hash) ? ptr_app->original_path : ptr_app->real_path); if (string) { if (is_shortened || _r_config_getboolean (L"ShowFilenames", TRUE)) return _r_obj_createstring (_r_path_getbasename (_r_obj_getstring (string))); return _r_obj_createstring2 (string); } return NULL; } BOOLEAN _app_getfileicon (LPCWSTR path, BOOLEAN is_small, PINT picon_id, HICON* picon) { if (_r_str_isempty (path)) return FALSE; BOOLEAN result = FALSE; SHFILEINFO shfi = {0}; DWORD flags = 0; if (picon_id) flags |= SHGFI_SYSICONINDEX; if (picon) flags |= SHGFI_ICON; if (is_small) flags |= SHGFI_SMALLICON; if (SHGetFileInfo (path, 0, &shfi, sizeof (shfi), flags)) { if (picon_id) *picon_id = shfi.iIcon; if (picon && shfi.hIcon) *picon = shfi.hIcon; result = TRUE; } if (!result) { if (picon_id) *picon_id = config.icon_id; if (picon) *picon = CopyIcon (is_small ? config.hicon_small : config.hicon_large); result = TRUE; } return result; } PR_STRING _app_getsignatureinfo (SIZE_T app_hash, const PITEM_APP ptr_app) { if (_r_str_isempty (ptr_app->real_path) || (ptr_app->type != DataAppRegular && ptr_app->type != DataAppService && ptr_app->type != DataAppUWP)) return NULL; HANDLE hfile = NULL; PR_STRING signatureCacheString = NULL; if (cache_signatures.find (app_hash) != cache_signatures.end ()) { signatureCacheString = cache_signatures.at (app_hash); goto CleanupExit; } else { cache_signatures.emplace (app_hash, (PR_STRING)NULL); hfile = CreateFile (ptr_app->real_path->Buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (_r_fs_isvalidhandle (hfile)) { GUID WinTrustActionGenericVerifyV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; WINTRUST_FILE_INFO fileInfo = {0}; fileInfo.cbStruct = sizeof (fileInfo); fileInfo.pcwszFilePath = ptr_app->real_path->Buffer; fileInfo.hFile = hfile; WINTRUST_DATA trustData = {0}; trustData.cbStruct = sizeof (trustData); trustData.dwUIChoice = WTD_UI_NONE; trustData.fdwRevocationChecks = WTD_REVOKE_NONE; trustData.dwProvFlags = WTD_SAFER_FLAG | WTD_CACHE_ONLY_URL_RETRIEVAL; trustData.dwUnionChoice = WTD_CHOICE_FILE; trustData.pFile = &fileInfo; trustData.dwStateAction = WTD_STATEACTION_VERIFY; if (WinVerifyTrust ((HWND)INVALID_HANDLE_VALUE, &WinTrustActionGenericVerifyV2, &trustData) == ERROR_SUCCESS) { PCRYPT_PROVIDER_DATA provData = WTHelperProvDataFromStateData (trustData.hWVTStateData); if (provData) { PCRYPT_PROVIDER_SGNR psProvSigner = WTHelperGetProvSignerFromChain (provData, 0, FALSE, 0); if (psProvSigner) { CRYPT_PROVIDER_CERT* psProvCert = WTHelperGetProvCertFromChain (psProvSigner, 0); if (psProvCert) { ULONG num_chars = CertGetNameString (psProvCert->pCert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0) - 1; if (num_chars) { signatureCacheString = _r_obj_createstringex (NULL, num_chars * sizeof (WCHAR)); if (CertGetNameString (psProvCert->pCert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, signatureCacheString->Buffer, num_chars + 1)) { _app_freestrings_map (&cache_signatures, MAP_CACHE_MAX); cache_signatures.insert_or_assign (app_hash, signatureCacheString); } else { _r_obj_clearreference (&signatureCacheString); } } } } } } trustData.dwStateAction = WTD_STATEACTION_CLOSE; WinVerifyTrust ((HWND)INVALID_HANDLE_VALUE, &WinTrustActionGenericVerifyV2, &trustData); } } CleanupExit: if (_r_fs_isvalidhandle (hfile)) CloseHandle (hfile); ptr_app->is_signed = !_r_str_isempty (signatureCacheString); if (signatureCacheString) return _r_obj_reference (signatureCacheString); return NULL; } PR_STRING _app_getversioninfo (SIZE_T app_hash, const PITEM_APP ptr_app) { if (_r_str_isempty (ptr_app->real_path)) return NULL; HINSTANCE hlib = NULL; HRSRC hres = NULL; HGLOBAL hglob = NULL; PR_STRING versionCacheString = NULL; if (cache_versions.find (app_hash) != cache_versions.end ()) { versionCacheString = cache_versions.at (app_hash); goto CleanupExit; } cache_versions.emplace (app_hash, (PR_STRING)NULL); hlib = LoadLibraryEx (ptr_app->real_path->Buffer, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE); if (!hlib) goto CleanupExit; hres = FindResource (hlib, MAKEINTRESOURCE (VS_VERSION_INFO), RT_VERSION); if (!hres) goto CleanupExit; hglob = LoadResource (hlib, hres); if (!hglob) goto CleanupExit; PVOID versionInfo = LockResource (hglob); if (versionInfo) { versionCacheString = _r_obj_createstringbuilder (); PVOID buffer; ULONG langId; UINT length; WCHAR authorEntry[128]; WCHAR descriptionEntry[128]; if (VerQueryValue (versionInfo, L"\\VarFileInfo\\Translation", &buffer, &length) && length == 4) { RtlCopyMemory (&langId, buffer, length); _r_str_printf (authorEntry, RTL_NUMBER_OF (authorEntry), L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName", (langId & 0xff00) >> 8, langId & 0xff, (langId & 0xff000000) >> 24, (langId & 0xff0000) >> 16); _r_str_printf (descriptionEntry, RTL_NUMBER_OF (descriptionEntry), L"\\StringFileInfo\\%02X%02X%02X%02X\\FileDescription", (langId & 0xff00) >> 8, langId & 0xff, (langId & 0xff000000) >> 24, (langId & 0xff0000) >> 16); } else { _r_str_printf (authorEntry, RTL_NUMBER_OF (authorEntry), L"\\StringFileInfo\\%04X04B0\\CompanyName", GetUserDefaultLangID ()); _r_str_printf (descriptionEntry, RTL_NUMBER_OF (descriptionEntry), L"\\StringFileInfo\\%04X04B0\\FileDescription", GetUserDefaultLangID ()); } if (VerQueryValue (versionInfo, descriptionEntry, &buffer, &length)) { _r_string_appendformat (&versionCacheString, SZ_TAB L"%s", buffer); VS_FIXEDFILEINFO* verInfo; if (VerQueryValue (versionInfo, L"\\", (PVOID*)&verInfo, &length)) { _r_string_appendformat (&versionCacheString, L" %d.%d", HIWORD (verInfo->dwFileVersionMS), LOWORD (verInfo->dwFileVersionMS)); if (HIWORD (verInfo->dwFileVersionLS) || LOWORD (verInfo->dwFileVersionLS)) { _r_string_appendformat (&versionCacheString, L".%d", HIWORD (verInfo->dwFileVersionLS)); if (LOWORD (verInfo->dwFileVersionLS)) _r_string_appendformat (&versionCacheString, L".%d", LOWORD (verInfo->dwFileVersionLS)); } } _r_string_append (&versionCacheString, L"\r\n"); } if (VerQueryValue (versionInfo, authorEntry, &buffer, &length)) { _r_string_appendformat (&versionCacheString, SZ_TAB L"%s\r\n", buffer); } _r_str_trim (versionCacheString, DIVIDER_TRIM); if (_r_str_isempty (versionCacheString)) { _r_obj_clearreference (&versionCacheString); goto CleanupExit; } _app_freestrings_map (&cache_versions, MAP_CACHE_MAX); cache_versions.insert_or_assign (app_hash, versionCacheString); } CleanupExit: if (hglob) FreeResource (hglob); if (hlib) FreeLibrary (hlib); if (versionCacheString) return _r_obj_reference (versionCacheString); return NULL; } LPCWSTR _app_getservicename (UINT16 port, LPCWSTR default_value) { switch (port) { case 1: return L"tcpmux"; case 7: return L"echo"; case 9: return L"discard"; case 11: return L"systat"; case 13: return L"daytime"; case 20: return L"ftp-data"; case 21: return L"ftp"; case 22: return L"ssh"; case 23: return L"telnet"; case 25: return L"smtp"; case 26: return L"rsftp"; case 37: return L"time"; case 39: return L"rlp"; case 42: return L"nameserver"; case 43: return L"nicname"; case 48: return L"auditd"; case 53: return L"domain"; case 63: return L"whois++"; case 67: case 68: return L"dhcp"; case 69: return L"tftp"; case 78: return L"vettcp"; case 79: case 2003: return L"finger"; case 80: return L"http"; case 81: return L"hosts2-ns"; case 84: return L"ctf"; case 88: return L"kerberos-sec"; case 90: return L"dnsix"; case 92: return L"npp"; case 93: return L"dcp"; case 94: return L"objcall"; case 95: return L"supdup"; case 101: return L"hostname"; case 105: return L"cso"; case 106: return L"pop3pw"; case 107: return L"rtelnet"; case 109: return L"pop2"; case 110: return L"pop3"; case 111: return L"rpcbind"; case 112: return L"mcidas"; case 113: return L"auth"; case 115: return L"sftp"; case 118: return L"sqlserv"; case 119: return L"nntp"; case 123: return L"ntp"; case 126: return L"nxedit"; case 129: return L"pwdgen"; case 135: return L"msrpc"; case 136: return L"profile"; case 137: return L"netbios-ns"; case 138: return L"netbios-dgm"; case 139: return L"netbios-ssn"; case 143: return L"imap"; case 144: return L"news"; case 145: return L"uaac"; case 150: return L"sql-net"; case 152: return L"bftp"; case 156: return L"sqlsrv"; case 159: return L"nss-routing"; case 160: return L"sgmp-traps"; case 161: return L"snmp"; case 162: return L"snmptrap"; case 169: return L"send"; case 174: return L"mailq"; case 175: return L"vmnet"; case 179: return L"bgp"; case 182: return L"audit"; case 185: return L"remote-kis"; case 186: return L"kis"; case 194: case 529: return L"irc"; case 195: return L"dn6-nlm-aud"; case 196: return L"dn6-smm-red"; case 197: return L"dls"; case 199: return L"smux"; case 209: return L"qmtp"; case 245: return L"link"; case 280: return L"http-mgmt"; case 322: return L"rtsps"; case 349: return L"mftp"; case 389: return L"ldap"; case 427: return L"svrloc"; case 443: return L"https"; case 444: return L"snpp"; case 445: return L"microsoft-ds"; case 464: return L"kerberos"; case 465: return L"smtps"; case 500: return L"isakmp"; case 513: return L"login"; case 514: return L"shell"; case 515: return L"printer"; case 524: return L"ncp"; case 530: return L"rpc"; case 543: return L"klogin"; case 544: return L"kshell"; case 546: return L"dhcpv6-client"; case 547: return L"dhcpv6-server"; case 548: return L"afp"; case 554: return L"rtsp"; case 565: return L"whoami"; case 558: return L"sdnskmp"; case 585: return L"imap4-ssl"; case 587: return L"submission"; case 631: return L"ipp"; case 636: return L"ldaps"; case 646: return L"ldp"; case 647: return L"dhcp-failover"; case 666: return L"doom"; // khe-khe-khe! case 847: return L"dhcp-failover2"; case 861: return L"owamp-control"; case 862: return L"twamp-control"; case 873: return L"rsync"; case 853: return L"domain-s"; case 989: return L"ftps-data"; case 990: return L"ftps"; case 992: return L"telnets"; case 993: return L"imaps"; case 994: return L"ircs"; case 995: return L"pop3s"; case 1025: return L"NFS-or-IIS"; case 1027: return L"IIS"; case 1029: return L"ms-lsa"; case 1110: return L"nfsd"; case 1111: return L"lmsocialserver"; case 1112: case 1114: case 4333: return L"mini-sql"; case 1119: return L"bnetgame"; case 1120: return L"bnetfile"; case 1123: return L"murray"; case 1194: return L"openvpn"; case 1337: return L"menandmice-dns"; case 1433: return L"ms-sql-s"; case 1688: return L"nsjtp-data"; case 1701: return L"l2tp"; case 1720: return L"h323q931"; case 1723: return L"pptp"; case 1863: return L"msnp"; case 1900: case 5000: return L"upnp"; case 2000: return L"cisco-sccp"; case 2054: return L"weblogin"; case 2086: return L"gnunet"; case 2001: return L"dc"; case 2121: return L"ccproxy-ftp"; case 2164: return L"ddns-v3"; case 2167: return L"raw-serial"; case 2171: return L"msfw-storage"; case 2172: return L"msfw-s-storage"; case 2173: return L"msfw-replica"; case 2174: return L"msfw-array"; case 2371: return L"worldwire"; case 2717: return L"pn-requester"; case 2869: return L"icslap"; case 3000: return L"ppp"; case 3074: return L"xbox"; case 3128: return L"squid-http"; case 3306: return L"mysql"; case 3389: return L"ms-wbt-server"; case 3407: return L"ldap-admin"; case 3540: return L"pnrp-port"; case 3558: return L"mcp-port"; case 3587: return L"p2pgroup"; case 3702: return L"ws-discovery"; case 3713: return L"tftps"; case 3724: return L"blizwow"; case 4500: return L"ipsec-nat-t"; case 4554: return L"msfrs"; case 4687: return L"nst"; case 4876: return L"tritium-can"; case 4899: return L"radmin"; case 5004: return L"rtp-data"; case 5005: return L"rtp"; case 5009: return L"airport-admin"; case 5051: return L"ida-agent"; case 5060: return L"sip"; case 5101: return L"admdog"; case 5190: return L"aol"; case 5350: return L"nat-pmp-status"; case 5351: return L"nat-pmp"; case 5352: return L"dns-llq"; case 5353: return L"mdns"; case 5354: return L"mdnsresponder"; case 5355: return L"llmnr"; case 5357: return L"wsdapi"; case 5358: return L"wsdapi-s"; case 5362: return L"serverwsd2"; case 5432: return L"postgresql"; case 5631: return L"pcanywheredata"; case 5666: return L"nrpe"; case 5687: return L"gog-multiplayer"; case 5800: return L"vnc-http"; case 5900: return L"vnc"; case 5938: return L"teamviewer"; case 6000: case 6001: case 6002: case 6003: return L"x11"; case 6222: case 6662: // deprecated! return L"radmind"; case 6346: return L"gnutella"; case 6347: return L"gnutella2"; case 6622: return L"mcftp"; case 6665: case 6666: case 6667: case 6668: case 6669: return L"ircu"; case 6881: return L"bittorrent-tracker"; case 7070: return L"realserver"; case 7235: return L"aspcoordination"; case 8443: return L"https-alt"; case 8021: return L"ftp-proxy"; case 8333: case 18333: return L"bitcoin"; case 591: case 8000: case 8008: case 8080: case 8444: return L"http-alt"; case 8999: return L"bctp"; case 9418: return L"git"; case 9800: return L"webdav"; case 10107: return L"bctp-server"; case 11371: return L"hkp"; case 25565: return L"minecraft"; case 26000: return L"quake"; case 27015: return L"halflife"; case 27017: case 27018: case 27019: case 28017: return L"mongod"; case 27500: return L"quakeworld"; case 27910: return L"quake2"; case 27960: return L"quake3"; case 28240: return L"siemensgsm"; case 33434: return L"traceroute"; } return default_value; } LPCWSTR _app_getprotoname (UINT8 proto, ADDRESS_FAMILY af, LPCWSTR default_value) { switch (proto) { case IPPROTO_HOPOPTS: return L"hopopt"; case IPPROTO_ICMP: return L"icmp"; case IPPROTO_IGMP: return L"igmp"; case IPPROTO_GGP: return L"ggp"; case IPPROTO_IPV4: return L"ipv4"; case IPPROTO_ST: return L"st"; case IPPROTO_TCP: return ((af == AF_INET6) ? L"tcp6" : L"tcp"); case IPPROTO_CBT: return L"cbt"; case IPPROTO_EGP: return L"egp"; case IPPROTO_IGP: return L"igp"; case IPPROTO_PUP: return L"pup"; case IPPROTO_UDP: return ((af == AF_INET6) ? L"udp6" : L"udp"); case IPPROTO_IDP: return L"xns-idp"; case IPPROTO_RDP: return L"rdp"; case IPPROTO_IPV6: return L"ipv6"; case IPPROTO_ROUTING: return L"ipv6-route"; case IPPROTO_FRAGMENT: return L"ipv6-frag"; case IPPROTO_ESP: return L"esp"; case IPPROTO_AH: return L"ah"; case IPPROTO_ICMPV6: return L"ipv6-icmp"; case IPPROTO_DSTOPTS: return L"ipv6-opts"; case IPPROTO_L2TP: return L"l2tp"; case IPPROTO_SCTP: return L"sctp"; } return default_value; } LPCWSTR _app_getconnectionstatusname (DWORD state, LPCWSTR default_value) { switch (state) { case MIB_TCP_STATE_CLOSED: return L"Closed"; case MIB_TCP_STATE_LISTEN: return L"Listen"; case MIB_TCP_STATE_SYN_SENT: return L"SYN sent"; case MIB_TCP_STATE_SYN_RCVD: return L"SYN received"; case MIB_TCP_STATE_ESTAB: return L"Established"; case MIB_TCP_STATE_FIN_WAIT1: return L"FIN wait 1"; case MIB_TCP_STATE_FIN_WAIT2: return L"FIN wait 2"; case MIB_TCP_STATE_CLOSE_WAIT: return L"Close wait"; case MIB_TCP_STATE_CLOSING: return L"Closing"; case MIB_TCP_STATE_LAST_ACK: return L"Last ACK"; case MIB_TCP_STATE_TIME_WAIT: return L"Time wait"; case MIB_TCP_STATE_DELETE_TCB: return L"Delete TCB"; } return default_value; } PR_STRING _app_getdirectionname (FWP_DIRECTION direction, BOOLEAN is_loopback, BOOLEAN is_localized) { PR_STRING string; if (is_localized) { if (direction == FWP_DIRECTION_OUTBOUND) { string = _r_obj_createstring (_r_locale_getstring (IDS_DIRECTION_1)); } else if (direction == FWP_DIRECTION_INBOUND) { string = _r_obj_createstring (_r_locale_getstring (IDS_DIRECTION_2)); } else if (direction == FWP_DIRECTION_MAX) { string = _r_obj_createstring (_r_locale_getstring (IDS_ANY)); } else { return NULL; } if (is_loopback) { _r_string_appendformat (&string, L" (%s)", SZ_DIRECTION_LOOPBACK); } } else { if (direction == FWP_DIRECTION_OUTBOUND) { string = _r_obj_createstring (SZ_DIRECTION_OUT); } else if (direction == FWP_DIRECTION_INBOUND) { string = _r_obj_createstring (SZ_DIRECTION_IN); } else if (direction == FWP_DIRECTION_MAX) { string = _r_obj_createstring (SZ_DIRECTION_ANY); } else { return NULL; } if (is_loopback) { _r_string_append (&string, L"-" SZ_DIRECTION_LOOPBACK); } } return string; } COLORREF _app_getcolorvalue (SIZE_T color_hash) { if (!color_hash) return 0; for (auto it = colors.begin (); it != colors.end (); ++it) { PITEM_COLOR ptr_clr = *it; if (ptr_clr->hash == color_hash) return ptr_clr->new_clr ? ptr_clr->new_clr : ptr_clr->default_clr; } return 0; } PR_STRING _app_getservicenamefromtag (HANDLE hprocess, LPCVOID ptag) { PR_STRING serviceNameString = NULL; HMODULE hlib = GetModuleHandle (L"advapi32.dll"); if (hlib) { typedef ULONG (NTAPI* IQTI) (PVOID, SC_SERVICE_TAG_QUERY_TYPE, PSC_SERVICE_TAG_QUERY); // I_QueryTagInformation const IQTI _I_QueryTagInformation = (IQTI)GetProcAddress (hlib, "I_QueryTagInformation"); if (_I_QueryTagInformation) { PSC_SERVICE_TAG_QUERY pnameTag = (PSC_SERVICE_TAG_QUERY)_r_mem_allocatezero (sizeof (SC_SERVICE_TAG_QUERY)); pnameTag->ProcessId = HandleToUlong (hprocess); pnameTag->ServiceTag = PtrToUlong (ptag); _I_QueryTagInformation (NULL, ServiceNameFromTagInformation, pnameTag); if (pnameTag->Buffer) { serviceNameString = _r_obj_createstring ((LPCWSTR)pnameTag->Buffer); LocalFree (pnameTag->Buffer); } _r_mem_free (pnameTag); } } return serviceNameString; } BOOLEAN _app_isimmersiveprocess (HANDLE hprocess) { HMODULE huser32 = GetModuleHandle (L"user32.dll"); if (huser32) { typedef BOOL (WINAPI* IIP) (HANDLE); // IsImmersiveProcess const IIP _IsImmersiveProcess = (IIP)GetProcAddress (huser32, "IsImmersiveProcess"); if (_IsImmersiveProcess) return !!_IsImmersiveProcess (hprocess); } return FALSE; } PR_STRING _app_getnetworkpath (DWORD pid, PULONG64 pmodules, PITEM_NETWORK ptr_network) { if (pid == PROC_WAITING_PID) { ptr_network->app_hash = 0; ptr_network->icon_id = config.icon_id; ptr_network->type = DataAppRegular; return _r_obj_createstring (PROC_WAITING_NAME); } else if (pid == PROC_SYSTEM_PID) { ptr_network->app_hash = config.ntoskrnl_hash; ptr_network->icon_id = config.icon_id; ptr_network->type = DataAppRegular; return _r_obj_createstring (PROC_SYSTEM_NAME); } PR_STRING processName = NULL; if (pmodules) { PR_STRING serviceName = _app_getservicenamefromtag (UlongToHandle (pid), UlongToPtr (*(PULONG)pmodules)); if (serviceName) { _r_obj_movereference (&processName, serviceName); ptr_network->type = DataAppService; } } if (!processName) { HANDLE hprocess = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); if (hprocess) { if (_r_sys_isosversiongreaterorequal (WINDOWS_8) && _app_isimmersiveprocess (hprocess)) { ptr_network->type = DataAppUWP; } else { ptr_network->type = DataAppRegular; } DWORD size = 1024; processName = _r_obj_createstringex (NULL, size * sizeof (WCHAR)); BOOL is_success = QueryFullProcessImageName (hprocess, 0, processName->Buffer, &size); // fix for WSL processes (issue #606) if (!is_success) { if (GetLastError () == ERROR_GEN_FAILURE) { size = 1024; QueryFullProcessImageName (hprocess, PROCESS_NAME_NATIVE, processName->Buffer, &size); is_success = TRUE; } } if (!is_success) { SAFE_DELETE_REFERENCE (processName); } else { _r_string_trimtonullterminator (processName); } CloseHandle (hprocess); } } if (processName) { SIZE_T app_hash = _r_str_hash (processName); ptr_network->app_hash = app_hash; ptr_network->icon_id = (INT)_app_getappinfo (app_hash, InfoIconId); if (!ptr_network->icon_id) _app_getfileicon (_r_obj_getstring (processName), TRUE, &ptr_network->icon_id, NULL); } else { ptr_network->app_hash = 0; ptr_network->icon_id = config.icon_id; } return processName; } SIZE_T _app_getnetworkhash (ADDRESS_FAMILY af, DWORD pid, LPCVOID remote_addr, DWORD remote_port, LPCVOID local_addr, DWORD local_port, UINT8 proto, DWORD state) { PR_STRING networkString; WCHAR remoteAddress[LEN_IP_MAX]; WCHAR localAddress[LEN_IP_MAX]; SIZE_T networkHash; if (remote_addr) _app_formatip (af, remote_addr, remoteAddress, RTL_NUMBER_OF (remoteAddress), FALSE); else *remoteAddress = UNICODE_NULL; if (local_addr) _app_formatip (af, local_addr, localAddress, RTL_NUMBER_OF (localAddress), FALSE); else *localAddress = UNICODE_NULL; networkString = _r_format_string (L"%" TEXT (PRIu8) L"_%" TEXT (PR_ULONG) L"_%s_%" TEXT (PR_ULONG) L"_%s_%" TEXT (PR_ULONG) L"_%" TEXT (PRIu8) L"_%" TEXT (PR_ULONG), af, pid, remoteAddress, remote_port, localAddress, local_port, proto, state ); networkHash = _r_str_hash (networkString); _r_obj_dereference (networkString); return networkHash; } BOOLEAN _app_isvalidconnection (ADDRESS_FAMILY af, LPCVOID paddr) { if (af == AF_INET) { PIN_ADDR p4addr = (PIN_ADDR)paddr; return (!IN4_IS_ADDR_UNSPECIFIED (p4addr) && !IN4_IS_ADDR_LOOPBACK (p4addr) && !IN4_IS_ADDR_LINKLOCAL (p4addr) && !IN4_IS_ADDR_MULTICAST (p4addr) && !IN4_IS_ADDR_MC_ADMINLOCAL (p4addr) && !IN4_IS_ADDR_RFC1918 (p4addr) ); } else if (af == AF_INET6) { PIN6_ADDR p6addr = (PIN6_ADDR)paddr; return (!IN6_IS_ADDR_UNSPECIFIED (p6addr) && !IN6_IS_ADDR_LOOPBACK (p6addr) && !IN6_IS_ADDR_LINKLOCAL (p6addr) && !IN6_IS_ADDR_MULTICAST (p6addr) && !IN6_IS_ADDR_SITELOCAL (p6addr) && !IN6_IS_ADDR_ANYCAST (p6addr) ); } return FALSE; } VOID _app_generate_connections (OBJECTS_NETWORK_MAP* ptr_map, HASHER_MAP* checker_map) { checker_map->clear (); PITEM_NETWORK ptr_network; SIZE_T network_hash; DWORD allocationSize = 0x4000; PVOID memoryAddress = _r_mem_allocatezero (allocationSize); DWORD requiredSize = 0; GetExtendedTcpTable (NULL, &requiredSize, FALSE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0); if (requiredSize) { if (allocationSize < requiredSize) { memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize); allocationSize = requiredSize; } PMIB_TCPTABLE_OWNER_MODULE tcp4Table = (PMIB_TCPTABLE_OWNER_MODULE)memoryAddress; if (GetExtendedTcpTable (tcp4Table, &requiredSize, FALSE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0) == NO_ERROR) { for (DWORD i = 0; i < tcp4Table->dwNumEntries; i++) { IN_ADDR remote_addr = {0}; IN_ADDR local_addr = {0}; remote_addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr; local_addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr; network_hash = _app_getnetworkhash (AF_INET, tcp4Table->table[i].dwOwningPid, &remote_addr, tcp4Table->table[i].dwRemotePort, &local_addr, tcp4Table->table[i].dwLocalPort, IPPROTO_TCP, tcp4Table->table[i].dwState); if (ptr_map->find (network_hash) != ptr_map->end ()) { checker_map->emplace (network_hash, FALSE); continue; } ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); ptr_network->path = _app_getnetworkpath (tcp4Table->table[i].dwOwningPid, tcp4Table->table[i].OwningModuleInfo, ptr_network); if (!ptr_network->path) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET; ptr_network->protocol = IPPROTO_TCP; ptr_network->remote_addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr; ptr_network->remote_port = _r_byteswap_ushort ((USHORT)tcp4Table->table[i].dwRemotePort); ptr_network->local_addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr; ptr_network->local_port = _r_byteswap_ushort ((USHORT)tcp4Table->table[i].dwLocalPort); ptr_network->state = tcp4Table->table[i].dwState; if (tcp4Table->table[i].dwState == MIB_TCP_STATE_ESTAB) { if (_app_isvalidconnection (ptr_network->af, &ptr_network->remote_addr) || _app_isvalidconnection (ptr_network->af, &ptr_network->local_addr)) ptr_network->is_connection = TRUE; } ptr_map->insert_or_assign (network_hash, ptr_network); checker_map->emplace (network_hash, TRUE); } } } requiredSize = 0; GetExtendedTcpTable (NULL, &requiredSize, FALSE, AF_INET6, TCP_TABLE_OWNER_MODULE_ALL, 0); if (requiredSize) { if (allocationSize < requiredSize) { memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize); allocationSize = requiredSize; } PMIB_TCP6TABLE_OWNER_MODULE tcp6Table = (PMIB_TCP6TABLE_OWNER_MODULE)memoryAddress; if (GetExtendedTcpTable (tcp6Table, &requiredSize, FALSE, AF_INET6, TCP_TABLE_OWNER_MODULE_ALL, 0) == NO_ERROR) { for (DWORD i = 0; i < tcp6Table->dwNumEntries; i++) { network_hash = _app_getnetworkhash (AF_INET6, tcp6Table->table[i].dwOwningPid, tcp6Table->table[i].ucRemoteAddr, tcp6Table->table[i].dwRemotePort, tcp6Table->table[i].ucLocalAddr, tcp6Table->table[i].dwLocalPort, IPPROTO_TCP, tcp6Table->table[i].dwState); if (ptr_map->find (network_hash) != ptr_map->end ()) { checker_map->emplace (network_hash, FALSE); continue; } ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); ptr_network->path = _app_getnetworkpath (tcp6Table->table[i].dwOwningPid, tcp6Table->table[i].OwningModuleInfo, ptr_network); if (!ptr_network->path) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET6; ptr_network->protocol = IPPROTO_TCP; RtlCopyMemory (ptr_network->remote_addr6.u.Byte, tcp6Table->table[i].ucRemoteAddr, FWP_V6_ADDR_SIZE); ptr_network->remote_port = _r_byteswap_ushort ((USHORT)tcp6Table->table[i].dwRemotePort); RtlCopyMemory (ptr_network->local_addr6.u.Byte, tcp6Table->table[i].ucLocalAddr, FWP_V6_ADDR_SIZE); ptr_network->local_port = _r_byteswap_ushort ((USHORT)tcp6Table->table[i].dwLocalPort); ptr_network->state = tcp6Table->table[i].dwState; if (tcp6Table->table[i].dwState == MIB_TCP_STATE_ESTAB) { if (_app_isvalidconnection (ptr_network->af, &ptr_network->remote_addr6) || _app_isvalidconnection (ptr_network->af, &ptr_network->local_addr6)) ptr_network->is_connection = TRUE; } ptr_map->insert_or_assign (network_hash, ptr_network); checker_map->emplace (network_hash, TRUE); } } } requiredSize = 0; GetExtendedUdpTable (NULL, &requiredSize, FALSE, AF_INET, UDP_TABLE_OWNER_MODULE, 0); if (requiredSize) { if (allocationSize < requiredSize) { memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize); allocationSize = requiredSize; } PMIB_UDPTABLE_OWNER_MODULE udp4Table = (PMIB_UDPTABLE_OWNER_MODULE)memoryAddress; if (GetExtendedUdpTable (udp4Table, &requiredSize, FALSE, AF_INET, UDP_TABLE_OWNER_MODULE, 0) == NO_ERROR) { for (DWORD i = 0; i < udp4Table->dwNumEntries; i++) { IN_ADDR local_addr = {0}; local_addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr; network_hash = _app_getnetworkhash (AF_INET, udp4Table->table[i].dwOwningPid, NULL, 0, &local_addr, udp4Table->table[i].dwLocalPort, IPPROTO_UDP, 0); if (ptr_map->find (network_hash) != ptr_map->end ()) { checker_map->emplace (network_hash, FALSE); continue; } ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); ptr_network->path = _app_getnetworkpath (udp4Table->table[i].dwOwningPid, udp4Table->table[i].OwningModuleInfo, ptr_network); if (!ptr_network->path) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET; ptr_network->protocol = IPPROTO_UDP; ptr_network->local_addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr; ptr_network->local_port = _r_byteswap_ushort ((USHORT)udp4Table->table[i].dwLocalPort); //ptr_network->state = 0; if (_app_isvalidconnection (ptr_network->af, &ptr_network->local_addr)) ptr_network->is_connection = TRUE; ptr_map->insert_or_assign (network_hash, ptr_network); checker_map->emplace (network_hash, TRUE); } } } requiredSize = 0; GetExtendedUdpTable (NULL, &requiredSize, FALSE, AF_INET6, UDP_TABLE_OWNER_MODULE, 0); if (requiredSize) { if (allocationSize < requiredSize) { memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize); allocationSize = requiredSize; } PMIB_UDP6TABLE_OWNER_MODULE udp6Table = (PMIB_UDP6TABLE_OWNER_MODULE)memoryAddress; if (GetExtendedUdpTable (udp6Table, &requiredSize, FALSE, AF_INET6, UDP_TABLE_OWNER_MODULE, 0) == NO_ERROR) { for (DWORD i = 0; i < udp6Table->dwNumEntries; i++) { network_hash = _app_getnetworkhash (AF_INET6, udp6Table->table[i].dwOwningPid, NULL, 0, udp6Table->table[i].ucLocalAddr, udp6Table->table[i].dwLocalPort, IPPROTO_UDP, 0); if (ptr_map->find (network_hash) != ptr_map->end ()) { checker_map->emplace (network_hash, FALSE); continue; } ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); ptr_network->path = _app_getnetworkpath (udp6Table->table[i].dwOwningPid, udp6Table->table[i].OwningModuleInfo, ptr_network); if (!ptr_network->path) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET6; ptr_network->protocol = IPPROTO_UDP; RtlCopyMemory (ptr_network->local_addr6.u.Byte, udp6Table->table[i].ucLocalAddr, FWP_V6_ADDR_SIZE); ptr_network->local_port = _r_byteswap_ushort ((USHORT)udp6Table->table[i].dwLocalPort); //ptr_network->state = 0; if (_app_isvalidconnection (ptr_network->af, &ptr_network->local_addr6)) ptr_network->is_connection = TRUE; ptr_map->insert_or_assign (network_hash, ptr_network); checker_map->emplace (network_hash, TRUE); } } } if (memoryAddress) _r_mem_free (memoryAddress); } VOID _app_generate_packages () { LSTATUS code; HKEY hkey; HKEY hsubkey; DWORD key_index; DWORD max_length; DWORD size; PR_BYTE packageSid; PR_STRING keyName; PR_STRING displayName; PR_STRING packageSidString; SIZE_T app_hash; code = RegOpenKeyEx (HKEY_CLASSES_ROOT, L"Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\Repository\\Packages", 0, KEY_READ, &hkey); if (code == ERROR_SUCCESS) { max_length = _r_reg_querysubkeylength (hkey); if (!max_length) { RegCloseKey (hkey); return; } keyName = _r_obj_createstringex (NULL, max_length * sizeof (WCHAR)); key_index = 0; while (TRUE) { size = max_length; if (RegEnumKeyEx (hkey, key_index++, keyName->Buffer, &size, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) break; _r_string_trimtonullterminator (keyName); code = RegOpenKeyEx (hkey, keyName->Buffer, 0, KEY_READ, &hsubkey); if (code == ERROR_SUCCESS) { packageSid = _r_reg_querybinary (hsubkey, L"PackageSid"); if (packageSid) { if (RtlValidSid (packageSid->Buffer)) { packageSidString = _r_str_fromsid (packageSid->Buffer); if (packageSidString) { app_hash = _r_str_hash (packageSidString); if (!_app_isapphelperfound (app_hash)) { displayName = _r_reg_querystring (hsubkey, L"DisplayName"); if (displayName) { if (displayName->Buffer[0] == L'@') { UINT localizedLength = 256; PR_STRING localizedName = _r_obj_createstringex (NULL, localizedLength * sizeof (WCHAR)); if (SUCCEEDED (SHLoadIndirectString (displayName->Buffer, localizedName->Buffer, localizedLength, NULL))) { _r_string_trimtonullterminator (localizedName); _r_obj_movereference (&displayName, localizedName); } else { _r_obj_dereference (localizedName); } } PITEM_APP_HELPER ptr_item = (PITEM_APP_HELPER)_r_obj_allocateex (sizeof (ITEM_APP_HELPER), &_app_dereferenceappshelper); ptr_item->type = DataAppUWP; _r_obj_movereference (&ptr_item->pbytes, packageSid); // query timestamp ptr_item->timestamp = _r_reg_querytimestamp (hsubkey); _r_obj_movereference (&ptr_item->display_name, displayName); _r_obj_movereference (&ptr_item->internal_name, packageSidString); _r_obj_movereference (&ptr_item->real_path, _r_reg_querystring (hsubkey, L"PackageRootFolder")); // load additional info from appx manifest _app_load_appxmanifest (ptr_item); // clear references packageSidString = NULL; packageSid = NULL; apps_helper.emplace (app_hash, ptr_item); } } if (packageSidString) _r_obj_clearreference (&packageSidString); } } if (packageSid) _r_obj_dereference (packageSid); } RegCloseKey (hsubkey); } } _r_obj_dereference (keyName); RegCloseKey (hkey); } } VOID _app_generate_services () { SC_HANDLE hsvcmgr = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); if (!hsvcmgr) return; static DWORD initialBufferSize = 0x8000; DWORD returnLength = 0; DWORD servicesReturned = 0; DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS; DWORD dwServiceState = SERVICE_STATE_ALL; // win10+ if (_r_sys_isosversiongreaterorequal (WINDOWS_10)) dwServiceType |= SERVICE_INTERACTIVE_PROCESS | SERVICE_USER_SERVICE | SERVICE_USERSERVICE_INSTANCE; DWORD bufferSize = initialBufferSize; PVOID buffer = _r_mem_allocatezero (bufferSize); if (!EnumServicesStatusEx (hsvcmgr, SC_ENUM_PROCESS_INFO, dwServiceType, dwServiceState, (LPBYTE)buffer, bufferSize, &returnLength, &servicesReturned, NULL, NULL)) { if (GetLastError () == ERROR_MORE_DATA) { // Set the buffer bufferSize += returnLength; buffer = _r_mem_reallocatezero (buffer, bufferSize); // Now query again for services if (!EnumServicesStatusEx (hsvcmgr, SC_ENUM_PROCESS_INFO, dwServiceType, dwServiceState, (LPBYTE)buffer, bufferSize, &returnLength, &servicesReturned, NULL, NULL)) { _r_mem_free (buffer); buffer = NULL; } } else { _r_mem_free (buffer); buffer = NULL; } } // now traverse each service to get information if (buffer) { LPENUM_SERVICE_STATUS_PROCESS service; LPENUM_SERVICE_STATUS_PROCESS services; services = (LPENUM_SERVICE_STATUS_PROCESS)buffer; for (DWORD i = 0; i < servicesReturned; i++) { service = &services[i]; LPCWSTR display_name = service->lpDisplayName; LPCWSTR service_name = service->lpServiceName; SIZE_T app_hash = _r_str_hash (service_name); if (_app_isapphelperfound (app_hash)) continue; PR_STRING servicePath = NULL; time_t serviceTimestamp = 0; HKEY hkey; WCHAR generalKey[256]; WCHAR parametersKey[256]; _r_str_printf (generalKey, RTL_NUMBER_OF (generalKey), L"System\\CurrentControlSet\\Services\\%s", service_name); _r_str_printf (parametersKey, RTL_NUMBER_OF (parametersKey), L"System\\CurrentControlSet\\Services\\%s\\Parameters", service_name); // query "ServiceDll" path if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, parametersKey, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { // query path servicePath = _r_reg_querystring (hkey, L"ServiceDll"); // query timestamp serviceTimestamp = _r_reg_querytimestamp (hkey); RegCloseKey (hkey); } // fallback if (!servicePath || !serviceTimestamp) { if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, generalKey, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { // query path if (!servicePath) { servicePath = _r_reg_querystring (hkey, L"ImagePath"); if (servicePath) { PathRemoveArgs (servicePath->Buffer); _r_string_trimtonullterminator (servicePath); PathUnquoteSpaces (servicePath->Buffer); _r_string_trimtonullterminator (servicePath); } } // query timestamp if (!serviceTimestamp) serviceTimestamp = _r_reg_querytimestamp (hkey); RegCloseKey (hkey); } } if (servicePath) { PR_STRING convertedPath = _r_path_dospathfromnt (_r_obj_getstring (servicePath)); if (convertedPath) _r_obj_movereference (&servicePath, convertedPath); } PSID pserviceSid = _app_queryservicesid (service_name); if (pserviceSid) { PVOID pservice_sd = NULL; DWORD sd_length = 0; EXPLICIT_ACCESS ea; RtlSecureZeroMemory (&ea, sizeof (ea)); // When evaluating SECURITY_DESCRIPTOR conditions, the filter engine // checks for FWP_ACTRL_MATCH_FILTER access. If the DACL grants access, // it does not mean that the traffic is allowed; it just means that the // condition evaluates to true. Likewise if it denies access, the // condition evaluates to false. _app_setexplicitaccess (&ea, GRANT_ACCESS, NO_INHERITANCE, FWP_ACTRL_MATCH_FILTER, pserviceSid); // Security descriptors must be in self-relative form (i.e., contiguous). // The security descriptor returned by BuildSecurityDescriptorW is // already self-relative, but if you're using another mechanism to build // the descriptor, you may have to convert it. See MakeSelfRelativeSD for // details. if (BuildSecurityDescriptor (NULL, NULL, 1, &ea, 0, NULL, NULL, &sd_length, &pservice_sd) != ERROR_SUCCESS) { SAFE_DELETE_REFERENCE (servicePath); continue; } PITEM_APP_HELPER ptr_item = (PITEM_APP_HELPER)_r_obj_allocateex (sizeof (ITEM_APP_HELPER), &_app_dereferenceappshelper); ptr_item->type = DataAppService; ptr_item->timestamp = serviceTimestamp; ptr_item->display_name = _r_obj_createstring (display_name); ptr_item->internal_name = _r_obj_createstring (service_name); _r_obj_movereference (&ptr_item->real_path, servicePath); servicePath = NULL; ptr_item->pbytes = _r_obj_createbyteex (NULL, sd_length); RtlCopyMemory (ptr_item->pbytes->Buffer, pservice_sd, sd_length); SAFE_DELETE_LOCAL (pservice_sd); apps_helper.emplace (app_hash, ptr_item); _r_mem_free (pserviceSid); } SAFE_DELETE_REFERENCE (servicePath); } _r_mem_free (buffer); } CloseServiceHandle (hsvcmgr); } VOID _app_generate_rulesmenu (HMENU hsubmenu, SIZE_T app_hash) { PITEM_STATUS pstatus = (PITEM_STATUS)_r_mem_allocatezero (sizeof (ITEM_STATUS)); _app_getcount (pstatus); if (!app_hash || !pstatus->rules_count) { AppendMenu (hsubmenu, MF_SEPARATOR, 0, NULL); AppendMenu (hsubmenu, MF_STRING, IDX_RULES_SPECIAL, _r_locale_getstring (IDS_STATUS_EMPTY)); _r_menu_enableitem (hsubmenu, IDX_RULES_SPECIAL, MF_BYCOMMAND, FALSE); } else { MENUITEMINFO mii = {0}; WCHAR buffer[128]; PITEM_RULE ptr_rule; BOOLEAN is_global; BOOLEAN is_enabled; for (UINT8 type = 0; type < 2; type++) { if (type == 0) { if (!pstatus->rules_predefined_count) continue; } else { if (!pstatus->rules_user_count) continue; } AppendMenu (hsubmenu, MF_SEPARATOR, 0, NULL); for (UINT8 loop = 0; loop < 2; loop++) { for (SIZE_T i = 0; i < rules_arr.size (); i++) { ptr_rule = rules_arr.at (i); if (!ptr_rule) continue; ptr_rule = (PITEM_RULE)_r_obj_reference (ptr_rule); is_global = (ptr_rule->is_enabled && ptr_rule->apps->empty ()); is_enabled = is_global || (ptr_rule->is_enabled && (ptr_rule->apps->find (app_hash) != ptr_rule->apps->end ())); if (ptr_rule->type != DataRuleCustom || (type == 0 && (!ptr_rule->is_readonly || is_global)) || (type == 1 && (ptr_rule->is_readonly || is_global))) { _r_obj_dereference (ptr_rule); continue; } if ((loop == 0 && !is_enabled) || (loop == 1 && is_enabled)) { _r_obj_dereference (ptr_rule); 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); mii.cbSize = sizeof (mii); mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STATE | MIIM_STRING | MIIM_BITMAP | MIIM_CHECKMARKS; mii.fType = MFT_STRING; mii.dwTypeData = buffer; mii.hbmpItem = ptr_rule->is_block ? config.hbmp_block : config.hbmp_allow; mii.hbmpChecked = config.hbmp_checked; mii.hbmpUnchecked = config.hbmp_unchecked; mii.fState = (is_enabled ? MF_CHECKED : MF_UNCHECKED); mii.wID = IDX_RULES_SPECIAL + (UINT)i; InsertMenuItem (hsubmenu, mii.wID, FALSE, &mii); _r_obj_dereference (ptr_rule); } } } } AppendMenu (hsubmenu, MF_SEPARATOR, 0, NULL); AppendMenu (hsubmenu, MF_STRING, IDM_EDITRULES, _r_locale_getstring (IDS_EDITRULES)); AppendMenu (hsubmenu, MF_STRING, IDM_OPENRULESEDITOR, _r_locale_getstring (IDS_OPENRULESEDITOR)); _r_mem_free (pstatus); } VOID _app_generate_timermenu (HMENU hsubmenu, SIZE_T app_hash) { BOOLEAN is_checked = (app_hash == 0); time_t current_time = _r_unixtime_now (); time_t* ptime = (time_t*)_app_getappinfo (app_hash, InfoTimerPtr); time_t app_time = ptime ? *ptime : 0; WCHAR intervalString[128]; for (SIZE_T i = 0; i < timers.size (); i++) { UINT menu_id = IDX_TIMER + (UINT)i; time_t timer = timers.at (i); _r_format_interval (intervalString, RTL_NUMBER_OF (intervalString), timer + 1, 1); AppendMenu (hsubmenu, MF_STRING, menu_id, intervalString); if (!is_checked && (app_time > current_time) && (app_time <= (current_time + timer))) { _r_menu_checkitem (hsubmenu, IDX_TIMER, menu_id, MF_BYCOMMAND, menu_id); is_checked = TRUE; } } if (!is_checked) _r_menu_checkitem (hsubmenu, IDM_DISABLETIMER, IDM_DISABLETIMER, MF_BYCOMMAND, IDM_DISABLETIMER); } BOOLEAN _app_item_get (ENUM_TYPE_DATA type, SIZE_T app_hash, PR_STRING* displayName, PR_STRING* realPath, time_t* ptime, PR_BYTE* lpdata) { PITEM_APP_HELPER ptr_app_item = _app_getapphelperitem (app_hash); if (!ptr_app_item) return FALSE; if (ptr_app_item->type != type) { _r_obj_dereference (ptr_app_item); return FALSE; } if (displayName) { if (!_r_str_isempty (ptr_app_item->display_name)) *displayName = _r_obj_createstring2 (ptr_app_item->display_name); else if (!_r_str_isempty (ptr_app_item->real_path)) *displayName = _r_obj_createstring2 (ptr_app_item->real_path); else if (!_r_str_isempty (ptr_app_item->internal_name)) *displayName = _r_obj_createstring2 (ptr_app_item->internal_name); } if (realPath) { if (!_r_str_isempty (ptr_app_item->real_path)) *realPath = _r_obj_createstring2 (ptr_app_item->real_path); } if (lpdata) { if (ptr_app_item->pbytes) *lpdata = _r_obj_reference (ptr_app_item->pbytes); } if (ptime) *ptime = ptr_app_item->timestamp; _r_obj_dereference (ptr_app_item); return TRUE; } PR_STRING _app_parsehostaddress_dns (LPCWSTR hostname, USHORT port) { if (_r_str_isempty (hostname)) return NULL; PR_STRING string; PDNS_RECORD ppQueryResultsSet = NULL; string = _r_obj_createstringbuilder (); // ipv4 address DNS_STATUS dnsStatus = DnsQuery (hostname, DNS_TYPE_A, DNS_QUERY_NO_HOSTS_FILE, NULL, &ppQueryResultsSet, NULL); if (dnsStatus != DNS_ERROR_RCODE_NO_ERROR) { if (dnsStatus != DNS_INFO_NO_RECORDS) _r_logerror (0, L"DnsQuery (DNS_TYPE_A)", dnsStatus, hostname); } else { if (ppQueryResultsSet) { for (auto current = ppQueryResultsSet; current != NULL; current = current->pNext) { // ipv4 address WCHAR str[INET_ADDRSTRLEN]; if (_app_formatip (AF_INET, &(current->Data.A.IpAddress), str, RTL_NUMBER_OF (str), TRUE)) { _r_string_append (&string, str); if (port) _r_string_appendformat (&string, L":%d", port); _r_string_append (&string, DIVIDER_RULE); } } } } if (ppQueryResultsSet) { DnsRecordListFree (ppQueryResultsSet, DnsFreeRecordList); ppQueryResultsSet = NULL; } // ipv6 address dnsStatus = DnsQuery (hostname, DNS_TYPE_AAAA, DNS_QUERY_NO_HOSTS_FILE, NULL, &ppQueryResultsSet, NULL); if (dnsStatus != DNS_ERROR_RCODE_NO_ERROR) { if (dnsStatus != DNS_INFO_NO_RECORDS) _r_logerror (0, L"DnsQuery (DNS_TYPE_AAAA)", dnsStatus, hostname); } else { if (ppQueryResultsSet) { for (auto current = ppQueryResultsSet; current != NULL; current = current->pNext) { WCHAR str[INET6_ADDRSTRLEN]; if (_app_formatip (AF_INET6, ¤t->Data.AAAA.Ip6Address, str, RTL_NUMBER_OF (str), TRUE)) { _r_string_appendformat (&string, L"[%s]", str); if (port) _r_string_appendformat (&string, L":%d", port); _r_string_append (&string, DIVIDER_RULE); } } } } if (ppQueryResultsSet) { DnsRecordListFree (ppQueryResultsSet, DnsFreeRecordList); ppQueryResultsSet = NULL; } _r_str_trim (string, DIVIDER_RULE); if (_r_str_isempty (string)) { _r_obj_dereference (string); return NULL; } return string; } BOOLEAN _app_parsenetworkstring (LPCWSTR network_string, NET_ADDRESS_FORMAT* format_ptr, PUSHORT port_ptr, FWP_V4_ADDR_AND_MASK* paddr4, FWP_V6_ADDR_AND_MASK* paddr6, LPWSTR dnsString, SIZE_T dnsLength) { NET_ADDRESS_INFO ni; RtlSecureZeroMemory (&ni, sizeof (ni)); USHORT port; BYTE prefix_length; DWORD types = NET_STRING_ANY_ADDRESS | NET_STRING_ANY_SERVICE | NET_STRING_IP_NETWORK | NET_STRING_ANY_ADDRESS_NO_SCOPE | NET_STRING_ANY_SERVICE_NO_SCOPE; DWORD code = ParseNetworkString (network_string, types, &ni, &port, &prefix_length); if (code != ERROR_SUCCESS) { _r_logerror (0, L"ParseNetworkString", code, network_string); return FALSE; } else { if (format_ptr) *format_ptr = ni.Format; if (port_ptr) *port_ptr = port; if (ni.Format == NET_ADDRESS_IPV4) { if (paddr4) { ULONG mask = 0; ConvertLengthToIpv4Mask (prefix_length, &mask); paddr4->addr = _r_byteswap_ulong (ni.Ipv4Address.sin_addr.S_un.S_addr); paddr4->mask = _r_byteswap_ulong (mask); } return TRUE; } else if (ni.Format == NET_ADDRESS_IPV6) { if (paddr6) { RtlCopyMemory (paddr6->addr, ni.Ipv6Address.sin6_addr.u.Byte, FWP_V6_ADDR_SIZE); paddr6->prefixLength = min (prefix_length, 128); } return TRUE; } else if (ni.Format == NET_ADDRESS_DNS_NAME) { if (dnsString) { SIZE_T dns_hash = _r_str_hash (ni.NamedAddress.Address); if (cache_dns.find (dns_hash) != cache_dns.end ()) { PR_STRING pdata = cache_dns.at (dns_hash); if (pdata) { PR_STRING dnsCacheString = _r_obj_reference (pdata); _r_str_copy (dnsString, dnsLength, _r_obj_getstring (dnsCacheString)); _r_obj_dereference (dnsCacheString); return !_r_str_isempty (dnsString); } } PR_STRING hostString = _app_parsehostaddress_dns (ni.NamedAddress.Address, port); if (!hostString) { return FALSE; } else { _r_str_copy (dnsString, dnsLength, hostString->Buffer); _app_freestrings_map (&cache_dns, MAP_CACHE_MAX); cache_dns.insert_or_assign (dns_hash, hostString); return TRUE; } } return TRUE; } } return FALSE; } BOOLEAN _app_parserulestring (PR_STRING rule, PITEM_ADDRESS ptr_addr) { if (_r_str_isempty (rule)) return TRUE; if (!_app_isrulevalidchars (rule->Buffer)) return FALSE; ENUM_TYPE_DATA type = DataUnknown; SIZE_T rule_length = _r_obj_getstringlength (rule); SIZE_T range_pos = _r_str_findchar (rule->Buffer, rule_length, DIVIDER_RULE_RANGE); BOOLEAN is_range = (range_pos != INVALID_SIZE_T); WCHAR range_start[LEN_IP_MAX] = {0}; WCHAR range_end[LEN_IP_MAX] = {0}; if (is_range) { PR_STRING rangeStart = _r_str_extract (rule, 0, range_pos); PR_STRING rangeEnd = _r_str_extract (rule, range_pos + 1, INVALID_SIZE_T); _r_str_copy (range_start, RTL_NUMBER_OF (range_start), _r_obj_getstring (rangeStart)); _r_str_copy (range_end, RTL_NUMBER_OF (range_end), _r_obj_getstring (rangeEnd)); _r_obj_dereference (rangeStart); _r_obj_dereference (rangeEnd); } // auto-parse rule type { SIZE_T rule_hash = _r_str_hash (rule); BOOLEAN is_exists = cache_types.find (rule_hash) != cache_types.end (); if (is_exists) { type = cache_types[rule_hash]; } else { if (_app_isruleport (rule->Buffer)) { type = DataTypePort; } else if (is_range ? (_app_isruleip (range_start) && _app_isruleip (range_end)) : _app_isruleip (rule->Buffer)) { type = DataTypeIp; } else if (_app_isrulehost (rule->Buffer)) { type = DataTypeHost; } if (type != DataUnknown) { if (cache_types.size () >= MAP_CACHE_MAX) cache_types.clear (); cache_types.emplace (rule_hash, type); } } } if (type == DataUnknown) return FALSE; if (!ptr_addr) return TRUE; if (type == DataTypeHost) is_range = FALSE; ptr_addr->is_range = is_range; if (type == DataTypePort) { if (!is_range) { // ...port ptr_addr->type = DataTypePort; ptr_addr->port = (UINT16)_r_str_touinteger (rule->Buffer); return TRUE; } else { // ...port range ptr_addr->type = DataTypePort; ptr_addr->range.valueLow.type = FWP_UINT16; ptr_addr->range.valueLow.uint16 = (UINT16)wcstoul (range_start, NULL, 10); ptr_addr->range.valueHigh.type = FWP_UINT16; ptr_addr->range.valueHigh.uint16 = (UINT16)wcstoul (range_end, NULL, 10); return TRUE; } } else { NET_ADDRESS_FORMAT format; FWP_V4_ADDR_AND_MASK addr4 = {0}; FWP_V6_ADDR_AND_MASK addr6 = {0}; USHORT port2 = 0; if (type == DataTypeIp && is_range) { // ...ip range (start) if (_app_parsenetworkstring (range_start, &format, &port2, &addr4, &addr6, NULL, 0)) { if (format == NET_ADDRESS_IPV4) { ptr_addr->range.valueLow.type = FWP_UINT32; ptr_addr->range.valueLow.uint32 = addr4.addr; } else if (format == NET_ADDRESS_IPV6) { ptr_addr->range.valueLow.type = FWP_BYTE_ARRAY16_TYPE; RtlCopyMemory (ptr_addr->range.valueLow.byteArray16->byteArray16, addr6.addr, FWP_V6_ADDR_SIZE); } else { return FALSE; } if (port2 && !ptr_addr->port) ptr_addr->port = port2; } else { return FALSE; } // ...ip range (end) if (_app_parsenetworkstring (range_end, &format, &port2, &addr4, &addr6, NULL, 0)) { if (format == NET_ADDRESS_IPV4) { ptr_addr->range.valueHigh.type = FWP_UINT32; ptr_addr->range.valueHigh.uint32 = addr4.addr; } else if (format == NET_ADDRESS_IPV6) { ptr_addr->range.valueHigh.type = FWP_BYTE_ARRAY16_TYPE; RtlCopyMemory (ptr_addr->range.valueHigh.byteArray16->byteArray16, addr6.addr, FWP_V6_ADDR_SIZE); } else { return FALSE; } } else { return FALSE; } ptr_addr->format = format; ptr_addr->type = DataTypeIp; } else { // ...ip/host if (_app_parsenetworkstring (rule->Buffer, &format, &port2, &ptr_addr->addr4, &ptr_addr->addr6, ptr_addr->host, RTL_NUMBER_OF (ptr_addr->host))) { ptr_addr->type = DataTypeIp; ptr_addr->format = format; if (port2) ptr_addr->port = port2; return TRUE; } else { return FALSE; } } } return TRUE; } INT _app_getlistview_id (ENUM_TYPE_DATA type) { if (type == DataAppRegular || type == DataAppDevice || type == DataAppNetwork || type == DataAppPico) return IDC_APPS_PROFILE; else if (type == DataAppService) return IDC_APPS_SERVICE; else if (type == DataAppUWP) return IDC_APPS_UWP; else if (type == DataRuleBlocklist) return IDC_RULES_BLOCKLIST; else if (type == DataRuleSystem) return IDC_RULES_SYSTEM; else if (type == DataRuleCustom) return IDC_RULES_CUSTOM; return 0; } HBITMAP _app_bitmapfromico (HICON hicon, INT icon_size) { if (!hicon) return NULL; RECT iconRectangle; SetRect (&iconRectangle, 0, 0, icon_size, icon_size); HBITMAP hbitmap = NULL; HDC screenHdc = GetDC (NULL); if (screenHdc) { HDC hdc = CreateCompatibleDC (screenHdc); if (hdc) { BITMAPINFO bitmapInfo = {0}; bitmapInfo.bmiHeader.biSize = sizeof (bitmapInfo); bitmapInfo.bmiHeader.biPlanes = 1; bitmapInfo.bmiHeader.biCompression = BI_RGB; bitmapInfo.bmiHeader.biWidth = icon_size; bitmapInfo.bmiHeader.biHeight = icon_size; bitmapInfo.bmiHeader.biBitCount = 32; hbitmap = CreateDIBSection (hdc, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0); if (hbitmap) { HGDIOBJ oldBitmap = SelectObject (hdc, hbitmap); BLENDFUNCTION blendFunction = {0}; blendFunction.BlendOp = AC_SRC_OVER; blendFunction.AlphaFormat = AC_SRC_ALPHA; blendFunction.SourceConstantAlpha = 255; BP_PAINTPARAMS paintParams = {0}; paintParams.cbSize = sizeof (paintParams); paintParams.dwFlags = BPPF_ERASE; paintParams.pBlendFunction = &blendFunction; HDC bufferHdc = NULL; HPAINTBUFFER paintBuffer = BeginBufferedPaint (hdc, &iconRectangle, BPBF_DIB, &paintParams, &bufferHdc); if (paintBuffer) { DrawIconEx (bufferHdc, 0, 0, hicon, icon_size, icon_size, 0, NULL, DI_NORMAL); EndBufferedPaint (paintBuffer, TRUE); } else { _r_dc_fillrect (hdc, &iconRectangle, GetSysColor (COLOR_MENU)); DrawIconEx (hdc, 0, 0, hicon, icon_size, icon_size, 0, NULL, DI_NORMAL); } SelectObject (hdc, oldBitmap); } SAFE_DELETE_DC (hdc); } ReleaseDC (NULL, screenHdc); } return hbitmap; } HBITMAP _app_bitmapfrompng (HINSTANCE hinst, LPCWSTR name, INT icon_size) { BOOLEAN success = FALSE; UINT frameCount = 0; ULONG resourceLength = 0; HDC screenHdc = NULL; HDC hdc = NULL; BITMAPINFO bi = {0}; HBITMAP hbitmap = NULL; PVOID bitmapBuffer = NULL; IWICStream* wicStream = NULL; IWICBitmapSource* wicBitmapSource = NULL; IWICBitmapDecoder* wicDecoder = NULL; IWICBitmapFrameDecode* wicFrame = NULL; IWICImagingFactory* wicFactory = NULL; IWICBitmapScaler* wicScaler = NULL; WICPixelFormatGUID pixelFormat; WICRect rect = {0, 0, icon_size, icon_size}; // Create the ImagingFactory if (FAILED (CoCreateInstance (CLSID_WICImagingFactory1, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (PVOID*)&wicFactory))) goto DoExit; // Load the resource WICInProcPointer resourceBuffer = (WICInProcPointer)_r_loadresource (hinst, name, L"PNG", &resourceLength); if (!resourceBuffer) goto DoExit; // Create the Stream if (FAILED (wicFactory->CreateStream (&wicStream))) goto DoExit; // Initialize the Stream from Memory if (FAILED (wicStream->InitializeFromMemory (resourceBuffer, resourceLength))) goto DoExit; if (FAILED (wicFactory->CreateDecoder (GUID_ContainerFormatPng, NULL, &wicDecoder))) goto DoExit; if (FAILED (wicDecoder->Initialize ((IStream*)wicStream, WICDecodeMetadataCacheOnLoad))) goto DoExit; // Get the Frame count if (FAILED (wicDecoder->GetFrameCount (&frameCount)) || frameCount < 1) goto DoExit; // Get the Frame if (FAILED (wicDecoder->GetFrame (0, &wicFrame))) goto DoExit; // Get the WicFrame image format if (FAILED (wicFrame->GetPixelFormat (&pixelFormat))) goto DoExit; // Check if the image format is supported: if (RtlEqualMemory (&pixelFormat, &GUID_WICPixelFormat32bppPRGBA, sizeof (GUID))) { wicBitmapSource = (IWICBitmapSource*)wicFrame; } else { IWICFormatConverter* wicFormatConverter = NULL; if (FAILED (wicFactory->CreateFormatConverter (&wicFormatConverter))) goto DoExit; if (FAILED (wicFormatConverter->Initialize ( (IWICBitmapSource*)wicFrame, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom ))) { wicFormatConverter->Release (); goto DoExit; } // Convert the image to the correct format: wicFormatConverter->QueryInterface (&wicBitmapSource); // Cleanup the converter. wicFormatConverter->Release (); // Dispose the old frame now that the converted frame is in wicBitmapSource. wicFrame->Release (); } bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); bi.bmiHeader.biWidth = rect.Width; bi.bmiHeader.biHeight = -((LONG)rect.Height); bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; screenHdc = GetDC (NULL); hdc = CreateCompatibleDC (screenHdc); hbitmap = CreateDIBSection (screenHdc, &bi, DIB_RGB_COLORS, &bitmapBuffer, NULL, 0); if (FAILED (wicFactory->CreateBitmapScaler (&wicScaler))) goto DoExit; if (FAILED (wicScaler->Initialize (wicBitmapSource, rect.Width, rect.Height, WICBitmapInterpolationModeFant))) goto DoExit; if (FAILED (wicScaler->CopyPixels (&rect, rect.Width * 4, rect.Width * rect.Height * 4, (LPBYTE)bitmapBuffer))) goto DoExit; success = TRUE; DoExit: if (wicScaler) wicScaler->Release (); SAFE_DELETE_DC (hdc); if (screenHdc) ReleaseDC (NULL, screenHdc); if (wicBitmapSource) wicBitmapSource->Release (); if (wicStream) wicStream->Release (); if (wicDecoder) wicDecoder->Release (); if (wicFactory) wicFactory->Release (); if (!success) { SAFE_DELETE_OBJECT (hbitmap); return NULL; } return hbitmap; } VOID _app_load_appxmanifest (PITEM_APP_HELPER ptr_app_item) { if (_r_str_isempty (ptr_app_item->real_path)) return; WCHAR path[512]; PR_STRING resultPath; LPCWSTR appx_names[] = { L"AppxManifest.xml", L"VSAppxManifest.xml", }; for (SIZE_T i = 0; i < RTL_NUMBER_OF (appx_names); i++) { _r_str_printf (path, RTL_NUMBER_OF (path), L"%s\\%s", _r_obj_getstring (ptr_app_item->real_path), appx_names[i]); if (_r_fs_exists (path)) goto DoOpen; } return; DoOpen: resultPath = NULL; pugi::xml_document doc; pugi::xml_parse_result xml_result = doc.load_file (path, PUGIXML_LOAD_FLAGS, PUGIXML_LOAD_ENCODING); if (xml_result) { pugi::xml_node root = doc.child (L"Package"); if (root) { pugi::xml_node xml_applications = root.child (L"Applications"); for (pugi::xml_node item = xml_applications.child (L"Application"); item; item = item.next_sibling (L"Application")) { if (!item.attribute (L"Executable").empty ()) { SAFE_DELETE_REFERENCE (resultPath); resultPath = _r_format_string (L"%s\\%s", _r_obj_getstring (ptr_app_item->real_path), item.attribute (L"Executable").as_string ()); if (_r_fs_exists (_r_obj_getstring (resultPath))) break; } } } } _r_obj_movereference (&ptr_app_item->real_path, resultPath); }