Repository: henrypp/simplewall Branch: master Commit: b33787d02273 Files: 98 Total size: 1.0 MB Directory structure: gitextract_imtg74o1/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ ├── feature_request.yml │ │ └── question.md │ └── workflows/ │ └── scorecard.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── CHANGELOGv1.md ├── LICENSE ├── README.md ├── VERSION ├── bin/ │ ├── History.txt │ ├── License.txt │ ├── Readme.txt │ ├── i18n/ │ │ ├── !example.txt │ │ ├── Arabic.ini │ │ ├── Bulgarian.ini │ │ ├── Catalan.ini │ │ ├── Chinese (Simplified).ini │ │ ├── Chinese (Traditional).ini │ │ ├── Czech.ini │ │ ├── Dutch.ini │ │ ├── Finnish.ini │ │ ├── French.ini │ │ ├── German.ini │ │ ├── Hungarian.ini │ │ ├── Italian.ini │ │ ├── Japanese.ini │ │ ├── Korean.ini │ │ ├── Persian.ini │ │ ├── Polish.ini │ │ ├── Portuguese (Brazil).ini │ │ ├── Portuguese.ini │ │ ├── Russian.ini │ │ ├── Serbian (Cyrillic).ini │ │ ├── Serbian (Latin).ini │ │ ├── Slovak.ini │ │ ├── Slovenian.ini │ │ ├── Spanish.ini │ │ ├── Swedish.ini │ │ ├── Turkish.ini │ │ ├── Ukrainian.ini │ │ └── Vietnamese.ini │ ├── profile_internal.xml │ └── simplewall.lng ├── build.bat ├── build_locale.bat ├── build_simplewall_rules.bat ├── build_vc.bat ├── packages.config ├── simplewall.sln ├── simplewall.vcxproj ├── simplewall.vcxproj.filters ├── simplewall.vcxproj.user └── src/ ├── app.h ├── controls.c ├── controls.h ├── db.c ├── db.h ├── editor.c ├── editor.h ├── global.h ├── helper.c ├── helper.h ├── icons.c ├── icons.h ├── listview.c ├── listview.h ├── log.c ├── log.h ├── main.c ├── main.h ├── messages.c ├── messages.h ├── network.c ├── network.h ├── notifications.c ├── notifications.h ├── packages.c ├── packages.h ├── profile.c ├── profile.h ├── res/ │ └── manifest.xml ├── resource.h ├── resource.rc ├── search.c ├── search.h ├── security.c ├── security.h ├── timer.c ├── timer.h ├── uwp.cpp ├── uwp.h ├── wfp.c └── wfp.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *.c diff *.cpp diff *.h diff *.rc diff *.ini diff *.txt diff *.xml diff *.lng diff ================================================ FILE: .github/FUNDING.yml ================================================ custom: ["https://www.paypal.me/henrypp", "https://yoomoney.ru/to/4100115776040583", "https://www.blockchain.com/btc/address/1LrRTXPsvHcQWCNZotA9RcwjsGcRghG96c", "https://www.blockchain.com/eth/address/0xe2C84A62eb2a4EF154b19bec0c1c106734B95960"] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug report title: "[Bug]" description: Let me know about crash or existing functionality not working like it should. labels: [ "bug" ] body: - type: markdown attributes: value: Thanks for taking the time to fill out this bug report! - type: checkboxes id: checklist attributes: label: Checklist options: - label: I have used the search function to see if someone else has already submitted the same bug report. required: true - label: I will describe the problem with as much detail as possible. required: true - type: input id: version attributes: label: App version description: What the application version do you use. placeholder: x.y.z validations: required: true - type: input id: windows_version attributes: label: Windows version description: What Windows version do you use. validations: required: true - type: textarea id: steps attributes: label: Steps to reproduce placeholder: | 1. Go to '…' 2. Click on '…' 3. Scroll down to '…' 4. etc. validations: required: true - type: textarea id: expected attributes: label: Expected behavior description: After following the steps, what did you think application would do? validations: required: false - type: textarea id: actual attributes: label: Actual behavior description: What did application do instead? Screenshots might help. validations: required: true - type: textarea id: logs attributes: label: Logs description: | - If application have debug log insert it here. - If application have crash dump please attach it here. Tip: You can attach images, log files or crash dumps by clicking this area to highlight it and then dragging files in. ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yml ================================================ name: Feature request title: "[Feature]" description: Suggest an idea for this project. labels: [ "feature" ] body: - type: checkboxes id: checklist attributes: label: Checklist options: - label: I have used the search function to see if someone else has already submitted the same feature request. required: true - label: I will describe the problem with as much detail as possible. required: true - label: This issue only contains a request for one single feature, **not** multiple (related) features. required: true - type: input id: version attributes: label: App version description: What the application version do you use. placeholder: x.y.z validations: required: true - type: textarea id: problem attributes: label: Problem you are trying to solve description: Give a brief explanation of the problem you are trying to solve. validations: required: true - type: textarea id: solution attributes: label: Suggested solution description: Describe how you would like the app to help you solve that problem. Try to be as specific as possible. validations: required: true - type: textarea id: screenshots attributes: label: Screenshots / Drawings / Technical details description: | If your request is about (or includes) changing or extending the user interface (UI), describe what the UI would look like and how the user would interact with it. Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. ================================================ FILE: .github/ISSUE_TEMPLATE/question.md ================================================ --- name: Question about: Ask a question about application. title: '[Question]' labels: [ "question" ] assignees: '' --- Describe the question with as much detail as possible. --- App version: Windows version: ================================================ FILE: .github/workflows/scorecard.yml ================================================ # This workflow uses actions that are not certified by GitHub. They are provided # by a third-party and are governed by separate terms of service, privacy # policy, and support documentation. name: Scorecard supply-chain security on: # For Branch-Protection check. Only the default branch is supported. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection branch_protection_rule: # To guarantee Maintained check is occasionally updated. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained schedule: - cron: '32 18 * * 3' push: branches: [ "master" ] # Declare default permissions as read only. permissions: read-all jobs: analysis: name: Scorecard analysis runs-on: ubuntu-latest # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled. if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request' permissions: # Needed to upload the results to code-scanning dashboard. security-events: write # Needed to publish results and get a badge (see publish_results below). id-token: write # Uncomment the permissions below if installing in a private repository. # contents: read # actions: read steps: - name: "Checkout code" uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Run analysis" uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 with: results_file: results.sarif results_format: sarif # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: # - you want to enable the Branch-Protection check on a *public* repository, or # - you are installing Scorecard on a *private* repository # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. # repo_token: ${{ secrets.SCORECARD_TOKEN }} # Public repositories: # - Publish results to OpenSSF REST API for easy access by consumers # - Allows the repository to include the Scorecard badge. # - See https://github.com/ossf/scorecard-action#publishing-results. # For private repositories: # - `publish_results` will always be set to `false`, regardless # of the value entered here. publish_results: true # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore file_mode: git # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: SARIF file path: results.sarif retention-days: 5 # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif ================================================ FILE: .gitignore ================================================ .vs/ .vscode/ temp/ packages/ bin/32/ bin/64/ bin/arm64/ x64/ win32/ arm64/ __pycache__ thumbs.db ehthumbs.db desktop.ini *.cab *.msi *.msm *.msp *.lnk *.jpg *.zip *.log *.pdb *.exp *.sdf *.opensdf *.db *.opendb *.suo *.exp *.iobj *.ipch *.ipdb *.ilk *.obj *.res *.tlog *PVS-Studio* ================================================ FILE: .gitmodules ================================================ [submodule "routine"] path = ../routine url = https://github.com/henrypp/routine.git [submodule "builder"] path = ../builder url = https://github.com/henrypp/builder.git ================================================ FILE: CHANGELOG.md ================================================ v3.8.7 (8 August 2025) - fixed not logical crash (issue #2012) - fixed context menu performance - updated locale (issue #1984) - updated project sdk - cosmetic fixes v3.8.6.1 (21 May 2025) - fixed "open containing folder" error (issue #1977) - fixed crash at startup (issue #1979) - fixed crash dump (issue #1958) v3.8.6 (1 April 2025) - fixed check for update, does not bring up popup (issue #1923) - fixed memory heap error (issue #1945) - fixed possible crash - improved dark theme support v3.8.5 (27 November 2024) - fixed adding apps with drive letters instead of specific apps (issue #1887) - fixed creating rules for inaccessible paths (issue #1891) - fixed opening log with spaces path (issue #1912) - fixed windows 7 loopback rules - cosmetic fixes v3.8.4 (11 September 2024) - added listview empty markup - fixed tray icon middle click not worked when log ui is disabled - fixed notification displays invalid signature (issue #1871) - fixed does not show up tray icon (issue #1844) - fixed crash when cleanup timers (issue #1860) - fixed possible memory leak - updated project sdk - updated rule hint - cosmetic fixes v3.8.3 (8 August 2024) - added remember last position of notification window (issue #1659) - added watch services & uwp apps for install/uninstall - added displays long time for apps - improved windows 7 compatibility - improved arm64 compatibility - improved dark theme support - fixed show log button does not work as expected (issue #1757, again!) - fixed apps sometimes delete themselves (issue #1794, not fixed) - fixed duplicate process at startup (issue #1769) - fixed do not save hash when it is not enabled - fixed row colors for dark mode (issue #1767) - fixed log listview sorting by date - fixed displaying timer tooltip - updated project sdk v3.8.2 (9 May 2024) - revert back windows 7 & windows 8 support - improved dark theme support - improved log subscription - fixed show log button does not work as expected (issue #1757) - fixed search visibility v3.8.1 (27 April 2024) - fixed lacks search context (issue #1760) - fixed incorrect log ui listview item counting - updated confirm message for timers cleanup - updated confirm message for unused cleanup - updated cppwinrt package - updated project sdk v3.8 (1 April 2024) - added mitigations (win10+) (issue #611) - added dark theme support (issue #248) - fixed displaying same context menu on apps and packets log - updated search engine - updated project sdk v3.7.8 (28 January 2024) - added saving flag state for install/uninstall filters - fixed crash on tooltip (issue #1686) - fixed apps disabled removal menu - updated dropped packets (ui) listview context menu - updated project sdk v3.7.7 (3 January 2024) - added error message when loading library on subscribe - added comment item for apps/rules (issue #1664) - added recheck app hash in properies dialog - added highlighting of undelatable apps - fixed displaying incorrect error messages - fixed high disk usage (issue #1665) - updated ports list v3.7.6 (30 November 2023) - fixed configuration of windows update (issue #1648) - fixed auto update fails to install (issue #1565) - updated project sdk v3.7.5 (1 November 2023) - fixed saving services and uwp apps (issue #1616) - fixed file locked by simplewall (issue #1621) - fixed removing unused apps - fixed process creation - updated project sdk v3.7.4 (27 October 2023) - added set option to disable apps removal from profile (issue #1155) - fixed cannot save itself as unchecked (issue #1609) - fixed could not save profile (issue #1594) - fixed crash (issue #1582) - updated project sdk v3.7.3 (11 October 2023) - added error message for saving profile - removed redistributable package requirement (issue #1587) - fixed profile was not found message (issue #1557) - fixed crash on reading version information - revert back certificates checking option - updated project sdk v3.7.2 (21 September 2023) - dropped windows 7 and windows 8 support - fixed launch of several copies of the application (issue #1547) - fixed create filters for inaccessible apps (issue #1528) - fixed displaying update dialog at startup (issue #1511) - fixed retrieving version information for some files - fixed slow apps search (issue #1477) - fixed periodicaly crashing (issue #1486) - fixed retrieving some apps icons - fixed saving input on settings - fixed saving unused apps - fixed process creation - improved signature checking - updated project sdk v3.7.1 (31 July 2023) - fixed import not correcly worked (issue #1466) - fixed crash when checking files (issue #1455) - updated project sdk v3.7 (27 July 2023) - added profile encryption [oldest versions cannot open new profile] (issue #599) - added terminate process into notification window (issue #1398) - added checksum calculation for the apps (issue #394) - added error message for log subscription - improved search performance (issue #1383) - fixed timer and apps timestamp displays incorrect information (32-bit only) - fixed sometimes application displays incrorrect icons - fixed possible crash when clearing log - fixed silent uninstaller do not worked - fixed arm64 build crash (issue #1228) - fixed internal bugs - fixed memory leaks - updated nuget package - updated project sdk - updated locale v3.6.7 (21 September 2022) - added windows update service solution (issue #677, thx @taviso) [win10+] - added feature to allow only the requested ip in notification (issue #1265) - added 12 and 24 hour timer values (issue #1298) - fixed opening editor are overlapped by notification window - fixed uwp apps are reset after installing updates (issue #1294) - fixed select all with search filter selects everything (issue #1264) - fixed loading default icons for services and uwp apps - fixed check update option in main menu (issue #1309) - fixed port numbers are now verified (issue #1240) v3.6.6 (12 August 2022) - fixed editor does not disable save button when rule name is empty - fixed network monitor duplicate calls - fixed application crash (issue #1272) v3.6.5 (11 August 2022) - added group for apps with timers - display long time in packets log date column - fixed uwp packages display name parsing - fixed blank notifications (again!) (issue #1009) v3.6.4 (19 Juny 2022) - added focus assistant support (win10rs3+) - fixed notification sometimes can lose focus of fullscreen app - fixed internal profile loading crash (issue #1228) v3.6.3 (10 May 2022) - fixed installer launches simplewall without asking user (issue #1119) - fixed saving unused apps in profile (issue #1216) - fixed app crash on create process (issue ##1224) - fixed uninstaller delete not all files - improved workqueue environment - improved threading model - fixed internal bugs v3.6.2 (26 April 2022) - added autoinstall non-executable updates feature (issue #1122) - added clear search with escape button for editor - added fallback for font loading when it does not exists - improved uwp packages information loading - fixed restore properties window position - fixed rule tooltip whitespace - fixed internal bugs - updated network monitor - updated locales - cosmetic fixes v3.6.1 (11 November 2021) - added clear search with escape button - fixed crash on delete filters (issue #1084) - fixed import profile warning (issue #1086) - fixed crash dumps processing - updated locales - cosmetic fixes v3.6 (9 November 2021) - improved multi-threading safety - improved startup time - improved dpi support - added option to confirm allowing applications (issue #1070) - added filtering for the application list (issue #663) - added editor list items count mark for tab title - added wfp initialization failure workaround - added filtering for editor apps and rules - added layer name into log - moved log exclude configuration into another settings page (issue #1064) - revert notification x button (issue #973) - changed create rule toolbar icon (#723) - fixed filters with hard permit can access internet (issue #689) - fixed issue with hotkeys for switch tabs (issue #723) - fixed rebar incrorrect resizing when dpi was changed - fixed update installation issue (issue #1061) - fixed notification multi-monitor support - fixed service missing path (issue #1036) - fixed editor can cause crash (#1071) - fixed big memory leak (issue #1066) - fixed net events unsubscription - optimized listview sorting - fixed internal bugs - cosmetic fixes v3.5.3 (18 October 2021) - fixed using uninitialzed port variable in ip ranges [regression] (issue #1055) v3.5.2 (17 October 2021) - builded with windows 11 sdk - fixed port can be omited when parsing ip ranges (issue #1010) - fixed remote range replaces local range (issue #1044) - fixed interface stuck by comctl library (issue #1009) - fixed massive gdi handles leak - fixed internal bugs v3.5.1 (6 October 2021) - optimized certificate checking - fixed check apps for digital signatures option not works (issue #1037) - fixed lock to avoid duplicate file information loading - fixed crash on profile loading (issue #1033) v3.5 (4 October 2021) - in this release fqdn support was removed because of security issue (issues #1012) - improved performance due caching network resolution and file information - partially revert of windows defender power off (issue #1022) - added ballon tip to display input limitations (issue #809) - added compress internal profile in resources with lznt1 - fixed signatures information pointer use-after-free when dns resolver avoid arpa requests (issue #1008) - fixed resolve network addresses can cause crash (issue #1015) - fixed notification color issues (issue #1007) - fixed update installation (issue #1016) - fixed version information retrieval - fixed workqueue environment - fixed internal bugs v3.4.3 (30 August 2021) - added verify code signatures from catalog files (issue #1003) - fixed crash at startup (issue #995) - fixed rule reference (issue #1002) v3.4.2 (24 August 2021) - enable checking apps certificates by default - show notifications immediately without waiting for busy operations to complete - impoved listview responsiveness by using virtual listview callback - fixed packets log displays incorrect direction (issue #945) - fixed missed listview icons on refresh - fixed thread environment - fixed internal bugs - cosmetic fixes v3.4.1 (15 August 2021) - fixed blocklist can does not change action status - fixed crash at startup (issue #976) - fixed profile import compatibility - fixed install update v3.4 (11 August 2021) - added arm64 binaries (portable only) - added protocol and host name information into network alert window (issue #843) - added limit number of packets log entries (issue #941) - added host resolving for packet logger listview - added listview group for forever blocked apps - fixed loading icons of each application freezes interface (issue #830) - fixed log listview can have empty lines due to race condition - fixed ui not properly display installation status (issue #962) - fixed memory leak when loading profile (issue #888, #937) - fixed high cpu usage for packet logger (issue #949) - updated system rules - updated project sdk - fixed internal bugs v3.3.5 (5 July 2021) - added command line short opts - use guid for tray icon - updated project sdk - fixed toolbar glitch on hidpi displays (issue #950) - fixed multi-monitor with diffirent dpi support - fixed installer creates unused files - fixed internal bugs v3.3.4 (3 June 2021) - autoclean packets log ui when system suspended - fixed config may not be saved when profile directory does not exist - fixed unnecessary checking for app paths attributes - fixed threadpool does not initialized com library - fixed installer silent mode (issue #907) - updated blocklist and system rules - fixed internal bugs v3.3.3 (29 April 2021) - fixed listview tooltip can cause crash (issue #890) - fixed editor does not create filters for the app - fixed incorrect shared icons behaviour - fixed interlocked operations logic - fixed caching behaviour - fixed internal bugs v3.3.2 Beta (23 April 2021) - added half an hour timer - added missing spinlocks - fixed file write operation can cause crash - fixed path unexpand does not worked - fixed running log viewer - fixed little memory leak - fixed bugs v3.3.1 Beta (16 April 2021) - added workaround for native paths on profile loading (issue #817) - fixed net events does not subscribe on os version lower than 1607 v3.3 Beta (15 April 2021) - added option for tray icon to open window in single click - added warning message for allowing service host - added quic service for internal rules (issue #819) - added multiple rules at once in rules editor - added properties dialog for apps - added index column for logs - added sorting for logs - do not mark apps as unused if it applied for rules - set limit for rules popup menu (issue #692) - increased speed of service enumeration - removed notification ignore button - use threadpool for timers - improved multi-monitor support - improved listviews highlighting - improved file dialogs - fixed rule window does not display rule length limitation (issue #867) - fixed update period timestamp does not set correctly (issue #745) - fixed crash when user uses ipv6 range in rules (issue #822) - fixed support filesystems with custom driver (issue #817) - fixed blank notification window (issue #775) - fixed dependencies load flags for win10rs1+ - fixed crash on app startup (issue #775) - updated project sdk - cosmetic fixes - fixed bugs v3.2.4 (5 September 2020) - removed assertion from release builds (issue #764) - removed user service instance from the list (win10+) - fixed parsing not existing apps (issue #732, #739) - displays incorrect name on timer expiration - check app timer expiration on profile load - incorrect read-only rules tooltip markup - create filter does not report errors - fixed checking of file attributes - fixed parsing ip/port ranges - cosmetic fixes - fixed bugs v3.2.3 (25 August 2020) - added ncsi system rule (issue #709) - added command line mutex checking (issue #750) - added noficitation window redraw (issue #731) - use logical sorting order (issue #735) - check for provider status before create filters - do not highlight connections in log tab - fixed support oldest win7 versions (issue #737) - removed listview empty markup - cosmetic fixes - fixed bugs v3.2.2 (29 July 2020) - user rules broken with 3.2.1 (issue #729) v3.2.1 (29 July 2020) - added Enable silent-mode when full screen app in foreground option - added error message for createprocess failure (issue #720) - highlighting valid connections in network tab - changed "Disabled apps" group title into "Apps without internet access" - skip uac warning does not worked (issue #724) - notification window localized in english only - revert ip version selection ipv4/ipv6 in rules editor (issue #723) - revert expand rules in tooltip (issue #723) - revert "recommended" tag (fix #719) - fixed bugs v3.2 Beta (18 July 2020) - new rules editor - added option "IsInternalRulesDisabled" for completely disable internal rules (issue #630) - added temporary filtering mode whether is active until reboot (issue #576) - added packets logging interface (issue #672) - added tile view for listview - added information for export profile failure (issue #707) - improved tooltips details for apps and rules - improved listview resizing performance - changed "Enabled apps" group title into "Apps with internet access" - now highlight app with user rules only when user rules group is disabled - removed compatibility with v2 profile databases - removed special group for rules - removed user id from title - fixed local network connection treats as valid network connection (issue #579) - fixed notification window will bring focus to it's parent window (issue #668) - fixed "/uninstall" argument does not removing filters (issue #645) - fixed wfp engine security violation (issue #680) - fixed support custom windows themes (issue #701) - fixed getting uwp app paths and timestamps - fixed dpi support (issue #693) - fixed internal upnp rule - fixed bugs v3.1.2 (26 March 2020) - reverted disable windows firewall on startup (issue #559 and #562) - fixed application cannot be started because of continuously restart - fixed possible duplicate apps entries with short path (issue #640) - fixed network alert steals the focus (issue #637) - fixed network paths parsing (issue #629) - fixed netbios direction (issue #636) - fixed localization (issue #607) - fixed bugs v3.1.1 (27 February 2020) - fixed displaying tooltips for non-existing apps in network tab (issue #422) - fixed wsl apps do not display names in the network tab (issue #606) - fixed incorrect default locale name on some systems (issue #621) - fixed process mitigation policy (win10rs2+) (issue #611) - fixed persistent dark theme (win10rs5+) (issue #609) - fixed update window does not close (issue #616) - fixed log cleanup (issue #613) - updated blocklist - fixed bugs v3.1 (8 February 2020) - changed compiler build settings - changed settings interface - improved windows 10 1903+ suppport - show log cleanup confirmation only when it has entries - fixed notification tabstop processing (issue #497) by @flipkick - fixed downloading updates progress gets stuck (issue #568) - fixed find dialog does not worked correctly (issue #511) - fixed drawing filename in notification (issue #595) - fixed adjust privileges (theoretically fixes #596) - fixed inbound direction recognition (issue #581) - fixed search for next/active notification - fixed notification hotkeys (issue #597) - fixed memory duplicate allocation - updated project sdk (routine++) - updated ports definitions - updated blocklist - fixed bugs v3.0.9 (15 November 2019) - do not set notification to top when fullscreen apps working - fixed disable notifications for app from notification (issue #563) - fixed crash on system settings changing (issue #552) - fixed winhttp encoding conversion (issue #568) - fixed statusbar glitch (issue #569) - updated blocklist - fixed bugs v3.0.8 (8 November 2019) - removed disable windows firewall on startup (issue #554) - updated default timer values (issue #340) - fixed non-default system dpi (issue #544) - fixed overwrite notifications - fixed crash (issue #552) - cosmetics fixes - fixed bugs v3.0.7 (1 November 2019) - improved dpi support (win81+) - fixed ended timer handling on restart - fixed regular update message (issue #543) - fixed components update installation - fixed window and listview sizing - updated project sdk - updated blocklist - cosmetics fixes - fixed bugs v3.0.6 RC (12 October 2019) - added windows 10 1903+ support - added csv file title (clear the log to see changes) - disable network address resolution in network tab by default (issue #515) - improved refreshing filters on device connecting - improved network monitoring speed and ui - improved notification ui - improved dpi support (win81+) - fixed collecting services & uwp information - fixed device names resolution (issue #529) - fixed toolbar gray text draw (issue #437) - fixed network items blinking on refresh - fixed flickering on window resizing - fixed notification windows refresh - fixed hostname restricted symbols - fixed wfp security attributes - fixed highlighting priority - fixed memory leak - updated system rules - cosmetics fixes - fixed bugs v3.0.5 RC (6 August 2019) - added option to block outbound connections globally - added close connection feature (issue #506) - added powerful blocklist configuration - removed listen layer - skip saving default rules configuration - fixed connections port byte order (issue #504) - fixed user rules ui bug (issue #500) - fixed dropped packets log layout - fixed internal rules editor - fixed ipv6 rule formatting (issue #475) - fixed connections hashing - listview menu cosmetics - cosmetics fixes - fixed bugs v3.0.4 RC (23 July 2019) - added rules and blocklist options into main menu - set security settings enabled by default - set protocol names based on IEEE - made correct backups for profile on reset - bring notification window to top - correct determine connections for apps - fixed error message on new device insertion (issue #215) - fixed missing connections (issue #423) - fixed listview sorting does not save state sometimes - fixed listview sorting compare checked items - fixed uninstaller does not remove new profile - fixed tray menu notifications cosmetics - optimized group items counting - optimized listview sorting - cosmetics fixes - fixed bugs v3.0.3 Beta (3 July 2019) - added option to show notification window on tray - added highlighting for network tab - redraw app item on connection change - remove "beta" mark from network tab - improved wfp transactions - fixed ipv6 rules port parsing for system rules (issue #475) - fixed direction case for log and notification (issue #474) - fixed notification action adds timer (issue #472) - fixed timer set does not work (issue #484) - fixed notification refresh when app remove - fixed configuration reset does not work - fixed menu graphics (issue #473) - fixed log stack cleanup - updated port service names - cosmetics fixes - fixed bugs v3.0.2 Beta (22 Juny 2019) - new notification ui - allow microsoft update & microsoft apps servers by default - added information about ports into the log - moved icmp4 and icmp6 rules into custom rules - improved dropped packets log markup cosmetics - improved network monitoring speed - improved blocklist configuration - fixed saving special rules for uwp apps and services (issue #454) - fixed tray icon dissapear sometimes (issue #450) - fixed profile import does not work (issue #445) - fixed semicolons in app paths (issue #462) - fixed windows 20h1 uwp apps loading crash - fixed parsing rules with "*" - updated locales - cosmetic fixes - fixed bugs v3.0.1 Beta (22 May 2019) - new profile structure - added checking for correct xml file format before import - added service name resolution for connections - added Reverse DNS Lookup for IP - more flexible autoresizing for listview - fixed column size initialization (issue #426) - fixed apps list sorting by date (issue #412) - fixed status refreshing on timer deletion - fixed table view for rules (issue #438) - fixed connections recognition condition - fixed highlighting (issue #408) - fixed timers sets (issue #424) - fixed services icons - updated locales - cosmetic fixes - fixed bugs v3.0 Beta (7 May 2019) - dropped windows vista support - improved dpi support (ui) - moved rules list into main window - added services and uwp apps tab - added network connections monitor - fixed displaying notifications when it's disabled - fixed log file write through (issue #369) - fixed notifications safety timeout - fixed possible race conditions - fixed services path retrieve - fixed notifications cleanup - improved listview resizing - improved listview sorting - removed blacklist mode - cosmetic fixes - fixed bugs ================================================ FILE: CHANGELOGv1.md ================================================ v2.4.6 (27 March 2019) - enabled special rules group by default (issue #352) - fixed removing dropped packet items when overflow - fixed notifications crashing (issue #360) - fixed checkbox saving state (issue #355) - fixed possible memory dereferencing - fixed errors log overflow - cosmetic fixes - fixed bugs v2.4.5 (20 March 2019) - fixed user reported bugs v2.4.4 Beta (15 March 2019) - added safety timeout for notification buttons - added filename highlighting into notification window (issue #344) - fixed new notifications replacing old one (issue #299) - fixed updates installation in some cases - cosmetic fixes - fixed bugs v2.4.3 Beta (9 March 2019) - fixed filters access rights - fixed race conditions crash (issue #337) - fixed notifications locale - fixed bugs v2.4.2 Beta (5 March 2019) - fixed crash (issue #337) - updated blocklist - cosmetic fixes - fixed bugs v2.4.1 Beta (1 March 2019) - improved notifications speed - fixed rules listview sorting - fixed notification ui - cosmetic fixes - fixed bugs v2.4 Beta (21 February 2019) - new notification ui - improved transactions processing - added predefined rules (ftp, http etc) - added option to configure 6to4 redirections (it's allowed, but undocumented earlier) - added double-click for statusbar parts to make purgen faster - added option to secure installed filters - added more list view modes - fixed notifications stay visible when special rules applied for the app - fixed possible duplicate of special rules from notifications - fixed multithreading and possible race conditions - fixed duplicate filters callback on device arrival (issue #291) - fixed dropped packets csv log delimeter - fixed packages path retrieving (win8+) - replaced netsh commands by com interface - cosmetic fixes - fixed bugs v2.3.13 (3 January 2019) - added dns resolver caching - added dns resolver winsock fallback (issue #290) - avoid window flickering on window sizing - revert refresh filters on device arrival - fixed access rights for wfp provider and sublayer - fixed allocated strings dereferencing (issue #285) - fixed parsing hosnames with dashes (issue #271) - fixed localization (issue #288) - fixed bugs v2.3.12 (25 December 2018) - added (partialy) win10rs5+ dark theme (issue #248) - allow loopback connections by default for new users - fixed allocated strings dereferencing (issue #283) - cosmetic fixes - fixed bugs v2.3.11 (14 December 2018) - added "/install" argument for install filtering - added cache auto clean up (to prevent overflow) - changed minimum size of main window (issue #269) - changed installation message - increased rule parsing speed (issue #276) - memory optimization - fixed notification window appears on taskbar (regression) - fixed exclude user rules option was not working - cosmetic fixes - fixed bugs v2.3.10 (28 November 2018) - fixed old bug where incorrect rules are may accepted as filters - fixed bugs v2.3.9 (20 November 2018) - fixed resolving ip addresses may hang out net events thread (issue #256) - fixed net events subscription when option is not set - fixed protocol names - fixed bugs v2.3.8 (7 November 2018) - fixed #251 - fixed #253 v2.3.7 (5 November 2018) - fixed dropped events callback subscription on latest win10 - fixed notifications sound cannot be played in some cases - fixed fastlock race condition (critical) - cosmetic fixes - fixed bugs v2.3.6 (16 October 2018) - added purgen submenu into tray menu - added more statusbar information - set extra large icons view by default - tray menu services counting bug - fixed app with overdue timer still enabled on profile load - fixed resetting some data on profile load - fixed timer resetting on profie load - fixed listview checkboxes - cosmetic fixes - fixed bugs v2.3.5 (14 October 2018) - added extra large icons view - use correct function for netevents subscription (win10rs4+) - fixed forced cleartype font style (issue #233) - fixed possible buffer overflow - rerwritten timer engine - cosmetic fixes v2.3.4 (21 September 2018) - fixed dns system rules when dns service is stopped - fixed listen filter conditions (issue #213, #222) - fixed memory referencing bug (issue #221) - fixed massive handles leak (issue #230) - fixed thread termination - various ui fixes v2.3.3 (8 July 2018) - added system rules update feature - fixed inaccurate timeout between notifications (issue #194) - fixed fullscreen apps showstopper (issue #209) - fixed possible crash for device path resolution - fixed skipuac warnings for some machines - fixed some services path resolution - fixed saving empty rules config - fixed update engine (issue #182) - updated system rules v2.3.2 (27 Juny 2018) - added sorting by state for user rules in app context menu - increased priority for blocking user rules - fixed loading on startup (issue #75) - fixed editor apps list sorting - fixed service names displaying v2.3.1 (25 Juny 2018) - fixed loopback rules (added more reserved ip addresses) - fixed sometimes system cannot be going to sleep - fixed applying rules for services (appcrash) - fixed update sometimes cannot be installed - fixed services enumeration - fixed system rules v2.3 (19 Juny 2018) - added allowed connections monitoring in dropped packets log (win8+) - added inbound multicast and broadcast connections logging (win8+) - added outbound redirection filter layer (win7+) - added separation for remote/local address/port in rules editor - added hotkeys for import/export profile - added win10 rs5 support - prevent memory overflow for singly linked lists (win7+) (issue #193) - do not load icons for processes if icons displaying are disabled - improved multiple rules applying speed in settings window - increased time limit for displaying same notification (win7+) - search loading dlls in system directories only (safety) - check for correct xml data type before loading - store last notification timestamp for apps - removed proxy support (win8+) - fixed dropped events callback crash (win7+) - fixed applying services filters - fixed alphanumeric sorting - improved port scanning defense - improved loopback connections - improved boot-time filters - stability improvements - cleanup xml atributes - updated system rules - cosmetics fixes - fixed ui bugs - fixed bugs v2.2.12 (6 Juny 2018) - added win10 rs4 support v2.2.11 (6 Juny 2018) - fixed double race condition lock (critical) v2.2.10 (6 Juny 2018) - added feature to disable special rules group (issue #181) - revert special rules highlighting - fixed listview focusing (issue #164) - fixed switching modes - fixed reported bugs - code cleanup - fixed bugs v2.2.9 (5 Juny 2018) - added exclude custom rules from notifications feature (issue #177) - fixed app does not change group when special rule was removed - fixed sometimes netevents cannot be unsubcribed - fixed ipv6 addresses loopbacks - fixed thread event synchronization - fixed special rules group sorting - cosmetics fixes - fixed bugs v2.2.8 RC (21 May 2018) - fixed device changes notifications (issue #128) - fixed fullscreen apps loses focus (issue #178) - fixed saving new rules (issue #179) - fixed loopback condition flag - code cleanup v2.2.7 RC (13 May 2018) - removed search feature (do not used by anyone) - stability improvements - fixed loopback blocking (adobe software now working well when you enable loopback connections) - fixed singly linked list structure alignment for 32-bit - fixed timers does not applied from notification window (issue #172) - fixed apps does not change sorting sometimes - fixed apps does not change group sometimes - fixed bugs v2.2.6 RC (11 May 2018) - fixed special rules does not change apps group - fixed notifications indexing - fixed notifications icon redraw - fixed another dns caching - fixed ui bugs - fixed bugs v2.2.5 Beta (4 May 2018) - fixed saving profile on manual apps state changing - fixed some untranslated strings - fixed installer/uninstaller - fixed rules checkboxes - fixed ui bugs - fixed bugs v2.2.4 Beta (3 May 2018) - now simplewall install filters fastest than Manco pulls out his revolver - reworked update engine, now it check all components updates automatically - sort rules alphabeticaly - fixed threads priority race condition - fixed applying filters without pause - fixed dns caching (issue #153) - fixed ui bugs - fixed bugs v2.2.3 Beta (16 April 2018) - added drop settings to default feature - changed log format to csv (comma-separated values) table - changed install/uninstall filters button icon - notifications: instant timer applying in notification window - notifications: cosmetics ui (issue #150) - notifications: restored "disable notifications for this app" button - notifications: fixed notification buttons behavior - notifications: removed timeout threshold - changed current locale version calculation method (more precision) - removed special rules highlighting (they have own group for it) - updated to the latest pugixml 1.9 - cosmetics update engine - fixed ui bugs - fixed bugs v2.2.2 Beta (26 March 2018) - new update engine - show full app paths in notifications when "show filenames only" is unchecked - added grouping for apps with user rules - added opening file properties feature - cosmetics for the notification ui (issue #146) - cosmetics for the apps menu - fixed installer who does not removing profile backups - fixed signature of apps cannot be checked at startup - fixed dns resolution in some cases (issue #127) - fixed various memory leaks because of icons resources - fixed ui bugs - fixed bugs v2.2.1 Beta (14 March 2018) - instant apps list sorting - notifications: added information about blocked protocol - notifications: replaced "disable notifications for this app" icon - notifications: changed default timeout between same notifications - notifications: tray popup sometimes won't shown on some systems - notifications: ignore button combined with block button - notifications: changed texts for remote/local addresses - timer does not removed when user manually uncheck apps - removed font boldening for itself (issue #135) - changed minimal width of main window - fixed timers formatting - fixed ui bugs - fixed bugs v2.2 Beta (4 March 2018) - new notification ui - now simplewall added to the apps list automatically (issue #106) - added windows services support [beta] (issue #88) - added profile timestamping - new localization engine (single .lng file) - more sensitive notifications (issue #107) - lock-free dropped events callback (win7+) - added group total items count indication - added block action for notifications (issue #123) - automatic profile backup (issue #110) - added network address resolution - make internal apps undeletable - menu bitmap transparent icons - app paths case correction - added timers (issue #96) - set process high priority - ipsec dropped packets logging (win8+) - removed wow64 redirection (use simplewall 64-bit binaries for win64) - revert "purge unused apps" feature - optimized apps types recognition - improved tray context menu (issue #103) - improved memory allocation - changed verify signatures algorithm (issue #94) - changed "purge invalid apps" hotkey - changed default font - cosmetics for filter names - cosmetic fixes (issue #108) - stability improvements - updated default colors - updated localization - fixed dropped events callback failure (win10 rs3 and above) - fixed steal focus at startup and when notification displaying - fixed working under blacklist mode - fixed multi-monitor support - fixed ui bugs - fixed bugs v2.1.4 (27 November 2017) - do not verify signatures for store apps (win8+) - optimized digital signatures verification (issue #94) - fixed appcontainers listing (removed firewallapi.dll dependence) (win8+) (issue #104) - fixed notifications race conditions (it may fix issue #73) - fixed status does not changed when app deleted - fixed "system" process marked as pico - updated blocklist - code cleanup - fixed bugs v2.1.3 (22 November 2017) - disabled loopback and digital signatures config by default - fixed displaying name of store apps (win8+) (issue #98) - fixed network paths rules (issue #102) v2.1.2 RC (21 November 2017) - added option to disable apps signature checking - set selected apps when you are open rules editor from main window - reworked special rules (minimized memory usage and speed improvements, also removed limit in apps selection for special rules) - removed ocsp signature verification (issue #94) - improved apps version receiving - renamed "filters" into "rules" - fixed various rules editor crashes (issue #89) - fixed notifications race conditions (it may fix issue #73) - fixed blocklist incorrect check state - fixed restoring after hibernation - updated localization - fixed ui bugs - fixed bugs v2.1.1 Beta (17 November 2017) - reworked filter settings page - added option to disable hosts support for rules - added option to load blocklist extra rules - cosmetic fixes for ipv6 address format - fixed dns resolutions where it does not required (issue #94) - fixed various rules editor crashes (issue #89) - fixed windows store icon destroying - removed filters configuration from menu (use settings dialog instead) - removed internal rules files from distro - updated internal rules - updated localization - fixed ui bugs - fixed bugs v2.1 Beta (12 November 2017) - added windows store apps support (win8+) - revert allowing loopback connection feature - converted log limit unit to kilobytes - dropped packets log cosmetic fixes - improved confirmation dialogs - updated localization - fixed settings will not be applied for main menu - fixed displaying icons for some processes - fixed rules editor crash (issue #89) - fixed color items reorganization - fixed ui bugs - fixed bugs v2.0.20 (6 November 2017) - now custom rules will overwrite system rules - added warning message for listen connections option - apply filters on demand in settings dialog - added port support for ip ranges - removed rules configuration from menu (use settings dialog instead) - fixed rule apps does not saved when checkbox are checked - fixed rule generation from notification window - fixed listen connections does not blocked - fixed highlighting special rules for apps - fixed running under non-admin account - fixed skip-uac working directory - fixed listview sorting - fixed ui bugs - fixed bugs v2.0.19 (1 November 2017) - new rules editor ui - added highlighting rules with errors - automatically sorting rules after changing - added feature to set custom dns ipv4 server ("DnsServerV4" in .ini) - added option to exclude blocklist rules from notifications - show process information in statusbar on menu item hover - optimized signature information retrieving from binaries - updated localization - fixed saving profile in some cases - fixed parsing rules types (issue #70) - fixed dns queries - fixed ui bugs - fixed bugs v2.0.18 (20 October 2017) - added setting to disable proxy support (win8+) - prevent notifications duplicate - fixed windows firewall disabling on win10 - fixed notifications sound configuration does not saved - fixed notifications sound does not played on some systems - cosmetic fixes about notifications cross button - updated localization - updated blocklist - fixed dpi support - fixed ui bugs v2.0.17 (12 October 2017) - clear notifications cache on apply filters and configuration - show more address information on notification window tooltip - fixed redraw listview after notification actions - fixed ui hangouts for a long time sometimes - fixed race conditions - fixed ui bugs - fixed bugs v2.0.16 (6 October 2017) - fixed internal rules configuration saving v2.0.15 (6 October 2017) - make current settings backup before import - changed default listview font - fixed settings listview groups does not changed immediately - fixed notification window display at startup - fixed uninstaller do not removed some files v2.0.14 (5 October 2017) - apply settings on demand (too much faster) - revert listen connections blocking feature (request) - set font also for settings lists - revert forgotten rules editor button - updated localization - fixed ui bugs v2.0.13 (4 October 2017) - new settings ui - fixed settings reset on device arrival - fixed colors configuration checkboxes v2.0.12 RC (3 October 2017) - use colors and tooltip for notification icon same as in main window - do not show notifications on tray hover when it is disabled - do not bring notifications window into the foreground when it shows - revert error log tray menu - fixed network paths detection - fixed displaying non interesting errors - fixed some device path conversions - fixed notifications cleanup - updated localization - fixed ui bugs v2.0.11 Beta (30 September 2017) - subscribe for net events only when filters are installed (win7+) - fixed incorrect filters applied for special rules - fixed all apps are in lowercase v2.0.10 Beta (29 September 2017) - added selection counting for remove items dialog - show signature information in notification app icon tooltip - show exit confirmation dialog when filters are installing - set low-limit for notification timeout - revert forgotten privelege (regression) - fixed filters for non existing paths (regression) - fixed string case for cyrillic symbols - fixed filters thread - fixed minimize button - fixed ui bugs - fixed bugs v2.0.9 Beta (25 September 2017) - improved notifications cleanup - revert processes icons - fixed nt path conversions (regression) - fixed notification ui display timeout - fixed ui bugs - fixed bugs v2.0.8 Beta (21 September 2017) - new logo - changed minimal size of main window - updated notification ui - updated icons pack - updated blocklist - fixed font quality (use cleartype ever) - fixed notifications sound - fixed bugs v2.0.7 Beta (14 September 2017) - added count marks for all groups - added font selection for listview - prefer "blocklist_full.xml" parsing if it's presented - improved signatures checking - optimized listview redraw items - optimized listview autosizing columns - disable retrieving icon handle for network paths for notification dialog - changed default listview colors - optimized loading speed - code cleanup - fixed ui hanging in some cases - fixed bugs v2.0.6 Beta (11 September 2017) - added signature checking for apps - added set default language as in system - changed default listview colors - updated project sdk - fixed allowed apps cannot recieve any data from network (when stealth-mode enabled) - fixed retrieving nt path for reparse point files (issue #59) - fixed update checking not working on some systems - fixed bugs v2.0.5 Beta (30 August 2017) - added proxy support (win8+) - added indication for inbound connections for all (when stealth-mode enabled) - added group for special rules (rules applied for apps) - added apps list selection indication - changed experimental settings mark into "for experts only" - removed process list menu icons - improved retrieving file path by handle - improved notifications ui - updated project sdk - fixed ui bugs - fixed bugs v2.0.4 Beta (23 August 2017) - added grouping for rules - removed listen connections blocking feature - improved import/export xml database - fixed open rules editor action in main window - fixed crash on delete rules - fixed ui bugs - fixed bugs v2.0.3 Beta (17 August 2017) - added import/export applications list feature - added mode selection into installation dialog - added tooltips into the notifications ui - added remembering collapsed state for the listview groups - increased internal rules loading speed (please update blocklist.xml and rules_system.xml to latest versions) - increased rules list icons size - changed default sorting configuration - fixed notifications ui logic - fixed filters installation state flag - fixed support some domains - fixed carriage return type for rules_system.xml - fixed thread spinlock - updated localization - updated project sdk - updated blocklist - fixed bugs v2.0.2 Beta (7 August 2017) - fixed incorrect vector index v2.0.1 Beta (7 August 2017) - added update checking for new beta version - added flush dns cache after filters applied - set max prefix length for ipv6 addresses to 64 - new rules editor interface - changed minimum width for a main window - fixed running with "/minimized" argument under uac - updated localization - fixed bugs v2.0 Beta (1 August 2017) - new notification ui - show notifications only for whitelist mode - allow listen connections for all is enabled by default - added import custom rules from file feature - added support to load large xml files - added more information into the main window - added apps grouping (allowed/blocked) - added custom rules syntax checking - added support dns resolution for custom rules - added resolving shortcut path - added notification display timeout config - save internal rules configuration into xml - purgen remove only apps with errors - minimized dropped packets log size (union remote and local address information) - minimized memory usage - removed "trust no one" mode - updated system rules - updated blocklist - fixed dropped packets logging hibernation (win7+) - fixed remember windows size and position sometimes - fixed version string trimming - fixed ui bugs - fixed memory leaks - fixed bugs v1.6.5 (1 June 2017) - do not block listen connections on stealth-mode - do not block listen connections on boot-time - fixed dropped events does not shutdown on exit (win7+) - fixed memory leak v1.6.4 (31 May 2017) - added fallback if blocklist and/or system rules not found - added more dropped events logging (win7+) - fixed dropped events subscription duplicate (win7+) - fixed run as admin does not work sometimes - updated blocklist - fixed bugs v1.6.3 (27 May 2017) - generate unique session key at startup - fixed custom app rules crash on delete - fixed lookup account sid length mismatch - fixed dropped packets logging crash (win7+) - stability improvements - updated system rules - fixed bugs v1.6.2 (24 May 2017) - create filter even if file doesn't exists (drive must be mounted) - allow inbound & listen traffic only if stealth-mode does not enabled - added required rules for the ipv6 stack to work properly - stealth-mode marked as experimental - fixed com library initialization (again!) - fixed stealth-mode - fixed bugs v1.6.1 (23 May 2017) - added username and domain information to the window title - added configuration refresh on user logon - removed static wfp session key (request) - fixed com library initialization - fixed incorrect return value on file not found error v1.6 (19 May 2017) - added stealth-mode (to prevent udp/tcp port scanning) - added acl (access control list) to the engine - added gridline for the listview config - added item into the custom rules menu for open rules editor - added version-independent network events api call (win7+) - added dropped packets log file size limit to 1mb (win7+) - reset windows firewall to its initial state when restore it back - blocklist marked as experimental - removed custom rules from package - fixed dropped packets logging stop sometimes (win7+) - fixed removing custom rules - fixed classic ui - fixed bugs - ui fixes v1.5.5 (6 May 2017) - added installer - added static wfp session key - copy filter name if description is not available for dropped packets log - removed "file not found" xml parsing errors - revert trim rules back (request) - fixed index flag cannot be set (win8+) - fixed ui bugs v1.5.4 (30 April 2017) - trim executable version string - fixed filters uninstallation - fixed duplicate update checking - fixed bugs v1.5.3 (27 April 2017) - fixed restoring windows firewall state - fixed incorrect window size at startup sometimes v1.5.2 (27 April 2017) - fixed dropped packets log spinlock cannot be unlocked (critical) - fixed displaying "file not found" errors - restore listview selection after application delete - disable main button on filters installation - improved shutting down windows firewall feature - removed unnecessary whitespace trims - optimized window resizing - updated to the latest sdk - fixed bugs v1.5.1 (17 April 2017) - added remember window position and size feature - added "enable errors notifications" config - added f11 hotkey for maximize window - disable wow64 filesystem redirection - changed error log notification text - fixed possible memory leak v1.5 (15 April 2017) - added index flag to the filters, to help enable faster lookup during classification (win8+) - added app container loopback traffic permission (win8+) - added "allow listen connections for all" config - added loopback indication for dropped packets log - copy real path instead display path on copy command in main window listview - do not show dropped packets notifications when filters are not installed - if boot-time filters enabled then apply system rules for boot-time too - custom rules for apps does not saved sometimes - removed running without admin rights feature - changed notification about errors logic - changed alt+f4 behaviour (request) - cosmetic fixes for tooltips - fixed disabling windows firewall on some systems - fixed settings tabstop doesn't work - fixed incorrect listview icons for some apps - fixed process list some apps have no icons - fixed possible duplicate filters - fixed purge unused apps - stability improvements - updated translations - updated system rules - updated pugixml - fixed bugs v1.4.6 (5 April 2017) - added write error logs into a file feature - fixed process list does not recognize pico applications on win10 - updated translations - fixed bugs v1.4.5 (4 April 2017) - added pico support (subsystem for unix-based applications) for win10 - added l2tp/ipsec for system rules - added localhost for custom rules - fixed access denied for some self protected applications (like "ekrn.exe" for nod32) v1.4.4 (28 March 2017) - added ipsec connections monitoring into the log (win8+) - cosmetic fixes about tray notifications - fixed dropped packets callback crash (critical) - fixed displaying tray notifications on win10 - fixed possible duplicate filters v1.4.3 (27 March 2017) - added provider information into the log/notifications - added displaying error messages on filters configuration via tray popup - fixed link processing in settings window - cosmetic changes about debug error messages - removed "nlatunicast" flag from loopback permissions - updated blocklist - code cleanup v1.4.2 (19 February 2017) - added hints to rules pages - fixed filter creation for nonexistent apps (critical) - fixed resource definition - fixed purge unused apps - cosmetic changes about rules tooltip v1.4.1 (4 February 2017) - fixed suspended drop event callback (critical) - fixed suspended apply filters thread (critical) - fixed purge unused apps v1.4.0 (31 January 2017) * revert original project name - added mode changing confirmation - added reading information about "System" process - added protocol and version (ports only) option into the rules editor - added blocklist editor (set it "on" or "off" only) - added custom rules applying to the apps feature - added "show filenames only" option - added icon indication for rules - added loopback permission for "trust no one" mode - moved system rules into the "rules_system.xml" file - clear log even if logging to a file is not enabled - do not load information about apps from shared resources - fixed profile not saved if filters is not installed - removed tray balloon tips on filters changing - boot-time filters marked as experimental - improved working under uac (no rights) - improved system apps detection - cosmetic fixes in process list - cosmetic fixes in apps tooltip - fixed race conditions - updated translation - updated blocklist - updated ui - fixed bugs v1.3.7 (21 November 2016) - fixed special rules crash on apply settings - fixed special rules reinitialization in main menu/tray menu - updated translation v1.3.6 (20 November 2016) - added loopback permission for boot-time filters - added ip:port syntax for special rules - added default values for new special rules - fixed restore listview selection - fixed special rules crash on delete item - fixed log path unexpand environment strings v1.3.5 (17 November 2016) - fixed configuration saving (critical) - fixed xml saving (critical) v1.3.3 (14 November 2016) - added boot-time filters for prevent data leak during system startup, even before "Base Filtering Engine" (BFE) service starts - added "purge unused applications" feature - added "hide icons" feature - added documentation for rules editor and filter page - added special rules to main menu/tray menu - fixed multi-select configuration in listview - fixed system imagelist destroying - fixed dropped packets filters decription empty sometimes - fixed find dialog crash - removed inbound events logging for some reason - updated translation - updated pugixml v1.3.2 (29 October 2016) - added domain\username indication to log events - added filter name to log events - added ip/port range support for rules - combined ip and port rules settings page - added save checkbox state on install/delete message - added listen loopback permission - added inbound events logging - set xml load encoding to auto - improved logic for detect incorrect applications - listview empty text indication doesn't changed at locale change - changed default log parameters for "system" & "svchost.exe" - fixed inbound ip doesn't affected in applied rules - changed default color for silent applications - removed output log into debug log feature - improved open/save file dialog flags - optimized log callback - updated blocklist - updated translation - minor improvements v1.3.1 (21 October 2016) - added option to set application for open log file - added option to exclude application from log - added option for disable notification sound - added middle click on tray icon now open log file - added empty listview text indication - added rules highlighting - added usage examples to rules.xml - reorganized log settings - fixed unit of time for notification timeout had in minutes (instead seconds) - fixed special rules saved twice - fixed skip user account control not worked - fixed special rules saved empty when filters not installed - fixed system rules cannot be unchecked automatically - changed auto byte order mask for xml load/save - replaced QueryFullProcessImageName to NtQueryInformationProcess - stability improvements - updated translation - ui improvements v1.3 (15 October 2016) - disable/enable windows firewall on filters installation/deletion - normalize nt paths for dropped packets callback - exclude "svchost.exe" & "system" from log configuration - abbility to show/clear log - resize support as in alpha builds - hotkeys for menu items - PathUnExpandEnvStrings for log path - confirmation settings for exit/deleting application/log clear - changed message boxes style - changed default color for invalid applications - fixed access denied for some processes - config doesn't saved if user don't trigger apply filters - improved windows firewall control - stability improvements - updated translation v1.2.118 (5 October 2016) - fixed crash on filters installation - save sort order into profile (regression) - unable to clear log path config - stability improvements - updated translation v1.2.117 (4 October 2016) * changed ui by IAEA safety standards (issue #2) - added logging configuration - now filters disabled by default - inbound ports doesn't blocked for special rules - updated translation - minor improvements v1.1.116 (30 September 2016) - added "listen" layer blocking - added forgotten rules into settings menu - added open folder by double click for listview - added shared resources highlighting - dropped packets logging optimizations - fixed process list menu icons with classic ui - updated translation - minor improvements v1.1.115 (22 September 2016) - added more information to dropped packets logging (win7+) - fixed inbound dont't blocking - cannot add port in rules editor - updated translation v1.1.114 (21 September 2016) - rules in settings dialog cannot be saved v1.1.113 (20 September 2016) - fixed cannot delete application from list bug - fixed default values for settings - filters for services do not set - fixed dhcpv6 ports configuration - fixed windows firewall configuration - updated translation - fixed bugs v1.1.112 (19 September 2016) * project renamed - added "trust no one" mode - added dropped packets logging to debugview (win7+) - added automatic rules applying on insert device - added name for filters - moved telemetry rules to the resources - rewritten rules editor - improved classic ui config - fixed tray tooltip visibility - decreased ballon tips v1.0.101 (7 September 2016) - added outbound connections configuration for rules - added color configuration - changed weight for sublayer - removed startup popup notification - updated translation v1.0.100 (30 August 2016) - added individual applicaiton rules - added highlight for invalid items - added icons for process popup menu - rewritten process retrieving code (fixed many bugs) - restored "Refresh" listview feature - prevent for duplicate filters on some configurations - unlocked application layer configuration in "for all (global)" rules - loaded default rules on initilize settings - updated translation - fixed bugs v1.0.99 (25 August 2016) - added windows update and http protocol allow rule - blocking list editor context menu does not showed - blocking list editor first item cannot be edited - fix rules checkbox displaying in settings window - rules re-grouped by OSI model - changed listview custom draw - updated translation - updated ui v1.0.98b (22 August 2016) - added ballon tip on remove filters - changed default rules for all - changed default rules for allowed v1.0.96b (21 August 2016) - settings improvements - fixed duplicate popup on startup - cleanup code/resources - updated translation v1.0.94b (20 August 2016) - updated translation - removed excess tray popups - filters not applied when firewall started manually - tray icon does not change on firewall enable - improved block list editor v1.0.90b (19 August 2016) - now compiled with "treat warnings as error" parameter - added global rules configuration - added "disable windows firewall" param - added balloon tips param - started localization - fixed buffer overflow on remove filters - finished blocking list editor - removed duplicate filters - fixed memory leaks on change window icon - ui improvements - now checking updates worked - fixed statusbar redraw forgotten - updated translation - ui fixes v1.0.81a (18 August 2016) - added indication allowed/blocked item count - added edit blocking list support - added loopback configuration into profile - fixed profile mask set to default at startup - improved profile configuration dialog v1.0.79a (17 August 2016) - added tooltips - inbound traffic not blocked sometimes v1.0.77a (16 August 2016) - added profiles for applications - added more hotkeys - find now worked - increased startup speed (moved filters applying function into another thread) - fixed ntp setting - fixed memory leak - ui improvements v1.0.52a (13 August 2016) - fixed main window dpi - fixed scroll height on change icon size - removed comments/debug strings - fixed application state does not saved on check/uncheck - added "select all" (ctrl+a) hotkey - added "telemetry.xml" - ip parsing optimization (due ParseNetworkString) - ui improvements v1.0.42a (12 August 2016) - added outbound/inbound ICMP permission - auto apply filters on settings change - removed "Apply rules" button (do not need it anymore) - increased startup speed - removed process monitor - changed config defaults - ui improvements - small bug fixes v1.0.30a (11 August 2016) - added outbound loopback permission - fixed DHCP/DNS/NTP allowed for all - fixed memory leak v1.0.23a (6 August 2016) - added support to allow DHCP/DNS/NTP through svchost.exe - fixed NtOpenProcess access rights v1.0.21a (4 August 2016) - fixed uncheck item doesn't saved - previous build changes extended - removed duplicate function calling - menu fixes v1.0.18a (4 August 2016) - added internal telemetry blocking - added menu accelerators - moved process monitor to low-level - fixed provider persistency - re-fuck-to-ring v1.0.13a (2 August 2016) - added search abbility for existing application filters and show them - added tray icon indication - added find in application list feature - increased speed (due transactions) - fixed 32-bit working under 64-bit system - ui improvements v1.0.10a (30 July 2016) - fixed xml saving/parsing bug - fixed read memory access on filter enumeration v1.0.7a (29 July 2016) - added inbound loopback permission - added balloon tips on events - fixed inbound permission for allowed applications - fixed critical bug (incorrect memory address access) - common optimizations - ui improvements v1.0.4a (27 July 2016) - added icons size configuration - fixed background thread to catch applications doesn't worked - fixed v6 callout misstake - ui improvements v1.0.3a (26 July 2016) - added more settings - improved ui - removed service (do not need it anymore) v1.0.2a (26 July 2016) - first public version ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: README.md ================================================

simplewall

Definitely for advanced users.

-------

### Description: Simple tool to configure [Windows Filtering Platform (WFP)](https://docs.microsoft.com/en-us/windows/win32/fwp/windows-filtering-platform-start-page) which can configure network activity on your computer. The lightweight application is less than a megabyte, and it is compatible with Windows 7 SP1 and higher operating systems. You can download either the installer or portable version. For correct working you are require administrator rights. ### Nota bene: Keep in mind, simplewall is not a control UI over Windows Firewall, and does not interact in any level with Windows Firewall. It works over Windows Filtering Platform (WFP) which is a set of internal API and system services that provide a platform for creating network filtering applications. Windows Filtering Platform is a development technology and not a firewall itself, but simplewall is the tool that uses this technology. ### Features: - Simple interface without annoying pop ups - [Rules editor](https://github.com/henrypp/simplewall#rules-editor) (create your own rules) - [Internal blocklist](https://crazymax.dev/WindowsSpyBlocker/blocking-rules/simplewall/) (block Windows spy / telemetry) - Dropped packets information with notification and logging to a file feature (win7+) - Allowed packets information with logging to a file feature (win8+) - Windows Subsystem for Linux (WSL) support - Windows Store support (win8+) - Windows services support - Free and open source - Localization support - IPv6 support ``` To activate portable mode, create "simplewall.ini" in application folder, or move it from "%APPDATA%\Henry++\simplewall". ``` ### System requirements: - Windows 7, 8, 8.1, 10, 11 64-bit/ARM64 - An SSE2-capable CPU - KB2533623 [KB3063858](https://www.microsoft.com/en-us/download/details.aspx?id=47442) update for Windows 7 was required ### Donate: - [Bitcoin](https://www.blockchain.com/btc/address/1LrRTXPsvHcQWCNZotA9RcwjsGcRghG96c) (BTC) - [Ethereum](https://www.blockchain.com/explorer/addresses/eth/0xe2C84A62eb2a4EF154b19bec0c1c106734B95960) (ETH) - [Yandex Money](https://yoomoney.ru/to/4100115776040583) (RUB) - [Paypal](https://paypal.me/henrypp) (USD) ### GPG Signature: Binaries have GPG signature `simplewall.exe.sig` in application folder. - Public key: [pubkey.asc](https://raw.githubusercontent.com/henrypp/builder/master/pubkey.asc) ([pgpkeys.eu](https://pgpkeys.eu/pks/lookup?op=index&fingerprint=on&search=0x5635B5FD)) - Key ID: 0x5635B5FD - Fingerprint: D985 2361 1524 AB29 BE73 30AC 2881 20A7 5635 B5FD ### Reviews of idiots: [](https://alternativeto.net/software/simplewall-firewall/about/) Look at them, he does not know about [.gitmodules](https://github.com/henrypp/simplewall/blob/master/.gitmodules) and how to use, lol. PS: Without idiots we are not to be fun, yeah! ### Installation: When install rules, you can choose two modes: - Permanent rules - rules are working until you disable it manually. - Temporary rules - rules are reset after the next reboot. ### Uninstall: When you uninstall simplewall, all previously configured filters stay alive in system. To remove all filters created by simplewall, start simplewall and press "Disable filters" button. ### Command line: ~~~ -install - enable filtering. -install -temp - enable filtering until next reboot. -install -silent - enable filtering without prompt. -uninstall - remove all installed filters. ~~~ ### Rules editor: simplewall have two types of custom user rules rules: - **Global rules:** rule applied for all applications. - **Special rules:** rule applied only for specified applications. ### Rule syntax format: To set rule applications, open rule and then navigate to "Apps" tab.
Rule syntax format: --- - IP addresses `192.168.0.1; 192.168.0.1; [fc00::]` - IP addresses with port `192.168.0.1:80; 192.168.0.1:443; [fc00::]:443;` - IP ranges `192.168.0.1-192.168.0.255; 192.168.0.1-192.168.0.255;` - IP ranges (with port) `192.168.0.1-192.168.0.255:80; 192.168.0.1-192.168.0.255:443;` (v2.0.20+) - IP with prefix lengths (CIDR) `192.168.0.0/16; 192.168.0.0/24; fe80::/10` - Ports `21; 80; 443;` - Ports ranges `20-21; 49152-65534;` _To specify more than one ip, port and/or host, use semicolon._ ---
IPv4 CIDR blocks: --- | Address format | Mask | | -------- | ------- | | a.b.c.d/32 | 255.255.255.255 | | a.b.c.d/31 | 255.255.255.254 | | a.b.c.d/30 | 255.255.255.252 | | a.b.c.d/29 | 255.255.255.248 | | a.b.c.d/28 | 255.255.255.240 | | a.b.c.d/27 | 255.255.255.224 | | a.b.c.d/26 | 255.255.255.192 | | a.b.c.d/25 | 255.255.255.128 | | a.b.c.0/24 | 255.255.255.0| | a.b.c.0/23 | 255.255.254.0| | a.b.c.0/22 | 255.255.252.0| | a.b.c.0/21 | 255.255.248.0| | a.b.c.0/20 | 255.255.240.0| | a.b.c.0/19 | 255.255.224.0| | a.b.c.0/18 | 255.255.192.0| | a.b.c.0/17 | 255.255.128.0| | a.b.0.0/16 | 255.255.0.0| | a.b.0.0/15 | 255.254.0.0| | a.b.0.0/14 | 255.252.0.0| | a.b.0.0/13 | 255.248.0.0| | a.b.0.0/12 | 255.240.0.0| | a.b.0.0/11 | 255.224.0.0| | a.b.0.0/10 | 255.192.0.0| | a.b.0.0/9 | 255.128.0.0| | a.0.0.0/8 | 255.0.0.0| | a.0.0.0/7 | 254.0.0.0| | a.0.0.0/6 | 252.0.0.0| | a.0.0.0/5 | 248.0.0.0| | a.0.0.0/4 | 240.0.0.0| | a.0.0.0/3 | 224.0.0.0| | a.0.0.0/2 | 192.0.0.0| | a.0.0.0/1 | 128.0.0.0| | 0.0.0.0/0 | 0.0.0.0| ---
IPv6 CIDR blocks: --- [IPv6 CIDR blocks](https://www.mediawiki.org/wiki/Help:Range_blocks/IPv6) ---
### FAQ: #### Q: Are internet connections blocked when simplewall is not running? A: Yes. Installed filters are working even if simplewall is terminated. #### Q: What apps are blocked in default configuration? A: By default, simplewall blocks **all** applications. You do not need to create custom rules to block specific applications. #### Q: Is it safe to use simplewall with Windows Firewall? A: Yes. You do not need to disable Windows Firewall. These two firewalls work independently. #### Q: How can i disable blocklist entirely? A: Open `Settings` -> `Blocklist` and then click the radio buttons labeled `Disable`. #### Q: Where is blacklist mode? A: Blacklist was removed many days ago for uselessness. But if you need it, you can still configure it.
Solution: Configure blacklist mode in simplewall: --- 1) Open `Settings` -> `Rules` 2) Uncheck `Block outbound for all` and `Block inbound for all` options. 3) Create user rule (green cross on toolbar) with block action, any direction, `Block connection` name and empty remote and local rule. 4) You can assign this rule for apps whatever you want to block network access. ---
#### Q: Why does my network icon have an exclamation mark? A: When you are connected to a network, Windows checks for internet connectivity using Active Probing. This feature is named as NCSI (Network Connectivity Status Indicator). You can resolve this problem in one of the following ways:
Solution 1: Enable NCSI through internal system rule: --- 1) Open `System rules` tab. 2) Allow `NCSI` rule (enabled by default). ---
Solution 2: Disable NCSI through system registry: --- Create `Disable NCSI.reg` and import it into registry. ```reg Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\NetworkConnectivityStatusIndicator] "NoActiveProbe"=dword:00000001 "DisablePassivePolling"=dword:00000001 ``` ---
Solution 3: Disable NCSI through group policy: --- 1) Launch the group policy editor (`gpedit.msc` ). 2) Go to `Computer Configuration -> Administrative Templates -> System -> Internet Communication Management -> Internet Communication Settings`. 3) Double-click `Turn off Windows Network Connectivity Status Indicator active tests` and then select Enabled. Click Ok. 4) Open the Command Prompt (Admin) and enter `gpupdate /force` to enforce the changes made to the Group Policies. ---
#### Q: How can I disable Windows Firewall? Start the command line _as an administrator_, and enter the commands below.
Disable Windows Firewall profiles: --- ~~~bat netsh advfirewall set allprofiles state off ~~~ ---
Enable Windows Firewall profiles: --- ~~~bat netsh advfirewall set allprofiles state on ~~~ ---
#### Q: How can I view all filters information? Start the command line _as an administrator_, and enter the commands below.
Dump filters information saved into a `filters.xml` file: --- ~~~bat cd /d %USERPROFILE%\Desktop netsh wfp show filters ~~~ ---
Dump providers, callouts and layers information into a `wfpstate.xml` file: --- ~~~bat cd /d %USERPROFILE%\Desktop netsh wfp show state ~~~ ---
Open it in any text editor and study. #### Q: How to fix Windows Update internet access?
Windows 10 and above: --- Open main window menu `Settings` -> `Rules` -> `Allow Windows Update`.
This is working by method described [here](https://github.com/henrypp/simplewall/issues/677). ---
Windows 8.1: --- Open main window, Navigate into `System rules` tab and then enable `Windows Update service` rule. ---
#### Q: Other questions: - [Windows Security center integration (impossible)](https://stackoverflow.com/questions/3698285/how-can-i-tell-the-windows-security-center-that-im-an-antivirus/3698375#3698375) --- - Website: [github.com/henrypp](https://github.com/henrypp) - Support: sforce5@mail.ru --- (c) 2016-2026 Henry++ ================================================ FILE: VERSION ================================================ simplewall=3.8.7|https://github.com/henrypp/simplewall/releases/download/v.3.8.7/simplewall-3.8.7-setup.exe; language=1770315696|https://raw.githubusercontent.com/henrypp/simplewall/master/bin/simplewall.lng; rules_internal=1717635779|https://raw.githubusercontent.com/henrypp/simplewall/master/bin/profile_internal.sp; ================================================ FILE: bin/History.txt ================================================ v3.8.7 (8 August 2025) - fixed not logical crash (issue #2012) - fixed context menu performance - updated locale (issue #1984) - updated project sdk - cosmetic fixes v3.8.6.1 (21 May 2025) - fixed "open containing folder" error (issue #1977) - fixed crash at startup (issue #1979) - fixed crash dump (issue #1958) v3.8.6 (1 April 2025) - fixed check for update, does not bring up popup (issue #1923) - fixed memory heap error (issue #1945) - fixed possible crash - improved dark theme support v3.8.5 (27 November 2024) - fixed adding apps with drive letters instead of specific apps (issue #1887) - fixed creating rules for inaccessible paths (issue #1891) - fixed opening log with spaces path (issue #1912) - fixed windows 7 loopback rules - cosmetic fixes v3.8.4 (11 September 2024) - added listview empty markup - fixed tray icon middle click not worked when log ui is disabled - fixed notification displays invalid signature (issue #1871) - fixed does not show up tray icon (issue #1844) - fixed crash when cleanup timers (issue #1860) - fixed possible memory leak - updated project sdk - updated rule hint - cosmetic fixes v3.8.3 (8 August 2024) - added remember last position of notification window (issue #1659) - added watch services & uwp apps for install/uninstall - added displays long time for apps - improved windows 7 compatibility - improved arm64 compatibility - improved dark theme support - fixed show log button does not work as expected (issue #1757, again!) - fixed apps sometimes delete themselves (issue #1794, not fixed) - fixed duplicate process at startup (issue #1769) - fixed do not save hash when it is not enabled - fixed row colors for dark mode (issue #1767) - fixed log listview sorting by date - fixed displaying timer tooltip - updated project sdk v3.8.2 (9 May 2024) - revert back windows 7 & windows 8 support - improved dark theme support - improved log subscription - fixed show log button does not work as expected (issue #1757) - fixed search visibility v3.8.1 (27 April 2024) - fixed lacks search context (issue #1760) - fixed incorrect log ui listview item counting - updated confirm message for timers cleanup - updated confirm message for unused cleanup - updated cppwinrt package - updated project sdk v3.8 (1 April 2024) - added mitigations (win10+) (issue #611) - added dark theme support (issue #248) - fixed displaying same context menu on apps and packets log - updated search engine - updated project sdk v3.7.8 (28 January 2024) - added saving flag state for install/uninstall filters - fixed crash on tooltip (issue #1686) - fixed apps disabled removal menu - updated dropped packets (ui) listview context menu - updated project sdk v3.7.7 (3 January 2024) - added error message when loading library on subscribe - added comment item for apps/rules (issue #1664) - added recheck app hash in properies dialog - added highlighting of undelatable apps - fixed displaying incorrect error messages - fixed high disk usage (issue #1665) - updated ports list v3.7.6 (30 November 2023) - fixed configuration of windows update (issue #1648) - fixed auto update fails to install (issue #1565) - updated project sdk v3.7.5 (1 November 2023) - fixed saving services and uwp apps (issue #1616) - fixed file locked by simplewall (issue #1621) - fixed removing unused apps - fixed process creation - updated project sdk v3.7.4 (27 October 2023) - added set option to disable apps removal from profile (issue #1155) - fixed cannot save itself as unchecked (issue #1609) - fixed could not save profile (issue #1594) - fixed crash (issue #1582) - updated project sdk v3.7.3 (11 October 2023) - added error message for saving profile - removed redistributable package requirement (issue #1587) - fixed profile was not found message (issue #1557) - fixed crash on reading version information - revert back certificates checking option - updated project sdk v3.7.2 (21 September 2023) - dropped windows 7 and windows 8 support - fixed launch of several copies of the application (issue #1547) - fixed create filters for inaccessible apps (issue #1528) - fixed displaying update dialog at startup (issue #1511) - fixed retrieving version information for some files - fixed slow apps search (issue #1477) - fixed periodicaly crashing (issue #1486) - fixed retrieving some apps icons - fixed saving input on settings - fixed saving unused apps - fixed process creation - improved signature checking - updated project sdk v3.7.1 (31 July 2023) - fixed import not correcly worked (issue #1466) - fixed crash when checking files (issue #1455) - updated project sdk v3.7 (27 July 2023) - added profile encryption [oldest versions cannot open new profile] (issue #599) - added terminate process into notification window (issue #1398) - added checksum calculation for the apps (issue #394) - added error message for log subscription - improved search performance (issue #1383) - fixed timer and apps timestamp displays incorrect information (32-bit only) - fixed sometimes application displays incrorrect icons - fixed possible crash when clearing log - fixed silent uninstaller do not worked - fixed arm64 build crash (issue #1228) - fixed internal bugs - fixed memory leaks - updated nuget package - updated project sdk - updated locale v3.6.7 (21 September 2022) - added windows update service solution (issue #677, thx @taviso) [win10+] - added feature to allow only the requested ip in notification (issue #1265) - added 12 and 24 hour timer values (issue #1298) - fixed opening editor are overlapped by notification window - fixed uwp apps are reset after installing updates (issue #1294) - fixed select all with search filter selects everything (issue #1264) - fixed loading default icons for services and uwp apps - fixed check update option in main menu (issue #1309) - fixed port numbers are now verified (issue #1240) v3.6.6 (12 August 2022) - fixed editor does not disable save button when rule name is empty - fixed network monitor duplicate calls - fixed application crash (issue #1272) v3.6.5 (11 August 2022) - added group for apps with timers - display long time in packets log date column - fixed uwp packages display name parsing - fixed blank notifications (again!) (issue #1009) v3.6.4 (19 Juny 2022) - added focus assistant support (win10rs3+) - fixed notification sometimes can lose focus of fullscreen app - fixed internal profile loading crash (issue #1228) v3.6.3 (10 May 2022) - fixed installer launches simplewall without asking user (issue #1119) - fixed saving unused apps in profile (issue #1216) - fixed app crash on create process (issue ##1224) - fixed uninstaller delete not all files - improved workqueue environment - improved threading model - fixed internal bugs v3.6.2 (26 April 2022) - added autoinstall non-executable updates feature (issue #1122) - added clear search with escape button for editor - added fallback for font loading when it does not exists - improved uwp packages information loading - fixed restore properties window position - fixed rule tooltip whitespace - fixed internal bugs - updated network monitor - updated locales - cosmetic fixes v3.6.1 (11 November 2021) - added clear search with escape button - fixed crash on delete filters (issue #1084) - fixed import profile warning (issue #1086) - fixed crash dumps processing - updated locales - cosmetic fixes v3.6 (9 November 2021) - improved multi-threading safety - improved startup time - improved dpi support - added option to confirm allowing applications (issue #1070) - added filtering for the application list (issue #663) - added editor list items count mark for tab title - added wfp initialization failure workaround - added filtering for editor apps and rules - added layer name into log - moved log exclude configuration into another settings page (issue #1064) - revert notification x button (issue #973) - changed create rule toolbar icon (#723) - fixed filters with hard permit can access internet (issue #689) - fixed issue with hotkeys for switch tabs (issue #723) - fixed rebar incrorrect resizing when dpi was changed - fixed update installation issue (issue #1061) - fixed notification multi-monitor support - fixed service missing path (issue #1036) - fixed editor can cause crash (#1071) - fixed big memory leak (issue #1066) - fixed net events unsubscription - optimized listview sorting - fixed internal bugs - cosmetic fixes v3.5.3 (18 October 2021) - fixed using uninitialzed port variable in ip ranges [regression] (issue #1055) v3.5.2 (17 October 2021) - builded with windows 11 sdk - fixed port can be omited when parsing ip ranges (issue #1010) - fixed remote range replaces local range (issue #1044) - fixed interface stuck by comctl library (issue #1009) - fixed massive gdi handles leak - fixed internal bugs v3.5.1 (6 October 2021) - optimized certificate checking - fixed check apps for digital signatures option not works (issue #1037) - fixed lock to avoid duplicate file information loading - fixed crash on profile loading (issue #1033) v3.5 (4 October 2021) - in this release fqdn support was removed because of security issue (issues #1012) - improved performance due caching network resolution and file information - partially revert of windows defender power off (issue #1022) - added ballon tip to display input limitations (issue #809) - added compress internal profile in resources with lznt1 - fixed signatures information pointer use-after-free when dns resolver avoid arpa requests (issue #1008) - fixed resolve network addresses can cause crash (issue #1015) - fixed notification color issues (issue #1007) - fixed update installation (issue #1016) - fixed version information retrieval - fixed workqueue environment - fixed internal bugs v3.4.3 (30 August 2021) - added verify code signatures from catalog files (issue #1003) - fixed crash at startup (issue #995) - fixed rule reference (issue #1002) v3.4.2 (24 August 2021) - enable checking apps certificates by default - show notifications immediately without waiting for busy operations to complete - impoved listview responsiveness by using virtual listview callback - fixed packets log displays incorrect direction (issue #945) - fixed missed listview icons on refresh - fixed thread environment - fixed internal bugs - cosmetic fixes v3.4.1 (15 August 2021) - fixed blocklist can does not change action status - fixed crash at startup (issue #976) - fixed profile import compatibility - fixed install update v3.4 (11 August 2021) - added arm64 binaries (portable only) - added protocol and host name information into network alert window (issue #843) - added limit number of packets log entries (issue #941) - added host resolving for packet logger listview - added listview group for forever blocked apps - fixed loading icons of each application freezes interface (issue #830) - fixed log listview can have empty lines due to race condition - fixed ui not properly display installation status (issue #962) - fixed memory leak when loading profile (issue #888, #937) - fixed high cpu usage for packet logger (issue #949) - updated system rules - updated project sdk - fixed internal bugs v3.3.5 (5 July 2021) - added command line short opts - use guid for tray icon - updated project sdk - fixed toolbar glitch on hidpi displays (issue #950) - fixed multi-monitor with diffirent dpi support - fixed installer creates unused files - fixed internal bugs v3.3.4 (3 June 2021) - autoclean packets log ui when system suspended - fixed config may not be saved when profile directory does not exist - fixed unnecessary checking for app paths attributes - fixed threadpool does not initialized com library - fixed installer silent mode (issue #907) - updated blocklist and system rules - fixed internal bugs v3.3.3 (29 April 2021) - fixed listview tooltip can cause crash (issue #890) - fixed editor does not create filters for the app - fixed incorrect shared icons behaviour - fixed interlocked operations logic - fixed caching behaviour - fixed internal bugs v3.3.2 Beta (23 April 2021) - added half an hour timer - added missing spinlocks - fixed file write operation can cause crash - fixed path unexpand does not worked - fixed running log viewer - fixed little memory leak - fixed bugs v3.3.1 Beta (16 April 2021) - added workaround for native paths on profile loading (issue #817) - fixed net events does not subscribe on os version lower than 1607 v3.3 Beta (15 April 2021) - added option for tray icon to open window in single click - added warning message for allowing service host - added quic service for internal rules (issue #819) - added multiple rules at once in rules editor - added properties dialog for apps - added index column for logs - added sorting for logs - do not mark apps as unused if it applied for rules - set limit for rules popup menu (issue #692) - increased speed of service enumeration - removed notification ignore button - use threadpool for timers - improved multi-monitor support - improved listviews highlighting - improved file dialogs - fixed rule window does not display rule length limitation (issue #867) - fixed update period timestamp does not set correctly (issue #745) - fixed crash when user uses ipv6 range in rules (issue #822) - fixed support filesystems with custom driver (issue #817) - fixed blank notification window (issue #775) - fixed dependencies load flags for win10rs1+ - fixed crash on app startup (issue #775) - updated project sdk - cosmetic fixes - fixed bugs v3.2.4 (5 September 2020) - removed assertion from release builds (issue #764) - removed user service instance from the list (win10+) - fixed parsing not existing apps (issue #732, #739) - displays incorrect name on timer expiration - check app timer expiration on profile load - incorrect read-only rules tooltip markup - create filter does not report errors - fixed checking of file attributes - fixed parsing ip/port ranges - cosmetic fixes - fixed bugs v3.2.3 (25 August 2020) - added ncsi system rule (issue #709) - added command line mutex checking (issue #750) - added noficitation window redraw (issue #731) - use logical sorting order (issue #735) - check for provider status before create filters - do not highlight connections in log tab - fixed support oldest win7 versions (issue #737) - removed listview empty markup - cosmetic fixes - fixed bugs v3.2.2 (29 July 2020) - user rules broken with 3.2.1 (issue #729) v3.2.1 (29 July 2020) - added Enable silent-mode when full screen app in foreground option - added error message for createprocess failure (issue #720) - highlighting valid connections in network tab - changed "Disabled apps" group title into "Apps without internet access" - skip uac warning does not worked (issue #724) - notification window localized in english only - revert ip version selection ipv4/ipv6 in rules editor (issue #723) - revert expand rules in tooltip (issue #723) - revert "recommended" tag (fix #719) - fixed bugs v3.2 Beta (18 July 2020) - new rules editor - added option "IsInternalRulesDisabled" for completely disable internal rules (issue #630) - added temporary filtering mode whether is active until reboot (issue #576) - added packets logging interface (issue #672) - added tile view for listview - added information for export profile failure (issue #707) - improved tooltips details for apps and rules - improved listview resizing performance - changed "Enabled apps" group title into "Apps with internet access" - now highlight app with user rules only when user rules group is disabled - removed compatibility with v2 profile databases - removed special group for rules - removed user id from title - fixed local network connection treats as valid network connection (issue #579) - fixed notification window will bring focus to it's parent window (issue #668) - fixed "/uninstall" argument does not removing filters (issue #645) - fixed wfp engine security violation (issue #680) - fixed support custom windows themes (issue #701) - fixed getting uwp app paths and timestamps - fixed dpi support (issue #693) - fixed internal upnp rule - fixed bugs v3.1.2 (26 March 2020) - reverted disable windows firewall on startup (issue #559 and #562) - fixed application cannot be started because of continuously restart - fixed possible duplicate apps entries with short path (issue #640) - fixed network alert steals the focus (issue #637) - fixed network paths parsing (issue #629) - fixed netbios direction (issue #636) - fixed localization (issue #607) - fixed bugs v3.1.1 (27 February 2020) - fixed displaying tooltips for non-existing apps in network tab (issue #422) - fixed wsl apps do not display names in the network tab (issue #606) - fixed incorrect default locale name on some systems (issue #621) - fixed process mitigation policy (win10rs2+) (issue #611) - fixed persistent dark theme (win10rs5+) (issue #609) - fixed update window does not close (issue #616) - fixed log cleanup (issue #613) - updated blocklist - fixed bugs v3.1 (8 February 2020) - changed compiler build settings - changed settings interface - improved windows 10 1903+ suppport - show log cleanup confirmation only when it has entries - fixed notification tabstop processing (issue #497) by @flipkick - fixed downloading updates progress gets stuck (issue #568) - fixed find dialog does not worked correctly (issue #511) - fixed drawing filename in notification (issue #595) - fixed adjust privileges (theoretically fixes #596) - fixed inbound direction recognition (issue #581) - fixed search for next/active notification - fixed notification hotkeys (issue #597) - fixed memory duplicate allocation - updated project sdk (routine++) - updated ports definitions - updated blocklist - fixed bugs v3.0.9 (15 November 2019) - do not set notification to top when fullscreen apps working - fixed disable notifications for app from notification (issue #563) - fixed crash on system settings changing (issue #552) - fixed winhttp encoding conversion (issue #568) - fixed statusbar glitch (issue #569) - updated blocklist - fixed bugs v3.0.8 (8 November 2019) - removed disable windows firewall on startup (issue #554) - updated default timer values (issue #340) - fixed non-default system dpi (issue #544) - fixed overwrite notifications - fixed crash (issue #552) - cosmetics fixes - fixed bugs v3.0.7 (1 November 2019) - improved dpi support (win81+) - fixed ended timer handling on restart - fixed regular update message (issue #543) - fixed components update installation - fixed window and listview sizing - updated project sdk - updated blocklist - cosmetics fixes - fixed bugs v3.0.6 RC (12 October 2019) - added windows 10 1903+ support - added csv file title (clear the log to see changes) - disable network address resolution in network tab by default (issue #515) - improved refreshing filters on device connecting - improved network monitoring speed and ui - improved notification ui - improved dpi support (win81+) - fixed collecting services & uwp information - fixed device names resolution (issue #529) - fixed toolbar gray text draw (issue #437) - fixed network items blinking on refresh - fixed flickering on window resizing - fixed notification windows refresh - fixed hostname restricted symbols - fixed wfp security attributes - fixed highlighting priority - fixed memory leak - updated system rules - cosmetics fixes - fixed bugs v3.0.5 RC (6 August 2019) - added option to block outbound connections globally - added close connection feature (issue #506) - added powerful blocklist configuration - removed listen layer - skip saving default rules configuration - fixed connections port byte order (issue #504) - fixed user rules ui bug (issue #500) - fixed dropped packets log layout - fixed internal rules editor - fixed ipv6 rule formatting (issue #475) - fixed connections hashing - listview menu cosmetics - cosmetics fixes - fixed bugs v3.0.4 RC (23 July 2019) - added rules and blocklist options into main menu - set security settings enabled by default - set protocol names based on IEEE - made correct backups for profile on reset - bring notification window to top - correct determine connections for apps - fixed error message on new device insertion (issue #215) - fixed missing connections (issue #423) - fixed listview sorting does not save state sometimes - fixed listview sorting compare checked items - fixed uninstaller does not remove new profile - fixed tray menu notifications cosmetics - optimized group items counting - optimized listview sorting - cosmetics fixes - fixed bugs v3.0.3 Beta (3 July 2019) - added option to show notification window on tray - added highlighting for network tab - redraw app item on connection change - remove "beta" mark from network tab - improved wfp transactions - fixed ipv6 rules port parsing for system rules (issue #475) - fixed direction case for log and notification (issue #474) - fixed notification action adds timer (issue #472) - fixed timer set does not work (issue #484) - fixed notification refresh when app remove - fixed configuration reset does not work - fixed menu graphics (issue #473) - fixed log stack cleanup - updated port service names - cosmetics fixes - fixed bugs v3.0.2 Beta (22 Juny 2019) - new notification ui - allow microsoft update & microsoft apps servers by default - added information about ports into the log - moved icmp4 and icmp6 rules into custom rules - improved dropped packets log markup cosmetics - improved network monitoring speed - improved blocklist configuration - fixed saving special rules for uwp apps and services (issue #454) - fixed tray icon dissapear sometimes (issue #450) - fixed profile import does not work (issue #445) - fixed semicolons in app paths (issue #462) - fixed windows 20h1 uwp apps loading crash - fixed parsing rules with "*" - updated locales - cosmetic fixes - fixed bugs v3.0.1 Beta (22 May 2019) - new profile structure - added checking for correct xml file format before import - added service name resolution for connections - added Reverse DNS Lookup for IP - more flexible autoresizing for listview - fixed column size initialization (issue #426) - fixed apps list sorting by date (issue #412) - fixed status refreshing on timer deletion - fixed table view for rules (issue #438) - fixed connections recognition condition - fixed highlighting (issue #408) - fixed timers sets (issue #424) - fixed services icons - updated locales - cosmetic fixes - fixed bugs v3.0 Beta (7 May 2019) - dropped windows vista support - improved dpi support (ui) - moved rules list into main window - added services and uwp apps tab - added network connections monitor - fixed displaying notifications when it's disabled - fixed log file write through (issue #369) - fixed notifications safety timeout - fixed possible race conditions - fixed services path retrieve - fixed notifications cleanup - improved listview resizing - improved listview sorting - removed blacklist mode - cosmetic fixes - fixed bugs ================================================ FILE: bin/License.txt ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: bin/Readme.txt ================================================ simplewall Description: Simple tool to configure Windows Filtering Platform (WFP) which can configure network activity on your computer. The lightweight application is less than a megabyte, and it is compatible with Windows 7 SP1 and higher operating systems. You can download either the installer or portable version. For correct working you are require administrator rights. System requirements: - Windows 7, 8, 8.1, 10, 11 64-bit/ARM64 - An SSE2-capable CPU Nota bene: Keep in mind, simplewall is not a control UI over Windows Firewall, and does not interact in any level with Windows Firewall. It works over Windows Filtering Platform (WFP) which is a set of internal API and system services that provide a platform for creating network filtering applications. Windows Filtering Platform is a development technology and not a firewall itself, but simplewall is the tool that uses this technology. Command line: List of arguments for simplewall. -install - enable filtering (you can set "-silent" argument to skip prompt) -uninstall - remove all installed filters Uninstall: When you uninstall simplewall, all previously installed filters are stay alive in system. To remove all filters created by simplewall, start simplewall and press "Disable filters" button. Features: - Simple interface without annoying pop ups - Rules editor (create your own rules) - Internal blocklist rules (block Windows spy / telemetry) - Dropped packets information with notification and logging to a file feature (win7+) - Allowed packets information with logging to a file feature (win8+) - Windows Subsystem for Linux (WSL) support - Windows Store support (win8+) - Windows services support - Free and open source - Localization support - IPv6 support To activate portable mode, create "simplewall.ini" in application folder, or move it from "%APPDATA%\Henry++\simplewall". Installation: When install rules, you can choose two modes: - Permanent rules - rules are working until you disable it manually. - Temporary rules - rules are reset after the next reboot. Uninstall: When you uninstall simplewall, all previously configured filters stay alive in system. To remove all filters created by simplewall, start simplewall and press "Disable filters" button. Command line: -install - enable filtering. -install -temp - enable filtering until next reboot. -install -silent - enable filtering without prompt. -uninstall - remove all installed filters. Website: https://github.com/henrypp Support: sforce5@mail.ru (c) 2016-2026 Henry++ ================================================ FILE: bin/profile_internal.xml ================================================ ================================================ FILE: build.bat ================================================ @echo off cd ..\builder call build simplewall 3.8.7 simplewall pause ================================================ FILE: build_locale.bat ================================================ @echo off cd ..\builder call build_locale simplewall pause ================================================ FILE: build_simplewall_rules.bat ================================================ @echo off cd ..\builder call build_simplewall_rules update %~dp0bin\profile_internal.xml %~dp0bin\profile_internal.xml pause ================================================ FILE: build_vc.bat ================================================ @echo off @setlocal enableextensions rem @cd /d "%~dp0\..\" rem VS 2026 if exist "%ProgramFiles%\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsall.bat" ( call "%ProgramFiles%\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 goto start ) if exist "%ProgramFiles%\Microsoft Visual Studio\18\Professional\VC\Auxiliary\Build\vcvarsall.bat" ( call "%ProgramFiles%\Microsoft Visual Studio\18\Professional\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 goto start ) echo VS 2026 was not found... goto end :start msbuild simplewall.sln -property:Configuration=Release -property:Platform=x64 -verbosity:normal if %ERRORLEVEL% neq 0 goto end msbuild simplewall.sln -property:Configuration=Release -property:Platform=ARM64 -verbosity:normal if %ERRORLEVEL% neq 0 goto end :end echo done... pause ================================================ FILE: packages.config ================================================  ================================================ FILE: simplewall.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 VisualStudioVersion = 18.1.11312.151 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simplewall", "simplewall.vcxproj", "{7FB76828-A353-4113-82D7-CD728EED81DF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {7FB76828-A353-4113-82D7-CD728EED81DF}.Debug|ARM64.ActiveCfg = Debug|ARM64 {7FB76828-A353-4113-82D7-CD728EED81DF}.Debug|ARM64.Build.0 = Debug|ARM64 {7FB76828-A353-4113-82D7-CD728EED81DF}.Debug|x64.ActiveCfg = Debug|x64 {7FB76828-A353-4113-82D7-CD728EED81DF}.Debug|x64.Build.0 = Debug|x64 {7FB76828-A353-4113-82D7-CD728EED81DF}.Release|ARM64.ActiveCfg = Release|ARM64 {7FB76828-A353-4113-82D7-CD728EED81DF}.Release|ARM64.Build.0 = Release|ARM64 {7FB76828-A353-4113-82D7-CD728EED81DF}.Release|x64.ActiveCfg = Release|x64 {7FB76828-A353-4113-82D7-CD728EED81DF}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A433DCFD-EECB-43BE-9EB1-DC7D0094F85F} EndGlobalSection EndGlobal ================================================ FILE: simplewall.vcxproj ================================================  Debug ARM64 Release ARM64 Debug Win32 Release Win32 Debug x64 Release x64 {7FB76828-A353-4113-82D7-CD728EED81DF} simplewall simplewall 10.0 Application true Unicode v145 Application false true Unicode v145 Application true Unicode v145 Application false true Unicode v145 Application true Unicode v145 Application false true Unicode v145 $(ProjectName) $(VC_IncludePath);$(WindowsSDK_IncludePath);.\..\routine\src\;.\src\include\;.\src\ false $(Platform)\$(Configuration)\$(ProjectName)\ MixedRecommendedRules.ruleset $(SolutionDir)bin\$(PlatformArchitecture)\ $(ProjectName) $(VC_IncludePath);$(WindowsSDK_IncludePath);.\..\routine\src\;.\src\include\;.\src\ false $(Platform)\$(Configuration)\$(ProjectName)\ MixedRecommendedRules.ruleset $(SolutionDir)bin\$(PlatformArchitecture)\ $(SolutionDir)bin\$(PlatformArchitecture)\ $(ProjectName) $(VC_IncludePath);$(WindowsSDK_IncludePath);.\..\routine\src\;.\src\include\;.\src\ false $(Platform)\$(Configuration)\$(ProjectName)\ MixedRecommendedRules.ruleset $(SolutionDir)bin\$(PlatformArchitecture)\ $(ProjectName) $(VC_IncludePath);$(WindowsSDK_IncludePath);.\..\routine\src\;.\src\include\;.\src\ false $(Platform)\$(Configuration)\$(ProjectName)\ MixedRecommendedRules.ruleset $(SolutionDir)bin\$(PlatformArchitecture)\ $(ProjectName) $(VC_IncludePath);$(WindowsSDK_IncludePath);.\..\routine\src\;.\src\include\;.\src\ false $(Platform)\$(Configuration)\$(ProjectName)\ MixedRecommendedRules.ruleset $(SolutionDir)bin\$(PlatformArchitecture)\ $(ProjectName) $(VC_IncludePath);$(WindowsSDK_IncludePath);.\..\routine\src\;.\src\include\;.\src\ false $(Platform)\$(Configuration)\$(ProjectName)\ MixedRecommendedRules.ruleset Level3 Disabled true true Guard true SECURITY_WIN32;MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;APP_NO_GUEST;APP_HAVE_AUTORUN;APP_HAVE_SKIPUAC;APP_HAVE_TRAY;APP_HAVE_SETTINGS;APP_HAVE_UPDATES;%(PreprocessorDefinitions) true ProgramDatabase true stdcpplatest stdclatest true true true true true AnySuitable true true true Windows /DEPENDENTLOADFLAG:0x800 /BREPRO %(AdditionalOptions) %(DelayLoadDLLs) true _UNICODE;UNICODE;_WIN64;%(PreprocessorDefinitions) Level3 Disabled true true Guard true SECURITY_WIN32;MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS;;UNICODE;WIN32_LEAN_AND_MEAN;APP_NO_GUEST;APP_HAVE_AUTORUN;APP_HAVE_SKIPUAC;APP_HAVE_TRAY;APP_HAVE_SETTINGS;APP_HAVE_UPDATES;%(PreprocessorDefinitions) true ProgramDatabase true stdcpplatest stdclatest StdCall true StreamingSIMDExtensions2 true true true AnySuitable true true true Windows 6.1 /DEPENDENTLOADFLAG:0x800 /BREPRO %(AdditionalOptions) true %(DelayLoadDLLs) true _UNICODE;UNICODE;%(PreprocessorDefinitions) Level3 Disabled true true Guard true SECURITY_WIN32;MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;APP_NO_GUEST;APP_HAVE_AUTORUN;APP_HAVE_SKIPUAC;APP_HAVE_TRAY;APP_HAVE_SETTINGS;APP_HAVE_UPDATES;%(PreprocessorDefinitions) true ProgramDatabase true stdcpplatest stdclatest StdCall true true StreamingSIMDExtensions2 true true true AnySuitable true true true Windows /DEPENDENTLOADFLAG:0x800 /BREPRO %(AdditionalOptions) 6.1 true %(DelayLoadDLLs) true _UNICODE;UNICODE;_WIN64;%(PreprocessorDefinitions) Level3 MaxSpeed true true Guard true MultiThreaded ProgramDatabase SECURITY_WIN32;MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;APP_NO_GUEST;APP_HAVE_AUTORUN;APP_HAVE_SKIPUAC;APP_HAVE_TRAY;APP_HAVE_SETTINGS;APP_HAVE_UPDATES;NDEBUG;%(PreprocessorDefinitions) true true stdcpplatest stdclatest true true true true true AnySuitable Speed true true true true Windows /DEPENDENTLOADFLAG:0x800 /BREPRO %(AdditionalOptions) UseLinkTimeCodeGeneration %(DelayLoadDLLs) true _UNICODE;UNICODE;_WIN64;%(PreprocessorDefinitions) Level3 MaxSpeed true true Guard true MultiThreaded ProgramDatabase SECURITY_WIN32;MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;APP_NO_GUEST;APP_HAVE_AUTORUN;APP_HAVE_SKIPUAC;APP_HAVE_TRAY;APP_HAVE_SETTINGS;APP_HAVE_UPDATES;NDEBUG;%(PreprocessorDefinitions) true true stdcpplatest stdclatest StdCall true StreamingSIMDExtensions2 true true true AnySuitable Speed true true true true Windows 6.1 /DEPENDENTLOADFLAG:0x800 /BREPRO %(AdditionalOptions) true UseLinkTimeCodeGeneration %(DelayLoadDLLs) true _UNICODE;UNICODE;%(PreprocessorDefinitions) Level3 MaxSpeed true true Guard true MultiThreaded ProgramDatabase SECURITY_WIN32;MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;APP_NO_GUEST;APP_HAVE_AUTORUN;APP_HAVE_SKIPUAC;APP_HAVE_TRAY;APP_HAVE_SETTINGS;APP_HAVE_UPDATES;NDEBUG;%(PreprocessorDefinitions) true true stdcpplatest stdclatest StdCall true true StreamingSIMDExtensions2 true true true AnySuitable Speed true true true true Windows /DEPENDENTLOADFLAG:0x800 /BREPRO %(AdditionalOptions) 6.1 true UseLinkTimeCodeGeneration %(DelayLoadDLLs) true _UNICODE;UNICODE;_WIN64;%(PreprocessorDefinitions) This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. ================================================ FILE: simplewall.vcxproj.filters ================================================  {3C4265CC-2D78-44DE-BC9F-1C64FB817DA5} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {7B1ACFC7-8801-49F4-9D4D-E3CBFEC33A8D} h;hh;hpp;hxx;hm;inl;inc;xsd {0373C32A-908E-4C0A-8D5B-07C4A21C3725} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Resource Files ================================================ FILE: simplewall.vcxproj.user ================================================  $(SolutionDir)bin\$(PlatformArchitecture)\ WindowsRemoteDebugger $(SolutionDir)bin\$(PlatformArchitecture)\ WindowsRemoteDebugger $(SolutionDir)bin\$(PlatformArchitecture)\ WindowsLocalDebugger $(SolutionDir)bin\$(PlatformArchitecture)\ WindowsLocalDebugger $(SolutionDir)bin\$(PlatformArchitecture)\ WindowsLocalDebugger $(SolutionDir)bin\$(PlatformArchitecture)\ WindowsLocalDebugger ================================================ FILE: src/app.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once #define APP_NAME L"simplewall" #define APP_NAME_SHORT L"simplewall" #define APP_VERSION L"3.8.7" #define APP_VERSION_RES 3,8,7,0 #define APP_AUTHOR L"Henry++" #define APP_COPYRIGHT L"(c) 2016-2026 " APP_AUTHOR L". All Rights Reversed." ================================================ FILE: src/controls.c ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #include "global.h" VOID _app_getapptooltipstring ( _Inout_ PR_STRINGBUILDER buffer, _In_ ULONG app_hash, _In_opt_ PITEM_NETWORK ptr_network, _In_opt_ PITEM_LOG ptr_log ) { PITEM_APP_INFO ptr_app_info; R_STRINGBUILDER sb; PR_STRING path = NULL; PITEM_APP ptr_app; PR_STRING string; PR_STRING value; ptr_app = _app_getappitem (app_hash); // file path if (ptr_app) { if (ptr_app->real_path) { path = ptr_app->real_path; } else if (ptr_app->display_name) { path = ptr_app->display_name; } else { path = ptr_app->original_path; } } else if (ptr_network) { path = ptr_network->path; } else if (ptr_log) { if (ptr_log->path) path = ptr_log->path; } if (ptr_log) _r_obj_appendstringbuilderformat (buffer, L"#%d - ", _InterlockedCompareExchange (&ptr_log->log_id, 0, 0)); if (path) { _r_obj_appendstringbuilder2 (buffer, &path->sr); _r_obj_appendstringbuilder (buffer, SZ_CRLF); } // file information _r_obj_initializestringbuilder (&sb, 512); // file display name if (ptr_app) { if (ptr_app->display_name) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder2 (&sb, &ptr_app->display_name->sr); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } } // file version ptr_app_info = _app_getappinfobyhash2 (app_hash); if (ptr_app_info) { if (!_r_obj_isstringempty (ptr_app_info->version_info)) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder2 (&sb, &ptr_app_info->version_info->sr); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } } // compile if (!_r_obj_isstringempty2 (sb.string)) { string = _r_obj_concatstrings ( 2, _r_locale_getstring (IDS_FILE), L":\r\n" ); _r_obj_insertstringbuilder2 (&sb, 0, &string->sr); _r_obj_appendstringbuilder2 (buffer, &sb.string->sr); _r_obj_dereference (string); } // comment if (ptr_app) { if (!_r_obj_isstringempty (ptr_app->comment)) { string = _r_obj_concatstrings ( 2, _r_locale_getstring (IDS_COMMENT), L":\r\n" ); _r_obj_appendstringbuilder2 (buffer, &string->sr); _r_obj_appendstringbuilder (buffer, SZ_TAB); _r_obj_appendstringbuilder2 (buffer, &ptr_app->comment->sr); _r_obj_appendstringbuilder (buffer, SZ_CRLF); _r_obj_dereference (string); } } // file signature if (ptr_app_info) { if (!_r_obj_isstringempty (ptr_app_info->signature_info)) { string = _r_obj_concatstrings ( 4, _r_locale_getstring (IDS_SIGNATURE), L":\r\n" SZ_TAB, ptr_app_info->signature_info->buffer, SZ_CRLF ); _r_obj_appendstringbuilder2 (buffer, &string->sr); _r_obj_dereference (string); } } _r_obj_deletestringbuilder (&sb); // app timer if (ptr_app) { if (_app_istimerset (ptr_app)) { value = _r_format_interval (ptr_app->timer - _r_unixtime_now ()); if (value) { string = _r_obj_concatstrings ( 4, _r_locale_getstring (IDS_TIMELEFT), L":" SZ_TAB_CRLF, value->buffer, SZ_CRLF ); _r_obj_appendstringbuilder2 (buffer, &string->sr); _r_obj_dereference (string); _r_obj_dereference (value); } } } // app rules value = _app_appexpandrules (app_hash, SZ_TAB_CRLF); if (value) { string = _r_obj_concatstrings ( 4, _r_locale_getstring (IDS_RULE), L":" SZ_TAB_CRLF, value->buffer, SZ_CRLF ); _r_obj_appendstringbuilder2 (buffer, &string->sr); _r_obj_dereference (string); _r_obj_dereference (value); } // app notes if (ptr_app) { _r_obj_initializestringbuilder (&sb, 512); // app type if (ptr_app->type == DATA_APP_NETWORK) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder (&sb, _r_locale_getstring (IDS_HIGHLIGHT_NETWORK)); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } else if (ptr_app->type == DATA_APP_PICO) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder (&sb, _r_locale_getstring (IDS_HIGHLIGHT_PICO)); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } // app settings if (_app_isappfromsystem (ptr_app->real_path, app_hash)) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder (&sb, _r_locale_getstring (IDS_HIGHLIGHT_SYSTEM)); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } if (_app_network_isapphaveconnection (app_hash)) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder (&sb, _r_locale_getstring (IDS_HIGHLIGHT_CONNECTION)); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } if (ptr_app->is_silent) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder (&sb, _r_locale_getstring (IDS_HIGHLIGHT_SILENT)); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } if (ptr_app->is_undeletable) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder (&sb, _r_locale_getstring (IDS_DISABLEREMOVAL)); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } if (!_app_isappexists (ptr_app)) { _r_obj_appendstringbuilder (&sb, SZ_TAB); _r_obj_appendstringbuilder (&sb, _r_locale_getstring (IDS_HIGHLIGHT_INVALID)); _r_obj_appendstringbuilder (&sb, SZ_CRLF); } string = _r_obj_finalstringbuilder (&sb); if (!_r_obj_isstringempty2 (string)) { _r_obj_insertstringbuilder (&sb, 0, L":\r\n"); _r_obj_insertstringbuilder (&sb, 0, _r_locale_getstring (IDS_NOTES)); _r_obj_appendstringbuilder2 (buffer, &string->sr); } _r_obj_deletestringbuilder (&sb); _r_obj_dereference (ptr_app); } // show additional log information if (ptr_log) { _r_obj_appendstringbuilder (buffer, _r_locale_getstring (IDS_TITLE_ADVANCED)); _r_obj_appendstringbuilder (buffer, L":\r\n"); _r_obj_appendstringbuilder (buffer, SZ_TAB); _r_obj_appendstringbuilder (buffer, _r_locale_getstring (IDS_FILTER)); _r_obj_appendstringbuilder (buffer, L": "); if (ptr_log->filter_name) { _r_obj_appendstringbuilder2 (buffer, &ptr_log->filter_name->sr); } else { _r_obj_appendstringbuilder (buffer, _r_locale_getstring (IDS_STATUS_EMPTY)); } _r_obj_appendstringbuilder (buffer, SZ_CRLF SZ_TAB); _r_obj_appendstringbuilder (buffer, _r_locale_getstring (IDS_LAYER)); _r_obj_appendstringbuilder (buffer, L": "); if (ptr_log->layer_name) { _r_obj_appendstringbuilder2 (buffer, &ptr_log->layer_name->sr); } else { _r_obj_appendstringbuilder (buffer, _r_locale_getstring (IDS_STATUS_EMPTY)); } _r_obj_appendstringbuilder (buffer, SZ_CRLF); } } _Ret_maybenull_ PR_STRING _app_gettooltipbylparam ( _In_ HWND hwnd, _In_ INT listview_id, _In_ LONG_PTR lparam ) { R_STRINGBUILDER sb; PITEM_NETWORK ptr_network; PITEM_RULE ptr_rule; PR_STRING string1; PR_STRING string2; PITEM_LOG ptr_log; UNREFERENCED_PARAMETER (hwnd); _r_obj_initializestringbuilder (&sb, 512); switch (listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: case IDC_RULE_APPS_ID: { _app_getapptooltipstring (&sb, (ULONG)lparam, NULL, NULL); break; } case IDC_RULES_BLOCKLIST: case IDC_RULES_SYSTEM: case IDC_RULES_CUSTOM: case IDC_APP_RULES_ID: { ptr_rule = _app_getrulebyid (lparam); if (!ptr_rule) break; // rule address string1 = _app_rulesexpandrules (ptr_rule->rule_remote, SZ_CRLF SZ_TAB); string2 = _app_rulesexpandrules (ptr_rule->rule_local, SZ_CRLF SZ_TAB); _r_obj_appendstringbuilderformat ( &sb, L"%s (#%" TEXT (PR_LONG_PTR) L")\r\n%s (%s):\r\n%s%s\r\n%s (%s):\r\n%s%s", _r_obj_getstringordefault (ptr_rule->name, _r_locale_getstring (IDS_STATUS_EMPTY)), lparam, _r_locale_getstring (IDS_RULE), _r_locale_getstring (IDS_DIRECTION_REMOTE), SZ_TAB, _r_obj_getstringordefault (string1, _r_locale_getstring (IDS_STATUS_EMPTY)), _r_locale_getstring (IDS_RULE), _r_locale_getstring (IDS_DIRECTION_LOCAL), SZ_TAB, _r_obj_getstringordefault (string2, _r_locale_getstring (IDS_STATUS_EMPTY)) ); if (string1) _r_obj_dereference (string1); if (string2) _r_obj_dereference (string2); // rule apps if (ptr_rule->is_forservices || !_r_obj_isempty (ptr_rule->apps)) { string1 = _app_rulesexpandapps (ptr_rule, TRUE, SZ_TAB_CRLF); if (string1) { string2 = _r_obj_concatstrings ( 4, SZ_CRLF, _r_locale_getstring (IDS_TAB_APPS), L":\r\n" SZ_TAB, string1->buffer ); _r_obj_appendstringbuilder2 (&sb, &string2->sr); _r_obj_appendstringbuilder (&sb, SZ_CRLF); _r_obj_dereference (string1); _r_obj_dereference (string2); } } // comment if (!_r_obj_isstringempty (ptr_rule->comment)) { string1 = _r_obj_concatstrings ( 3, SZ_CRLF, _r_locale_getstring (IDS_COMMENT), L":\r\n" SZ_TAB ); _r_obj_appendstringbuilder2 (&sb, &string1->sr); _r_obj_appendstringbuilder2 (&sb, &ptr_rule->comment->sr); _r_obj_dereference (string1); } // rule notes if (ptr_rule->is_readonly && ptr_rule->type == DATA_RULE_USER) { string2 = _r_obj_concatstrings ( 4, SZ_CRLF, _r_locale_getstring (IDS_NOTES), L":\r\n" SZ_TAB, _r_locale_getstring (IDS_INTERNAL_RULE) ); _r_obj_appendstringbuilder2 (&sb, &string2->sr); _r_obj_dereference (string2); } _r_obj_dereference (ptr_rule); break; } case IDC_NETWORK: { ptr_network = _app_network_getitem ((ULONG)lparam); if (!ptr_network) break; _app_getapptooltipstring (&sb, ptr_network->app_hash, ptr_network, NULL); _r_obj_dereference (ptr_network); break; } case IDC_LOG: { ptr_log = _app_getlogitem ((ULONG)lparam); if (!ptr_log) break; _app_getapptooltipstring (&sb, ptr_log->app_hash, NULL, ptr_log); _r_obj_dereference (ptr_log); break; } } string1 = _r_obj_finalstringbuilder (&sb); if (!_r_obj_isstringempty2 (string1)) return string1; _r_obj_deletestringbuilder (&sb); return NULL; } VOID _app_settab_id ( _In_ HWND hwnd, _In_ INT page_id ) { PITEM_TAB_CONTEXT tab_context; HWND hctrl; if (!page_id) return; hctrl = GetDlgItem (hwnd, page_id); if (!hctrl) return; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context || (tab_context->listview_id == page_id && _r_wnd_isvisible (hctrl, FALSE))) return; for (INT i = 0; i < _r_tab_getitemcount (hwnd, IDC_TAB); i++) { tab_context = _app_listview_getcontext (hwnd, i); if (tab_context && tab_context->listview_id == page_id) { _r_tab_selectitem (hwnd, IDC_TAB, i); return; } } if (page_id != IDC_APPS_PROFILE) _app_settab_id (hwnd, IDC_APPS_PROFILE); } LPWSTR _app_getstateaction ( _In_ ENUM_INSTALL_TYPE install_type ) { UINT locale_id; switch (install_type) { case INSTALL_ENABLED: case INSTALL_ENABLED_TEMPORARY: { locale_id = IDS_TRAY_STOP; break; } case INSTALL_DISABLED: { locale_id = IDS_TRAY_START; break; } default: { return NULL; } } return _r_locale_getstring (locale_id); } HBITMAP _app_getstatebitmap ( _In_ ENUM_INSTALL_TYPE install_type ) { switch (install_type) { case INSTALL_ENABLED: case INSTALL_ENABLED_TEMPORARY: { return config.hbmp_disable; } case INSTALL_DISABLED: { return config.hbmp_enable; } } return NULL; } INT _app_getstateicon ( _In_ ENUM_INSTALL_TYPE install_type ) { switch (install_type) { case INSTALL_ENABLED: case INSTALL_ENABLED_TEMPORARY: { return IDI_ACTIVE; } default: { FALLTHROUGH; } } return IDI_INACTIVE; } LPCWSTR _app_getstatelocale ( _In_ ENUM_INSTALL_TYPE install_type ) { UINT locale_id; switch (install_type) { case INSTALL_ENABLED: { locale_id = IDS_STATUS_FILTERS_ACTIVE; break; } case INSTALL_ENABLED_TEMPORARY: { locale_id = IDS_STATUS_FILTERS_ACTIVE_TEMP; break; } case INSTALL_DISABLED: { locale_id = IDS_STATUS_FILTERS_INACTIVE; break; } default: { return NULL; } } return _r_locale_getstring (locale_id); } BOOLEAN _app_initinterfacestate ( _In_ HWND hwnd, _In_ BOOLEAN is_forced ) { if (is_forced || _r_toolbar_isenabled (config.hrebar, IDC_TOOLBAR, IDM_TRAY_START)) { _r_toolbar_enablebutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_START, FALSE); _r_toolbar_enablebutton (config.hrebar, IDC_TOOLBAR, IDM_REFRESH, FALSE); _r_status_settextformat (hwnd, IDC_STATUSBAR, 0, L"%s...", _r_locale_getstring (IDS_STATUS_FILTERS_PROCESSING)); return TRUE; } return FALSE; } VOID _app_restoreinterfacestate ( _In_ HWND hwnd, _In_ BOOLEAN is_enabled ) { ENUM_INSTALL_TYPE install_type; if (!is_enabled) return; install_type = _wfp_getinstalltype (); _r_toolbar_enablebutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_START, TRUE); _r_toolbar_enablebutton (config.hrebar, IDC_TOOLBAR, IDM_REFRESH, TRUE); _r_status_settext (hwnd, IDC_STATUSBAR, 0, _app_getstatelocale (install_type)); } VOID _app_setinterfacestate ( _In_ HWND hwnd, _In_ LONG dpi_value ) { ENUM_INSTALL_TYPE install_type; HICON hico_sm; HICON hico_big; LONG icon_small; LONG icon_large; INT icon_id; BOOLEAN is_filtersinstalled; install_type = _wfp_getinstalltype (); is_filtersinstalled = (install_type != INSTALL_DISABLED); icon_small = _r_dc_getsystemmetrics (SM_CXSMICON, dpi_value); icon_large = _r_dc_getsystemmetrics (SM_CXICON, dpi_value); icon_id = _app_getstateicon (install_type); hico_sm = _r_sys_loadsharedicon (_r_sys_getimagebase (), MAKEINTRESOURCE (icon_id), icon_small); hico_big = _r_sys_loadsharedicon (_r_sys_getimagebase (), MAKEINTRESOURCE (icon_id), icon_large); _r_wnd_seticon (hwnd, hico_sm, hico_big); //_r_status_seticon (hwnd, IDC_STATUSBAR, 0, hico_sm); if (!_wfp_isfiltersapplying ()) _r_status_settext (hwnd, IDC_STATUSBAR, 0, _app_getstatelocale (install_type)); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_START, _app_getstateaction (install_type), BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, 0, is_filtersinstalled ? 1 : 0); _app_settrayicon (hwnd, install_type); } VOID _app_settrayicon ( _In_ HWND hwnd, _In_ ENUM_INSTALL_TYPE install_type ) { HICON current_handle; HICON new_handle; LONG dpi_value; LONG icon_size; INT icon_id; dpi_value = _r_dc_gettaskbardpi (); icon_size = _r_dc_getsystemmetrics (SM_CXSMICON, dpi_value); icon_id = _app_getstateicon (install_type); current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.htray_icon, NULL, config.htray_icon); if (current_handle) DestroyIcon (current_handle); _r_sys_loadicon (_r_sys_getimagebase (), MAKEINTRESOURCE (icon_id), icon_size, &new_handle); _r_tray_setinfo (hwnd, &GUID_TrayIcon, new_handle, _r_app_getname ()); current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.htray_icon, new_handle, NULL); if (current_handle) DestroyIcon (current_handle); } VOID _app_imagelist_init ( _In_opt_ HWND hwnd, _In_ LONG dpi_value ) { UINT toolbar_ids[] = { IDP_SHIELD_ENABLE, IDP_SHIELD_DISABLE, IDP_REFRESH, IDP_SETTINGS, IDP_NOTIFICATIONS, IDP_LOG, IDP_LOGOPEN, IDP_LOGCLEAR, IDP_ADD, IDP_DONATE, IDP_LOGUI, }; UINT rules_ids[] = { IDP_ALLOW, IDP_BLOCK }; HBITMAP hbitmap; LONG icon_size_toolbar; LONG icon_small; LONG icon_large; SAFE_DELETE_OBJECT (config.hbmp_enable); SAFE_DELETE_OBJECT (config.hbmp_disable); SAFE_DELETE_OBJECT (config.hbmp_allow); SAFE_DELETE_OBJECT (config.hbmp_block); icon_small = _r_dc_getsystemmetrics (SM_CXSMICON, dpi_value); icon_large = _r_dc_getsystemmetrics (SM_CXICON, dpi_value); icon_size_toolbar = _r_calc_clamp (_r_dc_getdpi (_r_config_getlong (L"ToolbarSize", PR_SIZE_ITEMHEIGHT, NULL), dpi_value), icon_small, icon_large); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_SHIELD_ENABLE), &GUID_ContainerFormatPng, icon_small, icon_small, &config.hbmp_enable); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_SHIELD_DISABLE), &GUID_ContainerFormatPng, icon_small, icon_small, &config.hbmp_disable); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_ALLOW), &GUID_ContainerFormatPng, icon_small, icon_small, &config.hbmp_allow); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_BLOCK), &GUID_ContainerFormatPng, icon_small, icon_small, &config.hbmp_block); // toolbar imagelist if (config.himg_toolbar) { _r_imagelist_setsize (config.himg_toolbar, icon_size_toolbar); } else { _r_imagelist_create (icon_size_toolbar, icon_size_toolbar, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, RTL_NUMBER_OF (toolbar_ids), RTL_NUMBER_OF (toolbar_ids), &config.himg_toolbar); } if (config.himg_toolbar) { for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (toolbar_ids); i++) { _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (toolbar_ids[i]), &GUID_ContainerFormatPng, icon_size_toolbar, icon_size_toolbar, &hbitmap); if (hbitmap) _r_imagelist_add (config.himg_toolbar, hbitmap, NULL, NULL); } } if (config.htoolbar) _r_toolbar_setimagelist (config.htoolbar, 0, config.himg_toolbar); // rules imagelist (small) if (config.himg_rules_small) { _r_imagelist_setsize (config.himg_rules_small, icon_small); } else { _r_imagelist_create (icon_small, icon_small, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, RTL_NUMBER_OF (rules_ids), RTL_NUMBER_OF (rules_ids), &config.himg_rules_small); } if (config.himg_rules_small) { for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (rules_ids); i++) { _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (rules_ids[i]), &GUID_ContainerFormatPng, icon_small, icon_small, &hbitmap); if (hbitmap) _r_imagelist_add (config.himg_rules_small, hbitmap, NULL, NULL); } } // rules imagelist (large) if (config.himg_rules_large) { _r_imagelist_setsize (config.himg_rules_large, icon_large); } else { _r_imagelist_create (icon_large, icon_large, ILC_COLOR32 | ILC_HIGHQUALITYSCALE, RTL_NUMBER_OF (rules_ids), RTL_NUMBER_OF (rules_ids), &config.himg_rules_large); } if (config.himg_rules_large) { for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (rules_ids); i++) { _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (rules_ids[i]), &GUID_ContainerFormatPng, icon_large, icon_large, &hbitmap); if (hbitmap) _r_imagelist_add (config.himg_rules_large, hbitmap, NULL, NULL); } } } HFONT _app_createfont ( _Inout_ PLOGFONT logfont, _In_ LONG size, _In_ BOOLEAN is_underline, _In_ LONG dpi_value ) { HFONT hfont; if (size) logfont->lfHeight = _r_dc_fontsizetoheight (size, dpi_value); logfont->lfUnderline = is_underline; logfont->lfCharSet = DEFAULT_CHARSET; logfont->lfQuality = DEFAULT_QUALITY; hfont = CreateFontIndirectW (logfont); return hfont; } VOID _app_windowloadfont ( _In_ LONG dpi_value ) { NONCLIENTMETRICS ncm = {0}; ncm.cbSize = sizeof (NONCLIENTMETRICS); if (!_r_dc_getsystemparametersinfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, dpi_value)) return; SAFE_DELETE_OBJECT (config.wnd_font); config.wnd_font = _app_createfont (&ncm.lfMessageFont, 0, FALSE, 0); _app_toolbar_setfont (); } VOID _app_toolbar_init ( _In_ HWND hwnd, _In_ LONG dpi_value ) { ULONG button_size; config.hrebar = GetDlgItem (hwnd, IDC_REBAR); _app_windowloadfont (dpi_value); config.htoolbar = CreateWindowExW ( 0, TOOLBARCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | CCS_NOPARENTALIGN | CCS_NODIVIDER | TBSTYLE_FLAT | TBSTYLE_LIST | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS | TBSTYLE_AUTOSIZE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, config.hrebar, (HMENU)IDC_TOOLBAR, _r_sys_getimagebase (), NULL ); if (config.htoolbar) { _r_toolbar_setstyle (config.hrebar, IDC_TOOLBAR, TBSTYLE_EX_DOUBLEBUFFER | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_HIDECLIPPEDBUTTONS); _r_ctrl_setfont (config.htoolbar, 0, config.wnd_font); // fix font _r_toolbar_setimagelist (config.htoolbar, 0, config.himg_toolbar); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_START, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, I_IMAGENONE); _r_toolbar_addseparator (config.hrebar, IDC_TOOLBAR); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_OPENRULESEDITOR, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 8); _r_toolbar_addseparator (config.hrebar, IDC_TOOLBAR); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLENOTIFICATIONS_CHK, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 4); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLELOG_CHK, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 5); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLEUILOG_CHK, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 10); _r_toolbar_addseparator (config.hrebar, IDC_TOOLBAR); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_REFRESH, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 2); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_SETTINGS, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 3); _r_toolbar_addseparator (config.hrebar, IDC_TOOLBAR); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_LOGSHOW, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 6); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_LOGCLEAR, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 7); _r_toolbar_addseparator (config.hrebar, IDC_TOOLBAR); _r_toolbar_addbutton (config.hrebar, IDC_TOOLBAR, IDM_DONATE, BTNS_BUTTON | BTNS_AUTOSIZE, NULL, TBSTATE_ENABLED, 9); _r_toolbar_resize (config.hrebar, IDC_TOOLBAR); // insert toolbar button_size = _r_toolbar_getbuttonsize (config.hrebar, IDC_TOOLBAR); _r_rebar_insertband (hwnd, IDC_REBAR, REBAR_TOOLBAR_ID, config.htoolbar, RBBS_VARIABLEHEIGHT | RBBS_NOGRIPPER | RBBS_USECHEVRON, LOWORD (button_size), HIWORD (button_size)); } // insert searchbar config.hsearchbar = CreateWindowExW ( WS_EX_CLIENTEDGE, WC_EDITW, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | ES_LEFT | ES_AUTOHSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, config.hrebar, (HMENU)IDC_SEARCH, _r_sys_getimagebase (), NULL ); if (!config.hsearchbar) return; _r_ctrl_setfont (config.hsearchbar, 0, config.wnd_font); // fix font _app_search_create (config.hsearchbar); _app_search_setvisible (hwnd, config.hsearchbar, dpi_value); } VOID _app_toolbar_resize ( _In_ HWND hwnd, _In_ LONG dpi_value ) { REBARBANDINFOW rbi; SIZE ideal_size = {0}; ULONG button_size; UINT rebar_count; _app_toolbar_setfont (); _r_toolbar_resize (config.htoolbar, 0); rebar_count = _r_rebar_getcount (config.hrebar, 0); for (UINT i = 0; i < rebar_count; i++) { RtlZeroMemory (&rbi, sizeof (REBARBANDINFOW)); rbi.cbSize = sizeof (REBARBANDINFOW); rbi.fMask = RBBIM_ID | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_CHILDSIZE; if (!_r_rebar_getinfo (config.hrebar, 0, i, &rbi)) continue; if (rbi.wID == REBAR_TOOLBAR_ID) { if (!_r_toolbar_getidealsize (config.htoolbar, 0, FALSE, &ideal_size)) continue; button_size = _r_toolbar_getbuttonsize (config.hrebar, IDC_TOOLBAR); rbi.cxIdeal = (UINT)ideal_size.cx; rbi.cxMinChild = LOWORD (button_size); rbi.cyMinChild = HIWORD (button_size); } else if (rbi.wID == REBAR_SEARCH_ID) { if (_r_wnd_isvisible (rbi.hwndChild, FALSE)) { rbi.cxIdeal = (UINT)_r_dc_getdpi (180, dpi_value); } else { rbi.cxIdeal = 0; } rbi.cxMinChild = rbi.cxIdeal; rbi.cyMinChild = 20; } else { continue; } _r_rebar_setinfo (config.hrebar, 0, i, &rbi); } } VOID _app_toolbar_setfont () { if (config.htoolbar) _r_ctrl_setfont (config.htoolbar, 0, config.wnd_font); // fix font if (config.hsearchbar) _r_ctrl_setfont (config.hsearchbar, 0, config.wnd_font); // fix font } VOID _app_window_resize ( _In_ HWND hwnd, _In_ LPCRECT rect, _In_ LONG dpi_value ) { PITEM_TAB_CONTEXT new_context; PITEM_TAB_CONTEXT tab_context; HDWP hdefer; LONG statusbar_height; LONG rebar_height; _app_toolbar_resize (hwnd, dpi_value); _r_wnd_sendmessage (config.hrebar, 0, WM_SIZE, 0, 0); _r_wnd_sendmessage (hwnd, IDC_STATUSBAR, WM_SIZE, 0, 0); tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return; rebar_height = _r_rebar_getheight (hwnd, IDC_REBAR); statusbar_height = _r_status_getheight (hwnd, IDC_STATUSBAR); hdefer = BeginDeferWindowPos (2); if (hdefer) { hdefer = DeferWindowPos ( hdefer, config.hrebar, NULL, 0, 0, rect->right, rebar_height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER ); hdefer = DeferWindowPos ( hdefer, GetDlgItem (hwnd, IDC_TAB), NULL, 0, rebar_height, rect->right, rect->bottom - rebar_height - statusbar_height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER ); EndDeferWindowPos (hdefer); } for (INT i = 0; i < _r_tab_getitemcount (hwnd, IDC_TAB); i++) { new_context = _app_listview_getcontext (hwnd, i); if (!new_context) continue; _r_tab_adjustchild (hwnd, IDC_TAB, GetDlgItem (hwnd, new_context->listview_id)); if (new_context->listview_id == tab_context->listview_id) _app_listview_resize (hwnd, new_context->listview_id, FALSE); } _app_refreshstatus (hwnd); } VOID _app_refreshstatus ( _In_ HWND hwnd ) { ITEM_STATUS status = {0}; PR_STRING string[STATUSBAR_PARTS_COUNT] = {0}; LONG parts[STATUSBAR_PARTS_COUNT] = {0}; LONG size[STATUSBAR_PARTS_COUNT] = {0}; LONG calculated_width = 0; LONG spacing; HWND hstatus; HDC hdc; LONG dpi_value; hstatus = GetDlgItem (hwnd, IDC_STATUSBAR); if (!hstatus) return; hdc = GetDC (hstatus); if (!hdc) return; _r_dc_fixfont (hdc, hwnd, IDC_STATUSBAR); // fix _app_getcount (&status); dpi_value = _r_dc_getwindowdpi (hwnd); spacing = _r_dc_getdpi (16, dpi_value); for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (parts); i++) { switch (i) { case 1: { string[i] = _r_format_string (L"%s: %" TEXT (PR_ULONG_PTR), _r_locale_getstring (IDS_STATUS_UNUSED_APPS), status.apps_unused_count); break; } case 2: { string[i] = _r_format_string (L"%s: %" TEXT (PR_ULONG_PTR), _r_locale_getstring (IDS_STATUS_TIMER_APPS), status.apps_timer_count); break; } } if (i) { if (string[i]) { size[i] = _r_dc_getfontwidth (hdc, &string[i]->sr, NULL) + spacing; calculated_width += size[i]; } } } parts[0] = _r_ctrl_getwidth (hwnd, IDC_STATUSBAR) - calculated_width - _r_dc_getsystemmetrics (SM_CXVSCROLL, dpi_value) - (_r_dc_getsystemmetrics (SM_CXBORDER, dpi_value) * 4); parts[1] = parts[0] + size[1]; parts[2] = parts[1] + size[2]; _r_status_setparts (hwnd, IDC_STATUSBAR, parts, RTL_NUMBER_OF (parts)); for (ULONG_PTR i = 1; i < STATUSBAR_PARTS_COUNT; i++) { if (string[i]) { _r_status_settext (hwnd, IDC_STATUSBAR, (LONG)i, string[i]->buffer); _r_obj_dereference (string[i]); } } ReleaseDC (hstatus, hdc); } ================================================ FILE: src/controls.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once EXTERN_C const IID IID_IImageList2; _Ret_maybenull_ PR_STRING _app_gettooltipbylparam ( _In_ HWND hwnd, _In_ INT listview_id, _In_ LONG_PTR lparam ); VOID _app_settab_id ( _In_ HWND hwnd, _In_ INT page_id ); LPWSTR _app_getstateaction ( _In_ ENUM_INSTALL_TYPE install_type ); HBITMAP _app_getstatebitmap ( _In_ ENUM_INSTALL_TYPE install_type ); INT _app_getstateicon ( _In_ ENUM_INSTALL_TYPE install_type ); LPCWSTR _app_getstatelocale ( _In_ ENUM_INSTALL_TYPE install_type ); BOOLEAN _app_initinterfacestate ( _In_ HWND hwnd, _In_ BOOLEAN is_forced ); VOID _app_restoreinterfacestate ( _In_ HWND hwnd, _In_ BOOLEAN is_enabled ); VOID _app_setinterfacestate ( _In_ HWND hwnd, _In_ LONG dpi_value ); VOID _app_settrayicon ( _In_ HWND hwnd, _In_ ENUM_INSTALL_TYPE install_type ); VOID _app_imagelist_init ( _In_opt_ HWND hwnd, _In_ LONG dpi_value ); HFONT _app_createfont ( _Inout_ PLOGFONT logfont, _In_ LONG size, _In_ BOOLEAN is_underline, _In_ LONG dpi_value ); VOID _app_windowloadfont ( _In_ LONG dpi_value ); VOID _app_toolbar_init ( _In_ HWND hwnd, _In_ LONG dpi_value ); VOID _app_toolbar_resize ( _In_ HWND hwnd, _In_ LONG dpi_value ); VOID _app_toolbar_setfont (); VOID _app_window_resize ( _In_ HWND hwnd, _In_ LPCRECT rect, _In_ LONG dpi_value ); VOID _app_refreshstatus ( _In_ HWND hwnd ); ================================================ FILE: src/db.c ================================================ // simplewall // Copyright (c) 2019-2025 Henry++ #include "global.h" _Success_ (SUCCEEDED (return)) HRESULT _app_db_initialize ( _Out_ PDB_INFORMATION db_info, _In_ BOOLEAN is_reader ) { RtlZeroMemory (db_info, sizeof (DB_INFORMATION)); return _r_xml_initializelibrary (&db_info->xml_library, is_reader); } VOID _app_db_destroy ( _Inout_ PDB_INFORMATION db_info ) { if (db_info->bytes) _r_obj_clearreference ((PVOID_PTR)&db_info->bytes); _r_xml_destroylibrary (&db_info->xml_library); } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_encrypt ( _In_ PR_BYTEREF bytes, _Out_ PR_BYTE_PTR out_buffer ) { R_CRYPT_CONTEXT crypt_context; R_BYTEREF key; NTSTATUS status; *out_buffer = NULL; status = _r_crypt_createcryptcontext (&crypt_context, BCRYPT_AES_ALGORITHM); if (!NT_SUCCESS (status)) return status; _r_obj_initializebyteref (&key, PROFILE2_KEY); status = _r_crypt_generatekey (&crypt_context, &key); if (!NT_SUCCESS (status)) goto CleanupExit; status = _r_crypt_encryptbuffer (&crypt_context, bytes->buffer, (ULONG)bytes->length, out_buffer); CleanupExit: _r_crypt_destroycryptcontext (&crypt_context); return status; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_decrypt ( _In_ PR_BYTEREF bytes, _Out_ PR_BYTE_PTR out_buffer ) { R_CRYPT_CONTEXT crypt_context; R_BYTEREF key; NTSTATUS status; *out_buffer = NULL; status = _r_crypt_createcryptcontext (&crypt_context, BCRYPT_AES_ALGORITHM); if (!NT_SUCCESS (status)) return status; _r_obj_initializebyteref (&key, PROFILE2_KEY); status = _r_crypt_generatekey (&crypt_context, &key); if (!NT_SUCCESS (status)) goto CleanupExit; status = _r_crypt_decryptbuffer (&crypt_context, bytes->buffer, (ULONG)bytes->length, out_buffer); CleanupExit: _r_crypt_destroycryptcontext (&crypt_context); return status; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_gethash ( _In_ PR_BYTEREF bytes, _Out_ PR_BYTE_PTR out_buffer ) { R_CRYPT_CONTEXT hash_context; NTSTATUS status; *out_buffer = NULL; status = _r_crypt_createhashcontext (&hash_context, BCRYPT_SHA256_ALGORITHM); if (!NT_SUCCESS (status)) return status; status = _r_crypt_hashbuffer (&hash_context, bytes->buffer, (ULONG)bytes->length); if (NT_SUCCESS (status)) status = _r_crypt_finalhashcontext (&hash_context, NULL, out_buffer); _r_crypt_destroycryptcontext (&hash_context); return status; } BYTE _app_getprofiletype () { LONG profile_type; profile_type = _r_config_getlong (L"ProfileType", 0, NULL); switch (profile_type) { case 1: { return PROFILE2_ID_COMPRESSED; } case 2: { return PROFILE2_ID_ENCRYPTED; } } return PROFILE2_ID_PLAIN; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_ishashvalid ( _In_ PR_BYTEREF buffer, _In_ PR_BYTEREF hash_bytes ) { PR_BYTE new_hash_bytes = NULL; NTSTATUS status; status = _app_db_gethash (buffer, &new_hash_bytes); if (!NT_SUCCESS (status)) return status; if (RtlEqualMemory (hash_bytes->buffer, new_hash_bytes->buffer, new_hash_bytes->length)) { status = STATUS_SUCCESS; } else { status = STATUS_INVALID_IMAGE_HASH; } _r_obj_dereference (new_hash_bytes); return status; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_openfrombuffer ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STORAGE buffer, _In_ ENUM_VERSION_XML min_version, _In_ ENUM_TYPE_XML type ) { NTSTATUS status; _r_obj_movereference ((PVOID_PTR)&db_info->bytes, _r_obj_createbyte4 (buffer)); status = _app_db_decodebuffer (db_info, type, min_version); return status; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_openfromfile ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STRING path, _In_ ENUM_VERSION_XML min_version, _In_ ENUM_TYPE_XML type ) { HANDLE hfile; NTSTATUS status; if (db_info->bytes) _r_obj_clearreference ((PVOID_PTR)&db_info->bytes); status = _r_fs_openfile (&path->sr, GENERIC_READ, FILE_SHARE_READ, 0, FALSE, &hfile); if (!NT_SUCCESS (status)) return status; status = _r_fs_readbytes (hfile, &db_info->bytes); if (!NT_SUCCESS (status)) { NtClose (hfile); return status; } status = _app_db_decodebuffer (db_info, type, min_version); NtClose (hfile); return status; } VOID _app_db_parse_app ( _Inout_ PDB_INFORMATION db_info ) { PITEM_APP ptr_app; PR_STRING string; PR_STRING path; PR_STRING dos_path; LONG64 timestamp; LONG64 timer; ULONG app_hash; BOOLEAN is_undeletable; BOOLEAN is_enabled; BOOLEAN is_silent; path = _r_xml_getattribute_string (&db_info->xml_library, L"path"); if (_r_obj_isstringempty (path)) return; // workaround for native paths // https://github.com/henrypp/simplewall/issues/817 if (_r_str_isstartswith2 (&path->sr, L"\\device\\", TRUE)) { dos_path = _r_path_dospathfromnt (&path->sr); if (dos_path) _r_obj_movereference ((PVOID_PTR)&path, dos_path); } if (!_r_obj_isstringempty2 (path)) { app_hash = _app_addapplication (NULL, DATA_UNKNOWN, path, NULL, NULL); if (app_hash) { ptr_app = _app_getappitem (app_hash); if (ptr_app) { is_enabled = _r_xml_getattribute_boolean (&db_info->xml_library, L"is_enabled"); is_silent = _r_xml_getattribute_boolean (&db_info->xml_library, L"is_silent"); is_undeletable = _r_xml_getattribute_boolean (&db_info->xml_library, L"is_undeletable"); timestamp = _r_xml_getattribute_long64 (&db_info->xml_library, L"timestamp"); timer = _r_xml_getattribute_long64 (&db_info->xml_library, L"timer"); string = _r_xml_getattribute_string (&db_info->xml_library, L"hash"); if (string) { if (!_r_obj_isstringempty2 (string)) { _app_setappinfo (ptr_app, INFO_HASH, string); } else { _r_obj_dereference (string); } } string = _r_xml_getattribute_string (&db_info->xml_library, L"comment"); if (string) { if (!_r_obj_isstringempty2 (string)) { _app_setappinfo (ptr_app, INFO_COMMENT, string); } else { _r_obj_dereference (string); } } if (is_silent) _app_setappinfo (ptr_app, INFO_IS_SILENT, LongToPtr (is_silent)); if (is_enabled) _app_setappinfo (ptr_app, INFO_IS_ENABLED, LongToPtr (is_enabled)); if (is_undeletable) _app_setappinfo (ptr_app, INFO_IS_UNDELETABLE, LongToPtr (is_undeletable)); if (timestamp) _app_setappinfo (ptr_app, INFO_TIMESTAMP, ×tamp); if (timer) _app_setappinfo (ptr_app, INFO_TIMER, &timer); _r_obj_dereference (ptr_app); } } } _r_obj_dereference (path); } VOID _app_db_parse_rule ( _Inout_ PDB_INFORMATION db_info, _In_ ENUM_TYPE_DATA type ) { PITEM_RULE_CONFIG ptr_config = NULL; R_STRINGBUILDER sb; R_STRINGREF first_part; R_STRINGREF sr; PR_STRING rule_name; PR_STRING rule_remote; PR_STRING rule_local; PR_STRING path_string; PR_STRING comment; PR_STRING string; LONG blocklist_spy_state; LONG blocklist_update_state; LONG blocklist_extra_state; FWP_DIRECTION direction; FWP_ACTION_TYPE action; UINT8 protocol; ADDRESS_FAMILY af; PITEM_RULE ptr_rule; ULONG rule_hash; ULONG app_hash; BOOLEAN is_internal; NTSTATUS status; // check support version status = _r_xml_getattribute (&db_info->xml_library, L"os_version", &sr); if (SUCCEEDED (status)) { if (!_app_isrulesupportedbyos (&sr)) return; } rule_name = _r_xml_getattribute_string (&db_info->xml_library, L"name"); if (!rule_name) return; rule_remote = _r_xml_getattribute_string (&db_info->xml_library, L"rule"); rule_local = _r_xml_getattribute_string (&db_info->xml_library, L"rule_local"); comment = _r_xml_getattribute_string (&db_info->xml_library, L"comment"); direction = (FWP_DIRECTION)_r_xml_getattribute_long (&db_info->xml_library, L"dir"); action = _r_xml_getattribute_boolean (&db_info->xml_library, L"is_block") ? FWP_ACTION_BLOCK : FWP_ACTION_PERMIT; protocol = (UINT8)_r_xml_getattribute_long (&db_info->xml_library, L"protocol"); af = (ADDRESS_FAMILY)_r_xml_getattribute_long (&db_info->xml_library, L"version"); ptr_rule = _app_addrule (rule_name, rule_remote, rule_local, direction, action, protocol, af); _r_obj_dereference (rule_name); if (rule_remote) _r_obj_dereference (rule_remote); if (rule_local) _r_obj_dereference (rule_local); rule_hash = _r_str_gethash (&ptr_rule->name->sr, TRUE); if (!_r_obj_isstringempty (comment)) { _r_obj_movereference ((PVOID_PTR)&ptr_rule->comment, comment); } else { if (comment) _r_obj_dereference (comment); } ptr_rule->type = (type == DATA_RULE_SYSTEM_USER) ? DATA_RULE_USER : type; ptr_rule->is_forservices = _r_xml_getattribute_boolean (&db_info->xml_library, L"is_services"); ptr_rule->is_readonly = (type != DATA_RULE_USER); ptr_rule->is_enabled = _r_xml_getattribute_boolean (&db_info->xml_library, L"is_enabled"); // calculate rule weight if (type == DATA_RULE_BLOCKLIST) { ptr_rule->weight = FW_WEIGHT_RULE_BLOCKLIST; } else if (type == DATA_RULE_SYSTEM || type == DATA_RULE_SYSTEM_USER) { ptr_rule->weight = FW_WEIGHT_RULE_SYSTEM; } else if (type == DATA_RULE_USER) { ptr_rule->weight = (ptr_rule->action == FWP_ACTION_BLOCK) ? FW_WEIGHT_RULE_USER_BLOCK : FW_WEIGHT_RULE_USER; } if (type == DATA_RULE_BLOCKLIST) { blocklist_spy_state = _r_calc_clamp (_r_config_getlong (L"BlocklistSpyState", 2, NULL), 0, 2); blocklist_update_state = _r_calc_clamp (_r_config_getlong (L"BlocklistUpdateState", 0, NULL), 0, 2); blocklist_extra_state = _r_calc_clamp (_r_config_getlong (L"BlocklistExtraState", 0, NULL), 0, 2); _app_ruleblocklistsetstate (ptr_rule, blocklist_spy_state, blocklist_update_state, blocklist_extra_state); } else { ptr_rule->is_enabled_default = ptr_rule->is_enabled; // set default value for rule } // load rules config is_internal = (type == DATA_RULE_BLOCKLIST || type == DATA_RULE_SYSTEM || type == DATA_RULE_SYSTEM_USER); if (is_internal) { // internal rules ptr_config = _app_getruleconfigitem (rule_hash); if (ptr_config) ptr_rule->is_enabled = ptr_config->is_enabled; } // load apps _r_obj_initializestringbuilder (&sb, 256); string = _r_xml_getattribute_string (&db_info->xml_library, L"apps"); if (!_r_obj_isstringempty (string)) { _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_dereference (string); } if (is_internal && ptr_config && !_r_obj_isstringempty (ptr_config->apps)) { if (!_r_obj_isstringempty2 (sb.string)) _r_obj_appendstringbuilder (&sb, DIVIDER_APP); _r_obj_appendstringbuilder2 (&sb, &ptr_config->apps->sr); } string = _r_obj_finalstringbuilder (&sb); if (!_r_obj_isstringempty2 (string)) { if (db_info->version < XML_VERSION_3) _r_str_replacechar (&string->sr, DIVIDER_RULE[0], DIVIDER_APP[0]); _r_obj_initializestringref2 (&sr, &string->sr); while (sr.length != 0) { _r_str_splitatchar (&sr, DIVIDER_APP[0], &first_part, &sr); status = _r_str_environmentexpandstring (NULL, &first_part, &path_string); if (status != STATUS_SUCCESS) path_string = _r_obj_createstring2 (&first_part); app_hash = _r_str_gethash (&path_string->sr, TRUE); if (app_hash) { if (ptr_rule->is_forservices && _app_issystemhash (app_hash)) { _r_obj_dereference (path_string); continue; } if (!_app_isappfound (app_hash)) app_hash = _app_addapplication (NULL, DATA_UNKNOWN, path_string, NULL, NULL); if (app_hash) { _r_obj_addhashtableitem (ptr_rule->apps, app_hash, NULL); if (ptr_rule->type == DATA_RULE_SYSTEM) _app_setappinfobyhash (app_hash, INFO_IS_UNDELETABLE, LongToPtr (TRUE)); } } _r_obj_dereference (path_string); } // check if no app is added into rule, then disable it! if (ptr_rule->is_enabled) { if (_r_obj_isempty (ptr_rule->apps)) ptr_rule->is_enabled = FALSE; } } _r_queuedlock_acquireexclusive (&lock_rules); _r_obj_addlistitem (rules_list, ptr_rule, NULL); _r_queuedlock_releaseexclusive (&lock_rules); _r_obj_deletestringbuilder (&sb); } VOID _app_db_parse_ruleconfig ( _Inout_ PDB_INFORMATION db_info ) { PITEM_RULE_CONFIG ptr_config; PR_STRING rule_name; ULONG rule_hash; rule_name = _r_xml_getattribute_string (&db_info->xml_library, L"name"); if (!rule_name) return; rule_hash = _r_str_gethash (&rule_name->sr, TRUE); if (!rule_hash) { _r_obj_dereference (rule_name); return; } ptr_config = _app_getruleconfigitem (rule_hash); if (!ptr_config) { _r_queuedlock_acquireexclusive (&lock_rules_config); ptr_config = _app_addruleconfigtable (rules_config, rule_hash, rule_name, _r_xml_getattribute_boolean (&db_info->xml_library, L"is_enabled")); _r_queuedlock_releaseexclusive (&lock_rules_config); if (ptr_config) { ptr_config->apps = _r_xml_getattribute_string (&db_info->xml_library, L"apps"); if (ptr_config->apps && db_info->version < XML_VERSION_3) _r_str_replacechar (&ptr_config->apps->sr, DIVIDER_RULE[0], DIVIDER_APP[0]); } } _r_obj_dereference (rule_name); } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_decodebody ( _Inout_ PDB_INFORMATION db_info ) { USHORT format[] = {COMPRESSION_FORMAT_LZNT1, COMPRESSION_FORMAT_XPRESS}; USHORT architecture; PR_BYTE new_bytes; BYTE profile_type; NTSTATUS status; if (db_info->bytes->length < PROFILE2_HEADER_LENGTH) return STATUS_SUCCESS; if (!RtlEqualMemory (db_info->bytes->buffer, profile2_fourcc, sizeof (profile2_fourcc)) || !RtlEqualMemory (db_info->bytes->buffer, profile2_fourcc, sizeof (profile2_fourcc_old))) return STATUS_SUCCESS; profile_type = db_info->bytes->buffer[sizeof (profile2_fourcc)]; // skip fourcc _r_obj_skipbytelength (&db_info->bytes->sr, PROFILE2_FOURCC_LENGTH); // read the hash _r_obj_movereference ((PVOID_PTR)&db_info->hash, _r_obj_createbyte_ex (db_info->bytes->buffer, PROFILE2_SHA256_LENGTH)); // skip hash _r_obj_skipbytelength (&db_info->bytes->sr, PROFILE2_SHA256_LENGTH); switch (profile_type) { case PROFILE2_ID_COMPRESSED: { // decompress bytes for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (format); i++) { status = _r_sys_decompressbuffer (format[i], &db_info->bytes->sr, &new_bytes); if (NT_SUCCESS (status)) { _r_obj_movereference ((PVOID_PTR)&db_info->bytes, new_bytes); break; } } break; } case PROFILE2_ID_ENCRYPTED: { // decrypt bytes status = _app_db_decrypt (&db_info->bytes->sr, &new_bytes); if (!NT_SUCCESS (status)) return status; _r_obj_movereference ((PVOID_PTR)&db_info->bytes, new_bytes); break; } default: { return STATUS_FILE_NOT_SUPPORTED; } } if (!NT_SUCCESS (status)) return status; if (RtlEqualMemory (db_info->bytes->buffer, profile2_fourcc, sizeof (profile2_fourcc)) || RtlEqualMemory (db_info->bytes->buffer, profile2_fourcc_old, sizeof (profile2_fourcc_old))) return STATUS_MORE_PROCESSING_REQUIRED; // fix arm64 crash that was introduced by Micro$oft (issue #1228) if (NT_SUCCESS (_r_sys_getprocessorinformation (&architecture, NULL, NULL))) { if (architecture == PROCESSOR_ARCHITECTURE_ARM || architecture == PROCESSOR_ARCHITECTURE_ARM64) return STATUS_SUCCESS; } // validate hash if (db_info->hash) status = _app_db_ishashvalid (&db_info->bytes->sr, &db_info->hash->sr); return status; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_encodebody ( _Inout_ PDB_INFORMATION db_info, _In_ BYTE profile_type, _Out_ PR_BYTE_PTR out_buffer ) { PR_BYTE body_bytes; PR_BYTE hash_value; PR_BYTE new_bytes; PR_BYTE bytes; NTSTATUS status; *out_buffer = NULL; status = _r_xml_readstream (&db_info->xml_library, &bytes); if (FAILED (status)) return status; // generate body hash status = _app_db_gethash (&bytes->sr, &hash_value); if (!NT_SUCCESS (status)) { _r_obj_dereference (hash_value); _r_obj_dereference (bytes); return status; } switch (profile_type) { case PROFILE2_ID_PLAIN: { new_bytes = _r_obj_reference (bytes); break; } case PROFILE2_ID_COMPRESSED: { // compress body status = _r_sys_compressbuffer (COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, &bytes->sr, &new_bytes); if (!NT_SUCCESS (status)) { _r_obj_dereference (hash_value); _r_obj_dereference (bytes); return status; } break; } case PROFILE2_ID_ENCRYPTED: { status = _app_db_encrypt (&bytes->sr, &new_bytes); if (!NT_SUCCESS (status)) { _r_obj_dereference (hash_value); _r_obj_dereference (bytes); return status; } break; } default: { return STATUS_FILE_NOT_SUPPORTED; } } _r_obj_movereference ((PVOID_PTR)&bytes, new_bytes); status = _app_db_generatebody (profile_type, hash_value, bytes, &body_bytes); *out_buffer = body_bytes; _r_obj_dereference (hash_value); _r_obj_dereference (bytes); return status; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_generatebody ( _In_ BYTE profile_type, _In_ PR_BYTE hash_value, _In_ PR_BYTE buffer, _Out_ PR_BYTE_PTR out_buffer ) { PR_BYTE bytes; PVOID ptr; switch (profile_type) { case PROFILE2_ID_PLAIN: { bytes = _r_obj_reference (buffer); break; } case PROFILE2_ID_COMPRESSED: case PROFILE2_ID_ENCRYPTED: { bytes = _r_obj_createbyte_ex (NULL, PROFILE2_HEADER_LENGTH + buffer->length); RtlCopyMemory (bytes->buffer, profile2_fourcc, sizeof (profile2_fourcc)); ptr = PTR_ADD_OFFSET (bytes->buffer, sizeof (profile2_fourcc)); RtlCopyMemory (ptr, &profile_type, sizeof (BYTE)); ptr = PTR_ADD_OFFSET (bytes->buffer, PROFILE2_FOURCC_LENGTH); RtlCopyMemory (ptr, hash_value->buffer, hash_value->length); ptr = PTR_ADD_OFFSET (bytes->buffer, PROFILE2_HEADER_LENGTH); RtlCopyMemory (ptr, buffer->buffer, buffer->length); break; } default: { *out_buffer = NULL; return STATUS_FILE_NOT_SUPPORTED; } } *out_buffer = bytes; return STATUS_SUCCESS; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_decodebuffer ( _Inout_ PDB_INFORMATION db_info, _In_ ENUM_TYPE_XML type, _In_ ENUM_VERSION_XML min_version ) { ULONG attempts = 6; NTSTATUS status; if (!db_info->bytes) return STATUS_BUFFER_ALL_ZEROS; do { status = _app_db_decodebody (db_info); if (status != STATUS_MORE_PROCESSING_REQUIRED) break; } while (--attempts); if (!NT_SUCCESS (status)) return status; status = _r_xml_parsestring (&db_info->xml_library, db_info->bytes->buffer, (ULONG)db_info->bytes->length); if (FAILED (status)) return status; if (!_r_xml_findchildbytagname (&db_info->xml_library, L"root")) return STATUS_DATA_ERROR; db_info->timestamp = _r_xml_getattribute_long64 (&db_info->xml_library, L"timestamp"); db_info->type = _r_xml_getattribute_long (&db_info->xml_library, L"type"); db_info->version = _r_xml_getattribute_long (&db_info->xml_library, L"version"); if (db_info->type != type) return STATUS_NDIS_INVALID_DATA; if (db_info->version < min_version) return STATUS_FILE_NOT_SUPPORTED; return STATUS_SUCCESS; } BOOLEAN _app_db_parse ( _Inout_ PDB_INFORMATION db_info, _In_ ENUM_TYPE_XML type ) { if (!_r_xml_findchildbytagname (&db_info->xml_library, L"root")) return FALSE; switch (type) { case XML_TYPE_PROFILE: { // load apps if (_r_xml_findchildbytagname (&db_info->xml_library, L"apps")) { while (_r_xml_enumchilditemsbytagname (&db_info->xml_library, L"item")) { _app_db_parse_app (db_info); } } // load rules config if (_r_xml_findchildbytagname (&db_info->xml_library, L"rules_config")) { while (_r_xml_enumchilditemsbytagname (&db_info->xml_library, L"item")) { _app_db_parse_ruleconfig (db_info); } } // load user rules if (_r_xml_findchildbytagname (&db_info->xml_library, L"rules_custom")) { while (_r_xml_enumchilditemsbytagname (&db_info->xml_library, L"item")) { _app_db_parse_rule (db_info, DATA_RULE_USER); } } break; } case XML_TYPE_PROFILE_INTERNAL: { // load system rules if (_r_xml_findchildbytagname (&db_info->xml_library, L"rules_system")) { while (_r_xml_enumchilditemsbytagname (&db_info->xml_library, L"item")) { _app_db_parse_rule (db_info, DATA_RULE_SYSTEM); } } // load internal custom rules if (_r_xml_findchildbytagname (&db_info->xml_library, L"rules_custom")) { while (_r_xml_enumchilditemsbytagname (&db_info->xml_library, L"item")) { _app_db_parse_rule (db_info, DATA_RULE_SYSTEM_USER); } } // load blocklist rules if (_r_xml_findchildbytagname (&db_info->xml_library, L"rules_blocklist")) { while (_r_xml_enumchilditemsbytagname (&db_info->xml_library, L"item")) { _app_db_parse_rule (db_info, DATA_RULE_BLOCKLIST); } } break; } } return TRUE; } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_savetofile ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STRING path, _In_ ENUM_VERSION_XML version, _In_ ENUM_TYPE_XML type, _In_ LONG64 timestamp ) { NTSTATUS status; status = _r_xml_createstream (&db_info->xml_library, NULL, 1024); if (FAILED (status)) return status; _r_xml_writestartdocument (&db_info->xml_library); _r_xml_writestartelement (&db_info->xml_library, L"root"); _r_xml_setattribute_long (&db_info->xml_library, L"version", version); _r_xml_setattribute_long (&db_info->xml_library, L"type", type); _r_xml_setattribute_long64 (&db_info->xml_library, L"timestamp", timestamp); _app_db_save_app (db_info); _app_db_save_rule (db_info); _app_db_save_ruleconfig (db_info); _r_xml_writewhitespace (&db_info->xml_library, L"\r\n"); _r_xml_writeendelement (&db_info->xml_library); _r_xml_writewhitespace (&db_info->xml_library, L"\r\n"); _r_xml_writeenddocument (&db_info->xml_library); return _app_db_save_streamtofile (db_info, path); } _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_save_streamtofile ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STRING path ) { PR_BYTE new_bytes; HANDLE hfile; NTSTATUS status; status = _r_fs_createfile ( &path->sr, FILE_OVERWRITE_IF, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_ATTRIBUTE_NORMAL, 0, FALSE, NULL, &hfile ); if (!NT_SUCCESS (status)) return status; status = _app_db_encodebody (db_info, _app_getprofiletype (), &new_bytes); if (NT_SUCCESS (status)) { _r_fs_writefile (hfile, new_bytes->buffer, (ULONG)new_bytes->length); _r_obj_dereference (new_bytes); } NtClose (hfile); return status; } FORCEINLINE VOID _app_db_writeelementstart ( _Inout_ PDB_INFORMATION db_info, _In_ LPCWSTR name ) { _r_xml_writewhitespace (&db_info->xml_library, L"\r\n\t"); _r_xml_writestartelement (&db_info->xml_library, name); } FORCEINLINE VOID _app_db_writeelementend ( _Inout_ PDB_INFORMATION db_info ) { _r_xml_writewhitespace (&db_info->xml_library, L"\r\n\t"); _r_xml_writeendelement (&db_info->xml_library); } VOID _app_db_save_app ( _Inout_ PDB_INFORMATION db_info ) { PITEM_APP ptr_app = NULL; ULONG_PTR enum_key = 0; BOOLEAN is_keepunusedapps; BOOLEAN is_usedapp; is_keepunusedapps = _r_config_getboolean (L"IsKeepUnusedApps", TRUE, NULL); _app_db_writeelementstart (db_info, L"apps"); _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (_r_obj_isstringempty (ptr_app->original_path)) continue; is_usedapp = _app_isappused (ptr_app); // do not save unused apps/uwp apps... if (!is_usedapp && (!is_keepunusedapps || (ptr_app->type == DATA_APP_SERVICE || ptr_app->type == DATA_APP_UWP))) { //_app_deleteappitem (_r_app_gethwnd (), ptr_app->type, ptr_app->app_hash); continue; } _r_xml_writewhitespace (&db_info->xml_library, L"\r\n\t\t"); _r_xml_writestartelement (&db_info->xml_library, L"item"); _r_xml_setattribute (&db_info->xml_library, L"path", ptr_app->original_path->buffer); if (!_r_obj_isstringempty (ptr_app->hash) && _r_config_getboolean (L"IsHashesEnabled", FALSE, NULL)) _r_xml_setattribute (&db_info->xml_library, L"hash", ptr_app->hash->buffer); if (!_r_obj_isstringempty (ptr_app->comment)) _r_xml_setattribute (&db_info->xml_library, L"comment", ptr_app->comment->buffer); if (ptr_app->timestamp) _r_xml_setattribute_long64 (&db_info->xml_library, L"timestamp", ptr_app->timestamp); // set timer (if presented) if (ptr_app->timer && _app_istimerset (ptr_app)) _r_xml_setattribute_long64 (&db_info->xml_library, L"timer", ptr_app->timer); // ffu! if (ptr_app->profile) _r_xml_setattribute_long (&db_info->xml_library, L"profile", ptr_app->profile); if (ptr_app->is_undeletable) _r_xml_setattribute_boolean (&db_info->xml_library, L"is_undeletable", !!ptr_app->is_undeletable); if (ptr_app->is_silent) _r_xml_setattribute_boolean (&db_info->xml_library, L"is_silent", !!ptr_app->is_silent); if (ptr_app->is_enabled) _r_xml_setattribute_boolean (&db_info->xml_library, L"is_enabled", !!ptr_app->is_enabled); _r_xml_writeendelement (&db_info->xml_library); } _r_queuedlock_releaseshared (&lock_apps); _app_db_writeelementend (db_info); } VOID _app_db_save_rule ( _Inout_ PDB_INFORMATION db_info ) { PITEM_RULE ptr_rule; PR_STRING apps_string; _app_db_writeelementstart (db_info, L"rules_custom"); _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (!ptr_rule || ptr_rule->is_readonly || _r_obj_isstringempty (ptr_rule->name)) continue; _r_xml_writewhitespace (&db_info->xml_library, L"\r\n\t\t"); _r_xml_writestartelement (&db_info->xml_library, L"item"); _r_xml_setattribute (&db_info->xml_library, L"name", ptr_rule->name->buffer); if (!_r_obj_isstringempty (ptr_rule->rule_remote)) _r_xml_setattribute (&db_info->xml_library, L"rule", ptr_rule->rule_remote->buffer); if (!_r_obj_isstringempty (ptr_rule->rule_local)) _r_xml_setattribute (&db_info->xml_library, L"rule_local", ptr_rule->rule_local->buffer); if (!_r_obj_isstringempty (ptr_rule->comment)) _r_xml_setattribute (&db_info->xml_library, L"comment", ptr_rule->comment->buffer); // ffu! if (ptr_rule->profile) _r_xml_setattribute_long (&db_info->xml_library, L"profile", ptr_rule->profile); if (ptr_rule->direction != FWP_DIRECTION_OUTBOUND) _r_xml_setattribute_long (&db_info->xml_library, L"dir", ptr_rule->direction); if (ptr_rule->protocol != 0) _r_xml_setattribute_long (&db_info->xml_library, L"protocol", ptr_rule->protocol); if (ptr_rule->af != AF_UNSPEC) _r_xml_setattribute_long (&db_info->xml_library, L"version", ptr_rule->af); // add apps attribute if (!_r_obj_isempty (ptr_rule->apps)) { apps_string = _app_rulesexpandapps (ptr_rule, FALSE, DIVIDER_APP); if (apps_string) { _r_xml_setattribute (&db_info->xml_library, L"apps", apps_string->buffer); _r_obj_dereference (apps_string); } } if (ptr_rule->action == FWP_ACTION_BLOCK) _r_xml_setattribute_boolean (&db_info->xml_library, L"is_block", TRUE); if (ptr_rule->is_enabled) _r_xml_setattribute_boolean (&db_info->xml_library, L"is_enabled", !!ptr_rule->is_enabled); _r_xml_writeendelement (&db_info->xml_library); } _r_queuedlock_releaseshared (&lock_rules); _app_db_writeelementend (db_info); } VOID _app_db_save_ruleconfig ( _Inout_ PDB_INFORMATION db_info ) { PITEM_RULE_CONFIG ptr_config = NULL; PITEM_RULE ptr_rule; PR_STRING apps_string; ULONG_PTR enum_key = 0; ULONG_PTR rule_hash; BOOLEAN is_enabled_default; _app_db_writeelementstart (db_info, L"rules_config"); _r_queuedlock_acquireshared (&lock_rules_config); while (_r_obj_enumhashtable (rules_config, (PVOID_PTR)&ptr_config, NULL, &enum_key)) { if (_r_obj_isstringempty (ptr_config->name)) continue; is_enabled_default = ptr_config->is_enabled; rule_hash = _r_str_gethash (&ptr_config->name->sr, TRUE); ptr_rule = _app_getrulebyhash (rule_hash); apps_string = NULL; if (ptr_rule) { is_enabled_default = !!ptr_rule->is_enabled_default; if (ptr_rule->type == DATA_RULE_USER && !_r_obj_isempty (ptr_rule->apps)) apps_string = _app_rulesexpandapps (ptr_rule, FALSE, DIVIDER_APP); _r_obj_dereference (ptr_rule); } // skip saving untouched configuration if (ptr_config->is_enabled == is_enabled_default && !apps_string) continue; _r_xml_writewhitespace (&db_info->xml_library, L"\r\n\t\t"); _r_xml_writestartelement (&db_info->xml_library, L"item"); _r_xml_setattribute (&db_info->xml_library, L"name", ptr_config->name->buffer); if (apps_string) { _r_xml_setattribute (&db_info->xml_library, L"apps", apps_string->buffer); _r_obj_clearreference ((PVOID_PTR)&apps_string); } _r_xml_setattribute_boolean (&db_info->xml_library, L"is_enabled", ptr_config->is_enabled); _r_xml_writeendelement (&db_info->xml_library); } _r_queuedlock_releaseshared (&lock_rules_config); _app_db_writeelementend (db_info); } _Ret_maybenull_ LPCWSTR _app_db_getconnectionstatename ( _In_ ULONG state ) { 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 NULL; } _Ret_maybenull_ PR_STRING _app_db_getdirectionname ( _In_ FWP_DIRECTION direction, _In_ BOOLEAN is_loopback, _In_ BOOLEAN is_localized ) { LPCWSTR text = NULL; if (is_localized) { switch (direction) { case FWP_DIRECTION_OUTBOUND: { text = _r_locale_getstring (IDS_DIRECTION_1); break; } case FWP_DIRECTION_INBOUND: { text = _r_locale_getstring (IDS_DIRECTION_2); break; } case FWP_DIRECTION_MAX: { text = _r_locale_getstring (IDS_ANY); break; } } } else { switch (direction) { case FWP_DIRECTION_OUTBOUND: { text = SZ_DIRECTION_OUT; break; } case FWP_DIRECTION_INBOUND: { text = SZ_DIRECTION_IN; break; } case FWP_DIRECTION_MAX: { text = SZ_DIRECTION_ANY; break; } } } if (!text) return NULL; if (is_loopback) return _r_obj_concatstrings (2, text, L" (" SZ_DIRECTION_LOOPBACK L")"); return _r_obj_createstring (text); } LPCWSTR _app_db_getprotoname ( _In_ ULONG proto, _In_ ADDRESS_FAMILY af ) { switch (proto) { // NOTE: this is used for "any" protocol case IPPROTO_HOPOPTS: break; 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"; case IPPROTO_RAW: return L"raw"; } return L"n/a"; } _Ret_maybenull_ LPCWSTR _app_db_getservicename ( _In_ UINT16 port, _In_ UINT8 proto ) { switch (port) { case 1: return L"tcpmux"; case 2: case 3: return L"compressnet"; case 5: return L"rje"; case 7: return L"echo"; case 9: return L"discard"; case 11: return L"systat"; case 13: return L"daytime"; case 15: { if (proto == IPPROTO_TCP) return L"netstat"; break; } case 17: return L"qotd"; case 18: return L"msp"; case 20: return L"ftp-data"; case 21: return L"ftp"; case 22: return L"ssh"; case 23: return L"telnet"; case 24: return L"priv-mail"; case 25: return L"smtp"; case 26: { if (proto == IPPROTO_TCP) return L"rsftp"; break; } case 27: return L"nsw-fe"; case 29: return L"msg-icp"; case 31: return L"msg-auth"; case 33: return L"dsp"; case 35: return L"priv-print"; case 37: return L"time"; case 38: return L"rap"; case 39: return L"rlp"; case 41: return L"graphics"; case 42: return L"nameserver"; case 43: return L"whois"; case 47: return L"ni-ftp"; case 48: return L"auditd"; case 49: return L"tacacs"; case 50: return L"re-mail-ck"; case 52: return L"xns-time"; case 53: return L"domain"; case 54: return L"xns-ch"; case 55: return L"isi-gl"; case 57: return L"priv-term"; case 58: return L"xns-mail"; case 59: return L"priv-file"; case 61: return L"ni-mail"; case 62: return L"acas"; case 63: return L"via-ftp"; // whoispp case 64: return L"covia"; case 65: return L"tacacs-ds"; case 66: return L"sqlnet"; case 67: return L"dhcps"; case 68: return L"dhcpc"; case 69: return L"tftp"; case 70: return L"gopher"; case 75: return L"priv-dial"; case 76: return L"deos"; case 77: return L"priv-rje"; // netjrs case 78: return L"vettcp"; case 79: case 2003: return L"finger"; case 80: return L"http"; case 81: return L"hosts2-ns"; case 82: return L"xfer"; case 83: return L"mit-ml-dev"; case 84: return L"ctf"; case 85: return L"mit-ml-dev"; case 86: return L"mfcobol"; case 87: { if (proto == IPPROTO_TCP) return L"priv-term-l"; break; } case 88: return L"kerberos-sec"; case 89: return L"su-mit-tg"; case 90: return L"dnsix"; case 91: return L"mit-dov"; case 92: return L"npp"; case 93: return L"dcp"; case 94: return L"objcall"; case 95: return L"supdup"; case 96: return L"dixie"; case 97: return L"swift-rvf"; case 98: return L"metagram"; case 100: { if (proto == IPPROTO_TCP) return L"newacct"; break; } case 101: return L"hostname"; case 105: return L"csnet-ns"; case 106: { if (proto == IPPROTO_TCP) return L"pop3pw"; break; } case 107: return L"rtelnet"; case 108: return L"snagas"; case 109: return L"pop2"; case 110: return L"pop3"; case 111: return L"rpcbind"; case 112: return L"mcidas"; case 113: { if (proto == IPPROTO_TCP) { return L"ident"; } else if (proto == IPPROTO_UDP) { return L"auth"; } break; } case 114: return L"audionews"; case 115: return L"sftp"; case 116: return L"ansanotify"; case 117: return L"uucp-path"; case 118: return L"sqlserv"; case 119: return L"nntp"; case 121: return L"erpc"; case 123: return L"ntp"; case 125: return L"locus-map"; case 126: return L"unitary"; case 127: return L"locus-con"; case 128: return L"gss-xlicen"; case 129: return L"pwdgen"; case 130: return L"cisco-fna"; case 131: return L"cisco-tna"; case 132: return L"cisco-sys"; case 133: return L"statsrv"; case 134: return L"ingres-net"; 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 140: return L"emfis-data"; case 141: return L"emfis-cntl"; case 142: return L"bl-idm"; case 143: return L"imap"; case 144: return L"news"; case 145: return L"uaac"; case 148: return L"cronus"; case 149: return L"aed-512"; case 150: return L"sql-net"; case 152: return L"bftp"; case 153: return L"sgmp"; case 154: return L"netsc-prod"; case 155: return L"netsc-dev"; 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 163: return L"cmip-man"; case 164: return L"cmip-agent"; case 165: return L"xns-courier"; case 166: return L"s-net"; case 167: return L"namp"; case 168: return L"rsvd"; case 169: return L"send"; case 170: return L"print-srv"; case 171: return L"multiplex"; case 172: return L"cl-1"; case 173: return L"xyplex-mux"; case 174: return L"mailq"; case 175: return L"vmnet"; case 176: return L"genrad-mux"; case 177: return L"xdmcp"; case 178: return L"nextstep"; case 179: return L"bgp"; case 180: return L"ris"; case 181: return L"unify"; case 182: return L"audit"; case 183: return L"ocbinder"; case 184: return L"ocserver"; case 185: return L"remote-kis"; case 186: return L"kis"; case 187: return L"aci"; case 188: return L"mumps"; case 189: return L"qft"; case 190: { if (proto == IPPROTO_TCP) { return L"gacp"; } else if (proto == IPPROTO_UDP) { return L"cacp"; } break; } case 191: return L"prospero"; case 192: return L"osu-nms"; case 193: return L"srmp"; 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 198: return L"dls-mon"; case 199: return L"smux"; case 200: return L"src"; case 201: return L"at-rtmp"; case 202: return L"at-nbp"; case 203: return L"at-3"; case 204: return L"at-echo"; case 205: return L"at-5"; case 206: return L"at-zis"; case 207: return L"at-7"; case 208: return L"at-8"; case 209: return L"tam"; // qmtp case 212: return L"anet"; case 213: return L"ipx"; case 214: return L"vmpwscs"; case 215: return L"softpc"; case 216: return L"atls"; case 217: return L"dbase"; case 218: return L"mpp"; case 219: return L"uarps"; case 220: return L"imap3"; case 221: case 222: return L"rsh-spx"; case 223: return L"cdc"; case 224: return L"masqdialer"; case 242: return L"direct"; case 243: return L"sur-meas"; case 244: return L"dayna"; case 245: return L"link"; case 246: return L"dsp3270"; case 247: return L"subntbcst_tftp"; case 248: return L"bhfhs"; case 256: { if (proto == IPPROTO_TCP) { return L"fw1-secureremote"; } else if (proto == IPPROTO_UDP) { return L"rap"; } break; } case 257: { if (proto == IPPROTO_TCP) return L"fw1-mc-fwmodule"; break; } case 258: return L"yak-chat"; case 259: { if (proto == IPPROTO_TCP) { return L"esro-gen"; } else if (proto == IPPROTO_UDP) { return L"firewall1-rdp"; } break; } case 260: return L"openport"; case 261: return L"nsiiops"; case 262: return L"arcisdms"; case 264: return L"fw1-or-bgmp"; case 265: { if (proto == IPPROTO_TCP) { return L"maybe-fw1"; } else if (proto == IPPROTO_UDP) { return L"x-bone-ctl"; } break; } case 266: return L"sst"; case 267: return L"td-service"; case 268: return L"td-replica"; case 269: return L"manet"; case 270: return L"gist"; case 271: { if (proto == IPPROTO_TCP) return L"pt-tls"; break; } case 280: return L"http-mgmt"; case 281: return L"personal-link"; case 282: return L"cableport-ax"; case 283: return L"rescap"; case 284: return L"corerjd"; case 286: return L"fxp"; case 287: return L"k-block"; case 308: return L"novastorbakcup"; case 309: return L"entrusttime"; case 310: return L"bhmds"; case 311: return L"asip-webadmin"; case 312: return L"vslmp"; case 313: return L"magenta-logic"; case 314: return L"opalis-robot"; case 318: return L"pkix-timestamp"; case 319: return L"ptp-event"; case 320: return L"ptp-general"; case 321: return L"pip"; case 322: return L"rtsps"; case 323: { if (proto == IPPROTO_TCP) return L"rpki-rtr"; break; } case 324: { if (proto == IPPROTO_TCP) return L"rpki-rtr-tls"; break; } case 333: return L"texar"; case 344: return L"pdap"; case 345: return L"pawserv"; case 346: return L"zserv"; case 347: return L"fatserv"; case 348: return L"csi-sgwp"; case 349: return L"mftp"; case 353: return L"ndsauth"; case 355: return L"datex-asn"; case 358: return L"shrinkwrap"; case 359: return L"tenebris_nts"; case 362: return L"srssend"; case 363: return L"rsvp_tunnel"; case 364: return L"aurora-cmgr"; case 365: return L"dtk"; case 367: return L"mortgageware"; case 369: return L"rpc2portmap"; case 370: return L"codaauth2"; case 375: return L"hassle"; case 376: return L"nip"; case 377: return L"tnETOS"; case 378: return L"dsETOS"; case 381: return L"hp-collector"; case 382: return L"hp-managed-node"; case 383: return L"hp-alarm-mgr"; case 384: return L"arns"; case 386: return L"asa"; case 387: return L"aurp"; case 388: return L"unidata-ldm"; case 389: return L"ldap"; case 391: return L"synotics-relay"; case 392: return L"synotics-broker"; case 393: return L"dis"; case 398: return L"kryptolan"; case 399: return L"iso-tsap-c2"; case 401: return L"ups"; case 402: return L"genie"; case 403: return L"decap"; case 404: { if (proto == IPPROTO_UDP) return L"nced"; break; } case 405: return L"ncld"; case 406: return L"imsp"; case 407: return L"timbuktu"; case 410: return L"decladebug"; case 411: return L"rmt"; case 412: return L"synoptics-trap"; case 413: return L"smsp"; case 414: return L"infoseek"; case 415: return L"bnet"; case 417: return L"onmux"; case 418: return L"hyper-g"; case 419: return L"ariel1"; case 420: return L"smpte"; case 421: return L"ariel2"; case 422: return L"ariel3"; case 423: return L"opc-job-start"; case 424: return L"opc-job-track"; case 427: return L"svrloc"; case 428: return L"ocs_cmu"; case 429: return L"ocs_amu"; case 430: return L"utmpsd"; case 431: return L"utmpcd"; case 433: return L"nnsp"; case 434: return L"mobileip-agent"; case 435: return L"mobilip-mn"; case 437: return L"comscm"; case 442: return L"cvc_hostd"; case 443: { if (proto == IPPROTO_TCP) { return L"https"; } else if (proto == IPPROTO_UDP) { return L"quic"; } break; } case 444: return L"snpp"; case 445: return L"microsoft-ds"; case 450: return L"tserver"; case 456: return L"macon"; case 458: return L"appleqtc"; case 464: return L"kpasswd5"; // kerberos case 465: return L"smtps"; case 469: return L"rcp"; case 470: return L"scx-proxy"; case 471: return L"mondex"; case 473: return L"hybrid-pop"; case 475: return L"tcpnethaspsrv"; case 482: { if (proto == IPPROTO_UDP) return L"xlog"; break; } case 485: return L"powerburst"; case 486: { if (proto == IPPROTO_UDP) { return L"sstats"; } else if (proto == IPPROTO_UDP) { return L"avian"; } break; } case 488: return L"gss-http"; case 489: return L"nest-protocol"; case 490: return L"micom-pfs"; case 491: return L"go-login"; case 494: return L"pov-ray"; case 495: return L"intecourier"; case 496: return L"pim-rp-disc"; case 497: return L"retrospect"; case 499: return L"iso-ill"; case 500: return L"isakmp"; case 501: return L"stmf"; case 502: return L"mbap"; case 503: return L"intrinsa"; case 505: return L"mailbox-lm"; case 509: return L"snare"; case 510: return L"fcp"; case 511: return L"passgo"; case 512: { if (proto == IPPROTO_TCP) { return L"exec"; } else if (proto == IPPROTO_TCP) { return L"biff"; } break; } case 513: { if (proto == IPPROTO_TCP) { return L"login"; } else if (proto == IPPROTO_TCP) { return L"who"; } break; } case 514: { if (proto == IPPROTO_TCP) { return L"shell"; } else if (proto == IPPROTO_TCP) { return L"syslog"; } break; } case 515: return L"printer"; case 517: { if (proto == IPPROTO_TCP) { return L"talk"; } else if (proto == IPPROTO_TCP) { return L"talk"; } break; } case 518: return L"ntalk"; case 519: return L"utime"; case 520: { if (proto == IPPROTO_TCP) { return L"efs"; } else if (proto == IPPROTO_TCP) { return L"route"; } break; } case 521: return L"ripng"; case 524: return L"ncp"; case 525: return L"timed"; case 526: return L"tempo"; case 530: return L"courier"; // rpc case 531: return L"conference"; case 532: return L"netnews"; case 533: return L"netwall"; case 537: return L"nmsp"; case 540: return L"uucp"; case 541: return L"uucp-rlogin"; case 543: return L"klogin"; case 544: return L"kshell"; case 545: { if (proto == IPPROTO_TCP) return L"ekshell"; break; } case 546: return L"dhcpv6-client"; case 547: return L"dhcpv6-server"; case 548: return L"afp"; case 550: return L"new-rwho"; case 554: return L"rtsp"; case 555: return L"dsf"; case 556: return L"remotefs"; case 558: return L"sdnskmp"; case 560: return L"rmonitor"; case 561: return L"monitor"; case 562: return L"chshell"; case 563: return L"snews"; case 565: return L"whoami"; case 568: return L"ms-shuttle"; case 569: return L"ms-rome"; case 574: return L"ftp-agent"; case 580: return L"sntp-heartbeat"; case 582: return L"scc-security"; case 584: return L"keyserver"; case 585: return L"imap4-ssl"; case 587: return L"submission"; case 591: case 8000: case 8008: case 8080: return L"http-alt"; case 593: return L"http-rpc-epmap"; case 609: return L"npmp-trap"; case 610: return L"npmp-local"; case 611: return L"npmp-gui"; case 614: return L"sshell"; case 620: return L"sco-websrvrmgr"; case 624: return L"cryptoadmin"; case 625: return L"apple-xsrvr-admin"; case 626: { if (proto == IPPROTO_TCP) { return L"apple-imap-admin"; } else if (proto == IPPROTO_UDP) { return L"serialnumberd"; } break; } case 628: return L"qmqp"; case 629: return L"3com-amp3"; case 630: return L"rda"; case 631: return L"ipp"; case 633: return L"servstat"; case 636: { if (proto == IPPROTO_TCP) { return L"ldapssl"; } else if (proto == IPPROTO_UDP) { return L"ldaps"; } break; } case 639: return L"msdp"; case 646: return L"ldp"; case 647: return L"dhcp-failover"; case 648: return L"rrp"; case 651: return L"ieee-mms"; case 652: return L"hello-port"; case 653: return L"repscmd"; case 656: return L"spmp"; case 658: return L"tenfold"; case 660: return L"mac-srvr-admin"; case 662: return L"pftp"; case 663: return L"purenoise"; case 666: return L"doom"; // khe-khe-khe! case 667: return L"disclose"; case 674: return L"acapc"; // stalker case 678: return L"ggf-ncp"; case 687: return L"asipregistry"; case 691: { if (proto == IPPROTO_UDP) return L"msexch-routing"; break; } case 697: return L"msexch-routing"; case 699: return L"accessnetwork"; case 701: return L"lmp"; case 707: return L"borland-dsj"; case 709: return L"entrustmanager"; case 710: return L"entrust-ash"; case 711: return L"cisco-tdp"; case 713: return L"iris-xpc"; case 714: return L"iris-xpcs"; case 716: return L"pana"; case 740: return L"netcp"; case 741: return L"netgw"; case 742: return L"netrcs"; case 747: return L"fujitsu-dev"; case 751: return L"kadmin"; case 754: { if (proto == IPPROTO_TCP) { return L"krb_prop"; } else if (proto == IPPROTO_UDP) { return L"tell"; } break; } case 758: return L"nlogin"; case 761: { if (proto == IPPROTO_TCP) { return L"kpasswd"; } else if (proto == IPPROTO_UDP) { return L"rxe"; } break; } case 767: return L"phonebook"; case 773: { if (proto == IPPROTO_TCP) { return L"submit"; } else if (proto == IPPROTO_UDP) { return L"notify"; } break; } case 777: return L"multiling-http"; case 783: { if (proto == IPPROTO_TCP) return L"spamassassin"; break; } case 799: { if (proto == IPPROTO_TCP) return L"controlit"; break; } case 800: return L"mdbs_daemon"; case 802: { if (proto == IPPROTO_TCP) return L"mbap-s"; break; } case 808: { if (proto == IPPROTO_TCP) return L"ccproxy-http"; break; } case 810: return L"fcp-udp"; case 828: return L"itm-mcell-s"; case 829: return L"pkix-3-ca-ra"; case 830: return L"netconf-ssh"; case 831: return L"netconf-beep"; case 832: return L"netconfsoaphttp"; case 833: return L"netconfsoapbeep"; case 847: return L"dhcp-failover2"; case 853: { if (proto == IPPROTO_TCP) return L"domain-s"; break; } case 854: { if (proto == IPPROTO_TCP) return L"dlep"; break; } case 860: return L"iscsi"; case 861: return L"owamp-control"; case 862: return L"twamp-control"; case 873: return L"rsync"; case 888: return L"accessbuilder"; case 901: { if (proto == IPPROTO_TCP) return L"samba-swat"; break; } case 910: return L"kink"; case 950: { if (proto == IPPROTO_TCP) return L"oftep-rpc"; break; } case 989: return L"ftps-data"; case 990: return L"ftps"; case 991: return L"nas"; case 992: return L"telnets"; case 993: return L"imaps"; case 994: return L"ircs"; case 995: return L"pop3s"; case 1001: return L"webpush"; case 1002: { if (proto == IPPROTO_TCP) return L"windows-icfw"; break; } case 1025: { if (proto == IPPROTO_TCP) { return L"NFS-or-IIS"; } else if (proto == IPPROTO_UDP) { return L"blackjack"; } break; } case 1026: { if (proto == IPPROTO_UDP) return L"win-rpc"; break; } case 1027: { if (proto == IPPROTO_TCP) return L"IIS"; break; } case 1028: { if (proto == IPPROTO_UDP) return L"ms-lsa"; break; } case 1029: { if (proto == IPPROTO_TCP) return L"ms-lsa"; break; } case 1033: { if (proto == IPPROTO_TCP) { return L"netinfo"; } else if (proto == IPPROTO_UDP) { return L"netinfo-local"; } break; } case 1035: { if (proto == IPPROTO_TCP) { return L"multidropper"; } else if (proto == IPPROTO_UDP) { return L"mxxrlogin"; } break; } case 1050: { if (proto == IPPROTO_TCP) { return L"java-or-OTGfileshare"; } else if (proto == IPPROTO_UDP) { return L"cma"; } break; } case 1080: return L"socks"; case 1085: return L"webobjects"; case 1096: return L"cnrprotocol"; case 1098: return L"rmiactivation"; case 1099: return L"rmiregistry"; case 1100: return L"mctp"; case 1109: { if (proto == IPPROTO_TCP) return L"kpop"; // kerberos break; } case 1110: return L"nfsd"; case 1111: return L"lmsocialserver"; case 1112: { if (proto == IPPROTO_TCP) { return L"msql"; } else if (proto == IPPROTO_UDP) { return L"icp"; } break; } case 1114: case 4333: return L"mini-sql"; case 1119: return L"bnetgame"; case 1120: return L"bnetfile"; case 1121: return L"rmpp"; case 1123: return L"murray"; case 1130: return L"casp"; case 1131: return L"caspssl"; case 1138: return L"encrypted_admin"; case 1147: return L"capioverlan"; case 1150: return L"blaze"; case 1153: return L"c1222-acse"; case 1155: return L"nfa"; case 1159: return L"oracle-oms"; case 1164: return L"qsm-proxy"; case 1165: return L"qsm-gui"; case 1166: return L"qsm-remote"; case 1168: return L"vchat"; case 1183: return L"llsurfup-http"; case 1184: return L"llsurfup-https"; case 1186: return L"mysql-cluster"; case 1187: return L"alias"; case 1188: return L"hp-webadmin"; case 1194: return L"openvpn"; case 1214: return L"fasttrack"; // kazaa case 1220: { if (proto == IPPROTO_TCP) { return L"quicktime"; } else if (proto == IPPROTO_UDP) { return L"qt-serveradmin"; } break; } case 1234: { if (proto == IPPROTO_TCP) { return L"hotline"; } else if (proto == IPPROTO_UDP) { return L"search-agent"; } break; } case 1257: return L"shockwave2"; case 1258: return L"opennl"; case 1259: return L"opennl-voice"; case 1270: { if (proto == IPPROTO_TCP) { return L"ssserver"; } else if (proto == IPPROTO_UDP) { return L"opsmgr"; // Microsoft Operations Manager } break; } case 1273: return L"emc-gateway"; case 1307: return L"pacmand"; case 1311: return L"rxmon"; case 1318: return L"krb5gatekeeper"; case 1321: return L"pip"; case 1333: return L"passwrd-policy"; case 1336: return L"ischat"; case 1337: { if (proto == IPPROTO_TCP) { return L"waste"; } else if (proto == IPPROTO_UDP) { return L"menandmice-dns"; } break; } case 1368: return L"screencast"; case 1380: return L"telesis-licman"; case 1381: return L"apple-licman"; case 1384: return L"os-licman"; case 1433: return L"ms-sql-s"; case 1434: return L"ms-sql-m"; case 1462: return L"world-lm"; case 1498: return L"watcom-sql"; case 1525: { if (proto == IPPROTO_TCP) { return L"orasrv"; } else if (proto == IPPROTO_UDP) { return L"oracle"; } break; } case 1529: { if (proto == IPPROTO_TCP) { return L"support"; } else if (proto == IPPROTO_UDP) { return L"coauthor"; } break; } case 1590: return L"gemini-lm"; case 1630: return L"oraclenet8cman"; case 1687: return L"nsjtp-ctrl"; case 1688: return L"nsjtp-data"; case 1689: return L"firefox"; case 1701: { if (proto == IPPROTO_TCP) { return L"l2f"; } else if (proto == IPPROTO_UDP) { return L"L2TP"; } break; } case 1702: return L"deskshare"; case 1720: { if (proto == IPPROTO_TCP) { return L"h323q931"; } else if (proto == IPPROTO_UDP) { return L"h323q931"; } break; } case 1723: return L"pptp"; case 1726: return L"iberiagames"; case 1733: return L"siipat"; case 1745: return L"remote-winsock"; case 1748: return L"oracle-em1"; case 1750: return L"sslp"; case 1755: { if (proto == IPPROTO_TCP) { return L"wms"; } else if (proto == IPPROTO_UDP) { return L"ms-streaming"; } break; } case 1758: return L"tftp-mcast"; case 1761: { if (proto == IPPROTO_TCP) { return L"landesk-rc"; } else if (proto == IPPROTO_UDP) { return L"cft-0"; } break; } case 1762: { if (proto == IPPROTO_TCP) { return L"landesk-rc"; } else if (proto == IPPROTO_UDP) { return L"cft-1"; } break; } case 1763: { if (proto == IPPROTO_TCP) { return L"landesk-rc"; } else if (proto == IPPROTO_UDP) { return L"cft-2"; } break; } case 1764: { if (proto == IPPROTO_TCP) { return L"landesk-rc"; } else if (proto == IPPROTO_UDP) { return L"cft-3"; } break; } case 1789: return L"hello"; case 1793: return L"rsc-robot"; case 1795: return L"dpi-proxy"; case 1801: return L"msmq"; // Microsoft Message Queuing case 1833: return L"udpradio"; case 1850: return L"gsi"; case 1862: return L"mysql-cm-agent"; case 1863: return L"msnp"; // MSN Messenger case 1900: case 5000: return L"upnp"; case 1931: return L"amdsched"; case 1981: return L"p2pq"; case 2000: return L"cisco-sccp"; case 2001: { if (proto == IPPROTO_TCP) { return L"dc"; } else if (proto == IPPROTO_UDP) { return L"wizard"; } break; } case 2009: { if (proto == IPPROTO_TCP) { return L"news"; } else if (proto == IPPROTO_UDP) { return L"whosockami"; } break; } case 2019: { if (proto == IPPROTO_TCP) { return L"whosockami"; } else if (proto == IPPROTO_UDP) { return L"about"; } break; } case 2054: return L"weblogin"; case 2086: return L"gnunet"; case 2105: return L"eklogin"; // kerberos case 2106: return L"ekshell"; // kerberos case 2115: return L"kdm"; // Key Distribution Manager case 2121: { if (proto == IPPROTO_TCP) { return L"ccproxy-ftp"; } else if (proto == IPPROTO_UDP) { return L"scientia-ssdb"; } break; } case 2129: return L"cs-live"; case 2137: return L"connect"; case 2142: return L"tdmoip"; case 2159: return L"gdbremote"; case 2164: return L"ddns-v3"; // Dynamic DNS Version 3 case 2167: return L"raw-serial"; // Raw Async Serial Link case 2171: return L"msfw-storage"; // MS Firewall Storage case 2172: return L"msfw-s-storage"; // MS Firewall SecureStorage case 2173: return L"msfw-replica"; // MS Firewall Replication case 2174: return L"msfw-array"; // MS Firewall Intra Array case 2175: return L"ms-airsync"; // Microsoft Desktop AirSync Protocol case 2179: return L"ms-vmrdp"; // Microsoft RDP for virtual machines case 2191: return L"tvbus"; case 2193: return L"drwcs"; // Dr.Web Enterprise Management Service case 2213: return L"kali"; case 2273: return L"mysql-im"; // MySQL Instance Manager case 2311: return L"messageservice"; // Message Service case 2169: { if (proto == IPPROTO_TCP) return L"bif-p2p"; break; } case 2374: return L"hydra"; case 2375: { if (proto == IPPROTO_TCP) return L"docker"; break; } case 2376: { if (proto == IPPROTO_TCP) return L"docker"; break; } case 2377: { if (proto == IPPROTO_TCP) return L"swarm"; break; } case 2382: return L"ms-olap3"; // Microsoft OLAP case 2383: return L"ms-olap4"; // Microsoft OLAP case 2525: return L"ms-v-worlds"; // MS V-Worlds case 2679: return L"syncserverssl"; case 2710: return L"sso-service"; case 2711: return L"sso-control"; case 2717: return L"pn-requester"; case 2718: return L"pn-requester2"; case 2723: return L"watchdog-nt"; case 2725: return L"msolap-ptp2"; case 2775: return L"smpp"; case 2784: return L"www-dev"; case 2869: return L"icslap"; case 2948: return L"wap-push"; case 2949: return L"wap-pushsecure"; case 2947: return L"symantec-av"; case 2979: return L"h263-video"; case 3000: { if (proto == IPPROTO_TCP) { return L"ppp"; } if (proto == IPPROTO_UDP) { return L"hbci"; } break; } case 3074: return L"xbox"; case 3128: { if (proto == IPPROTO_TCP) return L"squid-http"; break; } case 3224: return L"aes-discovery"; case 3260: return L"iscsi"; case 3295: return L"dyniplookup"; case 3306: return L"mysql"; case 3326: return L"sftu"; // ;) case 3343: return L"ms-cluster-net"; case 3352: return L"ssql"; // Scalable SQL case 3389: return L"ms-wbt-server"; // Microsoft Remote Display Protocol (aka ms-term-serv, microsoft-rdp) case 3407: return L"ldap-admin"; case 3476: return L"nppmp"; // NVIDIA Mgmt Protocol case 3500: return L"rtmp-port"; case 3535: return L"ms-la"; case 3540: return L"pnrp-port"; case 3544: return L"teredo"; case 3547: return L"symantec-sim"; case 3550: return L"ssmpp"; // Secure SMPP case 3558: return L"mcp-port"; // MCP user port case 3559: return L"cctv-port"; // CCTV control port case 3563: return L"watcomdebug"; case 3587: return L"p2pgroup"; case 3702: return L"ws-discovery"; case 3713: return L"tftps"; case 3721: return L"xsync"; case 3724: return L"blizwow"; case 4041: return L"ltp"; // Location Tracking Protocol case 4180: return L"httpx"; case 4317: { if (proto == IPPROTO_TCP) return L"opentelemetry"; break; } case 4321: return L"rwhois"; // Remote Who Is case 4500: { if (proto == IPPROTO_UDP) return L"nat-t-ike"; break; } case 4554: return L"msfrs"; // MS FRS Replication case 4687: return L"nst"; // Network Scanner Tool FTP 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 5145: return L"rmonitor_secure"; case 5190: case 5191: case 5192: case 5193: 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 5359: return L"ms-alerter"; case 5360: return L"ms-sideshow"; case 5361: return L"ms-s-sideshow"; case 5362: return L"serverwsd2"; // Microsoft Windows Server WSD2 Service case 5432: return L"postgresql"; case 5631: return L"pcanywheredata"; case 5632: return L"pcanywherestat"; case 5666: { if (proto == IPPROTO_TCP) return L"nrpe"; // Nagios Remote Plugin Executor break; } case 5687: { if (proto == IPPROTO_TCP) return L"gog-multiplayer"; break; } case 5741: return L"ida-discover1"; case 5742: return L"ida-discover2"; case 5800: case 5801: case 5802: case 5803: { if (proto == IPPROTO_TCP) return L"vnc-http"; break; } case 5900: { if (proto == IPPROTO_TCP) return L"vnc"; break; } case 5901: { if (proto == IPPROTO_TCP) return L"vnc-1"; break; } case 5902: { if (proto == IPPROTO_TCP) return L"vnc-2"; break; } case 5903: { if (proto == IPPROTO_TCP) return L"vnc-3"; break; } case 5938: { if (proto == IPPROTO_TCP) return L"teamviewer"; break; } case 6000: case 6001: case 6002: case 6003: case 6004: case 6005: case 6006: case 6007: case 6008: case 6009: case 6010: case 6011: case 6012: case 6013: case 6014: case 6015: case 6016: case 6017: case 6018: case 6019: case 6020: case 6021: case 6022: case 6023: case 6024: case 6025: case 6026: case 6027: case 6028: case 6029: case 6030: case 6031: case 6032: case 6033: case 6034: case 6035: case 6036: case 6037: case 6038: case 6039: case 6040: case 6041: case 6042: case 6043: case 6044: case 6045: case 6046: case 6047: case 6048: case 6049: case 6050: case 6051: case 6052: case 6053: case 6054: case 6055: case 6056: case 6057: case 6058: case 6059: case 6060: case 6061: case 6062: case 6063: return L"x11"; case 6074: return L"max"; // Microsoft Max case 6076: { if (proto == IPPROTO_TCP) return L"msft-dpm-cert"; // Microsoft DPM WCF Certificates break; } case 6222: case 6662: // deprecated! return L"radmind"; case 6346: return L"gnutella"; case 6347: return L"gnutella2"; case 6620: return L"kftp-data"; // Kerberos V5 FTP Data case 6621: return L"kftp"; // Kerberos V5 FTP Control case 6622: return L"mcftp"; case 6665: case 6666: case 6667: case 6668: case 6669: case 6670: { if (proto == IPPROTO_TCP) { return L"irc"; } if (proto == IPPROTO_UDP) { return L"ircu"; } break; } case 6881: { if (proto == IPPROTO_TCP) return L"bittorrent-tracker"; break; } case 7070: { if (proto == IPPROTO_TCP) return L"realserver"; break; } case 7235: { if (proto == IPPROTO_TCP) return L"aspcoordination"; break; } case 8021: { if (proto == IPPROTO_TCP) return L"ftp-proxy"; break; } case 8333: case 18333: { if (proto == IPPROTO_TCP) return L"bitcoin"; break; } case 8443: { if (proto == IPPROTO_TCP) { return L"https-alt"; } else if (proto == IPPROTO_UDP) { return L"pcsync-https"; } break; } case 8444: return L"pcsync-http"; case 8999: return L"bctp"; case 9418: return L"git"; case 9800: return L"davsrc"; // WebDav Source Port case 10107: return L"bctp-server"; case 11371: { if (proto == IPPROTO_TCP) { return L"pksd"; } else if (proto == IPPROTO_UDP) { return L"hkp"; } break; } case 25565: { if (proto == IPPROTO_TCP) return L"minecraft"; break; } case 26000: return L"quake"; case 27015: { if (proto == IPPROTO_UDP) return L"halflife"; break; } case 27017: case 27018: case 27019: case 28017: { if (proto == IPPROTO_TCP) return L"mongod"; break; } case 27500: { if (proto == IPPROTO_UDP) return L"quakeworld"; break; } case 27910: { if (proto == IPPROTO_UDP) return L"quake2"; break; } case 27960: { if (proto == IPPROTO_UDP) return L"quake3"; break; } case 28240: return L"siemensgsm"; case 33434: return L"traceroute"; } return NULL; } ================================================ FILE: src/db.h ================================================ // simplewall // Copyright (c) 2019-2025 Henry++ #pragma once // profile types typedef enum _ENUM_TYPE_XML { XML_TYPE_PROFILE = 3, XML_TYPE_PROFILE_INTERNAL = 4, } ENUM_TYPE_XML; // profile versions typedef enum _ENUM_VERSION_XML { // v3.0.2: first major update, rule attribute "apps" now separated by "|" XML_VERSION_3 = 3, // v3.4: added "rules_custom" into internal profile and "os_version" for rule attributes XML_VERSION_4 = 4, // v3.7: added hashes support, use encrypted file format and added comments for apps/rules XML_VERSION_5 = 5, } ENUM_VERSION_XML; typedef struct _DB_INFORMATION { R_XML_LIBRARY xml_library; PR_BYTE bytes; PR_BYTE hash; LONG64 timestamp; ENUM_VERSION_XML version; ENUM_TYPE_XML type; } DB_INFORMATION, *PDB_INFORMATION; // Offset Length Description // ------------------------------------------ // 0 3 FOURCC string 'SWC' // 4 1 Body information flag // 36 32 SHA256 checksum of the decrypted bytes // 68 whole Body contained specified data static const BYTE profile2_fourcc[] = { 0x53, 0x57, 0x43, // 'S', 'W', 'C' }; static const BYTE profile2_fourcc_old[] = { 0x73, 0x77, 0x63, // 's', 'w', 'c' }; #define XML_VERSION_MINIMAL XML_VERSION_3 #define XML_VERSION_CURRENT XML_VERSION_4 #define XML_VERSION_MAXIMUM XML_VERSION_5 #define XML_PROFILE_FILE L"profile.xml" #define XML_PROFILE_INTERNAL L"profile_internal.xml" #define PROFILE2_ID_PLAIN ((BYTE)(0x30)) #define PROFILE2_ID_COMPRESSED ((BYTE)(0x31)) #define PROFILE2_ID_ENCRYPTED ((BYTE)(0x32)) #define PROFILE2_KEY "Gc(j1EptodnKP?{ZT!SlMVip[fJIs&Ci3fOqjATfp@h,q0(]QVaGs5Iht3)/b:Ll" #define PROFILE2_FOURCC_LENGTH sizeof (profile2_fourcc) + sizeof (BYTE) #define PROFILE2_SHA256_LENGTH 32UL #define PROFILE2_HEADER_LENGTH (PROFILE2_FOURCC_LENGTH + PROFILE2_SHA256_LENGTH) _Success_ (SUCCEEDED (return)) HRESULT _app_db_initialize ( _Out_ PDB_INFORMATION db_info, _In_ BOOLEAN is_reader ); VOID _app_db_destroy ( _Inout_ PDB_INFORMATION db_info ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_encrypt ( _In_ PR_BYTEREF bytes, _Out_ PR_BYTE_PTR out_buffer ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_decrypt ( _In_ PR_BYTEREF buffer, _Out_ PR_BYTE_PTR out_buffer ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_gethash ( _In_ PR_BYTEREF bytes, _Out_ PR_BYTE_PTR out_buffer ); BYTE _app_getprofiletype (); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_ishashvalid ( _In_ PR_BYTEREF buffer, _In_ PR_BYTEREF hash_bytes ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_openfrombuffer ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STORAGE buffer, _In_ ENUM_VERSION_XML min_version, _In_ ENUM_TYPE_XML type ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_openfromfile ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STRING path, _In_ ENUM_VERSION_XML min_version, _In_ ENUM_TYPE_XML type ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_decodebody ( _Inout_ PDB_INFORMATION db_info ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_encodebody ( _Inout_ PDB_INFORMATION db_info, _In_ BYTE profile_type, _Out_ PR_BYTE_PTR out_buffer ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_generatebody ( _In_ BYTE profile_type, _In_ PR_BYTE hash_value, _In_ PR_BYTE buffer, _Out_ PR_BYTE_PTR out_buffer ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_decodebuffer ( _Inout_ PDB_INFORMATION db_info, _In_ ENUM_TYPE_XML type, _In_ ENUM_VERSION_XML min_version ); BOOLEAN _app_db_parse ( _Inout_ PDB_INFORMATION db_info, _In_ ENUM_TYPE_XML type ); VOID _app_db_parse_app ( _Inout_ PDB_INFORMATION db_info ); VOID _app_db_parse_rule ( _Inout_ PDB_INFORMATION db_info, _In_ ENUM_TYPE_DATA type ); VOID _app_db_parse_ruleconfig ( _Inout_ PDB_INFORMATION db_info ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_savetofile ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STRING path, _In_ ENUM_VERSION_XML version, _In_ ENUM_TYPE_XML type, _In_ LONG64 timestamp ); _Success_ (NT_SUCCESS (return)) NTSTATUS _app_db_save_streamtofile ( _Inout_ PDB_INFORMATION db_info, _In_ PR_STRING path ); VOID _app_db_save_app ( _Inout_ PDB_INFORMATION db_info ); VOID _app_db_save_rule ( _Inout_ PDB_INFORMATION db_info ); VOID _app_db_save_ruleconfig ( _Inout_ PDB_INFORMATION db_info ); _Ret_maybenull_ LPCWSTR _app_db_getconnectionstatename ( _In_ ULONG state ); _Ret_maybenull_ PR_STRING _app_db_getdirectionname ( _In_ FWP_DIRECTION direction, _In_ BOOLEAN is_loopback, _In_ BOOLEAN is_localized ); LPCWSTR _app_db_getprotoname ( _In_ ULONG proto, _In_ ADDRESS_FAMILY af ); _Ret_maybenull_ LPCWSTR _app_db_getservicename ( _In_ UINT16 port, _In_ UINT8 proto ); ================================================ FILE: src/editor.c ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #include "global.h" _Ret_maybenull_ PEDITOR_CONTEXT _app_editor_createwindow ( _In_ HWND hwnd, _In_ PVOID lparam, _In_ INT page_id, _In_ BOOLEAN is_settorules ) { PEDITOR_CONTEXT context; context = _r_mem_allocate (sizeof (EDITOR_CONTEXT)); context->ptr_app = lparam; context->page_id = page_id; context->is_settorules = is_settorules; if (_r_wnd_createmodalwindow (_r_sys_getimagebase (), MAKEINTRESOURCE (IDD_EDITOR), hwnd, &EditorProc, context)) return context; _app_editor_deletewindow (context); return NULL; } VOID _app_editor_deletewindow ( _In_ PEDITOR_CONTEXT context ) { _r_mem_free (context); } _Ret_maybenull_ PEDITOR_CONTEXT _app_editor_getcontext ( _In_ HWND hwnd ) { PEDITOR_CONTEXT context; context = _r_wnd_getcontext (hwnd, SHORT_MAX); return context; } VOID _app_editor_setcontext ( _In_ HWND hwnd, _In_ PEDITOR_CONTEXT context ) { _r_wnd_setcontext (hwnd, SHORT_MAX, context); } VOID _app_editor_addtabitem ( _In_ HWND hwnd, _In_ UINT locale_id, _In_ INT dlg_id, _In_ PEDITOR_CONTEXT context ) { HWND htab; htab = _r_wnd_createwindow (_r_sys_getimagebase (), MAKEINTRESOURCE (dlg_id), hwnd, &EditorPagesProc, context); if (!htab) return; _r_tab_additem (hwnd, IDC_TAB, INT_ERROR, _r_locale_getstring (locale_id), I_DEFAULT, (LPARAM)htab); _r_tab_adjustchild (hwnd, IDC_TAB, htab); BringWindowToTop (htab); // HACK!!! _r_wnd_sendmessage (htab, 0, RM_INITIALIZE, 0, 0); } VOID _app_editor_settabtitle ( _In_ HWND hwnd, _In_ INT listview_id ) { WCHAR buffer[128]; HWND hparent; UINT locale_id; INT checked_count; INT tab_id; if (listview_id == IDC_RULE_APPS_ID) { locale_id = IDS_TAB_APPS; tab_id = 2; } else if (listview_id == IDC_APP_RULES_ID) { locale_id = IDS_TRAY_RULES; tab_id = 1; } else { return; } hparent = GetParent (hwnd); if (!hparent) return; checked_count = _r_listview_getitemcheckedcount (hwnd, listview_id); _r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s (%d)", _r_locale_getstring (locale_id), checked_count); _r_tab_setitem (hparent, IDC_TAB, tab_id, buffer, I_DEFAULT, I_DEFAULT); } _Ret_maybenull_ PR_STRING _app_editor_getrulesfromlistview ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ INT exclude_id ) { R_STRINGREF divider_sr = PR_STRINGREF_INIT (DIVIDER_RULE); R_STRINGBUILDER sb; PR_STRING string; INT item_count; item_count = _r_listview_getitemcount (hwnd, ctrl_id); if (!item_count) return NULL; _r_obj_initializestringbuilder (&sb, 512); for (INT i = 0; i < item_count; i++) { if (i == exclude_id) continue; string = _r_listview_getitemtext (hwnd, ctrl_id, i, 0); if (string) { _r_str_trimstring2 (&string->sr, DIVIDER_RULE DIVIDER_TRIM, 0); if (!_r_obj_isstringempty2 (string)) { // check maximum length of one rule if ((_r_str_getlength2 (&sb.string->sr) + _r_str_getlength2 (&string->sr)) > RULE_RULE_CCH_MAX) { _r_obj_dereference (string); break; } _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_appendstringbuilder2 (&sb, ÷r_sr); } _r_obj_dereference (string); } } string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring (&string->sr, ÷r_sr, PR_TRIM_END_ONLY); if (_r_obj_isstringempty2 (string)) { _r_obj_dereference (string); return NULL; } return string; } VOID _app_editor_setrulestolistview ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ PR_STRING rule ) { PR_STRING rule_string; R_STRINGREF first_part; R_STRINGREF remaining_part; INT item_id = 0; _r_obj_initializestringref2 (&remaining_part, &rule->sr); while (remaining_part.length != 0) { _r_str_splitatchar (&remaining_part, DIVIDER_RULE[0], &first_part, &remaining_part); rule_string = _r_obj_createstring2 (&first_part); _app_listview_lock (hwnd, ctrl_id, TRUE); _r_listview_additem (hwnd, ctrl_id, item_id, rule_string->buffer, I_DEFAULT, I_DEFAULT, I_DEFAULT); _app_listview_lock (hwnd, ctrl_id, FALSE); item_id += 1; _r_obj_dereference (rule_string); } _r_listview_setcolumn (hwnd, ctrl_id, 0, NULL, -100); } INT_PTR CALLBACK EditorRuleProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ) { PEDITOR_CONTEXT context; switch (msg) { case WM_INITDIALOG: { PR_STRING string; context = (PEDITOR_CONTEXT)lparam; _app_editor_setcontext (hwnd, context); _r_wnd_center (hwnd, GetParent (hwnd)); // localize window _r_ctrl_setstring (hwnd, 0, _r_locale_getstring (IDS_RULE)); _r_edit_settextlimit ( hwnd, IDC_RULE_ID, _r_calc_clamp (RULE_RULE_CCH_MAX - (LONG)(context->current_length) - 1, 1, RULE_RULE_CCH_MAX) ); _r_edit_setcuebanner (hwnd, IDC_RULE_ID, L"Example: 192.168.0.1;192.168.0.17"); if (context->item_id != INT_ERROR) { string = _r_listview_getitemtext (context->hwnd, context->listview_id, context->item_id, 0); if (string) { _r_ctrl_setstring (hwnd, IDC_RULE_ID, string->buffer); _r_obj_dereference (string); } } _r_ctrl_setstring ( hwnd, IDC_RULE_HINT, L"eg. 192.168.0.1; 192.168.0.1; [fc00::]\r\neg. 192.168.0.1:80; 192.168.0.1:443; [fc00::]:443;\r\n"\ L"eg. 192.168.0.1-192.168.0.255; 192.168.0.1-192.168.0.255;\r\neg. 192.168.0.1-192.168.0.255:80; 192.168.0.1-192.168.0.255:443;\r\n"\ L"eg. 192.168.0.0/16; 192.168.0.0/24; fe80::/10;\r\n"\ L"eg. 20-21; 49152-65534;\r\neg. 21; 80; 443\r\n" ); _r_ctrl_setstring ( hwnd, IDC_SAVE, _r_locale_getstring (context->item_id != INT_ERROR ? IDS_SAVE : IDS_ADD) ); _r_ctrl_setstring (hwnd, IDC_CLOSE, _r_locale_getstring (IDS_CLOSE)); // enable save button _r_ctrl_enable (hwnd, IDC_SAVE, _r_ctrl_getstringlength (hwnd, IDC_RULE_ID) != 0); _r_theme_initialize (hwnd); SetFocus (NULL); break; } case WM_CLOSE: { EndDialog (hwnd, FALSE); break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint (hwnd, &ps); if (!hdc) break; _r_dc_drawwindow (hdc, hwnd, TRUE); EndPaint (hwnd, &ps); break; } case WM_DPICHANGED: { _r_wnd_message_dpichanged (hwnd, wparam, lparam); break; } case WM_SETTINGCHANGE: { _r_wnd_message_settingchange (hwnd, wparam, lparam); break; } case WM_COMMAND: { INT ctrl_id = LOWORD (wparam); INT notify_code = HIWORD (wparam); if (notify_code == EN_CHANGE) { // enable save button _r_ctrl_enable (hwnd, IDC_SAVE, _r_ctrl_getstringlength (hwnd, IDC_RULE_ID) != 0); return FALSE; } else if (notify_code == EN_MAXTEXT) { _r_ctrl_showballoontip (hwnd, ctrl_id, 0, NULL, _r_locale_getstring (IDS_LIMIT_REACHED)); return FALSE; } switch (ctrl_id) { case IDOK: // process Enter key case IDC_SAVE: { ITEM_ADDRESS address; R_STRINGREF remaining_part; R_STRINGREF first_part; WCHAR rule_string[256]; PR_STRING string; INT item_id; if (!_r_ctrl_isenabled (hwnd, IDC_SAVE)) return FALSE; string = _r_ctrl_getstring (hwnd, IDC_RULE_ID); if (!string) return FALSE; _r_str_trimstring2 (&string->sr, DIVIDER_TRIM DIVIDER_RULE, 0); if (_r_obj_isstringempty2 (string)) { _r_ctrl_showballoontip (hwnd, IDC_RULE_ID, 0, NULL, _r_locale_getstring (IDS_STATUS_EMPTY)); _r_ctrl_enable (hwnd, IDC_SAVE, FALSE); _r_obj_dereference (string); return FALSE; } context = _app_editor_getcontext (hwnd); if (!context) return FALSE; _r_obj_initializestringref2 (&remaining_part, &string->sr); item_id = _r_listview_getitemcount (context->hwnd, context->listview_id); while (remaining_part.length != 0) { _r_str_splitatchar (&remaining_part, DIVIDER_RULE[0], &first_part, &remaining_part); if (!_app_parserulestring (&first_part, &address)) { _r_ctrl_showballoontip (hwnd, IDC_RULE_ID, 0, NULL, _r_locale_getstring (IDS_STATUS_SYNTAX_ERROR)); _r_ctrl_enable (hwnd, IDC_SAVE, FALSE); return FALSE; } _r_str_copystring (rule_string, RTL_NUMBER_OF (rule_string), &first_part); _r_listview_additem (context->hwnd, context->listview_id, item_id, rule_string, I_DEFAULT, I_DEFAULT, I_DEFAULT); item_id += 1; } if (context->item_id != INT_ERROR) _r_listview_deleteitem (context->hwnd, context->listview_id, context->item_id); _r_listview_setcolumn (context->hwnd, context->listview_id, 0, NULL, -100); _r_obj_dereference (string); FALLTHROUGH; } case IDCANCEL: // process Esc key case IDC_CLOSE: { EndDialog (hwnd, FALSE); break; } } break; } } return FALSE; } INT_PTR CALLBACK EditorPagesProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ) { PEDITOR_CONTEXT context; switch (msg) { case WM_INITDIALOG: { WCHAR buffer[256]; PITEM_APP ptr_app = NULL; PITEM_RULE ptr_rule; PR_STRING string; HWND hctrl; INT i; ULONG_PTR enum_key; BOOLEAN is_enabled; context = (PEDITOR_CONTEXT)lparam; _app_editor_setcontext (hwnd, context); EnableThemeDialogTexture (hwnd, ETDT_ENABLETAB); SetWindowPos ( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED ); // name if (GetDlgItem (hwnd, IDC_RULE_NAME_ID)) { _r_ctrl_setstringformat (hwnd, IDC_RULE_NAME, L"%s:", _r_locale_getstring (IDS_NAME)); if (!_r_obj_isstringempty (context->ptr_rule->name)) _r_ctrl_setstring (hwnd, IDC_RULE_NAME_ID, context->ptr_rule->name->buffer); _r_ctrl_setreadonly (hwnd, IDC_RULE_NAME_ID, !!context->ptr_rule->is_readonly); _r_ctrl_settextlimit (hwnd, IDC_RULE_NAME_ID, RULE_NAME_CCH_MAX - 1); } // comment if (GetDlgItem (hwnd, IDC_RULE_COMMENT_ID)) { _r_ctrl_setstringformat (hwnd, IDC_RULE_COMMENT, L"%s:", _r_locale_getstring (IDS_COMMENT)); if (!_r_obj_isstringempty (context->ptr_rule->comment)) _r_ctrl_setstring (hwnd, IDC_RULE_COMMENT_ID, context->ptr_rule->comment->buffer); _r_ctrl_enable (hwnd, IDC_RULE_COMMENT_ID, !context->ptr_rule->is_readonly); _r_ctrl_settextlimit (hwnd, IDC_RULE_COMMENT_ID, RULE_RULE_CCH_MAX - 1); } // direction if (GetDlgItem (hwnd, IDC_RULE_DIRECTION)) { _r_ctrl_setstringformat (hwnd, IDC_RULE_DIRECTION, L"%s:", _r_locale_getstring (IDS_DIRECTION)); _r_combobox_insertitem (hwnd, IDC_RULE_DIRECTION_ID, 0, _r_locale_getstring (IDS_DIRECTION_1), (LPARAM)FWP_DIRECTION_OUTBOUND); _r_combobox_insertitem (hwnd, IDC_RULE_DIRECTION_ID, 1, _r_locale_getstring (IDS_DIRECTION_2), (LPARAM)FWP_DIRECTION_INBOUND); _r_combobox_insertitem (hwnd, IDC_RULE_DIRECTION_ID, 2, _r_locale_getstring (IDS_ANY), (LPARAM)FWP_DIRECTION_MAX); _r_combobox_setcurrentitembylparam (hwnd, IDC_RULE_DIRECTION_ID, (LPARAM)context->ptr_rule->direction); _r_ctrl_enable (hwnd, IDC_RULE_DIRECTION_ID, !context->ptr_rule->is_readonly); } // action if (GetDlgItem (hwnd, IDC_RULE_ACTION)) { _r_ctrl_setstringformat (hwnd, IDC_RULE_ACTION, L"%s:", _r_locale_getstring (IDS_ACTION)); _r_combobox_insertitem (hwnd, IDC_RULE_ACTION_ID, 0, _r_locale_getstring (IDS_ACTION_BLOCK), (LPARAM)FWP_ACTION_BLOCK); _r_combobox_insertitem (hwnd, IDC_RULE_ACTION_ID, 1, _r_locale_getstring (IDS_ACTION_ALLOW), (LPARAM)FWP_ACTION_PERMIT); _r_combobox_setcurrentitembylparam (hwnd, IDC_RULE_ACTION_ID, (LPARAM)context->ptr_rule->action); _r_ctrl_enable (hwnd, IDC_RULE_ACTION_ID, !context->ptr_rule->is_readonly); } // protocols if (GetDlgItem (hwnd, IDC_RULE_PROTOCOL_ID)) { UINT8 protos[] = { IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPV4, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_RDP, IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_L2TP, IPPROTO_SCTP, IPPROTO_RAW, }; _r_ctrl_setstringformat (hwnd, IDC_RULE_PROTOCOL, L"%s:", _r_locale_getstring (IDS_PROTOCOL)); _r_combobox_insertitem (hwnd, IDC_RULE_PROTOCOL_ID, 0, _r_locale_getstring (IDS_ANY), 0); for (i = 0; i < RTL_NUMBER_OF (protos); i++) { _r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s (%" TEXT (PRIu8) L")", _app_db_getprotoname (protos[i], AF_UNSPEC), protos[i]); _r_combobox_insertitem (hwnd, IDC_RULE_PROTOCOL_ID, i + 1, buffer, (LPARAM)protos[i]); } // unknown protocol if (_r_combobox_getcurrentitem (hwnd, IDC_RULE_PROTOCOL_ID) == CB_ERR && context->ptr_rule->protocol != 0) { _r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s (%" TEXT (PRIu8) L")", _app_db_getprotoname (context->ptr_rule->protocol, AF_UNSPEC), context->ptr_rule->protocol); _r_combobox_insertitem (hwnd, IDC_RULE_PROTOCOL_ID, i + 1, buffer, (LPARAM)context->ptr_rule->protocol); } _r_combobox_setcurrentitembylparam (hwnd, IDC_RULE_PROTOCOL_ID, (LPARAM)context->ptr_rule->protocol); _r_ctrl_enable (hwnd, IDC_RULE_PROTOCOL_ID, !context->ptr_rule->is_readonly); } // family (ports-only) if (GetDlgItem (hwnd, IDC_RULE_VERSION_ID)) { _r_ctrl_setstringformat (hwnd, IDC_RULE_VERSION, L"%s:", _r_locale_getstring (IDS_PORTVERSION)); _r_combobox_insertitem (hwnd, IDC_RULE_VERSION_ID, 0, _r_locale_getstring (IDS_ANY), (LPARAM)AF_UNSPEC); _r_combobox_insertitem (hwnd, IDC_RULE_VERSION_ID, 1, L"IPv4", (LPARAM)AF_INET); _r_combobox_insertitem (hwnd, IDC_RULE_VERSION_ID, 2, L"IPv6", (LPARAM)AF_INET6); _r_combobox_setcurrentitembylparam (hwnd, IDC_RULE_VERSION_ID, (LPARAM)context->ptr_rule->af); _r_ctrl_enable (hwnd, IDC_RULE_VERSION_ID, !context->ptr_rule->is_readonly); } // rule (remote) if (GetDlgItem (hwnd, IDC_RULE_REMOTE_ID)) { _r_ctrl_setstringformat (hwnd, IDC_RULE_REMOTE, L"%s (%s):", _r_locale_getstring (IDS_RULE), _r_locale_getstring (IDS_DIRECTION_REMOTE)); _r_listview_setstyle ( hwnd, IDC_RULE_REMOTE_ID, LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP, FALSE ); _r_listview_addcolumn (hwnd, IDC_RULE_REMOTE_ID, 0, NULL, -100, 0); if (!_r_obj_isstringempty (context->ptr_rule->rule_remote)) { _app_editor_setrulestolistview (hwnd, IDC_RULE_REMOTE_ID, context->ptr_rule->rule_remote); _r_listview_setcolumn (hwnd, IDC_RULE_REMOTE_ID, 0, NULL, -100); } _r_ctrl_setstringformat (hwnd, IDC_RULE_REMOTE_ADD, L"%s...", _r_locale_getstring (IDS_ADD)); _r_ctrl_setstringformat (hwnd, IDC_RULE_REMOTE_EDIT, L"%s...", _r_locale_getstring (IDS_EDIT2)); _r_ctrl_setstringformat (hwnd, IDC_RULE_REMOTE_DELETE, L"%s...", _r_locale_getstring (IDS_DELETE)); _r_ctrl_enable (hwnd, IDC_RULE_REMOTE_ADD, !context->ptr_rule->is_readonly); _r_ctrl_enable (hwnd, IDC_RULE_REMOTE_EDIT, FALSE); _r_ctrl_enable (hwnd, IDC_RULE_REMOTE_DELETE, FALSE); } // rule (local) if (GetDlgItem (hwnd, IDC_RULE_LOCAL_ID)) { _r_ctrl_setstringformat (hwnd, IDC_RULE_LOCAL, L"%s (%s):", _r_locale_getstring (IDS_RULE), _r_locale_getstring (IDS_DIRECTION_LOCAL)); _r_listview_setstyle ( hwnd, IDC_RULE_LOCAL_ID, LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP, FALSE ); _r_listview_addcolumn (hwnd, IDC_RULE_LOCAL_ID, 0, NULL, 100, 0); if (!_r_obj_isstringempty (context->ptr_rule->rule_local)) { _app_editor_setrulestolistview (hwnd, IDC_RULE_LOCAL_ID, context->ptr_rule->rule_local); _r_listview_setcolumn (hwnd, IDC_RULE_LOCAL_ID, 0, NULL, -100); } _r_ctrl_setstringformat (hwnd, IDC_RULE_LOCAL_ADD, L"%s...", _r_locale_getstring (IDS_ADD)); _r_ctrl_setstringformat (hwnd, IDC_RULE_LOCAL_EDIT, L"%s...", _r_locale_getstring (IDS_EDIT2)); _r_ctrl_setstringformat (hwnd, IDC_RULE_LOCAL_DELETE, L"%s...", _r_locale_getstring (IDS_DELETE)); _r_ctrl_enable (hwnd, IDC_RULE_LOCAL_ADD, !context->ptr_rule->is_readonly); _r_ctrl_enable (hwnd, IDC_RULE_LOCAL_EDIT, FALSE); _r_ctrl_enable (hwnd, IDC_RULE_LOCAL_DELETE, FALSE); } // search hctrl = GetDlgItem (hwnd, IDC_SEARCH); if (hctrl) { _app_search_create (hctrl); SetWindowPos (hctrl, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED); // HACK!!! } // apps if (GetDlgItem (hwnd, IDC_RULE_APPS_ID)) { _app_listview_setview (hwnd, IDC_RULE_APPS_ID); _r_listview_setstyle ( hwnd, IDC_RULE_APPS_ID, LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP | LVS_EX_CHECKBOXES, TRUE ); _r_listview_addcolumn (hwnd, IDC_RULE_APPS_ID, 0, _r_locale_getstring (IDS_NAME), 100, LVCFMT_LEFT); _r_listview_addgroup (hwnd, IDC_RULE_APPS_ID, 0, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, IDC_RULE_APPS_ID, 1, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, IDC_RULE_APPS_ID, 2, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, IDC_RULE_APPS_ID, LV_HIDDEN_GROUP_ID, L"", 3, LVGS_HIDDEN, LVGS_HIDDEN); // apps (apply to) enum_key = 0; _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { // check for services is_enabled = ((_r_obj_findhashtable (context->ptr_rule->apps, ptr_app->app_hash)) || (context->ptr_rule->is_forservices && _app_issystemhash (ptr_app->app_hash))); _app_listview_lock (hwnd, IDC_RULE_APPS_ID, TRUE); _r_listview_additem (hwnd, IDC_RULE_APPS_ID, 0, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, _app_listview_createcontext (ptr_app->app_hash)); _r_listview_setitemcheck (hwnd, IDC_RULE_APPS_ID, 0, is_enabled); _app_listview_lock (hwnd, IDC_RULE_APPS_ID, FALSE); } _r_queuedlock_releaseshared (&lock_apps); // resize column _r_listview_setcolumn (hwnd, IDC_RULE_APPS_ID, 0, NULL, -100); // localize groups _app_listview_refreshgroups (hwnd, IDC_RULE_APPS_ID); // sort column _app_listview_sort (hwnd, IDC_RULE_APPS_ID, INT_ERROR, FALSE); } // app group if (GetDlgItem (hwnd, IDC_APP_NAME)) _r_ctrl_setstringformat (hwnd, IDC_APP_NAME, L"%s:", _r_locale_getstring (IDS_SETTINGS_GENERAL)); // app path if (GetDlgItem (hwnd, IDC_APP_PATH)) _r_ctrl_setstringformat (hwnd, IDC_APP_PATH, L"%s:", _r_locale_getstring (IDS_FILEPATH)); // app comment if (GetDlgItem (hwnd, IDC_APP_COMMENT)) _r_ctrl_setstringformat (hwnd, IDC_APP_COMMENT, L"%s:", _r_locale_getstring (IDS_COMMENT)); // app icon if (GetDlgItem (hwnd, IDC_APP_ICON_ID)) { context->hicon = _app_icons_getsafeapp_hicon (context->ptr_app->app_hash); _r_wnd_sendmessage (hwnd, IDC_APP_ICON_ID, STM_SETICON, (WPARAM)context->hicon, 0); } // app display name if (GetDlgItem (hwnd, IDC_APP_NAME_ID)) { string = _app_getappdisplayname (context->ptr_app, TRUE); if (string) { _r_ctrl_setstring (hwnd, IDC_APP_NAME_ID, string->buffer); _r_obj_dereference (string); } _r_ctrl_settextmargin (hwnd, IDC_APP_NAME_ID, 0, 0); } // app comment if (GetDlgItem (hwnd, IDC_APP_COMMENT_ID)) { _r_ctrl_setstring (hwnd, IDC_APP_COMMENT_ID, _r_obj_getstring (context->ptr_app->comment)); _r_ctrl_settextmargin (hwnd, IDC_APP_COMMENT_ID, 0, 0); } // app signature if (GetDlgItem (hwnd, IDC_APP_SIGNATURE_ID)) { string = NULL; _app_getappinfoparam2 (context->ptr_app->app_hash, 0, INFO_SIGNATURE_STRING, &string, sizeof (PR_STRING)); _r_ctrl_setstringformat ( hwnd, IDC_APP_SIGNATURE_ID, L"%s: %s", _r_locale_getstring (IDS_SIGNATURE), _r_obj_getstringordefault (string, _r_locale_getstring (IDS_SIGN_UNSIGNED)) ); _r_ctrl_settextmargin (hwnd, IDC_APP_NAME_ID, 0, 0); _r_ctrl_settextmargin (hwnd, IDC_APP_SIGNATURE_ID, 0, 0); if (string) _r_obj_dereference (string); } // app path if (GetDlgItem (hwnd, IDC_APP_PATH_ID)) { if (_app_isappvalidpath (context->ptr_app->real_path)) { _r_ctrl_setstring (hwnd, IDC_APP_PATH_ID, context->ptr_app->real_path->buffer); } else { _r_ctrl_enable (hwnd, IDC_APP_EXPLORE_ID, FALSE); } } // app hash if (GetDlgItem (hwnd, IDC_APP_HASH_ID)) _r_ctrl_setstring (hwnd, IDC_APP_HASH_ID, _r_obj_getstringordefault (context->ptr_app->hash, L"")); // app rules if (GetDlgItem (hwnd, IDC_APP_RULES_ID)) { // configure listview _app_listview_setview (hwnd, IDC_APP_RULES_ID); _r_listview_setstyle ( hwnd, IDC_APP_RULES_ID, LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP | LVS_EX_CHECKBOXES, TRUE ); _r_listview_addcolumn (hwnd, IDC_APP_RULES_ID, 0, _r_locale_getstring (IDS_NAME), 100, LVCFMT_LEFT); _r_listview_addgroup (hwnd, IDC_APP_RULES_ID, 0, _r_locale_getstring (IDS_TRAY_SYSTEM_RULES), 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, IDC_APP_RULES_ID, 1, _r_locale_getstring (IDS_TRAY_USER_RULES), 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, IDC_APP_RULES_ID, LV_HIDDEN_GROUP_ID, L"", 2, LVGS_COLLAPSED, LVGS_COLLAPSED); // initialize _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (!ptr_rule || ptr_rule->type != DATA_RULE_USER) continue; // check for services is_enabled = ((ptr_rule->is_forservices && _app_issystemhash (context->ptr_app->app_hash)) || _r_obj_findhashtable (ptr_rule->apps, context->ptr_app->app_hash)); _app_listview_lock (hwnd, IDC_APP_RULES_ID, TRUE); _r_listview_additem (hwnd, IDC_APP_RULES_ID, 0, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, _app_listview_createcontext ((ULONG)i)); _r_listview_setitemcheck (hwnd, IDC_APP_RULES_ID, 0, is_enabled); _app_listview_lock (hwnd, IDC_APP_RULES_ID, FALSE); } _r_queuedlock_releaseshared (&lock_rules); // resize column _r_listview_setcolumn (hwnd, IDC_APP_RULES_ID, 0, NULL, -100); // localize groups _app_listview_refreshgroups (hwnd, IDC_APP_RULES_ID); // sort column _app_listview_sort (hwnd, IDC_APP_RULES_ID, INT_ERROR, FALSE); } // hints if (GetDlgItem (hwnd, IDC_RULE_HINT)) _r_ctrl_setstring (hwnd, IDC_RULE_HINT, _r_locale_getstring (IDS_RULE_HINT)); if (GetDlgItem (hwnd, IDC_RULE_APPS_HINT)) _r_ctrl_setstring (hwnd, IDC_RULE_APPS_HINT, _r_locale_getstring (IDS_RULE_APPS_HINT)); if (GetDlgItem (hwnd, IDC_APP_HINT)) _r_ctrl_setstring (hwnd, IDC_APP_HINT, _r_locale_getstring (IDS_APP_HINT)); break; } case RM_INITIALIZE: { // apps if (GetDlgItem (hwnd, IDC_RULE_APPS_ID)) _app_editor_settabtitle (hwnd, IDC_RULE_APPS_ID); // rules if (GetDlgItem (hwnd, IDC_APP_RULES_ID)) _app_editor_settabtitle (hwnd, IDC_APP_RULES_ID); break; } case WM_DESTROY: { // apps if (GetDlgItem (hwnd, IDC_RULE_APPS_ID)) _r_listview_deleteallitems (hwnd, IDC_RULE_APPS_ID); // app rules if (GetDlgItem (hwnd, IDC_APP_RULES_ID)) _r_listview_deleteallitems (hwnd, IDC_APP_RULES_ID); context = _app_editor_getcontext (hwnd); if (!context) break; if (context->hicon) DestroyIcon (context->hicon); break; } case WM_SIZE: { INT listview_ids[] = { IDC_RULE_APPS_ID, IDC_APP_RULES_ID, IDC_RULE_REMOTE_ID, IDC_RULE_LOCAL_ID, }; HWND hlistview; for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (listview_ids); i++) { hlistview = GetDlgItem (hwnd, listview_ids[i]); if (hlistview) _r_listview_setcolumn (hwnd, listview_ids[i], 0, NULL, -100); } break; } case WM_NOTIFY: { LPNMHDR nmlp = (LPNMHDR)lparam; switch (nmlp->code) { case NM_CUSTOMDRAW: { LONG_PTR result; result = _app_message_custdraw (hwnd, (LPNMLVCUSTOMDRAW)lparam); SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, result); return result; } case NM_DBLCLK: { LPNMITEMACTIVATE lpnmlv; ULONG command_id = 0; INT listview_id; lpnmlv = (LPNMITEMACTIVATE)lparam; if (lpnmlv->iItem == INT_ERROR) break; listview_id = (INT)(INT_PTR)(lpnmlv->hdr.idFrom); if (listview_id == IDC_RULE_REMOTE_ID) { command_id = IDC_RULE_REMOTE_EDIT; } else if (listview_id == IDC_RULE_LOCAL_ID) { command_id = IDC_RULE_LOCAL_EDIT; } else if (listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID) { command_id = IDM_PROPERTIES; } if (command_id) _r_ctrl_sendcommand (hwnd, command_id, 0); break; } case NM_RCLICK: { LPNMITEMACTIVATE lpnmlv; HMENU hsubmenu; PR_STRING localized_string = NULL; UINT id_add; UINT id_edit; UINT id_delete; INT listview_id; BOOLEAN is_remote; BOOLEAN is_selected; lpnmlv = (LPNMITEMACTIVATE)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (listview_id != IDC_RULE_REMOTE_ID && listview_id != IDC_RULE_LOCAL_ID && listview_id != IDC_RULE_APPS_ID && listview_id != IDC_APP_RULES_ID) break; context = _app_editor_getcontext (hwnd); if (!context) break; hsubmenu = CreatePopupMenu (); if (!hsubmenu) break; is_selected = _r_listview_getselectedcount (hwnd, listview_id) != 0; if (listview_id == IDC_RULE_REMOTE_ID || listview_id == IDC_RULE_LOCAL_ID) { is_remote = (listview_id == IDC_RULE_REMOTE_ID); id_add = is_remote ? IDC_RULE_REMOTE_ADD : IDC_RULE_LOCAL_ADD; id_edit = is_remote ? IDC_RULE_REMOTE_EDIT : IDC_RULE_LOCAL_EDIT; id_delete = is_remote ? IDC_RULE_REMOTE_DELETE : IDC_RULE_LOCAL_DELETE; _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_ADD), L"...")); _r_menu_additem (hsubmenu, id_add, localized_string->buffer); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_EDIT2), L"...")); _r_menu_additem (hsubmenu, id_edit, localized_string->buffer); _r_menu_additem (hsubmenu, id_delete, _r_locale_getstring (IDS_DELETE)); _r_menu_addseparator (hsubmenu); _r_menu_additem (hsubmenu, IDM_COPY, _r_locale_getstring (IDS_COPY)); if (context->ptr_rule->is_readonly) { _r_menu_enableitem (hsubmenu, id_add, FALSE, FALSE); _r_menu_enableitem (hsubmenu, id_edit, FALSE, FALSE); _r_menu_enableitem (hsubmenu, id_delete, FALSE, FALSE); } if (!is_selected) { _r_menu_enableitem (hsubmenu, id_edit, FALSE, FALSE); _r_menu_enableitem (hsubmenu, id_delete, FALSE, FALSE); _r_menu_enableitem (hsubmenu, IDM_COPY, FALSE, FALSE); } _r_obj_dereference (localized_string); } else if (listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID) { _r_menu_additem (hsubmenu, IDM_CHECK, _r_locale_getstring (IDS_CHECK)); _r_menu_additem (hsubmenu, IDM_UNCHECK, _r_locale_getstring (IDS_UNCHECK)); _r_menu_addseparator (hsubmenu); _r_menu_additem (hsubmenu, IDM_COPY, _r_locale_getstring (IDS_COPY)); if (context->is_settorules && context->ptr_rule->type != DATA_RULE_USER) { _r_menu_enableitem (hsubmenu, IDM_CHECK, FALSE, FALSE); _r_menu_enableitem (hsubmenu, IDM_UNCHECK, FALSE, FALSE); } if (!is_selected) { _r_menu_enableitem (hsubmenu, IDM_CHECK, FALSE, FALSE); _r_menu_enableitem (hsubmenu, IDM_UNCHECK, FALSE, FALSE); _r_menu_enableitem (hsubmenu, IDM_COPY, FALSE, FALSE); } } _r_menu_popup (hsubmenu, hwnd, NULL, TRUE); DestroyMenu (hsubmenu); break; } case LVN_DELETEITEM: { PITEM_LISTVIEW_CONTEXT listview_context; LPNMLISTVIEW lpnmlv; INT listview_id; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (!(listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID)) break; listview_context = (PITEM_LISTVIEW_CONTEXT)lpnmlv->lParam; if (!listview_context) break; _app_listview_destroycontext (listview_context); break; } case LVN_GETDISPINFO: { LPNMLVDISPINFOW lpnmlv; INT listview_id; lpnmlv = (LPNMLVDISPINFOW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; _app_message_displayinfo (hwnd, listview_id, lpnmlv); break; } case LVN_COLUMNCLICK: { LPNMLISTVIEW lpnmlv; INT listview_id; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; _app_listview_sort (hwnd, listview_id, lpnmlv->iSubItem, TRUE); break; } case LVN_ITEMCHANGING: { LPNMLISTVIEW lpnmlv; INT listview_id; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; context = _app_editor_getcontext (hwnd); if (!context) break; if ((lpnmlv->uChanged & LVIF_STATE) != 0) { if (listview_id == IDC_RULE_APPS_ID) { if ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (1) || ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (2))) { if (!_app_listview_islocked (hwnd, (INT)(INT_PTR)lpnmlv->hdr.idFrom) && context->ptr_rule->type != DATA_RULE_USER) { SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } } } } break; } case LVN_ITEMCHANGED: { LPNMLISTVIEW lpnmlv; INT listview_id; BOOLEAN is_selected; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; context = _app_editor_getcontext (hwnd); if (!context) break; if ((lpnmlv->uChanged & LVIF_STATE) != 0) { if (listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID) { if ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (1) || ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (2))) { if (_app_listview_islocked (hwnd, (INT)(INT_PTR)lpnmlv->hdr.idFrom)) break; _app_editor_settabtitle (hwnd, listview_id); _app_listview_refreshgroups (hwnd, listview_id); _app_listview_sort (hwnd, listview_id, INT_ERROR, FALSE); } } else if (listview_id == IDC_RULE_REMOTE_ID || listview_id == IDC_RULE_LOCAL_ID) { if ((lpnmlv->uOldState & LVIS_SELECTED) != 0 || (lpnmlv->uNewState & LVIS_SELECTED) != 0) { if (!context->ptr_rule->is_readonly) { is_selected = (lpnmlv->uNewState & LVIS_SELECTED) != 0; if (listview_id == IDC_RULE_REMOTE_ID) { _r_ctrl_enable (hwnd, IDC_RULE_REMOTE_EDIT, is_selected); _r_ctrl_enable (hwnd, IDC_RULE_REMOTE_DELETE, is_selected); } else if (listview_id == IDC_RULE_LOCAL_ID) { _r_ctrl_enable (hwnd, IDC_RULE_LOCAL_EDIT, is_selected); _r_ctrl_enable (hwnd, IDC_RULE_LOCAL_DELETE, is_selected); } } } } } break; } case LVN_GETINFOTIP: { LPNMLVGETINFOTIPW lpnmlv; PR_STRING string; ULONG_PTR context; INT listview_id; lpnmlv = (LPNMLVGETINFOTIPW)lparam; listview_id = (INT)lpnmlv->hdr.idFrom; if (listview_id != IDC_RULE_APPS_ID && listview_id != IDC_APP_RULES_ID) break; context = _app_listview_getitemcontext (hwnd, listview_id, lpnmlv->iItem); string = _app_gettooltipbylparam (hwnd, listview_id, context); if (!string) break; _r_str_copy (lpnmlv->pszText, lpnmlv->cchTextMax, string->buffer); _r_obj_dereference (string); break; } case LVN_GETEMPTYMARKUP: { NMLVEMPTYMARKUP* lpnmlv = (NMLVEMPTYMARKUP*)lparam; lpnmlv->dwFlags = EMF_CENTERED; _r_str_copy (lpnmlv->szMarkup, RTL_NUMBER_OF (lpnmlv->szMarkup), _r_locale_getstring (IDS_STATUS_EMPTY)); SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } } break; } case WM_COMMAND: { INT notify_code = HIWORD (wparam); INT ctrl_id = LOWORD (wparam); if (notify_code == EN_CHANGE) { PR_STRING string; INT listview_id; if (ctrl_id == IDC_RULE_NAME_ID) { _r_ctrl_enable (GetParent (hwnd), IDC_SAVE, _r_ctrl_getstringlength (hwnd, ctrl_id) != 0); // enable apply button break; } if (ctrl_id != IDC_SEARCH) break; if (GetDlgItem (hwnd, IDC_RULE_APPS_ID)) { listview_id = IDC_RULE_APPS_ID; } else if (GetDlgItem (hwnd, IDC_APP_RULES_ID)) { listview_id = IDC_APP_RULES_ID; } else { return FALSE; } string = _r_ctrl_getstring (hwnd, IDC_SEARCH); _app_search_applyfilter (hwnd, listview_id, string); if (string) _r_obj_dereference (string); return FALSE; } else if (notify_code == EN_MAXTEXT) { _r_ctrl_showballoontip (hwnd, ctrl_id, 0, NULL, _r_locale_getstring (IDS_LIMIT_REACHED)); return FALSE; } switch (ctrl_id) { case IDC_RULE_REMOTE_ADD: case IDC_RULE_LOCAL_ADD: case IDC_RULE_REMOTE_EDIT: case IDC_RULE_LOCAL_EDIT: { PR_STRING string; ULONG_PTR current_length; INT listview_id; INT item_id; if (!_r_ctrl_isenabled (hwnd, ctrl_id)) break; listview_id = (ctrl_id == IDC_RULE_REMOTE_ADD || ctrl_id == IDC_RULE_REMOTE_EDIT) ? IDC_RULE_REMOTE_ID : IDC_RULE_LOCAL_ID; if (ctrl_id == IDC_RULE_REMOTE_EDIT || ctrl_id == IDC_RULE_LOCAL_EDIT) { // edit rule item_id = _r_listview_getnextselected (hwnd, listview_id, INT_ERROR); if (item_id == INT_ERROR) break; } else { // create new rule item_id = INT_ERROR; } string = _app_editor_getrulesfromlistview (hwnd, listview_id, item_id); if (string) { current_length = _r_str_getlength2 (&string->sr); _r_obj_dereference (string); } else { current_length = 0; } if (ctrl_id == IDC_RULE_REMOTE_ADD || ctrl_id == IDC_RULE_LOCAL_ADD) { if (current_length >= RULE_RULE_CCH_MAX) { _r_show_errormessage (hwnd, NULL, STATUS_IMPLEMENTATION_LIMIT, NULL, ET_NATIVE); return FALSE; } } context = _app_editor_getcontext (hwnd); if (!context) break; context->hwnd = hwnd; context->listview_id = listview_id; context->item_id = item_id; context->current_length = current_length; _r_wnd_createmodalwindow (_r_sys_getimagebase (), MAKEINTRESOURCE (IDD_EDITOR_ADDRULE), hwnd, &EditorRuleProc, context); break; } case IDC_RULE_REMOTE_DELETE: case IDC_RULE_LOCAL_DELETE: { INT listview_id; INT selected_count; INT item_count; listview_id = ((ctrl_id == IDC_RULE_REMOTE_DELETE) ? IDC_RULE_REMOTE_ID : IDC_RULE_LOCAL_ID); selected_count = _r_listview_getselectedcount (hwnd, listview_id); if (!selected_count) break; if (_r_show_message (hwnd, MB_YESNO | MB_ICONEXCLAMATION, NULL, _r_locale_getstring (IDS_QUESTION_DELETE)) != IDYES) break; item_count = _r_listview_getitemcount (hwnd, listview_id) - 1; for (INT i = item_count; i != INT_ERROR; i--) { if (_r_listview_isitemselected (hwnd, listview_id, i)) _r_listview_deleteitem (hwnd, listview_id, i); } _r_listview_setcolumn (hwnd, listview_id, 0, NULL, -100); break; } case IDM_CHECK: case IDM_UNCHECK: { INT listview_id; INT item_id = INT_ERROR; BOOLEAN new_val; if (GetDlgItem (hwnd, IDC_RULE_APPS_ID)) { listview_id = IDC_RULE_APPS_ID; } else if (GetDlgItem (hwnd, IDC_APP_RULES_ID)) { listview_id = IDC_APP_RULES_ID; } else { break; } new_val = (ctrl_id == IDM_CHECK); _app_listview_lock (hwnd, listview_id, TRUE); while ((item_id = _r_listview_getnextselected (hwnd, listview_id, item_id)) != INT_ERROR) { _r_listview_setitemcheck (hwnd, listview_id, item_id, new_val); } _app_listview_lock (hwnd, listview_id, FALSE); _app_listview_refreshgroups (hwnd, listview_id); _app_listview_sort (hwnd, listview_id, INT_ERROR, FALSE); break; } case IDC_APP_EXPLORE_ID: { context = _app_editor_getcontext (hwnd); if (!context) break; if (_app_isappvalidpath (context->ptr_app->real_path)) _r_shell_showfile (&context->ptr_app->real_path->sr); break; } case IDC_APP_HASH_RECHECK_ID: { PR_STRING string; HANDLE hfile; NTSTATUS status; context = _app_editor_getcontext (hwnd); if (!context) break; if (!_app_isappvalidpath (context->ptr_app->real_path)) break; status = _r_fs_openfile ( &context->ptr_app->real_path->sr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, 0, FALSE, &hfile ); if (NT_SUCCESS (status)) { string = _app_getfilehashinfo (hfile, context->ptr_app->app_hash); _r_ctrl_setstring (hwnd, IDC_APP_HASH_ID, _r_obj_getstringordefault (string, L"")); NtClose (hfile); } break; } case IDM_PROPERTIES: { ULONG_PTR index; INT listview_id; INT item_id; if (GetDlgItem (hwnd, IDC_RULE_APPS_ID)) { listview_id = IDC_RULE_APPS_ID; } else if (GetDlgItem (hwnd, IDC_APP_RULES_ID)) { listview_id = IDC_APP_RULES_ID; } else { break; } item_id = _r_listview_getnextselected (hwnd, listview_id, INT_ERROR); if (item_id != INT_ERROR) { index = _app_listview_getitemcontext (hwnd, listview_id, item_id); _app_listview_showitemby_param (_r_app_gethwnd (), index, (listview_id == IDC_RULE_APPS_ID)); } break; } case IDM_COPY: { R_STRINGBUILDER sb; PR_STRING string; HWND hlistview; INT listview_id; INT item_id = INT_ERROR; hlistview = GetFocus (); if (!hlistview) break; listview_id = GetDlgCtrlID (hlistview); if (!listview_id || !_r_listview_getitemcount (hwnd, listview_id)) break; _r_obj_initializestringbuilder (&sb, 512); while ((item_id = _r_listview_getnextselected (hwnd, listview_id, item_id)) != INT_ERROR) { string = _r_listview_getitemtext (hwnd, listview_id, item_id, 0); if (string) { _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_appendstringbuilder (&sb, SZ_CRLF); _r_obj_dereference (string); } } string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring2 (&string->sr, DIVIDER_TRIM, 0); _r_clipboard_set (hwnd, &string->sr); _r_obj_deletestringbuilder (&sb); break; } } break; } } return FALSE; } INT_PTR CALLBACK EditorProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ) { PEDITOR_CONTEXT context; switch (msg) { case WM_INITDIALOG: { WCHAR title[128] = {0}; PR_STRING string; context = (PEDITOR_CONTEXT)lparam; _app_editor_setcontext (hwnd, context); // configure tabs if (context->is_settorules) { _r_str_copy (title, RTL_NUMBER_OF (title), _r_obj_getstringorempty (context->ptr_rule->name)); if (context->ptr_rule->is_readonly) _r_str_appendformat (title, RTL_NUMBER_OF (title), L" (%s)", _r_locale_getstring (IDS_INTERNAL_RULE)); _app_editor_addtabitem (hwnd, IDS_SETTINGS_GENERAL, IDD_EDITOR_GENERAL, context); _app_editor_addtabitem (hwnd, IDS_RULE, IDD_EDITOR_RULE, context); _app_editor_addtabitem (hwnd, IDS_TAB_APPS, IDD_EDITOR_APPS, context); // set state _r_ctrl_setstring (hwnd, IDC_ENABLE_CHK, _r_locale_getstring (IDS_ENABLE_CHK)); _r_ctrl_checkbutton (hwnd, IDC_ENABLE_CHK, !!(context->ptr_rule->is_enabled)); } else { string = _app_getappdisplayname (context->ptr_app, TRUE); if (string) { _r_str_copy (title, RTL_NUMBER_OF (title), string->buffer); _r_obj_dereference (string); } _app_editor_addtabitem (hwnd, IDS_SETTINGS_GENERAL, IDD_EDITOR_APPINFO, context); _app_editor_addtabitem (hwnd, IDS_TRAY_RULES, IDD_EDITOR_APPRULES, context); // show state _r_ctrl_setstring (hwnd, IDC_ENABLE_CHK, _r_locale_getstring (IDS_ENABLE_APP_CHK)); _r_ctrl_checkbutton (hwnd, IDC_ENABLE_CHK, !!(context->ptr_app->is_enabled)); } // initialize layout _r_layout_initializemanager (&context->layout_manager, hwnd); _r_wnd_top (hwnd, TRUE); _r_wnd_center (hwnd, GetParent (hwnd)); _r_window_restoreposition (hwnd, L"editor"); // set window title _r_ctrl_setstring (hwnd, 0, title); _r_ctrl_setstring (hwnd, IDC_SAVE, _r_locale_getstring (IDS_SAVE)); _r_ctrl_setstring (hwnd, IDC_CLOSE, _r_locale_getstring (IDS_CLOSE)); _r_tab_selectitem (hwnd, IDC_TAB, _r_calc_clamp (context->page_id, 0, _r_tab_getitemcount (hwnd, IDC_TAB))); _r_theme_initialize (hwnd); break; } case WM_DESTROY: { _r_window_saveposition (hwnd, L"editor"); context = _app_editor_getcontext (hwnd); if (context) _r_layout_destroymanager (&context->layout_manager); break; } case WM_CLOSE: { EndDialog (hwnd, FALSE); break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint (hwnd, &ps); if (!hdc) break; _r_dc_drawwindow (hdc, hwnd, FALSE); EndPaint (hwnd, &ps); break; } case WM_DPICHANGED: { _r_wnd_message_dpichanged (hwnd, wparam, lparam); break; } case WM_SETTINGCHANGE: { _r_wnd_message_settingchange (hwnd, wparam, lparam); break; } case WM_SIZE: { HWND hpage; INT item_id; context = _app_editor_getcontext (hwnd); if (!context) break; _r_layout_resize (&context->layout_manager, wparam); item_id = _r_tab_getcurrentitem (hwnd, IDC_TAB); hpage = (HWND)_r_tab_getitemlparam (hwnd, IDC_TAB, item_id); if (hpage) _r_tab_adjustchild (hwnd, IDC_TAB, hpage); break; } case WM_GETMINMAXINFO: { context = _app_editor_getcontext (hwnd); if (!context) break; _r_layout_resizeminimumsize (&context->layout_manager, lparam); break; } case WM_NOTIFY: { LPNMHDR nmlp = (LPNMHDR)lparam; switch (nmlp->code) { case TCN_SELCHANGING: { HWND hpage; INT item_id; item_id = _r_tab_getcurrentitem (hwnd, IDC_TAB); hpage = (HWND)_r_tab_getitemlparam (hwnd, IDC_TAB, item_id); if (hpage) ShowWindow (hpage, SW_HIDE); break; } case TCN_SELCHANGE: { HWND hpage; INT item_id; item_id = _r_tab_getcurrentitem (hwnd, IDC_TAB); hpage = (HWND)_r_tab_getitemlparam (hwnd, IDC_TAB, item_id); if (!hpage) break; _r_tab_adjustchild (hwnd, IDC_TAB, hpage); ShowWindow (hpage, SW_SHOWNA); SetFocus (NULL); break; } } break; } case WM_COMMAND: { INT ctrl_id = LOWORD (wparam); switch (ctrl_id) { case IDOK: // process Enter key case IDC_SAVE: { HWND hpage_general; HWND hpage_rule; HWND hpage_apps; PR_STRING string; PR_LIST rules = NULL; PITEM_RULE ptr_rule; HANDLE hengine; ULONG_PTR rule_idx; ULONG app_hash; INT listview_id; INT item_id; BOOLEAN is_enable; context = _app_editor_getcontext (hwnd); if (!context) break; hpage_general = (HWND)_r_tab_getitemlparam (hwnd, IDC_TAB, 0); hpage_rule = (HWND)_r_tab_getitemlparam (hwnd, IDC_TAB, 1); if (context->is_settorules) { hpage_apps = (HWND)_r_tab_getitemlparam (hwnd, IDC_TAB, 2); if (!hpage_general || !_r_ctrl_getstringlength (hpage_general, IDC_RULE_NAME_ID)) return FALSE; context->ptr_rule->is_haveerrors = FALSE; // reset errors // do not change read-only rules if (!context->ptr_rule->is_readonly) { // name string = _r_ctrl_getstring (hpage_general, IDC_RULE_NAME_ID); if (!string) return FALSE; _r_str_trimstring2 (&string->sr, DIVIDER_TRIM DIVIDER_RULE, 0); if (_r_obj_isstringempty2 (string)) { _r_ctrl_showballoontip (hpage_general, IDC_RULE_NAME_ID, 0, NULL, _r_locale_getstring (IDS_STATUS_EMPTY)); _r_obj_dereference (string); return FALSE; } _r_obj_movereference ((PVOID_PTR)&context->ptr_rule->name, string); // comment string = _r_ctrl_getstring (hpage_general, IDC_RULE_COMMENT_ID); if (string) _r_str_trimstring2 (&string->sr, DIVIDER_TRIM DIVIDER_RULE, 0); _r_obj_movereference ((PVOID_PTR)&context->ptr_rule->comment, string); if (hpage_rule) { // rule (remote) string = _app_editor_getrulesfromlistview (hpage_rule, IDC_RULE_REMOTE_ID, INT_ERROR); _r_obj_movereference ((PVOID_PTR)&context->ptr_rule->rule_remote, string); // rule (local) string = _app_editor_getrulesfromlistview (hpage_rule, IDC_RULE_LOCAL_ID, INT_ERROR); _r_obj_movereference ((PVOID_PTR)&context->ptr_rule->rule_local, string); } item_id = _r_combobox_getcurrentitem (hpage_general, IDC_RULE_PROTOCOL_ID); context->ptr_rule->protocol = (UINT8)_r_combobox_getitemlparam (hpage_general, IDC_RULE_PROTOCOL_ID, item_id); item_id = _r_combobox_getcurrentitem (hpage_general, IDC_RULE_VERSION_ID); context->ptr_rule->af = (ADDRESS_FAMILY)_r_combobox_getitemlparam (hpage_general, IDC_RULE_VERSION_ID, item_id); _r_obj_movereference ((PVOID_PTR)&context->ptr_rule->protocol_str, _r_obj_createstring (_app_db_getprotoname (context->ptr_rule->protocol, context->ptr_rule->af))); item_id = _r_combobox_getcurrentitem (hpage_general, IDC_RULE_DIRECTION_ID); context->ptr_rule->direction = (FWP_DIRECTION)_r_combobox_getitemlparam (hpage_general, IDC_RULE_DIRECTION_ID, item_id); item_id = _r_combobox_getcurrentitem (hpage_general, IDC_RULE_ACTION_ID); context->ptr_rule->action = (FWP_ACTION_TYPE)_r_combobox_getitemlparam (hpage_general, IDC_RULE_ACTION_ID, item_id); if (context->ptr_rule->type == DATA_RULE_USER) { if (context->ptr_rule->action == FWP_ACTION_BLOCK) { context->ptr_rule->weight = FW_WEIGHT_RULE_USER_BLOCK; } else { context->ptr_rule->weight = FW_WEIGHT_RULE_USER; } } } // save rule apps if (context->ptr_rule->type == DATA_RULE_USER) { _r_obj_clearhashtable (context->ptr_rule->apps); for (INT i = 0; i < _r_listview_getitemcount (hpage_apps, IDC_RULE_APPS_ID); i++) { if (!_r_listview_isitemchecked (hpage_apps, IDC_RULE_APPS_ID, i)) continue; app_hash = (ULONG)_app_listview_getitemcontext (hpage_apps, IDC_RULE_APPS_ID, i); if (context->ptr_rule->is_forservices && _app_issystemhash (app_hash)) continue; if (_app_isappfound (app_hash)) _r_obj_addhashtableitem (context->ptr_rule->apps, app_hash, NULL); } } // enable rule _app_ruleenable (context->ptr_rule, _r_ctrl_isbuttonchecked (hwnd, IDC_ENABLE_CHK), TRUE); rules = _r_obj_createlist (1, NULL); _r_obj_addlistitem (rules, context->ptr_rule, NULL); } else { context->ptr_app->is_haveerrors = FALSE; // reset errors context->ptr_app->is_enabled = _r_ctrl_isbuttonchecked (hwnd, IDC_ENABLE_CHK); rules = _r_obj_createlist (1, NULL); _r_obj_addlistitem (rules, context->ptr_app, NULL); // comment string = _r_ctrl_getstring (hpage_general, IDC_APP_COMMENT_ID); if (string) _r_str_trimstring2 (&string->sr, DIVIDER_TRIM DIVIDER_RULE, 0); _r_obj_movereference ((PVOID_PTR)&context->ptr_app->comment, string); if (hpage_rule) { _r_queuedlock_acquireshared (&lock_rules); for (INT i = 0; i < _r_listview_getitemcount (hpage_rule, IDC_APP_RULES_ID); i++) { rule_idx = _app_listview_getitemcontext (hpage_rule, IDC_APP_RULES_ID, i); ptr_rule = _r_obj_getlistitem (rules_list, rule_idx); if (!ptr_rule) continue; listview_id = _app_listview_getbytype (ptr_rule->type); item_id = _app_listview_finditem (_r_app_gethwnd (), listview_id, rule_idx); if (item_id != INT_ERROR) { is_enable = _r_listview_isitemchecked (hpage_rule, IDC_APP_RULES_ID, i); _app_setruletoapp (_r_app_gethwnd (), ptr_rule, item_id, context->ptr_app, is_enable); } } _r_queuedlock_releaseshared (&lock_rules); } } // apply filter if (rules) { if (!_r_obj_isempty2 (rules) && _wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); if (context->is_settorules) { _wfp_create4filters (hengine, rules, DBG_ARG, FALSE); } else { _wfp_create3filters (hengine, rules, DBG_ARG, FALSE); } } _r_obj_dereference (rules); } EndDialog (hwnd, TRUE); break; } case IDCANCEL: // process Esc key { HWND hpage; HWND hsearch; INT item_id; item_id = _r_tab_getcurrentitem (hwnd, IDC_TAB); hpage = (HWND)_r_tab_getitemlparam (hwnd, IDC_TAB, item_id); if (hpage) { hsearch = GetDlgItem (hpage, IDC_SEARCH); if (hsearch) { if (GetFocus () == hsearch) { _r_ctrl_setstring (hsearch, 0, L""); SetFocus (hwnd); break; } } } FALLTHROUGH; } case IDC_CLOSE: { EndDialog (hwnd, FALSE); break; } } break; } } return FALSE; } ================================================ FILE: src/editor.h ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #pragma once typedef struct _EDITOR_CONTEXT { R_LAYOUT_MANAGER layout_manager; HWND hwnd; HICON hicon; union { PITEM_APP ptr_app; PITEM_RULE ptr_rule; }; struct { ULONG_PTR current_length; INT listview_id; INT item_id; }; INT page_id; BOOLEAN is_settorules; } EDITOR_CONTEXT, *PEDITOR_CONTEXT; _Ret_maybenull_ PEDITOR_CONTEXT _app_editor_createwindow ( _In_ HWND hwnd, _In_ PVOID lparam, _In_ INT page_id, _In_ BOOLEAN is_settorules ); VOID _app_editor_deletewindow ( _In_ PEDITOR_CONTEXT context ); _Ret_maybenull_ PEDITOR_CONTEXT _app_editor_getcontext ( _In_ HWND hwnd ); VOID _app_editor_setcontext ( _In_ HWND hwnd, _In_ PEDITOR_CONTEXT context ); VOID _app_editor_addtabitem ( _In_ HWND hwnd, _In_ UINT locale_id, _In_ INT dlg_id, _In_ PEDITOR_CONTEXT context ); VOID _app_editor_settabtitle ( _In_ HWND hwnd, _In_ INT listview_id ); _Ret_maybenull_ PR_STRING _app_editor_getrulesfromlistview ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ INT exclude_id ); VOID _app_editor_setrulestolistview ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ PR_STRING rule ); INT_PTR CALLBACK EditorRuleProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ); INT_PTR CALLBACK EditorPagesProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ); INT_PTR CALLBACK EditorProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ); ================================================ FILE: src/global.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once #include "routine.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app.h" #include "rapp.h" #include "main.h" #include "resource.h" DECLSPEC_SELECTANY STATIC_DATA config = {0}; DECLSPEC_SELECTANY PROFILE_DATA profile_info = {0}; DECLSPEC_SELECTANY PR_HASHTABLE apps_table = NULL; DECLSPEC_SELECTANY PR_LIST rules_list = NULL; DECLSPEC_SELECTANY PR_HASHTABLE rules_config = NULL; DECLSPEC_SELECTANY PR_HASHTABLE log_table = NULL; DECLSPEC_SELECTANY PR_HASHTABLE cache_information = NULL; DECLSPEC_SELECTANY PR_HASHTABLE cache_resolution = NULL; DECLSPEC_SELECTANY PR_HASHTABLE colors_table = NULL; DECLSPEC_SELECTANY PR_ARRAY filter_ids = NULL; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_apps = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_apply = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_rules = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_rules_config = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_loglist = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_notify = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_profile = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_transaction = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_cache_information = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_QUEUED_LOCK lock_cache_resolution = PR_QUEUED_LOCK_INIT; DECLSPEC_SELECTANY R_WORKQUEUE file_queue = {0}; DECLSPEC_SELECTANY R_WORKQUEUE log_queue = {0}; DECLSPEC_SELECTANY R_WORKQUEUE resolver_queue = {0}; DECLSPEC_SELECTANY R_WORKQUEUE resolve_notify_queue = {0}; DECLSPEC_SELECTANY R_WORKQUEUE wfp_queue = {0}; DECLSPEC_SELECTANY R_FREE_LIST context_free_list = {0}; DECLSPEC_SELECTANY R_FREE_LIST listview_free_list = {0}; // timers array DECLSPEC_SELECTANY const LONG64 timer_array[] = { 2 * 60LL, // 2 min 5 * 60LL, // 5 min 10 * 60LL, // 10 min 30 * 60LL, // 30 min 1 * 3600LL, // 1 hour 2 * 3600LL, // 2 hour 4 * 3600LL, // 4 hour 6 * 3600LL, // 6 hour 12 * 3600LL, // 12 hour 24 * 3600LL // 24 hour }; // dropped events callback subscription (win7+) #ifndef FWP_DIRECTION_IN #define FWP_DIRECTION_IN 0x00003900L #endif #ifndef FWP_DIRECTION_OUT #define FWP_DIRECTION_OUT 0x00003901L #endif #ifndef FWP_DIRECTION_FORWARD #define FWP_DIRECTION_FORWARD 0x00003902L #endif #ifndef FWP_DIRECTION_FORWARD2 #define FWP_DIRECTION_FORWARD2 0x00003903L #endif #define WM_NOTIFICATION (WM_APP + 21) #include "controls.h" #include "db.h" #include "editor.h" #include "helper.h" #include "icons.h" #include "listview.h" #include "log.h" #include "messages.h" #include "network.h" #include "notifications.h" #include "packages.h" #include "profile.h" #include "search.h" #include "security.h" #include "timer.h" #include "uwp.h" #include "wfp.h" ================================================ FILE: src/helper.c ================================================ // simplewall // Copyright (c) 2016-2026 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 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 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; PIN6_ADDR p6addr; PIN_ADDR p4addr; _r_obj_initializestringbuilder (&formatted_address, 256); switch (af) { case AF_INET: { p4addr = (const 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 = (const 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; LPCWSTR string; NTSTATUS status; _r_obj_initializestringbuilder (&formatted_address, 0x100); if (flags & FMTADDR_USE_PROTOCOL) { string = _app_db_getprotoname (proto, af); if (_r_str_compare (string, L"n/a", FALSE) != 0) { _r_obj_appendstringbuilder (&formatted_address, string); _r_obj_appendstringbuilder (&formatted_address, L"://"); } } 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 = RtlIpv4AddressToStringExW (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 = RtlIpv6AddressToStringExW (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); 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 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 app_hash, _In_opt_ INT listview_id, _In_ ENUM_INFO_DATA2 info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ) { 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 (length != 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, length); if (ptr_app_info) _r_obj_dereference (ptr_app_info); return TRUE; } break; } case INFO_SIGNATURE_STRING: { PVOID ptr; if (length != 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, length); _r_obj_dereference (ptr_app_info); return TRUE; } break; } case INFO_VERSION_STRING: { PVOID ptr; if (length != 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, length); _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 app_hash ) { PR_STRING string = NULL; BOOLEAN is_signed = FALSE; if (_app_getappinfoparam2 (app_hash, 0, INFO_SIGNATURE_STRING, &string, sizeof (PR_STRING))) { is_signed = !_r_obj_isstringempty2 (string); _r_obj_dereference (string); } return is_signed; } BOOLEAN _app_isappvalidbinary ( _In_opt_ PR_STRING path ) { if (!path) return FALSE; if (!_app_isappvalidpath (path)) return FALSE; if (_r_str_isendsswith2 (&path->sr, L".exe", 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 (!_r_obj_isstringempty (ptr_app->original_path)) return _r_obj_reference (ptr_app->original_path); } switch (ptr_app->type) { case DATA_APP_SERVICE: { if (!_r_obj_isstringempty (ptr_app->original_path)) return _r_obj_reference (ptr_app->original_path); break; } case DATA_APP_UWP: { if (!_r_obj_isstringempty (ptr_app->display_name)) return _r_obj_reference (ptr_app->display_name); if (!_r_obj_isstringempty (ptr_app->real_path)) return _r_obj_reference (ptr_app->real_path); if (!_r_obj_isstringempty (ptr_app->original_path)) return _r_obj_reference (ptr_app->original_path); break; } } if (is_shortened || _r_config_getboolean (L"ShowFilenames", TRUE, NULL)) { if (!_r_obj_isstringempty (ptr_app->short_name)) return _r_obj_reference (ptr_app->short_name); } if (!_r_obj_isstringempty (ptr_app->real_path)) return _r_obj_reference (ptr_app->real_path); return NULL; } _Ret_maybenull_ PR_STRING _app_getapppath ( _In_ PITEM_APP ptr_app, _In_ BOOLEAN is_returnshort ) { PR_STRING path = NULL; PR_STRING string; if (ptr_app->type == DATA_APP_UWP || ptr_app->type == DATA_APP_SERVICE) { if (ptr_app->real_path) path = _r_obj_reference (ptr_app->real_path); if (ptr_app->display_name) path = _r_obj_reference (ptr_app->display_name); } if (ptr_app->original_path) path = _r_obj_reference (ptr_app->original_path); if (ptr_app->real_path) path = _r_obj_reference (ptr_app->real_path); if (is_returnshort && path) { string = _r_str_environmentunexpandstring (&path->sr); _r_obj_movereference ((PVOID_PTR)&path, _r_path_compact (&string->sr, 64)); _r_obj_dereference (string); } return path; } 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, NULL); if (is_iconshidded || !_app_isappvalidbinary (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_PTR hcat_admin_ptr ) { static R_INITONCE init_once = PR_INITONCE_INIT; static CCAHFFH2 _CryptCATAdminCalcHashFromFileHandle2 = NULL; static CCAAC2 _CryptCATAdminAcquireContext2 = NULL; GUID DriverActionVerify = DRIVER_ACTION_VERIFY; HCATADMIN hcat_admin; PVOID hwintrust; PBYTE file_hash; ULONG file_hash_length = 32; NTSTATUS status; if (_r_initonce_begin (&init_once)) { status = _r_sys_loadlibrary2 (L"wintrust.dll", 0, &hwintrust); if (NT_SUCCESS (status)) { _CryptCATAdminAcquireContext2 = _r_sys_getprocaddress (hwintrust, "CryptCATAdminAcquireContext2", 0); _CryptCATAdminCalcHashFromFileHandle2 = _r_sys_getprocaddress (hwintrust, "CryptCATAdminCalcHashFromFileHandle2", 0); // _r_sys_freelibrary (hwintrust, FALSE); } _r_initonce_end (&init_once); } if (_CryptCATAdminAcquireContext2) { if (!_CryptCATAdminAcquireContext2 (&hcat_admin, &DriverActionVerify, algorithm_id, NULL, 0)) return FALSE; } else { if (!CryptCATAdminAcquireContext (&hcat_admin, &DriverActionVerify, 0)) return FALSE; } file_hash = _r_mem_allocate (file_hash_length); if (_CryptCATAdminCalcHashFromFileHandle2) { 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; } } } else { if (!CryptCATAdminCalcHashFromFileHandle (hfile, &file_hash_length, file_hash, 0)) { file_hash = _r_mem_reallocate (file_hash, file_hash_length); if (!CryptCATAdminCalcHashFromFileHandle (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 = CertGetNameStringW (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)); CertGetNameStringW (prov_cert->pCert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, string->buffer, length + 1); _r_str_trimtonullterminator (&string->sr); 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.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN; trust_data.pPolicyCallbackData = policy_callback; trust_data.dwUnionChoice = union_choice; trust_data.dwStateAction = WTD_STATEACTION_VERIFY; trust_data.dwProvFlags = WTD_SAFER_FLAG | WTD_DISABLE_MD2_MD4; trust_data.pFile = union_data; if (union_choice == WTD_CHOICE_CATALOG) trust_data.pCatalog = union_data; if (_r_config_getboolean (L"IsOCSPEnabled", FALSE, NULL)) { 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; } NTSTATUS _app_verifyfilefromcatalog ( _In_ HANDLE hfile, _In_ LPCWSTR path, _In_opt_ LPCWSTR algorithm_id, _Out_ PR_STRING_PTR signature_string ) { GUID DriverActionVerify = DRIVER_ACTION_VERIFY; WINTRUST_CATALOG_INFO catalog_info = {0}; DRIVER_VER_INFO ver_info = {0}; CATALOG_INFO ci = {0}; HCATADMIN hcat_admin; HCATINFO hcat_info; PR_STRING string = NULL; PR_STRING file_hash_tag; PVOID file_hash; LONG64 file_size; ULONG file_hash_length; NTSTATUS status; status = _r_fs_getsize2 (NULL, hfile, &file_size); if (!NT_SUCCESS (status)) { *signature_string = NULL; return status; } if (!file_size || file_size > _r_calc_megabytes2bytes64 (32)) { *signature_string = NULL; 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 = 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); } *signature_string = string; CryptCATAdminReleaseContext (hcat_admin, 0); _r_mem_free (file_hash); } else { *signature_string = NULL; status = TRUST_E_SUBJECT_FORM_UNKNOWN; } return status; } VOID _app_getfilesignatureinfo ( _In_ HANDLE hfile, _Inout_ PITEM_APP_INFO ptr_app_info ) { GUID WinTrustActionGenericVerifyV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; WINTRUST_FILE_INFO file_info = {0}; PR_STRING string = NULL; LONG status; __try { if (ptr_app_info->signature_info) _r_obj_clearreference ((PVOID_PTR)&ptr_app_info->signature_info); } __except (EXCEPTION_EXECUTE_HANDLER) { NOTHING; } 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) { if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { status = _app_verifyfilefromcatalog (hfile, ptr_app_info->path->buffer, BCRYPT_SHA256_ALGORITHM, &string); } else { status = _app_verifyfilefromcatalog (hfile, ptr_app_info->path->buffer, NULL, &string); } if (status == TRUST_E_NOSIGNATURE) _app_verifyfilefromcatalog (hfile, ptr_app_info->path->buffer, BCRYPT_SHA1_ALGORITHM, &string); } __try { _r_obj_movereference ((PVOID_PTR)&ptr_app_info->signature_info, string); } __except (EXCEPTION_EXECUTE_HANDLER) { NOTHING; } } 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; // clean value __try { if (ptr_app_info->version_info) _r_obj_clearreference ((PVOID_PTR)&ptr_app_info->version_info); } __except (EXCEPTION_EXECUTE_HANDLER) { NOTHING; } status = _r_sys_loadlibraryasresource (&ptr_app_info->path->sr, &hlib); if (!NT_SUCCESS (status)) goto CleanupExit; status = _r_res_loadresource (hlib, RT_VERSION, MAKEINTRESOURCE (VS_VERSION_INFO), 0, &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->sr); _r_obj_dereference (string); } // get file version if (_r_res_queryversion (ver_block.buffer, (PVOID_PTR)&ver_info)) { _r_obj_appendstringbuilder (&sb, _r_obj_isstringempty2 (sb.string) ? SZ_TAB : 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->sr); _r_obj_appendstringbuilder (&sb, SZ_CRLF); _r_obj_dereference (string); } version_string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring2 (&version_string->sr, DIVIDER_TRIM, 0); CleanupExit: ptr_app_info->version_info = version_string; if (hlib) _r_sys_freelibrary (hlib); } _Ret_maybenull_ PR_STRING _app_getfilehashinfo ( _In_ HANDLE hfile, _In_ ULONG app_hash ) { PITEM_APP ptr_app; PR_STRING string; ptr_app = _app_getappitem (app_hash); if (!ptr_app) return NULL; _r_crypt_getfilehash (BCRYPT_SHA256_ALGORITHM, NULL, hfile, &string); _r_obj_movereference ((PVOID_PTR)&ptr_app->hash, string); return ptr_app->hash; } ULONG _app_addcolor ( _In_ ULONG locale_id, _In_ LPCWSTR config_name, _In_ LPCWSTR config_value, _In_ COLORREF default_clr, _In_ BOOLEAN is_enabled ) { 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 (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_gethash (&ptr_clr.config_name->sr, TRUE); _r_obj_addhashtableitem (colors_table, hash_code, &ptr_clr); return hash_code; } COLORREF _app_getcolorvalue ( _In_ ULONG 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 app_hash, _In_opt_ PITEM_LOG ptr_log ) { ITEM_STATUS status = {0}; WCHAR buffer[128]; PITEM_RULE ptr_rule; ULONG_PTR limit_group; ULONG i; BOOLEAN is_global; BOOLEAN is_enabled; _app_getcount (&status); if (!status.rules_count) { _r_menu_additem_ex (hsubmenu, IDX_RULES_SPECIAL, _r_locale_getstring (IDS_STATUS_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 < (ULONG)_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_isempty (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_addseparator (hsubmenu); } if (ptr_log) { _r_menu_addseparator (hsubmenu); _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_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s...", _r_locale_getstring (IDS_OPENRULESEDITOR)); _r_menu_additem (hsubmenu, IDM_OPENRULESEDITOR, buffer); } VOID _app_generate_timerscontrol ( _In_ HMENU hsubmenu, _In_ ULONG app_hash ) { LONG64 current_time; LONG64 app_time = 0; LONG64 timestamp; PR_STRING string; ULONG index; BOOLEAN is_checked = FALSE; current_time = _r_unixtime_now (); _app_getappinfobyhash (app_hash, INFO_TIMER, &app_time, sizeof (LONG64)); for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (timer_array); i++) { timestamp = timer_array[i]; string = _r_format_interval (timestamp); if (!string) continue; index = IDX_TIMER + (ULONG)i; _r_menu_additem (hsubmenu, index, 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 (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_isempty (ptr_rule->apps)) _app_ruleenable (ptr_rule, FALSE, TRUE); } if (item_id != INT_ERROR) { 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; USHORT range_port1 = 0; USHORT range_port2 = 0; USHORT port; BYTE prefix_length; ULONG status; 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) { 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_getlength2 (rule); for (ULONG_PTR i = 0; i < length; i++) { if (IsCharAlphaNumericW (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 string = NULL; PR_STRING arpa_string; DNS_STATUS status; ULONG arpa_hash; arpa_string = _app_formatarpa (af, address); arpa_hash = _r_str_gethash (&arpa_string->sr, 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_BYPASS_CACHE | DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_MULTICAST, 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; } } DnsFree (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, NULL); if (is_enable) { status = _r_sys_createthread (&config.hmonitor_thread, NtCurrentProcess (), &_app_timercallback, NULL, 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; } } } VOID NTAPI _app_timercallback ( _In_opt_ PVOID context ) { PITEM_APP ptr_app = NULL; PR_STRING hash; ULONG_PTR enum_key; NTSTATUS status; while (TRUE) { _r_queuedlock_acquireshared (&lock_apps); enum_key = 0; while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (!ptr_app->hash || !_app_isappvalidbinary (ptr_app->real_path)) continue; if (!_app_isappused (ptr_app)) continue; status = _r_crypt_getfilehash (BCRYPT_SHA256_ALGORITHM, &ptr_app->real_path->sr, NULL, &hash); if (NT_SUCCESS (status)) { if (!_r_str_isequal (&ptr_app->hash->sr, &hash->sr, TRUE)) { _r_obj_movereference ((PVOID_PTR)&ptr_app->hash, hash); _app_setappinfo (ptr_app, INFO_DISABLE, NULL); } else { _r_obj_dereference (hash); } } } _r_queuedlock_releaseshared (&lock_apps); _r_sys_waitforsingleobject (NtCurrentThread (), _r_calc_minutes2milliseconds (10)); } } VOID _app_getfileinformation ( _In_ PR_STRING path, _In_ ULONG 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 (_r_obj_isstringempty (path)) return; 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); 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); } // check for binary path is valid if (_app_isappvalidbinary (path)) _r_workqueue_queueitem (&file_queue, &_app_queue_fileinformation, 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_queue_resolveinformation, context); } VOID NTAPI _app_queue_fileinformation ( _In_ PVOID arglist ) { PITEM_APP_INFO ptr_app_info; HANDLE hfile; HWND hwnd; NTSTATUS status; ptr_app_info = arglist; hwnd = _r_app_gethwnd (); if (ptr_app_info->is_loaded) return; status = _r_fs_openfile (&ptr_app_info->path->sr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, 0, FALSE, &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_openfile", status, ptr_app_info->path->buffer); return; } // query app icon _app_getfileicon (ptr_app_info); // query certificate information if (_r_config_getboolean (L"IsCertificatesEnabled", TRUE, NULL)) _app_getfilesignatureinfo (hfile, ptr_app_info); // query version info _app_getfileversioninfo (ptr_app_info); // query sha256 info if (_r_config_getboolean (L"IsHashesEnabled", FALSE, NULL)) _app_getfilehashinfo (hfile, ptr_app_info->app_hash); // redraw listview if (_r_wnd_isvisible (hwnd, FALSE)) _r_listview_redraw (hwnd, ptr_app_info->listview_id); ptr_app_info->is_loaded = TRUE; _r_obj_dereference (ptr_app_info); NtClose (hfile); } VOID NTAPI _app_queue_notifyinformation ( _In_ PVOID arglist ) { PITEM_APP_INFO ptr_app_info; PITEM_CONTEXT context; PITEM_LOG ptr_log; PR_STRING signature_str = NULL; PR_STRING host_str = NULL; PR_STRING localized_string; PR_STRING address_str; HANDLE hfile; HICON hicon; HDWP hdefer; ULONG attempts = 6; 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, NULL)) { host_str = _app_resolveaddress_interlocked ((volatile PVOID_PTR)&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 if (_r_config_getboolean (L"IsCertificatesEnabled", TRUE, NULL)) { ptr_app_info = _app_getappinfobyhash2 (ptr_log->app_hash); if (ptr_app_info) { if (_app_isappvalidbinary (ptr_app_info->path)) { status = _r_fs_openfile (&ptr_app_info->path->sr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, 0, FALSE, &hfile); if (NT_SUCCESS (status)) { _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, FALSE)) { if (ptr_log->app_hash == _app_notify_getapp_id (context->hwnd)) { // set file icon _app_notify_setapp_icon (context->hwnd, hicon); is_iconset = TRUE; // set signature information localized_string = _r_obj_concatstrings ( 2, _r_locale_getstring (IDS_SIGNATURE), L":" ); do { if (!_app_getappinfoparam2 (ptr_log->app_hash, 0, INFO_SIGNATURE_STRING, &signature_str, sizeof (signature_str))) { _r_sys_sleep (250); } else { break; } } while (--attempts); if (!signature_str) _r_obj_movereference ((PVOID_PTR)&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 ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_ADDRESS), L":")); if (_r_obj_isstringempty (address_str)) _r_obj_movereference ((PVOID_PTR)&address_str, _r_locale_getstring_ex (IDS_STATUS_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 ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_HOST), L":")); if (_r_obj_isstringempty (host_str)) _r_obj_movereference ((PVOID_PTR)&host_str, _r_locale_getstring_ex (IDS_STATUS_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_queue_resolveinformation ( _In_ PVOID arglist ) { PITEM_NETWORK ptr_network; PITEM_CONTEXT context; PITEM_LOG ptr_log; BOOLEAN is_resolutionenabled; context = arglist; is_resolutionenabled = _r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE, NULL); switch (context->listview_id) { case IDC_LOG: { ptr_log = context->base_address; _app_resolveaddress_interlocked ((volatile PVOID_PTR)&ptr_log->local_host_str, ptr_log->af, &ptr_log->local_addr, is_resolutionenabled); _app_resolveaddress_interlocked ((volatile PVOID_PTR)&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 ((volatile PVOID_PTR)&ptr_network->local_addr_str, ptr_network->af, &ptr_network->local_addr); _app_formataddress_interlocked ((volatile PVOID_PTR)&ptr_network->remote_addr_str, ptr_network->af, &ptr_network->remote_addr); _app_resolveaddress_interlocked ((volatile PVOID_PTR)&ptr_network->local_host_str, ptr_network->af, &ptr_network->local_addr, is_resolutionenabled); _app_resolveaddress_interlocked ((volatile PVOID_PTR)&ptr_network->remote_host_str, ptr_network->af, &ptr_network->remote_addr, is_resolutionenabled); break; } } // redraw listview if (_r_wnd_isvisible (context->hwnd, FALSE)) _r_listview_redraw (context->hwnd, context->listview_id); _r_obj_dereference (context->base_address); _r_freelist_deleteitem (&context_free_list, context); } BOOLEAN _app_wufixenabled () { WCHAR file_path[256]; R_STRINGREF sr; if (!_r_config_getboolean (L"IsWUFixEnabled", FALSE, NULL)) return FALSE; _r_str_printf (file_path, RTL_NUMBER_OF (file_path), L"%s\\wusvc.exe", _r_sys_getsystemdirectory ()->buffer); _r_obj_initializestringref (&sr, file_path); if (_r_fs_isexists (&sr)) return TRUE; return FALSE; } 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_value[128]; WCHAR reg_key[128]; PR_STRING image_path; SC_HANDLE hsvc; HANDLE hkey; BOOLEAN is_enabled = FALSE; NTSTATUS status; _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, 0, KEY_READ | KEY_WRITE, &hkey); if (!NT_SUCCESS (status)) return; // query service path status = _r_reg_querystring (hkey, L"ImagePath", &image_path, NULL); 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 ? PATH_WUSVC : PATH_SVCHOST, k_value); _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 = OpenServiceW (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 ) { PR_STRING service_path; SC_HANDLE hsvcmgr; ULONG app_hash; hsvcmgr = OpenSCManagerW (NULL, NULL, SC_MANAGER_CONNECT | SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS); if (!hsvcmgr) return; if (is_enable) { if (_r_fs_isexists (&config.wusvc_path->sr)) _r_fs_deletefile (&config.wusvc_path->sr, NULL); _r_fs_copyfile (&config.svchost_path->sr, &config.wusvc_path->sr, FALSE); service_path = _r_obj_createstring2 (&config.wusvc_path->sr); app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, service_path, NULL, NULL); if (app_hash) { _app_setappinfobyhash (app_hash, INFO_IS_ENABLED, LongToPtr (TRUE)); _app_setappinfobyhash (app_hash, INFO_IS_UNDELETABLE, LongToPtr (TRUE)); } _r_obj_dereference (service_path); } else { if (_r_fs_isexists (&config.wusvc_path->sr)) { app_hash = _r_str_gethash (&config.wusvc_path->sr, TRUE); if (app_hash) { _app_setappinfobyhash (app_hash, INFO_IS_ENABLED, LongToPtr (FALSE)); _app_setappinfobyhash (app_hash, INFO_IS_UNDELETABLE, LongToPtr (FALSE)); } _r_fs_deletefile (&config.wusvc_path->sr, NULL); } } _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); _r_config_setboolean (L"IsWUFixEnabled", is_enable, NULL); CloseServiceHandle (hsvcmgr); } ================================================ FILE: src/helper.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once typedef struct _ICON_INFORMATION { HICON app_hicon; HICON service_hicon; HICON uwp_hicon; LONG app_icon_id; LONG service_icon_id; LONG uwp_icon_id; } ICON_INFORMATION, *PICON_INFORMATION; #define FMTADDR_AS_RULE 0x0001 #define FMTADDR_USE_PROTOCOL 0x0002 VOID NTAPI _app_dereferenceapp ( _In_ PVOID entry ); VOID NTAPI _app_dereferenceappinfo ( _In_ PVOID entry ); VOID NTAPI _app_dereferenceruleconfig ( _In_ PVOID entry ); VOID NTAPI _app_dereferencenetwork ( _In_ PVOID entry ); VOID NTAPI _app_dereferencelog ( _In_ PVOID entry ); VOID NTAPI _app_dereferencerule ( _In_ PVOID entry ); VOID _app_addcachetable ( _Inout_ PR_HASHTABLE hashtable, _In_ ULONG hash_code, _In_ PR_QUEUED_LOCK spin_lock, _In_opt_ PR_STRING string ); BOOLEAN _app_getcachetable ( _Inout_ PR_HASHTABLE cache_table, _In_ ULONG hash_code, _In_ PR_QUEUED_LOCK spin_lock, _Out_ PR_STRING_PTR string ); PR_STRING _app_formatarpa ( _In_ ADDRESS_FAMILY af, _In_ LPCVOID address ); _Ret_maybenull_ PR_STRING _app_formataddress ( _In_ ADDRESS_FAMILY af, _In_ UINT8 proto, _In_ LPCVOID address, _In_opt_ UINT16 port, _In_ ULONG flags ); PR_STRING _app_formataddress_interlocked ( _In_ PVOID volatile *string, _In_ ADDRESS_FAMILY af, _In_ LPCVOID address ); _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 ); PR_STRING _app_formatport ( _In_ UINT16 port, _In_ UINT8 proto ); _Ret_maybenull_ PITEM_APP_INFO _app_getappinfobyhash2 ( _In_ ULONG app_hash ); _Success_ (return) BOOLEAN _app_getappinfoparam2 ( _In_ ULONG app_hash, _In_opt_ INT listview_id, _In_ ENUM_INFO_DATA2 info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ); BOOLEAN _app_isappsigned ( _In_ ULONG app_hash ); BOOLEAN _app_isappvalidbinary ( _In_opt_ PR_STRING path ); BOOLEAN _app_isappvalidpath ( _In_opt_ PR_STRING path ); _Ret_maybenull_ PR_STRING _app_getappdisplayname ( _In_ PITEM_APP ptr_app, _In_ BOOLEAN is_shortened ); _Ret_maybenull_ PR_STRING _app_getapppath ( _In_ PITEM_APP ptr_app, _In_ BOOLEAN is_returnshort ); VOID _app_getfileicon ( _Inout_ PITEM_APP_INFO ptr_app_info ); VOID _app_getfilesignatureinfo ( _In_ HANDLE hfile, _Inout_ PITEM_APP_INFO ptr_app_info ); VOID _app_getfileversioninfo ( _Inout_ PITEM_APP_INFO ptr_app_info ); _Ret_maybenull_ PR_STRING _app_getfilehashinfo ( _In_ HANDLE hfile, _In_ ULONG app_hash ); ULONG _app_addcolor ( _In_ ULONG locale_id, _In_ LPCWSTR config_name, _In_ LPCWSTR config_value, _In_ COLORREF default_clr, _In_ BOOLEAN is_enabled ); COLORREF _app_getcolorvalue ( _In_ ULONG color_hash ); VOID _app_generate_rulescontrol ( _In_ HMENU hsubmenu, _In_ ULONG app_hash, _In_opt_ PITEM_LOG ptr_log ); VOID _app_generate_timerscontrol ( _In_ HMENU hsubmenu, _In_ ULONG app_hash ); BOOLEAN _app_setruletoapp ( _In_ HWND hwnd, _Inout_ PITEM_RULE ptr_rule, _In_ INT item_id, _In_ PITEM_APP ptr_app, _In_ BOOLEAN is_enable ); _Success_ (return) BOOLEAN _app_parsenetworkstring ( _In_ LPCWSTR network_string, _Inout_ PITEM_ADDRESS address ); _Success_ (return) BOOLEAN _app_preparserulestring ( _In_ PR_STRINGREF rule, _Out_ PITEM_ADDRESS address ); _Success_ (return) BOOLEAN _app_parserulestring ( _In_opt_ PR_STRINGREF rule, _Out_ PITEM_ADDRESS address ); _Ret_maybenull_ PR_STRING _app_resolveaddress ( _In_ ADDRESS_FAMILY af, _In_ LPCVOID address ); PR_STRING _app_resolveaddress_interlocked ( _In_ PVOID volatile *string, _In_ ADDRESS_FAMILY af, _In_ LPCVOID address, _In_ BOOLEAN is_resolutionenabled ); VOID _app_fileloggingenable (); VOID NTAPI _app_timercallback ( _In_opt_ PVOID context ); VOID _app_getfileinformation ( _In_ PR_STRING path, _In_ ULONG app_hash, _In_ ENUM_TYPE_DATA type, _In_ INT listview_id ); VOID _app_queue_resolver ( _In_ HWND hwnd, _In_ INT listview_id, _In_ ULONG_PTR hash_code, _In_ PVOID base_address ); VOID NTAPI _app_queue_fileinformation ( _In_ PVOID arglist ); VOID NTAPI _app_queue_notifyinformation ( _In_ PVOID arglist ); VOID NTAPI _app_queue_resolveinformation ( _In_ PVOID arglist ); BOOLEAN _app_wufixenabled (); VOID _app_wufixhelper ( _In_ SC_HANDLE hsvcmgr, _In_ LPCWSTR service_name, _In_ LPCWSTR k_value, _In_ BOOLEAN is_enable ); VOID _app_wufixenable ( _In_ HWND hwnd, _In_ BOOLEAN is_install ); ================================================ FILE: src/icons.c ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #include "global.h" PICON_INFORMATION _app_icons_getdefault () { static R_INITONCE init_once = PR_INITONCE_INIT; static ICON_INFORMATION icon_info = {0}; PR_STRING path; if (_r_initonce_begin (&init_once)) { // load default icons path = _r_obj_concatstrings ( 2, _r_sys_getsystemdirectory ()->buffer, PATH_SVCHOST ); _app_icons_loadfromfile (path, 0, &icon_info.app_icon_id, &icon_info.app_hicon, FALSE); // load default service icons _r_obj_dereference (path); path = _r_obj_concatstrings ( 2, _r_sys_getsystemdirectory ()->buffer, L"\\shell32.dll" ); _app_icons_loadfromfile (path, 0, &icon_info.service_icon_id, &icon_info.service_hicon, FALSE); _r_obj_dereference (path); // load uwp icons if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { path = _r_obj_concatstrings ( 2, _r_sys_getsystemdirectory ()->buffer, L"\\wsreset.exe" ); _app_icons_loadfromfile (path, 0, &icon_info.uwp_icon_id, &icon_info.uwp_hicon, FALSE); _r_obj_dereference (path); } _r_initonce_end (&init_once); } return &icon_info; } _Ret_maybenull_ HICON _app_icons_getdefaultapp_hicon () { PICON_INFORMATION icon_info; icon_info = _app_icons_getdefault (); if (icon_info->app_hicon) return CopyIcon (icon_info->app_hicon); return NULL; } _Ret_maybenull_ HICON _app_icons_getdefaulttype_hicon ( _In_ ENUM_TYPE_DATA type, _In_ PICON_INFORMATION icon_info ) { if (type == DATA_APP_SERVICE) { if (icon_info->service_hicon) return CopyIcon (icon_info->service_hicon); } else if (type == DATA_APP_UWP) { if (icon_info->uwp_hicon) return CopyIcon (icon_info->uwp_hicon); } if (icon_info->app_hicon) return CopyIcon (icon_info->app_hicon); return NULL; } LONG _app_icons_getdefaultapp_id ( _In_ ENUM_TYPE_DATA type ) { PICON_INFORMATION icon_info; icon_info = _app_icons_getdefault (); if (type == DATA_APP_SERVICE) { return icon_info->service_icon_id; } else if (type == DATA_APP_UWP) { return icon_info->uwp_icon_id; } return icon_info->app_icon_id; } _Ret_maybenull_ HICON _app_icons_getsafeapp_hicon ( _In_ ULONG app_hash ) { PICON_INFORMATION icon_info; PITEM_APP ptr_app; HICON hicon; LONG icon_id; BOOLEAN is_iconshidded; icon_info = _app_icons_getdefault (); ptr_app = _app_getappitem (app_hash); if (!ptr_app) { if (icon_info->app_hicon) return CopyIcon (icon_info->app_hicon); return NULL; } is_iconshidded = _r_config_getboolean (L"IsIconsHidden", FALSE, NULL); if (is_iconshidded || !_app_isappvalidbinary (ptr_app->real_path)) { hicon = _app_icons_getdefaulttype_hicon (ptr_app->type, icon_info); _r_obj_dereference (ptr_app); return hicon; } _app_icons_loadfromfile (ptr_app->real_path, ptr_app->type, &icon_id, &hicon, TRUE); if (!icon_id || ((ptr_app->type == DATA_APP_UWP || ptr_app->type == DATA_APP_SERVICE) && icon_id == icon_info->app_icon_id)) { if (hicon) DestroyIcon (hicon); hicon = _app_icons_getdefaulttype_hicon (ptr_app->type, icon_info); } _r_obj_dereference (ptr_app); return hicon; } VOID _app_icons_loaddefaults ( _In_ ENUM_TYPE_DATA type, _Inout_opt_ HICON_PTR hicon_ptr, _Inout_opt_ PLONG icon_id_ptr ) { PICON_INFORMATION icon_info; icon_info = _app_icons_getdefault (); if (icon_id_ptr) { if (*icon_id_ptr == 0 || (type == DATA_APP_UWP && *icon_id_ptr == icon_info->app_icon_id) || (type == DATA_APP_SERVICE && *icon_id_ptr == icon_info->app_icon_id)) { if (type == DATA_APP_UWP) { *icon_id_ptr = icon_info->uwp_icon_id; } else if (type == DATA_APP_SERVICE) { *icon_id_ptr = icon_info->service_icon_id; } else { *icon_id_ptr = icon_info->app_icon_id; } } } if (hicon_ptr) { if (*hicon_ptr == NULL || type == DATA_APP_UWP) { if (type == DATA_APP_UWP) { if (icon_info->uwp_hicon) *hicon_ptr = CopyIcon (icon_info->uwp_hicon); } else { if (icon_info->app_hicon) *hicon_ptr = CopyIcon (icon_info->app_hicon); } } } } VOID _app_icons_loadfromfile ( _In_opt_ PR_STRING path, _In_ ENUM_TYPE_DATA type, _Out_opt_ PLONG icon_id_ptr, _Out_opt_ HICON_PTR hicon_ptr, _In_ BOOLEAN is_loaddefaults ) { if (!icon_id_ptr && !hicon_ptr) return; if (icon_id_ptr) *icon_id_ptr = 0; if (hicon_ptr) *hicon_ptr = NULL; if (!_r_obj_isstringempty (path)) _r_path_geticon (&path->sr, hicon_ptr, icon_id_ptr); if (is_loaddefaults) _app_icons_loaddefaults (type, hicon_ptr, icon_id_ptr); } ================================================ FILE: src/icons.h ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #pragma once PICON_INFORMATION _app_icons_getdefault (); _Ret_maybenull_ HICON _app_icons_getdefaultapp_hicon (); _Ret_maybenull_ HICON _app_icons_getdefaulttype_hicon ( _In_ ENUM_TYPE_DATA type, _In_ PICON_INFORMATION icon_info ); LONG _app_icons_getdefaultapp_id ( _In_ ENUM_TYPE_DATA type ); _Ret_maybenull_ HICON _app_icons_getsafeapp_hicon ( _In_ ULONG app_hash ); VOID _app_icons_loaddefaults ( _In_ ENUM_TYPE_DATA type, _Inout_opt_ HICON_PTR hicon_ptr, _Inout_opt_ PLONG icon_id_ptr ); VOID _app_icons_loadfromfile ( _In_opt_ PR_STRING path, _In_ ENUM_TYPE_DATA type, _Out_opt_ PLONG icon_id_ptr, _Out_opt_ HICON_PTR hicon_ptr, _In_ BOOLEAN is_loaddefaults ); ================================================ FILE: src/listview.c ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #include "global.h" _Ret_maybenull_ PITEM_TAB_CONTEXT _app_listview_getcontext ( _In_ HWND hwnd, _In_ INT tab_id ) { if (tab_id == INT_ERROR) { tab_id = _r_tab_getcurrentitem (hwnd, IDC_TAB); if (tab_id == INT_ERROR) tab_id = 0; } return (PITEM_TAB_CONTEXT)_r_tab_getitemlparam (hwnd, IDC_TAB, tab_id); } _Success_ (return != 0) INT _app_listview_getbytype ( _In_ ENUM_TYPE_DATA type ) { switch (type) { case DATA_APP_REGULAR: case DATA_APP_DEVICE: case DATA_APP_NETWORK: case DATA_APP_PICO: { return IDC_APPS_PROFILE; } case DATA_APP_SERVICE: { return IDC_APPS_SERVICE; } case DATA_APP_UWP: { return IDC_APPS_UWP; } case DATA_RULE_BLOCKLIST: { return IDC_RULES_BLOCKLIST; } case DATA_RULE_SYSTEM: { return IDC_RULES_SYSTEM; } case DATA_RULE_SYSTEM_USER: case DATA_RULE_USER: { return IDC_RULES_CUSTOM; } default: { FALLTHROUGH; } } return 0; } VOID _app_listview_additems ( _In_ HWND hwnd ) { PITEM_APP ptr_app = NULL; PITEM_RULE ptr_rule; LONG64 current_time; ULONG_PTR enum_key = 0; current_time = _r_unixtime_now (); // add apps _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { _app_listview_addappitem (hwnd, ptr_app); // install timer if (ptr_app->timer) _app_timer_set (hwnd, ptr_app, ptr_app->timer - current_time); } _r_queuedlock_releaseshared (&lock_apps); // add rules _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (ptr_rule) _app_listview_addruleitem (hwnd, ptr_rule, (ULONG)i, FALSE); } _r_queuedlock_releaseshared (&lock_rules); } VOID _app_listview_clearitems ( _In_ HWND hwnd ) { for (INT i = IDC_APPS_PROFILE; i <= IDC_RULES_CUSTOM; i++) { _r_listview_deleteallitems (hwnd, i); } } VOID _app_listview_addappitem ( _In_ HWND hwnd, _In_ PITEM_APP ptr_app ) { INT listview_id; INT item_id; listview_id = _app_listview_getbytype (ptr_app->type); if (!listview_id) return; item_id = _r_listview_getitemcount (hwnd, listview_id); _app_listview_lock (hwnd, listview_id, TRUE); _r_listview_additem (hwnd, listview_id, item_id, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, _app_listview_createcontext (ptr_app->app_hash)); _app_setappiteminfo (hwnd, listview_id, item_id, ptr_app); _app_listview_lock (hwnd, listview_id, FALSE); } VOID _app_listview_addruleitem ( _In_ HWND hwnd, _In_ PITEM_RULE ptr_rule, _In_ ULONG_PTR rule_idx, _In_ BOOLEAN is_forapp ) { INT listview_id; INT item_id; listview_id = _app_listview_getbytype (ptr_rule->type); if (!listview_id) return; item_id = _r_listview_getitemcount (hwnd, listview_id); _app_listview_lock (hwnd, listview_id, TRUE); _r_listview_additem (hwnd, listview_id, item_id, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, _app_listview_createcontext (rule_idx)); _app_setruleiteminfo (hwnd, listview_id, item_id, ptr_rule, is_forapp); _app_listview_lock (hwnd, listview_id, FALSE); } VOID _app_listview_addnetworkitem ( _In_ HWND hwnd, _In_ ULONG network_hash ) { _r_listview_additem (hwnd, IDC_NETWORK, INT_ERROR, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, _app_listview_createcontext (network_hash)); } VOID _app_listview_addlogitem ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log, _In_ ULONG log_hash ) { // increment value _InterlockedIncrement (&config.log_id); ptr_log->log_id = _InterlockedCompareExchange (&config.log_id, 0, 0); _r_listview_additem (hwnd, IDC_LOG, INT_ERROR, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, 0, _app_listview_createcontext (log_hash)); } BOOLEAN _app_listview_islocked ( _In_ HWND hwnd, _In_ INT ctrl_id ) { PVOID context; ULONG property_id; property_id = (USHORT_MAX - ctrl_id); context = _r_wnd_getcontext (hwnd, property_id); return (context != NULL); } VOID _app_listview_lock ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ BOOLEAN is_lock ) { ULONG property_id; property_id = (USHORT_MAX - ctrl_id); if (is_lock) { _r_wnd_setcontext (hwnd, property_id, INVALID_HANDLE_VALUE); } else { _r_wnd_removecontext (hwnd, property_id); } } LONG_PTR _app_listview_createcontext ( _In_ ULONG_PTR id_code ) { PITEM_LISTVIEW_CONTEXT context; context = _r_freelist_allocateitem (&listview_free_list); context->id_code = id_code; return (LONG_PTR)context; } VOID _app_listview_destroycontext ( _In_ PITEM_LISTVIEW_CONTEXT context ) { _r_freelist_deleteitem (&listview_free_list, context); } ULONG_PTR _app_listview_getcontextcode ( _In_ LONG_PTR lparam ) { PITEM_LISTVIEW_CONTEXT context; context = (PITEM_LISTVIEW_CONTEXT)lparam; return context->id_code; } _Success_ (return != 0) ULONG _app_listview_getappcontext ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id ) { PITEM_NETWORK ptr_network; PITEM_LOG ptr_log; LONG_PTR context; ULONG app_hash = 0; context = _r_listview_getitemlparam (hwnd, listview_id, item_id); if (!context) return 0; context = _app_listview_getcontextcode (context); switch (listview_id) { case IDC_NETWORK: { ptr_network = _app_network_getitem ((ULONG)context); if (ptr_network) { app_hash = ptr_network->app_hash; _r_obj_dereference (ptr_network); } break; } case IDC_LOG: { ptr_log = _app_getlogitem ((ULONG)context); if (ptr_log) { app_hash = ptr_log->app_hash; _r_obj_dereference (ptr_log); } break; } default: { app_hash = (ULONG)context; break; } } return app_hash; } ULONG_PTR _app_listview_getitemcontext ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id ) { LONG_PTR lparam; lparam = _r_listview_getitemlparam (hwnd, listview_id, item_id); if (!lparam) return 0; return _app_listview_getcontextcode (lparam); } BOOLEAN _app_listview_isitemhidden ( _In_ LPARAM lparam ) { PITEM_LISTVIEW_CONTEXT context; context = (PITEM_LISTVIEW_CONTEXT)lparam; if (!context) return FALSE; return !!context->is_hidden; } _Success_ (return != INT_ERROR) INT _app_listview_finditem ( _In_ HWND hwnd, _In_ INT listview_id, _In_ ULONG_PTR id_code ) { ULONG_PTR current_code; INT item_count; if ((listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG) || listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID) { item_count = _r_listview_getitemcount (hwnd, listview_id); for (INT i = 0; i < item_count; i++) { current_code = _app_listview_getitemcontext (hwnd, listview_id, i); if (current_code == id_code) return i; } } else { return _r_listview_finditem (hwnd, listview_id, INT_ERROR, id_code); } return INT_ERROR; } VOID _app_listview_removeitem ( _In_ HWND hwnd, _In_ ULONG_PTR id_code, _In_ ENUM_TYPE_DATA type ) { INT listview_id; INT item_id; if (!hwnd) return; listview_id = _app_listview_getbytype (type); if (!listview_id) return; item_id = _app_listview_finditem (hwnd, listview_id, id_code); if (item_id != INT_ERROR) _r_listview_deleteitem (hwnd, listview_id, item_id); } VOID _app_listview_showitemby_id ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _In_ INT scroll_pos ) { INT total_count; _app_settab_id (hwnd, listview_id); total_count = _r_listview_getitemcount (hwnd, listview_id); if (!total_count) return; if (item_id != INT_ERROR) { item_id = _r_calc_clamp (item_id, 0, total_count - 1); _r_listview_setitemvisible (hwnd, listview_id, item_id); } // restore scroll position if (scroll_pos > 0) _r_listview_scroll (hwnd, listview_id, scroll_pos); } VOID _app_listview_showitemby_param ( _In_ HWND hwnd, _In_ ULONG_PTR lparam, _In_ BOOLEAN is_app ) { PITEM_TAB_CONTEXT tab_context; INT listview_id = 0; INT item_id; if (is_app) { _app_getappinfobyhash ((ULONG)lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (INT)); } else { _app_getruleinfobyid (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (INT)); } if (!listview_id) return; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (tab_context) { if (listview_id != tab_context->listview_id) { _app_listview_sort (hwnd, listview_id, INT_ERROR, FALSE); _app_listview_resize (hwnd, listview_id, FALSE); } } item_id = _app_listview_finditem (hwnd, listview_id, lparam); if (item_id != INT_ERROR) { _app_listview_showitemby_id (hwnd, listview_id, item_id, INT_ERROR); _r_wnd_toggle (hwnd, TRUE); } } VOID _app_listview_updateby_id ( _In_ HWND hwnd, _In_ INT lparam, _In_ ULONG flags ) { PITEM_TAB_CONTEXT tab_context; ENUM_TYPE_DATA type; INT listview_id; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return; if (flags & PR_UPDATE_TYPE) { type = lparam; if (type == DATA_LISTVIEW_CURRENT) { listview_id = tab_context->listview_id; } else { listview_id = _app_listview_getbytype (type); } } else { listview_id = lparam; } if ((flags & PR_UPDATE_FORCE) || (listview_id == tab_context->listview_id)) { if (!(flags & PR_UPDATE_NOREDRAW)) _r_listview_redraw (hwnd, listview_id); if (!(flags & PR_UPDATE_NOSETVIEW)) { _app_listview_setfont (hwnd, listview_id); _app_listview_setview (hwnd, listview_id); } if (!(flags & PR_UPDATE_NOREFRESH)) _app_listview_refreshgroups (hwnd, listview_id); if (!(flags & PR_UPDATE_NOSORT)) _app_listview_sort (hwnd, listview_id, INT_ERROR, FALSE); if (!(flags & PR_UPDATE_NORESIZE)) _app_listview_resize (hwnd, listview_id, FALSE); } _app_refreshstatus (hwnd); } VOID _app_listview_updateby_param ( _In_ HWND hwnd, _In_ ULONG_PTR lparam, _In_ ULONG flags, _In_ BOOLEAN is_app ) { PITEM_TAB_CONTEXT tab_context; INT listview_id = 0; if (is_app) { _app_getappinfobyhash ((ULONG)lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (INT)); } else { _app_getruleinfobyid (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (INT)); } if (!listview_id) return; if ((flags & PR_SETITEM_UPDATE)) _app_listview_updateby_id (hwnd, listview_id, 0); if ((flags & PR_SETITEM_REDRAW)) { tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (tab_context) { if (listview_id == tab_context->listview_id) _r_listview_redraw (hwnd, listview_id); } } } VOID _app_listview_updateitemby_param ( _In_ HWND hwnd, _In_ ULONG_PTR lparam, _In_ BOOLEAN is_app ) { PITEM_RULE ptr_rule; PITEM_APP ptr_app; INT listview_id = 0; INT item_id; if (is_app) { _app_getappinfobyhash ((ULONG)lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (INT)); } else { _app_getruleinfobyid (lparam, INFO_LISTVIEW_ID, &listview_id, sizeof (INT)); } if (!listview_id) return; item_id = _app_listview_finditem (hwnd, listview_id, lparam); if (item_id == INT_ERROR) return; if (is_app) { ptr_app = _app_getappitem ((ULONG)lparam); if (!ptr_app) return; _app_listview_lock (hwnd, listview_id, TRUE); _app_setappiteminfo (hwnd, listview_id, item_id, ptr_app); _app_listview_lock (hwnd, listview_id, FALSE); _r_obj_dereference (ptr_app); } else { ptr_rule = _app_getrulebyid (lparam); if (!ptr_rule) return; _app_listview_lock (hwnd, listview_id, TRUE); _app_setruleiteminfo (hwnd, listview_id, item_id, ptr_rule, FALSE); _app_listview_lock (hwnd, listview_id, FALSE); _r_obj_dereference (ptr_rule); } } VOID _app_listview_updateitemby_id ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id ) { _r_listview_setitem (hwnd, listview_id, item_id, 0, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, I_DEFAULT); } VOID _app_listview_loadfont ( _In_ LONG dpi_value, _In_ BOOLEAN is_forced ) { LOGFONT logfont = {0}; if (is_forced || !config.hfont) { SAFE_DELETE_OBJECT (config.hfont); _r_config_getfont (L"Font", &logfont, dpi_value, NULL); config.hfont = _app_createfont (&logfont, 0, FALSE, 0); } } VOID _app_listview_refreshgroups ( _In_ HWND hwnd, _In_ INT listview_id ) { WCHAR buffer1[128]; WCHAR buffer2[128]; UINT group1_title; UINT group2_title; UINT group3_title; UINT group4_title; UINT group5_title; INT total_count; INT group1_count = 0; INT group2_count = 0; INT group3_count = 0; INT group4_count = 0; INT group5_count = 0; INT group_id; BOOLEAN is_rules; if (!_r_listview_isgroupviewenabled (hwnd, listview_id)) return; is_rules = (listview_id >= IDC_RULES_BLOCKLIST && listview_id <= IDC_RULES_CUSTOM); if (listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_APPS_UWP) { group1_title = IDS_GROUP_ALLOWED; group2_title = IDS_GROUP_TIMER; group3_title = IDS_GROUP_SPECIAL_APPS; group4_title = IDS_GROUP_BLOCKED; group5_title = IDS_GROUP_BLOCKED; } else if (is_rules) { group1_title = IDS_GROUP_ENABLED; group2_title = IDS_GROUP_ENABLED; group3_title = IDS_GROUP_DISABLED; group4_title = 0; group5_title = 0; } else if (listview_id == IDC_RULE_APPS_ID || listview_id == IDC_NETWORK) { group1_title = IDS_TAB_APPS; group2_title = IDS_TAB_SERVICES; group3_title = IDS_TAB_PACKAGES; group4_title = 0; group5_title = 0; } else if (listview_id == IDC_APP_RULES_ID) { group1_title = IDS_TRAY_SYSTEM_RULES; group2_title = IDS_TRAY_USER_RULES; group3_title = 0; group4_title = 0; group5_title = 0; } else { return; } total_count = _r_listview_getitemcount (hwnd, listview_id); for (INT i = 0; i < total_count; i++) { if (listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID) { if (_r_listview_isitemchecked (hwnd, listview_id, i)) group1_count = group2_count = group3_count += 1; } else { group_id = _r_listview_getitemgroup (hwnd, listview_id, i); if (group_id == 4) { group5_count += 1; } else if (group_id == 3) { group4_count += 1; } else if (group_id == 2) { group3_count += 1; } else if (group_id == 1) { group2_count += 1; } else if (group_id == 0) { group1_count += 1; } } } if (total_count) { // set group titles if (is_rules) { _r_str_printf (buffer1, RTL_NUMBER_OF (buffer1), L"%s (%d/%d) [%s]", _r_locale_getstring (group1_title), group1_count, total_count, _r_locale_getstring (IDS_RULE_FOR_ALL)); _r_str_printf (buffer2, RTL_NUMBER_OF (buffer2), L"%s (%d/%d) [%s]", _r_locale_getstring (group2_title), group2_count, total_count, _r_locale_getstring (IDS_RULE_FOR_ALL)); } else { _r_str_printf (buffer1, RTL_NUMBER_OF (buffer1), L"%s (%d/%d)", _r_locale_getstring (group1_title), group1_count, total_count); _r_str_printf (buffer2, RTL_NUMBER_OF (buffer2), L"%s (%d/%d)", _r_locale_getstring (group2_title), group2_count, total_count); } _r_listview_setgroup (hwnd, listview_id, 0, buffer1, 0, 0); _r_listview_setgroup (hwnd, listview_id, 1, buffer2, 0, 0); if (group3_title) { _r_str_printf (buffer1, RTL_NUMBER_OF (buffer1), L"%s (%d/%d)", _r_locale_getstring (group3_title), group3_count, total_count); _r_listview_setgroup (hwnd, listview_id, 2, buffer1, 0, 0); } if (group4_title) { _r_str_printf (buffer1, RTL_NUMBER_OF (buffer1), L"%s (%d/%d)", _r_locale_getstring (group4_title), group4_count, total_count); _r_listview_setgroup (hwnd, listview_id, 3, buffer1, 0, 0); } // set group #5 title if (group5_title) { _r_str_printf (buffer1, RTL_NUMBER_OF (buffer1), L"%s (%d/%d) [silent]", _r_locale_getstring (group5_title), group5_count, total_count); _r_listview_setgroup (hwnd, listview_id, 4, buffer1, 0, 0); } } } VOID _app_listview_resize ( _In_ HWND hwnd, _In_ INT listview_id, _In_ BOOLEAN is_forced ) { PR_STRING string; HWND hlistview; HWND header = NULL; HDC hdc_listview = NULL; HDC hdc_header = NULL; LONG column_general_id = 0; // set general column id LONG calculated_width = 0; LONG column_count; LONG column_width; LONG total_width; LONG item_count; LONG text_width; LONG dpi_value; LONG max_width; LONG spacing; BOOLEAN is_tableview; if (!is_forced && !_r_config_getboolean (L"AutoSizeColumns", TRUE, NULL)) return; hlistview = GetDlgItem (hwnd, listview_id); if (!hlistview) return; column_count = _r_listview_getcolumncount (hwnd, listview_id); if (!column_count) return; // get device context hdc_listview = GetDC (hlistview); if (!hdc_listview) goto CleanupExit; header = _r_listview_getheader (hwnd, listview_id); if (!header) goto CleanupExit; hdc_header = GetDC (header); if (!hdc_header) goto CleanupExit; _r_dc_fixfont (hdc_listview, hwnd, listview_id); // fix font set _r_dc_fixfont (hdc_header, header, 0); // fix font set is_tableview = (_r_listview_getview (hwnd, listview_id) == LV_VIEW_DETAILS); dpi_value = _r_dc_getwindowdpi (hwnd); max_width = _r_dc_getdpi (158, dpi_value); spacing = _r_dc_getsystemmetrics (SM_CXSMICON, dpi_value); total_width = _r_ctrl_getwidth (hwnd, listview_id); item_count = _r_listview_getitemcount (hwnd, listview_id); if (listview_id == IDC_LOG) column_general_id = 1; for (LONG i = 0; i < column_count; i++) { if (i == column_general_id) continue; // get column text width string = _r_listview_getcolumntext (hwnd, listview_id, i); if (!string) continue; column_width = _r_dc_getfontwidth (hdc_header, &string->sr, NULL) + spacing; _r_obj_dereference (string); if (column_width >= max_width) { column_width = max_width; } else { // calculate max width of listview subitems (only for details view) if (is_tableview) { for (INT j = 0; j < item_count; j++) { // check for number column if ((i == 0) && (listview_id == IDC_LOG)) { text_width = _r_dc_getdpi (50, dpi_value); } else { string = _r_listview_getitemtext (hwnd, listview_id, j, i); if (!string) continue; text_width = _r_dc_getfontwidth (hdc_listview, &string->sr, NULL) + spacing; _r_obj_dereference (string); } // do not continue reaching higher and higher values for performance reason! if (text_width >= max_width) { column_width = max_width; break; } if (text_width > column_width) column_width = text_width; } } } _r_listview_setcolumn (hwnd, listview_id, i, NULL, column_width); calculated_width += column_width; } // set general column width _r_listview_setcolumn (hwnd, listview_id, column_general_id, NULL, max (total_width - calculated_width, max_width)); CleanupExit: if (hdc_listview) ReleaseDC (hlistview, hdc_listview); if (hdc_header) ReleaseDC (header, hdc_header); } VOID _app_listview_setfont ( _In_ HWND hwnd, _In_ INT listview_id ) { if (config.hfont) _r_ctrl_setfont (hwnd, listview_id, config.hfont); } VOID _app_listview_setview ( _In_ HWND hwnd, _In_ INT listview_id ) { HIMAGELIST himg = NULL; LONG view_type; LONG icons_size; BOOLEAN is_mainview; is_mainview = (listview_id >= IDC_APPS_PROFILE) && (listview_id <= IDC_RULES_CUSTOM); if (is_mainview) { view_type = _r_calc_clamp (_r_config_getlong (L"ViewType", LV_VIEW_DETAILS, NULL), LV_VIEW_ICON, LV_VIEW_MAX); } else { view_type = LV_VIEW_DETAILS; } if (is_mainview) { icons_size = _r_calc_clamp (_r_config_getlong (L"IconSize", SHIL_SMALL, NULL), SHIL_LARGE, SHIL_LAST); } else { icons_size = SHIL_SMALL; } if ((listview_id >= IDC_RULES_BLOCKLIST && listview_id <= IDC_RULES_CUSTOM) || listview_id == IDC_APP_RULES_ID) { if (icons_size == SHIL_SMALL || icons_size == SHIL_SYSSMALL) { himg = config.himg_rules_small; } else { himg = config.himg_rules_large; } } else { _r_imagelist_getsystem (icons_size, &himg); } if (himg) _r_listview_setimagelist (hwnd, listview_id, himg); _r_listview_setview (hwnd, listview_id, view_type); } INT CALLBACK _app_listview_compare_callback ( _In_ LPARAM lparam1, _In_ LPARAM lparam2, _In_ LPARAM lparam ) { PR_STRING item_text_1; PR_STRING item_text_2; PITEM_LOG ptr_log1; PITEM_LOG ptr_log2; WCHAR section_name[128]; HWND hwnd; LONG64 timestamp1 = 0; LONG64 timestamp2 = 0; ULONG context1; ULONG context2; LONG column_id; INT listview_id; INT result = 0; INT item_id1; INT item_id2; BOOLEAN is_success1; BOOLEAN is_success2; BOOLEAN is_checked1; BOOLEAN is_checked2; BOOLEAN is_descend; hwnd = GetParent ((HWND)lparam); if (!hwnd) return 0; listview_id = GetDlgCtrlID ((HWND)lparam); if (!listview_id) return 0; item_id1 = (INT)(INT_PTR)lparam1; item_id2 = (INT)(INT_PTR)lparam2; _r_str_printf (section_name, RTL_NUMBER_OF (section_name), L"listview\\%04" TEXT (PRIX32), listview_id); column_id = _r_config_getlong (L"SortColumn", 0, section_name); is_descend = _r_config_getboolean (L"SortIsDescending", FALSE, section_name); if ((_r_listview_getstyle_ex (hwnd, listview_id) & LVS_EX_CHECKBOXES) != 0) { is_checked1 = _r_listview_isitemchecked (hwnd, listview_id, item_id1); is_checked2 = _r_listview_isitemchecked (hwnd, listview_id, item_id2); if (is_checked1 != is_checked2) { if (is_checked1 && !is_checked2) { result = is_descend ? 1 : -1; } else if (!is_checked1 && is_checked2) { result = is_descend ? -1 : 1; } } } context1 = (ULONG)_app_listview_getitemcontext (hwnd, listview_id, item_id1); context2 = (ULONG)_app_listview_getitemcontext (hwnd, listview_id, item_id2); if (!result) { // timestamp sorting if ((listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_APPS_UWP) && column_id == 1) { is_success1 = _app_getappinfobyhash (context1, INFO_TIMESTAMP, ×tamp1, sizeof (LONG64)); is_success2 = _app_getappinfobyhash (context2, INFO_TIMESTAMP, ×tamp2, sizeof (LONG64)); if (is_success1 && is_success2) { if (timestamp1 < timestamp2) { result = -1; } else if (timestamp1 > timestamp2) { result = 1; } } } else if (listview_id == IDC_LOG && column_id == 1) { ptr_log1 = _app_getlogitem (context1); ptr_log2 = _app_getlogitem (context2); if (ptr_log1 && ptr_log2) { if (ptr_log1->timestamp < ptr_log2->timestamp) { result = -1; } else if (ptr_log1->timestamp > ptr_log2->timestamp) { result = 1; } } if (ptr_log1) _r_obj_dereference (ptr_log1); if (ptr_log2) _r_obj_dereference (ptr_log2); } } if (!result) { item_text_1 = _r_listview_getitemtext (hwnd, listview_id, item_id1, column_id); item_text_2 = _r_listview_getitemtext (hwnd, listview_id, item_id2, column_id); if (item_text_1 && item_text_2) result = _r_str_compare_logical (item_text_1->buffer, item_text_2->buffer); if (item_text_1) _r_obj_dereference (item_text_1); if (item_text_2) _r_obj_dereference (item_text_2); } return is_descend ? -result : result; } VOID _app_listview_sort ( _In_ HWND hwnd, _In_ INT listview_id, _In_ LONG column_id, _In_ BOOLEAN is_notifycode ) { WCHAR config_name[128]; HWND hlistview; INT column_count; BOOLEAN is_descend; hlistview = GetDlgItem (hwnd, listview_id); if (!hlistview) return; if ((GetWindowLongPtrW (hlistview, GWL_STYLE) & (LVS_NOSORTHEADER | LVS_OWNERDATA)) != 0) return; column_count = _r_listview_getcolumncount (hwnd, listview_id); if (!column_count) return; _r_str_printf (config_name, RTL_NUMBER_OF (config_name), L"listview\\%04" TEXT (PRIX32), listview_id); is_descend = _r_config_getboolean (L"SortIsDescending", FALSE, config_name); if (is_notifycode) is_descend = !is_descend; if (column_id == INT_ERROR) column_id = _r_config_getlong (L"SortColumn", 0, config_name); column_id = _r_calc_clamp (column_id, 0, column_count - 1); // set range if (is_notifycode) { _r_config_setboolean (L"SortIsDescending", is_descend, config_name); _r_config_setlong (L"SortColumn", column_id, config_name); } for (INT i = 0; i < column_count; i++) _r_listview_setcolumnsortindex (hwnd, listview_id, i, 0); _r_listview_setcolumnsortindex (hwnd, listview_id, column_id, is_descend ? -1 : 1); _r_listview_sort (hwnd, listview_id, &_app_listview_compare_callback, (WPARAM)hlistview); } ================================================ FILE: src/listview.h ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #pragma once typedef struct _ITEM_LISTVIEW_CONTEXT { ULONG_PTR id_code; struct { ULONG is_hidden : 1; ULONG spare_bits : 31; } DUMMYSTRUCTNAME; } ITEM_LISTVIEW_CONTEXT, *PITEM_LISTVIEW_CONTEXT; #define PR_SETITEM_REDRAW 0x0001 #define PR_SETITEM_UPDATE 0x0002 #define PR_UPDATE_TYPE 0x0001 #define PR_UPDATE_FORCE 0x0002 #define PR_UPDATE_NOREFRESH 0x0004 #define PR_UPDATE_NOSORT 0x0008 #define PR_UPDATE_NORESIZE 0x0010 #define PR_UPDATE_NOREDRAW 0x0020 #define PR_UPDATE_NOSETVIEW 0x0040 _Ret_maybenull_ PITEM_TAB_CONTEXT _app_listview_getcontext ( _In_ HWND hwnd, _In_ INT tab_id ); _Success_ (return != 0) INT _app_listview_getbytype ( _In_ ENUM_TYPE_DATA type ); VOID _app_listview_additems ( _In_ HWND hwnd ); VOID _app_listview_clearitems ( _In_ HWND hwnd ); VOID _app_listview_addappitem ( _In_ HWND hwnd, _In_ PITEM_APP ptr_app ); VOID _app_listview_addruleitem ( _In_ HWND hwnd, _In_ PITEM_RULE ptr_rule, _In_ ULONG_PTR rule_idx, _In_ BOOLEAN is_forapp ); VOID _app_listview_addnetworkitem ( _In_ HWND hwnd, _In_ ULONG network_hash ); VOID _app_listview_addlogitem ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log, _In_ ULONG log_hash ); BOOLEAN _app_listview_islocked ( _In_ HWND hwnd, _In_ INT ctrl_id ); VOID _app_listview_lock ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ BOOLEAN is_lock ); LONG_PTR _app_listview_createcontext ( _In_ ULONG_PTR id_code ); VOID _app_listview_destroycontext ( _In_ PITEM_LISTVIEW_CONTEXT context ); ULONG_PTR _app_listview_getcontextcode ( _In_ LONG_PTR lparam ); _Success_ (return != 0) ULONG _app_listview_getappcontext ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id ); ULONG_PTR _app_listview_getitemcontext ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id ); BOOLEAN _app_listview_isitemhidden ( _In_ LPARAM lparam ); _Success_ (return != INT_ERROR) INT _app_listview_finditem ( _In_ HWND hwnd, _In_ INT listview_id, _In_ ULONG_PTR id_code ); VOID _app_listview_removeitem ( _In_ HWND hwnd, _In_ ULONG_PTR id_code, _In_ ENUM_TYPE_DATA type ); VOID _app_listview_showitemby_id ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _In_ INT scroll_pos ); VOID _app_listview_showitemby_param ( _In_ HWND hwnd, _In_ ULONG_PTR lparam, _In_ BOOLEAN is_app ); VOID _app_listview_updateby_id ( _In_ HWND hwnd, _In_ INT lparam, _In_ ULONG flags ); VOID _app_listview_updateby_param ( _In_ HWND hwnd, _In_ ULONG_PTR lparam, _In_ ULONG flags, _In_ BOOLEAN is_app ); VOID _app_listview_updateitemby_param ( _In_ HWND hwnd, _In_ ULONG_PTR lparam, _In_ BOOLEAN is_app ); VOID _app_listview_updateitemby_id ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id ); VOID _app_listview_loadfont ( _In_ LONG dpi_value, _In_ BOOLEAN is_forced ); VOID _app_listview_refreshgroups ( _In_ HWND hwnd, _In_ INT listview_id ); VOID _app_listview_resize ( _In_ HWND hwnd, _In_ INT listview_id, _In_ BOOLEAN is_forced ); VOID _app_listview_setfont ( _In_ HWND hwnd, _In_ INT listview_id ); VOID _app_listview_setview ( _In_ HWND hwnd, _In_ INT listview_id ); INT CALLBACK _app_listview_compare_callback ( _In_ LPARAM lparam1, _In_ LPARAM lparam2, _In_ LPARAM lparam ); VOID _app_listview_sort ( _In_ HWND hwnd, _In_ INT listview_id, _In_ LONG column_id, _In_ BOOLEAN is_notifycode ); ================================================ FILE: src/log.c ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #include "global.h" VOID _app_loginit ( _In_ BOOLEAN is_install ) { HANDLE current_handle; HANDLE new_handle; PR_STRING log_path; NTSTATUS status; current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hlogfile, NULL, config.hlogfile); // reset log handle if (current_handle) NtClose (current_handle); if (!is_install || !_r_config_getboolean (L"IsLogEnabled", FALSE, NULL)) return; // already closed or not enabled log_path = _app_getlogpath (); if (!log_path) return; status = _r_fs_createfile ( &log_path->sr, FILE_OPEN_IF, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, FILE_ATTRIBUTE_NORMAL, 0, FALSE, NULL, &new_handle ); if (NT_SUCCESS (status)) { _app_loginitfile (new_handle); current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hlogfile, new_handle, NULL); if (current_handle) NtClose (new_handle); } _r_obj_dereference (log_path); } VOID _app_loginitfile ( _In_ HANDLE hfile ) { BYTE bom[] = {0xFF, 0xFE}; LARGE_INTEGER file_size; _r_fs_getsize (NULL, hfile, &file_size); if (!file_size.QuadPart) { // write utf-16 le byte order mask _r_fs_writefile (hfile, bom, sizeof (bom)); // write csv header _r_fs_writefile (hfile, SZ_LOG_TITLE, (ULONG)(_r_str_getlength (SZ_LOG_TITLE) * sizeof (WCHAR))); } else { // move to eof _r_fs_setpos (hfile, &file_size); } } ULONG _app_getloghash ( _In_ PITEM_LOG ptr_log ) { PR_STRING string; ULONG log_hash; string = _r_format_string ( L"%" TEXT (PRIu8) L"_%" TEXT (PR_ULONG) L"_%" TEXT (PRIu8) L"_%" \ TEXT (PRIu8) L"_%" TEXT (PRIu16) L"_%" TEXT (PRIu16) L"_%s_%s_IJAHudm4*^(uaokUH_!&%#!", ptr_log->af, ptr_log->app_hash, ptr_log->protocol, ptr_log->direction, ptr_log->local_port, ptr_log->remote_port, _r_obj_getstring (ptr_log->local_addr_str), _r_obj_getstring (ptr_log->remote_addr_str) ); log_hash = _r_str_gethash (&string->sr, TRUE); _r_obj_dereference (string); return log_hash; } _Ret_maybenull_ PR_STRING _app_getlogpath () { PR_STRING path; path = _r_config_getstringexpand (L"LogPath", LOG_PATH_DEFAULT, NULL); return path; } _Ret_maybenull_ PR_STRING _app_getlogviewer () { R_STRINGREF sr; PR_STRING path; path = _r_config_getstringexpand (L"LogViewer", LOG_VIEWER_DEFAULT, NULL); if (!path || !_r_fs_isexists (&path->sr)) { if (path) _r_obj_dereference (path); _r_obj_initializestringref (&sr, LOG_VIEWER_DEFAULT); _r_str_environmentexpandstring (NULL, &sr, &path); } return path; } BOOLEAN _app_islogfound ( _In_ ULONG log_hash ) { BOOLEAN is_found; _r_queuedlock_acquireshared (&lock_loglist); is_found = (_r_obj_findhashtable (log_table, log_hash) != NULL); _r_queuedlock_releaseshared (&lock_loglist); return is_found; } BOOLEAN _app_logislimitreached ( _In_ HANDLE hfile ) { LONG64 file_size; LONG64 limit; limit = _r_config_getlong64 (L"LogSizeLimitKb", LOG_SIZE_LIMIT_DEFAULT, NULL); if (!limit) return FALSE; _r_fs_getsize2 (NULL, hfile, &file_size); return (file_size >= (_r_calc_kilobytes2bytes64 (limit))); } VOID _app_logclear ( _In_opt_ HANDLE hfile ) { PR_STRING log_path; if (hfile) { _r_fs_clearfile (hfile); _app_loginitfile (hfile); } log_path = _app_getlogpath (); if (!log_path) return; _r_fs_deletefile (&log_path->sr, NULL); _r_obj_dereference (log_path); } VOID _app_logclear_ui ( _In_ HWND hwnd ) { _InterlockedExchange (&config.log_id, 0); _r_listview_deleteallitems (hwnd, IDC_LOG); _app_listview_resize (hwnd, IDC_LOG, FALSE); _r_queuedlock_acquireexclusive (&lock_loglist); _r_obj_clearhashtable (log_table); _r_queuedlock_releaseexclusive (&lock_loglist); } VOID _app_logwrite ( _In_ PITEM_LOG ptr_log ) { PR_STRING remote_port_string; PR_STRING local_port_string; PR_STRING direction_string; PR_STRING date_string; PR_STRING path = NULL; PR_STRING buffer; PITEM_APP ptr_app; HANDLE current_handle; current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hlogfile, NULL, NULL); if (!current_handle) return; // parse path ptr_app = _app_getappitem (ptr_log->app_hash); if (ptr_app) { path = _app_getapppath (ptr_app, _r_config_getboolean (L"IsShortPath", TRUE, NULL)); _r_obj_dereference (ptr_app); } date_string = _r_format_unixtime (ptr_log->timestamp, FDTF_SHORTDATE | FDTF_LONGTIME); local_port_string = _app_formatport (ptr_log->local_port, ptr_log->protocol); remote_port_string = _app_formatport (ptr_log->remote_port, ptr_log->protocol); direction_string = _app_db_getdirectionname (ptr_log->direction, ptr_log->is_loopback, FALSE); buffer = _r_format_string ( SZ_LOG_BODY, _r_obj_getstringordefault (date_string, _r_locale_getstring (IDS_STATUS_EMPTY)), _r_obj_getstringordefault (ptr_log->username, _r_locale_getstring (IDS_STATUS_EMPTY)), _r_obj_getstringordefault (path, _r_locale_getstring (IDS_STATUS_EMPTY)), _r_obj_getstringordefault (ptr_log->local_addr_str, _r_locale_getstring (IDS_STATUS_EMPTY)), local_port_string->buffer, _r_obj_getstringordefault (ptr_log->remote_addr_str, _r_locale_getstring (IDS_STATUS_EMPTY)), remote_port_string->buffer, _r_obj_getstringordefault (ptr_log->protocol_str, SZ_DIRECTION_ANY), _r_obj_getstringordefault (ptr_log->layer_name, _r_locale_getstring (IDS_STATUS_EMPTY)), _r_obj_getstringordefault (ptr_log->filter_name, _r_locale_getstring (IDS_STATUS_EMPTY)), ptr_log->filter_id, _r_obj_getstringordefault (direction_string, _r_locale_getstring (IDS_STATUS_EMPTY)), (ptr_log->is_allow ? SZ_STATE_ALLOW : SZ_STATE_BLOCK) ); if (_app_logislimitreached (current_handle)) _app_logclear (current_handle); _r_fs_writefile (current_handle, buffer->buffer, (ULONG)buffer->length); if (date_string) _r_obj_dereference (date_string); if (direction_string) _r_obj_dereference (direction_string); if (path) _r_obj_dereference (path); _r_obj_dereference (local_port_string); _r_obj_dereference (remote_port_string); _r_obj_dereference (buffer); } VOID _app_logwrite_ui ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log ) { ULONG_PTR table_size; ULONG log_hash; ULONG hash_code; INT item_id; log_hash = _app_getloghash (ptr_log); if (!log_hash) return; // log was already in list, so skip it... if (_app_islogfound (log_hash)) return; _r_queuedlock_acquireshared (&lock_loglist); table_size = _r_obj_gethashtablesize (log_table); _r_queuedlock_releaseshared (&lock_loglist); if (table_size >= MAP_CACHE_MAX) { item_id = _r_listview_getitemcount (hwnd, IDC_LOG) - 1; hash_code = (ULONG)_app_listview_getitemcontext (hwnd, IDC_LOG, item_id); _r_listview_deleteitem (hwnd, IDC_LOG, item_id); if (hash_code) { _r_queuedlock_acquireexclusive (&lock_loglist); _r_obj_removehashtableitem (log_table, hash_code); _r_queuedlock_releaseexclusive (&lock_loglist); } } _r_queuedlock_acquireexclusive (&lock_loglist); _r_obj_addhashtablepointer (log_table, log_hash, _r_obj_reference (ptr_log)); _r_queuedlock_releaseexclusive (&lock_loglist); _app_listview_addlogitem (hwnd, ptr_log, log_hash); _app_queue_resolver (hwnd, IDC_LOG, log_hash, ptr_log); _app_listview_updateby_id (hwnd, IDC_LOG, 0); } VOID _wfp_logsubscribe ( _In_opt_ HWND hwnd, _In_ HANDLE engine_handle ) { static R_INITONCE init_once = PR_INITONCE_INIT; static FWPMNES4 _FwpmNetEventSubscribe4 = NULL; static FWPMNES3 _FwpmNetEventSubscribe3 = NULL; static FWPMNES2 _FwpmNetEventSubscribe2 = NULL; static FWPMNES1 _FwpmNetEventSubscribe1 = NULL; FWPM_NET_EVENT_ENUM_TEMPLATE0 enum_template = {0}; FWPM_NET_EVENT_SUBSCRIPTION0 subscription = {0}; HANDLE new_handle = NULL; HANDLE current_handle; PVOID hfwpuclnt; BOOLEAN is_success = FALSE; NTSTATUS status; current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hnetevent, NULL, NULL); if (current_handle) return; // already subscribed if (_r_initonce_begin (&init_once)) { status = _r_sys_loadlibrary2 (L"fwpuclnt.dll", 0, &hfwpuclnt); if (NT_SUCCESS (status)) { _FwpmNetEventSubscribe4 = _r_sys_getprocaddress (hfwpuclnt, "FwpmNetEventSubscribe4", 0); _FwpmNetEventSubscribe3 = _r_sys_getprocaddress (hfwpuclnt, "FwpmNetEventSubscribe3", 0); _FwpmNetEventSubscribe2 = _r_sys_getprocaddress (hfwpuclnt, "FwpmNetEventSubscribe2", 0); _FwpmNetEventSubscribe1 = _r_sys_getprocaddress (hfwpuclnt, "FwpmNetEventSubscribe1", 0); _r_sys_freelibrary (hfwpuclnt); } else { if (hwnd) { _r_show_errormessage (hwnd, L"Could not load \"fwpuclnt.dll\" library!", status, NULL, ET_NATIVE); } else { _r_log (LOG_LEVEL_WARNING, NULL, L"_r_sys_loadlibrary", status, L"fwpuclnt.dll"); } } _r_initonce_end (&init_once); } subscription.enumTemplate = &enum_template; subscription.sessionKey = config.session_key; // win10rs3+ if (!is_success && _FwpmNetEventSubscribe4) { status = _FwpmNetEventSubscribe4 (engine_handle, &subscription, &_wfp_logcallback4, NULL, &new_handle); is_success = (status == STATUS_SUCCESS); } // win10rs1+ if (!is_success && _FwpmNetEventSubscribe3) { status = _FwpmNetEventSubscribe3 (engine_handle, &subscription, &_wfp_logcallback3, NULL, &new_handle); is_success = (status == STATUS_SUCCESS); } // win10rs1+ if (!is_success && _FwpmNetEventSubscribe2) { status = _FwpmNetEventSubscribe2 (engine_handle, &subscription, &_wfp_logcallback2, NULL, &new_handle); is_success = (status == STATUS_SUCCESS); } // win8+ if (!is_success && _FwpmNetEventSubscribe1) { status = _FwpmNetEventSubscribe1 (engine_handle, &subscription, &_wfp_logcallback1, NULL, &new_handle); is_success = (status == STATUS_SUCCESS); } // win7+ if (!is_success) { status = FwpmNetEventSubscribe0 (engine_handle, &subscription, &_wfp_logcallback0, NULL, &new_handle); is_success = (status == STATUS_SUCCESS); } if (!is_success) { if (hwnd && status != ERROR_PATH_NOT_FOUND) { _r_show_errormessage (hwnd, L"Log subscribe failed. Try again later!", status, NULL, ET_WINDOWS); } else { _r_log (LOG_LEVEL_WARNING, NULL, L"FwpmNetEventSubscribe", status, NULL); } } _r_toolbar_enablebutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLENOTIFICATIONS_CHK, is_success); _r_toolbar_enablebutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLELOG_CHK, is_success); _r_toolbar_enablebutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLEUILOG_CHK, is_success); current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hnetevent, new_handle, NULL); if (current_handle) { if (new_handle) FwpmNetEventUnsubscribe0 (engine_handle, new_handle); } // initialize log file if (_r_config_getboolean (L"IsLogEnabled", FALSE, NULL)) _app_loginit (TRUE); } VOID _wfp_logunsubscribe ( _In_ HANDLE engine_handle ) { HANDLE current_handle; ULONG status; _app_loginit (FALSE); // destroy log file handle if present current_handle = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hnetevent, NULL, config.hnetevent); if (!current_handle) return; status = FwpmNetEventUnsubscribe0 (engine_handle, current_handle); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_WARNING, NULL, L"FwpmNetEventUnsubscribe", status, NULL); } VOID _wfp_logsetoption ( _In_ HANDLE engine_handle ) { FWP_VALUE0 val; UINT32 mask = 0; ULONG status; // configure dropped packets logging (win8+) if (!_r_sys_isosversiongreaterorequal (WINDOWS_8)) return; // add allowed connections monitor if (!_r_config_getboolean (L"IsExcludeClassifyAllow", TRUE, NULL)) mask |= FWPM_NET_EVENT_KEYWORD_CLASSIFY_ALLOW; // add inbound multicast and broadcast connections monitor if (!_r_config_getboolean (L"IsExcludeInbound", FALSE, NULL)) mask |= FWPM_NET_EVENT_KEYWORD_INBOUND_MCAST | FWPM_NET_EVENT_KEYWORD_INBOUND_BCAST; // add port scanning drop connections monitor (19H1+) if (_r_sys_isosversiongreaterorequal (WINDOWS_10_19H1)) { if (!_r_config_getboolean (L"IsExcludePortScanningDrop", FALSE, NULL)) mask |= FWPM_NET_EVENT_KEYWORD_PORT_SCANNING_DROP; } // the filter engine will collect wfp network events that match any supplied key words RtlZeroMemory (&val, sizeof (FWP_VALUE0)); val.type = FWP_UINT32; val.uint32 = mask; status = FwpmEngineSetOption0 (engine_handle, FWPM_ENGINE_NET_EVENT_MATCH_ANY_KEYWORDS, &val); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_WARNING, NULL, L"FwpmEngineSetOption0", status, L"FWPM_ENGINE_NET_EVENT_MATCH_ANY_KEYWORDS"); // enables the connection monitoring feature and starts logging creation and deletion events (and notifying any subscribers) RtlZeroMemory (&val, sizeof (FWP_VALUE0)); val.type = FWP_UINT32; val.uint32 = !_r_config_getboolean (L"IsExcludeIPSecConnections", FALSE, NULL); status = FwpmEngineSetOption0 (engine_handle, FWPM_ENGINE_MONITOR_IPSEC_CONNECTIONS, &val); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_WARNING, NULL, L"FwpmEngineSetOption0", status, L"FWPM_ENGINE_MONITOR_IPSEC_CONNECTIONS"); } VOID CALLBACK _wfp_logcallback ( _In_ PITEM_LOG_CALLBACK log ) { HANDLE engine_handle; PITEM_LOG ptr_log; GUID layer_guid; PR_STRING filter_name = NULL; PR_STRING sid_string = NULL; PR_STRING resolved_path; PR_STRING layer_name; PR_STRING path; FWPM_FILTER0 *filter_ptr; FWPM_LAYER0 *layer_ptr; UINT8 filter_weight = 0; BOOLEAN is_myprovider = FALSE; NTSTATUS status; if (!log->filter_id || !log->layer_id) return; if (log->is_allow && _r_config_getboolean (L"IsExcludeClassifyAllow", TRUE, NULL)) return; engine_handle = _wfp_getenginehandle (); // do not parse when tcp connection has been established, or when non-tcp traffic has been authorized if (FwpmLayerGetById0 (engine_handle, log->layer_id, &layer_ptr) != ERROR_SUCCESS || !layer_ptr) return; if (IsEqualGUID (&layer_ptr->layerKey, &FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4) || IsEqualGUID (&layer_ptr->layerKey, &FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6)) { FwpmFreeMemory0 ((PVOID_PTR)&layer_ptr); return; } if (IsEqualGUID (&layer_ptr->layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4) || IsEqualGUID (&layer_ptr->layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6)) log->direction = FWP_DIRECTION_INBOUND; // HACK!!! (issue #581) RtlCopyMemory (&layer_guid, &layer_ptr->layerKey, sizeof (GUID)); FwpmFreeMemory0 ((PVOID_PTR)&layer_ptr); // get filter information if (FwpmFilterGetById0 (engine_handle, log->filter_id, &filter_ptr) != ERROR_SUCCESS || !filter_ptr) return; layer_name = _wfp_getlayername (&layer_guid); if (!_r_str_isempty (filter_ptr->displayData.description)) { filter_name = _r_obj_createstring (filter_ptr->displayData.description); } else if (!_r_str_isempty (filter_ptr->displayData.name)) { filter_name = _r_obj_createstring (filter_ptr->displayData.name); } if (filter_ptr->weight.type == FWP_UINT8) filter_weight = filter_ptr->weight.uint8; if (filter_ptr->providerKey) { if (IsEqualGUID (filter_ptr->providerKey, &GUID_WfpProvider)) is_myprovider = TRUE; } FwpmFreeMemory0 ((PVOID_PTR)&filter_ptr); // allocate log object ptr_log = _r_obj_allocate (sizeof (ITEM_LOG), &_app_dereferencelog); // copy date and time ptr_log->timestamp = _r_unixtime_from_filetime (&log->timestamp); // check token for null (not an appcontainer) (HACK!!!) if ((log->flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) == FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET && log->package_id) { if (RtlEqualSid (log->package_id, &SeNobodySid)) { log->flags &= ~(FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET); log->package_id = NULL; } } // get package id (win8+) if ((log->flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) == FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET && log->package_id) { status = _r_str_fromsid (log->package_id, &sid_string); if (NT_SUCCESS (status)) { if (!_app_package_isnotexists (sid_string)) _r_obj_clearreference ((PVOID_PTR)&sid_string); } } // copy converted nt device path into win32 if ((log->flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) == FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET && sid_string) { _r_obj_swapreference ((PVOID_PTR)&ptr_log->path, sid_string); ptr_log->app_hash = _r_str_gethash (&ptr_log->path->sr, TRUE); } else if ((log->flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) == FWPM_NET_EVENT_FLAG_APP_ID_SET && log->app_id) { path = _r_obj_createstring ((LPCWSTR)(log->app_id)); resolved_path = _r_path_dospathfromnt (&path->sr); if (resolved_path) _r_obj_movereference ((PVOID_PTR)&path, resolved_path); if (path) { _r_obj_movereference ((PVOID_PTR)&ptr_log->path, path); ptr_log->app_hash = _r_str_gethash (&ptr_log->path->sr, TRUE); } } else { ptr_log->app_hash = 0; } // get username information if ((log->flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) == FWPM_NET_EVENT_FLAG_USER_ID_SET && log->user_id) _r_sys_getusername (log->user_id, TRUE, &ptr_log->username); // destination if ((log->flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) == FWPM_NET_EVENT_FLAG_IP_VERSION_SET) { if (log->version == FWP_IP_VERSION_V4) { ptr_log->af = AF_INET; // local address if ((log->flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) ptr_log->local_addr.S_un.S_addr = _r_byteswap_ulong ((ULONG)log->local_addr4); // remote address if ((log->flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) ptr_log->remote_addr.S_un.S_addr = _r_byteswap_ulong ((ULONG)log->remote_addr4); } else if (log->version == FWP_IP_VERSION_V6) { ptr_log->af = AF_INET6; // remote address if ((log->flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET && log->remote_addr6) RtlCopyMemory (ptr_log->remote_addr6.u.Byte, log->remote_addr6->byteArray16, FWP_V6_ADDR_SIZE); // local address if ((log->flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET && log->local_addr6) RtlCopyMemory (ptr_log->local_addr6.u.Byte, log->local_addr6->byteArray16, FWP_V6_ADDR_SIZE); } } // ports if ((log->flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) == FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) ptr_log->local_port = log->local_port; if ((log->flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) == FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) ptr_log->remote_port = log->remote_port; // protocol if ((log->flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) == FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) { ptr_log->protocol = log->protocol; ptr_log->protocol_str = _r_obj_createstring (_app_db_getprotoname (ptr_log->protocol, ptr_log->af)); } // indicates FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW state ptr_log->is_allow = log->is_allow; // indicates whether the packet originated from (or was heading to) the loopback adapter ptr_log->is_loopback = log->is_loopback; // set filter information ptr_log->filter_id = log->filter_id; ptr_log->direction = log->direction; ptr_log->is_myprovider = is_myprovider; ptr_log->filter_name = filter_name; ptr_log->layer_name = layer_name; ptr_log->is_blocklist = (filter_weight == FW_WEIGHT_RULE_BLOCKLIST); ptr_log->is_system = (filter_weight == FW_WEIGHT_HIGHEST) || (filter_weight == FW_WEIGHT_HIGHEST_IMPORTANT); ptr_log->is_custom = (filter_weight == FW_WEIGHT_RULE_USER) || (filter_weight == FW_WEIGHT_RULE_USER_BLOCK); _r_workqueue_queueitem (&log_queue, &_app_logthread, ptr_log); if (sid_string) _r_obj_dereference (sid_string); } FORCEINLINE BOOLEAN log_struct_to_f ( _Out_ PITEM_LOG_CALLBACK log, _In_ ULONG version, _In_ LPCVOID event_data ) { RtlSecureZeroMemory (log, sizeof (ITEM_LOG_CALLBACK)); switch (version) { case WINDOWS_10_RS3: { const FWPM_NET_EVENT5 *evt = event_data; if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && evt->classifyDrop) { log->layer_id = evt->classifyDrop->layerId; log->filter_id = evt->classifyDrop->filterId; log->direction = evt->classifyDrop->msFwpDirection; log->is_loopback = !!evt->classifyDrop->isLoopback; } else if (evt->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && evt->ipsecDrop) { log->layer_id = evt->ipsecDrop->layerId; log->filter_id = evt->ipsecDrop->filterId; log->direction = evt->ipsecDrop->direction; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && evt->classifyAllow) { log->layer_id = evt->classifyAllow->layerId; log->filter_id = evt->classifyAllow->filterId; log->direction = evt->classifyAllow->msFwpDirection; log->is_loopback = !!evt->classifyAllow->isLoopback; log->is_allow = TRUE; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && evt->classifyDropMac) { log->layer_id = evt->classifyDropMac->layerId; log->filter_id = evt->classifyDropMac->filterId; log->direction = evt->classifyDropMac->msFwpDirection; log->is_loopback = !!evt->classifyDropMac->isLoopback; } else { return FALSE; } // indicates the direction of the packet transmission and set valid directions switch (log->direction) { case FWP_DIRECTION_IN: case FWP_DIRECTION_INBOUND: { log->direction = FWP_DIRECTION_INBOUND; break; } case FWP_DIRECTION_OUT: case FWP_DIRECTION_OUTBOUND: { log->direction = FWP_DIRECTION_OUTBOUND; break; } default: { return FALSE; } } log->flags = evt->header.flags; RtlCopyMemory (&log->timestamp, &evt->header.timeStamp, sizeof (FILETIME)); if ((evt->header.flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) == FWPM_NET_EVENT_FLAG_APP_ID_SET) log->app_id = evt->header.appId.data; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) == FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) log->package_id = evt->header.packageSid; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) == FWPM_NET_EVENT_FLAG_USER_ID_SET) log->user_id = evt->header.userId; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) == FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) log->protocol = evt->header.ipProtocol; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) == FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) log->local_port = evt->header.localPort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) == FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) log->remote_port = evt->header.remotePort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) == FWPM_NET_EVENT_FLAG_IP_VERSION_SET) { log->version = evt->header.ipVersion; if (evt->header.ipVersion == FWP_IP_VERSION_V4) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr4 = evt->header.localAddrV4; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr4 = evt->header.remoteAddrV4; } else if (evt->header.ipVersion == FWP_IP_VERSION_V6) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr6 = &evt->header.localAddrV6; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr6 = &evt->header.remoteAddrV6; } } else { log->version = FWP_IP_VERSION_NONE; } break; } case WINDOWS_10_RS1: { const FWPM_NET_EVENT4 *evt = (const FWPM_NET_EVENT4*)event_data; if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && evt->classifyDrop) { log->layer_id = evt->classifyDrop->layerId; log->filter_id = evt->classifyDrop->filterId; log->direction = evt->classifyDrop->msFwpDirection; log->is_loopback = !!evt->classifyDrop->isLoopback; } else if (evt->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && evt->ipsecDrop) { log->layer_id = evt->ipsecDrop->layerId; log->filter_id = evt->ipsecDrop->filterId; log->direction = evt->ipsecDrop->direction; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && evt->classifyAllow) { log->layer_id = evt->classifyAllow->layerId; log->filter_id = evt->classifyAllow->filterId; log->direction = evt->classifyAllow->msFwpDirection; log->is_loopback = !!evt->classifyAllow->isLoopback; log->is_allow = TRUE; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && evt->classifyDropMac) { log->layer_id = evt->classifyDropMac->layerId; log->filter_id = evt->classifyDropMac->filterId; log->direction = evt->classifyDropMac->msFwpDirection; log->is_loopback = !!evt->classifyDropMac->isLoopback; } else { return FALSE; } // indicates the direction of the packet transmission and set valid directions switch (log->direction) { case FWP_DIRECTION_IN: case FWP_DIRECTION_INBOUND: { log->direction = FWP_DIRECTION_INBOUND; break; } case FWP_DIRECTION_OUT: case FWP_DIRECTION_OUTBOUND: { log->direction = FWP_DIRECTION_OUTBOUND; break; } default: { return FALSE; } } log->flags = evt->header.flags; RtlCopyMemory (&log->timestamp, &evt->header.timeStamp, sizeof (FILETIME)); if ((evt->header.flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) == FWPM_NET_EVENT_FLAG_APP_ID_SET) log->app_id = evt->header.appId.data; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) == FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) log->package_id = evt->header.packageSid; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) == FWPM_NET_EVENT_FLAG_USER_ID_SET) log->user_id = evt->header.userId; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) == FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) log->protocol = evt->header.ipProtocol; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) == FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) log->local_port = evt->header.localPort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) == FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) log->remote_port = evt->header.remotePort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) == FWPM_NET_EVENT_FLAG_IP_VERSION_SET) { log->version = evt->header.ipVersion; if (evt->header.ipVersion == FWP_IP_VERSION_V4) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr4 = evt->header.localAddrV4; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr4 = evt->header.remoteAddrV4; } else if (evt->header.ipVersion == FWP_IP_VERSION_V6) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr6 = &evt->header.localAddrV6; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr6 = &evt->header.remoteAddrV6; } } else { log->version = FWP_IP_VERSION_NONE; } break; } case WINDOWS_10_RS2: { const FWPM_NET_EVENT3 *evt = event_data; if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && evt->classifyDrop) { log->layer_id = evt->classifyDrop->layerId; log->filter_id = evt->classifyDrop->filterId; log->direction = evt->classifyDrop->msFwpDirection; log->is_loopback = !!evt->classifyDrop->isLoopback; } else if (evt->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && evt->ipsecDrop) { log->layer_id = evt->ipsecDrop->layerId; log->filter_id = evt->ipsecDrop->filterId; log->direction = evt->ipsecDrop->direction; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && evt->classifyAllow) { log->layer_id = evt->classifyAllow->layerId; log->filter_id = evt->classifyAllow->filterId; log->direction = evt->classifyAllow->msFwpDirection; log->is_loopback = !!evt->classifyAllow->isLoopback; log->is_allow = TRUE; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && evt->classifyDropMac) { log->layer_id = evt->classifyDropMac->layerId; log->filter_id = evt->classifyDropMac->filterId; log->direction = evt->classifyDropMac->msFwpDirection; log->is_loopback = !!evt->classifyDropMac->isLoopback; } else { return FALSE; } // indicates the direction of the packet transmission and set valid directions switch (log->direction) { case FWP_DIRECTION_IN: case FWP_DIRECTION_INBOUND: { log->direction = FWP_DIRECTION_INBOUND; break; } case FWP_DIRECTION_OUT: case FWP_DIRECTION_OUTBOUND: { log->direction = FWP_DIRECTION_OUTBOUND; break; } default: { return FALSE; } } log->flags = evt->header.flags; RtlCopyMemory (&log->timestamp, &evt->header.timeStamp, sizeof (FILETIME)); if ((evt->header.flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) == FWPM_NET_EVENT_FLAG_APP_ID_SET) log->app_id = evt->header.appId.data; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) == FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) log->package_id = evt->header.packageSid; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) == FWPM_NET_EVENT_FLAG_USER_ID_SET) log->user_id = evt->header.userId; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) == FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) log->protocol = evt->header.ipProtocol; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) == FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) log->local_port = evt->header.localPort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) == FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) log->remote_port = evt->header.remotePort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) == FWPM_NET_EVENT_FLAG_IP_VERSION_SET) { log->version = evt->header.ipVersion; if (evt->header.ipVersion == FWP_IP_VERSION_V4) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr4 = evt->header.localAddrV4; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr4 = evt->header.remoteAddrV4; } else if (evt->header.ipVersion == FWP_IP_VERSION_V6) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr6 = &evt->header.localAddrV6; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr6 = &evt->header.remoteAddrV6; } } else { log->version = FWP_IP_VERSION_NONE; } break; } case WINDOWS_8: { const FWPM_NET_EVENT2 *evt = event_data; if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && evt->classifyDrop) { log->layer_id = evt->classifyDrop->layerId; log->filter_id = evt->classifyDrop->filterId; log->direction = evt->classifyDrop->msFwpDirection; log->is_loopback = !!evt->classifyDrop->isLoopback; } else if (evt->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && evt->ipsecDrop) { log->layer_id = evt->ipsecDrop->layerId; log->filter_id = evt->ipsecDrop->filterId; log->direction = evt->ipsecDrop->direction; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && evt->classifyAllow) { log->layer_id = evt->classifyAllow->layerId; log->filter_id = evt->classifyAllow->filterId; log->direction = evt->classifyAllow->msFwpDirection; log->is_loopback = !!evt->classifyAllow->isLoopback; log->is_allow = TRUE; } else if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && evt->classifyDropMac) { log->layer_id = evt->classifyDropMac->layerId; log->filter_id = evt->classifyDropMac->filterId; log->direction = evt->classifyDropMac->msFwpDirection; log->is_loopback = !!evt->classifyDropMac->isLoopback; } else { return FALSE; } // indicates the direction of the packet transmission and set valid directions switch (log->direction) { case FWP_DIRECTION_IN: case FWP_DIRECTION_INBOUND: { log->direction = FWP_DIRECTION_INBOUND; break; } case FWP_DIRECTION_OUT: case FWP_DIRECTION_OUTBOUND: { log->direction = FWP_DIRECTION_OUTBOUND; break; } default: { return FALSE; } } log->flags = evt->header.flags; RtlCopyMemory (&log->timestamp, &evt->header.timeStamp, sizeof (FILETIME)); if ((evt->header.flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) == FWPM_NET_EVENT_FLAG_APP_ID_SET) log->app_id = evt->header.appId.data; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) == FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) log->package_id = evt->header.packageSid; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) == FWPM_NET_EVENT_FLAG_USER_ID_SET) log->user_id = evt->header.userId; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) == FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) log->protocol = evt->header.ipProtocol; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) == FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) log->local_port = evt->header.localPort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) == FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) log->remote_port = evt->header.remotePort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) == FWPM_NET_EVENT_FLAG_IP_VERSION_SET) { log->version = evt->header.ipVersion; if (evt->header.ipVersion == FWP_IP_VERSION_V4) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr4 = evt->header.localAddrV4; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr4 = evt->header.remoteAddrV4; } else if (evt->header.ipVersion == FWP_IP_VERSION_V6) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr6 = &evt->header.localAddrV6; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr6 = &evt->header.remoteAddrV6; } } else { log->version = FWP_IP_VERSION_NONE; } break; } case WINDOWS_7: { const FWPM_NET_EVENT1 *evt = event_data; if (evt->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && evt->classifyDrop) { log->layer_id = evt->classifyDrop->layerId; log->filter_id = evt->classifyDrop->filterId; log->direction = evt->classifyDrop->msFwpDirection; log->is_loopback = !!evt->classifyDrop->isLoopback; } else if (evt->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && evt->ipsecDrop) { log->layer_id = evt->ipsecDrop->layerId; log->filter_id = evt->ipsecDrop->filterId; log->direction = evt->ipsecDrop->direction; } else { return FALSE; } // indicates the direction of the packet transmission and set valid directions switch (log->direction) { case FWP_DIRECTION_IN: case FWP_DIRECTION_INBOUND: { log->direction = FWP_DIRECTION_INBOUND; break; } case FWP_DIRECTION_OUT: case FWP_DIRECTION_OUTBOUND: { log->direction = FWP_DIRECTION_OUTBOUND; break; } default: { return FALSE; } } log->flags = evt->header.flags; RtlCopyMemory (&log->timestamp, &evt->header.timeStamp, sizeof (FILETIME)); if ((evt->header.flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) == FWPM_NET_EVENT_FLAG_APP_ID_SET) log->app_id = evt->header.appId.data; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) == FWPM_NET_EVENT_FLAG_USER_ID_SET) log->user_id = evt->header.userId; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) == FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) log->protocol = evt->header.ipProtocol; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) == FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) log->local_port = evt->header.localPort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) == FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) log->remote_port = evt->header.remotePort; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) == FWPM_NET_EVENT_FLAG_IP_VERSION_SET) { log->version = evt->header.ipVersion; if (evt->header.ipVersion == FWP_IP_VERSION_V4) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr4 = evt->header.localAddrV4; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr4 = evt->header.remoteAddrV4; } else if (evt->header.ipVersion == FWP_IP_VERSION_V6) { if ((evt->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) == FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) log->local_addr6 = &evt->header.localAddrV6; if ((evt->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) == FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) log->remote_addr6 = &evt->header.remoteAddrV6; } } else { log->version = FWP_IP_VERSION_NONE; } break; } default: { return FALSE; } } return TRUE; } // win7+ callback VOID CALLBACK _wfp_logcallback0 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT1* event_data ) { ITEM_LOG_CALLBACK log; if (log_struct_to_f (&log, WINDOWS_7, event_data)) _wfp_logcallback (&log); } // win8+ callback VOID CALLBACK _wfp_logcallback1 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT2* event_data ) { ITEM_LOG_CALLBACK log; if (log_struct_to_f (&log, WINDOWS_8, event_data)) _wfp_logcallback (&log); } // win10rs1+ callback VOID CALLBACK _wfp_logcallback2 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT3* event_data ) { ITEM_LOG_CALLBACK log; if (log_struct_to_f (&log, WINDOWS_10_RS1, event_data)) _wfp_logcallback (&log); } // win10rs1+ callback VOID CALLBACK _wfp_logcallback3 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT4* event_data ) { ITEM_LOG_CALLBACK log; if (log_struct_to_f (&log, WINDOWS_10_RS2, event_data)) _wfp_logcallback (&log); } // win10rs3+ callback VOID CALLBACK _wfp_logcallback4 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT5* event_data ) { ITEM_LOG_CALLBACK log; if (log_struct_to_f (&log, WINDOWS_10_RS3, event_data)) _wfp_logcallback (&log); } VOID NTAPI _app_logthread ( _In_ PVOID arglist ) { PITEM_APP ptr_app = NULL; PITEM_LOG ptr_log; HWND hwnd; BOOLEAN is_notificationenabled; BOOLEAN is_exludeblocklist; BOOLEAN is_exludestealth; BOOLEAN is_loguienabled; BOOLEAN is_exludeallow; BOOLEAN is_silent = FALSE; BOOLEAN is_logenabled; BOOLEAN is_notexist; hwnd = _r_app_gethwnd (); ptr_log = arglist; // apps collector is_notexist = ptr_log->app_hash && !ptr_log->is_allow && !_app_isappfound (ptr_log->app_hash); if (is_notexist) { ptr_log->app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, ptr_log->path, NULL, NULL); if (ptr_log->app_hash) { ptr_app = _app_getappitem (ptr_log->app_hash); if (ptr_app) _app_listview_updateby_id (hwnd, ptr_app->type, PR_UPDATE_TYPE); _app_profile_save (hwnd); } } if (!ptr_app) ptr_app = _app_getappitem (ptr_log->app_hash); is_logenabled = _r_config_getboolean (L"IsLogEnabled", FALSE, NULL); is_loguienabled = _r_config_getboolean (L"IsLogUiEnabled", FALSE, NULL); is_notificationenabled = _r_config_getboolean (L"IsNotificationsEnabled", TRUE, NULL); is_exludeallow = !(ptr_log->is_allow && _r_config_getboolean (L"IsExcludeClassifyAllow", TRUE, NULL)); is_exludestealth = !(ptr_log->is_system && _r_config_getboolean (L"IsExcludeStealth", TRUE, NULL)); is_exludeblocklist = !(ptr_log->is_blocklist && _r_config_getboolean (L"IsExcludeBlocklist", TRUE, NULL)) && !(ptr_log->is_custom && _r_config_getboolean (L"IsExcludeCustomRules", TRUE, NULL)); if ((is_logenabled || is_loguienabled || is_notificationenabled) && is_exludestealth && is_exludeallow) { // get network string ptr_log->remote_addr_str = _app_formataddress (ptr_log->af, ptr_log->protocol, &ptr_log->remote_addr, 0, 0); ptr_log->local_addr_str = _app_formataddress (ptr_log->af, ptr_log->protocol, &ptr_log->local_addr, 0, 0); // display notification if (is_notificationenabled) { if (ptr_app && !ptr_log->is_allow && is_exludeblocklist) { if (_app_getappinfo (ptr_app, INFO_IS_SILENT, &is_silent, sizeof (BOOLEAN))) { if (!is_silent) _app_notify_addobject (hwnd, ptr_log, ptr_app); } } } // write log to a file if (is_logenabled) _app_logwrite (ptr_log); // only for my own provider if (ptr_log->is_myprovider) { // write log to a ui if (is_loguienabled) _app_logwrite_ui (hwnd, ptr_log); // write to a ui } } if (ptr_app) _r_obj_dereference (ptr_app); _r_obj_dereference (ptr_log); } ================================================ FILE: src/log.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once // FwpmNetEventSubscribe4 (win10rs5+) typedef ULONG (WINAPI *FWPMNES4)( _In_ HANDLE engine_handle, _In_ const FWPM_NET_EVENT_SUBSCRIPTION0 *subscription, _In_ FWPM_NET_EVENT_CALLBACK4 callback, _In_opt_ PVOID context, _Out_ PHANDLE events_handle ); // FwpmNetEventSubscribe3 (win10rs4+) typedef ULONG (WINAPI *FWPMNES3)( _In_ HANDLE engine_handle, _In_ const FWPM_NET_EVENT_SUBSCRIPTION0 *subscription, _In_ FWPM_NET_EVENT_CALLBACK3 callback, _In_opt_ PVOID context, _Out_ PHANDLE events_handle ); // FwpmNetEventSubscribe2 (win10rs1+) typedef ULONG (WINAPI *FWPMNES2)( _In_ HANDLE engine_handle, _In_ const FWPM_NET_EVENT_SUBSCRIPTION0 *subscription, _In_ FWPM_NET_EVENT_CALLBACK2 callback, _In_opt_ PVOID context, _Out_ PHANDLE events_handle ); // FwpmNetEventSubscribe1 (win8+) typedef ULONG (WINAPI *FWPMNES1)( _In_ HANDLE engine_handle, _In_ const FWPM_NET_EVENT_SUBSCRIPTION0 *subscription, _In_ FWPM_NET_EVENT_CALLBACK1 callback, _In_opt_ PVOID context, _Out_ PHANDLE events_handle ); VOID _app_loginit ( _In_ BOOLEAN is_install ); VOID _app_loginitfile ( _In_ HANDLE hfile ); ULONG _app_getloghash ( _In_ PITEM_LOG ptr_log ); _Ret_maybenull_ PR_STRING _app_getlogpath (); _Ret_maybenull_ PR_STRING _app_getlogviewer (); BOOLEAN _app_islogfound ( _In_ ULONG log_hash ); BOOLEAN _app_logislimitreached ( _In_ HANDLE hfile ); VOID _app_logclear ( _In_opt_ HANDLE hfile ); VOID _app_logclear_ui ( _In_ HWND hwnd ); VOID _app_logwrite ( _In_ PITEM_LOG ptr_log ); VOID _app_logwrite_ui ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log ); VOID _wfp_logsubscribe ( _In_opt_ HWND hwnd, _In_ HANDLE engine_handle ); VOID _wfp_logunsubscribe ( _In_ HANDLE engine_handle ); VOID _wfp_logsetoption ( _In_ HANDLE engine_handle ); VOID CALLBACK _wfp_logcallback ( _In_ PITEM_LOG_CALLBACK log ); // win7+ callback VOID CALLBACK _wfp_logcallback0 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT1* event_data ); // win8+ callback VOID CALLBACK _wfp_logcallback1 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT2* event_data ); // win10rs1+ callback VOID CALLBACK _wfp_logcallback2 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT3* event_data ); // win10rs4+ callback VOID CALLBACK _wfp_logcallback3 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT4* event_data ); // win10rs5+ callback VOID CALLBACK _wfp_logcallback4 ( _Inout_ PVOID context, _In_ const FWPM_NET_EVENT5* event_data ); VOID NTAPI _app_logthread ( _In_ PVOID arglist ); ================================================ FILE: src/main.c ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #include "global.h" BOOLEAN _app_changefilters ( _In_ HWND hwnd, _In_ BOOLEAN is_install, _In_ BOOLEAN is_forced ) { PITEM_TAB_CONTEXT tab_context; PITEM_CONTEXT context; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return FALSE; _app_listview_sort (hwnd, tab_context->listview_id, INT_ERROR, FALSE); if (is_forced || _wfp_isfiltersinstalled ()) { _app_initinterfacestate (hwnd, TRUE); context = _r_freelist_allocateitem (&context_free_list); context->hwnd = hwnd; context->is_install = is_install; _r_workqueue_queueitem (&wfp_queue, &_wfp_applythread, context); return TRUE; } _r_listview_redraw (hwnd, tab_context->listview_id); _app_profile_save (hwnd); return FALSE; } BOOLEAN _app_installmessage ( _In_opt_ HWND hwnd, _In_ BOOLEAN is_install ) { TASKDIALOGCONFIG tdc = {0}; WCHAR str_main[256]; WCHAR radio_text_1[128]; WCHAR radio_text_2[128]; WCHAR str_flag[128]; WCHAR str_button_text_1[64]; WCHAR str_button_text_2[64]; TASKDIALOG_BUTTON td_buttons[2] = {0}; TASKDIALOG_BUTTON td_radios[2] = {0}; INT command_id; INT radio_id; BOOL is_flagchecked; HRESULT status; tdc.cbSize = sizeof (TASKDIALOGCONFIG); tdc.dwFlags = TDF_ENABLE_HYPERLINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_NO_SET_FOREGROUND; tdc.hwndParent = hwnd; tdc.pszWindowTitle = _r_app_getname (); tdc.pszMainIcon = is_install ? TD_INFORMATION_ICON : TD_WARNING_ICON; //tdc.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON; tdc.pfCallback = &_r_msg_callback; tdc.lpCallbackData = MAKELONG (0, TRUE); // on top if (_r_config_getboolean (L"WF_State", TRUE, NULL)) tdc.dwFlags |= TDF_VERIFICATION_FLAG_CHECKED; tdc.pButtons = td_buttons; tdc.cButtons = RTL_NUMBER_OF (td_buttons); tdc.nDefaultButton = IDYES; _r_str_copy ( str_button_text_1, RTL_NUMBER_OF (str_button_text_1), _app_getstateaction (is_install ? INSTALL_DISABLED : INSTALL_ENABLED) ); _r_str_copy (str_button_text_2, RTL_NUMBER_OF (str_button_text_2), _r_locale_getstring (IDS_CLOSE)); td_buttons[0].nButtonID = IDYES; td_buttons[0].pszButtonText = str_button_text_1; td_buttons[1].nButtonID = IDNO; td_buttons[1].pszButtonText = str_button_text_2; if (is_install) { _r_str_copy (str_main, RTL_NUMBER_OF (str_main), _r_locale_getstring (IDS_QUESTION_START)); _r_str_copy (str_flag, RTL_NUMBER_OF (str_flag), _r_locale_getstring (IDS_DISABLEWINDOWSFIREWALL_CHK)); tdc.pRadioButtons = td_radios; tdc.cRadioButtons = RTL_NUMBER_OF (td_radios); tdc.nDefaultRadioButton = IDYES; _r_str_copy (radio_text_1, RTL_NUMBER_OF (radio_text_1), _r_locale_getstring (IDS_INSTALL_PERMANENT)); _r_str_copy (radio_text_2, RTL_NUMBER_OF (radio_text_2), _r_locale_getstring (IDS_INSTALL_TEMPORARY)); td_radios[0].nButtonID = IDYES; td_radios[0].pszButtonText = radio_text_1; td_radios[1].nButtonID = IDNO; td_radios[1].pszButtonText = radio_text_2; } else { _r_str_copy (str_main, RTL_NUMBER_OF (str_main), _r_locale_getstring (IDS_QUESTION_STOP)); _r_str_copy (str_flag, RTL_NUMBER_OF (str_flag), _r_locale_getstring (IDS_ENABLEWINDOWSFIREWALL_CHK)); } tdc.pszMainInstruction = str_main; tdc.pszVerificationText = str_flag; status = _r_msg_taskdialog (&tdc, &command_id, &radio_id, &is_flagchecked); if (SUCCEEDED (status)) { _r_config_setboolean (L"WF_State", is_flagchecked ? TRUE : FALSE, NULL); if (command_id == IDYES) { if (is_install) { config.is_filterstemporary = (radio_id == IDNO); if (is_flagchecked) _wfp_firewallenable (FALSE); } else { config.is_filterstemporary = FALSE; if (is_flagchecked) _wfp_firewallenable (TRUE); } return TRUE; } } return FALSE; } VOID _app_config_apply ( _In_ HWND hwnd, _In_opt_ HWND hsettings, _In_ INT ctrl_id ) { HMENU hmenu; BOOLEAN is_enabled; BOOLEAN new_val; switch (ctrl_id) { case IDC_LOADONSTARTUP_CHK: case IDM_LOADONSTARTUP_CHK: { new_val = !_r_autorun_isenabled (); break; } case IDC_STARTMINIMIZED_CHK: case IDM_STARTMINIMIZED_CHK: { new_val = !_r_config_getboolean (L"IsStartMinimized", FALSE, NULL); break; } case IDC_SKIPUACWARNING_CHK: case IDM_SKIPUACWARNING_CHK: { new_val = !_r_skipuac_isenabled (); break; } case IDC_CHECKUPDATES_CHK: case IDM_CHECKUPDATES_CHK: { new_val = !_r_update_isenabled (FALSE); break; } case IDC_RULE_BLOCKOUTBOUND: case IDM_RULE_BLOCKOUTBOUND: { new_val = !_r_config_getboolean (L"BlockOutboundConnections", TRUE, NULL); break; } case IDC_RULE_BLOCKINBOUND: case IDM_RULE_BLOCKINBOUND: { new_val = !_r_config_getboolean (L"BlockInboundConnections", TRUE, NULL); break; } case IDC_RULE_ALLOWLOOPBACK: case IDM_RULE_ALLOWLOOPBACK: { new_val = !_r_config_getboolean (L"AllowLoopbackConnections", TRUE, NULL); break; } case IDC_RULE_ALLOW6TO4: case IDM_RULE_ALLOW6TO4: { new_val = !_r_config_getboolean (L"AllowIPv6", TRUE, NULL); break; } case IDM_RULE_ALLOWWINDOWSUPDATE: { new_val = !_app_wufixenabled (); break; } case IDC_USESTEALTHMODE_CHK: { new_val = !_r_config_getboolean (L"UseStealthMode", TRUE, NULL); break; } case IDC_USECERTIFICATES_CHK: case IDM_USECERTIFICATES_CHK: { new_val = !_r_config_getboolean (L"IsCertificatesEnabled", TRUE, NULL); break; } case IDM_KEEPUNUSED_CHK: { new_val = !_r_config_getboolean (L"IsKeepUnusedApps", TRUE, NULL); break; } case IDC_USEHASHES_CHK: case IDM_USEHASHES_CHK: { new_val = !_r_config_getboolean (L"IsHashesEnabled", FALSE, NULL); break; } case IDC_INSTALLBOOTTIMEFILTERS_CHK: { new_val = !_r_config_getboolean (L"InstallBoottimeFilters", TRUE, NULL); break; } case IDC_USENETWORKRESOLUTION_CHK: case IDM_USENETWORKRESOLUTION_CHK: { new_val = !_r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE, NULL); break; } case IDM_USEAPPMONITOR_CHK: { new_val = !_r_config_getboolean (L"IsEnableAppMonitor", FALSE, NULL); break; } case IDM_USEDARKTHEME_CHK: { new_val = !_r_theme_isenabled (); break; } case IDM_PROFILETYPE_PLAIN: case IDM_PROFILETYPE_COMPRESSED: case IDM_PROFILETYPE_ENCRYPTED: { break; } default: { return; } } hmenu = GetMenu (hwnd); if (!hmenu) return; switch (ctrl_id) { case IDC_LOADONSTARTUP_CHK: case IDM_LOADONSTARTUP_CHK: { _r_autorun_enable (hsettings ? hsettings : hwnd, new_val); is_enabled = _r_autorun_isenabled (); _r_menu_checkitem (hmenu, IDM_LOADONSTARTUP_CHK, 0, MF_BYCOMMAND, is_enabled); if (hsettings) _r_ctrl_checkbutton (hsettings, IDC_LOADONSTARTUP_CHK, is_enabled); break; } case IDC_STARTMINIMIZED_CHK: case IDM_STARTMINIMIZED_CHK: { _r_config_setboolean (L"IsStartMinimized", new_val, NULL); _r_menu_checkitem (hmenu, IDM_STARTMINIMIZED_CHK, 0, MF_BYCOMMAND, new_val); break; } case IDC_SKIPUACWARNING_CHK: case IDM_SKIPUACWARNING_CHK: { _r_skipuac_enable (hsettings ? hsettings : hwnd, new_val); is_enabled = _r_skipuac_isenabled (); _r_menu_checkitem (hmenu, IDM_SKIPUACWARNING_CHK, 0, MF_BYCOMMAND, is_enabled); if (hsettings) _r_ctrl_checkbutton (hsettings, IDC_SKIPUACWARNING_CHK, is_enabled); break; } case IDC_CHECKUPDATES_CHK: case IDM_CHECKUPDATES_CHK: { _r_update_enable (new_val); _r_menu_checkitem (hmenu, IDM_CHECKUPDATES_CHK, 0, MF_BYCOMMAND, new_val); break; } case IDC_RULE_BLOCKOUTBOUND: case IDM_RULE_BLOCKOUTBOUND: { _r_config_setboolean (L"BlockOutboundConnections", new_val, NULL); _r_menu_checkitem (hmenu, IDM_RULE_BLOCKOUTBOUND, 0, MF_BYCOMMAND, new_val); break; } case IDC_RULE_BLOCKINBOUND: case IDM_RULE_BLOCKINBOUND: { _r_config_setboolean (L"BlockInboundConnections", new_val, NULL); _r_menu_checkitem (hmenu, IDM_RULE_BLOCKINBOUND, 0, MF_BYCOMMAND, new_val); break; } case IDC_RULE_ALLOWLOOPBACK: case IDM_RULE_ALLOWLOOPBACK: { _r_config_setboolean (L"AllowLoopbackConnections", new_val, NULL); _r_menu_checkitem (hmenu, IDM_RULE_ALLOWLOOPBACK, 0, MF_BYCOMMAND, new_val); break; } case IDC_RULE_ALLOW6TO4: case IDM_RULE_ALLOW6TO4: { _r_config_setboolean (L"AllowIPv6", new_val, NULL); _r_menu_checkitem (hmenu, IDM_RULE_ALLOW6TO4, 0, MF_BYCOMMAND, new_val); break; } case IDM_RULE_ALLOWWINDOWSUPDATE: { _r_config_setboolean (L"IsWUFixEnabled", new_val, NULL); _r_menu_checkitem (hmenu, IDM_RULE_ALLOWWINDOWSUPDATE, 0, MF_BYCOMMAND, new_val); break; } case IDM_PROFILETYPE_PLAIN: { _r_config_setlong (L"ProfileType", 0, NULL); _r_menu_checkitem (hmenu, IDM_PROFILETYPE_PLAIN, IDM_PROFILETYPE_ENCRYPTED, MF_BYCOMMAND, IDM_PROFILETYPE_PLAIN); _app_profile_save (hwnd); break; } case IDM_PROFILETYPE_COMPRESSED: { _r_config_setlong (L"ProfileType", 1, NULL); _r_menu_checkitem (hmenu, IDM_PROFILETYPE_PLAIN, IDM_PROFILETYPE_ENCRYPTED, MF_BYCOMMAND, IDM_PROFILETYPE_COMPRESSED); _app_profile_save (hwnd); break; } case IDM_PROFILETYPE_ENCRYPTED: { _r_config_setlong (L"ProfileType", 2, NULL); _r_menu_checkitem (hmenu, IDM_PROFILETYPE_PLAIN, IDM_PROFILETYPE_ENCRYPTED, MF_BYCOMMAND, IDM_PROFILETYPE_ENCRYPTED); _app_profile_save (hwnd); break; } case IDC_USESTEALTHMODE_CHK: { _r_config_setboolean (L"UseStealthMode", new_val, NULL); break; } case IDC_INSTALLBOOTTIMEFILTERS_CHK: { _r_config_setboolean (L"InstallBoottimeFilters", new_val, NULL); break; } case IDC_USECERTIFICATES_CHK: case IDM_USECERTIFICATES_CHK: { PITEM_APP ptr_app = NULL; ULONG_PTR enum_key = 0; INT listview_id; _r_config_setboolean (L"IsCertificatesEnabled", new_val, NULL); _r_menu_checkitem (hmenu, IDM_USECERTIFICATES_CHK, 0, MF_BYCOMMAND, new_val); if (new_val) { _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (!ptr_app->real_path) continue; listview_id = _app_listview_getbytype (ptr_app->type); _app_getfileinformation (ptr_app->real_path, ptr_app->app_hash, ptr_app->type, listview_id); } _r_queuedlock_releaseshared (&lock_apps); } break; } case IDM_KEEPUNUSED_CHK: { _r_config_setboolean (L"IsKeepUnusedApps", new_val, NULL); _r_menu_checkitem (hmenu, IDM_KEEPUNUSED_CHK, 0, MF_BYCOMMAND, new_val); break; } case IDC_USEHASHES_CHK: case IDM_USEHASHES_CHK: { PITEM_APP ptr_app = NULL; ULONG_PTR enum_key = 0; INT listview_id; _r_config_setboolean (L"IsHashesEnabled", new_val, NULL); _r_menu_checkitem (hmenu, IDM_USEHASHES_CHK, 0, MF_BYCOMMAND, new_val); _r_menu_enableitem (hmenu, IDM_USEAPPMONITOR_CHK, FALSE, new_val); if (new_val) { _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (!ptr_app->real_path) continue; listview_id = _app_listview_getbytype (ptr_app->type); _app_getfileinformation (ptr_app->real_path, ptr_app->app_hash, ptr_app->type, listview_id); } _r_queuedlock_releaseshared (&lock_apps); } break; } case IDC_USENETWORKRESOLUTION_CHK: case IDM_USENETWORKRESOLUTION_CHK: { _r_config_setboolean (L"IsNetworkResolutionsEnabled", new_val, NULL); _r_menu_checkitem (hmenu, IDM_USENETWORKRESOLUTION_CHK, 0, MF_BYCOMMAND, new_val); break; } case IDM_USEAPPMONITOR_CHK: { _r_config_setboolean (L"IsEnableAppMonitor", new_val, NULL); _r_menu_checkitem (hmenu, IDM_USEAPPMONITOR_CHK, 0, MF_BYCOMMAND, new_val); _app_fileloggingenable (); break; } case IDM_USEDARKTHEME_CHK: { _r_menu_checkitem (hmenu, IDM_USEDARKTHEME_CHK, 0, MF_BYCOMMAND, new_val); _r_theme_enable (hwnd, new_val); break; } } switch (ctrl_id) { case IDM_LOADONSTARTUP_CHK: case IDC_LOADONSTARTUP_CHK: case IDM_STARTMINIMIZED_CHK: case IDC_STARTMINIMIZED_CHK: case IDM_SKIPUACWARNING_CHK: case IDC_SKIPUACWARNING_CHK: case IDM_CHECKUPDATES_CHK: case IDC_CHECKUPDATES_CHK: case IDM_PROFILETYPE_PLAIN: case IDM_PROFILETYPE_COMPRESSED: case IDM_PROFILETYPE_ENCRYPTED: case IDC_USENETWORKRESOLUTION_CHK: case IDM_USENETWORKRESOLUTION_CHK: case IDC_USECERTIFICATES_CHK: case IDM_USECERTIFICATES_CHK: case IDM_KEEPUNUSED_CHK: case IDC_USEHASHES_CHK: case IDM_USEHASHES_CHK: case IDM_USEAPPMONITOR_CHK: case IDM_USEDARKTHEME_CHK: { return; } } if (_wfp_isfiltersinstalled ()) _app_changefilters (hwnd, TRUE, TRUE); } INT_PTR CALLBACK SettingsProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ) { switch (msg) { case RM_INITIALIZE: { INT dialog_id = (INT)wparam; switch (dialog_id) { case IDD_SETTINGS_GENERAL: { _r_ctrl_checkbutton (hwnd, IDC_ALWAYSONTOP_CHK, _r_config_getboolean (L"AlwaysOnTop", FALSE, NULL)); #if defined(APP_HAVE_AUTORUN) _r_ctrl_checkbutton (hwnd, IDC_LOADONSTARTUP_CHK, _r_autorun_isenabled ()); #endif // APP_HAVE_AUTORUN _r_ctrl_checkbutton (hwnd, IDC_STARTMINIMIZED_CHK, _r_config_getboolean (L"IsStartMinimized", FALSE, NULL)); #if defined(APP_HAVE_SKIPUAC) _r_ctrl_checkbutton (hwnd, IDC_SKIPUACWARNING_CHK, _r_skipuac_isenabled ()); #endif // APP_HAVE_SKIPUAC _r_ctrl_checkbutton (hwnd, IDC_CHECKUPDATES_CHK, _r_update_isenabled (FALSE)); _r_locale_enum (hwnd, IDC_LANGUAGE, 0); break; } case IDD_SETTINGS_RULES: { HWND htip; _r_ctrl_checkbutton (hwnd, IDC_RULE_BLOCKOUTBOUND, _r_config_getboolean (L"BlockOutboundConnections", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_RULE_BLOCKINBOUND, _r_config_getboolean (L"BlockInboundConnections", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_RULE_ALLOWLOOPBACK, _r_config_getboolean (L"AllowLoopbackConnections", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_RULE_ALLOW6TO4, _r_config_getboolean (L"AllowIPv6", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_USESTEALTHMODE_CHK, _r_config_getboolean (L"UseStealthMode", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_INSTALLBOOTTIMEFILTERS_CHK, _r_config_getboolean (L"InstallBoottimeFilters", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_USECERTIFICATES_CHK, _r_config_getboolean (L"IsCertificatesEnabled", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_USEHASHES_CHK, _r_config_getboolean (L"IsHashesEnabled", FALSE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_USENETWORKRESOLUTION_CHK, _r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE, NULL)); htip = _r_ctrl_createtip (hwnd); if (!htip) break; _r_ctrl_settiptext (htip, hwnd, IDC_RULE_BLOCKOUTBOUND, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_RULE_BLOCKINBOUND, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_RULE_ALLOWLOOPBACK, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_RULE_ALLOW6TO4, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_USESTEALTHMODE_CHK, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_INSTALLBOOTTIMEFILTERS_CHK, LPSTR_TEXTCALLBACK); break; } case IDD_SETTINGS_BLOCKLIST: { _r_ctrl_checkradio ( hwnd, IDC_BLOCKLIST_SPY_DISABLE, IDC_BLOCKLIST_SPY_BLOCK, IDC_BLOCKLIST_SPY_DISABLE + _r_calc_clamp (_r_config_getlong (L"BlocklistSpyState", 2, NULL), 0, 2) ); _r_ctrl_checkradio ( hwnd, IDC_BLOCKLIST_UPDATE_DISABLE, IDC_BLOCKLIST_UPDATE_BLOCK, IDC_BLOCKLIST_UPDATE_DISABLE + _r_calc_clamp (_r_config_getlong (L"BlocklistUpdateState", 0, NULL), 0, 2) ); _r_ctrl_checkradio ( hwnd, IDC_BLOCKLIST_EXTRA_DISABLE, IDC_BLOCKLIST_EXTRA_BLOCK, IDC_BLOCKLIST_EXTRA_DISABLE + _r_calc_clamp (_r_config_getlong (L"BlocklistExtraState", 0, NULL), 0, 2) ); break; } case IDD_SETTINGS_INTERFACE: { _r_ctrl_checkbutton (hwnd, IDC_CONFIRMEXIT_CHK, _r_config_getboolean (L"ConfirmExit2", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_CONFIRMEXITTIMER_CHK, _r_config_getboolean (L"ConfirmExitTimer", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_CONFIRMLOGCLEAR_CHK, _r_config_getboolean (L"ConfirmLogClear", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_CONFIRMALLOW_CHK, _r_config_getboolean (L"ConfirmAllow", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_TRAYICONSINGLECLICK_CHK, _r_config_getboolean (L"IsTrayIconSingleClick", TRUE, NULL)); break; } case IDD_SETTINGS_HIGHLIGHTING: { PITEM_COLOR ptr_clr = NULL; ULONG_PTR enum_key = 0; BOOLEAN val; LONG icon_id; INT item_id = 0; // configure listview _r_listview_setstyle (hwnd, IDC_COLORS, LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP | LVS_EX_CHECKBOXES, FALSE); _app_listview_setview (hwnd, IDC_COLORS); _r_listview_deleteallitems (hwnd, IDC_COLORS); _r_listview_deleteallcolumns (hwnd, IDC_COLORS); _r_listview_addcolumn (hwnd, IDC_COLORS, 0, L"", 0, LVCFMT_LEFT); icon_id = _app_icons_getdefaultapp_id (DATA_APP_REGULAR); _app_listview_lock (hwnd, IDC_COLORS, TRUE); while (_r_obj_enumhashtable (colors_table, (PVOID_PTR)&ptr_clr, NULL, &enum_key)) { ptr_clr->new_clr = _r_config_getulong (ptr_clr->config_value->buffer, ptr_clr->default_clr, L"colors"); _r_listview_additem ( hwnd, IDC_COLORS, item_id, _r_locale_getstring (ptr_clr->locale_id), icon_id, I_GROUPIDNONE, (LPARAM)ptr_clr ); val = _r_config_getboolean (ptr_clr->config_name->buffer, ptr_clr->is_enabled, L"colors"); _r_listview_setitemcheck (hwnd, IDC_COLORS, item_id, val); item_id += 1; } _app_listview_lock (hwnd, IDC_COLORS, FALSE); break; } case IDD_SETTINGS_NOTIFICATIONS: { _r_ctrl_checkbutton (hwnd, IDC_ENABLENOTIFICATIONS_CHK, _r_config_getboolean (L"IsNotificationsEnabled", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_NOTIFICATIONSOUND_CHK, _r_config_getboolean (L"IsNotificationsSound", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_NOTIFICATIONFULLSCREENSILENTMODE_CHK, _r_config_getboolean (L"IsNotificationsFullscreenSilentMode", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_NOTIFICATIONONTRAY_CHK, _r_config_getboolean (L"IsNotificationsOnTray", FALSE, NULL)); _r_updown_setrange (hwnd, IDC_NOTIFICATIONTIMEOUT, 0, _r_calc_days2seconds (7)); _r_updown_setvalue (hwnd, IDC_NOTIFICATIONTIMEOUT, _r_config_getulong (L"NotificationsTimeout", NOTIFY_TIMEOUT_DEFAULT, NULL)); _r_ctrl_sendcommand (hwnd, IDC_ENABLENOTIFICATIONS_CHK, WM_APP); break; } case IDD_SETTINGS_LOGGING: { PR_STRING path; _r_ctrl_checkbutton (hwnd, IDC_ENABLELOG_CHK, _r_config_getboolean (L"IsLogEnabled", FALSE, NULL)); path = _app_getlogpath (); if (path) { _r_ctrl_setstring (hwnd, IDC_LOGPATH, path->buffer); _r_obj_dereference (path); } path = _r_config_getstringexpand (L"LogViewer", LOG_VIEWER_DEFAULT, NULL); if (path) { _r_ctrl_setstring (hwnd, IDC_LOGVIEWER, path->buffer); _r_obj_dereference (path); } _r_ctrl_setacceleration (hwnd, IDC_LOGSIZELIMIT, 64); // set step to 64kb _r_updown_setrange (hwnd, IDC_LOGSIZELIMIT, 64, _r_calc_kilobytes2bytes (512)); _r_updown_setvalue (hwnd, IDC_LOGSIZELIMIT, _r_config_getulong (L"LogSizeLimitKb", LOG_SIZE_LIMIT_DEFAULT, NULL)); _r_ctrl_checkbutton (hwnd, IDC_ENABLEUILOG_CHK, _r_config_getboolean (L"IsLogUiEnabled", FALSE, NULL)); _r_ctrl_sendcommand (hwnd, IDC_ENABLELOG_CHK, WM_APP); break; } case IDD_SETTINGS_EXCLUDE: { _r_ctrl_checkbutton (hwnd, IDC_EXCLUDEBLOCKLIST_CHK, _r_config_getboolean (L"IsExcludeBlocklist", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_EXCLUDECUSTOM_CHK, _r_config_getboolean (L"IsExcludeCustomRules", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_EXCLUDESTEALTH_CHK, _r_config_getboolean (L"IsExcludeStealth", TRUE, NULL)); _r_ctrl_checkbutton (hwnd, IDC_EXCLUDECLASSIFYALLOW_CHK, _r_config_getboolean (L"IsExcludeClassifyAllow", TRUE, NULL)); // win8+ if (_r_sys_isosversionlower (WINDOWS_8)) _r_ctrl_enable (hwnd, IDC_EXCLUDECLASSIFYALLOW_CHK, FALSE); break; } break; } break; } case RM_LOCALIZE: { INT dialog_id = (INT)wparam; // localize titles _r_ctrl_setstringformat ( hwnd, IDC_TITLE_GENERAL, L"%s:", _r_locale_getstring (IDS_TITLE_GENERAL) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_LANGUAGE, L"%s: (Language)", _r_locale_getstring (IDS_TITLE_LANGUAGE) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_BLOCKLIST_SPY, L"%s:", _r_locale_getstring (IDS_BLOCKLIST_SPY) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_BLOCKLIST_UPDATE, L"%s:", _r_locale_getstring (IDS_BLOCKLIST_UPDATE) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_BLOCKLIST_EXTRA, L"%s: (Skype, Bing, Live, Outlook, etc.)", _r_locale_getstring (IDS_BLOCKLIST_EXTRA) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_CONNECTIONS, L"%s:", _r_locale_getstring (IDS_TAB_NETWORK) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_SECURITY, L"%s:", _r_locale_getstring (IDS_TITLE_SECURITY) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_CONFIRMATIONS, L"%s:", _r_locale_getstring (IDS_TITLE_CONFIRMATIONS) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_TRAY, L"%s:", _r_locale_getstring (IDS_TITLE_TRAY) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_HIGHLIGHTING, L"%s:", _r_locale_getstring (IDS_TITLE_HIGHLIGHTING) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_LOGVIEWER, L"%s:", _r_locale_getstring (IDS_LOGVIEWER_HINT) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_INTERFACE, L"%s:", _r_locale_getstring (IDS_TITLE_INTERFACE) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_NOTIFICATIONS, L"%s:", _r_locale_getstring (IDS_TITLE_NOTIFICATIONS) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_LOGGING, L"%s:", _r_locale_getstring (IDS_TITLE_LOGGING) ); _r_ctrl_setstringformat ( hwnd, IDC_TITLE_ADVANCED, L"%s:", _r_locale_getstring (IDS_TITLE_ADVANCED) ); switch (dialog_id) { case IDD_SETTINGS_GENERAL: { _r_ctrl_setstring (hwnd, IDC_ALWAYSONTOP_CHK, _r_locale_getstring (IDS_ALWAYSONTOP_CHK)); _r_ctrl_setstring (hwnd, IDC_LOADONSTARTUP_CHK, _r_locale_getstring (IDS_LOADONSTARTUP_CHK)); _r_ctrl_setstring (hwnd, IDC_STARTMINIMIZED_CHK, _r_locale_getstring (IDS_STARTMINIMIZED_CHK)); _r_ctrl_setstring (hwnd, IDC_SKIPUACWARNING_CHK, _r_locale_getstring (IDS_SKIPUACWARNING_CHK)); _r_ctrl_setstring (hwnd, IDC_CHECKUPDATES_CHK, _r_locale_getstring (IDS_CHECKUPDATES_CHK)); _r_ctrl_setstring (hwnd, IDC_LANGUAGE_HINT, _r_locale_getstring (IDS_LANGUAGE_HINT)); break; } case IDD_SETTINGS_RULES: { LPCWSTR recommended_string; recommended_string = _r_locale_getstring (IDS_RECOMMENDED); _r_ctrl_setstringformat ( hwnd, IDC_RULE_BLOCKOUTBOUND, L"%s (%s)", _r_locale_getstring (IDS_RULE_BLOCKOUTBOUND), recommended_string ); _r_ctrl_setstringformat ( hwnd, IDC_RULE_BLOCKINBOUND, L"%s (%s)", _r_locale_getstring (IDS_RULE_BLOCKINBOUND), recommended_string ); _r_ctrl_setstringformat ( hwnd, IDC_RULE_ALLOWLOOPBACK, L"%s (%s)", _r_locale_getstring (IDS_RULE_ALLOWLOOPBACK), recommended_string ); _r_ctrl_setstringformat ( hwnd, IDC_RULE_ALLOW6TO4, L"%s (%s)", _r_locale_getstring (IDS_RULE_ALLOW6TO4), recommended_string ); _r_ctrl_setstringformat ( hwnd, IDC_USESTEALTHMODE_CHK, L"%s (%s)", _r_locale_getstring (IDS_USESTEALTHMODE_CHK), recommended_string ); _r_ctrl_setstringformat ( hwnd, IDC_INSTALLBOOTTIMEFILTERS_CHK, L"%s (%s)", _r_locale_getstring (IDS_INSTALLBOOTTIMEFILTERS_CHK), recommended_string ); _r_ctrl_setstring (hwnd, IDC_USECERTIFICATES_CHK, _r_locale_getstring (IDS_USECERTIFICATES_CHK)); _r_ctrl_setstring (hwnd, IDC_USEHASHES_CHK, _r_locale_getstring (IDS_USEHASHES_CHK)); _r_ctrl_setstring ( hwnd, IDC_USENETWORKRESOLUTION_CHK, _r_locale_getstring (IDS_USENETWORKRESOLUTION_CHK) ); break; } case IDD_SETTINGS_BLOCKLIST: { LPCWSTR recommended_string; LPCWSTR disable_string; LPCWSTR allow_string; LPCWSTR block_string; recommended_string = _r_locale_getstring (IDS_RECOMMENDED); disable_string = _r_locale_getstring (IDS_DISABLE); allow_string = _r_locale_getstring (IDS_ACTION_ALLOW); block_string = _r_locale_getstring (IDS_ACTION_BLOCK); _r_ctrl_setstring (hwnd, IDC_BLOCKLIST_SPY_DISABLE, disable_string); _r_ctrl_setstring (hwnd, IDC_BLOCKLIST_SPY_ALLOW, allow_string); _r_ctrl_setstringformat ( hwnd, IDC_BLOCKLIST_SPY_BLOCK, L"%s (%s)", block_string, recommended_string ); _r_ctrl_setstringformat ( hwnd, IDC_BLOCKLIST_UPDATE_DISABLE, L"%s (%s)", disable_string, recommended_string ); _r_ctrl_setstring (hwnd, IDC_BLOCKLIST_UPDATE_ALLOW, allow_string); _r_ctrl_setstring (hwnd, IDC_BLOCKLIST_UPDATE_BLOCK, block_string); _r_ctrl_setstringformat ( hwnd, IDC_BLOCKLIST_EXTRA_DISABLE, L"%s (%s)", disable_string, recommended_string ); _r_ctrl_setstring (hwnd, IDC_BLOCKLIST_EXTRA_ALLOW, allow_string); _r_ctrl_setstring (hwnd, IDC_BLOCKLIST_EXTRA_BLOCK, block_string); _r_ctrl_setstringformat ( hwnd, IDC_BLOCKLIST_INFO, L"Author: WindowsSpyBlocker - block spying and tracking on Windows systems.", WINDOWSSPYBLOCKER_URL ); break; } case IDD_SETTINGS_INTERFACE: { _r_ctrl_setstring (hwnd, IDC_CONFIRMEXIT_CHK, _r_locale_getstring (IDS_CONFIRMEXIT_CHK)); _r_ctrl_setstring (hwnd, IDC_CONFIRMEXITTIMER_CHK, _r_locale_getstring (IDS_CONFIRMEXITTIMER_CHK)); _r_ctrl_setstring (hwnd, IDC_CONFIRMLOGCLEAR_CHK, _r_locale_getstring (IDS_CONFIRMLOGCLEAR_CHK)); _r_ctrl_setstring (hwnd, IDC_CONFIRMALLOW_CHK, _r_locale_getstring (IDS_CONFIRMALLOW_CHK)); _r_ctrl_setstring ( hwnd, IDC_TRAYICONSINGLECLICK_CHK, _r_locale_getstring (IDS_TRAYICONSINGLECLICK_CHK) ); break; } case IDD_SETTINGS_HIGHLIGHTING: { PITEM_COLOR ptr_clr; _r_listview_setcolumn (hwnd, IDC_COLORS, 0, NULL, -100); for (INT i = 0; i < _r_listview_getitemcount (hwnd, IDC_COLORS); i++) { ptr_clr = (PITEM_COLOR)_r_listview_getitemlparam (hwnd, IDC_COLORS, i); if (ptr_clr) _r_listview_setitem (hwnd, IDC_COLORS, i, 0, _r_locale_getstring (ptr_clr->locale_id), I_DEFAULT, I_DEFAULT, I_DEFAULT); } _r_ctrl_setstring (hwnd, IDC_COLORS_HINT, _r_locale_getstring (IDS_COLORS_HINT)); break; } case IDD_SETTINGS_NOTIFICATIONS: { _r_ctrl_setstring ( hwnd, IDC_ENABLENOTIFICATIONS_CHK, _r_locale_getstring (IDS_ENABLENOTIFICATIONS_CHK) ); _r_ctrl_setstring ( hwnd, IDC_NOTIFICATIONSOUND_CHK, _r_locale_getstring (IDS_NOTIFICATIONSOUND_CHK) ); _r_ctrl_setstring ( hwnd, IDC_NOTIFICATIONFULLSCREENSILENTMODE_CHK, _r_locale_getstring (IDS_NOTIFICATIONFULLSCREENSILENTMODE_CHK) ); _r_ctrl_setstring ( hwnd, IDC_NOTIFICATIONONTRAY_CHK, _r_locale_getstring (IDS_NOTIFICATIONONTRAY_CHK) ); _r_ctrl_setstring ( hwnd, IDC_NOTIFICATIONTIMEOUT_HINT, _r_locale_getstring (IDS_NOTIFICATIONTIMEOUT_HINT) ); break; } case IDD_SETTINGS_LOGGING: { _r_ctrl_setstring (hwnd, IDC_ENABLELOG_CHK, _r_locale_getstring (IDS_ENABLELOG_CHK)); _r_ctrl_setstring (hwnd, IDC_LOGSIZELIMIT_HINT, _r_locale_getstring (IDS_LOGSIZELIMIT_HINT)); _r_ctrl_setstringformat ( hwnd, IDC_ENABLEUILOG_CHK, L"%s (%s)", _r_locale_getstring (IDS_ENABLEUILOG_CHK), _r_locale_getstring (IDS_SESSION_ONLY) ); break; } case IDD_SETTINGS_EXCLUDE: { _r_ctrl_setstringformat ( hwnd, IDC_EXCLUDEBLOCKLIST_CHK, L"%s %s", _r_locale_getstring (IDS_TITLE_EXCLUDE), _r_locale_getstring (IDS_EXCLUDEBLOCKLIST_CHK) ); _r_ctrl_setstringformat ( hwnd, IDC_EXCLUDECUSTOM_CHK, L"%s %s", _r_locale_getstring (IDS_TITLE_EXCLUDE), _r_locale_getstring (IDS_EXCLUDECUSTOM_CHK) ); _r_ctrl_setstringformat ( hwnd, IDC_EXCLUDESTEALTH_CHK, L"%s %s", _r_locale_getstring (IDS_TITLE_EXCLUDE), _r_locale_getstring (IDS_EXCLUDESTEALTH_CHK) ); _r_ctrl_setstringformat ( hwnd, IDC_EXCLUDECLASSIFYALLOW_CHK, L"%s %s [win8+]", _r_locale_getstring (IDS_TITLE_EXCLUDE), _r_locale_getstring (IDS_EXCLUDECLASSIFYALLOW_CHK) ); break; } } break; } case WM_SIZE: { RECT rect; HWND hlistview; hlistview = GetDlgItem (hwnd, IDC_COLORS); if (!hlistview) break; if (GetClientRect (hlistview, &rect)) _r_listview_setcolumn (hwnd, IDC_COLORS, 0, NULL, rect.right); break; } case WM_VSCROLL: case WM_HSCROLL: { LONG value; INT ctrl_id; ctrl_id = GetDlgCtrlID ((HWND)lparam); if (ctrl_id == IDC_LOGSIZELIMIT) { value = _r_updown_getvalue (hwnd, ctrl_id); _r_config_setlong (L"LogSizeLimitKb", value, NULL); } else if (ctrl_id == IDC_NOTIFICATIONTIMEOUT) { value = _r_updown_getvalue (hwnd, ctrl_id); _r_config_setlong (L"NotificationsTimeout", value, NULL); } break; } case WM_NOTIFY: { LPNMHDR nmlp; nmlp = (LPNMHDR)lparam; switch (nmlp->code) { case TTN_GETDISPINFO: { LPNMTTDISPINFOW lpnmdi = (LPNMTTDISPINFOW)lparam; WCHAR buffer[1024] = {0}; INT locale_id; INT ctrl_id; if ((lpnmdi->uFlags & TTF_IDISHWND) != TTF_IDISHWND) break; ctrl_id = GetDlgCtrlID ((HWND)(lpnmdi->hdr.idFrom)); if (ctrl_id == IDC_RULE_BLOCKOUTBOUND) { locale_id = IDS_RULE_BLOCKOUTBOUND; } else if (ctrl_id == IDC_RULE_BLOCKINBOUND) { locale_id = IDS_RULE_BLOCKINBOUND; } else if (ctrl_id == IDC_RULE_ALLOWLOOPBACK) { locale_id = IDS_RULE_ALLOWLOOPBACK_HINT; } else if (ctrl_id == IDC_USESTEALTHMODE_CHK) { locale_id = IDS_USESTEALTHMODE_HINT; } else if (ctrl_id == IDC_INSTALLBOOTTIMEFILTERS_CHK) { locale_id = IDS_INSTALLBOOTTIMEFILTERS_HINT; } else { break; } _r_str_copy (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (locale_id)); lpnmdi->lpszText = buffer; break; } case LVN_ITEMCHANGED: { PITEM_TAB_CONTEXT tab_context; LPNMLISTVIEW lpnmlv; PITEM_COLOR ptr_clr; INT listview_id; BOOLEAN is_enabled; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (listview_id != IDC_COLORS) break; if ((lpnmlv->uChanged & LVIF_STATE) == 0) break; if ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (1) || ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (2))) { if (_app_listview_islocked (hwnd, (INT)(INT_PTR)lpnmlv->hdr.idFrom)) break; ptr_clr = (PITEM_COLOR)lpnmlv->lParam; if (ptr_clr) { is_enabled = (lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (2); _r_config_setboolean (ptr_clr->config_name->buffer, is_enabled, L"colors"); tab_context = _app_listview_getcontext (_r_app_gethwnd (), INT_ERROR); if (tab_context) _r_listview_redraw (_r_app_gethwnd (), tab_context->listview_id); } } break; } case NM_CUSTOMDRAW: { LONG_PTR result; result = _app_message_custdraw (hwnd, (LPNMLVCUSTOMDRAW)lparam); SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, result); return result; } case NM_DBLCLK: { LPNMITEMACTIVATE lpnmlv; PITEM_TAB_CONTEXT tab_context; PITEM_COLOR ptr_clr_crnt; PITEM_COLOR ptr_clr = NULL; CHOOSECOLOR cc = {0}; COLORREF cust[16] = {0}; ULONG_PTR enum_key = 0; ULONG_PTR index = 0; INT listview_id; lpnmlv = (LPNMITEMACTIVATE)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (lpnmlv->iItem == INT_ERROR) break; if (listview_id != IDC_COLORS) break; ptr_clr_crnt = (PITEM_COLOR)_r_listview_getitemlparam (hwnd, listview_id, lpnmlv->iItem); if (!ptr_clr_crnt) break; while (_r_obj_enumhashtable (colors_table, (PVOID_PTR)&ptr_clr, NULL, &enum_key)) { cust[index++] = ptr_clr->default_clr; } cc.lStructSize = sizeof (CHOOSECOLOR); cc.Flags = CC_RGBINIT | CC_FULLOPEN; cc.hwndOwner = hwnd; cc.lpCustColors = cust; cc.rgbResult = ptr_clr_crnt->new_clr; if (ChooseColorW (&cc)) { ptr_clr_crnt->new_clr = cc.rgbResult; _r_config_setulong (ptr_clr_crnt->config_value->buffer, cc.rgbResult, L"colors"); _r_listview_redraw (hwnd, IDC_COLORS); tab_context = _app_listview_getcontext (_r_app_gethwnd (), INT_ERROR); if (tab_context) _r_listview_redraw (_r_app_gethwnd (), tab_context->listview_id); } break; } case NM_CLICK: case NM_RETURN: { PNMLINK pnmlink; pnmlink = (PNMLINK)lparam; if (!_r_str_isempty (pnmlink->item.szUrl)) _r_shell_opendefault (pnmlink->item.szUrl); break; } } break; } case WM_COMMAND: { INT ctrl_id = LOWORD (wparam); INT notify_code = HIWORD (wparam); switch (ctrl_id) { case IDC_ALWAYSONTOP_CHK: { BOOLEAN is_enabled; is_enabled = _r_ctrl_isbuttonchecked (hwnd, ctrl_id); _r_config_setboolean (L"AlwaysOnTop", is_enabled, NULL); _r_menu_checkitem (GetMenu (_r_app_gethwnd ()), IDM_ALWAYSONTOP_CHK, 0, MF_BYCOMMAND, is_enabled); break; } case IDC_LANGUAGE: { if (notify_code != CBN_SELCHANGE) break; _r_locale_apply (hwnd, ctrl_id, 0); break; } case IDC_CONFIRMEXIT_CHK: { _r_config_setboolean (L"ConfirmExit2", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_CONFIRMEXITTIMER_CHK: { _r_config_setboolean (L"ConfirmExitTimer", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_CONFIRMLOGCLEAR_CHK: { _r_config_setboolean (L"ConfirmLogClear", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_CONFIRMALLOW_CHK: { _r_config_setboolean (L"ConfirmAllow", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_TRAYICONSINGLECLICK_CHK: { _r_config_setboolean (L"IsTrayIconSingleClick", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_LOADONSTARTUP_CHK: case IDC_STARTMINIMIZED_CHK: case IDC_SKIPUACWARNING_CHK: case IDC_CHECKUPDATES_CHK: case IDC_RULE_BLOCKOUTBOUND: case IDC_RULE_BLOCKINBOUND: case IDC_RULE_ALLOWLOOPBACK: case IDC_RULE_ALLOW6TO4: case IDC_USESTEALTHMODE_CHK: case IDC_INSTALLBOOTTIMEFILTERS_CHK: case IDC_USECERTIFICATES_CHK: case IDC_USEHASHES_CHK: case IDC_USENETWORKRESOLUTION_CHK: { _app_config_apply (_r_app_gethwnd (), hwnd, ctrl_id); break; } case IDC_BLOCKLIST_SPY_DISABLE: case IDC_BLOCKLIST_SPY_ALLOW: case IDC_BLOCKLIST_SPY_BLOCK: case IDC_BLOCKLIST_UPDATE_DISABLE: case IDC_BLOCKLIST_UPDATE_ALLOW: case IDC_BLOCKLIST_UPDATE_BLOCK: case IDC_BLOCKLIST_EXTRA_DISABLE: case IDC_BLOCKLIST_EXTRA_ALLOW: case IDC_BLOCKLIST_EXTRA_BLOCK: { HMENU hmenu; LONG new_state; hmenu = GetMenu (_r_app_gethwnd ()); if (ctrl_id >= IDC_BLOCKLIST_SPY_DISABLE && ctrl_id <= IDC_BLOCKLIST_SPY_BLOCK) { new_state = _r_calc_clamp ( _r_ctrl_isradiochecked (hwnd, IDC_BLOCKLIST_SPY_DISABLE, IDC_BLOCKLIST_SPY_BLOCK) - IDC_BLOCKLIST_SPY_DISABLE, 0, 2 ); _r_menu_checkitem (hmenu, IDM_BLOCKLIST_SPY_DISABLE, IDM_BLOCKLIST_SPY_BLOCK, MF_BYCOMMAND, IDM_BLOCKLIST_SPY_DISABLE + new_state); _r_config_setlong (L"BlocklistSpyState", new_state, NULL); _app_ruleblocklistset (_r_app_gethwnd (), new_state, INT_ERROR, INT_ERROR, TRUE); } else if (ctrl_id >= IDC_BLOCKLIST_UPDATE_DISABLE && ctrl_id <= IDC_BLOCKLIST_UPDATE_BLOCK) { new_state = _r_calc_clamp ( _r_ctrl_isradiochecked (hwnd, IDC_BLOCKLIST_UPDATE_DISABLE, IDC_BLOCKLIST_UPDATE_BLOCK) - IDC_BLOCKLIST_UPDATE_DISABLE, 0, 2 ); _r_menu_checkitem (hmenu, IDM_BLOCKLIST_UPDATE_DISABLE, IDM_BLOCKLIST_UPDATE_BLOCK, MF_BYCOMMAND, IDM_BLOCKLIST_UPDATE_DISABLE + new_state); _r_config_setlong (L"BlocklistUpdateState", new_state, NULL); _app_ruleblocklistset (_r_app_gethwnd (), INT_ERROR, new_state, INT_ERROR, TRUE); } else if (ctrl_id >= IDC_BLOCKLIST_EXTRA_DISABLE && ctrl_id <= IDC_BLOCKLIST_EXTRA_BLOCK) { new_state = _r_calc_clamp ( _r_ctrl_isradiochecked (hwnd, IDC_BLOCKLIST_EXTRA_DISABLE, IDC_BLOCKLIST_EXTRA_BLOCK) - IDC_BLOCKLIST_EXTRA_DISABLE, 0, 2 ); _r_menu_checkitem (hmenu, IDM_BLOCKLIST_EXTRA_DISABLE, IDM_BLOCKLIST_EXTRA_BLOCK, MF_BYCOMMAND, IDM_BLOCKLIST_EXTRA_DISABLE + new_state); _r_config_setlong (L"BlocklistExtraState", new_state, NULL); _app_ruleblocklistset (_r_app_gethwnd (), INT_ERROR, INT_ERROR, new_state, TRUE); } break; } case IDC_ENABLELOG_CHK: { HWND hctrl; BOOLEAN is_postmessage; BOOLEAN is_enabled; //BOOLEAN is_logging_enabled; is_postmessage = (lparam == WM_APP); is_enabled = _r_ctrl_isbuttonchecked (hwnd, ctrl_id); //is_logging_enabled = is_enabled || _r_ctrl_isbuttonchecked (hwnd, IDC_ENABLEUILOG_CHK); if (!is_postmessage) { _r_config_setboolean (L"IsLogEnabled", is_enabled, NULL); _app_loginit (is_enabled); } _r_toolbar_pressbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLELOG_CHK, is_enabled); _r_ctrl_enable (hwnd, IDC_LOGPATH, is_enabled); // input _r_ctrl_enable (hwnd, IDC_LOGPATH_BTN, is_enabled); // button hctrl = _r_updown_getbuddy (hwnd, IDC_LOGSIZELIMIT); if (hctrl) _r_ctrl_enable (hctrl, 0, is_enabled); break; } case IDC_ENABLEUILOG_CHK: { BOOLEAN is_enabled; is_enabled = _r_ctrl_isbuttonchecked (hwnd, ctrl_id); _r_config_setboolean (L"IsLogUiEnabled", is_enabled, NULL); _r_toolbar_pressbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLEUILOG_CHK, is_enabled); break; } case IDC_LOGPATH: { PR_STRING log_path; if (notify_code == EN_KILLFOCUS) { log_path = _r_ctrl_getstring (hwnd, ctrl_id); if (log_path) { _r_config_setstringexpand (L"LogPath", log_path->buffer, NULL); if (_r_config_getboolean (L"IsLogEnabled", FALSE, NULL)) _app_loginit (TRUE); _r_obj_dereference (log_path); } } break; } case IDC_LOGPATH_BTN: { COMDLG_FILTERSPEC filters[] = { {L"Log files (*.log, *.csv)", L"*.log;*.csv"}, {L"All files (*.*)", L"*.*"}, }; R_FILE_DIALOG file_dialog; PR_STRING path; HRESULT status; status = _r_filedialog_initialize (&file_dialog, PR_FILEDIALOG_SAVEFILE); if (SUCCEEDED (status)) { _r_filedialog_setfilter (&file_dialog, filters, RTL_NUMBER_OF (filters)); path = _r_ctrl_getstring (hwnd, IDC_LOGPATH); if (path) { _r_filedialog_setpath (&file_dialog, &path->sr); _r_obj_dereference (path); } status = _r_filedialog_show (hwnd, &file_dialog); if (SUCCEEDED (status)) { status = _r_filedialog_getpath (&file_dialog, &path); if (SUCCEEDED (status)) { _r_config_setstringexpand (L"LogPath", path->buffer, NULL); _r_ctrl_setstring (hwnd, IDC_LOGPATH, path->buffer); _app_loginit (_r_config_getboolean (L"IsLogEnabled", FALSE, NULL)); _r_obj_dereference (path); } } _r_filedialog_destroy (&file_dialog); } break; } case IDC_LOGVIEWER: { PR_STRING log_viewer; if (notify_code != EN_KILLFOCUS) break; log_viewer = _r_ctrl_getstring (hwnd, ctrl_id); if (!log_viewer) break; _r_config_setstringexpand (L"LogViewer", log_viewer->buffer, NULL); _r_obj_dereference (log_viewer); break; } case IDC_LOGVIEWER_BTN: { COMDLG_FILTERSPEC filters[] = { {L"Executable files (*.exe)", L"*.exe"}, {L"All files (*.*)", L"*.*"}, }; R_FILE_DIALOG file_dialog; PR_STRING path; HRESULT status; status = _r_filedialog_initialize (&file_dialog, PR_FILEDIALOG_OPENFILE); if (SUCCEEDED (status)) { _r_filedialog_setfilter (&file_dialog, filters, RTL_NUMBER_OF (filters)); path = _r_ctrl_getstring (hwnd, IDC_LOGVIEWER); if (path) { _r_filedialog_setpath (&file_dialog, &path->sr); _r_obj_dereference (path); } status = _r_filedialog_show (hwnd, &file_dialog); if (SUCCEEDED (status)) { status = _r_filedialog_getpath (&file_dialog, &path); if (SUCCEEDED (status)) { _r_config_setstringexpand (L"LogViewer", path->buffer, NULL); _r_ctrl_setstring (hwnd, IDC_LOGVIEWER, path->buffer); _r_obj_dereference (path); } } _r_filedialog_destroy (&file_dialog); } break; } case IDC_LOGSIZELIMIT_CTRL: { LONG value; if (notify_code != EN_KILLFOCUS) break; value = _r_updown_getvalue (hwnd, IDC_LOGSIZELIMIT); _r_config_setlong (L"LogSizeLimitKb", value, NULL); break; } case IDC_ENABLENOTIFICATIONS_CHK: { HWND hctrl; BOOLEAN is_postmessage; BOOLEAN is_enabled; is_postmessage = ((INT)lparam == WM_APP); is_enabled = _r_ctrl_isbuttonchecked (hwnd, ctrl_id); if (!is_postmessage) _r_config_setboolean (L"IsNotificationsEnabled", is_enabled, NULL); _r_toolbar_pressbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLENOTIFICATIONS_CHK, is_enabled); _r_ctrl_enable (hwnd, IDC_NOTIFICATIONSOUND_CHK, is_enabled); _r_ctrl_enable (hwnd, IDC_NOTIFICATIONONTRAY_CHK, is_enabled); hctrl = _r_updown_getbuddy (hwnd, IDC_NOTIFICATIONTIMEOUT); if (hctrl) _r_ctrl_enable (hctrl, 0, is_enabled); _r_ctrl_sendcommand (hwnd, IDC_NOTIFICATIONSOUND_CHK, WM_APP); if (is_postmessage) break; hctrl = _app_notify_getwindow (NULL); if (hctrl) _app_notify_refresh (hctrl); break; } case IDC_NOTIFICATIONSOUND_CHK: { BOOLEAN is_postmessage; BOOLEAN is_checked; is_postmessage = ((INT)lparam == WM_APP); is_checked = _r_ctrl_isbuttonchecked (hwnd, ctrl_id); _r_ctrl_checkbutton (hwnd, IDC_NOTIFICATIONFULLSCREENSILENTMODE_CHK, _r_config_getboolean (L"IsNotificationsFullscreenSilentMode", TRUE, NULL)); if (!is_postmessage) _r_config_setboolean (L"IsNotificationsSound", is_checked, NULL); _r_ctrl_enable (hwnd, IDC_NOTIFICATIONFULLSCREENSILENTMODE_CHK, _r_ctrl_isenabled (hwnd, ctrl_id) && is_checked); break; } case IDC_NOTIFICATIONFULLSCREENSILENTMODE_CHK: { _r_config_setboolean (L"IsNotificationsFullscreenSilentMode", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_NOTIFICATIONONTRAY_CHK: { HWND hnotify; _r_config_setboolean (L"IsNotificationsOnTray", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); hnotify = _app_notify_getwindow (NULL); if (hnotify) _app_notify_setposition (hnotify, TRUE); break; } case IDC_NOTIFICATIONTIMEOUT_CTRL: { if (notify_code == EN_KILLFOCUS) _r_config_setlong (L"NotificationsTimeout", _r_updown_getvalue (hwnd, IDC_NOTIFICATIONTIMEOUT), NULL); break; } case IDC_EXCLUDESTEALTH_CHK: { _r_config_setboolean (L"IsExcludeStealth", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_EXCLUDECLASSIFYALLOW_CHK: { HANDLE hengine; _r_config_setboolean (L"IsExcludeClassifyAllow", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); hengine = _wfp_getenginehandle (); _wfp_logsetoption (hengine); break; } case IDC_EXCLUDEBLOCKLIST_CHK: { _r_config_setboolean (L"IsExcludeBlocklist", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } case IDC_EXCLUDECUSTOM_CHK: { _r_config_setboolean (L"IsExcludeCustomRules", _r_ctrl_isbuttonchecked (hwnd, ctrl_id), NULL); break; } } break; } } return FALSE; } VOID _app_addwindowtabs ( _In_ HWND hwnd ) { PITEM_TAB_CONTEXT context; // apps profile tab context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_APPS_PROFILE; context->locale_id = IDS_TAB_APPS; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); // apps services tab context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_APPS_SERVICE; context->locale_id = IDS_TAB_SERVICES; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); // uwp apps (win8+) if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_APPS_UWP; context->locale_id = IDS_TAB_PACKAGES; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); } if (!_r_config_getboolean (L"IsInternalRulesDisabled", FALSE, NULL)) { // rules blocklist tab context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_RULES_BLOCKLIST; context->locale_id = IDS_TRAY_BLOCKLIST_RULES; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); // rules system tab context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_RULES_SYSTEM; context->locale_id = IDS_TRAY_SYSTEM_RULES; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); } // rules user tab context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_RULES_CUSTOM; context->locale_id = IDS_TRAY_USER_RULES; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); // network tab context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_NETWORK; context->locale_id = IDS_TAB_NETWORK; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); // log tab context = _r_mem_allocate (sizeof (ITEM_TAB_CONTEXT)); context->listview_id = IDC_LOG; context->locale_id = IDS_TITLE_LOGGING; _r_tab_additem (hwnd, IDC_TAB, INT_MAX, L"", I_DEFAULT, (LPARAM)context); } VOID _app_tabs_init ( _In_ HWND hwnd, _In_ LONG dpi_value ) { PITEM_TAB_CONTEXT tab_context; RECT rect = {0}; LONG statusbar_height; LONG rebar_height; ULONG style; HWND hlistview; statusbar_height = _r_status_getheight (hwnd, IDC_STATUSBAR); rebar_height = _r_rebar_getheight (hwnd, IDC_REBAR); GetClientRect (hwnd, &rect); SetWindowPos ( config.hrebar, NULL, 0, 0, rect.right, rebar_height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER ); SetWindowPos ( GetDlgItem (hwnd, IDC_TAB), NULL , 0, rebar_height, rect.right, rect.bottom - rebar_height - statusbar_height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER ); _app_listview_loadfont (dpi_value, TRUE); style = LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP | LVS_EX_HEADERINALLVIEWS | LVS_EX_HEADERDRAGDROP; _app_addwindowtabs (hwnd); for (INT i = 0; i < _r_tab_getitemcount (hwnd, IDC_TAB); i++) { tab_context = _app_listview_getcontext (hwnd, i); if (!tab_context) continue; hlistview = GetDlgItem (hwnd, tab_context->listview_id); if (!hlistview) continue; _r_tab_adjustchild (hwnd, IDC_TAB, hlistview); if (tab_context->listview_id >= IDC_APPS_PROFILE && tab_context->listview_id <= IDC_RULES_CUSTOM) { _r_listview_setstyle (hwnd, tab_context->listview_id, style | LVS_EX_CHECKBOXES, TRUE); // with checkboxes if (tab_context->listview_id >= IDC_APPS_PROFILE && tab_context->listview_id <= IDC_APPS_UWP) { _r_listview_addcolumn (hwnd, tab_context->listview_id, 0, L"", -80, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 1, L"", -20, LVCFMT_RIGHT); } else { _r_listview_addcolumn (hwnd, tab_context->listview_id, 0, L"", -80, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 1, L"", -10, LVCFMT_RIGHT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 2, L"", -10, LVCFMT_RIGHT); } _r_listview_addgroup (hwnd, tab_context->listview_id, 0, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, tab_context->listview_id, 1, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, tab_context->listview_id, 2, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, tab_context->listview_id, 3, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, tab_context->listview_id, 4, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); } else if (tab_context->listview_id == IDC_NETWORK) { _r_listview_setstyle (hwnd, tab_context->listview_id, style, TRUE); _r_listview_addcolumn (hwnd, tab_context->listview_id, 0, L"", -20, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 1, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 2, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 3, L"", -10, LVCFMT_RIGHT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 4, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 5, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 6, L"", -10, LVCFMT_RIGHT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 7, L"", -10, LVCFMT_RIGHT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 8, L"", -10, LVCFMT_RIGHT); _r_listview_addgroup (hwnd, tab_context->listview_id, 0, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, tab_context->listview_id, 1, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); _r_listview_addgroup (hwnd, tab_context->listview_id, 2, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); } else if (tab_context->listview_id == IDC_LOG) { _r_listview_setstyle (hwnd, tab_context->listview_id, style, TRUE); _r_listview_addcolumn (hwnd, tab_context->listview_id, 0, L"#", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 1, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 2, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 3, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 4, L"", -10, LVCFMT_RIGHT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 5, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 6, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 7, L"", -10, LVCFMT_RIGHT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 8, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 9, L"", -10, LVCFMT_RIGHT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 10, L"", -10, LVCFMT_LEFT); _r_listview_addcolumn (hwnd, tab_context->listview_id, 11, L"", -10, LVCFMT_LEFT); _r_listview_addgroup (hwnd, tab_context->listview_id, 0, L"", 0, LVGS_COLLAPSIBLE, LVGS_COLLAPSIBLE); } // add filter group _r_listview_addgroup (hwnd, tab_context->listview_id, LV_HIDDEN_GROUP_ID, L"", 0, LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED, LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED); _app_listview_setfont (hwnd, tab_context->listview_id); BringWindowToTop (hlistview); // HACK!!! } } VOID _app_initialize ( _In_opt_ HWND hwnd ) { ULONG privileges[] = { SE_SECURITY_PRIVILEGE, SE_TAKE_OWNERSHIP_PRIVILEGE, SE_INC_BASE_PRIORITY_PRIVILEGE, SE_BACKUP_PRIVILEGE, SE_RESTORE_PRIVILEGE, SE_DEBUG_PRIVILEGE, }; R_ENVIRONMENT environment; // set privileges _r_sys_setprocessprivilege (NtCurrentProcess (), privileges, RTL_NUMBER_OF (privileges), TRUE); // set process priority _r_sys_setenvironment (&environment, PROCESS_PRIORITY_CLASS_HIGH, IoPriorityHigh, MEMORY_PRIORITY_NORMAL); _r_sys_setprocessenvironment (NtCurrentProcess (), &environment); // initialize workqueue _r_sys_setenvironment (&environment, THREAD_PRIORITY_ABOVE_NORMAL, IoPriorityHigh, MEMORY_PRIORITY_NORMAL); _r_workqueue_initialize (&file_queue, 12, &environment, L"FilesQueue"); _r_workqueue_initialize (&resolve_notify_queue, 2, &environment, L"NotificationQueue"); _r_sys_setenvironment (&environment, THREAD_PRIORITY_BELOW_NORMAL, IoPriorityLow, MEMORY_PRIORITY_NORMAL); _r_workqueue_initialize (&log_queue, 6, &environment, L"PacketsQueue"); _r_workqueue_initialize (&resolver_queue, 6, &environment, L"ResolverQueue"); _r_sys_setenvironment (&environment, THREAD_PRIORITY_HIGHEST, IoPriorityHigh, MEMORY_PRIORITY_NORMAL); _r_workqueue_initialize (&wfp_queue, 1, &environment, L"FiltersQueue"); // static initializer _r_sys_getsystemroot (&config.windows_dir); _app_profile_initialize (); config.my_path = _r_obj_createstring3 (&NtCurrentPeb ()->ProcessParameters->ImagePathName); config.svchost_path = _r_obj_concatstrings ( 2, _r_sys_getsystemdirectory ()->buffer, PATH_SVCHOST ); config.wusvc_path = _r_obj_concatstrings ( 2, _r_sys_getsystemdirectory ()->buffer, PATH_WUSVC ); config.system_path = _r_obj_createstring (PROC_SYSTEM_NAME); config.ntoskrnl_path = _r_sys_getkernelfilename (TRUE); if (!config.ntoskrnl_path) config.ntoskrnl_path = _r_obj_referenceemptystring (); config.my_hash = _r_str_gethash (&config.my_path->sr, TRUE); config.ntoskrnl_hash = _r_str_gethash (&config.system_path->sr, TRUE); config.svchost_hash = _r_str_gethash (&config.svchost_path->sr, TRUE); config.wusvc_hash = _r_str_gethash (&config.wusvc_path->sr, TRUE); // initialize free list _r_freelist_initialize (&context_free_list, sizeof (ITEM_CONTEXT), 0x20); _r_freelist_initialize (&listview_free_list, sizeof (ITEM_LISTVIEW_CONTEXT), 0x800); // initialize colors array colors_table = _r_obj_createhashtable (sizeof (ITEM_COLOR), 0x08, NULL); // initialize colors config.color_invalid = _app_addcolor (IDS_HIGHLIGHT_INVALID, L"IsHighlightInvalid", L"ColorInvalid", LV_COLOR_INVALID, TRUE); config.color_special = _app_addcolor (IDS_HIGHLIGHT_SPECIAL, L"IsHighlightSpecial", L"ColorSpecial", LV_COLOR_SPECIAL, TRUE); config.color_signed = _app_addcolor (IDS_HIGHLIGHT_SIGNED, L"IsHighlightSigned", L"ColorSigned", LV_COLOR_SIGNED, TRUE); config.color_pico = _app_addcolor (IDS_HIGHLIGHT_PICO, L"IsHighlightPico", L"ColorPico", LV_COLOR_PICO, TRUE); config.color_system = _app_addcolor (IDS_HIGHLIGHT_SYSTEM, L"IsHighlightSystem", L"ColorSystem", LV_COLOR_SYSTEM, TRUE); config.color_network = _app_addcolor (IDS_HIGHLIGHT_CONNECTION, L"IsHighlightConnection", L"ColorConnection", LV_COLOR_CONNECTION, TRUE); config.color_nonremovable = _app_addcolor (IDS_DISABLEREMOVAL, L"IsHighlightUndelete", L"ColorUndelete", LV_COLOR_UNDELETE, TRUE); _app_generate_credentials (); // load default icons _app_icons_getdefault (); // initialize global filters array object filter_ids = _r_obj_createarray (sizeof (GUID), 0x0A, NULL); // initialize apps table apps_table = _r_obj_createhashtablepointer (0x20); // initialize rules array object rules_list = _r_obj_createlist (0x0A, &_r_obj_dereference); // initialize rules configuration table rules_config = _r_obj_createhashtable (sizeof (ITEM_RULE_CONFIG), 8, &_app_dereferenceruleconfig); // initialize log hashtable object log_table = _r_obj_createhashtablepointer (0x20); // initialize cache table cache_information = _r_obj_createhashtablepointer (0x20); cache_resolution = _r_obj_createhashtablepointer (0x20); NtCreateEvent (&config.hnotify_evt, EVENT_ALL_ACCESS, NULL, NotificationEvent, TRUE); if (hwnd) _r_sys_createthread (NULL, NtCurrentProcess (), &_app_package_threadproc, hwnd, &environment, L"ServicesMonitor"); } INT FirstDriveFromMask ( _In_ ULONG unitmask ) { INT i; for (i = 0; i < PR_DEVICE_COUNT; ++i) { if (unitmask & 0x1) break; unitmask = unitmask >> 1; } return i; } INT_PTR CALLBACK DlgProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ) { switch (msg) { case WM_INITDIALOG: { WCHAR internal_profile_version[64]; ENUM_INSTALL_TYPE install_type; LONG dpi_value; // initialize vars dpi_value = _r_dc_getwindowdpi (hwnd); _r_app_sethwnd (hwnd); // HACK!!! _app_initialize (hwnd); // init buffered paint BufferedPaintInit (); // allow drag&drop support DragAcceptFiles (hwnd, TRUE); // restore window position (required!) _r_window_restoreposition (hwnd, L"window"); // initialize imagelist _app_imagelist_init (hwnd, dpi_value); // initialize toolbar _app_toolbar_init (hwnd, dpi_value); _app_toolbar_resize (hwnd, dpi_value); // initialize tabs _app_tabs_init (hwnd, dpi_value); // load profile _app_profile_load (hwnd, NULL); // install filters install_type = _wfp_isfiltersinstalled (); if (install_type != INSTALL_DISABLED) { if (install_type == INSTALL_ENABLED_TEMPORARY) config.is_filterstemporary = TRUE; _app_changefilters (hwnd, TRUE, TRUE); } else { _r_status_settext (hwnd, IDC_STATUSBAR, 0, _app_getstatelocale (install_type)); } // initialize settings _r_settings_addpage (IDD_SETTINGS_GENERAL, IDS_SETTINGS_GENERAL); _r_settings_addpage (IDD_SETTINGS_INTERFACE, IDS_TITLE_INTERFACE); _r_settings_addpage (IDD_SETTINGS_HIGHLIGHTING, IDS_TITLE_HIGHLIGHTING); _r_settings_addpage (IDD_SETTINGS_RULES, IDS_TRAY_RULES); if (!_r_config_getboolean (L"IsInternalRulesDisabled", FALSE, NULL)) _r_settings_addpage (IDD_SETTINGS_BLOCKLIST, IDS_TRAY_BLOCKLIST_RULES); // dropped packets logging (win7+) _r_settings_addpage (IDD_SETTINGS_NOTIFICATIONS, IDS_TITLE_NOTIFICATIONS); _r_settings_addpage (IDD_SETTINGS_LOGGING, IDS_TITLE_LOGGING); _r_settings_addpage (IDD_SETTINGS_EXCLUDE, IDS_TITLE_EXCLUDE); // add blocklist to update if (!_r_config_getboolean (L"IsInternalRulesDisabled", FALSE, NULL)) { _r_str_fromlong64 (internal_profile_version, RTL_NUMBER_OF (internal_profile_version), profile_info.profile_internal_timestamp); _r_update_addcomponent (L"Internal rules", L"rules_internal", internal_profile_version, &profile_info.profile_path_internal->sr, FALSE); } _app_network_initialize (hwnd); // initialize tab _app_settab_id (hwnd, _r_config_getlong (L"CurrentTab", IDC_APPS_PROFILE, NULL)); _app_fileloggingenable (); break; } case RM_INITIALIZE: { _app_message_initialize (hwnd); break; } case RM_UNINITIALIZE: { _app_message_uninitialize (hwnd); break; } case RM_LOCALIZE: { _app_message_localize (hwnd); break; } case RM_TASKBARCREATED: { ENUM_INSTALL_TYPE install_type; install_type = _wfp_getinstalltype (); // refresh tray icon _r_tray_create (hwnd, &GUID_TrayIcon, RM_TRAYICON, NULL, NULL, FALSE); _app_settrayicon (hwnd, install_type); break; } case RM_CONFIG_UPDATE: { _app_profile_load (hwnd, NULL); _app_changefilters (hwnd, TRUE, FALSE); break; } case RM_CONFIG_RESET: { _r_queuedlock_acquireexclusive (&lock_rules_config); _r_obj_clearhashtable (rules_config); _r_queuedlock_releaseexclusive (&lock_rules_config); _r_path_makebackup (&profile_info.profile_path->sr, TRUE); _app_profile_initialize (); _app_profile_load (hwnd, NULL); _app_changefilters (hwnd, TRUE, FALSE); break; } case RM_TRAYICON: { switch (LOWORD (lparam)) { case NIN_KEYSELECT: { if (GetForegroundWindow () != hwnd) _r_wnd_toggle (hwnd, TRUE); break; } case WM_MBUTTONUP: { _r_ctrl_sendcommand (hwnd, IDM_TRAY_LOGSHOW, 0); break; } case WM_LBUTTONUP: { if (_r_config_getboolean (L"IsTrayIconSingleClick", TRUE, NULL)) { _r_wnd_toggle (hwnd, FALSE); } else { SetForegroundWindow (hwnd); } break; } case WM_LBUTTONDBLCLK: { if (!_r_config_getboolean (L"IsTrayIconSingleClick", TRUE, NULL)) _r_wnd_toggle (hwnd, FALSE); break; } case WM_CONTEXTMENU: { _app_message_traycontextmenu (hwnd); break; } } break; } case WM_NOTIFICATION: { PITEM_LOG ptr_log; HWND hnotify; if (_r_queuedlock_tryacquireexclusive (&lock_notify)) { ptr_log = _r_obj_reference ((PITEM_LOG)lparam); hnotify = _app_notify_getwindow (ptr_log); _r_queuedlock_releaseexclusive (&lock_notify); SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, (LONG_PTR)hnotify); return (INT_PTR)hnotify; } return 0; } case WM_CLOSE: { LPCWSTR cfg_name; UINT locale_id; if (_wfp_isfiltersinstalled ()) { if (_app_istimersactive ()) { cfg_name = L"ConfirmExitTimer"; locale_id = IDS_QUESTION_TIMER; } else { cfg_name = L"ConfirmExit2"; locale_id = IDS_QUESTION_EXIT; } if (!_r_show_confirmmessage (hwnd, _r_locale_getstring (locale_id), NULL, cfg_name, FALSE)) { SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } } DestroyWindow (hwnd); break; } case WM_DESTROY: { HANDLE hengine; _app_loginit (FALSE); if (_r_queuedlock_islocked (&lock_apply)) { _r_workqueue_waitforfinish (&wfp_queue); _r_workqueue_destroy (&wfp_queue); } _r_tray_destroy (hwnd, &GUID_TrayIcon); hengine = _wfp_getenginehandle (); _wfp_uninitialize (hengine, FALSE); _r_imagelist_destroy (config.himg_rules_small); _r_imagelist_destroy (config.himg_rules_large); _r_imagelist_destroy (config.himg_toolbar); BufferedPaintUnInit (); PostQuitMessage (0); break; } case WM_DROPFILES: { PR_STRING path; HDROP hdrop; ULONG app_hash = 0; ULONG numfiles; ULONG length; hdrop = (HDROP)wparam; numfiles = DragQueryFileW (hdrop, UINT32_MAX, NULL, 0); for (ULONG i = 0; i < numfiles; i++) { length = DragQueryFileW (hdrop, i, NULL, 0); path = _r_obj_createstring_ex (NULL, length * sizeof (WCHAR)); if (DragQueryFileW (hdrop, i, path->buffer, length + 1)) { _r_str_trimtonullterminator (&path->sr); app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, path, NULL, NULL); } _r_obj_dereference (path); } DragFinish (hdrop); _app_profile_save (hwnd); if (!app_hash) break; _app_listview_updateby_param (hwnd, app_hash, PR_SETITEM_UPDATE, TRUE); _app_listview_showitemby_param (hwnd, app_hash, TRUE); break; } case WM_DPICHANGED: { _r_wnd_message_dpichanged (hwnd, wparam, lparam); _app_message_dpichanged (hwnd, LOWORD (wparam)); break; } case WM_THEMECHANGED: { LONG dpi_value; dpi_value = _r_dc_getwindowdpi (hwnd); _app_windowloadfont (dpi_value); _app_listview_loadfont (dpi_value, TRUE); _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE | PR_UPDATE_FORCE); _r_wnd_sendmessage (hwnd, 0, WM_SIZE, 0, 0); break; } case WM_SIZE: { RECT rect; LONG dpi_value; if (!GetClientRect (hwnd, &rect)) break; dpi_value = _r_dc_getwindowdpi (hwnd); _app_window_resize (hwnd, &rect, dpi_value); break; } case WM_GETMINMAXINFO: { LPMINMAXINFO minmax; R_SIZE point = {0}; LONG dpi_value; minmax = (LPMINMAXINFO)lparam; point.cx = 500; point.cy = 220; dpi_value = _r_dc_getwindowdpi (hwnd); _r_dc_getsizedpivalue (&point, dpi_value, TRUE); minmax->ptMinTrackSize.x = point.cx; minmax->ptMinTrackSize.y = point.cy; break; } case WM_NOTIFY: { LPNMHDR nmlp; nmlp = (LPNMHDR)lparam; switch (nmlp->code) { case RBN_HEIGHTCHANGE: { _r_wnd_sendmessage (hwnd, 0, WM_SIZE, 0, 0); break; } case TCN_SELCHANGING: { PITEM_TAB_CONTEXT tab_context; HWND hlistview; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) break; hlistview = GetDlgItem (hwnd, tab_context->listview_id); if (!hlistview) break; ShowWindow (hlistview, SW_HIDE); break; } case TCN_SELCHANGE: { PITEM_TAB_CONTEXT tab_context; HWND hlistview; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) break; hlistview = GetDlgItem (hwnd, tab_context->listview_id); if (!hlistview) break; _app_search_applyfilter (hwnd, tab_context->listview_id, config.search_string); _app_listview_updateby_id (hwnd, tab_context->listview_id, PR_UPDATE_FORCE | PR_UPDATE_NORESIZE); ShowWindow (hlistview, SW_SHOWNA); if (_r_wnd_isvisible (hwnd, TRUE)) // HACK!!! SetFocus (hlistview); _app_listview_resize (hwnd, tab_context->listview_id, FALSE); _r_config_setlong (L"CurrentTab", tab_context->listview_id, NULL); break; } case NM_CUSTOMDRAW: { LONG_PTR result; result = _app_message_custdraw (hwnd, (LPNMLVCUSTOMDRAW)lparam); SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, result); return result; } case LVN_INSERTITEM: { PITEM_LISTVIEW_CONTEXT context; LPNMLISTVIEW lpnmlv; INT listview_id; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (!(listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG)) break; if (_r_obj_isstringempty (config.search_string)) break; context = (PITEM_LISTVIEW_CONTEXT)_r_listview_getitemlparam (hwnd, listview_id, lpnmlv->iItem); if (!context) break; _app_search_applyfilteritem (hwnd, listview_id, lpnmlv->iItem, context, config.search_string); break; } case LVN_DELETEITEM: { PITEM_LISTVIEW_CONTEXT context; LPNMLISTVIEW lpnmlv; INT listview_id; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (!(listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG)) break; context = (PITEM_LISTVIEW_CONTEXT)lpnmlv->lParam; if (!context) break; _app_listview_destroycontext (context); break; } case LVN_COLUMNCLICK: { LPNMLISTVIEW lpnmlv; INT ctrl_id; lpnmlv = (LPNMLISTVIEW)lparam; ctrl_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; _app_listview_sort (hwnd, ctrl_id, lpnmlv->iSubItem, TRUE); break; } case LVN_GETINFOTIP: { LPNMLVGETINFOTIPW lpnmlv; PR_STRING string; INT listview_id; lpnmlv = (LPNMLVGETINFOTIPW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; lparam = _app_listview_getitemcontext (hwnd, listview_id, lpnmlv->iItem); string = _app_gettooltipbylparam (hwnd, listview_id, lparam); if (!string) break; _r_str_copy (lpnmlv->pszText, lpnmlv->cchTextMax, string->buffer); _r_obj_dereference (string); break; } case LVN_ITEMCHANGING: { LPNMLISTVIEW lpnmlv; INT listview_id; ULONG_PTR app_hash; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (_app_listview_islocked (hwnd, listview_id)) break; if (!(lpnmlv->uChanged & LVIF_STATE) || !lpnmlv->lParam) break; if ((listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_APPS_UWP)) { app_hash = _app_listview_getcontextcode (lpnmlv->lParam); if ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (1)) { if (app_hash == config.my_hash) { if (!_r_show_confirmmessage (hwnd, L"WARNING!", SZ_WARNING_ME, NULL, FALSE)) { SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } } } else if ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (2)) { if (app_hash == config.svchost_hash) { if (!_r_show_confirmmessage (hwnd, L"WARNING!", SZ_WARNING_SVCHOST, NULL, FALSE)) { SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } } else if (app_hash != config.my_hash) { if (!_r_show_confirmmessage (hwnd, NULL, _r_locale_getstring (IDS_QUESTION_ALLOW), L"ConfirmAllow", FALSE)) { SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } } } } break; } case LVN_ITEMCHANGED: { LPNMLISTVIEW lpnmlv; HANDLE hengine; PR_LIST rules; PITEM_APP ptr_app; PITEM_RULE ptr_rule; ULONG_PTR rule_idx; ULONG app_hash; INT listview_id; BOOLEAN is_changed = FALSE; BOOLEAN is_enabled; lpnmlv = (LPNMLISTVIEW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if ((lpnmlv->uChanged & LVIF_STATE) == 0) break; if ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (1) || ((lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (2))) { if (_app_listview_islocked (hwnd, listview_id)) break; is_enabled = (lpnmlv->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK (2); if (listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_APPS_UWP) { app_hash = (ULONG)_app_listview_getcontextcode (lpnmlv->lParam); ptr_app = _app_getappitem (app_hash); if (!ptr_app) break; if (ptr_app->is_enabled != is_enabled) { ptr_app->is_enabled = is_enabled; _app_listview_lock (hwnd, listview_id, TRUE); _app_setappiteminfo (hwnd, listview_id, lpnmlv->iItem, ptr_app); _app_listview_lock (hwnd, listview_id, FALSE); if (is_enabled) _app_notify_freeobject (NULL, ptr_app); if (!is_enabled && _app_istimerset (ptr_app)) _app_timer_reset (hwnd, ptr_app); if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); rules = _r_obj_createlist (1, NULL); _r_obj_addlistitem (rules, ptr_app, NULL); _wfp_create3filters (hengine, rules, DBG_ARG, FALSE); _r_obj_dereference (rules); } is_changed = TRUE; } _r_obj_dereference (ptr_app); } else if (listview_id >= IDC_RULES_BLOCKLIST && listview_id <= IDC_RULES_CUSTOM) { rule_idx = _app_listview_getcontextcode (lpnmlv->lParam); ptr_rule = _app_getrulebyid (rule_idx); if (!ptr_rule) break; if (ptr_rule->is_enabled != is_enabled) { _app_listview_lock (hwnd, listview_id, TRUE); _app_ruleenable (ptr_rule, is_enabled, TRUE); _app_setruleiteminfo (hwnd, listview_id, lpnmlv->iItem, ptr_rule, TRUE); _app_listview_lock (hwnd, listview_id, FALSE); if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); rules = _r_obj_createlist (1, NULL); _r_obj_addlistitem (rules, ptr_rule, NULL); _wfp_create4filters (hengine, rules, DBG_ARG, FALSE); _r_obj_dereference (rules); } is_changed = TRUE; } _r_obj_dereference (ptr_rule); } if (is_changed) { _app_listview_updateby_id (hwnd, listview_id, 0); _app_profile_save (hwnd); } } break; } case LVN_GETDISPINFO: { LPNMLVDISPINFOW lpnmlv; INT listview_id; lpnmlv = (LPNMLVDISPINFOW)lparam; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; _app_message_displayinfo (hwnd, listview_id, lpnmlv); break; } case LVN_GETEMPTYMARKUP: { NMLVEMPTYMARKUP* lpnmlv = (NMLVEMPTYMARKUP*)lparam; lpnmlv->dwFlags = EMF_CENTERED; _r_str_copy (lpnmlv->szMarkup, RTL_NUMBER_OF (lpnmlv->szMarkup), _r_locale_getstring (IDS_STATUS_EMPTY)); SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } case NM_DBLCLK: { LPNMITEMACTIVATE lpnmlv; LPNMMOUSE lpmouse; INT command_id = 0; INT listview_id; lpnmlv = (LPNMITEMACTIVATE)lparam; if (lpnmlv->iItem == INT_ERROR) break; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG) { command_id = IDM_PROPERTIES; } else if (listview_id == IDC_STATUSBAR) { lpmouse = (LPNMMOUSE)lparam; if (lpmouse->dwItemSpec == 0) { command_id = IDM_SELECT_ALL; } else if (lpmouse->dwItemSpec == 1) { command_id = IDM_PURGE_UNUSED; } else if (lpmouse->dwItemSpec == 2) { command_id = IDM_PURGE_TIMERS; } } if (command_id) _r_ctrl_sendcommand (hwnd, command_id, 0); break; } case NM_RCLICK: { LPNMITEMACTIVATE lpnmlv; if (nmlp->idFrom) { lpnmlv = (LPNMITEMACTIVATE)lparam; _app_message_contextmenu (hwnd, lpnmlv); } else { _app_message_contextmenu_columns (hwnd, nmlp); } break; } } break; } case WM_POWERBROADCAST: { if (_wfp_isfiltersapplying ()) break; switch (wparam) { case PBT_APMSUSPEND: { HANDLE engine_handle; _app_logclear_ui (hwnd); if (config.is_neteventset) { engine_handle = _wfp_getenginehandle (); _wfp_logunsubscribe (engine_handle); } SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } case PBT_APMRESUMECRITICAL: case PBT_APMRESUMESUSPEND: { HANDLE engine_handle; if (config.is_neteventset) { engine_handle = _wfp_getenginehandle (); _wfp_logsubscribe (hwnd, engine_handle); } SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } } break; } case WM_DEVICECHANGE: { switch (wparam) { case DBT_DEVICEARRIVAL: { PDEV_BROADCAST_HDR lbhdr; PDEV_BROADCAST_VOLUME lpdbv; BOOLEAN is_appexist; if (_wfp_isfiltersapplying () || !_wfp_isfiltersinstalled ()) break; lbhdr = (PDEV_BROADCAST_HDR)lparam; if (lbhdr && lbhdr->dbch_devicetype == DBT_DEVTYP_VOLUME) { lpdbv = (PDEV_BROADCAST_VOLUME)lparam; is_appexist = _app_isapphavedrive (FirstDriveFromMask (lpdbv->dbcv_unitmask)); if (is_appexist) _app_changefilters (hwnd, TRUE, FALSE); } break; } } break; } case WM_COMMAND: { INT ctrl_id = LOWORD (wparam); INT notify_code = HIWORD (wparam); if (notify_code == EN_CHANGE) { PITEM_TAB_CONTEXT tab_context; PR_STRING string; if (ctrl_id != IDC_SEARCH) break; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return 0; string = _r_ctrl_getstring (config.hrebar, IDC_SEARCH); _r_obj_movereference ((PVOID_PTR)&config.search_string, string); _app_search_applyfilter (hwnd, tab_context->listview_id, string); return 0; } else if (notify_code == 0) { if (ctrl_id >= IDX_LANGUAGE && ctrl_id <= IDX_LANGUAGE + (INT)(INT_PTR)_r_locale_getcount () + 1) { HMENU hsubmenu; HMENU hmenu; hmenu = GetMenu (hwnd); if (hmenu) { hsubmenu = GetSubMenu (GetSubMenu (hmenu, 2), LANG_MENU); if (hsubmenu) _r_locale_apply (hsubmenu, ctrl_id, IDX_LANGUAGE); } return 0; } else if (ctrl_id >= IDX_RULES_SPECIAL && ctrl_id <= (IDX_RULES_SPECIAL + (INT)(INT_PTR)_r_obj_getlistsize (rules_list))) { _app_command_idtorules (hwnd, ctrl_id); return 0; } else if (ctrl_id >= IDX_TIMER && ctrl_id <= (IDX_TIMER + (RTL_NUMBER_OF (timer_array) - 1))) { _app_command_idtotimers (hwnd, ctrl_id); return 0; } } switch (ctrl_id) { case IDCANCEL: // process Esc key { if (GetFocus () == config.hsearchbar) { _r_ctrl_setstring (config.hsearchbar, 0, L""); SetFocus (hwnd); break; } // fall through } case IDM_TRAY_SHOW: { _r_wnd_toggle (hwnd, FALSE); break; } case IDM_SETTINGS: case IDM_TRAY_SETTINGS: { _r_settings_createwindow (hwnd, &SettingsProc, 0); break; } case IDM_EXIT: case IDM_TRAY_EXIT: { _r_wnd_sendmessage (hwnd, 0, WM_CLOSE, 0, 0); break; } case IDM_WEBSITE: case IDM_TRAY_WEBSITE: { _r_shell_opendefault (_r_app_getwebsite_url ()); break; } case IDM_CHECKUPDATES: { _r_update_check (hwnd); break; } case IDM_DONATE: { _r_shell_opendefault (_r_app_getdonate_url ()); break; } case IDM_ABOUT: case IDM_TRAY_ABOUT: { _r_show_aboutmessage (hwnd); break; } case IDM_IMPORT: { COMDLG_FILTERSPEC filters[] = { {L"Profile files (*.xml)", L"*.xml"}, {L"All files (*.*)", L"*.*"}, }; R_FILE_DIALOG file_dialog; R_STRINGREF sr; PR_STRING path; HRESULT status; status = _r_filedialog_initialize (&file_dialog, PR_FILEDIALOG_OPENFILE); if (SUCCEEDED (status)) { _r_obj_initializestringref (&sr, XML_PROFILE_FILE); _r_filedialog_setfilter (&file_dialog, filters, RTL_NUMBER_OF (filters)); _r_filedialog_setpath (&file_dialog, &sr); status = _r_filedialog_show (hwnd, &file_dialog); if (SUCCEEDED (status)) { status = _r_filedialog_getpath (&file_dialog, &path); if (SUCCEEDED (status)) { status = _app_profile_load (hwnd, path); if (NT_SUCCESS (status)) { _app_profile_save (hwnd); _app_changefilters (hwnd, TRUE, FALSE); } _r_obj_dereference (path); } } _r_filedialog_destroy (&file_dialog); } break; } case IDM_EXPORT: { COMDLG_FILTERSPEC filters[] = { {L"Profile files (*.xml)", L"*.xml"}, {L"All files (*.*)", L"*.*"}, }; R_FILE_DIALOG file_dialog; R_STRINGREF sr; PR_STRING path; NTSTATUS status; status = _r_filedialog_initialize (&file_dialog, PR_FILEDIALOG_SAVEFILE); if (SUCCEEDED (status)) { _r_obj_initializestringref (&sr, XML_PROFILE_FILE); _r_filedialog_setfilter (&file_dialog, filters, RTL_NUMBER_OF (filters)); _r_filedialog_setpath (&file_dialog, &sr); status = _r_filedialog_show (hwnd, &file_dialog); if (SUCCEEDED (status)) { status = _r_filedialog_getpath (&file_dialog, &path); if (SUCCEEDED (status)) { _app_profile_save (hwnd); // added information for export profile failure (issue #707) status = _r_fs_copyfile (&profile_info.profile_path->sr, &path->sr, FALSE); if (!NT_SUCCESS (status)) _r_show_errormessage (hwnd, NULL, status, path->buffer, ET_NATIVE); _r_obj_dereference (path); } } _r_filedialog_destroy (&file_dialog); } break; } case IDM_ALWAYSONTOP_CHK: { BOOLEAN new_val; new_val = !_r_config_getboolean (L"AlwaysOnTop", FALSE, NULL); _r_menu_checkitem (GetMenu (hwnd), ctrl_id, 0, MF_BYCOMMAND, new_val); _r_config_setboolean (L"AlwaysOnTop", new_val, NULL); _r_wnd_top (hwnd, new_val); break; } case IDM_AUTOSIZECOLUMNS_CHK: { PITEM_TAB_CONTEXT tab_context; BOOLEAN new_val; new_val = !_r_config_getboolean (L"AutoSizeColumns", TRUE, NULL); _r_menu_checkitem (GetMenu (hwnd), ctrl_id, 0, MF_BYCOMMAND, new_val); _r_config_setboolean (L"AutoSizeColumns", new_val, NULL); if (new_val) { tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (tab_context) _app_listview_resize (hwnd, tab_context->listview_id, FALSE); } break; } case IDM_SHOWFILENAMESONLY_CHK: { PITEM_TAB_CONTEXT tab_context; BOOLEAN new_val; new_val = !_r_config_getboolean (L"ShowFilenames", TRUE, NULL); _r_menu_checkitem (GetMenu (hwnd), ctrl_id, 0, MF_BYCOMMAND, new_val); _r_config_setboolean (L"ShowFilenames", new_val, NULL); tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (tab_context) { _r_listview_redraw (hwnd, tab_context->listview_id); _app_listview_sort (hwnd, tab_context->listview_id, INT_ERROR, FALSE); } break; } case IDM_SHOWSEARCHBAR_CHK: { BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsShowSearchBar", TRUE, NULL); _r_menu_checkitem (GetMenu (hwnd), ctrl_id, 0, MF_BYCOMMAND, new_val); _r_config_setboolean (L"IsShowSearchBar", new_val, NULL); if (config.hsearchbar) _app_search_setvisible (hwnd, config.hsearchbar, _r_dc_getwindowdpi (hwnd)); break; } case IDM_VIEW_DETAILS: case IDM_VIEW_ICON: case IDM_VIEW_TILE: { LONG view_type; if (ctrl_id == IDM_VIEW_ICON) { view_type = LV_VIEW_ICON; } else if (ctrl_id == IDM_VIEW_TILE) { view_type = LV_VIEW_TILE; } else { view_type = LV_VIEW_DETAILS; } _r_menu_checkitem (GetMenu (hwnd), IDM_VIEW_DETAILS, IDM_VIEW_TILE, MF_BYCOMMAND, ctrl_id); _r_config_setlong (L"ViewType", view_type, NULL); _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE); break; } case IDM_SIZE_SMALL: case IDM_SIZE_LARGE: case IDM_SIZE_EXTRALARGE: { LONG icon_size; if (ctrl_id == IDM_SIZE_LARGE) { icon_size = SHIL_LARGE; } else if (ctrl_id == IDM_SIZE_EXTRALARGE) { icon_size = SHIL_EXTRALARGE; } else { icon_size = SHIL_SMALL; } _r_menu_checkitem (GetMenu (hwnd), IDM_SIZE_SMALL, IDM_SIZE_EXTRALARGE, MF_BYCOMMAND, ctrl_id); _r_config_setlong (L"IconSize", icon_size, NULL); _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE); break; } case IDM_ICONSISHIDDEN: { PITEM_APP ptr_app = NULL; ULONG_PTR enum_key = 0; INT listview_id; BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsIconsHidden", FALSE, NULL); _r_menu_checkitem (GetMenu (hwnd), ctrl_id, 0, MF_BYCOMMAND, new_val); _r_config_setboolean (L"IsIconsHidden", new_val, NULL); if (!new_val) { _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (!ptr_app->real_path) continue; listview_id = _app_listview_getbytype (ptr_app->type); _app_getfileinformation (ptr_app->real_path, ptr_app->app_hash, ptr_app->type, listview_id); } _r_queuedlock_releaseshared (&lock_apps); } break; } case IDM_FONT: { _app_command_selectfont (hwnd); break; } case IDM_FIND: { if (!config.hsearchbar || !_r_wnd_isvisible (config.hsearchbar, FALSE)) break; SetFocus (config.hsearchbar); _r_ctrl_setselection (config.hsearchbar, 0, 0, -1); break; } case IDM_REFRESH: { if (_wfp_isfiltersapplying ()) break; _app_profile_load (hwnd, NULL); _app_changefilters (hwnd, TRUE, FALSE); break; } case IDM_LOADONSTARTUP_CHK: case IDM_STARTMINIMIZED_CHK: case IDM_SKIPUACWARNING_CHK: case IDM_CHECKUPDATES_CHK: case IDM_RULE_BLOCKOUTBOUND: case IDM_RULE_BLOCKINBOUND: case IDM_RULE_ALLOWLOOPBACK: case IDM_RULE_ALLOW6TO4: case IDM_RULE_ALLOWWINDOWSUPDATE: case IDM_PROFILETYPE_PLAIN: case IDM_PROFILETYPE_COMPRESSED: case IDM_PROFILETYPE_ENCRYPTED: case IDM_USENETWORKRESOLUTION_CHK: case IDM_USECERTIFICATES_CHK: case IDM_KEEPUNUSED_CHK: case IDM_USEHASHES_CHK: case IDM_USEAPPMONITOR_CHK: case IDM_USEDARKTHEME_CHK: { _app_config_apply (hwnd, NULL, ctrl_id); break; } case IDM_BLOCKLIST_SPY_DISABLE: case IDM_BLOCKLIST_SPY_ALLOW: case IDM_BLOCKLIST_SPY_BLOCK: case IDM_BLOCKLIST_UPDATE_DISABLE: case IDM_BLOCKLIST_UPDATE_ALLOW: case IDM_BLOCKLIST_UPDATE_BLOCK: case IDM_BLOCKLIST_EXTRA_DISABLE: case IDM_BLOCKLIST_EXTRA_ALLOW: case IDM_BLOCKLIST_EXTRA_BLOCK: { HMENU hmenu; LONG new_state; hmenu = GetMenu (hwnd); if (!hmenu) break; if (ctrl_id >= IDM_BLOCKLIST_SPY_DISABLE && ctrl_id <= IDM_BLOCKLIST_SPY_BLOCK) { _r_menu_checkitem (hmenu, IDM_BLOCKLIST_SPY_DISABLE, IDM_BLOCKLIST_SPY_BLOCK, MF_BYCOMMAND, ctrl_id); new_state = _r_calc_clamp (ctrl_id - IDM_BLOCKLIST_SPY_DISABLE, 0, 2); _r_config_setlong (L"BlocklistSpyState", new_state, NULL); _app_ruleblocklistset (hwnd, new_state, INT_ERROR, INT_ERROR, TRUE); } else if (ctrl_id >= IDM_BLOCKLIST_UPDATE_DISABLE && ctrl_id <= IDM_BLOCKLIST_UPDATE_BLOCK) { _r_menu_checkitem (hmenu, IDM_BLOCKLIST_UPDATE_DISABLE, IDM_BLOCKLIST_UPDATE_BLOCK, MF_BYCOMMAND, ctrl_id); new_state = _r_calc_clamp (ctrl_id - IDM_BLOCKLIST_UPDATE_DISABLE, 0, 2); _r_config_setlong (L"BlocklistUpdateState", new_state, NULL); _app_ruleblocklistset (hwnd, INT_ERROR, new_state, INT_ERROR, TRUE); } else if (ctrl_id >= IDM_BLOCKLIST_EXTRA_DISABLE && ctrl_id <= IDM_BLOCKLIST_EXTRA_BLOCK) { _r_menu_checkitem (hmenu, IDM_BLOCKLIST_EXTRA_DISABLE, IDM_BLOCKLIST_EXTRA_BLOCK, MF_BYCOMMAND, ctrl_id); new_state = _r_calc_clamp (ctrl_id - IDM_BLOCKLIST_EXTRA_DISABLE, 0, 2); _r_config_setlong (L"BlocklistExtraState", new_state, NULL); _app_ruleblocklistset (hwnd, INT_ERROR, INT_ERROR, new_state, TRUE); } break; } case IDM_TRAY_ENABLELOG_CHK: { BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsLogEnabled", FALSE, NULL); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, ctrl_id, NULL, 0, new_val ? TBSTATE_PRESSED | TBSTATE_ENABLED : TBSTATE_ENABLED, I_IMAGENONE); _r_config_setboolean (L"IsLogEnabled", new_val, NULL); _app_loginit (new_val); break; } case IDM_TRAY_ENABLEUILOG_CHK: { BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsLogUiEnabled", FALSE, NULL); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, ctrl_id, NULL, 0, new_val ? TBSTATE_PRESSED | TBSTATE_ENABLED : TBSTATE_ENABLED, I_IMAGENONE); _r_config_setboolean (L"IsLogUiEnabled", new_val, NULL); break; } case IDM_TRAY_ENABLENOTIFICATIONS_CHK: { HWND hnotify; BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsNotificationsEnabled", TRUE, NULL); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, ctrl_id, NULL, 0, new_val ? TBSTATE_PRESSED | TBSTATE_ENABLED : TBSTATE_ENABLED, I_IMAGENONE); _r_config_setboolean (L"IsNotificationsEnabled", new_val, NULL); hnotify = _app_notify_getwindow (NULL); if (hnotify) _app_notify_refresh (hnotify); break; } case IDM_TRAY_ENABLENOTIFICATIONSSOUND_CHK: { BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsNotificationsSound", TRUE, NULL); _r_config_setboolean (L"IsNotificationsSound", new_val, NULL); break; } case IDM_TRAY_NOTIFICATIONFULLSCREENSILENTMODE_CHK: { BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsNotificationsFullscreenSilentMode", TRUE, NULL); _r_config_setboolean (L"IsNotificationsFullscreenSilentMode", new_val, NULL); break; } case IDM_TRAY_NOTIFICATIONONTRAY_CHK: { HWND hnotify; BOOLEAN new_val; new_val = !_r_config_getboolean (L"IsNotificationsOnTray", FALSE, NULL); _r_config_setboolean (L"IsNotificationsOnTray", new_val, NULL); hnotify = _app_notify_getwindow (NULL); if (hnotify) _app_notify_setposition (hnotify, TRUE); break; } case IDM_TRAY_LOGSHOW: { _app_command_logshow (hwnd); break; } case IDM_TRAY_LOGCLEAR: case IDM_LOGCLEAR: { _app_command_logclear (hwnd); break; } case IDM_TRAY_LOGSHOW_ERR: { _app_command_logerrshow (hwnd); break; } case IDM_TRAY_LOGCLEAR_ERR: { _app_command_logerrclear (hwnd); break; } case IDM_TRAY_START: { BOOLEAN is_filtersinstalled; if (_wfp_isfiltersapplying ()) break; is_filtersinstalled = !_wfp_isfiltersinstalled (); if (_app_installmessage (hwnd, is_filtersinstalled)) _app_changefilters (hwnd, is_filtersinstalled, TRUE); break; } case IDM_ADD_FILE: { COMDLG_FILTERSPEC filters[] = { {L"Executable files (*.exe)", L"*.exe"}, {L"All files (*.*)", L"*.*"}, }; R_FILE_DIALOG file_dialog; PR_STRING path; ULONG_PTR app_hash; HRESULT status; status = _r_filedialog_initialize (&file_dialog, PR_FILEDIALOG_OPENFILE); if (SUCCEEDED (status)) { _r_filedialog_setfilter (&file_dialog, filters, RTL_NUMBER_OF (filters)); status = _r_filedialog_show (hwnd, &file_dialog); if (SUCCEEDED (status)) { status = _r_filedialog_getpath (&file_dialog, &path); if (SUCCEEDED (status)) { app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, path, NULL, NULL); if (app_hash) { _app_listview_updateby_param (hwnd, app_hash, PR_SETITEM_UPDATE, TRUE); _app_listview_showitemby_param (hwnd, app_hash, TRUE); _app_profile_save (hwnd); } _r_obj_dereference (path); } } _r_filedialog_destroy (&file_dialog); } break; } case IDM_DISABLENOTIFICATIONS: case IDM_DISABLEREMOVAL: case IDM_DISABLETIMER: { _app_command_disable (hwnd, ctrl_id); break; } case IDM_COPY: case IDM_COPY_VALUE: { _app_command_copy (hwnd, ctrl_id, (INT)lparam); break; } case IDM_EXPLORE: { PITEM_TAB_CONTEXT tab_context; PITEM_NETWORK ptr_network; PITEM_APP ptr_app; PITEM_LOG ptr_log; ULONG hash_code; INT item_id = INT_ERROR; HRESULT status; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) break; if (tab_context->listview_id >= IDC_APPS_PROFILE && tab_context->listview_id <= IDC_APPS_UWP) { while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_app = _app_getappitem (hash_code); if (ptr_app) { if (ptr_app->real_path) { if (_app_isappvalidpath (ptr_app->real_path)) { status = _r_shell_showfile (&ptr_app->real_path->sr); if (FAILED (status)) _r_show_errormessage (hwnd, L"Cannot open file!", status, ptr_app->real_path->buffer, ET_WINDOWS); } } _r_obj_dereference (ptr_app); } } } else if (tab_context->listview_id == IDC_NETWORK) { while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_network = _app_network_getitem (hash_code); if (ptr_network) { if (ptr_network->path) { if (_app_isappvalidpath (ptr_network->path)) { status = _r_shell_showfile (&ptr_network->path->sr); if (FAILED (status)) _r_show_errormessage (hwnd, L"Cannot open file!", status, ptr_network->path->buffer, ET_WINDOWS); } } _r_obj_dereference (ptr_network); } } } else if (tab_context->listview_id == IDC_LOG) { while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_log = _app_getlogitem (hash_code); if (ptr_log) { if (ptr_log->path) { if (_app_isappvalidpath (ptr_log->path)) { status = _r_shell_showfile (&ptr_log->path->sr); if (FAILED (status)) _r_show_errormessage (hwnd, L"Cannot open file!", status, ptr_log->path->buffer, ET_WINDOWS); } } _r_obj_dereference (ptr_log); } } } break; } case IDM_OPENRULESEDITOR: { _app_command_openeditor (hwnd); break; } case IDM_CHECK: case IDM_UNCHECK: { _app_command_checkbox (hwnd, ctrl_id); break; } case IDM_DELETE: { _app_command_delete (hwnd); break; } case IDM_PROPERTIES: { _app_command_properties (hwnd); break; } case IDM_PURGE_UNUSED: { _app_command_purgeunused (hwnd); break; } case IDM_PURGE_TIMERS: { _app_command_purgetimers (hwnd); break; } case IDM_SELECT_ALL: { PITEM_TAB_CONTEXT tab_context; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) break; if (GetFocus () == GetDlgItem (hwnd, tab_context->listview_id)) _r_listview_setitemstate (hwnd, tab_context->listview_id, INT_ERROR, LVIS_SELECTED, LVIS_SELECTED); break; } case IDM_ZOOM: { ShowWindow (hwnd, IsZoomed (hwnd) ? SW_RESTORE : SW_MAXIMIZE); break; } case IDM_TAB_NEXT: case IDM_TAB_PREV: { INT tabs_count; INT item_id; tabs_count = _r_tab_getitemcount (hwnd, IDC_TAB); if (!tabs_count) break; item_id = _r_tab_getcurrentitem (hwnd, IDC_TAB); if (item_id == INT_ERROR) break; if (ctrl_id == IDM_TAB_NEXT) { item_id += 1; if (item_id >= tabs_count) item_id = 0; } else { item_id -= 1; if (item_id == INT_ERROR) item_id = tabs_count - 1; } _r_tab_selectitem (hwnd, IDC_TAB, item_id); break; } } break; } } return FALSE; } BOOLEAN NTAPI _app_parseargs ( _In_ R_CMDLINE_INFO_CLASS info_class ) { HANDLE hengine; _app_initialize (NULL); hengine = _wfp_getenginehandle (); switch (info_class) { case CmdlineHelp: { _r_show_message ( NULL, MB_OK | MB_ICONINFORMATION, L"Available options:", L"simplewall.exe -install - enable filtering.\r\n" L"simplewall.exe -install -temp - enable filtering until reboot.\r\n" L"simplewall.exe -install -silent - enable filtering without prompt.\r\n" L"simplewall.exe -uninstall - remove all installed filters.\r\n" L"simplewall.exe -help - show this message." ); return TRUE; } case CmdlineInstall: { if (_r_sys_getopt (_r_sys_getcommandline (), L"silent", NULL) || _app_installmessage (NULL, TRUE)) { if (_r_sys_getopt (_r_sys_getcommandline (), L"temp", NULL)) config.is_filterstemporary = TRUE; _app_profile_initialize (); _app_profile_load (NULL, NULL); if (_wfp_initialize (NULL, hengine)) _wfp_installfilters (hengine); _wfp_uninitialize (hengine, FALSE); } return TRUE; } case CmdlineUninstall: { if (_wfp_isfiltersinstalled () && _app_installmessage (NULL, FALSE)) { _wfp_destroyfilters (hengine); _wfp_uninitialize (hengine, TRUE); } return TRUE; } default: { FALLTHROUGH; } } return FALSE; } INT APIENTRY wWinMain ( _In_ HINSTANCE hinst, _In_opt_ HINSTANCE prev_hinst, _In_ LPWSTR cmdline, _In_ INT show_cmd ) { HWND hwnd; ULONG result; if (!_r_app_initialize (&_app_parseargs)) return ERROR_APP_INIT_FAILURE; hwnd = _r_app_createwindow (hinst, MAKEINTRESOURCE (IDD_MAIN), MAKEINTRESOURCE (IDI_MAIN), &DlgProc); if (!hwnd) return ERROR_APP_INIT_FAILURE; result = _r_wnd_message_callback (hwnd, MAKEINTRESOURCE (IDA_MAIN)); return result; } ================================================ FILE: src/main.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once #include "routine.h" #include "resource.h" #include "app.h" #include "global.h" // libs #pragma comment(lib, "msimg32.lib") #pragma comment(lib, "crypt32.lib") #pragma comment(lib, "dnsapi.lib") #pragma comment(lib, "fwpuclnt.lib") #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "rpcrt4.lib") #pragma comment(lib, "version.lib") #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "winmm.lib") #pragma comment(lib, "wintrust.lib") // log #define DBG_ARG TEXT (__FILE__), __LINE__ #define DBG_ARG_VAR file_name, line // guids DEFINE_GUID (GUID_TrayIcon, 0xDAB4837E, 0xCB0F, 0x47DA, 0x92, 0x22, 0x21, 0x20, 0x74, 0x9F, 0x5C, 0x41); // enums typedef enum _ENUM_TYPE_DATA { DATA_UNKNOWN = 0, DATA_APP_REGULAR, DATA_APP_DEVICE, DATA_APP_NETWORK, DATA_APP_SERVICE, DATA_APP_UWP, // win8+ DATA_APP_PICO, // win10+ DATA_RULE_BLOCKLIST, DATA_RULE_SYSTEM, DATA_RULE_SYSTEM_USER, DATA_RULE_USER, DATA_RULE_CONFIG, DATA_TYPE_PORT, DATA_TYPE_IP, DATA_FILTER_GENERAL, DATA_LISTVIEW_CURRENT, } ENUM_TYPE_DATA; typedef enum _ENUM_INSTALL_TYPE { INSTALL_DISABLED = 0, INSTALL_ENABLED, INSTALL_ENABLED_TEMPORARY, } ENUM_INSTALL_TYPE; typedef enum _ENUM_INFO_DATA { INFO_PATH = 1, INFO_BYTES_DATA, INFO_DISPLAY_NAME, INFO_COMMENT, INFO_HASH, INFO_TIMESTAMP, INFO_TIMER, INFO_LISTVIEW_ID, INFO_DISABLE, INFO_IS_ENABLED, INFO_IS_READONLY, INFO_IS_SILENT, INFO_IS_UNDELETABLE, } ENUM_INFO_DATA; typedef enum _ENUM_INFO_DATA2 { INFO_ICON_ID, INFO_SIGNATURE_STRING, // dereference required INFO_VERSION_STRING, // dereference required } ENUM_INFO_DATA2; #define LOG_PATH_DEFAULT L"%USERPROFILE%\\" APP_NAME_SHORT L".log" #define LOG_VIEWER_DEFAULT L"%SystemRoot%\\notepad.exe" #define LOG_SIZE_LIMIT_DEFAULT _r_calc_kilobytes2bytes (1) #define PROC_WAITING_PID 0 #define PROC_WAITING_NAME L"Waiting connections" #define PROC_SYSTEM_PID 4 #define PROC_SYSTEM_NAME L"System" #define PATH_SVCHOST L"\\svchost.exe" #define PATH_WUSVC L"\\wusvc.exe" #define WINDOWSSPYBLOCKER_URL L"https://github.com/crazy-max/WindowsSpyBlocker" #define SZ_TAB L" " #define SZ_CRLF L"\r\n" #define SZ_TAB_CRLF SZ_CRLF SZ_TAB #define SZ_RULE_INTERNAL_MENU L"*" #define SZ_STATE_ALLOW L"Allowed" #define SZ_STATE_BLOCK L"Blocked" #define SZ_DIRECTION_IN L"Inbound" #define SZ_DIRECTION_OUT L"Outbound" #define SZ_DIRECTION_ANY L"Any" #define SZ_DIRECTION_LOOPBACK L"Loopback" #define SZ_LOG_TITLE L"Date,Username,Path,Address (Local)," \ L"Port (Local),Address (Remote),Port (Remote)," \ L"Protocol,Layer,Filter name,Filter ID,Direction,State" SZ_CRLF #define SZ_LOG_BODY L"\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"," \ L"\"%s\",\"%s\",\"#%" TEXT (PRIu64) L"\",\"%s\",\"%s\"" SZ_CRLF #define SZ_WARNING_ME L"If you disallow this, you cannot use resolve network addresses option. Continue?" #define SZ_WARNING_SVCHOST L"Be careful, through service host (svchost.exe)" \ L"internet traffic can let out through unexpected ways. Continue?" #define SZ_HELP L"\"simplewall.exe -install\" - enable filtering." SZ_CRLF \ L"\"simplewall.exe -install -temp\" - enable filtering until reboot." SZ_CRLF \ L"\"simplewall.exe -install -silent\" - enable filtering without prompt." SZ_CRLF \ L"\"simplewall.exe -uninstall\" - remove all installed filters." SZ_CRLF \ L"\"simlewall.exe -help\" - show this message." #define DIVIDER_COPY L", " #define DIVIDER_APP L"|" #define DIVIDER_RULE L";" #define DIVIDER_RULE_RANGE L'-' #define DIVIDER_TRIM SZ_CRLF L" " #define BACKUP_HOURS_PERIOD _r_calc_hours2seconds (4) // make backup every X hour(s) (default) #define LEN_IP_MAX 68 #define MAP_CACHE_MAX 900 // limit for caching hashtable #define TRANSACTION_TIMEOUT 9000 // ui #define ICONS_MENU 6 #define LANG_MENU 7 #define NOTIFICATIONS_ID 4 #define LOGGING_ID 5 #define ERRLOG_ID 6 #define REBAR_TOOLBAR_ID 0 #define REBAR_SEARCH_ID 1 #define LV_HIDDEN_GROUP_ID 13 #define STATUSBAR_PARTS_COUNT 3 // notifications #define NOTIFY_TIMER_SAFETY_TIMEOUT 900 #define NOTIFY_TIMER_SAFETY_ID 666 #define NOTIFY_TIMEOUT_DEFAULT 60 // sec. #define NOTIFY_SOUND_NAME L"MailBeep" // default colors #define LV_COLOR_INVALID RGB(255, 125, 148) #define LV_COLOR_SPECIAL RGB(255, 255, 170) #define LV_COLOR_SIGNED RGB(175, 228, 163) #define LV_COLOR_PICO RGB(51, 153, 255) #define LV_COLOR_SYSTEM RGB(151, 196, 251) #define LV_COLOR_CONNECTION RGB(255, 168, 242) #define LV_COLOR_UNDELETE RGB(211, 211, 211) // memory limitation for 1 rule #define RULE_NAME_CCH_MAX 0x0040 // 64 #define RULE_RULE_CCH_MAX 0x0400 // 1024 typedef struct _STATIC_DATA { WCHAR windows_dir_buffer[256]; R_STRINGREF windows_dir; GUID session_key; PR_STRING search_string; PR_STRING my_path; PR_STRING ntoskrnl_path; PR_STRING svchost_path; PR_STRING wusvc_path; PR_STRING system_path; PR_BYTE service_wdiservicehost_sid; PR_BYTE service_policyagent_sid; PR_BYTE service_mpssvc_sid; PR_BYTE service_nlasvc_sid; PR_BYTE service_rpcss_sid; HIMAGELIST himg_rules_small; HIMAGELIST himg_rules_large; HIMAGELIST himg_toolbar; HBITMAP hbmp_disable; HBITMAP hbmp_enable; HBITMAP hbmp_allow; HBITMAP hbmp_block; HANDLE hmonitor_thread; HANDLE hnotify_evt; HFONT wnd_font; HFONT hfont; HWND hsearchbar; HWND htoolbar; HWND hrebar; PSID builtin_current_sid; PSID builtin_netops_sid; PSID builtin_admins_sid; volatile HWND hnotification; volatile HICON htray_icon; volatile HANDLE hnetevent; volatile HANDLE hlogfile; volatile LONG log_id; ULONG color_nonremovable; ULONG color_network; ULONG color_invalid; ULONG color_special; ULONG color_signed; ULONG color_system; ULONG color_pico; ULONG ntoskrnl_hash; ULONG svchost_hash; ULONG wusvc_hash; ULONG my_hash; BOOLEAN is_filterstemporary; BOOLEAN is_neteventenabled; BOOLEAN is_notifytimeout; BOOLEAN is_notifymouse; BOOLEAN is_neteventset; } STATIC_DATA, *PSTATIC_DATA; typedef struct _PROFILE_DATA { PR_STRING profile_path_internal; PR_STRING profile_path_backup; PR_STRING profile_path; LONG64 profile_internal_timestamp; } PROFILE_DATA, *PPROFILE_DATA; typedef struct _ITEM_APP { PR_ARRAY guids; PR_STRING original_path; PR_STRING display_name; PR_STRING short_name; PR_STRING real_path; PR_STRING comment; PR_STRING hash; PVOID notification; // PITEM_LOG PR_BYTE bytes; // service - PSECURITY_DESCRIPTOR / uwp - PSID (win8+) PTP_TIMER htimer; LONG64 last_notify; LONG64 timestamp; LONG64 timer; ULONG app_hash; ENUM_TYPE_DATA type; UINT8 profile; // reserved ffu! struct { ULONG is_undeletable : 1; ULONG is_haveerrors : 1; ULONG is_enabled : 1; ULONG is_silent : 1; ULONG spare_bits : 28; } DUMMYSTRUCTNAME; } ITEM_APP, *PITEM_APP; typedef struct _ITEM_APP_INFO { PR_STRING signature_info; PR_STRING version_info; PR_STRING path; ULONG app_hash; LONG icon_id; ENUM_TYPE_DATA type; INT listview_id; BOOLEAN is_loaded; } ITEM_APP_INFO, *PITEM_APP_INFO; typedef struct _ITEM_FILTER_CONFIG { FWP_DIRECTION direction; UINT8 protocol; ADDRESS_FAMILY af; } ITEM_FILTER_CONFIG, *PITEM_FILTER_CONFIG; typedef struct _ITEM_RULE { PR_HASHTABLE apps; PR_ARRAY guids; PR_STRING name; PR_STRING comment; PR_STRING rule_remote; PR_STRING rule_local; PR_STRING protocol_str; struct { ULONG is_enabled_default : 1; ULONG is_forservices : 1; ULONG is_haveerrors : 1; ULONG is_readonly : 1; ULONG is_enabled : 1; ULONG spare_bits : 27; } DUMMYSTRUCTNAME; union { ITEM_FILTER_CONFIG config; struct { FWP_DIRECTION direction; UINT8 protocol; ADDRESS_FAMILY af; } DUMMYSTRUCTNAME2; } DUMMYUNIONNAME; ENUM_TYPE_DATA type; FWP_ACTION_TYPE action; UINT8 profile; // reserved ffu! UINT8 weight; } ITEM_RULE, *PITEM_RULE; typedef struct _ITEM_RULE_CONFIG { PR_STRING name; PR_STRING apps; BOOLEAN is_enabled; } ITEM_RULE_CONFIG, *PITEM_RULE_CONFIG; typedef struct _ITEM_NETWORK { union { IN_ADDR remote_addr; IN6_ADDR remote_addr6; } DUMMYUNIONNAME; union { IN_ADDR local_addr; IN6_ADDR local_addr6; } DUMMYUNIONNAME2; PR_STRING path; volatile PR_STRING local_addr_str; volatile PR_STRING remote_addr_str; volatile PR_STRING local_host_str; volatile PR_STRING remote_host_str; PR_STRING protocol_str; ULONG app_hash; ULONG state; FWP_DIRECTION direction; ENUM_TYPE_DATA type; ADDRESS_FAMILY af; UINT16 remote_port; UINT16 local_port; UINT8 protocol; BOOLEAN is_connection; } ITEM_NETWORK, *PITEM_NETWORK; typedef struct _ITEM_LOG { union { IN_ADDR remote_addr; IN6_ADDR remote_addr6; } DUMMYUNIONNAME; union { IN_ADDR local_addr; IN6_ADDR local_addr6; } DUMMYUNIONNAME2; PR_STRING path; PR_STRING filter_name; PR_STRING layer_name; PR_STRING username; PR_STRING protocol_str; volatile PR_STRING local_addr_str; volatile PR_STRING remote_addr_str; volatile PR_STRING local_host_str; volatile PR_STRING remote_host_str; LONG64 timestamp; UINT64 filter_id; ULONG app_hash; volatile LONG log_id; FWP_DIRECTION direction; ADDRESS_FAMILY af; UINT16 remote_port; UINT16 local_port; UINT8 protocol; BOOLEAN is_allow; BOOLEAN is_loopback; BOOLEAN is_blocklist; BOOLEAN is_custom; BOOLEAN is_system; BOOLEAN is_myprovider; } ITEM_LOG, *PITEM_LOG; typedef struct _ITEM_STATUS { ULONG_PTR apps_count; ULONG_PTR apps_timer_count; ULONG_PTR apps_unused_count; ULONG_PTR rules_count; ULONG_PTR rules_global_count; ULONG_PTR rules_predefined_count; ULONG_PTR rules_user_count; } ITEM_STATUS, *PITEM_STATUS; typedef struct _ITEM_CONTEXT { HWND hwnd; INT listview_id; union { struct { PVOID base_address; LPARAM lparam; } DUMMYSTRUCTNAME; ULONG_PTR is_install; } DUMMYUNIONNAME; } ITEM_CONTEXT, *PITEM_CONTEXT; typedef struct _ITEM_COLOR { PR_STRING config_name; PR_STRING config_value; COLORREF default_clr; COLORREF new_clr; ULONG locale_id; BOOLEAN is_enabled; } ITEM_COLOR, *PITEM_COLOR; typedef struct _ITEM_ADDRESS { WCHAR range_start[LEN_IP_MAX]; WCHAR range_end[LEN_IP_MAX]; union { FWP_V4_ADDR_AND_MASK addr4; FWP_V6_ADDR_AND_MASK addr6; struct { FWP_RANGE range; UINT8 addr6_low[FWP_V6_ADDR_SIZE]; UINT8 addr6_high[FWP_V6_ADDR_SIZE]; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; UINT16 port; ENUM_TYPE_DATA type; NET_ADDRESS_FORMAT format; BOOLEAN is_range; } ITEM_ADDRESS, *PITEM_ADDRESS; typedef struct _ITEM_LOG_CALLBACK { union { const FWP_BYTE_ARRAY16 *remote_addr6; ULONG_PTR remote_addr4; } DUMMYUNIONNAME; union { const FWP_BYTE_ARRAY16 *local_addr6; ULONG_PTR local_addr4; } DUMMYUNIONNAME2; FILETIME timestamp; PUINT8 app_id; PSID package_id; PSID user_id; UINT64 filter_id; FWP_IP_VERSION version; UINT32 flags; UINT32 direction; UINT16 remote_port; UINT16 local_port; UINT16 layer_id; UINT8 protocol; BOOLEAN is_allow; BOOLEAN is_loopback; } ITEM_LOG_CALLBACK, *PITEM_LOG_CALLBACK; typedef struct _ITEM_TAB_CONTEXT { INT listview_id; INT locale_id; } ITEM_TAB_CONTEXT, *PITEM_TAB_CONTEXT; ================================================ FILE: src/messages.c ================================================ // simplewall // Copyright (c) 2021-2026 Henry++ #include "global.h" VOID _app_message_initialize ( _In_ HWND hwnd ) { ENUM_INSTALL_TYPE install_type; HMENU hmenu; LONG icon_size; LONG view_type; UINT menu_id; BOOLEAN is_enabled; install_type = _wfp_getinstalltype (); _r_tray_create (hwnd, &GUID_TrayIcon, RM_TRAYICON, NULL, NULL, FALSE); _app_settrayicon (hwnd, install_type); hmenu = GetMenu (hwnd); if (hmenu) { if (_r_config_getboolean (L"IsInternalRulesDisabled", FALSE, NULL)) _r_menu_enableitem (hmenu, 4, FALSE, FALSE); _r_menu_checkitem (hmenu, IDM_ALWAYSONTOP_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"AlwaysOnTop", FALSE, NULL)); _r_menu_checkitem (hmenu, IDM_AUTOSIZECOLUMNS_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"AutoSizeColumns", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_SHOWFILENAMESONLY_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"ShowFilenames", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_SHOWSEARCHBAR_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsShowSearchBar", TRUE, NULL)); view_type = _r_calc_clamp (_r_config_getlong (L"ViewType", LV_VIEW_DETAILS, NULL), LV_VIEW_ICON, LV_VIEW_MAX); if (view_type == LV_VIEW_ICON) { menu_id = IDM_VIEW_ICON; } else if (view_type == LV_VIEW_TILE) { menu_id = IDM_VIEW_TILE; } else { menu_id = IDM_VIEW_DETAILS; } _r_menu_checkitem (hmenu, IDM_VIEW_DETAILS, IDM_VIEW_TILE, MF_BYCOMMAND, menu_id); icon_size = _r_calc_clamp (_r_config_getlong (L"IconSize", SHIL_SMALL, NULL), SHIL_LARGE, SHIL_LAST); if (icon_size == SHIL_EXTRALARGE) { menu_id = IDM_SIZE_EXTRALARGE; } else if (icon_size == SHIL_LARGE) { menu_id = IDM_SIZE_LARGE; } else { menu_id = IDM_SIZE_SMALL; } _r_menu_checkitem (hmenu, IDM_SIZE_SMALL, IDM_SIZE_EXTRALARGE, MF_BYCOMMAND, menu_id); _r_menu_checkitem (hmenu, IDM_ICONSISHIDDEN, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsIconsHidden", FALSE, NULL)); _r_menu_checkitem (hmenu, IDM_USEDARKTHEME_CHK, 0, MF_BYCOMMAND, _r_theme_isenabled ()); _r_menu_checkitem (hmenu, IDM_LOADONSTARTUP_CHK, 0, MF_BYCOMMAND, _r_autorun_isenabled ()); _r_menu_checkitem (hmenu, IDM_STARTMINIMIZED_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsStartMinimized", FALSE, NULL)); _r_menu_checkitem (hmenu, IDM_SKIPUACWARNING_CHK, 0, MF_BYCOMMAND, _r_skipuac_isenabled ()); _r_menu_checkitem (hmenu, IDM_CHECKUPDATES_CHK, 0, MF_BYCOMMAND, _r_update_isenabled (FALSE)); _r_menu_checkitem (hmenu, IDM_RULE_BLOCKOUTBOUND, 0, MF_BYCOMMAND, _r_config_getboolean (L"BlockOutboundConnections", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_RULE_BLOCKINBOUND, 0, MF_BYCOMMAND, _r_config_getboolean (L"BlockInboundConnections", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_RULE_ALLOWLOOPBACK, 0, MF_BYCOMMAND, _r_config_getboolean (L"AllowLoopbackConnections", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_RULE_ALLOW6TO4, 0, MF_BYCOMMAND, _r_config_getboolean (L"AllowIPv6", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_RULE_ALLOWWINDOWSUPDATE, 0, MF_BYCOMMAND, _app_wufixenabled ()); if (!_r_sys_isosversiongreaterorequal (WINDOWS_10)) _r_menu_enableitem (hmenu, IDM_RULE_ALLOWWINDOWSUPDATE, FALSE, FALSE); _r_menu_checkitem (hmenu, IDM_PROFILETYPE_PLAIN, IDM_PROFILETYPE_ENCRYPTED, MF_BYCOMMAND, IDM_PROFILETYPE_PLAIN + _r_calc_clamp (_r_config_getlong (L"ProfileType", 0, NULL), 0, 2)); is_enabled = _r_config_getboolean (L"IsHashesEnabled", FALSE, NULL); _r_menu_checkitem (hmenu, IDM_USECERTIFICATES_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsCertificatesEnabled", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_KEEPUNUSED_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsKeepUnusedApps", TRUE, NULL)); _r_menu_checkitem (hmenu, IDM_USEHASHES_CHK, 0, MF_BYCOMMAND, is_enabled); _r_menu_checkitem (hmenu, IDM_USENETWORKRESOLUTION_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE, NULL)); _r_menu_checkitem (hmenu, IDM_USEAPPMONITOR_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsEnableAppMonitor", FALSE, NULL)); _r_menu_enableitem (hmenu, IDM_USEAPPMONITOR_CHK, FALSE, is_enabled); _r_menu_checkitem ( hmenu, IDM_BLOCKLIST_SPY_DISABLE, IDM_BLOCKLIST_SPY_BLOCK, MF_BYCOMMAND, IDM_BLOCKLIST_SPY_DISABLE + _r_calc_clamp (_r_config_getlong (L"BlocklistSpyState", 2, NULL), 0, 2) ); _r_menu_checkitem ( hmenu, IDM_BLOCKLIST_UPDATE_DISABLE, IDM_BLOCKLIST_UPDATE_BLOCK, MF_BYCOMMAND, IDM_BLOCKLIST_UPDATE_DISABLE + _r_calc_clamp (_r_config_getlong (L"BlocklistUpdateState", 0, NULL), 0, 2) ); _r_menu_checkitem ( hmenu, IDM_BLOCKLIST_EXTRA_DISABLE, IDM_BLOCKLIST_EXTRA_BLOCK, MF_BYCOMMAND, IDM_BLOCKLIST_EXTRA_DISABLE + _r_calc_clamp (_r_config_getlong (L"BlocklistExtraState", 0, NULL), 0, 2) ); } _r_toolbar_setbutton ( config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLENOTIFICATIONS_CHK, NULL, 0, _r_config_getboolean (L"IsNotificationsEnabled", TRUE, NULL) ? TBSTATE_PRESSED | TBSTATE_ENABLED : TBSTATE_ENABLED, I_IMAGENONE ); _r_toolbar_setbutton ( config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLELOG_CHK, NULL, 0, _r_config_getboolean (L"IsLogEnabled", FALSE, NULL) ? TBSTATE_PRESSED | TBSTATE_ENABLED : TBSTATE_ENABLED, I_IMAGENONE ); _r_toolbar_setbutton ( config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLEUILOG_CHK, NULL, 0, _r_config_getboolean (L"IsLogUiEnabled", FALSE, NULL) ? TBSTATE_PRESSED | TBSTATE_ENABLED : TBSTATE_ENABLED, I_IMAGENONE ); } VOID _app_message_localize ( _In_ HWND hwnd ) { PITEM_TAB_CONTEXT tab_context; PR_STRING localized_string = NULL; LPCWSTR recommended_string; HMENU hmenu; HMENU hsubmenu; LONG dpi_value; hmenu = GetMenu (hwnd); dpi_value = _r_dc_getwindowdpi (hwnd); if (hmenu) { _r_menu_setitemtext (hmenu, 0, TRUE, _r_locale_getstring (IDS_FILE)); _r_menu_setitemtext (hmenu, 1, TRUE, _r_locale_getstring (IDS_EDIT)); _r_menu_setitemtext (hmenu, 2, TRUE, _r_locale_getstring (IDS_VIEW)); _r_menu_setitemtext (hmenu, 3, TRUE, _r_locale_getstring (IDS_SETTINGS)); _r_menu_setitemtext (hmenu, 4, TRUE, _r_locale_getstring (IDS_TRAY_BLOCKLIST_RULES)); _r_menu_setitemtext (hmenu, 5, TRUE, _r_locale_getstring (IDS_HELP)); // file submenu _r_menu_setitemtextformat ( hmenu, IDM_SETTINGS, FALSE, L"%s...\tF2", _r_locale_getstring (IDS_SETTINGS) ); _r_menu_setitemtextformat ( hmenu, IDM_ADD_FILE, FALSE, L"%s...", _r_locale_getstring (IDS_ADD_FILE) ); _r_menu_setitemtextformat ( hmenu, IDM_IMPORT, FALSE, L"%s...\tCtrl+O", _r_locale_getstring (IDS_IMPORT) ); _r_menu_setitemtextformat ( hmenu, IDM_EXPORT, FALSE, L"%s...\tCtrl+S", _r_locale_getstring (IDS_EXPORT) ); _r_menu_setitemtextformat ( hmenu, IDM_EXIT, FALSE, _r_locale_getstring (IDS_EXIT) ); // edit submenu _r_menu_setitemtextformat ( hmenu, IDM_PURGE_UNUSED, FALSE, L"%s\tCtrl+Shift+X", _r_locale_getstring (IDS_PURGE_UNUSED) ); _r_menu_setitemtextformat ( hmenu, IDM_PURGE_TIMERS, FALSE, L"%s\tCtrl+Shift+T", _r_locale_getstring (IDS_PURGE_TIMERS) ); _r_menu_setitemtextformat ( hmenu, IDM_LOGCLEAR, FALSE, L"%s\tCtrl+X", _r_locale_getstring (IDS_LOGCLEAR) ); _r_menu_setitemtextformat ( hmenu, IDM_REFRESH, FALSE, L"%s\tF5", _r_locale_getstring (IDS_REFRESH) ); // view submenu _r_menu_setitemtext (hmenu, IDM_ALWAYSONTOP_CHK, FALSE, _r_locale_getstring (IDS_ALWAYSONTOP_CHK)); _r_menu_setitemtext (hmenu, IDM_AUTOSIZECOLUMNS_CHK, FALSE, _r_locale_getstring (IDS_AUTOSIZECOLUMNS_CHK)); _r_menu_setitemtext (hmenu, IDM_SHOWFILENAMESONLY_CHK, FALSE, _r_locale_getstring (IDS_SHOWFILENAMESONLY_CHK)); _r_menu_setitemtext (hmenu, IDM_SHOWSEARCHBAR_CHK, FALSE, _r_locale_getstring (IDS_SHOWSEARCHBAR_CHK)); _r_menu_setitemtext (hmenu, IDM_SIZE_SMALL, FALSE, _r_locale_getstring (IDS_ICONSSMALL)); _r_menu_setitemtext (hmenu, IDM_SIZE_LARGE, FALSE, _r_locale_getstring (IDS_ICONSLARGE)); _r_menu_setitemtext (hmenu, IDM_SIZE_EXTRALARGE, FALSE, _r_locale_getstring (IDS_ICONSEXTRALARGE)); _r_menu_setitemtext (hmenu, IDM_VIEW_DETAILS, FALSE, _r_locale_getstring (IDS_VIEW_DETAILS)); _r_menu_setitemtext (hmenu, IDM_VIEW_ICON, FALSE, _r_locale_getstring (IDS_VIEW_ICON)); _r_menu_setitemtext (hmenu, IDM_VIEW_TILE, FALSE, _r_locale_getstring (IDS_VIEW_TILE)); _r_menu_setitemtext (hmenu, IDM_ICONSISHIDDEN, FALSE, _r_locale_getstring (IDS_ICONSISHIDDEN)); _r_menu_setitemtext (hmenu, IDM_USEDARKTHEME_CHK, FALSE, _r_locale_getstring (IDS_USEDARKTHEME)); hsubmenu = GetSubMenu (hmenu, 2); if (hsubmenu) { _r_menu_setitemtext (hsubmenu, ICONS_MENU, TRUE, _r_locale_getstring (IDS_ICONS)); _r_menu_setitemtextformat ( hsubmenu, LANG_MENU, TRUE, L"%s (Language)", _r_locale_getstring (IDS_LANGUAGE) ); _r_locale_enum (hsubmenu, LANG_MENU, IDX_LANGUAGE); // enum localizations } _r_menu_setitemtextformat (hmenu, IDM_FONT, FALSE, L"%s...", _r_locale_getstring (IDS_FONT)); // settings submenu _r_menu_setitemtext (hmenu, IDM_LOADONSTARTUP_CHK, FALSE, _r_locale_getstring (IDS_LOADONSTARTUP_CHK)); _r_menu_setitemtext (hmenu, IDM_STARTMINIMIZED_CHK, FALSE, _r_locale_getstring (IDS_STARTMINIMIZED_CHK)); _r_menu_setitemtext (hmenu, IDM_SKIPUACWARNING_CHK, FALSE, _r_locale_getstring (IDS_SKIPUACWARNING_CHK)); _r_menu_setitemtext (hmenu, IDM_CHECKUPDATES_CHK, FALSE, _r_locale_getstring (IDS_CHECKUPDATES_CHK)); _r_menu_setitemtext (hmenu, IDM_RULE_BLOCKOUTBOUND, FALSE, _r_locale_getstring (IDS_RULE_BLOCKOUTBOUND)); _r_menu_setitemtext (hmenu, IDM_RULE_BLOCKINBOUND, FALSE, _r_locale_getstring (IDS_RULE_BLOCKINBOUND)); _r_menu_setitemtext (hmenu, IDM_RULE_ALLOWLOOPBACK, FALSE, _r_locale_getstring (IDS_RULE_ALLOWLOOPBACK)); _r_menu_setitemtext (hmenu, IDM_RULE_ALLOW6TO4, FALSE, _r_locale_getstring (IDS_RULE_ALLOW6TO4)); _r_menu_setitemtext (hmenu, IDM_RULE_ALLOWWINDOWSUPDATE, FALSE, _r_locale_getstring (IDS_RULE_ALLOWWINDOWSUPDATE)); _r_menu_setitemtext (hmenu, IDM_PROFILETYPE_PLAIN, FALSE, _r_locale_getstring (IDS_PROFILE_TYPE_PLAIN)); _r_menu_setitemtext (hmenu, IDM_PROFILETYPE_COMPRESSED, FALSE, _r_locale_getstring (IDS_PROFILE_TYPE_COMPRESSED)); _r_menu_setitemtext (hmenu, IDM_PROFILETYPE_ENCRYPTED, FALSE, _r_locale_getstring (IDS_PROFILE_TYPE_ENCRYPTED)); _r_menu_setitemtext (hmenu, IDM_USENETWORKRESOLUTION_CHK, FALSE, _r_locale_getstring (IDS_USENETWORKRESOLUTION_CHK)); _r_menu_setitemtext (hmenu, IDM_USECERTIFICATES_CHK, FALSE, _r_locale_getstring (IDS_USECERTIFICATES_CHK)); _r_menu_setitemtext (hmenu, IDM_KEEPUNUSED_CHK, FALSE, _r_locale_getstring (IDS_KEEPUNUSED_CHK)); _r_menu_setitemtext (hmenu, IDM_USEHASHES_CHK, FALSE, _r_locale_getstring (IDS_USEHASHES_CHK)); _r_menu_setitemtext (hmenu, IDM_USEAPPMONITOR_CHK, FALSE, _r_locale_getstring (IDS_USEAPPMONITOR_CHK)); hsubmenu = GetSubMenu (hmenu, 3); if (hsubmenu) { _r_menu_setitemtext (hsubmenu, 5, TRUE, _r_locale_getstring (IDS_TRAY_RULES)); _r_menu_setitemtext (hsubmenu, 6, TRUE, _r_locale_getstring (IDS_PROFILE_TYPE)); } recommended_string = _r_locale_getstring (IDS_RECOMMENDED); // blocklist submenu _r_menu_setitemtext (hmenu, IDM_BLOCKLIST_SPY_DISABLE, FALSE, _r_locale_getstring (IDS_DISABLE)); _r_menu_setitemtext (hmenu, IDM_BLOCKLIST_SPY_ALLOW, FALSE, _r_locale_getstring (IDS_ACTION_ALLOW)); _r_menu_setitemtextformat (hmenu, IDM_BLOCKLIST_SPY_BLOCK, FALSE, L"%s (%s)", _r_locale_getstring (IDS_ACTION_BLOCK), recommended_string); _r_menu_setitemtextformat (hmenu, IDM_BLOCKLIST_UPDATE_DISABLE, FALSE, L"%s (%s)", _r_locale_getstring (IDS_DISABLE), recommended_string); _r_menu_setitemtext (hmenu, IDM_BLOCKLIST_UPDATE_ALLOW, FALSE, _r_locale_getstring (IDS_ACTION_ALLOW)); _r_menu_setitemtext (hmenu, IDM_BLOCKLIST_UPDATE_BLOCK, FALSE, _r_locale_getstring (IDS_ACTION_BLOCK)); _r_menu_setitemtextformat (hmenu, IDM_BLOCKLIST_EXTRA_DISABLE, FALSE, L"%s (%s)", _r_locale_getstring (IDS_DISABLE), recommended_string); _r_menu_setitemtext (hmenu, IDM_BLOCKLIST_EXTRA_ALLOW, FALSE, _r_locale_getstring (IDS_ACTION_ALLOW)); _r_menu_setitemtext (hmenu, IDM_BLOCKLIST_EXTRA_BLOCK, FALSE, _r_locale_getstring (IDS_ACTION_BLOCK)); hsubmenu = GetSubMenu (hmenu, 4); if (hsubmenu) { _r_menu_setitemtext (hsubmenu, 0, TRUE, _r_locale_getstring (IDS_BLOCKLIST_SPY)); _r_menu_setitemtext (hsubmenu, 1, TRUE, _r_locale_getstring (IDS_BLOCKLIST_UPDATE)); _r_menu_setitemtext (hsubmenu, 2, TRUE, _r_locale_getstring (IDS_BLOCKLIST_EXTRA)); } // help submenu _r_menu_setitemtext (hmenu, IDM_WEBSITE, FALSE, _r_locale_getstring (IDS_WEBSITE)); _r_menu_setitemtext (hmenu, IDM_CHECKUPDATES, FALSE, _r_locale_getstring (IDS_CHECKUPDATES)); _r_menu_setitemtextformat (hmenu, IDM_ABOUT, FALSE, L"%s\tF1", _r_locale_getstring (IDS_ABOUT)); } // localize toolbar _app_setinterfacestate (hwnd, dpi_value); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_REFRESH, _r_locale_getstring (IDS_REFRESH), BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_SETTINGS, _r_locale_getstring (IDS_SETTINGS), BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s...", _r_locale_getstring (IDS_OPENRULESEDITOR))); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_OPENRULESEDITOR, localized_string->buffer, BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLENOTIFICATIONS_CHK, _r_locale_getstring (IDS_ENABLENOTIFICATIONS_CHK), BTNS_CHECK | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLELOG_CHK, _r_locale_getstring (IDS_ENABLELOG_CHK), BTNS_CHECK | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_ENABLEUILOG_CHK), _r_locale_getstring (IDS_SESSION_ONLY))); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLEUILOG_CHK, localized_string->buffer, BTNS_CHECK | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (Ctrl+I)", _r_locale_getstring (IDS_LOGSHOW))); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_LOGSHOW, localized_string->buffer, BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (Ctrl+X)", _r_locale_getstring (IDS_LOGCLEAR))); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_LOGCLEAR, localized_string->buffer, BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_DONATE, _r_locale_getstring (IDS_DONATE), BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s... (Ctrl+F)", _r_locale_getstring (IDS_FIND))); _r_edit_setcuebanner (config.hrebar, IDC_SEARCH, localized_string->buffer); // set rebar size _app_toolbar_resize (hwnd, dpi_value); // localize tabs for (INT i = 0; i < _r_tab_getitemcount (hwnd, IDC_TAB); i++) { tab_context = _app_listview_getcontext (hwnd, i); if (!tab_context) continue; _r_tab_setitem (hwnd, IDC_TAB, i, _r_locale_getstring (tab_context->locale_id), I_DEFAULT, I_DEFAULT); switch (tab_context->listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: { _r_listview_setcolumn (hwnd, tab_context->listview_id, 0, _r_locale_getstring (IDS_NAME), 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 1, _r_locale_getstring (IDS_ADDED), 0); break; } case IDC_RULES_BLOCKLIST: case IDC_RULES_SYSTEM: case IDC_RULES_CUSTOM: { _r_listview_setcolumn (hwnd, tab_context->listview_id, 0, _r_locale_getstring (IDS_NAME), 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 1, _r_locale_getstring (IDS_PROTOCOL), 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 2, _r_locale_getstring (IDS_DIRECTION), 0); break; } case IDC_NETWORK: { _r_listview_setcolumn (hwnd, tab_context->listview_id, 0, _r_locale_getstring (IDS_NAME), 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_ADDRESS), _r_locale_getstring (IDS_DIRECTION_LOCAL))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 1, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_HOST), _r_locale_getstring (IDS_DIRECTION_LOCAL))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 2, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_PORT), _r_locale_getstring (IDS_DIRECTION_LOCAL))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 3, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_ADDRESS), _r_locale_getstring (IDS_DIRECTION_REMOTE))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 4, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_HOST), _r_locale_getstring (IDS_DIRECTION_REMOTE))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 5, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_PORT), _r_locale_getstring (IDS_DIRECTION_REMOTE))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 6, localized_string->buffer, 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 7, _r_locale_getstring (IDS_PROTOCOL), 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 8, _r_locale_getstring (IDS_STATE), 0); break; } case IDC_LOG: { _r_listview_setcolumn (hwnd, tab_context->listview_id, 1, _r_locale_getstring (IDS_NAME), 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 2, _r_locale_getstring (IDS_DATE), 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_ADDRESS), _r_locale_getstring (IDS_DIRECTION_LOCAL))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 3, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_HOST), _r_locale_getstring (IDS_DIRECTION_LOCAL))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 4, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_PORT), _r_locale_getstring (IDS_DIRECTION_LOCAL))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 5, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_ADDRESS), _r_locale_getstring (IDS_DIRECTION_REMOTE))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 6, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_HOST), _r_locale_getstring (IDS_DIRECTION_REMOTE))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 7, localized_string->buffer, 0); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_format_string (L"%s (%s)", _r_locale_getstring (IDS_PORT), _r_locale_getstring (IDS_DIRECTION_REMOTE))); _r_listview_setcolumn (hwnd, tab_context->listview_id, 8, localized_string->buffer, 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 9, _r_locale_getstring (IDS_PROTOCOL), 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 10, _r_locale_getstring (IDS_DIRECTION), 0); _r_listview_setcolumn (hwnd, tab_context->listview_id, 11, _r_locale_getstring (IDS_FILTER), 0); break; } } } _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE | PR_UPDATE_FORCE); if (localized_string) _r_obj_dereference (localized_string); } VOID _app_message_uninitialize ( _In_ HWND hwnd ) { _r_tray_destroy (hwnd, &GUID_TrayIcon); } VOID _app_generate_appmenu ( _In_ HMENU hmenu, _In_opt_ HMENU hsubmenu_rules, _In_opt_ HMENU hsubmenu_timers, _In_ ULONG app_hash ) { _r_menu_addseparator (hmenu); // show rules if (hsubmenu_rules) { _r_menu_addsubmenu (hmenu, INT_ERROR, hsubmenu_rules, _r_locale_getstring (IDS_TRAY_RULES)); _r_menu_additem (hsubmenu_rules, IDM_DISABLENOTIFICATIONS, _r_locale_getstring (IDS_DISABLENOTIFICATIONS)); _r_menu_additem (hsubmenu_rules, IDM_DISABLEREMOVAL, _r_locale_getstring (IDS_DISABLEREMOVAL)); if (_app_isdisabledremoval (app_hash)) _r_menu_enableitem (hsubmenu_rules, IDM_DISABLEREMOVAL, FALSE, FALSE); _r_menu_addseparator (hsubmenu_rules); _app_generate_rulescontrol (hsubmenu_rules, app_hash, NULL); } // show timers if (hsubmenu_timers) { _r_menu_addsubmenu (hmenu, INT_ERROR, hsubmenu_timers, _r_locale_getstring (IDS_TIMER)); _r_menu_additem (hsubmenu_timers, IDM_DISABLETIMER, _r_locale_getstring (IDS_DISABLETIMER)); _r_menu_addseparator (hsubmenu_timers); _app_generate_timerscontrol (hsubmenu_timers, app_hash); } _r_menu_addseparator (hmenu); } VOID _app_message_contextmenu ( _In_ HWND hwnd, _In_ LPNMITEMACTIVATE lpnmlv ) { PR_STRING localized_string = NULL; PR_STRING column_text = NULL; HMENU hsubmenu_timers = NULL; HMENU hsubmenu_rules = NULL; HMENU hmenu; PITEM_NETWORK ptr_network; PITEM_APP ptr_app = NULL; ULONG hash_code; ULONG app_hash; INT listview_id; INT command_id; BOOLEAN is_readonly = FALSE; BOOLEAN is_checked = FALSE; if (lpnmlv->iItem == INT_ERROR) return; listview_id = (INT)(INT_PTR)lpnmlv->hdr.idFrom; if (!(listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG)) return; hmenu = CreatePopupMenu (); if (!hmenu) return; app_hash = _app_listview_getappcontext (hwnd, listview_id, lpnmlv->iItem); switch (listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: { ptr_app = _app_getappitem (app_hash); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_EDIT2), L"...\tEnter")); _r_menu_additem_ex (hmenu, IDM_PROPERTIES, localized_string->buffer, MF_DEFAULT); hsubmenu_rules = CreatePopupMenu (); hsubmenu_timers = CreatePopupMenu (); _app_generate_appmenu (hmenu, hsubmenu_rules, hsubmenu_timers, app_hash); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_EXPLORE), L"\tCtrl+E")); _r_menu_additem (hmenu, IDM_EXPLORE, localized_string->buffer); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_DELETE), L"\tDel")); _r_menu_additem (hmenu, IDM_DELETE, localized_string->buffer); _r_menu_addseparator (hmenu); _r_menu_additem (hmenu, IDM_CHECK, _r_locale_getstring (IDS_CHECK)); _r_menu_additem (hmenu, IDM_UNCHECK, _r_locale_getstring (IDS_UNCHECK)); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_SELECT_ALL), L"\tCtrl+A")); _r_menu_additem (hmenu, IDM_SELECT_ALL, localized_string->buffer); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_COPY), L"\tCtrl+C")); _r_menu_additem (hmenu, IDM_COPY, localized_string->buffer); column_text = _r_listview_getcolumntext (hwnd, listview_id, lpnmlv->iSubItem); if (column_text) { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (4, _r_locale_getstring (IDS_COPY), L" \"", column_text->buffer, L"\"")); _r_menu_additem (hmenu, IDM_COPY_VALUE, localized_string->buffer); _r_obj_dereference (column_text); } if (ptr_app) { if (_app_getappinfo (ptr_app, INFO_IS_SILENT, &is_checked, sizeof (BOOLEAN))) { if (is_checked) _r_menu_checkitem (hmenu, IDM_DISABLENOTIFICATIONS, 0, MF_BYCOMMAND, is_checked); } if (_app_getappinfo (ptr_app, INFO_IS_UNDELETABLE, &is_checked, sizeof (BOOLEAN))) { if (is_checked) { _r_menu_checkitem (hmenu, IDM_DISABLEREMOVAL, 0, MF_BYCOMMAND, is_checked); _r_menu_enableitem (hmenu, IDM_DELETE, FALSE, FALSE); } } } break; } case IDC_RULES_BLOCKLIST: case IDC_RULES_SYSTEM: case IDC_RULES_CUSTOM: { if (listview_id == IDC_RULES_CUSTOM) { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_ADD), L"...")); _r_menu_additem (hmenu, IDM_OPENRULESEDITOR, localized_string->buffer); } _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_EDIT2), L"...\tEnter")); _r_menu_additem_ex (hmenu, IDM_PROPERTIES, localized_string->buffer, MF_DEFAULT); if (listview_id == IDC_RULES_CUSTOM) { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_DELETE), L"\tDel")); _r_menu_additem (hmenu, IDM_DELETE, localized_string->buffer); hash_code = (ULONG)_app_listview_getitemcontext (hwnd, listview_id, lpnmlv->iItem); if (_app_getruleinfobyid (hash_code, INFO_IS_READONLY, &is_readonly, sizeof (BOOLEAN))) { if (is_readonly) _r_menu_enableitem (hmenu, IDM_DELETE, FALSE, FALSE); } } _r_menu_addseparator (hmenu); _r_menu_additem (hmenu, IDM_CHECK, _r_locale_getstring (IDS_CHECK)); _r_menu_additem (hmenu, IDM_UNCHECK, _r_locale_getstring (IDS_UNCHECK)); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_SELECT_ALL), L"\tCtrl+A")); _r_menu_additem (hmenu, IDM_SELECT_ALL, localized_string->buffer); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_COPY), L"\tCtrl+C")); _r_menu_additem (hmenu, IDM_COPY, localized_string->buffer); column_text = _r_listview_getcolumntext (hwnd, listview_id, lpnmlv->iSubItem); if (column_text) { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (4, _r_locale_getstring (IDS_COPY), L" \"", column_text->buffer, L"\"")); _r_menu_additem (hmenu, IDM_COPY_VALUE, localized_string->buffer); _r_obj_dereference (column_text); } break; } case IDC_NETWORK: { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_SHOWINLIST), L"\tEnter")); _r_menu_additem_ex (hmenu, IDM_PROPERTIES, localized_string->buffer, MF_DEFAULT); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_OPENRULESEDITOR), L"...")); _r_menu_additem (hmenu, IDM_OPENRULESEDITOR, localized_string->buffer); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_EXPLORE), L"\tCtrl+E")); _r_menu_additem (hmenu, IDM_EXPLORE, localized_string->buffer); _r_menu_additem (hmenu, IDM_DELETE, _r_locale_getstring (IDS_NETWORK_CLOSE)); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_SELECT_ALL), L"\tCtrl+A")); _r_menu_additem (hmenu, IDM_SELECT_ALL, localized_string->buffer); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_COPY), L"\tCtrl+C")); _r_menu_additem (hmenu, IDM_COPY, localized_string->buffer); column_text = _r_listview_getcolumntext (hwnd, listview_id, lpnmlv->iSubItem); if (column_text) { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (4, _r_locale_getstring (IDS_COPY), L" \"", column_text->buffer, L"\"")); _r_menu_additem (hmenu, IDM_COPY_VALUE, localized_string->buffer); _r_obj_dereference (column_text); } hash_code = (ULONG)_app_listview_getitemcontext (hwnd, listview_id, lpnmlv->iItem); ptr_network = _app_network_getitem (hash_code); if (ptr_network) { if (ptr_network->af != AF_INET || ptr_network->state != MIB_TCP_STATE_ESTAB) _r_menu_enableitem (hmenu, IDM_DELETE, FALSE, FALSE); _r_obj_dereference (ptr_network); } break; } case IDC_LOG: { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_SHOWINLIST), L"\tEnter")); _r_menu_additem_ex (hmenu, IDM_PROPERTIES, localized_string->buffer, MF_DEFAULT); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_OPENRULESEDITOR), L"...")); _r_menu_additem (hmenu, IDM_OPENRULESEDITOR, localized_string->buffer); hsubmenu_rules = CreatePopupMenu (); hsubmenu_timers = CreatePopupMenu (); _app_generate_appmenu (hmenu, hsubmenu_rules, hsubmenu_timers, app_hash); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_EXPLORE), L"\tCtrl+E")); _r_menu_additem (hmenu, IDM_EXPLORE, localized_string->buffer); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_LOGCLEAR), L"\tCtrl+X")); _r_menu_additem (hmenu, IDM_TRAY_LOGCLEAR, localized_string->buffer); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_SELECT_ALL), L"\tCtrl+A")); _r_menu_additem (hmenu, IDM_SELECT_ALL, localized_string->buffer); _r_menu_addseparator (hmenu); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_COPY), L"\tCtrl+C")); _r_menu_additem (hmenu, IDM_COPY, localized_string->buffer); column_text = _r_listview_getcolumntext (hwnd, listview_id, lpnmlv->iSubItem); if (column_text) { _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (4, _r_locale_getstring (IDS_COPY), L" \"", column_text->buffer, L"\"")); _r_menu_additem (hmenu, IDM_COPY_VALUE, localized_string->buffer); _r_obj_dereference (column_text); } ptr_app = _app_getappitem (app_hash); if (ptr_app) { if (_app_getappinfo (ptr_app, INFO_IS_SILENT, &is_checked, sizeof (BOOLEAN))) { if (is_checked) _r_menu_checkitem (hmenu, IDM_DISABLENOTIFICATIONS, 0, MF_BYCOMMAND, is_checked); } if (_app_getappinfo (ptr_app, INFO_IS_UNDELETABLE, &is_checked, sizeof (BOOLEAN))) { if (is_checked) _r_menu_checkitem (hmenu, IDM_DISABLEREMOVAL, 0, MF_BYCOMMAND, is_checked); } } break; } } command_id = _r_menu_popup (hmenu, hwnd, NULL, FALSE); if (command_id) _r_ctrl_sendcommand (hwnd, command_id, (LPARAM)lpnmlv->iSubItem); if (hsubmenu_rules) DestroyMenu (hsubmenu_rules); if (hsubmenu_timers) DestroyMenu (hsubmenu_timers); DestroyMenu (hmenu); if (localized_string) _r_obj_dereference (localized_string); if (ptr_app) _r_obj_dereference (ptr_app); } VOID _app_message_contextmenu_columns ( _In_ HWND hwnd, _In_ LPNMHDR nmlp ) { PR_STRING column_text; HWND hlistview; HMENU hmenu; INT listview_id; hlistview = GetParent (nmlp->hwndFrom); if (!hlistview) return; listview_id = GetDlgCtrlID (hlistview); if (!(listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG)) return; hmenu = CreatePopupMenu (); if (!hmenu) return; for (INT i = 0; i < _r_listview_getcolumncount (hwnd, listview_id); i++) { column_text = _r_listview_getcolumntext (hwnd, listview_id, i); if (column_text) { _r_menu_additem (hmenu, IDX_COLUMN + i, column_text->buffer); _r_menu_checkitem (hmenu, IDX_COLUMN + i, 0, MF_BYCOMMAND, TRUE); _r_obj_dereference (column_text); } } _r_menu_popup (hmenu, hwnd, NULL, TRUE); DestroyMenu (hmenu); } VOID _app_message_traycontextmenu ( _In_ HWND hwnd ) { ENUM_INSTALL_TYPE install_type; HMENU hsubmenu; HMENU hmenu; hmenu = LoadMenuW (NULL, MAKEINTRESOURCE (IDM_TRAY)); if (!hmenu) return; hsubmenu = GetSubMenu (hmenu, 0); if (!hsubmenu) { DestroyMenu (hmenu); return; } install_type = _wfp_getinstalltype (); _r_menu_setitembitmap (hsubmenu, IDM_TRAY_START, FALSE, _app_getstatebitmap (install_type)); // localize _r_menu_setitemtext (hsubmenu, IDM_TRAY_SHOW, FALSE, _r_locale_getstring (IDS_TRAY_SHOW)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_START, FALSE, _app_getstateaction (install_type)); _r_menu_setitemtext (hsubmenu, NOTIFICATIONS_ID, TRUE, _r_locale_getstring (IDS_TITLE_NOTIFICATIONS)); _r_menu_setitemtext (hsubmenu, LOGGING_ID, TRUE, _r_locale_getstring (IDS_TITLE_LOGGING)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_ENABLENOTIFICATIONS_CHK, FALSE, _r_locale_getstring (IDS_ENABLENOTIFICATIONS_CHK)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_ENABLENOTIFICATIONSSOUND_CHK, FALSE, _r_locale_getstring (IDS_NOTIFICATIONSOUND_CHK)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_NOTIFICATIONFULLSCREENSILENTMODE_CHK, FALSE, _r_locale_getstring (IDS_NOTIFICATIONFULLSCREENSILENTMODE_CHK)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_NOTIFICATIONONTRAY_CHK, FALSE, _r_locale_getstring (IDS_NOTIFICATIONONTRAY_CHK)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_ENABLELOG_CHK, FALSE, _r_locale_getstring (IDS_ENABLELOG_CHK)); _r_menu_setitemtextformat (hsubmenu, IDM_TRAY_ENABLEUILOG_CHK, FALSE, L"%s (%s)", _r_locale_getstring (IDS_ENABLEUILOG_CHK), _r_locale_getstring (IDS_SESSION_ONLY)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_LOGSHOW, FALSE, _r_locale_getstring (IDS_LOGSHOW)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_LOGCLEAR, FALSE, _r_locale_getstring (IDS_LOGCLEAR)); if (_r_fs_isexists (&_r_app_getlogpath ()->sr)) { _r_menu_setitemtext (hsubmenu, ERRLOG_ID, TRUE, _r_locale_getstring (IDS_TRAY_LOGERR)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_LOGSHOW_ERR, FALSE, _r_locale_getstring (IDS_LOGSHOW)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_LOGCLEAR_ERR, FALSE, _r_locale_getstring (IDS_LOGCLEAR)); } else { DeleteMenu (hsubmenu, ERRLOG_ID, MF_BYPOSITION); } _r_menu_setitemtextformat (hsubmenu, IDM_TRAY_SETTINGS, FALSE, L"%s...", _r_locale_getstring (IDS_SETTINGS)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_WEBSITE, FALSE, _r_locale_getstring (IDS_WEBSITE)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_ABOUT, FALSE, _r_locale_getstring (IDS_ABOUT)); _r_menu_setitemtext (hsubmenu, IDM_TRAY_EXIT, FALSE, _r_locale_getstring (IDS_EXIT)); _r_menu_checkitem (hsubmenu, IDM_TRAY_ENABLENOTIFICATIONS_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsNotificationsEnabled", TRUE, NULL)); _r_menu_checkitem (hsubmenu, IDM_TRAY_ENABLENOTIFICATIONSSOUND_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsNotificationsSound", TRUE, NULL)); _r_menu_checkitem (hsubmenu, IDM_TRAY_NOTIFICATIONFULLSCREENSILENTMODE_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsNotificationsFullscreenSilentMode", TRUE, NULL)); _r_menu_checkitem (hsubmenu, IDM_TRAY_NOTIFICATIONONTRAY_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsNotificationsOnTray", FALSE, NULL)); _r_menu_checkitem (hsubmenu, IDM_TRAY_ENABLELOG_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsLogEnabled", FALSE, NULL)); _r_menu_checkitem (hsubmenu, IDM_TRAY_ENABLEUILOG_CHK, 0, MF_BYCOMMAND, _r_config_getboolean (L"IsLogUiEnabled", FALSE, NULL)); if (!_r_config_getboolean (L"IsNotificationsEnabled", TRUE, NULL)) { _r_menu_enableitem (hsubmenu, IDM_TRAY_ENABLENOTIFICATIONSSOUND_CHK, FALSE, FALSE); _r_menu_enableitem (hsubmenu, IDM_TRAY_NOTIFICATIONFULLSCREENSILENTMODE_CHK, FALSE, FALSE); _r_menu_enableitem (hsubmenu, IDM_TRAY_NOTIFICATIONONTRAY_CHK, FALSE, FALSE); } else if (!_r_config_getboolean (L"IsNotificationsSound", TRUE, NULL)) { _r_menu_enableitem (hsubmenu, IDM_TRAY_NOTIFICATIONFULLSCREENSILENTMODE_CHK, FALSE, FALSE); } if (_wfp_isfiltersapplying ()) _r_menu_enableitem (hsubmenu, IDM_TRAY_START, FALSE, FALSE); SetForegroundWindow (hwnd); // don't touch _r_menu_popup (hsubmenu, hwnd, NULL, TRUE); DestroyMenu (hmenu); } VOID _app_message_dpichanged ( _In_ HWND hwnd, _In_ LONG dpi_value ) { PR_STRING localized_string = NULL; _app_windowloadfont (dpi_value); _app_imagelist_init (hwnd, dpi_value); // reset toolbar information _app_setinterfacestate (hwnd, dpi_value); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_REFRESH, _r_locale_getstring (IDS_REFRESH), BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_SETTINGS, _r_locale_getstring (IDS_SETTINGS), BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_OPENRULESEDITOR), L"...")); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_OPENRULESEDITOR, localized_string->buffer, BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLENOTIFICATIONS_CHK, _r_locale_getstring (IDS_ENABLENOTIFICATIONS_CHK), BTNS_CHECK | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLELOG_CHK, _r_locale_getstring (IDS_ENABLELOG_CHK), BTNS_CHECK | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_ENABLEUILOG_CHK, _r_locale_getstring (IDS_ENABLEUILOG_CHK), BTNS_CHECK | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_LOGSHOW), L" (Ctrl+I)")); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_LOGSHOW, localized_string->buffer, BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_LOGCLEAR), L" (Ctrl+X)")); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_TRAY_LOGCLEAR, localized_string->buffer, BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _r_toolbar_setbutton (config.hrebar, IDC_TOOLBAR, IDM_DONATE, _r_locale_getstring (IDS_DONATE), BTNS_BUTTON | BTNS_AUTOSIZE, 0, I_IMAGENONE); _app_listview_loadfont (dpi_value, TRUE); _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE | PR_UPDATE_FORCE); _r_wnd_sendmessage (hwnd, 0, WM_SIZE, 0, 0); _r_obj_dereference (localized_string); } LONG_PTR _app_message_custdraw ( _In_ HWND hwnd, _In_ LPNMLVCUSTOMDRAW lpnmlv ) { PR_STRING real_path = NULL; PITEM_NETWORK ptr_network; PITEM_COLOR ptr_clr; PITEM_LOG ptr_log; COLORREF new_clr = 0; ULONG app_hash = 0; ULONG index; INT listview_id; BOOLEAN is_validconnection = FALSE; BOOLEAN is_systemapp = FALSE; switch (lpnmlv->nmcd.dwDrawStage) { case CDDS_PREPAINT: { return CDRF_NOTIFYITEMDRAW; } case CDDS_ITEMPREPAINT: { listview_id = (INT)(INT_PTR)lpnmlv->nmcd.hdr.idFrom; if (lpnmlv->dwItemType != LVCDI_ITEM) return CDRF_DODEFAULT; if (!lpnmlv->nmcd.lItemlParam) return CDRF_DODEFAULT; if (!_r_config_getboolean (L"IsEnableHighlighting", TRUE, NULL)) return CDRF_DODEFAULT; switch (listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: case IDC_RULE_APPS_ID: case IDC_NETWORK: case IDC_LOG: { index = (ULONG)_app_listview_getcontextcode (lpnmlv->nmcd.lItemlParam); if (listview_id == IDC_NETWORK) { ptr_network = _app_network_getitem (index); if (ptr_network) { app_hash = ptr_network->app_hash; is_systemapp = _app_isappfromsystem (ptr_network->path, app_hash); is_validconnection = ptr_network->is_connection; //is_validconnection = FALSE; // do not highlight connections _r_obj_dereference (ptr_network); } } else if (listview_id == IDC_LOG) { ptr_log = _app_getlogitem (index); if (ptr_log) { app_hash = _app_getlogapp (index); is_systemapp = _app_isappfromsystem (ptr_log->path, app_hash); _r_obj_dereference (ptr_log); } } else { app_hash = index; is_validconnection = _app_network_isapphaveconnection (app_hash); if (_app_getappinfobyhash (app_hash, INFO_PATH, &real_path, sizeof (PR_STRING))) { is_systemapp = _app_isappfromsystem (real_path, app_hash); _r_obj_dereference (real_path); } } if (app_hash) new_clr = _app_getappcolor (listview_id, app_hash, is_systemapp, is_validconnection); break; } case IDC_RULES_BLOCKLIST: case IDC_RULES_SYSTEM: case IDC_RULES_CUSTOM: case IDC_APP_RULES_ID: { index = (ULONG)_app_listview_getcontextcode (lpnmlv->nmcd.lItemlParam); new_clr = _app_getrulecolor (listview_id, index); break; } case IDC_COLORS: { ptr_clr = (PITEM_COLOR)lpnmlv->nmcd.lItemlParam; new_clr = ptr_clr->new_clr ? ptr_clr->new_clr : ptr_clr->default_clr; break; } default: { return CDRF_DODEFAULT; } } if (new_clr) { lpnmlv->clrText = _r_dc_getcolorbrightness (new_clr); lpnmlv->clrTextBk = new_clr; _r_dc_fillrect (lpnmlv->nmcd.hdc, &lpnmlv->nmcd.rc, new_clr); return CDRF_NEWFONT; } break; } } return CDRF_DODEFAULT; } VOID _app_displayinfoapp_callback ( _In_ PITEM_APP ptr_app, _Inout_ LPNMLVDISPINFOW lpnmlv ) { PR_STRING string; LONG icon_id = 0; // set text if (lpnmlv->item.mask & LVIF_TEXT) { switch (lpnmlv->item.iSubItem) { case 0: { string = _app_getappdisplayname (ptr_app, FALSE); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } break; } case 1: { string = _r_format_unixtime (ptr_app->timestamp, FDTF_SHORTDATE | FDTF_LONGTIME); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } break; } } } // set image if (lpnmlv->item.mask & LVIF_IMAGE) { if (_app_getappinfoparam2 (ptr_app->app_hash, (INT)lpnmlv->hdr.idFrom, INFO_ICON_ID, &icon_id, sizeof (LONG))) lpnmlv->item.iImage = icon_id; } // set group id if (lpnmlv->item.mask & LVIF_GROUPID) { if (_app_listview_isitemhidden (lpnmlv->item.lParam)) { lpnmlv->item.iGroupId = LV_HIDDEN_GROUP_ID; } else { if (lpnmlv->hdr.idFrom == IDC_RULE_APPS_ID) { if (ptr_app->type == DATA_APP_UWP) { lpnmlv->item.iGroupId = 2; } else if (ptr_app->type == DATA_APP_SERVICE) { lpnmlv->item.iGroupId = 1; } else { lpnmlv->item.iGroupId = 0; } } else { // apps with special rule if (_app_isapphaverule (ptr_app->app_hash, FALSE)) { lpnmlv->item.iGroupId = 2; } else if (_app_istimerset (ptr_app)) { lpnmlv->item.iGroupId = 1; } else if (ptr_app->is_enabled) { lpnmlv->item.iGroupId = 0; } else { // silent apps without rules and not enabled added into silent group if (ptr_app->is_silent) { lpnmlv->item.iGroupId = 4; } else { lpnmlv->item.iGroupId = 3; } } } } } } VOID _app_displayinforule_callback ( _In_ INT listview_id, _In_ PITEM_RULE ptr_rule, _Inout_ LPNMLVDISPINFOW lpnmlv ) { PR_STRING string; // set text if (lpnmlv->item.mask & LVIF_TEXT) { switch (lpnmlv->item.iSubItem) { case 0: { if (ptr_rule->name) { if (ptr_rule->is_readonly && ptr_rule->type == DATA_RULE_USER) { _r_str_printf (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, L"%s" SZ_RULE_INTERNAL_MENU, ptr_rule->name->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, ptr_rule->name->buffer); } } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_STATUS_EMPTY)); } break; } case 1: { if (ptr_rule->protocol_str) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, ptr_rule->protocol_str->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_ANY)); } break; } case 2: { string = _app_db_getdirectionname (ptr_rule->direction, FALSE, TRUE); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } break; } } } // set image if (lpnmlv->item.mask & LVIF_IMAGE) lpnmlv->item.iImage = (ptr_rule->action == FWP_ACTION_BLOCK) ? 1 : 0; // set group id if (lpnmlv->item.mask & LVIF_GROUPID) { if (_app_listview_isitemhidden (lpnmlv->item.lParam)) { lpnmlv->item.iGroupId = LV_HIDDEN_GROUP_ID; } else { if (listview_id == IDC_APP_RULES_ID) { lpnmlv->item.iGroupId = ptr_rule->is_readonly ? 0 : 1; } else { if (ptr_rule->is_enabled) { if (ptr_rule->is_forservices || !_r_obj_isempty (ptr_rule->apps)) { lpnmlv->item.iGroupId = 1; } else { lpnmlv->item.iGroupId = 0; } } else { lpnmlv->item.iGroupId = 2; } } } } } VOID _app_displayinfonetwork_callback ( _In_ PITEM_NETWORK ptr_network, _Inout_ LPNMLVDISPINFOW lpnmlv ) { PITEM_APP ptr_app; PR_STRING string; LPCWSTR name; LONG icon_id = 0; // set text if (lpnmlv->item.mask & LVIF_TEXT) { switch (lpnmlv->item.iSubItem) { case 0: { ptr_app = _app_getappitem (ptr_network->app_hash); if (ptr_app) { string = _app_getappdisplayname (ptr_app, TRUE); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } _r_obj_dereference (ptr_app); } else if (ptr_network->path) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_path_getbasename (&ptr_network->path->sr)); } break; } case 1: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->local_addr_str, NULL, NULL); if (string) _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); break; } case 2: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->local_host_str, NULL, NULL); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_LOADING)); } break; } case 3: { if (ptr_network->local_port) { string = _app_formatport (ptr_network->local_port, ptr_network->protocol); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } } break; } case 4: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->remote_addr_str, NULL, NULL); if (string) _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); break; } case 5: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->remote_host_str, NULL, NULL); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_LOADING)); } break; } case 6: { if (ptr_network->remote_port) { string = _app_formatport (ptr_network->remote_port, ptr_network->protocol); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } } break; } case 7: { if (ptr_network->protocol_str) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, ptr_network->protocol_str->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_ANY)); } break; } case 8: { name = _app_db_getconnectionstatename (ptr_network->state); if (name) _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, name); break; } } } // set image if (lpnmlv->item.mask & LVIF_IMAGE) { if (_app_getappinfoparam2 (ptr_network->app_hash, (INT)lpnmlv->hdr.idFrom, INFO_ICON_ID, &icon_id, sizeof (LONG))) lpnmlv->item.iImage = icon_id; } // set group id if (lpnmlv->item.mask & LVIF_GROUPID) { if (_app_listview_isitemhidden (lpnmlv->item.lParam)) { lpnmlv->item.iGroupId = LV_HIDDEN_GROUP_ID; } else { if (ptr_network->type == DATA_APP_SERVICE) { lpnmlv->item.iGroupId = 1; } else if (ptr_network->type == DATA_APP_UWP) { lpnmlv->item.iGroupId = 2; } else { lpnmlv->item.iGroupId = 0; } } } } VOID _app_displayinfolog_callback ( _Inout_ LPNMLVDISPINFOW lpnmlv, _In_opt_ PITEM_APP ptr_app, _In_ PITEM_LOG ptr_log ) { PR_STRING string; LONG icon_id = 0; // set text if (lpnmlv->item.mask & LVIF_TEXT) { switch (lpnmlv->item.iSubItem) { case 0: { _r_str_printf (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, L"%d", _InterlockedCompareExchange (&ptr_log->log_id, 0, 0)); break; } case 1: { if (ptr_app) { string = _app_getappdisplayname (ptr_app, TRUE); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } } else if (ptr_log->path) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_path_getbasename (&ptr_log->path->sr)); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_STATUS_EMPTY)); } break; } case 2: { string = _r_format_unixtime (ptr_log->timestamp, FDTF_SHORTDATE | FDTF_LONGTIME); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } break; } case 3: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->local_addr_str, NULL, NULL); if (string) _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); break; } case 4: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->local_host_str, NULL, NULL); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_LOADING)); } break; } case 5: { if (ptr_log->local_port) { string = _app_formatport (ptr_log->local_port, ptr_log->protocol); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } } break; } case 6: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->remote_addr_str, NULL, NULL); if (string) _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); break; } case 7: { string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->remote_host_str, NULL, NULL); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_LOADING)); } break; } case 8: { if (ptr_log->remote_port) { string = _app_formatport (ptr_log->remote_port, ptr_log->protocol); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } } break; } case 9: { if (ptr_log->protocol_str) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, ptr_log->protocol_str->buffer); } else { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, _r_locale_getstring (IDS_ANY)); } break; } case 10: { string = _app_db_getdirectionname (ptr_log->direction, ptr_log->is_loopback, FALSE); if (string) { _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); } break; } case 11: { string = _r_obj_concatstrings ( 2, ptr_log->is_allow ? L"[A] " : L"[B] ", _r_obj_getstringordefault (ptr_log->filter_name, _r_locale_getstring (IDS_STATUS_EMPTY)) ); _r_str_copy (lpnmlv->item.pszText, lpnmlv->item.cchTextMax, string->buffer); _r_obj_dereference (string); break; } } } // set image if (lpnmlv->item.mask & LVIF_IMAGE) { if (_app_getappinfoparam2 (ptr_log->app_hash, (INT)lpnmlv->hdr.idFrom, INFO_ICON_ID, &icon_id, sizeof (LONG))) lpnmlv->item.iImage = icon_id; } // set group id if (lpnmlv->item.mask & LVIF_GROUPID) { if (_app_listview_isitemhidden (lpnmlv->item.lParam)) { lpnmlv->item.iGroupId = LV_HIDDEN_GROUP_ID; } else { lpnmlv->item.iGroupId = 0; } } } BOOLEAN _app_message_displayinfo ( _In_ HWND hwnd, _In_ INT listview_id, _Inout_ LPNMLVDISPINFOW lpnmlv ) { PITEM_NETWORK ptr_network; PITEM_RULE ptr_rule; PITEM_APP ptr_app; PITEM_LOG ptr_log; ULONG_PTR index; index = _app_listview_getitemcontext (hwnd, listview_id, lpnmlv->item.iItem); switch (listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: case IDC_RULE_APPS_ID: { ptr_app = _app_getappitem ((ULONG)index); if (ptr_app) { _app_displayinfoapp_callback (ptr_app, lpnmlv); _r_obj_dereference (ptr_app); return TRUE; } break; } case IDC_RULES_BLOCKLIST: case IDC_RULES_SYSTEM: case IDC_RULES_CUSTOM: case IDC_APP_RULES_ID: { ptr_rule = _app_getrulebyid (index); if (ptr_rule) { _app_displayinforule_callback (listview_id, ptr_rule, lpnmlv); _r_obj_dereference (ptr_rule); return TRUE; } break; } case IDC_NETWORK: { ptr_network = _app_network_getitem ((ULONG)index); if (ptr_network) { _app_displayinfonetwork_callback (ptr_network, lpnmlv); _r_obj_dereference (ptr_network); return TRUE; } break; } case IDC_LOG: { ptr_log = _app_getlogitem ((ULONG)index); if (ptr_log) { ptr_app = _app_getappitem (ptr_log->app_hash); _app_displayinfolog_callback (lpnmlv, ptr_app, ptr_log); if (ptr_app) _r_obj_dereference (ptr_app); _r_obj_dereference (ptr_log); return TRUE; } break; } } return FALSE; } VOID _app_command_idtorules ( _In_ HWND hwnd, _In_ INT ctrl_id ) { PITEM_TAB_CONTEXT tab_context; PITEM_RULE ptr_rule; PITEM_APP ptr_app; PR_LIST rules; HANDLE hengine; ULONG_PTR rule_idx; ULONG app_hash; INT item_id = INT_ERROR; BOOL is_remove = INT_ERROR; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context || !_r_listview_getselectedcount (hwnd, tab_context->listview_id)) return; rule_idx = (ULONG_PTR)ctrl_id - IDX_RULES_SPECIAL; ptr_rule = _app_getrulebyid (rule_idx); if (!ptr_rule) return; while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { app_hash = _app_listview_getappcontext (hwnd, tab_context->listview_id, item_id); if (ptr_rule->is_forservices && _app_issystemhash (app_hash)) continue; ptr_app = _app_getappitem (app_hash); if (!ptr_app) continue; _app_notify_freeobject (NULL, ptr_app); if (is_remove == INT_ERROR) is_remove = !!(ptr_rule->is_enabled && _r_obj_findhashtable (ptr_rule->apps, app_hash)); _app_setruletoapp (hwnd, ptr_rule, item_id, ptr_app, !is_remove); _r_obj_dereference (ptr_app); } if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); rules = _r_obj_createlist (10, NULL); _r_obj_addlistitem (rules, ptr_rule, NULL); _wfp_create4filters (hengine, rules, DBG_ARG, FALSE); _r_obj_dereference (rules); } _app_listview_updateby_id (hwnd, tab_context->listview_id, 0); _app_listview_updateitemby_param (hwnd, rule_idx, FALSE); _r_obj_dereference (ptr_rule); _app_profile_save (hwnd); } VOID _app_command_idtotimers ( _In_ HWND hwnd, _In_ INT ctrl_id ) { PITEM_TAB_CONTEXT tab_context; PITEM_APP ptr_app; PR_LIST rules; HANDLE hengine; ULONG_PTR timer_idx; ULONG app_hash; LONG64 seconds; INT item_id = INT_ERROR; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context || !_r_listview_getselectedcount (hwnd, tab_context->listview_id)) return; timer_idx = (ULONG_PTR)ctrl_id - IDX_TIMER; seconds = timer_array[timer_idx]; if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); rules = _r_obj_createlist (8, &_r_obj_dereference); while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { app_hash = _app_listview_getappcontext (hwnd, tab_context->listview_id, item_id); ptr_app = _app_getappitem (app_hash); if (ptr_app) { _app_timer_set (hwnd, ptr_app, seconds); _r_obj_addlistitem (rules, ptr_app, NULL); } } _wfp_create3filters (hengine, rules, TEXT (__FILE__), __LINE__, FALSE); _r_obj_dereference (rules); } _app_listview_updateby_id (hwnd, tab_context->listview_id, PR_UPDATE_FORCE); _app_profile_save (hwnd); } VOID _app_command_logshow ( _In_ HWND hwnd ) { HANDLE current_handle; PR_STRING viewer_path; PR_STRING log_path; PR_STRING cmdline; INT item_count; NTSTATUS status; if (_r_config_getboolean (L"IsLogUiEnabled", FALSE, NULL)) { item_count = _r_listview_getitemcount (hwnd, IDC_LOG); _r_wnd_toggle (hwnd, TRUE); _app_settab_id (hwnd, IDC_LOG); if (item_count) _r_listview_ensurevisible (hwnd, IDC_LOG, item_count - 1); } else { log_path = _r_config_getstringexpand (L"LogPath", LOG_PATH_DEFAULT, NULL); viewer_path = _app_getlogviewer (); if (!log_path || !_r_fs_isexists (&log_path->sr) || !viewer_path || !_r_fs_isexists (&viewer_path->sr)) { if (log_path) _r_obj_dereference (log_path); if (viewer_path) _r_obj_dereference (viewer_path); _r_wnd_toggle (hwnd, TRUE); return; } current_handle = _InterlockedCompareExchangePointer (&config.hlogfile, NULL, NULL); if (current_handle) _r_fs_flushfile (current_handle); cmdline = _r_obj_concatstrings ( 5, L"\"", viewer_path->buffer, L"\" \"", log_path->buffer, L"\"" ); status = _r_sys_createprocess (&viewer_path->sr, &cmdline->sr, NULL, FALSE); if (status != STATUS_SUCCESS) _r_show_errormessage (hwnd, NULL, status, cmdline->buffer, ET_NATIVE); _r_obj_dereference (viewer_path); _r_obj_dereference (log_path); _r_obj_dereference (cmdline); } } VOID _app_command_logclear ( _In_ HWND hwnd ) { HANDLE current_handle; PR_STRING log_path; LONG64 file_size; BOOLEAN is_valid; log_path = _r_config_getstringexpand (L"LogPath", LOG_PATH_DEFAULT, NULL); current_handle = _InterlockedCompareExchangePointer (&config.hlogfile, NULL, NULL); if (current_handle) _r_fs_getsize2 (NULL, current_handle, &file_size); is_valid = (current_handle && file_size > 2) || (log_path && _r_fs_isexists (&log_path->sr)); if (!is_valid) { _r_queuedlock_acquireshared (&lock_loglist); is_valid = !_r_obj_isempty (log_table); _r_queuedlock_releaseshared (&lock_loglist); } if (is_valid) { if (_r_show_confirmmessage (hwnd, _r_locale_getstring (IDS_QUESTION), NULL, L"ConfirmLogClear", FALSE)) { _app_logclear (current_handle); _app_logclear_ui (hwnd); } } if (log_path) _r_obj_dereference (log_path); } VOID _app_command_logerrshow ( _In_opt_ HWND hwnd ) { PR_STRING process_path; PR_STRING viewer_path; PR_STRING path; NTSTATUS status; path = _r_app_getlogpath (); if (!_r_fs_isexists (&path->sr)) return; viewer_path = _app_getlogviewer (); if (!viewer_path) return; process_path = _r_obj_concatstrings ( 5, L"\"", viewer_path->buffer, L"\" \"", path->buffer, L"\"" ); status = _r_sys_createprocess (&viewer_path->sr, &process_path->sr, NULL, FALSE); if (status != STATUS_SUCCESS) _r_show_errormessage (hwnd, NULL, status, viewer_path->buffer, ET_NATIVE); _r_obj_dereference (process_path); _r_obj_dereference (viewer_path); } VOID _app_command_logerrclear ( _In_opt_ HWND hwnd ) { PR_STRING path; path = _r_app_getlogpath (); if (!_r_fs_isexists (&path->sr)) return; if (!_r_show_confirmmessage (hwnd, _r_locale_getstring (IDS_QUESTION), NULL, L"ConfirmLogClear", FALSE)) return; _r_fs_deletefile (&path->sr, NULL); } VOID _app_command_copy ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ INT column_id ) { R_STRINGREF divider_sr = PR_STRINGREF_INIT (DIVIDER_COPY); PITEM_TAB_CONTEXT tab_context; R_STRINGBUILDER sb; PR_STRING string; INT column_count; INT item_id = INT_ERROR; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return; column_count = _r_listview_getcolumncount (hwnd, tab_context->listview_id); _r_obj_initializestringbuilder (&sb, 512); while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { if (ctrl_id == IDM_COPY) { for (INT i = 0; i < column_count; i++) { string = _r_listview_getitemtext (hwnd, tab_context->listview_id, item_id, i); if (string) { _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_appendstringbuilder2 (&sb, ÷r_sr); _r_obj_dereference (string); } } string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring (&string->sr, ÷r_sr, 0); } else { string = _r_listview_getitemtext (hwnd, tab_context->listview_id, item_id, column_id); if (string) { _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_dereference (string); } } _r_obj_appendstringbuilder (&sb, SZ_CRLF); } string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring2 (&string->sr, DIVIDER_TRIM, 0); _r_clipboard_set (hwnd, &string->sr); _r_obj_deletestringbuilder (&sb); } VOID _app_command_checkbox ( _In_ HWND hwnd, _In_ INT ctrl_id ) { PITEM_TAB_CONTEXT tab_context; PITEM_APP ptr_app; PITEM_RULE ptr_rule; PR_LIST rules; HANDLE hengine; ULONG hash_code; INT item_id = INT_ERROR; BOOLEAN new_val = (ctrl_id == IDM_CHECK); BOOLEAN is_changed = FALSE; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return; rules = _r_obj_createlist (8, &_r_obj_dereference); if (tab_context->listview_id >= IDC_APPS_PROFILE && tab_context->listview_id <= IDC_APPS_UWP) { while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_app = _app_getappitem (hash_code); if (!ptr_app) continue; if (ptr_app->is_enabled != new_val) { if (!new_val) { _app_timer_reset (hwnd, ptr_app); } else { _app_notify_freeobject (NULL, ptr_app); } ptr_app->is_enabled = new_val; _app_listview_lock (hwnd, tab_context->listview_id, TRUE); _app_setappiteminfo (hwnd, tab_context->listview_id, item_id, ptr_app); _app_listview_lock (hwnd, tab_context->listview_id, FALSE); _r_obj_addlistitem (rules, ptr_app, NULL); is_changed = TRUE; // do not reset reference counter } else { _r_obj_dereference (ptr_app); } } if (is_changed) { if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); _wfp_create3filters (hengine, rules, DBG_ARG, FALSE); } } } else if (tab_context->listview_id >= IDC_RULES_BLOCKLIST && tab_context->listview_id <= IDC_RULES_CUSTOM) { while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_rule = _app_getrulebyid (hash_code); if (!ptr_rule) continue; if (ptr_rule->is_enabled != new_val) { _app_ruleenable (ptr_rule, new_val, TRUE); _app_listview_lock (hwnd, tab_context->listview_id, TRUE); _app_setruleiteminfo (hwnd, tab_context->listview_id, item_id, ptr_rule, TRUE); _app_listview_lock (hwnd, tab_context->listview_id, FALSE); _r_obj_addlistitem (rules, ptr_rule, NULL); is_changed = TRUE; // do not reset reference counter } else { _r_obj_dereference (ptr_rule); } } if (is_changed) { if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); _wfp_create4filters (hengine, rules, DBG_ARG, FALSE); } } } _r_obj_dereference (rules); if (is_changed) { _app_listview_updateby_id (hwnd, tab_context->listview_id, PR_UPDATE_FORCE); _app_profile_save (hwnd); } } VOID _app_command_delete ( _In_ HWND hwnd ) { R_STRINGREF crlf = PR_STRINGREF_INIT (SZ_CRLF); PITEM_TAB_CONTEXT tab_context; R_STRINGBUILDER sb; PR_ARRAY guids = NULL; PITEM_NETWORK ptr_network; PR_HASHTABLE apps_checker; MIB_TCPROW tcprow; PR_STRING string; HANDLE hengine; PITEM_APP ptr_app; PITEM_RULE ptr_rule; ULONG_PTR rule_idx; ULONG_PTR enum_key; ULONG hash_code; INT selected_count; LPARAM lparam; INT item_count; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context || (tab_context->listview_id != IDC_APPS_PROFILE && tab_context->listview_id != IDC_RULES_CUSTOM && tab_context->listview_id != IDC_NETWORK)) return; selected_count = _r_listview_getselectedcount (hwnd, tab_context->listview_id); if (!selected_count) return; item_count = _r_listview_getitemcount (hwnd, tab_context->listview_id); if (tab_context->listview_id != IDC_NETWORK) { _r_obj_initializestringbuilder (&sb, 256); string = _r_locale_getstring_ex (IDS_QUESTION_DELETE); if (string) { _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_appendstringbuilder2 (&sb, &crlf); _r_obj_appendstringbuilder2 (&sb, &crlf); _r_obj_dereference (string); } for (INT i = 0, j = 1; i < item_count; i++) { if (!_r_listview_isitemselected (hwnd, tab_context->listview_id, i)) continue; lparam = _r_listview_getitemlparam (hwnd, tab_context->listview_id, i); if (_app_listview_isitemhidden (lparam)) continue; string = _r_listview_getitemtext (hwnd, tab_context->listview_id, i, 0); if (string) { _r_obj_appendstringbuilderformat (&sb, L"%" TEXT (PRId32) ") ", j); _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_appendstringbuilder2 (&sb, &crlf); _r_obj_dereference (string); } j += 1; } string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring (&string->sr, &crlf, PR_TRIM_END_ONLY); if (_r_show_message (hwnd, MB_YESNO | MB_ICONEXCLAMATION, NULL, string->buffer) != IDYES) { _r_obj_dereference (string); return; } guids = _r_obj_createarray (sizeof (GUID), 10, NULL); _r_obj_dereference (string); } for (INT i = item_count - 1; i != INT_ERROR; i--) { if (!_r_listview_isitemselected (hwnd, tab_context->listview_id, i)) continue; if (tab_context->listview_id == IDC_APPS_PROFILE) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, i); ptr_app = _app_getappitem (hash_code); if (!ptr_app) continue; if (!ptr_app->is_undeletable) // skip "undeletable" apps { if (!_r_obj_isempty (ptr_app->guids)) _r_obj_addarrayitems (guids, ptr_app->guids->items, ptr_app->guids->count); _r_listview_deleteitem (hwnd, tab_context->listview_id, i); _app_timer_reset (hwnd, ptr_app); _app_notify_freeobject (NULL, ptr_app); _r_queuedlock_acquireexclusive (&lock_apps); _app_freeapplication (hwnd, hash_code); _r_queuedlock_releaseexclusive (&lock_apps); } _r_obj_dereference (ptr_app); } else if (tab_context->listview_id == IDC_RULES_CUSTOM) { rule_idx = _app_listview_getitemcontext (hwnd, tab_context->listview_id, i); ptr_rule = _app_getrulebyid (rule_idx); if (!ptr_rule) continue; if (!ptr_rule->is_readonly) // skip "read-only" rules { apps_checker = _r_obj_createhashtable (sizeof (SHORT), 6, NULL); if (!_r_obj_isempty (ptr_rule->guids)) _r_obj_addarrayitems (guids, ptr_rule->guids->items, ptr_rule->guids->count); enum_key = 0; while (_r_obj_enumhashtable (ptr_rule->apps, NULL, &hash_code, &enum_key)) { _r_obj_addhashtableitem (apps_checker, hash_code, NULL); } _r_listview_deleteitem (hwnd, tab_context->listview_id, i); _r_obj_reference (ptr_rule); // required to dereference later _r_queuedlock_acquireexclusive (&lock_rules); _r_obj_setlistitem (rules_list, rule_idx, NULL); _r_queuedlock_releaseexclusive (&lock_rules); enum_key = 0; while (_r_obj_enumhashtable (apps_checker, NULL, &hash_code, &enum_key)) { _app_listview_updateitemby_param (hwnd, hash_code, TRUE); } } _r_obj_dereference (ptr_rule); } else if (tab_context->listview_id == IDC_NETWORK) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, i); ptr_network = _app_network_getitem (hash_code); if (!ptr_network) continue; if (ptr_network->af == AF_INET && ptr_network->state == MIB_TCP_STATE_ESTAB) { RtlZeroMemory (&tcprow, sizeof (MIB_TCPROW)); tcprow.dwState = MIB_TCP_STATE_DELETE_TCB; tcprow.dwLocalAddr = ptr_network->local_addr.S_un.S_addr; tcprow.dwLocalPort = _r_byteswap_ushort ((USHORT)ptr_network->local_port); tcprow.dwRemoteAddr = ptr_network->remote_addr.S_un.S_addr; tcprow.dwRemotePort = _r_byteswap_ushort ((USHORT)ptr_network->remote_port); if (SetTcpEntry (&tcprow) == NO_ERROR) { _r_listview_deleteitem (hwnd, tab_context->listview_id, i); _app_network_removeitem (hash_code); } } _r_obj_dereference (ptr_network); } } if (guids) { if (!_r_obj_isempty (guids)) { if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); _wfp_destroyfilters_array (hengine, guids, DBG_ARG); } } _r_obj_dereference (guids); } _app_listview_updateby_id (hwnd, tab_context->listview_id, 0); _app_profile_save (hwnd); } VOID _app_command_disable ( _In_ HWND hwnd, _In_ INT ctrl_id ) { PITEM_TAB_CONTEXT tab_context; PITEM_APP ptr_app; ULONG app_hash; LONG new_val = INT_ERROR; INT item_id = INT_ERROR; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); // note: these commands only for apps... if (!tab_context || (!(tab_context->listview_id >= IDC_APPS_PROFILE && tab_context->listview_id <= IDC_APPS_UWP) && tab_context->listview_id != IDC_LOG)) return; while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { app_hash = _app_listview_getappcontext (hwnd, tab_context->listview_id, item_id); ptr_app = _app_getappitem (app_hash); if (!ptr_app) continue; if (ctrl_id == IDM_DISABLENOTIFICATIONS) { if (new_val == INT_ERROR) new_val = !ptr_app->is_silent; _app_setappinfo (ptr_app, INFO_IS_SILENT, LongToPtr (new_val)); } else if (ctrl_id == IDM_DISABLEREMOVAL) { if (_app_isdisabledremoval (app_hash)) continue; if (new_val == INT_ERROR) new_val = !ptr_app->is_undeletable; _app_setappinfo (ptr_app, INFO_IS_UNDELETABLE, LongToPtr (new_val)); } else if (ctrl_id == IDM_DISABLETIMER) { _app_timer_reset (hwnd, ptr_app); } _app_listview_updateitemby_id (hwnd, tab_context->listview_id, item_id); _r_obj_dereference (ptr_app); } _app_listview_updateby_id (hwnd, tab_context->listview_id, 0); _app_profile_save (hwnd); } VOID _app_command_openeditor ( _In_ HWND hwnd ) { PITEM_TAB_CONTEXT tab_context; PITEM_NETWORK ptr_network; PEDITOR_CONTEXT context; PITEM_RULE ptr_rule; PITEM_LOG ptr_log; PR_STRING string; ULONG_PTR id_code; ULONG hash_code; INT item_id = INT_ERROR; ptr_rule = _app_addrule (NULL, NULL, NULL, FWP_DIRECTION_OUTBOUND, FWP_ACTION_PERMIT, 0, 0); _app_ruleenable (ptr_rule, TRUE, FALSE); tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return; switch (tab_context->listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: { while ((item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, item_id)) != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); if (_app_isappfound (hash_code)) _r_obj_addhashtableitem (ptr_rule->apps, hash_code, NULL); } break; } case IDC_NETWORK: { ptr_rule->action = FWP_ACTION_BLOCK; item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, INT_ERROR); if (item_id != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_network = _app_network_getitem (hash_code); if (ptr_network) { if (!ptr_rule->name) ptr_rule->name = _r_listview_getitemtext (hwnd, tab_context->listview_id, item_id, 0); if (ptr_network->app_hash && !_r_obj_isstringempty (ptr_network->path)) { if (!_app_isappfound (ptr_network->app_hash)) { ptr_network->app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, ptr_network->path, NULL, NULL); if (ptr_network->app_hash) { _app_listview_updateby_param (hwnd, ptr_network->app_hash, PR_SETITEM_UPDATE, TRUE); _app_profile_save (hwnd); } } _r_obj_addhashtableitem (ptr_rule->apps, ptr_network->app_hash, NULL); } ptr_rule->protocol = ptr_network->protocol; string = _app_formataddress (ptr_network->af, 0, &ptr_network->remote_addr, ptr_network->remote_port, FMTADDR_AS_RULE); _r_obj_movereference ((PVOID_PTR)&ptr_rule->rule_remote, string); string = _app_formataddress (ptr_network->af, 0, &ptr_network->local_addr, ptr_network->local_port, FMTADDR_AS_RULE); _r_obj_movereference ((PVOID_PTR)&ptr_rule->rule_local, string); _r_obj_dereference (ptr_network); } } break; } case IDC_LOG: { item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, INT_ERROR); if (item_id != INT_ERROR) { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_log = _app_getlogitem (hash_code); if (ptr_log) { if (!ptr_rule->name) ptr_rule->name = _r_listview_getitemtext (hwnd, tab_context->listview_id, item_id, 0); if (ptr_log->app_hash && !_r_obj_isstringempty (ptr_log->path)) { if (!_app_isappfound (ptr_log->app_hash)) { ptr_log->app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, ptr_log->path, NULL, NULL); if (ptr_log->app_hash) { _app_listview_updateby_param (hwnd, ptr_log->app_hash, PR_SETITEM_UPDATE, TRUE); _app_profile_save (hwnd); } } _r_obj_addhashtableitem (ptr_rule->apps, ptr_log->app_hash, NULL); } ptr_rule->protocol = ptr_log->protocol; ptr_rule->direction = ptr_log->direction; string = _app_formataddress (ptr_log->af, 0, &ptr_log->remote_addr, ptr_log->remote_port, FMTADDR_AS_RULE); _r_obj_movereference ((PVOID_PTR)&ptr_rule->rule_remote, string); string = _app_formataddress (ptr_log->af, 0, &ptr_log->local_addr, ptr_log->local_port, FMTADDR_AS_RULE); _r_obj_movereference ((PVOID_PTR)&ptr_rule->rule_local, string); _r_obj_dereference (ptr_log); } } break; } } context = _app_editor_createwindow (hwnd, ptr_rule, 0, TRUE); if (context) { _r_queuedlock_acquireexclusive (&lock_rules); _r_obj_addlistitem (rules_list, _r_obj_reference (ptr_rule), &id_code); _r_queuedlock_releaseexclusive (&lock_rules); if (id_code != SIZE_MAX) { _app_listview_addruleitem (hwnd, ptr_rule, id_code, TRUE); _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE); _app_profile_save (hwnd); } _app_editor_deletewindow (context); } _r_obj_dereference (ptr_rule); } VOID _app_command_properties ( _In_ HWND hwnd ) { PITEM_TAB_CONTEXT tab_context; PEDITOR_CONTEXT context; PITEM_NETWORK ptr_network; PITEM_RULE ptr_rule; PITEM_APP ptr_app; PITEM_LOG ptr_log; ULONG hash_code; INT item_id; tab_context = _app_listview_getcontext (hwnd, INT_ERROR); if (!tab_context) return; item_id = _r_listview_getnextselected (hwnd, tab_context->listview_id, INT_ERROR); if (item_id == INT_ERROR) return; switch (tab_context->listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_app = _app_getappitem (hash_code); if (!ptr_app) return; context = _app_editor_createwindow (hwnd, ptr_app, 0, FALSE); if (context) { _app_listview_lock (hwnd, tab_context->listview_id, TRUE); _app_setappiteminfo (hwnd, tab_context->listview_id, item_id, ptr_app); _app_listview_lock (hwnd, tab_context->listview_id, FALSE); _app_listview_updateby_id (hwnd, tab_context->listview_id, 0); _app_profile_save (hwnd); _app_editor_deletewindow (context); } _r_obj_dereference (ptr_app); break; } case IDC_RULES_BLOCKLIST: case IDC_RULES_SYSTEM: case IDC_RULES_CUSTOM: { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_rule = _app_getrulebyid (hash_code); if (!ptr_rule) return; context = _app_editor_createwindow (hwnd, ptr_rule, 0, TRUE); if (context) { _app_listview_lock (hwnd, tab_context->listview_id, TRUE); _app_setruleiteminfo (hwnd, tab_context->listview_id, item_id, ptr_rule, TRUE); _app_listview_lock (hwnd, tab_context->listview_id, FALSE); _app_listview_updateby_id (hwnd, tab_context->listview_id, 0); _app_profile_save (hwnd); _app_editor_deletewindow (context); } _r_obj_dereference (ptr_rule); break; } case IDC_NETWORK: { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_network = _app_network_getitem (hash_code); if (!ptr_network) return; if (ptr_network->app_hash && !_r_obj_isstringempty (ptr_network->path)) { if (!_app_isappfound (ptr_network->app_hash)) { ptr_network->app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, ptr_network->path, NULL, NULL); if (ptr_network->app_hash) { _app_listview_updateby_param (hwnd, ptr_network->app_hash, PR_SETITEM_UPDATE, TRUE); _app_profile_save (hwnd); } } if (ptr_network->app_hash) _app_listview_showitemby_param (hwnd, ptr_network->app_hash, TRUE); } _r_obj_dereference (ptr_network); break; } case IDC_LOG: { hash_code = (ULONG)_app_listview_getitemcontext (hwnd, tab_context->listview_id, item_id); ptr_log = _app_getlogitem (hash_code); if (!ptr_log) return; if (ptr_log->app_hash && !_r_obj_isstringempty (ptr_log->path)) { if (!_app_isappfound (ptr_log->app_hash)) { ptr_log->app_hash = _app_addapplication (hwnd, DATA_UNKNOWN, ptr_log->path, NULL, NULL); if (ptr_log->app_hash) { _app_listview_updateby_param (hwnd, ptr_log->app_hash, PR_SETITEM_UPDATE, TRUE); _app_profile_save (hwnd); } } if (ptr_log->app_hash) _app_listview_showitemby_param (hwnd, ptr_log->app_hash, TRUE); } _r_obj_dereference (ptr_log); break; } } } VOID _app_command_purgeunused ( _In_ HWND hwnd ) { R_STRINGBUILDER sb; PITEM_APP ptr_app = NULL; PR_STRING string = NULL; PR_HASHTABLE apps_list; PR_ARRAY guids; HANDLE hengine; ULONG_PTR enum_key = 0; ULONG hash_code; apps_list = _r_obj_createhashtable (sizeof (ULONG_PTR), 8, NULL); guids = _r_obj_createarray (sizeof (GUID), 10, NULL); _r_obj_initializestringbuilder (&sb, 256); _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, &hash_code, &enum_key)) { if (!_app_isappunused (ptr_app) || ptr_app->type == DATA_APP_SERVICE || ptr_app->type == DATA_APP_UWP) continue; _app_deleteappitem (hwnd, ptr_app->type, hash_code); _app_timer_reset (NULL, ptr_app); _app_notify_freeobject (NULL, ptr_app); if (!_r_obj_isempty (ptr_app->guids)) _r_obj_addarrayitems (guids, ptr_app->guids->items, ptr_app->guids->count); _r_obj_addhashtableitem (apps_list, hash_code, NULL); string = _app_getapppath (ptr_app, _r_config_getboolean (L"IsShortPath", TRUE, NULL)); if (string) { _r_obj_appendstringbuilder (&sb, L"- "); _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_appendstringbuilder (&sb, SZ_CRLF); _r_obj_dereference (string); } } _r_queuedlock_releaseshared (&lock_apps); if (_r_obj_gethashtablesize (apps_list)) { enum_key = 0; string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring2 (&string->sr, SZ_CRLF, PR_TRIM_END_ONLY); if (_r_show_confirmmessage (hwnd, _r_locale_getstring (IDS_PURGE_UNUSED), string->buffer, L"ConfirmUnused", FALSE)) { _r_queuedlock_acquireexclusive (&lock_apps); while (_r_obj_enumhashtable (apps_list, NULL, &hash_code, &enum_key)) { _app_freeapplication (hwnd, hash_code); } _r_queuedlock_releaseexclusive (&lock_apps); if (!_r_obj_isempty2 (guids) && _wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); _wfp_destroyfilters_array (hengine, guids, DBG_ARG); } _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE | PR_UPDATE_FORCE); _app_profile_save (hwnd); } } _r_obj_deletestringbuilder (&sb); _r_obj_dereference (apps_list); _r_obj_dereference (guids); } VOID _app_command_purgetimers ( _In_ HWND hwnd ) { PITEM_APP ptr_app = NULL; R_STRINGBUILDER sb; PR_STRING string; PR_STRING path; HANDLE hengine; PR_LIST rules; ULONG_PTR enum_key = 0; if (!_app_istimersactive ()) return; rules = _r_obj_createlist (10, NULL); _r_obj_initializestringbuilder (&sb, 0x100); _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (_app_istimerset (ptr_app)) { _r_obj_addlistitem (rules, ptr_app, NULL); path = _app_getapppath (ptr_app, _r_config_getboolean (L"IsShortPath", TRUE, NULL)); if (path) { _r_obj_appendstringbuilder (&sb, L"- "); _r_obj_appendstringbuilder2 (&sb, &path->sr); string = _r_format_interval (ptr_app->timer - _r_unixtime_now ()); if (string) { _r_obj_appendstringbuilder (&sb, L" ("); _r_obj_appendstringbuilder2 (&sb, &string->sr); _r_obj_appendstringbuilder (&sb, L")"); _r_obj_dereference (string); } _r_obj_appendstringbuilder (&sb, SZ_CRLF); _r_obj_dereference (path); } } } _r_queuedlock_releaseshared (&lock_apps); if (!_r_obj_isempty2 (rules)) { string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring2 (&string->sr, SZ_CRLF, PR_TRIM_END_ONLY); if (_r_show_confirmmessage (hwnd, _r_locale_getstring (IDS_QUESTION_TIMERS), string->buffer, L"ConfirmTimers", FALSE)) { if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); _wfp_create3filters (hengine, rules, DBG_ARG, FALSE); } for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules); i++) { ptr_app = _r_obj_getlistitem (rules, i); if (ptr_app) _app_timer_reset (hwnd, ptr_app); } _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE | PR_UPDATE_FORCE); _app_profile_save (hwnd); } } _r_obj_deletestringbuilder (&sb); _r_obj_dereference (rules); } VOID _app_command_selectfont ( _In_ HWND hwnd ) { CHOOSEFONT cf = {0}; LOGFONT lf = {0}; LONG dpi_value; UINT flags; cf.lStructSize = sizeof (CHOOSEFONT); cf.hwndOwner = hwnd; cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_NOSCRIPTSEL | CF_LIMITSIZE | CF_NOVERTFONTS; cf.nSizeMax = 16; cf.nSizeMin = 8; cf.lpLogFont = &lf; dpi_value = _r_dc_getwindowdpi (hwnd); _r_config_getfont (L"Font", &lf, dpi_value, NULL); if (!ChooseFontW (&cf)) return; _r_config_setfont (L"Font", &lf, dpi_value, NULL); _app_listview_loadfont (dpi_value, TRUE); _app_listview_updateby_id (hwnd, DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE | PR_UPDATE_FORCE); flags = RDW_NOFRAME | RDW_NOINTERNALPAINT | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN; RedrawWindow (hwnd, NULL, NULL, flags); } ================================================ FILE: src/messages.h ================================================ // simplewall // Copyright (c) 2021-2026 Henry++ #pragma once VOID _app_message_initialize ( _In_ HWND hwnd ); VOID _app_message_localize ( _In_ HWND hwnd ); VOID _app_message_uninitialize ( _In_ HWND hwnd ); VOID _app_generate_appmenu ( _In_ HMENU hmenu, _In_opt_ HMENU hsubmenu_rules, _In_opt_ HMENU hsubmenu_timers, _In_ ULONG app_hash ); VOID _app_message_contextmenu ( _In_ HWND hwnd, _In_ LPNMITEMACTIVATE lpnmlv ); VOID _app_message_contextmenu_columns ( _In_ HWND hwnd, _In_ LPNMHDR nmlp ); VOID _app_message_traycontextmenu ( _In_ HWND hwnd ); LONG_PTR _app_message_custdraw ( _In_ HWND hwnd, _In_ LPNMLVCUSTOMDRAW lpnmlv ); VOID _app_message_dpichanged ( _In_ HWND hwnd, _In_ LONG dpi_value ); BOOLEAN _app_message_displayinfo ( _In_ HWND hwnd, _In_ INT listview_id, _Inout_ LPNMLVDISPINFOW lpnmlv ); VOID _app_command_idtorules ( _In_ HWND hwnd, _In_ INT ctrl_id ); VOID _app_command_idtotimers ( _In_ HWND hwnd, _In_ INT ctrl_id ); VOID _app_command_logshow ( _In_ HWND hwnd ); VOID _app_command_logclear ( _In_ HWND hwnd ); VOID _app_command_logerrshow ( _In_opt_ HWND hwnd ); VOID _app_command_logerrclear ( _In_opt_ HWND hwnd ); VOID _app_command_copy ( _In_ HWND hwnd, _In_ INT ctrl_id, _In_ INT column_id ); VOID _app_command_checkbox ( _In_ HWND hwnd, _In_ INT ctrl_id ); VOID _app_command_delete ( _In_ HWND hwnd ); VOID _app_command_disable ( _In_ HWND hwnd, _In_ INT ctrl_id ); VOID _app_command_openeditor ( _In_ HWND hwnd ); VOID _app_command_properties ( _In_ HWND hwnd ); VOID _app_command_purgeunused ( _In_ HWND hwnd ); VOID _app_command_purgetimers ( _In_ HWND hwnd ); VOID _app_command_selectfont ( _In_ HWND hwnd ); ================================================ FILE: src/network.c ================================================ // simplewall // Copyright (c) 2019-2025 Henry++ #include "global.h" _Ret_maybenull_ PITEM_NETWORK_CONTEXT _app_network_getcontext () { static R_INITONCE init_once = PR_INITONCE_INIT; static PITEM_NETWORK_CONTEXT network_context = NULL; if (_r_initonce_begin (&init_once)) { network_context = _r_mem_allocate (sizeof (ITEM_NETWORK_CONTEXT)); network_context->network_ptr = _r_obj_createhashtablepointer (256); network_context->checker_ptr = _r_obj_createhashtablepointer (256); _r_initonce_end (&init_once); } return network_context; } VOID _app_network_initialize ( _In_ HWND hwnd ) { PITEM_NETWORK_CONTEXT network_context; R_ENVIRONMENT environment; BOOLEAN is_enabled; is_enabled = _r_config_getboolean (L"IsNetworkMonitorEnabled", TRUE, NULL); if (!is_enabled) return; network_context = _app_network_getcontext (); if (!network_context) return; network_context->hwnd = hwnd; _r_queuedlock_acquireexclusive (&network_context->lock_network); _r_obj_clearhashtable (network_context->network_ptr); _r_queuedlock_releaseexclusive (&network_context->lock_network); _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_clearhashtable (network_context->checker_ptr); _r_queuedlock_releaseexclusive (&network_context->lock_checker); // create network monitor thread _r_sys_setenvironment (&environment, THREAD_PRIORITY_ABOVE_NORMAL, IoPriorityNormal, MEMORY_PRIORITY_NORMAL); _r_sys_createthread (NULL, NtCurrentProcess (), &_app_network_threadproc, network_context, &environment, L"NetworkMonitor"); } VOID _app_network_uninitialize ( _In_ PITEM_NETWORK_CONTEXT context ) { _r_queuedlock_acquireexclusive (&context->lock_network); _r_obj_clearhashtable (context->network_ptr); _r_queuedlock_releaseexclusive (&context->lock_network); _r_queuedlock_acquireexclusive (&context->lock_checker); _r_obj_clearhashtable (context->checker_ptr); _r_queuedlock_releaseexclusive (&context->lock_checker); } VOID _app_network_generatetable ( _Inout_ PITEM_NETWORK_CONTEXT network_context ) { PMIB_TCPTABLE_OWNER_MODULE tcp4_table; PMIB_TCP6TABLE_OWNER_MODULE tcp6_table; PMIB_UDPTABLE_OWNER_MODULE udp4_table; PMIB_UDP6TABLE_OWNER_MODULE udp6_table; PITEM_NETWORK ptr_network; IN_ADDR remote_addr; IN_ADDR local_addr; PVOID buffer; ULONG network_hash; ULONG allocated_size; ULONG required_size; ULONG status; _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_clearhashtable (network_context->checker_ptr); _r_queuedlock_releaseexclusive (&network_context->lock_checker); required_size = 0; GetExtendedTcpTable (NULL, &required_size, FALSE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0); allocated_size = required_size; buffer = _r_mem_allocate (allocated_size); if (required_size) { tcp4_table = buffer; status = GetExtendedTcpTable (tcp4_table, &required_size, FALSE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0); if (status == NO_ERROR) { for (ULONG i = 0; i < tcp4_table->dwNumEntries; i++) { RtlZeroMemory (&remote_addr, sizeof (remote_addr)); RtlZeroMemory (&local_addr, sizeof (local_addr)); remote_addr.S_un.S_addr = tcp4_table->table[i].dwRemoteAddr; local_addr.S_un.S_addr = tcp4_table->table[i].dwLocalAddr; network_hash = _app_network_gethash ( AF_INET, tcp4_table->table[i].dwOwningPid, &remote_addr, tcp4_table->table[i].dwRemotePort, &local_addr, tcp4_table->table[i].dwLocalPort, IPPROTO_TCP, tcp4_table->table[i].dwState ); if (_app_network_isitemfound (network_hash)) { _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, NULL); _r_queuedlock_releaseexclusive (&network_context->lock_checker); continue; } ptr_network = _r_obj_allocate (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); if (!_app_network_getpath (ptr_network, tcp4_table->table[i].dwOwningPid, tcp4_table->table[i].OwningModuleInfo)) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET; ptr_network->protocol = IPPROTO_TCP; ptr_network->protocol_str = _r_obj_createstring (_app_db_getprotoname (ptr_network->protocol, ptr_network->af)); ptr_network->remote_addr.S_un.S_addr = tcp4_table->table[i].dwRemoteAddr; ptr_network->remote_port = _r_byteswap_ushort ((USHORT)tcp4_table->table[i].dwRemotePort); ptr_network->local_addr.S_un.S_addr = tcp4_table->table[i].dwLocalAddr; ptr_network->local_port = _r_byteswap_ushort ((USHORT)tcp4_table->table[i].dwLocalPort); ptr_network->state = tcp4_table->table[i].dwState; if (tcp4_table->table[i].dwState == MIB_TCP_STATE_ESTAB) { if (_app_network_isvalidconnection (ptr_network->af, &ptr_network->remote_addr) || _app_network_isvalidconnection (ptr_network->af, &ptr_network->local_addr)) ptr_network->is_connection = TRUE; } _r_queuedlock_acquireexclusive (&network_context->lock_network); _r_obj_addhashtablepointer (network_context->network_ptr, network_hash, ptr_network); _r_queuedlock_releaseexclusive (&network_context->lock_network); _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, _r_obj_reference (ptr_network->path)); _r_queuedlock_releaseexclusive (&network_context->lock_checker); } } } required_size = 0; GetExtendedTcpTable (NULL, &required_size, FALSE, AF_INET6, TCP_TABLE_OWNER_MODULE_ALL, 0); if (required_size) { if (allocated_size < required_size) { buffer = _r_mem_reallocate (buffer, required_size); allocated_size = required_size; } tcp6_table = buffer; status = GetExtendedTcpTable (tcp6_table, &required_size, FALSE, AF_INET6, TCP_TABLE_OWNER_MODULE_ALL, 0); if (status == NO_ERROR) { for (ULONG i = 0; i < tcp6_table->dwNumEntries; i++) { network_hash = _app_network_gethash ( AF_INET6, tcp6_table->table[i].dwOwningPid, tcp6_table->table[i].ucRemoteAddr, tcp6_table->table[i].dwRemotePort, tcp6_table->table[i].ucLocalAddr, tcp6_table->table[i].dwLocalPort, IPPROTO_TCP, tcp6_table->table[i].dwState ); if (_app_network_isitemfound (network_hash)) { _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, NULL); _r_queuedlock_releaseexclusive (&network_context->lock_checker); continue; } ptr_network = _r_obj_allocate (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); if (!_app_network_getpath (ptr_network, tcp6_table->table[i].dwOwningPid, tcp6_table->table[i].OwningModuleInfo)) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET6; ptr_network->protocol = IPPROTO_TCP; ptr_network->protocol_str = _r_obj_createstring (_app_db_getprotoname (ptr_network->protocol, ptr_network->af)); RtlCopyMemory (ptr_network->remote_addr6.u.Byte, tcp6_table->table[i].ucRemoteAddr, FWP_V6_ADDR_SIZE); ptr_network->remote_port = _r_byteswap_ushort ((USHORT)tcp6_table->table[i].dwRemotePort); RtlCopyMemory (ptr_network->local_addr6.u.Byte, tcp6_table->table[i].ucLocalAddr, FWP_V6_ADDR_SIZE); ptr_network->local_port = _r_byteswap_ushort ((USHORT)tcp6_table->table[i].dwLocalPort); ptr_network->state = tcp6_table->table[i].dwState; if (tcp6_table->table[i].dwState == MIB_TCP_STATE_ESTAB) { if (_app_network_isvalidconnection (ptr_network->af, &ptr_network->remote_addr6) || _app_network_isvalidconnection (ptr_network->af, &ptr_network->local_addr6)) ptr_network->is_connection = TRUE; } _r_queuedlock_acquireexclusive (&network_context->lock_network); _r_obj_addhashtablepointer (network_context->network_ptr, network_hash, ptr_network); _r_queuedlock_releaseexclusive (&network_context->lock_network); _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, _r_obj_reference (ptr_network->path)); _r_queuedlock_releaseexclusive (&network_context->lock_checker); } } } required_size = 0; GetExtendedUdpTable (NULL, &required_size, FALSE, AF_INET, UDP_TABLE_OWNER_MODULE, 0); if (required_size) { if (allocated_size < required_size) { buffer = _r_mem_reallocate (buffer, required_size); allocated_size = required_size; } udp4_table = buffer; status = GetExtendedUdpTable (udp4_table, &required_size, FALSE, AF_INET, UDP_TABLE_OWNER_MODULE, 0); if (status == NO_ERROR) { for (ULONG i = 0; i < udp4_table->dwNumEntries; i++) { RtlZeroMemory (&local_addr, sizeof (local_addr)); local_addr.S_un.S_addr = udp4_table->table[i].dwLocalAddr; network_hash = _app_network_gethash ( AF_INET, udp4_table->table[i].dwOwningPid, NULL, 0, &local_addr, udp4_table->table[i].dwLocalPort, IPPROTO_UDP, 0 ); if (_app_network_isitemfound (network_hash)) { _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, NULL); _r_queuedlock_releaseexclusive (&network_context->lock_checker); continue; } ptr_network = _r_obj_allocate (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); if (!_app_network_getpath (ptr_network, udp4_table->table[i].dwOwningPid, udp4_table->table[i].OwningModuleInfo)) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET; ptr_network->protocol = IPPROTO_UDP; ptr_network->protocol_str = _r_obj_createstring (_app_db_getprotoname (ptr_network->protocol, ptr_network->af)); ptr_network->local_addr.S_un.S_addr = udp4_table->table[i].dwLocalAddr; ptr_network->local_port = _r_byteswap_ushort ((USHORT)udp4_table->table[i].dwLocalPort); if (_app_network_isvalidconnection (ptr_network->af, &ptr_network->local_addr)) ptr_network->is_connection = TRUE; _r_queuedlock_acquireexclusive (&network_context->lock_network); _r_obj_addhashtablepointer (network_context->network_ptr, network_hash, ptr_network); _r_queuedlock_releaseexclusive (&network_context->lock_network); _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, _r_obj_reference (ptr_network->path)); _r_queuedlock_releaseexclusive (&network_context->lock_checker); } } } required_size = 0; GetExtendedUdpTable (NULL, &required_size, FALSE, AF_INET6, UDP_TABLE_OWNER_MODULE, 0); if (required_size) { if (allocated_size < required_size) { buffer = _r_mem_reallocate (buffer, required_size); allocated_size = required_size; } udp6_table = buffer; status = GetExtendedUdpTable (udp6_table, &required_size, FALSE, AF_INET6, UDP_TABLE_OWNER_MODULE, 0); if (status == NO_ERROR) { for (ULONG i = 0; i < udp6_table->dwNumEntries; i++) { network_hash = _app_network_gethash ( AF_INET6, udp6_table->table[i].dwOwningPid, NULL, 0, udp6_table->table[i].ucLocalAddr, udp6_table->table[i].dwLocalPort, IPPROTO_UDP, 0 ); if (_app_network_isitemfound (network_hash)) { _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, NULL); _r_queuedlock_releaseexclusive (&network_context->lock_checker); continue; } ptr_network = _r_obj_allocate (sizeof (ITEM_NETWORK), &_app_dereferencenetwork); if (!_app_network_getpath (ptr_network, udp6_table->table[i].dwOwningPid, udp6_table->table[i].OwningModuleInfo)) { _r_obj_dereference (ptr_network); continue; } ptr_network->af = AF_INET6; ptr_network->protocol = IPPROTO_UDP; ptr_network->protocol_str = _r_obj_createstring (_app_db_getprotoname (ptr_network->protocol, ptr_network->af)); RtlCopyMemory (ptr_network->local_addr6.u.Byte, udp6_table->table[i].ucLocalAddr, FWP_V6_ADDR_SIZE); ptr_network->local_port = _r_byteswap_ushort ((USHORT)udp6_table->table[i].dwLocalPort); if (_app_network_isvalidconnection (ptr_network->af, &ptr_network->local_addr6)) ptr_network->is_connection = TRUE; _r_queuedlock_acquireexclusive (&network_context->lock_network); _r_obj_addhashtablepointer (network_context->network_ptr, network_hash, ptr_network); _r_queuedlock_releaseexclusive (&network_context->lock_network); _r_queuedlock_acquireexclusive (&network_context->lock_checker); _r_obj_addhashtablepointer (network_context->checker_ptr, network_hash, _r_obj_reference (ptr_network->path)); _r_queuedlock_releaseexclusive (&network_context->lock_checker); } } } if (buffer) _r_mem_free (buffer); } _Ret_maybenull_ PITEM_NETWORK _app_network_getitem ( _In_ ULONG network_hash ) { PITEM_NETWORK_CONTEXT network_context; PITEM_NETWORK ptr_network; network_context = _app_network_getcontext (); if (!network_context) return NULL; _r_queuedlock_acquireshared (&network_context->lock_network); ptr_network = _r_obj_findhashtablepointer (network_context->network_ptr, network_hash); _r_queuedlock_releaseshared (&network_context->lock_network); return ptr_network; } _Success_ (return != 0) ULONG _app_network_getappitem ( _In_ ULONG network_hash ) { PITEM_NETWORK ptr_network; ULONG hash_code; ptr_network = _app_network_getitem (network_hash); if (!ptr_network) return 0; hash_code = ptr_network->app_hash; _r_obj_dereference (ptr_network); return hash_code; } ULONG _app_network_gethash ( _In_ ADDRESS_FAMILY af, _In_ ULONG pid, _In_opt_ LPCVOID remote_addr, _In_opt_ ULONG remote_port, _In_opt_ LPCVOID local_addr, _In_opt_ ULONG local_port, _In_ UINT8 proto, _In_opt_ ULONG state ) { WCHAR remote_address[LEN_IP_MAX] = {0}; WCHAR local_address[LEN_IP_MAX] = {0}; PR_STRING network_string; ULONG network_hash; if (remote_addr) _app_formatip (af, remote_addr, remote_address, RTL_NUMBER_OF (remote_address), FALSE); if (local_addr) _app_formatip (af, local_addr, local_address, RTL_NUMBER_OF (local_address), FALSE); network_string = _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, remote_address, remote_port, local_address, local_port, proto, state ); network_hash = _r_str_gethash (&network_string->sr, TRUE); _r_obj_dereference (network_string); return network_hash; } BOOLEAN _app_network_getpath ( _Inout_ PITEM_NETWORK ptr_network, _In_ ULONG pid, _In_opt_ PULONG64 modules ) { PTOKEN_APPCONTAINER_INFORMATION app_container = NULL; PR_STRING process_name = NULL; HANDLE hprocess; HANDLE htoken; NTSTATUS status; if (pid == PROC_WAITING_PID) { ptr_network->app_hash = 0; ptr_network->type = DATA_APP_REGULAR; ptr_network->path = _r_obj_createstring (PROC_WAITING_NAME); return TRUE; } else if (pid == PROC_SYSTEM_PID) { ptr_network->app_hash = config.ntoskrnl_hash; ptr_network->type = DATA_APP_REGULAR; ptr_network->path = _r_obj_createstring (PROC_SYSTEM_NAME); return TRUE; } if (modules) { process_name = _r_sys_querytaginformation (pid, ULongToPtr (*(PULONG)modules)); if (process_name) ptr_network->type = DATA_APP_SERVICE; } if (!process_name) { status = _r_sys_openprocess (pid, PROCESS_QUERY_LIMITED_INFORMATION, &hprocess); if (NT_SUCCESS (status)) { if (_r_sys_isprocessimmersive (hprocess)) { ptr_network->type = DATA_APP_UWP; } else { ptr_network->type = DATA_APP_REGULAR; } if (ptr_network->type == DATA_APP_UWP) { status = NtOpenProcessTokenEx (hprocess, TOKEN_QUERY, 0, &htoken); if (NT_SUCCESS (status)) { status = _r_sys_querytokeninformation (htoken, TokenAppContainerSid, (PVOID_PTR)&app_container); if (NT_SUCCESS (status)) { _r_str_fromsid (app_container->TokenAppContainer, &process_name); _r_mem_free (app_container); } NtClose (htoken); } } if (!process_name) { status = _r_sys_queryprocessstring (hprocess, ProcessImageFileNameWin32, &process_name); // fix for WSL processes (issue #606) if (status == STATUS_UNSUCCESSFUL) status = _r_sys_queryprocessstring (hprocess, ProcessImageFileName, &process_name); } NtClose (hprocess); } } if (process_name) { ptr_network->app_hash = _r_str_gethash (&process_name->sr, TRUE); ptr_network->path = process_name; return TRUE; } return FALSE; } BOOLEAN _app_network_isapphaveconnection ( _In_ ULONG app_hash ) { PITEM_NETWORK_CONTEXT network_context; PITEM_NETWORK ptr_network = NULL; ULONG_PTR enum_key = 0; network_context = _app_network_getcontext (); if (!network_context) return FALSE; _r_queuedlock_acquireshared (&network_context->lock_network); while (_r_obj_enumhashtablepointer (network_context->network_ptr, (PVOID_PTR)&ptr_network, NULL, &enum_key)) { if (ptr_network->app_hash != app_hash) continue; if (ptr_network->is_connection) { _r_queuedlock_releaseshared (&network_context->lock_network); return TRUE; } } _r_queuedlock_releaseshared (&network_context->lock_network); return FALSE; } BOOLEAN _app_network_isitemfound ( _In_ ULONG network_hash ) { PITEM_NETWORK_CONTEXT network_context; BOOLEAN is_found; network_context = _app_network_getcontext (); if (!network_context) return FALSE; _r_queuedlock_acquireshared (&network_context->lock_network); is_found = (_r_obj_findhashtable (network_context->network_ptr, network_hash) != NULL); _r_queuedlock_releaseshared (&network_context->lock_network); return is_found; } BOOLEAN _app_network_isvalidconnection ( _In_ ADDRESS_FAMILY af, _In_ LPCVOID address ) { PIN_ADDR p4addr; PIN6_ADDR p6addr; switch (af) { case AF_INET: { p4addr = (PIN_ADDR)address; 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)); } case AF_INET6: { p6addr = (PIN6_ADDR)address; 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_network_printlistviewtable ( _Inout_ PITEM_NETWORK_CONTEXT network_context ) { PITEM_NETWORK ptr_network = NULL; PR_STRING string; ULONG_PTR enum_key = 0; ULONG_PTR app_hash; ULONG network_hash; INT item_count; BOOLEAN is_highlight = FALSE; BOOLEAN is_refresh = FALSE; if (_r_config_getboolean (L"IsEnableHighlighting", TRUE, NULL) && _r_config_getboolean (L"IsHighlightConnection", TRUE, L"colors")) is_highlight = TRUE; // add new connections into listview _r_queuedlock_acquireshared (&network_context->lock_network); while (_r_obj_enumhashtablepointer (network_context->network_ptr, (PVOID_PTR)&ptr_network, &network_hash, &enum_key)) { string = _r_obj_findhashtablepointer (network_context->checker_ptr, network_hash); if (!string) continue; _app_listview_addnetworkitem (network_context->hwnd, network_hash); if (ptr_network->path && ptr_network->app_hash) _app_getfileinformation (ptr_network->path, ptr_network->app_hash, ptr_network->type, IDC_NETWORK); // resolve network address _app_queue_resolver (network_context->hwnd, IDC_NETWORK, network_hash, ptr_network); _r_obj_dereference (string); is_refresh = TRUE; } _r_queuedlock_releaseshared (&network_context->lock_network); // refresh network tab if (is_refresh) _app_listview_updateby_id (network_context->hwnd, IDC_NETWORK, PR_UPDATE_NORESIZE); // remove closed connections from list item_count = _r_listview_getitemcount (network_context->hwnd, IDC_NETWORK); if (!item_count) return; for (INT i = item_count - 1; i != INT_ERROR; i--) { network_hash = (ULONG)_app_listview_getitemcontext (network_context->hwnd, IDC_NETWORK, i); if (_r_obj_findhashtable (network_context->checker_ptr, network_hash)) continue; _r_listview_deleteitem (network_context->hwnd, IDC_NETWORK, i); app_hash = _app_network_getappitem (network_hash); _app_network_removeitem (network_hash); // redraw listview item if (!is_highlight || !app_hash) continue; _app_listview_updateby_param (network_context->hwnd, app_hash, PR_SETITEM_REDRAW, TRUE); } } VOID _app_network_removeitem ( _In_ ULONG network_hash ) { PITEM_NETWORK_CONTEXT network_context; network_context = _app_network_getcontext (); if (!network_context) return; _r_queuedlock_acquireexclusive (&network_context->lock_network); _r_obj_removehashtableitem (network_context->network_ptr, network_hash); _r_queuedlock_releaseexclusive (&network_context->lock_network); } VOID NTAPI _app_network_threadproc ( _In_ PVOID arglist ) { PITEM_NETWORK_CONTEXT network_context; network_context = (PITEM_NETWORK_CONTEXT)arglist; while (TRUE) { // update network table _app_network_generatetable (network_context); _app_network_printlistviewtable (network_context); _r_sys_waitforsingleobject (NtCurrentThread (), 3000); } _app_network_uninitialize (network_context); } ================================================ FILE: src/network.h ================================================ // simplewall // Copyright (c) 2019-2025 Henry++ #pragma once typedef struct _ITEM_NETWORK_CONTEXT { HWND hwnd; R_QUEUED_LOCK lock_network; R_QUEUED_LOCK lock_checker; PR_HASHTABLE network_ptr; PR_HASHTABLE checker_ptr; } ITEM_NETWORK_CONTEXT, *PITEM_NETWORK_CONTEXT; VOID _app_network_initialize ( _In_ HWND hwnd ); VOID _app_network_uninitialize ( _In_ PITEM_NETWORK_CONTEXT context ); VOID _app_network_generatetable ( _Inout_ PITEM_NETWORK_CONTEXT context ); _Ret_maybenull_ PITEM_NETWORK _app_network_getitem ( _In_ ULONG network_hash ); _Success_ (return != 0) ULONG _app_network_getappitem ( _In_ ULONG network_hash ); ULONG _app_network_gethash ( _In_ ADDRESS_FAMILY af, _In_ ULONG pid, _In_opt_ LPCVOID remote_addr, _In_opt_ ULONG remote_port, _In_opt_ LPCVOID local_addr, _In_opt_ ULONG local_port, _In_ UINT8 proto, _In_opt_ ULONG state ); BOOLEAN _app_network_getpath ( _Inout_ PITEM_NETWORK ptr_network, _In_ ULONG pid, _In_opt_ PULONG64 modules ); BOOLEAN _app_network_isapphaveconnection ( _In_ ULONG app_hash ); BOOLEAN _app_network_isitemfound ( _In_ ULONG network_hash ); BOOLEAN _app_network_isvalidconnection ( _In_ ADDRESS_FAMILY af, _In_ LPCVOID address ); VOID _app_network_printlistviewtable ( _Inout_ PITEM_NETWORK_CONTEXT context ); VOID _app_network_removeitem ( _In_ ULONG network_hash ); VOID NTAPI _app_network_threadproc ( _In_ PVOID arglist ); ================================================ FILE: src/notifications.c ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #include "global.h" _Ret_maybenull_ HWND _app_notify_getwindow ( _In_opt_ PITEM_LOG ptr_log ) { HWND hwnd; hwnd = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hnotification, NULL, NULL); if (hwnd) { if (ptr_log) _app_notify_show (hwnd, ptr_log); return hwnd; } if (!ptr_log) return NULL; _r_wnd_createwindow (_r_sys_getimagebase (), MAKEINTRESOURCE (IDD_NOTIFICATION), NULL, &NotificationProc, ptr_log); _r_sys_waitforsingleobject (config.hnotify_evt, 2000); return _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hnotification, NULL, NULL); } _Ret_maybenull_ PNOTIFY_CONTEXT _app_notify_getcontext ( _In_ HWND hwnd ) { PNOTIFY_CONTEXT context; context = _r_wnd_getcontext (hwnd, SHORT_MAX); return context; } VOID _app_notify_setcontext ( _In_ HWND hwnd, _In_opt_ PNOTIFY_CONTEXT context ) { if (context) context->hwnd = hwnd; if (context) { _r_wnd_setcontext (hwnd, SHORT_MAX, context); } else { _r_wnd_removecontext (hwnd, SHORT_MAX); } } BOOLEAN _app_notify_command ( _In_ HWND hwnd, _In_ INT button_id, _In_opt_ LONG64 seconds ) { PITEM_APP ptr_app; PR_LIST rules; HANDLE hengine; ULONG app_hash; app_hash = _app_notify_getapp_id (hwnd); ptr_app = _app_getappitem (app_hash); if (!ptr_app) return FALSE; _app_notify_freeobject (hwnd, ptr_app); rules = _r_obj_createlist (4, NULL); if (button_id == IDC_ALLOW_BTN || button_id == IDC_BLOCK_BTN) { ptr_app->is_enabled = (button_id == IDC_ALLOW_BTN); ptr_app->is_silent = (button_id == IDC_BLOCK_BTN); if (ptr_app->is_enabled && seconds) { _app_timer_set (_r_app_gethwnd (), ptr_app, seconds); } else { _app_listview_updateitemby_param (_r_app_gethwnd (), app_hash, TRUE); } _r_obj_addlistitem (rules, ptr_app, NULL); } else if (button_id == IDC_NEXT_BTN) { // NOTHING! } else if (button_id == IDM_DISABLENOTIFICATIONS) { ptr_app->is_silent = TRUE; } ptr_app->last_notify = _r_unixtime_now (); if (rules->count) { if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); _wfp_create3filters (hengine, rules, DBG_ARG, FALSE); } } _app_listview_updateby_id (_r_app_gethwnd (), ptr_app->type, PR_UPDATE_TYPE); _r_obj_dereference (ptr_app); _r_obj_dereference (rules); _app_profile_save (hwnd); return TRUE; } BOOLEAN _app_notify_addobject ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log, _Inout_ PITEM_APP ptr_app ) { LONG64 current_time; LONG64 notification_timeout; current_time = _r_unixtime_now (); notification_timeout = _r_config_getlong64 (L"NotificationsTimeout", NOTIFY_TIMEOUT_DEFAULT, NULL); // check for last display time if (notification_timeout && ((current_time - ptr_app->last_notify) <= notification_timeout)) return FALSE; ptr_app->last_notify = current_time; _r_obj_swapreference (&ptr_app->notification, ptr_log); if (_r_wnd_sendmessage (hwnd, 0, WM_NOTIFICATION, 0, (LPARAM)ptr_app->notification)) { if (_r_config_getboolean (L"IsNotificationsSound", TRUE, NULL)) { if (!_r_config_getboolean (L"IsNotificationsFullscreenSilentMode", TRUE, NULL) || !_r_wnd_isfullscreenmode ()) _app_notify_playsound (); } return TRUE; } return FALSE; } VOID _app_notify_freeobject ( _In_opt_ HWND hwnd, _Inout_ PITEM_APP ptr_app ) { ULONG_PTR app_hash; if (!hwnd) hwnd = _app_notify_getwindow (NULL); if (ptr_app->notification) _r_obj_clearreference (&ptr_app->notification); if (!hwnd) return; app_hash = _app_notify_getnextapp_id (hwnd); if (app_hash) { _app_notify_refresh (hwnd); } else { DestroyWindow (hwnd); } } _Ret_maybenull_ PITEM_LOG _app_notify_getobject ( _In_ ULONG app_hash ) { PITEM_APP ptr_app; PITEM_LOG ptr_log; ptr_app = _app_getappitem (app_hash); if (!ptr_app) return NULL; ptr_log = _r_obj_referencesafe (ptr_app->notification); _r_obj_dereference (ptr_app); return ptr_log; } _Ret_maybenull_ HICON _app_notify_getapp_icon ( _In_ HWND hwnd ) { PNOTIFY_CONTEXT context; context = _app_notify_getcontext (hwnd); if (!context) return NULL; return context->hicon; } ULONG _app_notify_getapp_id ( _In_ HWND hwnd ) { PNOTIFY_CONTEXT context; context = _app_notify_getcontext (hwnd); if (!context) return 0; return context->app_hash; } ULONG _app_notify_getnextapp_id ( _In_ HWND hwnd ) { PNOTIFY_CONTEXT context; PITEM_APP ptr_app = NULL; ULONG_PTR enum_key = 0; ULONG app_hash = 0; context = _app_notify_getcontext (hwnd); if (context) app_hash = context->app_hash; _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (!ptr_app->notification) continue; // exclude current app from enumeration if (ptr_app->app_hash == app_hash) continue; app_hash = ptr_app->app_hash; break; } _r_queuedlock_releaseshared (&lock_apps); if (context) context->app_hash = app_hash; return app_hash; } VOID _app_notify_setapp_icon ( _In_ HWND hwnd, _In_opt_ HICON hicon ) { PNOTIFY_CONTEXT context; HICON hicon_prev; context = _app_notify_getcontext (hwnd); if (!context) return; if (!hicon) hicon = _app_icons_getdefaultapp_hicon (); hicon_prev = context->hicon; context->hicon = hicon; RedrawWindow (hwnd, NULL, NULL, RDW_ALLCHILDREN | RDW_ERASE | RDW_INVALIDATE); if (hicon_prev) DestroyIcon (hicon_prev); } VOID _app_notify_setapp_id ( _In_ HWND hwnd, _In_opt_ ULONG app_hash ) { PNOTIFY_CONTEXT context; context = _app_notify_getcontext (hwnd); if (!context) return; context->app_hash = app_hash; } VOID _app_notify_show ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log ) { PR_STRING localized_string = NULL; PR_STRING string = NULL; PR_STRING loading; PR_STRING empty; WCHAR window_title[128]; PITEM_APP ptr_app; HDWP hdefer; BOOLEAN is_fullscreenmode; ptr_app = _app_getappitem (ptr_log->app_hash); if (!ptr_app) { DestroyWindow (hwnd); return; } // set notification information _app_notify_setapp_id (hwnd, ptr_log->app_hash); _app_notify_setapp_icon (hwnd, NULL); // set window title _r_str_printf (window_title, RTL_NUMBER_OF (window_title), L"%s - %s", _r_locale_getstring (IDS_NOTIFY_TITLE), _r_app_getname ()); _r_ctrl_setstring (hwnd, 0, window_title); hdefer = BeginDeferWindowPos (2); empty = _r_locale_getstring_ex (IDS_STATUS_EMPTY); if (_r_obj_isstringempty (empty)) _r_obj_movereference ((PVOID_PTR)&empty, _r_obj_createstring (L"Empty...")); // print name _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_NAME), L":")); _r_obj_movereference ((PVOID_PTR)&string, _app_getappdisplayname (ptr_app, TRUE)); _r_ctrl_settablestring (hwnd, &hdefer, IDC_FILE_ID, &localized_string->sr, IDC_FILE_TEXT, string ? &string->sr : &empty->sr); loading = _r_locale_getstring_ex (IDS_LOADING); if (_r_obj_isstringempty (loading)) _r_obj_movereference ((PVOID_PTR)&loading, _r_obj_createstring (L"Loading...")); // print signature _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_SIGNATURE), L":")); _r_ctrl_settablestring (hwnd, &hdefer, IDC_SIGNATURE_ID, &localized_string->sr, IDC_SIGNATURE_TEXT, &loading->sr); // print address _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_ADDRESS), L":")); _r_ctrl_settablestring (hwnd, &hdefer, IDC_ADDRESS_ID, &localized_string->sr, IDC_ADDRESS_TEXT, &loading->sr); // print host _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_HOST), L":")); _r_ctrl_settablestring (hwnd, &hdefer, IDC_HOST_ID, &localized_string->sr, IDC_HOST_TEXT, &loading->sr); // print port _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_PORT), L":")); _r_obj_movereference ((PVOID_PTR)&string, _app_formatport (ptr_log->remote_port, ptr_log->protocol)); _r_ctrl_settablestring (hwnd, &hdefer, IDC_PORT_ID, &localized_string->sr, IDC_PORT_TEXT, string ? &string->sr : &empty->sr); // print direction _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_DIRECTION), L":")); _r_obj_movereference ((PVOID_PTR)&string, _app_db_getdirectionname (ptr_log->direction, ptr_log->is_loopback, TRUE)); _r_ctrl_settablestring (hwnd, &hdefer, IDC_DIRECTION_ID, &localized_string->sr, IDC_DIRECTION_TEXT, string ? &string->sr : &empty->sr); // print filter name _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_FILTER), L":")); _r_ctrl_settablestring (hwnd, &hdefer, IDC_FILTER_ID, &localized_string->sr, IDC_FILTER_TEXT, ptr_log->filter_name ? &ptr_log->filter_name->sr : &empty->sr); // print date _r_obj_movereference ((PVOID_PTR)&localized_string, _r_obj_concatstrings (2, _r_locale_getstring (IDS_DATE), L":")); _r_obj_movereference ((PVOID_PTR)&string, _r_format_unixtime (ptr_log->timestamp, FDTF_SHORTDATE | FDTF_LONGTIME)); _r_ctrl_settablestring (hwnd, &hdefer, IDC_DATE_ID, &localized_string->sr, IDC_DATE_TEXT, string ? &string->sr : &empty->sr); if (hdefer) EndDeferWindowPos (hdefer); //_r_ctrl_setstring (hwnd, IDC_RULES_BTN, _r_locale_getstring (IDS_TRAY_RULES)); _r_ctrl_setstring (hwnd, IDC_ALLOW_BTN, _r_locale_getstring (IDS_ACTION_ALLOW)); _r_ctrl_setstring (hwnd, IDC_BLOCK_BTN, _r_locale_getstring (IDS_ACTION_BLOCK)); // prevent fullscreen apps lose focus is_fullscreenmode = _r_wnd_isfullscreenmode (); if (!is_fullscreenmode) _r_wnd_top (hwnd, TRUE); // set safety timeout _app_notify_settimeout (hwnd); // set correct position _app_notify_setposition (hwnd, FALSE); ShowWindow (hwnd, SW_SHOWNOACTIVATE); InvalidateRect (hwnd, NULL, TRUE); // query busy information _app_notify_queueinfo (hwnd, ptr_log); if (string) _r_obj_dereference (string); _r_obj_dereference (loading); _r_obj_dereference (empty); _r_obj_dereference (ptr_app); } // Play notification sound even if system have "nosound" mode VOID _app_notify_playsound () { static volatile PR_STRING cached_path = NULL; PR_STRING current_path; PR_STRING path; HANDLE hkey; ULONG flags = SND_ASYNC | SND_NODEFAULT | SND_NOWAIT | SND_SENTRY; NTSTATUS status; current_path = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&cached_path, NULL, NULL); if (_r_obj_isstringempty (current_path) || !_r_fs_isexists (¤t_path->sr)) { status = _r_reg_openkey (HKEY_CURRENT_USER, L"AppEvents\\Schemes\\Apps\\.Default\\" NOTIFY_SOUND_NAME L"\\.Default", 0, KEY_READ, &hkey); if (NT_SUCCESS (status)) { status = _r_reg_querystring (hkey, NULL, &path, NULL); if (NT_SUCCESS (status)) { current_path = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&cached_path, path, current_path); if (current_path) _r_obj_dereference (path); } NtClose (hkey); } } if (_r_obj_isstringempty (current_path) || !_r_fs_isexists (¤t_path->sr) || !PlaySoundW (current_path->buffer, NULL, flags | SND_FILENAME)) PlaySoundW (NOTIFY_SOUND_NAME, NULL, flags); } VOID _app_notify_queueinfo ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log ) { PITEM_CONTEXT context; context = _r_freelist_allocateitem (&context_free_list); context->hwnd = hwnd; context->base_address = _r_obj_reference (ptr_log); _r_workqueue_queueitem (&resolve_notify_queue, &_app_queue_notifyinformation, context); } VOID _app_notify_killprocess ( _In_ HWND hwnd ) { PSYSTEM_PROCESS_INFORMATION process; PSYSTEM_PROCESS_INFORMATION spi; PNOTIFY_CONTEXT context; HANDLE process_handle; PITEM_APP ptr_app; PR_STRING path; PR_STRING file_name; NTSTATUS status; context = _app_notify_getcontext (hwnd); if (!context) return; ptr_app = _app_getappitem (context->app_hash); if (!ptr_app) return; status = _r_sys_enumprocesses (&spi); if (!NT_SUCCESS (status)) { _r_show_errormessage (hwnd, L"Cannot enumerate processes!", status, NULL, ET_NATIVE); _r_log (LOG_LEVEL_ERROR, NULL, L"_r_sys_enumprocesses", status, NULL); return; } file_name = _r_path_getbasenamestring (&ptr_app->real_path->sr); process = PR_FIRST_PROCESS (spi); do { if (!process->ImageName.Buffer) continue; if (_r_str_compare (process->ImageName.Buffer, file_name->buffer, TRUE) == 0) { status = _r_sys_getprocessimagepathbyid (HandleToULong (process->UniqueProcessId), TRUE, &path); if (NT_SUCCESS (status)) { if (_r_str_isequal (&path->sr, &ptr_app->real_path->sr, TRUE)) { status = _r_sys_openprocess (HandleToULong (process->UniqueProcessId), PROCESS_TERMINATE, &process_handle); if (NT_SUCCESS (status)) { status = NtTerminateProcess (process_handle, STATUS_SUCCESS); if (!NT_SUCCESS (status)) _r_show_errormessage (hwnd, L"Cannot terminate process!", status, file_name->buffer, ET_NATIVE); NtClose (process_handle); } else { _r_show_errormessage (hwnd, L"Cannot open process!", status, file_name->buffer, ET_NATIVE); } } _r_obj_dereference (path); } else { _r_show_errormessage (hwnd, L"Cannot get process path!", status, file_name->buffer, ET_NATIVE); } } } while ((process = PR_NEXT_PROCESS (process))); _r_obj_dereference (file_name); _r_mem_free (spi); } VOID _app_notify_refresh ( _In_ HWND hwnd ) { PITEM_LOG ptr_log; ULONG app_hash; if (!_r_wnd_isvisible (hwnd, TRUE)) { DestroyWindow (hwnd); return; } if (!_r_config_getboolean (L"IsNotificationsEnabled", TRUE, NULL)) { DestroyWindow (hwnd); return; } app_hash = _app_notify_getapp_id (hwnd); ptr_log = _app_notify_getobject (app_hash); if (!ptr_log) { DestroyWindow (hwnd); return; } _app_notify_show (hwnd, ptr_log); _r_obj_dereference (ptr_log); } VOID _app_notify_setposition ( _In_ HWND hwnd, _In_ BOOLEAN is_forced ) { MONITORINFO monitor_info = {0}; APPBARDATA taskbar_rect = {0}; R_RECTANGLE window_rect; HMONITOR hmonitor; PRECT rect; LONG dpi_value; LONG border_x; BOOLEAN is_intray; _r_wnd_getposition (hwnd, &window_rect); if (!is_forced && _r_wnd_isvisible (hwnd, FALSE)) { _r_wnd_adjustrectangletoworkingarea (hwnd, &window_rect); _r_wnd_setposition (hwnd, &window_rect.position, NULL); return; } is_intray = _r_config_getboolean (L"IsNotificationsOnTray", FALSE, NULL); if (is_intray) { monitor_info.cbSize = sizeof (MONITORINFO); hmonitor = MonitorFromWindow (hwnd, MONITOR_DEFAULTTONEAREST); if (GetMonitorInfoW (hmonitor, &monitor_info)) { taskbar_rect.cbSize = sizeof (APPBARDATA); if (SHAppBarMessage (ABM_GETTASKBARPOS, &taskbar_rect)) { dpi_value = _r_dc_getwindowdpi (hwnd); border_x = _r_dc_getsystemmetrics (SM_CXBORDER, dpi_value); rect = &monitor_info.rcWork; if (taskbar_rect.uEdge == ABE_LEFT) { window_rect.left = taskbar_rect.rc.right + border_x; window_rect.top = (rect->bottom - window_rect.height) - border_x; } else if (taskbar_rect.uEdge == ABE_TOP) { window_rect.left = (rect->right - window_rect.width) - border_x; window_rect.top = taskbar_rect.rc.bottom + border_x; } else if (taskbar_rect.uEdge == ABE_RIGHT) { window_rect.left = (rect->right - window_rect.width) - border_x; window_rect.top = (rect->bottom - window_rect.height) - border_x; } else //if (taskbar_rect.uEdge == ABE_BOTTOM) { window_rect.left = (rect->right - window_rect.width) - border_x; window_rect.top = (rect->bottom - window_rect.height) - border_x; } _r_wnd_adjustrectangletoworkingarea (NULL, &window_rect); _r_wnd_setposition (hwnd, &window_rect.position, NULL); return; } } } // display window on center (depends on error, config etc...) _r_wnd_center (hwnd, NULL); _r_window_restoreposition (hwnd, L"notification"); } VOID _app_notify_settimeout ( _In_ HWND hwnd ) { _r_ctrl_enable (hwnd, IDC_RULES_BTN, FALSE); _r_ctrl_enable (hwnd, IDC_KILLPROCESS_BTN, FALSE); _r_ctrl_enable (hwnd, IDC_ALLOW_BTN, FALSE); _r_ctrl_enable (hwnd, IDC_BLOCK_BTN, FALSE); _r_ctrl_enable (hwnd, IDC_NEXT_BTN, FALSE); SetTimer (hwnd, NOTIFY_TIMER_SAFETY_ID, NOTIFY_TIMER_SAFETY_TIMEOUT, NULL); } VOID _app_notify_initialize ( _Inout_ PNOTIFY_CONTEXT context, _In_ LONG dpi_value ) { NONCLIENTMETRICS ncm = {0}; HBITMAP hbmp_allow; HBITMAP hbmp_block; HBITMAP hbmp_cross; HBITMAP hbmp_next; HBITMAP hbmp_rules; LONG icon_small; LONG icon_large; // destroy previous resources SAFE_DELETE_OBJECT (context->hfont_title); SAFE_DELETE_OBJECT (context->hfont_link); SAFE_DELETE_OBJECT (context->hfont_text); SAFE_DELETE_ICON (context->hico_allow); SAFE_DELETE_ICON (context->hico_block); SAFE_DELETE_ICON (context->hico_cross); SAFE_DELETE_ICON (context->hico_next); SAFE_DELETE_ICON (context->hico_rules); icon_small = _r_dc_getsystemmetrics (SM_CXSMICON, dpi_value); icon_large = _r_dc_getsystemmetrics (SM_CXICON, dpi_value); // set window icon _r_wnd_seticon ( context->hwnd, _r_sys_loadsharedicon (NULL, MAKEINTRESOURCE (SIH_EXCLAMATION), icon_small), _r_sys_loadsharedicon (NULL, MAKEINTRESOURCE (SIH_EXCLAMATION), icon_large) ); // set window font ncm.cbSize = sizeof (ncm); if (_r_dc_getsystemparametersinfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, dpi_value)) { context->hfont_title = _app_createfont (&ncm.lfCaptionFont, 12, FALSE, dpi_value); context->hfont_link = _app_createfont (&ncm.lfMessageFont, 9, TRUE, dpi_value); context->hfont_text = _app_createfont (&ncm.lfMessageFont, 9, FALSE, dpi_value); _r_ctrl_setfont (context->hwnd, 0, context->hfont_text); _r_ctrl_setfont (context->hwnd, IDC_HEADER_ID, context->hfont_title); _r_ctrl_setfont (context->hwnd, IDC_FILE_TEXT, context->hfont_link); for (INT i = IDC_SIGNATURE_TEXT; i <= IDC_DATE_TEXT; i++) _r_ctrl_settextmargin (context->hwnd, i, 0, 0); for (INT i = IDC_SIGNATURE_TEXT; i <= IDC_NEXT_BTN; i++) _r_ctrl_setfont (context->hwnd, i, context->hfont_text); } // load images _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_SETTINGS), &GUID_ContainerFormatPng, icon_small, icon_small, &hbmp_rules); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_ALLOW), &GUID_ContainerFormatPng, icon_small, icon_small, &hbmp_allow); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_BLOCK), &GUID_ContainerFormatPng, icon_small, icon_small, &hbmp_block); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_CROSS), &GUID_ContainerFormatPng, icon_small, icon_small, &hbmp_cross); _r_res_loadimage (_r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_NEXT), &GUID_ContainerFormatPng, icon_small, icon_small, &hbmp_next); // set button configuration if (hbmp_rules) { context->hico_rules = _r_dc_bitmaptoicon (hbmp_rules, icon_small, icon_small); DeleteObject (hbmp_rules); } if (hbmp_cross) { context->hico_cross = _r_dc_bitmaptoicon (hbmp_cross, icon_small, icon_small); DeleteObject (hbmp_cross); } if (hbmp_allow) { context->hico_allow = _r_dc_bitmaptoicon (hbmp_allow, icon_small, icon_small); DeleteObject (hbmp_allow); } if (hbmp_block) { context->hico_block = _r_dc_bitmaptoicon (hbmp_block, icon_small, icon_small); DeleteObject (hbmp_block); } if (hbmp_next) { context->hico_next = _r_dc_bitmaptoicon (hbmp_next, icon_small, icon_small); DeleteObject (hbmp_next); } _r_ctrl_seticon (context->hwnd, IDC_RULES_BTN, context->hico_rules); _r_ctrl_seticon (context->hwnd, IDC_KILLPROCESS_BTN, context->hico_cross); _r_ctrl_seticon (context->hwnd, IDC_ALLOW_BTN, context->hico_allow); _r_ctrl_seticon (context->hwnd, IDC_BLOCK_BTN, context->hico_block); _r_ctrl_seticon (context->hwnd, IDC_NEXT_BTN, context->hico_next); _r_ctrl_setbuttonmargins (context->hwnd, IDC_RULES_BTN, dpi_value); _r_ctrl_setbuttonmargins (context->hwnd, IDC_KILLPROCESS_BTN, dpi_value); _r_ctrl_setbuttonmargins (context->hwnd, IDC_ALLOW_BTN, dpi_value); _r_ctrl_setbuttonmargins (context->hwnd, IDC_BLOCK_BTN, dpi_value); _r_ctrl_setbuttonmargins (context->hwnd, IDC_NEXT_BTN, dpi_value); } VOID _app_notify_destroy ( _In_ HWND hwnd ) { PNOTIFY_CONTEXT context; context = _app_notify_getcontext (hwnd); if (!context) return; _app_notify_setcontext (hwnd, NULL); SAFE_DELETE_ICON (context->hicon); SAFE_DELETE_OBJECT (context->hfont_title); SAFE_DELETE_OBJECT (context->hfont_link); SAFE_DELETE_OBJECT (context->hfont_text); SAFE_DELETE_ICON (context->hico_allow); SAFE_DELETE_ICON (context->hico_block); SAFE_DELETE_ICON (context->hico_cross); SAFE_DELETE_ICON (context->hico_rules); _r_mem_free (context); } VOID _app_notify_drawgradient ( _In_ HDC hdc, _In_ LPCRECT rect ) { COLORREF gradient_arr[] = { RGB (0, 68, 112), RGB (7, 111, 95), }; GRADIENT_RECT gradient_rect = {0}; TRIVERTEX trivertx[2] = {0}; C_ASSERT (RTL_NUMBER_OF (gradient_arr) == RTL_NUMBER_OF (trivertx)); gradient_rect.LowerRight = 1; //gradient_rect.UpperLeft = 0; for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (trivertx); i++) { trivertx[i].Red = GetRValue (gradient_arr[i]) << 8; trivertx[i].Green = GetGValue (gradient_arr[i]) << 8; trivertx[i].Blue = GetBValue (gradient_arr[i]) << 8; if (i == 0) { trivertx[i].x = -1; trivertx[i].y = -1; } else { trivertx[i].x = rect->right; trivertx[i].y = rect->bottom; } } GradientFill (hdc, trivertx, RTL_NUMBER_OF (trivertx), &gradient_rect, 1, GRADIENT_FILL_RECT_H); } INT_PTR CALLBACK NotificationProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ) { switch (msg) { case WM_INITDIALOG: { PNOTIFY_CONTEXT context; PITEM_LOG ptr_log; HWND current_hwnd; HWND htip; LONG dpi_value; current_hwnd = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hnotification, hwnd, config.hnotification); if (current_hwnd) DestroyWindow (current_hwnd); // initialize window context context = _r_mem_allocate (sizeof (NOTIFY_CONTEXT)); _app_notify_setcontext (hwnd, context); // set correct position _app_notify_setposition (hwnd, FALSE); dpi_value = _r_dc_getwindowdpi (hwnd); _app_notify_initialize (context, dpi_value); // initialize tips htip = _r_ctrl_createtip (hwnd); if (htip) { _r_ctrl_settiptext (htip, hwnd, IDC_FILE_TEXT, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_RULES_BTN, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_KILLPROCESS_BTN, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_ALLOW_BTN, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_BLOCK_BTN, LPSTR_TEXTCALLBACK); _r_ctrl_settiptext (htip, hwnd, IDC_NEXT_BTN, L"NEXT!"); } // display log information ptr_log = (PITEM_LOG)lparam; _app_notify_show (hwnd, ptr_log); NtSetEvent (config.hnotify_evt, NULL); _r_obj_dereference (ptr_log); _r_theme_initialize (hwnd); break; } case WM_CLOSE: { DestroyWindow (hwnd); break; } case WM_DESTROY: { _r_window_saveposition (hwnd, L"notification"); break; } case WM_NCDESTROY: { _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&config.hnotification, NULL, config.hnotification); _app_notify_destroy (hwnd); break; } case WM_TIMER: { KillTimer (hwnd, wparam); if (wparam != NOTIFY_TIMER_SAFETY_ID) break; _r_ctrl_enable (hwnd, IDC_RULES_BTN, TRUE); _r_ctrl_enable (hwnd, IDC_KILLPROCESS_BTN, TRUE); _r_ctrl_enable (hwnd, IDC_ALLOW_BTN, TRUE); _r_ctrl_enable (hwnd, IDC_BLOCK_BTN, TRUE); _r_ctrl_enable (hwnd, IDC_NEXT_BTN, TRUE); break; } case WM_DPICHANGED: { PNOTIFY_CONTEXT context; context = _app_notify_getcontext (hwnd); _r_wnd_message_dpichanged (hwnd, wparam, lparam); if (context) _app_notify_initialize (context, LOWORD (wparam)); _app_notify_refresh (hwnd); break; } case WM_SETTINGCHANGE: { _r_wnd_message_settingchange (hwnd, wparam, lparam); break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint (hwnd, &ps); if (!hdc) break; _r_dc_drawwindow (hdc, hwnd, TRUE); EndPaint (hwnd, &ps); break; } case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: { HDC hdc; INT text_clr; hdc = (HDC)wparam; if (msg == WM_CTLCOLORSTATIC && (GetDlgCtrlID ((HWND)lparam) == IDC_FILE_TEXT)) { text_clr = COLOR_HIGHLIGHT; } else { text_clr = COLOR_WINDOWTEXT; } SetBkMode (hdc, TRANSPARENT); // HACK!!! SetTextColor (hdc, GetSysColor (text_clr)); SetDCBrushColor (hdc, GetSysColor (COLOR_WINDOW)); return (INT_PTR)GetStockObject (DC_BRUSH); } case WM_DRAWITEM: { LPDRAWITEMSTRUCT draw_info; RECT rect; LONG dpi_value; LONG icon_size_x; LONG wnd_spacing; PR_STRING string; HICON hicon; draw_info = (LPDRAWITEMSTRUCT)lparam; if (draw_info->CtlID != IDC_HEADER_ID) break; dpi_value = _r_dc_getwindowdpi (hwnd); icon_size_x = _r_dc_getsystemmetrics (SM_CXICON, dpi_value); wnd_spacing = _r_dc_getdpi (12, dpi_value); SetBkMode (draw_info->hDC, TRANSPARENT); // HACK!!! // draw title gradient _app_notify_drawgradient (draw_info->hDC, &draw_info->rcItem); // draw title text string = _r_locale_getstring_ex (IDS_NOTIFY_HEADER); if (string) { SetTextColor (draw_info->hDC, RGB (255, 255, 255)); SetRect ( &rect, wnd_spacing, 0, _r_calc_rectwidth (&draw_info->rcItem) - (wnd_spacing * 3) - icon_size_x, _r_calc_rectheight (&draw_info->rcItem) ); _r_dc_drawtext (NULL, draw_info->hDC, &string->sr, &rect, 0, 0, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOCLIP | DT_NOPREFIX, 0); _r_obj_dereference (string); } // draw title icon hicon = _app_notify_getapp_icon (hwnd); if (hicon) { SetRect ( &rect, _r_calc_rectwidth (&draw_info->rcItem) - icon_size_x - wnd_spacing, (_r_calc_rectheight (&draw_info->rcItem) / 2) - (icon_size_x / 2), icon_size_x, icon_size_x ); DrawIconEx ( draw_info->hDC, rect.left, rect.top, hicon, rect.right, rect.bottom, 0, NULL, DI_IMAGE | DI_MASK ); } SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } case WM_SETCURSOR: { INT ctrl_id; ctrl_id = GetDlgCtrlID ((HWND)wparam); if (ctrl_id == IDC_FILE_TEXT) { SetCursor (LoadCursorW (NULL, IDC_HAND)); SetWindowLongPtrW (hwnd, DWLP_MSGRESULT, TRUE); return TRUE; } break; } case WM_LBUTTONDOWN: { _r_wnd_sendmessage (hwnd, 0, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0); break; } case WM_ENTERSIZEMOVE: case WM_EXITSIZEMOVE: case WM_CAPTURECHANGED: { HCURSOR hcursor; LONG_PTR ex_style; ex_style = _r_wnd_getstyle (hwnd, GWL_EXSTYLE); if (!(ex_style & WS_EX_LAYERED)) _r_wnd_setstyle (hwnd, WS_EX_LAYERED, WS_EX_LAYERED, GWL_EXSTYLE); hcursor = LoadCursorW (NULL, (msg == WM_ENTERSIZEMOVE) ? IDC_SIZEALL : IDC_ARROW); SetLayeredWindowAttributes (hwnd, 0, (msg == WM_ENTERSIZEMOVE) ? 150 : 255, LWA_ALPHA); SetCursor (hcursor); break; } case WM_NOTIFY: { LPNMHDR nmlp; nmlp = (LPNMHDR)lparam; switch (nmlp->code) { case BCN_DROPDOWN: { PNOTIFY_CONTEXT context; PITEM_LOG ptr_log; R_RECTANGLE rectangle; RECT rect; HMENU hsubmenu; INT ctrl_id; ctrl_id = (INT)(INT_PTR)nmlp->idFrom; if (!_r_ctrl_isenabled (hwnd, ctrl_id)) break; if (ctrl_id != IDC_ALLOW_BTN && ctrl_id != IDC_RULES_BTN) break; context = _app_notify_getcontext (hwnd); if (!context) break; ptr_log = _app_notify_getobject (context->app_hash); hsubmenu = CreatePopupMenu (); if (!hsubmenu) break; if (ctrl_id == IDC_RULES_BTN) { _app_generate_rulescontrol (hsubmenu, context->app_hash, ptr_log); } else if (ctrl_id == IDC_ALLOW_BTN) { _app_generate_timerscontrol (hsubmenu, context->app_hash); } if (GetClientRect (nmlp->hwndFrom, &rect)) { ClientToScreen (nmlp->hwndFrom, (PPOINT)&rect); _r_wnd_recttorectangle (&rectangle, &rect); _r_wnd_adjustrectangletoworkingarea (nmlp->hwndFrom, &rectangle); _r_wnd_rectangletorect (&rect, &rectangle); _r_menu_popup (hsubmenu, hwnd, (PPOINT)&rect, TRUE); } DestroyMenu (hsubmenu); break; } case TTN_GETDISPINFO: { LPNMTTDISPINFOW lpnmdi; WCHAR buffer[1024] = {0}; PR_STRING string; ULONG app_hash; INT ctrl_id; INT listview_id = 0; lpnmdi = (LPNMTTDISPINFOW)lparam; if ((lpnmdi->uFlags & TTF_IDISHWND) == 0) break; ctrl_id = GetDlgCtrlID ((HWND)lpnmdi->hdr.idFrom); if (ctrl_id == IDC_FILE_TEXT) { app_hash = _app_notify_getapp_id (hwnd); if (_app_getappinfobyhash (app_hash, INFO_LISTVIEW_ID, &listview_id, sizeof (INT))) { string = _app_gettooltipbylparam (_r_app_gethwnd (), listview_id, app_hash); if (string) { _r_str_copy (buffer, RTL_NUMBER_OF (buffer), string->buffer); _r_obj_dereference (string); } } } else if (ctrl_id == IDC_RULES_BTN) { _r_str_copy (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (IDS_NOTIFY_TOOLTIP)); } else if (ctrl_id == IDC_ALLOW_BTN) { _r_str_copy (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (IDS_ACTION_ALLOW_HINT)); } else if (ctrl_id == IDC_BLOCK_BTN) { _r_str_copy (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (IDS_ACTION_BLOCK_HINT)); } else if (ctrl_id == IDC_KILLPROCESS_BTN) { _r_str_copy (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (IDS_ACTION_TERMINATE_HINT)); } else { string = _r_ctrl_getstring (hwnd, ctrl_id); if (string) { _r_str_copy (buffer, RTL_NUMBER_OF (buffer), string->buffer); _r_obj_dereference (string); } } if (!_r_str_isempty2 (buffer)) lpnmdi->lpszText = buffer; break; } } break; } case WM_COMMAND: { INT ctrl_id; ctrl_id = LOWORD (wparam); if (ctrl_id >= IDX_RULES_SPECIAL && ctrl_id <= IDX_RULES_SPECIAL + (INT)(INT_PTR)_r_obj_getlistsize (rules_list) + 1) { HANDLE hengine; PR_LIST rules; PITEM_RULE ptr_rule; PITEM_APP ptr_app; PITEM_LOG ptr_log; PR_STRING rule; ULONG_PTR rule_idx; ULONG app_hash; BOOLEAN is_remove; app_hash = _app_notify_getapp_id (hwnd); ptr_app = _app_getappitem (app_hash); if (!ptr_app) return FALSE; rule_idx = (ULONG_PTR)ctrl_id - IDX_RULES_SPECIAL; ptr_rule = _app_getrulebyid (rule_idx); if (!ptr_rule) { ptr_log = _app_notify_getobject (app_hash); if (ptr_log) { rule = _app_formataddress (ptr_log->af, 0, &ptr_log->remote_addr, ptr_log->remote_port, FMTADDR_AS_RULE); ptr_rule = _app_addrule (NULL, NULL, NULL, FWP_DIRECTION_OUTBOUND, FWP_ACTION_PERMIT, ptr_log->protocol, ptr_log->af); ptr_rule->name = _r_obj_createstring2 (&rule->sr); ptr_rule->rule_remote = _r_obj_createstring2 (&rule->sr); _app_ruleenable (ptr_rule, TRUE, FALSE); _r_obj_addhashtableitem (ptr_rule->apps, app_hash, NULL); _r_obj_dereference (rule); _r_queuedlock_acquireexclusive (&lock_rules); _r_obj_addlistitem (rules_list, ptr_rule, &rule_idx); _r_queuedlock_releaseexclusive (&lock_rules); if (rule_idx != SIZE_MAX) { _app_listview_addruleitem (_r_app_gethwnd (), ptr_rule, (ULONG)rule_idx, TRUE); _app_listview_updateby_id (_r_app_gethwnd (), DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE); _app_profile_save (hwnd); } } _app_notify_freeobject (hwnd, ptr_app); break; } _app_notify_freeobject (hwnd, ptr_app); if (!(ptr_rule->is_forservices && _app_issystemhash (app_hash))) { is_remove = ptr_rule->is_enabled && _r_obj_findhashtable (ptr_rule->apps, app_hash); if (is_remove) { _r_obj_removehashtableitem (ptr_rule->apps, app_hash); if (_r_obj_isempty (ptr_rule->apps)) _app_ruleenable (ptr_rule, FALSE, TRUE); } else { _r_obj_addhashtableitem (ptr_rule->apps, app_hash, NULL); _app_ruleenable (ptr_rule, TRUE, TRUE); } _app_listview_updateitemby_param (_r_app_gethwnd (), app_hash, TRUE); _app_listview_updateitemby_param (_r_app_gethwnd (), rule_idx, FALSE); if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); rules = _r_obj_createlist (1, NULL); _r_obj_addlistitem (rules, ptr_rule, NULL); _wfp_create4filters (hengine, rules, DBG_ARG, FALSE); _r_obj_dereference (rules); } _app_listview_updateby_id (_r_app_gethwnd (), DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE); _r_obj_dereference (ptr_rule); _r_obj_dereference (ptr_app); _app_profile_save (hwnd); } return FALSE; } else if (ctrl_id >= IDX_TIMER && ctrl_id <= (IDX_TIMER + (RTL_NUMBER_OF (timer_array) - 1))) { ULONG_PTR timer_idx; LONG64 seconds; if (!_r_ctrl_isenabled (hwnd, IDC_ALLOW_BTN)) return FALSE; timer_idx = (ULONG_PTR)ctrl_id - IDX_TIMER; seconds = timer_array[timer_idx]; _app_notify_command (hwnd, IDC_ALLOW_BTN, seconds); return FALSE; } switch (ctrl_id) { case IDCANCEL: // process Esc key { DestroyWindow (hwnd); break; } case IDC_FILE_TEXT: { ULONG app_hash; app_hash = _app_notify_getapp_id (hwnd); if (app_hash) _app_listview_showitemby_param (_r_app_gethwnd (), app_hash, TRUE); break; } case IDC_RULES_BTN: { PEDITOR_CONTEXT context; PITEM_APP ptr_app; ULONG app_hash; app_hash = _app_notify_getapp_id (hwnd); ptr_app = _app_getappitem (app_hash); if (!ptr_app) break; context = _app_editor_createwindow (_r_app_gethwnd (), ptr_app, 1, FALSE); if (context) _app_editor_deletewindow (context); _app_notify_freeobject (hwnd, ptr_app); _r_obj_dereference (ptr_app); break; } case IDC_ALLOW_BTN: case IDC_BLOCK_BTN: case IDC_NEXT_BTN: { if (_r_ctrl_isenabled (hwnd, ctrl_id)) _app_notify_command (hwnd, ctrl_id, 0); break; } case IDC_KILLPROCESS_BTN: { _app_notify_killprocess (hwnd); _r_ctrl_enable (hwnd, ctrl_id, FALSE); break; } case IDM_OPENRULESEDITOR: { PEDITOR_CONTEXT context; PITEM_APP ptr_app; PITEM_RULE ptr_rule; PITEM_LOG ptr_log; PR_STRING app_name; PR_STRING rule_name; PR_STRING rule_string; ULONG_PTR rule_idx; ULONG app_hash; app_hash = _app_notify_getapp_id (hwnd); ptr_log = _app_notify_getobject (app_hash); if (!ptr_log) break; app_hash = ptr_log->app_hash; ptr_app = _app_getappitem (app_hash); if (!ptr_app) { _r_obj_dereference (ptr_log); break; } app_name = _app_getappdisplayname (ptr_app, TRUE); rule_string = _app_formataddress (ptr_log->af, 0, &ptr_log->remote_addr, ptr_log->remote_port, FMTADDR_AS_RULE); rule_name = _r_format_string (L"%s - %s", _r_obj_getstring (app_name), _r_obj_getstring (rule_string)); ptr_rule = _app_addrule (rule_name, rule_string, NULL, ptr_log->direction, FWP_ACTION_PERMIT, ptr_log->protocol, ptr_log->af); _r_obj_addhashtableitem (ptr_rule->apps, app_hash, NULL); _app_ruleenable (ptr_rule, TRUE, TRUE); context = _app_editor_createwindow (_r_app_gethwnd (), ptr_rule, 0, TRUE); if (context) { _r_queuedlock_acquireexclusive (&lock_rules); _r_obj_addlistitem (rules_list, _r_obj_reference (ptr_rule), &rule_idx); _r_queuedlock_releaseexclusive (&lock_rules); // set rule information _app_listview_addruleitem (_r_app_gethwnd (), ptr_rule, rule_idx, TRUE); // update app information _app_listview_updateitemby_param (_r_app_gethwnd (), app_hash, TRUE); _app_listview_updateby_id (_r_app_gethwnd (), DATA_LISTVIEW_CURRENT, PR_UPDATE_TYPE); _app_profile_save (hwnd); _app_editor_deletewindow (context); } _app_notify_freeobject (hwnd, ptr_app); if (app_name) _r_obj_dereference (app_name); if (rule_string) _r_obj_dereference (rule_string); _r_obj_dereference (rule_name); _r_obj_dereference (ptr_rule); _r_obj_dereference (ptr_log); _r_obj_dereference (ptr_app); break; } case IDM_COPY: // ctrl+c case IDM_SELECT_ALL: // ctrl+a { static R_STRINGREF sr = PR_STRINGREF_INIT (WC_EDITW); PR_STRING class_name; HWND hedit; hedit = GetFocus (); if (!hedit) break; class_name = _r_wnd_getclassname (hedit); if (!class_name) break; if (_r_str_isequal (&class_name->sr, &sr, TRUE)) { if (ctrl_id == IDM_COPY) { _r_wnd_sendmessage (hedit, 0, WM_COPY, 0, 0); // edit control hotkey for "ctrl+c" (issue #597) } else if (ctrl_id == IDM_SELECT_ALL) { _r_ctrl_setselection (hedit, 0, 0, -1); // edit control hotkey for "ctrl+a" } } _r_obj_dereference (class_name); break; } } break; } } return FALSE; } ================================================ FILE: src/notifications.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once typedef struct _NOTIFY_CONTEXT { HWND hwnd; HICON hico_allow; HICON hico_block; HICON hico_cross; HICON hico_next; HICON hico_rules; HFONT hfont_title; HFONT hfont_link; HFONT hfont_text; HICON hicon; ULONG app_hash; } NOTIFY_CONTEXT, *PNOTIFY_CONTEXT; _Ret_maybenull_ HWND _app_notify_getwindow ( _In_opt_ PITEM_LOG ptr_log ); _Ret_maybenull_ PNOTIFY_CONTEXT _app_notify_getcontext ( _In_ HWND hwnd ); VOID _app_notify_setcontext ( _In_ HWND hwnd, _In_opt_ PNOTIFY_CONTEXT context ); BOOLEAN _app_notify_command ( _In_ HWND hwnd, _In_ INT button_id, _In_opt_ LONG64 seconds ); BOOLEAN _app_notify_addobject ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log, _Inout_ PITEM_APP ptr_app ); VOID _app_notify_freeobject ( _In_opt_ HWND hwnd, _Inout_ PITEM_APP ptr_app ); _Ret_maybenull_ HICON _app_notify_getapp_icon ( _In_ HWND hwnd ); _Ret_maybenull_ PITEM_LOG _app_notify_getobject ( _In_ ULONG app_hash ); ULONG _app_notify_getapp_id ( _In_ HWND hwnd ); ULONG _app_notify_getnextapp_id ( _In_ HWND hwnd ); VOID _app_notify_setapp_icon ( _In_ HWND hwnd, _In_opt_ HICON hicon ); VOID _app_notify_setapp_id ( _In_ HWND hwnd, _In_opt_ ULONG app_hash ); VOID _app_notify_show ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log ); VOID _app_notify_playsound (); VOID _app_notify_queueinfo ( _In_ HWND hwnd, _In_ PITEM_LOG ptr_log ); VOID _app_notify_refresh ( _In_ HWND hwnd ); VOID _app_notify_setposition ( _In_ HWND hwnd, _In_ BOOLEAN is_forced ); VOID _app_notify_settimeout ( _In_ HWND hwnd ); VOID _app_notify_initialize ( _Inout_ PNOTIFY_CONTEXT context, _In_ LONG dpi_value ); VOID _app_notify_destroy ( _In_ HWND hwnd ); VOID _app_notify_drawgradient ( _In_ HDC hdc, _In_ LPCRECT rect ); INT_PTR CALLBACK NotificationProc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ); ================================================ FILE: src/packages.c ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #include "global.h" BOOLEAN _app_package_isnotexists ( _In_ PR_STRING package_sid ) { ULONG app_hash; app_hash = _r_str_gethash (&package_sid->sr, TRUE); if (_app_isappfound (app_hash)) return TRUE; // there we try to found new packages (HACK!!!) _app_package_getpackageslist (_r_app_gethwnd ()); return _app_isappfound (app_hash); } VOID _app_package_parsepath ( _Inout_ PR_STRING_PTR package_root_folder ) { R_STRINGREF appx_names[] = { PR_STRINGREF_INIT (L"AppxManifest.xml"), PR_STRINGREF_INIT (L"VSAppxManifest.xml"), }; R_STRINGREF separator_sr = PR_STRINGREF_INIT (L"\\"); R_XML_LIBRARY xml_library = {0}; PR_STRING manifest_path = NULL; PR_STRING result_path = NULL; PR_STRING path_string; R_STRINGREF executable_sr; HRESULT status; BOOLEAN is_success = FALSE; path_string = *package_root_folder; for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (appx_names); i++) { _r_obj_movereference ((PVOID_PTR)&manifest_path, _r_obj_concatstringrefs (3, &path_string->sr, &separator_sr, &appx_names[i])); if (_r_fs_isexists (&manifest_path->sr)) { is_success = TRUE; break; } } if (!is_success) goto CleanupExit; status = _r_xml_initializelibrary (&xml_library, TRUE); if (FAILED (status)) goto CleanupExit; status = _r_xml_parsefile (&xml_library, manifest_path->buffer); if (FAILED (status)) goto CleanupExit; if (_r_xml_findchildbytagname (&xml_library, L"Applications")) { while (_r_xml_enumchilditemsbytagname (&xml_library, L"Application")) { if (FAILED (_r_xml_getattribute (&xml_library, L"Executable", &executable_sr))) continue; _r_obj_movereference ((PVOID_PTR)&result_path, _r_obj_concatstringrefs (3, &path_string->sr, &separator_sr, &executable_sr)); if (_r_fs_isexists (&result_path->sr)) { _r_obj_swapreference ((PVOID_PTR)package_root_folder, result_path); break; } } } CleanupExit: if (result_path) _r_obj_dereference (result_path); if (manifest_path) _r_obj_dereference (manifest_path); _r_xml_destroylibrary (&xml_library); } VOID _app_package_getpackagebyname ( _In_ HANDLE hroot, _In_ LPCWSTR path, _In_ PR_STRING key_name ) { WCHAR buffer[256]; PR_STRING package_sid_string = NULL; PR_STRING display_name = NULL; PR_STRING real_path = NULL; PR_BYTE package_sid = NULL; PITEM_APP ptr_app; HANDLE hsubkey; LONG64 timestamp; ULONG app_hash; NTSTATUS status; _r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s\\%s", path, key_name->buffer); status = _r_reg_openkey (hroot, buffer, 0, KEY_READ, &hsubkey); if (!NT_SUCCESS (status)) goto CleanupExit; status = _r_reg_querybinary (hsubkey, L"PackageSid", &package_sid); if (!NT_SUCCESS (status)) goto CleanupExit; status = _r_str_fromsid (package_sid->buffer, &package_sid_string); if (!NT_SUCCESS (status)) goto CleanupExit; // already exists (skip) app_hash = _r_str_gethash (&package_sid_string->sr, TRUE); if (_app_isappfound (app_hash)) goto CleanupExit; // parse package information if (!_app_uwp_getpackageinfo (key_name, &display_name, &real_path)) goto CleanupExit; if (real_path) _app_package_parsepath (&real_path); //_r_queuedlock_acquireexclusive (&lock_apps); app_hash = _app_addapplication (NULL, DATA_APP_UWP, package_sid_string, display_name, real_path); //_r_queuedlock_releaseexclusive (&lock_apps); if (app_hash) { ptr_app = _app_getappitem (app_hash); if (ptr_app) { status = _r_reg_queryinfo (hsubkey, NULL, ×tamp); if (NT_SUCCESS (status)) _app_setappinfo (ptr_app, INFO_TIMESTAMP, ×tamp); _app_setappinfo (ptr_app, INFO_BYTES_DATA, _r_obj_reference (package_sid)); _r_obj_dereference (ptr_app); } } CleanupExit: if (display_name) _r_obj_dereference (display_name); if (package_sid) _r_obj_dereference (package_sid); if (package_sid_string) _r_obj_dereference (package_sid_string); if (real_path) _r_obj_dereference (real_path); if (hsubkey) NtClose (hsubkey); } VOID _app_package_getpackagebysid ( _In_ HANDLE hroot, _In_ LPCWSTR path, _In_ PR_STRING key_name ) { WCHAR buffer[256]; PR_STRING display_name = NULL; PR_STRING real_path = NULL; PR_BYTE package_sid = NULL; PR_STRING moniker = NULL; PITEM_APP ptr_app; HANDLE hsubkey; LONG64 timestamp = 0; ULONG app_hash; NTSTATUS status; // already exists (skip) app_hash = _r_str_gethash (&key_name->sr, TRUE); if (_app_isappfound (app_hash)) return; _r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s\\%s", path, key_name->buffer); status = _r_reg_openkey (hroot, buffer, 0, KEY_READ, &hsubkey); if (!NT_SUCCESS (status)) goto CleanupExit; package_sid = _r_str_tosid (key_name); if (!package_sid) goto CleanupExit; // query package moniker status = _r_reg_querystring (hsubkey, L"Moniker", &moniker, NULL); if (!NT_SUCCESS (status)) goto CleanupExit; // parse package information if (!_app_uwp_getpackageinfo (moniker, &display_name, &real_path)) goto CleanupExit; if (real_path) _app_package_parsepath (&real_path); //_r_queuedlock_acquireexclusive (&lock_apps); app_hash = _app_addapplication (NULL, DATA_APP_UWP, key_name, display_name, NULL); //_r_queuedlock_releaseexclusive (&lock_apps); if (app_hash) { ptr_app = _app_getappitem (app_hash); if (ptr_app) { status = _r_reg_queryinfo (hsubkey, NULL, ×tamp); if (NT_SUCCESS (status)) _app_setappinfo (ptr_app, INFO_TIMESTAMP, ×tamp); _app_setappinfo (ptr_app, INFO_BYTES_DATA, _r_obj_reference (package_sid)); _r_obj_dereference (ptr_app); } } CleanupExit: if (moniker) _r_obj_dereference (moniker); if (display_name) _r_obj_dereference (display_name); if (real_path) _r_obj_dereference (real_path); if (package_sid) _r_obj_dereference (package_sid); if (hsubkey) NtClose (hsubkey); } VOID NTAPI _app_package_threadproc ( _In_ PVOID arglist ) { IO_STATUS_BLOCK isb; HANDLE hservices_key = NULL; HANDLE hpackages_key = NULL; HANDLE event_handle1 = NULL; HANDLE event_handle2 = NULL; HANDLE hevents[2] = {0}; PITEM_APP ptr_app = NULL; HWND hwnd; LONG64 current_time; ULONG_PTR enum_key = 0; ULONG flags = REG_NOTIFY_CHANGE_NAME; NTSTATUS status; hwnd = arglist; status = NtCreateEvent (&event_handle1, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); if (!NT_SUCCESS (status)) { _r_show_errormessage (hwnd, NULL, status, L"NtCreateEvent", ET_NATIVE); return; } status = NtCreateEvent (&event_handle2, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); if (!NT_SUCCESS (status)) { _r_show_errormessage (hwnd, NULL, status, L"NtCreateEvent", ET_NATIVE); return; } hevents[0] = event_handle1; hevents[1] = event_handle2; status = _r_reg_openkey (HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services", 0, KEY_NOTIFY, &hservices_key); if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { flags |= REG_NOTIFY_THREAD_AGNOSTIC; _r_reg_openkey (HKEY_CURRENT_USER, L"Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\Repository\\Packages", 0, KEY_NOTIFY, &hpackages_key); } if (NT_SUCCESS (status)) { NtNotifyChangeKey (hservices_key, event_handle1, NULL, NULL, &isb, flags, TRUE, NULL, 0, TRUE); if (hpackages_key) NtNotifyChangeKey (hpackages_key, event_handle2, NULL, NULL, &isb, flags, TRUE, NULL, 0, TRUE); while (TRUE) { status = _r_sys_waitformultipleobjects (RTL_NUMBER_OF (hevents), hevents, INFINITE, FALSE); if (status == STATUS_WAIT_0) { _r_listview_deleteallitems (hwnd, IDC_APPS_SERVICE); _app_package_getserviceslist (hwnd); // add apps current_time = _r_unixtime_now (); enum_key = 0; _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (ptr_app->type == DATA_APP_SERVICE) { _app_listview_addappitem (hwnd, ptr_app); // install timer if (ptr_app->timer) _app_timer_set (hwnd, ptr_app, ptr_app->timer - current_time); } } _r_queuedlock_releaseshared (&lock_apps); NtNotifyChangeKey (hservices_key, event_handle1, NULL, NULL, &isb, flags, TRUE, NULL, 0, TRUE); // reset } else if (status == STATUS_WAIT_1) { _r_listview_deleteallitems (hwnd, IDC_APPS_UWP); _app_package_getpackageslist (hwnd); // add apps current_time = _r_unixtime_now (); enum_key = 0; _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (ptr_app->type == DATA_APP_UWP) { _app_listview_addappitem (hwnd, ptr_app); // install timer if (ptr_app->timer) _app_timer_set (hwnd, ptr_app, ptr_app->timer - current_time); } } _r_queuedlock_releaseshared (&lock_apps); if (hpackages_key) NtNotifyChangeKey (hpackages_key, event_handle2, NULL, NULL, &isb, flags, TRUE, NULL, 0, TRUE); // reset } else { break; } } } if (hservices_key) NtClose (hservices_key); if (hpackages_key) NtClose (hpackages_key); NtClose (event_handle1); NtClose (event_handle2); } VOID _app_package_getpackageslist ( _In_ HWND hwnd ) { LPWSTR reg_byname = L"Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\Repository\\Packages"; LPWSTR reg_bysid = L"Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Mappings"; PR_STRING name; HANDLE hkey; ULONG index = 0; NTSTATUS status; // query packages by name status = _r_reg_openkey (HKEY_CURRENT_USER, reg_byname, 0, KEY_READ, &hkey); if (!NT_SUCCESS (status)) { if (status != STATUS_OBJECT_NAME_NOT_FOUND) _r_show_errormessage (hwnd, NULL, status, reg_byname, ET_NATIVE); } else { while (TRUE) { status = _r_reg_enumkey (hkey, index, &name, NULL); if (!NT_SUCCESS (status)) break; _app_package_getpackagebyname (HKEY_CURRENT_USER, reg_byname, name); _r_obj_dereference (name); index += 1; } NtClose (hkey); } // query packages by sid status = _r_reg_openkey (HKEY_CURRENT_USER, reg_bysid, 0, KEY_READ, &hkey); if (!NT_SUCCESS (status)) { if (status != STATUS_OBJECT_NAME_NOT_FOUND) _r_show_errormessage (hwnd, NULL, status, reg_bysid, ET_NATIVE); } else { index = 0; while (TRUE) { status = _r_reg_enumkey (hkey, index, &name, NULL); if (!NT_SUCCESS (status)) break; _app_package_getpackagebysid (HKEY_CURRENT_USER, reg_bysid, name); _r_obj_dereference (name); index += 1; } NtClose (hkey); } } VOID _app_package_getserviceslist ( _In_ HWND hwnd ) { WCHAR general_key[256]; LPENUM_SERVICE_STATUS_PROCESS services; LPENUM_SERVICE_STATUS_PROCESS service; EXPLICIT_ACCESS ea; R_STRINGREF dummy_filename; PR_STRING converted_path; PR_STRING name_string; PR_STRING service_name; PR_STRING service_path; PR_BYTE service_sid; SC_HANDLE hsvcmgr; PITEM_APP ptr_app; PVOID service_sd; PVOID buffer; HANDLE hkey; LONG64 service_timestamp; ULONG service_type = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS; ULONG service_state = SERVICE_STATE_ALL; ULONG services_returned; ULONG return_length; ULONG buffer_size; ULONG sd_length; ULONG app_hash; NTSTATUS status; hsvcmgr = OpenSCManagerW (NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); if (!hsvcmgr) { _r_show_errormessage (hwnd, NULL, NtLastError (), L"OpenSCManagerW", ET_WINDOWS); return; } // win10+ if (_r_sys_isosversiongreaterorequal (WINDOWS_10)) service_type |= SERVICE_INTERACTIVE_PROCESS | SERVICE_USER_SERVICE; buffer_size = PR_SIZE_BUFFER; buffer = _r_mem_allocate (buffer_size); if (!EnumServicesStatusExW (hsvcmgr, SC_ENUM_PROCESS_INFO, service_type, service_state, buffer, buffer_size, &return_length, &services_returned, NULL, NULL)) { if (NtLastError () == ERROR_MORE_DATA) { // set the buffer buffer_size += return_length; buffer = _r_mem_reallocate (buffer, buffer_size); // now query again for services if (!EnumServicesStatusExW (hsvcmgr, SC_ENUM_PROCESS_INFO, service_type, service_state, buffer, buffer_size, &return_length, &services_returned, NULL, NULL)) { _r_mem_free (buffer); buffer = NULL; } } else { _r_mem_free (buffer); buffer = NULL; } } if (!buffer) { CloseServiceHandle (hsvcmgr); return; } // now traverse each service to get information services = (LPENUM_SERVICE_STATUS_PROCESS)buffer; for (ULONG i = 0; i < services_returned; i++) { service = &services[i]; app_hash = _r_str_gethash2 (service->lpServiceName, TRUE); if (_app_isappfound (app_hash)) continue; _r_str_printf (general_key, RTL_NUMBER_OF (general_key), L"System\\CurrentControlSet\\Services\\%s", service->lpServiceName); service_name = _r_obj_createstring (service->lpServiceName); status = _r_reg_openkey (HKEY_LOCAL_MACHINE, general_key, 0, KEY_READ, &hkey); if (!NT_SUCCESS (status)) { _r_obj_dereference (service_name); continue; } // skip userservice instances service types (win10+) if (_r_sys_isosversiongreaterorequal (WINDOWS_10)) { status = _r_reg_queryulong (hkey, L"Type", &service_type); if (!NT_SUCCESS (status) || (service_type & SERVICE_USERSERVICE_INSTANCE) != 0) { _r_obj_dereference (service_name); NtClose (hkey); continue; } } // query service path status = _r_reg_querystring (hkey, L"ImagePath", &service_path, NULL); if (NT_SUCCESS (status)) { _r_path_parsecommandlinefuzzy (&service_path->sr, &dummy_filename, NULL, &converted_path); if (converted_path) { _r_obj_movereference ((PVOID_PTR)&service_path, converted_path); } else { converted_path = _r_path_dospathfromnt (&service_path->sr); if (converted_path) _r_obj_movereference ((PVOID_PTR)&service_path, converted_path); } // query service sid status = _r_sys_getservicesid (service->lpServiceName, &service_sid); if (NT_SUCCESS (status)) { // 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, FWP_ACTRL_MATCH_FILTER, NO_INHERITANCE, service_sid->buffer); // 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. status = BuildSecurityDescriptorW (NULL, NULL, 1, &ea, 0, NULL, NULL, &sd_length, &service_sd); if (status == ERROR_SUCCESS && service_sd) { name_string = _r_obj_createstring (service->lpDisplayName); app_hash = _app_addapplication (NULL, DATA_APP_SERVICE, service_name, name_string, service_path); if (app_hash) { ptr_app = _app_getappitem (app_hash); if (ptr_app) { // query service timestamp status = _r_reg_queryinfo (hkey, NULL, &service_timestamp); if (NT_SUCCESS (status)) _app_setappinfo (ptr_app, INFO_TIMESTAMP, &service_timestamp); _app_setappinfo (ptr_app, INFO_BYTES_DATA, _r_obj_createbyte_ex (service_sd, sd_length)); _r_obj_dereference (ptr_app); } } LocalFree (service_sd); _r_obj_dereference (name_string); } _r_obj_dereference (service_sid); } _r_obj_dereference (service_path); } _r_obj_dereference (service_name); NtClose (hkey); } _r_mem_free (buffer); CloseServiceHandle (hsvcmgr); } ================================================ FILE: src/packages.h ================================================ // simplewall // Copyright (c) 2016-2025 Henry++ #pragma once BOOLEAN _app_package_isnotexists ( _In_ PR_STRING package_sid ); VOID _app_package_parsepath ( _Inout_ PR_STRING_PTR package_root_folder ); VOID _app_package_getpackagebyname ( _In_ HANDLE hroot, _In_ LPCWSTR path, _In_ PR_STRING key_name ); VOID _app_package_getpackagebysid ( _In_ HANDLE hroot, _In_ LPCWSTR path, _In_ PR_STRING key_name ); VOID NTAPI _app_package_threadproc ( _In_ PVOID arglist ); VOID _app_package_getpackageslist ( _In_ HWND hwnd ); VOID _app_package_getserviceslist ( _In_ HWND hwnd ); ================================================ FILE: src/profile.c ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #include "global.h" _Success_ (return) BOOLEAN _app_getappinfo ( _In_ PITEM_APP ptr_app, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ) { RtlZeroMemory (buffer, length); switch (info_data) { case INFO_PATH: { PVOID ptr; if (length != sizeof (PVOID)) return FALSE; if (ptr_app->real_path) { ptr = _r_obj_reference (ptr_app->real_path); RtlCopyMemory (buffer, &ptr, length); return TRUE; } break; } case INFO_DISPLAY_NAME: { PVOID ptr; if (length != sizeof (PVOID)) return FALSE; if (ptr_app->display_name) { ptr = _r_obj_reference (ptr_app->display_name); RtlCopyMemory (buffer, &ptr, length); return TRUE; } else if (ptr_app->original_path) { ptr = _r_obj_reference (ptr_app->original_path); RtlCopyMemory (buffer, &ptr, length); return TRUE; } break; } case INFO_HASH: { PVOID ptr; if (length != sizeof (PVOID)) return FALSE; if (ptr_app->hash) { ptr = _r_obj_reference (ptr_app->hash); RtlCopyMemory (buffer, &ptr, length); return TRUE; } break; } case INFO_TIMESTAMP: { if (length != sizeof (LONG64)) return FALSE; RtlCopyMemory (buffer, &ptr_app->timestamp, length); return TRUE; } case INFO_TIMER: { if (length != sizeof (LONG64)) return FALSE; RtlCopyMemory (buffer, &ptr_app->timer, length); return TRUE; } case INFO_LISTVIEW_ID: { INT listview_id; if (length != sizeof (INT)) return FALSE; listview_id = _app_listview_getbytype (ptr_app->type); RtlCopyMemory (buffer, &listview_id, length); return TRUE; } case INFO_IS_ENABLED: { BOOLEAN is_enabled; if (length != sizeof (BOOLEAN)) return FALSE; is_enabled = (ptr_app->is_enabled != 0); RtlCopyMemory (buffer, &is_enabled, length); return TRUE; } case INFO_IS_SILENT: { BOOLEAN is_silent; if (length != sizeof (BOOLEAN)) return FALSE; is_silent = (ptr_app->is_silent != 0); RtlCopyMemory (buffer, &is_silent, length); return TRUE; } case INFO_IS_UNDELETABLE: { BOOLEAN is_undeletable; if (length != sizeof (BOOLEAN)) return FALSE; is_undeletable = (ptr_app->is_undeletable != 0); RtlCopyMemory (buffer, &is_undeletable, length); return TRUE; } default: { FALLTHROUGH; } } return FALSE; } _Success_ (return) BOOLEAN _app_getappinfobyhash ( _In_ ULONG app_hash, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ) { PITEM_APP ptr_app; BOOLEAN is_success; RtlZeroMemory (buffer, length); ptr_app = _app_getappitem (app_hash); if (!ptr_app) return FALSE; is_success = _app_getappinfo (ptr_app, info_data, buffer, length); _r_obj_dereference (ptr_app); return is_success; } VOID _app_setappinfo ( _In_ PITEM_APP ptr_app, _In_ ENUM_INFO_DATA info_data, _In_opt_ PVOID value ) { switch (info_data) { case INFO_BYTES_DATA: { _r_obj_movereference ((PVOID_PTR)&ptr_app->bytes, value); break; } case INFO_COMMENT: { _r_obj_movereference ((PVOID_PTR)&ptr_app->comment, value); break; } case INFO_HASH: { _r_obj_movereference ((PVOID_PTR)&ptr_app->hash, value); break; } case INFO_TIMESTAMP: { if (!value) break; ptr_app->timestamp = *((PLONG64)value); break; } case INFO_TIMER: { HANDLE engine_handle; LONG64 timestamp; if (!value) break; timestamp = *((PLONG64)value); // check timer expiration if (timestamp <= _r_unixtime_now ()) { engine_handle = _wfp_getenginehandle (); _wfp_destroyfilters_array (engine_handle, ptr_app->guids, DBG_ARG); _r_obj_cleararray (ptr_app->guids); ptr_app->timer = 0; ptr_app->is_enabled = FALSE; } else { ptr_app->timer = timestamp; ptr_app->is_enabled = TRUE; } _app_listview_updateitemby_param (_r_app_gethwnd (), ptr_app->app_hash, TRUE); break; } case INFO_DISABLE: { HANDLE engine_handle; ptr_app->is_enabled = FALSE; engine_handle = _wfp_getenginehandle (); _wfp_destroyfilters_array (engine_handle, ptr_app->guids, DBG_ARG); _r_obj_cleararray (ptr_app->guids); _app_listview_updateitemby_param (_r_app_gethwnd (), ptr_app->app_hash, TRUE); break; } case INFO_IS_ENABLED: { ptr_app->is_enabled = (PtrToLong (value) ? TRUE : FALSE); _app_listview_updateitemby_param (_r_app_gethwnd (), ptr_app->app_hash, TRUE); break; } case INFO_IS_SILENT: { ptr_app->is_silent = (PtrToLong (value) ? TRUE : FALSE); if (ptr_app->is_silent) _app_notify_freeobject (NULL, ptr_app); break; } case INFO_IS_UNDELETABLE: { ptr_app->is_undeletable = (PtrToLong (value) ? TRUE : FALSE); break; } default: { FALLTHROUGH; } } } VOID _app_setappinfobyhash ( _In_ ULONG app_hash, _In_ ENUM_INFO_DATA info_data, _In_opt_ PVOID value ) { PITEM_APP ptr_app; ptr_app = _app_getappitem (app_hash); if (!ptr_app) return; _app_setappinfo (ptr_app, info_data, value); _r_obj_dereference (ptr_app); } _Success_ (return) BOOLEAN _app_getruleinfo ( _In_ PITEM_RULE ptr_rule, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ) { RtlZeroMemory (buffer, length); switch (info_data) { case INFO_LISTVIEW_ID: { INT listview_id; if (length != sizeof (INT)) return FALSE; listview_id = _app_listview_getbytype (ptr_rule->type); RtlCopyMemory (buffer, &listview_id, length); return TRUE; } case INFO_IS_READONLY: { INT is_readonly; if (length != sizeof (INT)) return FALSE; is_readonly = !!ptr_rule->is_readonly; RtlCopyMemory (buffer, &is_readonly, length); return TRUE; } default: { FALLTHROUGH; } } return FALSE; } _Success_ (return) BOOLEAN _app_getruleinfobyid ( _In_ ULONG_PTR index, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ) { PITEM_RULE ptr_rule; BOOLEAN is_success; ptr_rule = _app_getrulebyid (index); if (!ptr_rule) return FALSE; is_success = _app_getruleinfo (ptr_rule, info_data, buffer, length); _r_obj_dereference (ptr_rule); return is_success; } _Success_ (return != 0) ULONG _app_addapplication ( _In_opt_ HWND hwnd, _In_ ENUM_TYPE_DATA type, _In_ PR_STRING path, _In_opt_ PR_STRING display_name, _In_opt_ PR_STRING real_path ) { WCHAR path_full[0x400]; R_STRINGREF path_sr; PITEM_APP ptr_app; ULONG app_hash; BOOLEAN is_ntoskrnl; if (_r_obj_isstringempty2 (path)) return 0; if (_app_isappvalidpath (path) && _r_fs_isdirectory (&path->sr)) return 0; _r_obj_initializestringref2 (&path_sr, &path->sr); // prevent possible duplicate apps entries with short path (issue #640) if (_r_str_findchar (&path_sr, L'~', FALSE) != SIZE_MAX) { if (GetLongPathNameW (path_sr.buffer, path_full, RTL_NUMBER_OF (path_full))) _r_obj_initializestringref (&path_sr, path_full); } app_hash = _r_str_gethash (&path_sr, TRUE); if (_app_isappfound (app_hash)) return app_hash; // already exists ptr_app = _r_obj_allocate (sizeof (ITEM_APP), &_app_dereferenceapp); is_ntoskrnl = (app_hash == config.ntoskrnl_hash); ptr_app->app_hash = app_hash; if (type == DATA_UNKNOWN) { if (_r_str_isstartswith2 (&path_sr, L"S-1-", TRUE)) // uwp (win8+) type = DATA_APP_UWP; } if (type == DATA_APP_SERVICE || type == DATA_APP_UWP) { ptr_app->type = type; if (display_name) ptr_app->display_name = _r_obj_reference (display_name); if (real_path) ptr_app->real_path = _r_obj_reference (real_path); } else if (_r_str_isstartswith2 (&path_sr, L"\\device\\", TRUE)) // device path { ptr_app->type = DATA_APP_DEVICE; ptr_app->real_path = _r_obj_createstring2 (&path_sr); } else { if (!is_ntoskrnl && _r_str_findchar (&path_sr, OBJ_NAME_PATH_SEPARATOR, FALSE) == SIZE_MAX) { ptr_app->type = DATA_APP_PICO; } else { ptr_app->type = PathIsNetworkPathW (path_sr.buffer) ? DATA_APP_NETWORK : DATA_APP_REGULAR; } if (is_ntoskrnl) { ptr_app->real_path = _r_obj_createstring2 (&config.ntoskrnl_path->sr); } else { ptr_app->real_path = _r_obj_createstring2 (&path_sr); } } ptr_app->original_path = _r_obj_createstring2 (&path_sr); // fix "System" lowercase if (is_ntoskrnl) { _r_str_tolower (&ptr_app->original_path->sr); ptr_app->original_path->buffer[0] = _r_str_upper (ptr_app->original_path->buffer[0]); } //if (ptr_app->type == DATA_APP_REGULAR || ptr_app->type == DATA_APP_DEVICE || ptr_app->type == DATA_APP_NETWORK) { ptr_app->short_name = _r_path_getbasenamestring (&path_sr); } ptr_app->guids = _r_obj_createarray (sizeof (GUID), 0x04, NULL); // initialize guids array ptr_app->timestamp = _r_unixtime_now (); // insert object into the table // //_r_queuedlock_acquireexclusive (&lock_apps); _r_obj_addhashtablepointer (apps_table, app_hash, ptr_app); //_r_queuedlock_releaseexclusive (&lock_apps); // insert item if (hwnd) _app_listview_addappitem (hwnd, ptr_app); // queue file information if (!_r_obj_isstringempty (ptr_app->real_path)) _app_getfileinformation (ptr_app->real_path, app_hash, ptr_app->type, _app_listview_getbytype (ptr_app->type)); return app_hash; } PITEM_RULE _app_addrule ( _In_opt_ PR_STRING name, _In_opt_ PR_STRING rule_remote, _In_opt_ PR_STRING rule_local, _In_ FWP_DIRECTION direction, _In_ FWP_ACTION_TYPE action, _In_ UINT8 protocol, _In_ ADDRESS_FAMILY af ) { PITEM_RULE ptr_rule; ptr_rule = _r_obj_allocate (sizeof (ITEM_RULE), &_app_dereferencerule); ptr_rule->apps = _r_obj_createhashtable (sizeof (SHORT), 4, NULL); // initialize hashtable ptr_rule->guids = _r_obj_createarray (sizeof (GUID), 4, NULL); // initialize array ptr_rule->type = DATA_RULE_USER; // set rule name if (name) { ptr_rule->name = _r_obj_reference (name); if (_r_str_getlength2 (&ptr_rule->name->sr) > RULE_NAME_CCH_MAX) _r_str_setlength (&ptr_rule->name->sr, RULE_NAME_CCH_MAX * sizeof (WCHAR)); } // set rule destination if (rule_remote) { ptr_rule->rule_remote = _r_obj_reference (rule_remote); if (_r_str_getlength2 (&ptr_rule->rule_remote->sr) > RULE_RULE_CCH_MAX) _r_str_setlength (&ptr_rule->rule_remote->sr, RULE_RULE_CCH_MAX * sizeof (WCHAR)); } // set rule source if (rule_local) { ptr_rule->rule_local = _r_obj_reference (rule_local); if (_r_str_getlength2 (&ptr_rule->rule_local->sr) > RULE_RULE_CCH_MAX) _r_str_setlength (&ptr_rule->rule_local->sr, RULE_RULE_CCH_MAX * sizeof (WCHAR)); } // set configuration ptr_rule->direction = direction; ptr_rule->action = action; ptr_rule->protocol = protocol; ptr_rule->af = af; ptr_rule->protocol_str = _r_obj_createstring (_app_db_getprotoname (protocol, af)); return ptr_rule; } _Ret_maybenull_ PITEM_RULE_CONFIG _app_addruleconfigtable ( _In_ PR_HASHTABLE hashtable, _In_ ULONG rule_hash, _In_ PR_STRING rule_name, _In_ BOOLEAN is_enabled ) { ITEM_RULE_CONFIG entry = {0}; entry.name = _r_obj_reference (rule_name); entry.is_enabled = is_enabled; return _r_obj_addhashtableitem (hashtable, rule_hash, &entry); } _Ret_maybenull_ PITEM_APP _app_getappitem ( _In_ ULONG app_hash ) { PITEM_APP ptr_app; _r_queuedlock_acquireshared (&lock_apps); ptr_app = _r_obj_findhashtablepointer (apps_table, app_hash); _r_queuedlock_releaseshared (&lock_apps); return ptr_app; } _Ret_maybenull_ PITEM_RULE _app_getrulebyid ( _In_ ULONG_PTR index ) { PITEM_RULE ptr_rule; _r_queuedlock_acquireshared (&lock_rules); if (index < _r_obj_getlistsize (rules_list)) { ptr_rule = _r_obj_getlistitem (rules_list, index); } else { ptr_rule = NULL; } _r_queuedlock_releaseshared (&lock_rules); if (ptr_rule) return _r_obj_reference (ptr_rule); return NULL; } _Ret_maybenull_ PITEM_RULE _app_getrulebyhash ( _In_ ULONG_PTR rule_hash ) { PITEM_RULE ptr_rule; if (!rule_hash) return NULL; _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (ptr_rule) { if (ptr_rule->is_readonly) { if (_r_str_gethash (&ptr_rule->name->sr, TRUE) == rule_hash) { _r_queuedlock_releaseshared (&lock_rules); return _r_obj_reference (ptr_rule); } } } } _r_queuedlock_releaseshared (&lock_rules); return NULL; } _Ret_maybenull_ PITEM_RULE_CONFIG _app_getruleconfigitem ( _In_ ULONG rule_hash ) { PITEM_RULE_CONFIG ptr_rule_config; _r_queuedlock_acquireshared (&lock_rules_config); ptr_rule_config = _r_obj_findhashtable (rules_config, rule_hash); _r_queuedlock_releaseshared (&lock_rules_config); return ptr_rule_config; } _Ret_maybenull_ PITEM_LOG _app_getlogitem ( _In_ ULONG log_hash ) { PITEM_LOG ptr_log; _r_queuedlock_acquireshared (&lock_loglist); ptr_log = _r_obj_findhashtablepointer (log_table, log_hash); _r_queuedlock_releaseshared (&lock_loglist); return ptr_log; } _Success_ (return != 0) ULONG _app_getlogapp ( _In_ ULONG index ) { PITEM_LOG ptr_log; ULONG app_hash; ptr_log = _app_getlogitem (index); if (ptr_log) { app_hash = ptr_log->app_hash; _r_obj_dereference (ptr_log); return app_hash; } return 0; } COLORREF _app_getappcolor ( _In_ INT listview_id, _In_ ULONG app_hash, _In_ BOOLEAN is_systemapp, _In_ BOOLEAN is_validconnection ) { PITEM_APP ptr_app; ULONG color_hash = 0; BOOLEAN is_profilelist; BOOLEAN is_networklist; ptr_app = _app_getappitem (app_hash); is_profilelist = (listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_RULES_CUSTOM); is_networklist = (listview_id == IDC_NETWORK || listview_id == IDC_LOG); if (ptr_app && !is_networklist) { if (_r_config_getboolean (L"IsHighlightInvalid", TRUE, L"colors") && !_app_isappexists (ptr_app)) { color_hash = config.color_invalid; goto CleanupExit; } } if (_r_config_getboolean (L"IsHighlightConnection", TRUE, L"colors") && is_validconnection) { color_hash = config.color_network; goto CleanupExit; } if (_r_config_getboolean (L"IsHighlightSigned", TRUE, L"colors") && _app_isappsigned (app_hash)) { color_hash = config.color_signed; goto CleanupExit; } if (ptr_app) { if (!is_profilelist && (_r_config_getboolean (L"IsHighlightSpecial", TRUE, L"colors") && _app_isapphaverule (app_hash, FALSE))) { color_hash = config.color_special; goto CleanupExit; } if (_r_config_getboolean (L"IsHighlightPico", TRUE, L"colors") && ptr_app->type == DATA_APP_PICO) { color_hash = config.color_pico; goto CleanupExit; } if (_r_config_getboolean (L"IsHighlightUndelete", TRUE, L"colors") && ptr_app->is_undeletable) { color_hash = config.color_nonremovable; goto CleanupExit; } } if (_r_config_getboolean (L"IsHighlightSystem", TRUE, L"colors") && is_systemapp) { color_hash = config.color_system; goto CleanupExit; } CleanupExit: if (ptr_app) _r_obj_dereference (ptr_app); if (color_hash) return _app_getcolorvalue (color_hash); return 0; } VOID _app_deleteappitem ( _In_ HWND hwnd, _In_ ENUM_TYPE_DATA type, _In_ ULONG_PTR id_code ) { INT listview_id; INT item_id; listview_id = _app_listview_getbytype (type); if (!listview_id) return; item_id = _app_listview_finditem (hwnd, listview_id, id_code); if (item_id != INT_ERROR) _r_listview_deleteitem (hwnd, listview_id, item_id); } VOID _app_freeapplication ( _In_opt_ HWND hwnd, _In_ ULONG app_hash ) { PITEM_RULE ptr_rule; _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (!ptr_rule) continue; if (ptr_rule->type != DATA_RULE_USER) continue; if (hwnd) _app_ruleremoveapp (hwnd, i, ptr_rule, app_hash); } _r_queuedlock_releaseshared (&lock_rules); _r_obj_removehashtableitem (apps_table, app_hash); } VOID _app_getcount ( _Out_ PITEM_STATUS status ) { PITEM_APP ptr_app = NULL; PITEM_RULE ptr_rule; ULONG_PTR enum_key = 0; BOOLEAN is_used; RtlZeroMemory (status, sizeof (ITEM_STATUS)); _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { is_used = _app_isappused (ptr_app); if (_app_istimerset (ptr_app)) status->apps_timer_count += 1; if (!ptr_app->is_undeletable && (!_app_isappexists (ptr_app) || !is_used) && !(ptr_app->type == DATA_APP_SERVICE || ptr_app->type == DATA_APP_UWP)) status->apps_unused_count += 1; if (is_used) status->apps_count += 1; } _r_queuedlock_releaseshared (&lock_apps); _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (!ptr_rule) continue; if (ptr_rule->type == DATA_RULE_USER) { if (ptr_rule->is_enabled && !_r_obj_isempty (ptr_rule->apps)) status->rules_global_count += 1; if (ptr_rule->is_readonly) { status->rules_predefined_count += 1; } else { status->rules_user_count += 1; } status->rules_count += 1; } } _r_queuedlock_releaseshared (&lock_rules); } COLORREF _app_getrulecolor ( _In_ INT listview_id, _In_ ULONG_PTR rule_idx ) { PITEM_RULE ptr_rule; ULONG color_hash = 0; ptr_rule = _app_getrulebyid (rule_idx); if (!ptr_rule) return 0; if (_r_config_getboolean (L"IsHighlightInvalid", TRUE, L"colors") && ptr_rule->is_enabled && ptr_rule->is_haveerrors) { color_hash = config.color_invalid; } else if (_r_config_getboolean (L"IsHighlightSpecial", TRUE, L"colors") && (ptr_rule->is_forservices || !_r_obj_isempty (ptr_rule->apps))) { color_hash = config.color_special; } _r_obj_dereference (ptr_rule); if (color_hash) return _app_getcolorvalue (color_hash); return 0; } VOID _app_setappiteminfo ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _In_ PITEM_APP ptr_app ) { _r_listview_setitem (hwnd, listview_id, item_id, 0, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, I_DEFAULT); _r_listview_setitemcheck (hwnd, listview_id, item_id, !!ptr_app->is_enabled); } VOID _app_setruleiteminfo ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _In_ PITEM_RULE ptr_rule, _In_ BOOLEAN include_apps ) { ULONG_PTR enum_key = 0; ULONG hash_code; _r_listview_setitem (hwnd, listview_id, item_id, 0, LPSTR_TEXTCALLBACK, I_IMAGECALLBACK, I_GROUPIDCALLBACK, I_DEFAULT); _r_listview_setitemcheck (hwnd, listview_id, item_id, !!ptr_rule->is_enabled); if (!include_apps) return; while (_r_obj_enumhashtable (ptr_rule->apps, NULL, &hash_code, &enum_key)) { _app_listview_updateitemby_param (hwnd, hash_code, TRUE); } } VOID _app_ruleenable ( _Inout_ PITEM_RULE ptr_rule, _In_ BOOLEAN is_enable, _In_ BOOLEAN is_createconfig ) { PITEM_RULE_CONFIG ptr_config; ULONG rule_hash; ptr_rule->is_enabled = is_enable; if (!ptr_rule->is_readonly || !ptr_rule->name) return; rule_hash = _r_str_gethash (&ptr_rule->name->sr, TRUE); if (!rule_hash) return; ptr_config = _app_getruleconfigitem (rule_hash); if (ptr_config) { ptr_config->is_enabled = is_enable; } else { if (is_createconfig) { _r_queuedlock_acquireexclusive (&lock_rules_config); ptr_config = _app_addruleconfigtable (rules_config, rule_hash, ptr_rule->name, is_enable); _r_queuedlock_releaseexclusive (&lock_rules_config); if (ptr_config) ptr_config->is_enabled = is_enable; } } } VOID _app_ruleremoveapp ( _In_opt_ HWND hwnd, _In_ ULONG_PTR item_id, _In_ PITEM_RULE ptr_rule, _In_ ULONG app_hash ) { if (!ptr_rule->apps) return; if (!_r_obj_removehashtableitem (ptr_rule->apps, app_hash)) return; if (ptr_rule->is_enabled && _r_obj_isempty (ptr_rule->apps)) { ptr_rule->is_enabled = FALSE; ptr_rule->is_haveerrors = FALSE; if (hwnd) { if (item_id != SIZE_MAX) _app_listview_updateitemby_param (hwnd, item_id, FALSE); } } } BOOLEAN _app_ruleblocklistsetchange ( _Inout_ PITEM_RULE ptr_rule, _In_ LONG new_state ) { BOOLEAN is_block; if (new_state == INT_ERROR) return FALSE; // don't change if (new_state == 0 && !ptr_rule->is_enabled) return FALSE; // not changed is_block = (ptr_rule->action == FWP_ACTION_BLOCK); if (new_state == 1 && ptr_rule->is_enabled && !is_block) return FALSE; // not changed if (new_state == 2 && ptr_rule->is_enabled && is_block) return FALSE; // not changed ptr_rule->action = (new_state != 1) ? FWP_ACTION_BLOCK : FWP_ACTION_PERMIT; ptr_rule->is_enabled_default = ptr_rule->is_enabled; // set default value for rule ptr_rule->is_enabled = (new_state != 0); return TRUE; } BOOLEAN _app_ruleblocklistsetstate ( _Inout_ PITEM_RULE ptr_rule, _In_ LONG spy_state, _In_ LONG update_state, _In_ LONG extra_state ) { if (ptr_rule->type != DATA_RULE_BLOCKLIST || _r_obj_isstringempty (ptr_rule->name)) return FALSE; if (_r_str_isstartswith2 (&ptr_rule->name->sr, L"spy_", TRUE)) { return _app_ruleblocklistsetchange (ptr_rule, spy_state); } else if (_r_str_isstartswith2 (&ptr_rule->name->sr, L"update_", TRUE)) { return _app_ruleblocklistsetchange (ptr_rule, update_state); } else if (_r_str_isstartswith2 (&ptr_rule->name->sr, L"extra_", TRUE)) { return _app_ruleblocklistsetchange (ptr_rule, extra_state); } // fallback: block rules with other names by default! return _app_ruleblocklistsetchange (ptr_rule, 2); } VOID _app_ruleblocklistset ( _In_opt_ HWND hwnd, _In_ LONG spy_state, _In_ LONG update_state, _In_ LONG extra_state, _In_ BOOLEAN is_instantapply ) { PR_LIST rules; PITEM_RULE ptr_rule; HANDLE hengine; ULONG_PTR changes_count = 0; rules = _r_obj_createlist (6, &_r_obj_dereference); _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (!ptr_rule) continue; if (ptr_rule->type != DATA_RULE_BLOCKLIST) continue; if (!_app_ruleblocklistsetstate (ptr_rule, spy_state, update_state, extra_state)) continue; _app_ruleenable (ptr_rule, !!ptr_rule->is_enabled, FALSE); changes_count += 1; if (hwnd) _app_listview_updateitemby_param (hwnd, i, FALSE); if (is_instantapply) _r_obj_addlistitem (rules, _r_obj_reference (ptr_rule), NULL); // dereference later! } _r_queuedlock_releaseshared (&lock_rules); if (changes_count) { if (hwnd) _app_listview_updateby_id (hwnd, DATA_RULE_BLOCKLIST, PR_UPDATE_TYPE | PR_UPDATE_NORESIZE); if (is_instantapply) { if (rules->count) { if (_wfp_isfiltersinstalled ()) { hengine = _wfp_getenginehandle (); _wfp_create4filters (hengine, rules, DBG_ARG, FALSE); } } } _app_profile_save (hwnd); // required! } _r_obj_dereference (rules); } _Ret_maybenull_ PR_STRING _app_appexpandrules ( _In_ ULONG app_hash, _In_ LPWSTR delimeter ) { R_STRINGBUILDER buffer; R_STRINGREF delimeter_sr; PR_STRING string; PITEM_RULE ptr_rule; _r_obj_initializestringbuilder (&buffer, 256); _r_obj_initializestringref (&delimeter_sr, delimeter); _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (!ptr_rule) continue; if (ptr_rule->is_enabled && ptr_rule->type == DATA_RULE_USER && !_r_obj_isstringempty (ptr_rule->name) && _r_obj_findhashtable (ptr_rule->apps, app_hash)) { _r_obj_appendstringbuilder2 (&buffer, &ptr_rule->name->sr); if (ptr_rule->is_readonly) _r_obj_appendstringbuilder (&buffer, SZ_RULE_INTERNAL_MENU); _r_obj_appendstringbuilder2 (&buffer, &delimeter_sr); } } _r_queuedlock_releaseshared (&lock_rules); string = _r_obj_finalstringbuilder (&buffer); _r_str_trimstring (&string->sr, &delimeter_sr, 0); if (!_r_obj_isstringempty2 (string)) return string; _r_obj_deletestringbuilder (&buffer); return NULL; } _Ret_maybenull_ PR_STRING _app_rulesexpandapps ( _In_ PITEM_RULE ptr_rule, _In_ BOOLEAN is_fordisplay, _In_ LPWSTR delimeter ) { R_STRINGREF delimeter_sr; R_STRINGBUILDER sr; PITEM_APP ptr_app; PR_STRING string; ULONG_PTR enum_key = 0; ULONG hash_code; _r_obj_initializestringbuilder (&sr, 256); _r_obj_initializestringref (&delimeter_sr, delimeter); if (is_fordisplay && ptr_rule->is_forservices) { string = _r_obj_concatstrings ( 4, PROC_SYSTEM_NAME, delimeter, _r_obj_getstring (config.svchost_path), delimeter ); _r_obj_appendstringbuilder2 (&sr, &string->sr); _r_obj_dereference (string); } while (_r_obj_enumhashtable (ptr_rule->apps, NULL, &hash_code, &enum_key)) { ptr_app = _app_getappitem (hash_code); if (!ptr_app) continue; string = NULL; if (is_fordisplay) { if (ptr_app->type == DATA_APP_UWP) { if (ptr_app->display_name) string = _r_path_compact (&ptr_app->display_name->sr, 64); } } if (!string) { if (is_fordisplay) { if (ptr_app->original_path) string = _r_path_compact (&ptr_app->original_path->sr, 64); } } if (!string) string = _r_obj_referencesafe (ptr_app->original_path); if (string) { _r_obj_appendstringbuilder2 (&sr, &string->sr); _r_obj_appendstringbuilder2 (&sr, &delimeter_sr); _r_obj_dereference (string); } _r_obj_dereference (ptr_app); } string = _r_obj_finalstringbuilder (&sr); _r_str_trimstring (&string->sr, &delimeter_sr, PR_TRIM_END_ONLY); if (!_r_obj_isstringempty2 (string)) return string; _r_obj_deletestringbuilder (&sr); return NULL; } _Ret_maybenull_ PR_STRING _app_rulesexpandrules ( _In_opt_ PR_STRING rule, _In_ LPWSTR delimeter ) { R_STRINGBUILDER sb; R_STRINGREF delimeter_sr; R_STRINGREF remaining_part; R_STRINGREF first_part; PR_STRING string; if (_r_obj_isstringempty (rule)) return NULL; _r_obj_initializestringbuilder (&sb, 256); _r_obj_initializestringref (&delimeter_sr, delimeter); _r_obj_initializestringref2 (&remaining_part, &rule->sr); while (remaining_part.length != 0) { _r_str_splitatchar (&remaining_part, DIVIDER_RULE[0], &first_part, &remaining_part); _r_obj_appendstringbuilder2 (&sb, &first_part); _r_obj_appendstringbuilder2 (&sb, &delimeter_sr); } string = _r_obj_finalstringbuilder (&sb); _r_str_trimstring (&string->sr, &delimeter_sr, 0); if (!_r_obj_isstringempty2 (string)) return string; _r_obj_deletestringbuilder (&sb); return NULL; } BOOLEAN _app_isappfromsystem ( _In_opt_ PR_STRING path, _In_ ULONG app_hash ) { if (_app_issystemhash (app_hash)) return TRUE; if (path) { if (_r_str_isstartswith (&path->sr, &config.windows_dir, TRUE)) return TRUE; } return FALSE; } BOOLEAN _app_isapphavedrive ( _In_ INT letter ) { PITEM_APP ptr_app = NULL; ULONG_PTR enum_key = 0; INT drive_id; _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (_r_obj_isstringempty (ptr_app->original_path)) continue; if (ptr_app->type == DATA_APP_REGULAR) { drive_id = PathGetDriveNumberW (ptr_app->original_path->buffer); } else { drive_id = INT_ERROR; } if (ptr_app->type == DATA_APP_DEVICE || (drive_id != INT_ERROR && drive_id == letter)) { if (ptr_app->is_enabled || _app_isapphaverule (ptr_app->app_hash, FALSE)) { _r_queuedlock_releaseshared (&lock_apps); return TRUE; } } } _r_queuedlock_releaseshared (&lock_apps); return FALSE; } BOOLEAN _app_isapphaverule ( _In_ ULONG app_hash, _In_ BOOLEAN is_countdisabled ) { PITEM_RULE ptr_rule; _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (ptr_rule) { if (ptr_rule->type == DATA_RULE_USER && (is_countdisabled || ptr_rule->is_enabled)) { if (_r_obj_findhashtable (ptr_rule->apps, app_hash)) { _r_queuedlock_releaseshared (&lock_rules); return TRUE; } } } } _r_queuedlock_releaseshared (&lock_rules); return FALSE; } BOOLEAN _app_isappexists ( _In_ PITEM_APP ptr_app ) { if (ptr_app->is_undeletable) return TRUE; if (ptr_app->is_enabled && ptr_app->is_haveerrors) return FALSE; switch (ptr_app->type) { case DATA_APP_REGULAR: { if (ptr_app->real_path && !_r_fs_isexists (&ptr_app->real_path->sr)) return FALSE; return TRUE; } case DATA_APP_DEVICE: case DATA_APP_NETWORK: case DATA_APP_SERVICE: case DATA_APP_UWP: case DATA_APP_PICO: { return TRUE; // service and UWP is already undeletable } default: { FALLTHROUGH; } } return FALSE; } BOOLEAN _app_isappfound ( _In_ ULONG app_hash ) { BOOLEAN is_found; _r_queuedlock_acquireshared (&lock_apps); is_found = (_r_obj_findhashtable (apps_table, app_hash) != NULL); _r_queuedlock_releaseshared (&lock_apps); return is_found; } BOOLEAN _app_isappunused ( _In_ PITEM_APP ptr_app ) { if (ptr_app->is_undeletable) return FALSE; if (!_app_isappexists (ptr_app)) return TRUE; if (!_app_isappused (ptr_app)) return TRUE; return FALSE; } BOOLEAN _app_isappused ( _In_ PITEM_APP ptr_app ) { if (ptr_app->is_enabled || ptr_app->is_silent || ptr_app->is_undeletable) return TRUE; if (_app_isapphaverule (ptr_app->app_hash, TRUE)) return TRUE; return FALSE; } BOOLEAN _app_issystemhash ( _In_ ULONG app_hash ) { return (app_hash == config.ntoskrnl_hash || app_hash == config.svchost_hash); } BOOLEAN _app_isrulesupportedbyos ( _In_ PR_STRINGREF os_version ) { static PR_STRING version_string = NULL; PR_STRING current_version; PR_STRING new_version; current_version = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&version_string, NULL, NULL); if (!current_version) { new_version = _r_format_string (L"%d.%d", NtCurrentPeb ()->OSMajorVersion, NtCurrentPeb ()->OSMinorVersion); current_version = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&version_string, new_version, NULL); if (!current_version) { current_version = new_version; } else { _r_obj_dereference (new_version); } } return (_r_str_versioncompare (¤t_version->sr, os_version) != INT_ERROR); } VOID _app_profile_initialize () { R_STRINGREF profile_internal_sr = PR_STRINGREF_INIT (XML_PROFILE_INTERNAL); R_STRINGREF profile_bak_sr = PR_STRINGREF_INIT (XML_PROFILE_FILE L".bak"); R_STRINGREF profile_sr = PR_STRINGREF_INIT (XML_PROFILE_FILE); R_STRINGREF separator_sr = PR_STRINGREF_INIT (L"\\"); PR_STRING path; path = _r_app_getprofiledirectory (TRUE); _r_obj_movereference ((PVOID_PTR)&profile_info.profile_path, _r_obj_concatstringrefs (3, &path->sr, &separator_sr, &profile_sr)); _r_obj_movereference ((PVOID_PTR)&profile_info.profile_path_backup, _r_obj_concatstringrefs (3, &path->sr, &separator_sr, &profile_bak_sr)); _r_obj_movereference ((PVOID_PTR)&profile_info.profile_path_internal, _r_obj_concatstringrefs (3, &path->sr, &separator_sr, &profile_internal_sr)); } NTSTATUS _app_profile_load_fromresource ( _In_ LPCWSTR resource_name, _Out_ PDB_INFORMATION out_buffer ) { PDB_INFORMATION db_info; R_STORAGE bytes; NTSTATUS status; db_info = out_buffer; status = _app_db_initialize (db_info, TRUE); if (NT_SUCCESS (status)) { status = _r_res_loadresource (_r_sys_getimagebase (), RT_RCDATA, resource_name, 0, &bytes); if (NT_SUCCESS (status)) status = _app_db_openfrombuffer (db_info, &bytes, XML_VERSION_MAXIMUM, XML_TYPE_PROFILE_INTERNAL); } return status; } VOID _app_profile_load_fallback () { ULONG app_hash; if (!_app_isappfound (config.my_hash)) { app_hash = _app_addapplication (NULL, DATA_UNKNOWN, config.my_path, NULL, NULL); if (app_hash) _app_setappinfobyhash (app_hash, INFO_IS_ENABLED, LongToPtr (TRUE)); } _app_setappinfobyhash (config.my_hash, INFO_IS_UNDELETABLE, LongToPtr (TRUE)); // disable deletion for this shit ;) if (!_r_config_getboolean (L"IsInternalRulesDisabled", FALSE, NULL)) { if (!_app_isappfound (config.ntoskrnl_hash) && !_r_obj_isstringempty (config.system_path)) _app_addapplication (NULL, DATA_UNKNOWN, config.system_path, NULL, NULL); if (!_app_isappfound (config.svchost_hash) && !_r_obj_isstringempty (config.svchost_path)) _app_addapplication (NULL, DATA_UNKNOWN, config.svchost_path, NULL, NULL); _app_setappinfobyhash (config.ntoskrnl_hash, INFO_IS_UNDELETABLE, LongToPtr (TRUE)); _app_setappinfobyhash (config.svchost_hash, INFO_IS_UNDELETABLE, LongToPtr (TRUE)); } } VOID _app_profile_load_internal ( _In_opt_ HWND hwnd, _In_ PR_STRING path, _In_ LPCWSTR resource_name, _Out_ PLONG64 out_timestamp ) { DB_INFORMATION db_info_buffer; DB_INFORMATION db_info_file; PDB_INFORMATION db_info; BOOLEAN is_loadfromresource; LONG64 timestamp = 0; NTSTATUS status_file; NTSTATUS status_res; NTSTATUS status; status_file = _app_db_initialize (&db_info_file, TRUE); if (_r_fs_isexists (&path->sr)) { if (NT_SUCCESS (status_file)) status_file = _app_db_openfromfile (&db_info_file, path, XML_VERSION_MAXIMUM, XML_TYPE_PROFILE_INTERNAL); } else { status_file = STATUS_OBJECT_PATH_NOT_FOUND; } status_res = _app_profile_load_fromresource (resource_name, &db_info_buffer); // NOTE: prefer new profile version for 3.4+ if (!NT_SUCCESS (status_file)) { is_loadfromresource = TRUE; } else { is_loadfromresource = (db_info_file.version < db_info_buffer.version) || (db_info_file.timestamp < db_info_buffer.timestamp); } db_info = is_loadfromresource ? &db_info_buffer : &db_info_file; status = is_loadfromresource ? status_res : status_file; if (NT_SUCCESS (status)) { if (_app_db_parse (db_info, XML_TYPE_PROFILE_INTERNAL)) timestamp = db_info->timestamp; } else { if (status != STATUS_OBJECT_NAME_NOT_FOUND && status != STATUS_OBJECT_PATH_NOT_FOUND) { if (hwnd) _r_show_errormessage (hwnd, L"Could not load internal profile!", status, NULL, ET_NATIVE); _r_log (LOG_LEVEL_ERROR, NULL, L"_app_profile_load_internal", status, NULL); } } *out_timestamp = timestamp; _app_db_destroy (&db_info_buffer); _app_db_destroy (&db_info_file); } VOID _app_profile_refresh ( _In_opt_ HWND hwnd ) { // clear apps _r_queuedlock_acquireexclusive (&lock_apps); _r_obj_clearhashtable (apps_table); _r_queuedlock_releaseexclusive (&lock_apps); // clear rules _r_queuedlock_acquireexclusive (&lock_rules); _r_obj_clearlist (rules_list); _r_queuedlock_releaseexclusive (&lock_rules); // clear rules config _r_queuedlock_acquireexclusive (&lock_rules_config); _r_obj_clearhashtable (rules_config); _r_queuedlock_releaseexclusive (&lock_rules_config); if (!hwnd) hwnd = _r_app_gethwnd (); // generate services list _app_package_getserviceslist (hwnd); // generate uwp packages list (win8+) if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) _app_package_getpackageslist (hwnd); } NTSTATUS _app_profile_load ( _In_opt_ HWND hwnd, _In_opt_ PR_STRING path_custom ) { DB_INFORMATION db_info; BOOLEAN is_update; NTSTATUS status; status = _app_db_initialize (&db_info, TRUE); if (!NT_SUCCESS (status)) { if (hwnd) _r_show_errormessage (hwnd, L"Could not intitialize profile!", status, NULL, ET_WINDOWS); _r_log (LOG_LEVEL_ERROR, NULL, L"_app_db_initialize", status, NULL); goto CleanupExit; } if (path_custom) { status = _app_db_openfromfile (&db_info, path_custom, XML_VERSION_MINIMAL, XML_TYPE_PROFILE); } else { _r_queuedlock_acquireshared (&lock_profile); status = _app_db_openfromfile (&db_info, profile_info.profile_path, XML_VERSION_MINIMAL, XML_TYPE_PROFILE); if (!NT_SUCCESS (status)) status = _app_db_openfromfile (&db_info, profile_info.profile_path_backup, XML_VERSION_MINIMAL, XML_TYPE_PROFILE); _r_queuedlock_releaseshared (&lock_profile); } CleanupExit: is_update = (NT_SUCCESS (status) || !path_custom); if (is_update) { if (hwnd) _app_listview_clearitems (hwnd); _app_profile_refresh (hwnd); } if (NT_SUCCESS (status)) { _app_db_parse (&db_info, XML_TYPE_PROFILE); } else { if (status != STATUS_OBJECT_NAME_NOT_FOUND && status != STATUS_OBJECT_PATH_NOT_FOUND) { if (hwnd) _r_show_errormessage (hwnd, L"Could not load profile!", status, NULL, ET_NATIVE); _r_log (LOG_LEVEL_ERROR, NULL, L"_app_profile_load", status, NULL); } } if (is_update) { // load internal rules (new!) if (!_r_config_getboolean (L"IsInternalRulesDisabled", FALSE, NULL)) _app_profile_load_internal (hwnd, profile_info.profile_path_internal, MAKEINTRESOURCE (IDR_PROFILE_INTERNAL), &profile_info.profile_internal_timestamp); _app_profile_load_fallback (); if (hwnd) _app_listview_additems (hwnd); } _app_db_destroy (&db_info); return status; } NTSTATUS _app_profile_save ( _In_opt_ HWND hwnd ) { DB_INFORMATION db_info; LONG64 timestamp; BOOLEAN is_backuprequired = FALSE; NTSTATUS status; status = _app_db_initialize (&db_info, FALSE); if (!NT_SUCCESS (status)) { if (hwnd) _r_show_errormessage (hwnd, L"Could not intitialize profile!", status, NULL, ET_WINDOWS); _r_log (LOG_LEVEL_ERROR, NULL, L"_app_db_initialize", status, NULL); return status; } timestamp = _r_unixtime_now (); if (_r_config_getboolean (L"IsBackupProfile", TRUE, NULL)) { if (!_r_fs_isexists (&profile_info.profile_path_backup->sr)) is_backuprequired = TRUE; if (!is_backuprequired) { if (timestamp - _r_config_getlong64 (L"BackupTimestamp", 0, NULL) >= _r_config_getlong64 (L"BackupPeriod", BACKUP_HOURS_PERIOD, NULL)) is_backuprequired = TRUE; } } _r_queuedlock_acquireexclusive (&lock_profile); status = _app_db_savetofile (&db_info, profile_info.profile_path, XML_VERSION_MAXIMUM, XML_TYPE_PROFILE, timestamp); _r_queuedlock_releaseexclusive (&lock_profile); if (!NT_SUCCESS (status)) { if (hwnd) _r_show_errormessage (hwnd, L"Could not save profile!", status, NULL, ET_NATIVE); _r_log (LOG_LEVEL_ERROR, NULL, L"_app_db_savetofile", status, profile_info.profile_path->buffer); } _app_db_destroy (&db_info); // make backup if (is_backuprequired) { _r_fs_copyfile (&profile_info.profile_path->sr, &profile_info.profile_path_backup->sr, FALSE); _r_config_setlong64 (L"BackupTimestamp", timestamp, NULL); } return status; } ================================================ FILE: src/profile.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once FORCEINLINE BOOLEAN _app_isdisabledremoval ( _In_ ULONG app_hash ) { if (app_hash == config.my_hash || app_hash == config.ntoskrnl_hash || app_hash == config.svchost_hash || app_hash == config.wusvc_hash) return TRUE; return FALSE; } _Success_ (return) BOOLEAN _app_getappinfo ( _In_ PITEM_APP ptr_app, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ); _Success_ (return) BOOLEAN _app_getappinfobyhash ( _In_ ULONG app_hash, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ); VOID _app_setappinfo ( _In_ PITEM_APP ptr_app, _In_ ENUM_INFO_DATA info_data, _In_opt_ PVOID value ); VOID _app_setappinfobyhash ( _In_ ULONG app_hash, _In_ ENUM_INFO_DATA info_data, _In_opt_ PVOID value ); _Success_ (return) BOOLEAN _app_getruleinfo ( _In_ PITEM_RULE ptr_rule, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ); _Success_ (return) BOOLEAN _app_getruleinfobyid ( _In_ ULONG_PTR index, _In_ ENUM_INFO_DATA info_data, _Out_writes_bytes_all_ (length) PVOID buffer, _In_ ULONG_PTR length ); _Success_ (return != 0) ULONG _app_addapplication ( _In_opt_ HWND hwnd, _In_ ENUM_TYPE_DATA type, _In_ PR_STRING path, _In_opt_ PR_STRING display_name, _In_opt_ PR_STRING real_path ); PITEM_RULE _app_addrule ( _In_opt_ PR_STRING name, _In_opt_ PR_STRING rule_remote, _In_opt_ PR_STRING rule_local, _In_ FWP_DIRECTION direction, _In_ FWP_ACTION_TYPE action, _In_ UINT8 protocol, _In_ ADDRESS_FAMILY af ); _Ret_maybenull_ PITEM_RULE_CONFIG _app_addruleconfigtable ( _In_ PR_HASHTABLE hashtable, _In_ ULONG rule_hash, _In_ PR_STRING rule_name, _In_ BOOLEAN is_enabled ); _Ret_maybenull_ PITEM_APP _app_getappitem ( _In_ ULONG app_hash ); _Ret_maybenull_ PITEM_RULE _app_getrulebyid ( _In_ ULONG_PTR index ); _Ret_maybenull_ PITEM_RULE _app_getrulebyhash ( _In_ ULONG_PTR rule_hash ); _Ret_maybenull_ PITEM_RULE_CONFIG _app_getruleconfigitem ( _In_ ULONG rule_hash ); _Ret_maybenull_ PITEM_LOG _app_getlogitem ( _In_ ULONG log_hash ); _Success_ (return != 0) ULONG _app_getlogapp ( _In_ ULONG index ); COLORREF _app_getappcolor ( _In_ INT listview_id, _In_ ULONG app_hash, _In_ BOOLEAN is_systemapp, _In_ BOOLEAN is_validconnection ); VOID _app_deleteappitem ( _In_ HWND hwnd, _In_ ENUM_TYPE_DATA type, _In_ ULONG_PTR id_code ); VOID _app_freeapplication ( _In_opt_ HWND hwnd, _In_ ULONG app_hash ); BOOLEAN _app_isappfromsystem ( _In_opt_ PR_STRING path, _In_ ULONG app_hash ); BOOLEAN _app_isapphavedrive ( _In_ INT letter ); BOOLEAN _app_isapphaverule ( _In_ ULONG app_hash, _In_ BOOLEAN is_countdisabled ); BOOLEAN _app_isappexists ( _In_ PITEM_APP ptr_app ); BOOLEAN _app_isappfound ( _In_ ULONG app_hash ); BOOLEAN _app_isappunused ( _In_ PITEM_APP ptr_app ); BOOLEAN _app_isappused ( _In_ PITEM_APP ptr_app ); BOOLEAN _app_issystemhash ( _In_ ULONG app_hash ); VOID _app_getcount ( _Out_ PITEM_STATUS status ); COLORREF _app_getrulecolor ( _In_ INT listview_id, _In_ ULONG_PTR rule_idx ); VOID _app_setappiteminfo ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _In_ PITEM_APP ptr_app ); VOID _app_setruleiteminfo ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _In_ PITEM_RULE ptr_rule, _In_ BOOLEAN include_apps ); VOID _app_ruleenable ( _Inout_ PITEM_RULE ptr_rule, _In_ BOOLEAN is_enable, _In_ BOOLEAN is_createconfig ); //VOID _app_rulecleanapp ( // _In_opt_ HWND hwnd, // _In_ ULONG_PTR item_id, // _In_ PITEM_RULE ptr_rule, // _In_opt_ ULONG_PTR app_hash //); VOID _app_ruleremoveapp ( _In_opt_ HWND hwnd, _In_ ULONG_PTR item_id, _In_ PITEM_RULE ptr_rule, _In_ ULONG app_hash ); BOOLEAN _app_ruleblocklistsetchange ( _Inout_ PITEM_RULE ptr_rule, _In_ LONG new_state ); BOOLEAN _app_ruleblocklistsetstate ( _Inout_ PITEM_RULE ptr_rule, _In_ LONG spy_state, _In_ LONG update_state, _In_ LONG extra_state ); VOID _app_ruleblocklistset ( _In_opt_ HWND hwnd, _In_ LONG spy_state, _In_ LONG update_state, _In_ LONG extra_state, _In_ BOOLEAN is_instantapply ); _Ret_maybenull_ PR_STRING _app_appexpandrules ( _In_ ULONG app_hash, _In_ LPWSTR delimeter ); _Ret_maybenull_ PR_STRING _app_rulesexpandapps ( _In_ PITEM_RULE ptr_rule, _In_ BOOLEAN is_fordisplay, _In_ LPWSTR delimeter ); _Ret_maybenull_ PR_STRING _app_rulesexpandrules ( _In_opt_ PR_STRING rule, _In_ LPWSTR delimeter ); BOOLEAN _app_isrulesupportedbyos ( _In_ PR_STRINGREF os_version ); VOID _app_profile_initialize (); NTSTATUS _app_profile_load_fromresource ( _In_ LPCWSTR resource_name, _Out_ PDB_INFORMATION out_buffer ); VOID _app_profile_load_fallback (); VOID _app_profile_load_internal ( _In_opt_ HWND hwnd, _In_ PR_STRING path, _In_ LPCWSTR resource_name, _Out_ PLONG64 out_timestamp ); NTSTATUS _app_profile_load ( _In_opt_ HWND hwnd, _In_opt_ PR_STRING path_custom ); NTSTATUS _app_profile_save ( _In_opt_ HWND hwnd ); ================================================ FILE: src/res/manifest.xml ================================================ true PerMonitorV2, PerMonitor true true true UTF-8 SegmentHeap ================================================ FILE: src/resource.h ================================================ #ifndef __RESOURCE_H__ #define __RESOURCE_H__ #ifndef IDC_STATIC #define IDC_STATIC (-1) #endif // Acceleration #define IDA_MAIN 1 // Menu Id #define IDM_MAIN 100 #define IDM_TRAY 101 // Dialogs #define IDD_MAIN 100 #define IDD_NOTIFICATION 101 #define IDD_EDITOR 102 #define IDD_EDITOR_GENERAL 103 #define IDD_EDITOR_RULE 104 #define IDD_EDITOR_APPS 105 #define IDD_EDITOR_ADDRULE 106 #define IDD_EDITOR_APPINFO 107 #define IDD_EDITOR_APPRULES 108 #define IDD_SETTINGS_GENERAL 109 #define IDD_SETTINGS_INTERFACE 110 #define IDD_SETTINGS_HIGHLIGHTING 111 #define IDD_SETTINGS_RULES 112 #define IDD_SETTINGS_BLOCKLIST 113 #define IDD_SETTINGS_NOTIFICATIONS 114 #define IDD_SETTINGS_LOGGING 115 #define IDD_SETTINGS_EXCLUDE 116 // Main Dlg #define IDC_REBAR 102 #define IDC_TOOLBAR 103 #define IDC_SEARCH 104 #define IDC_TAB 105 #define IDC_APPS_PROFILE 106 #define IDC_APPS_SERVICE 107 #define IDC_APPS_UWP 108 #define IDC_RULES_BLOCKLIST 109 #define IDC_RULES_SYSTEM 110 #define IDC_RULES_CUSTOM 111 #define IDC_NETWORK 112 #define IDC_LOG 113 #define IDC_STATUSBAR 114 // Settings Dlg #define IDC_NAV 115 #define IDC_SAVE 116 #define IDC_RESET 117 #define IDC_CLOSE 118 #define IDC_TITLE_GENERAL 119 #define IDC_TITLE_LANGUAGE 120 #define IDC_TITLE_CONNECTIONS 121 #define IDC_TITLE_SECURITY 122 #define IDC_TITLE_BLOCKLIST_SPY 123 #define IDC_TITLE_BLOCKLIST_UPDATE 124 #define IDC_TITLE_BLOCKLIST_EXTRA 125 #define IDC_TITLE_CONFIRMATIONS 126 #define IDC_TITLE_TRAY 127 #define IDC_TITLE_HIGHLIGHTING 128 #define IDC_TITLE_NOTIFICATIONS 129 #define IDC_TITLE_LOGGING 130 #define IDC_TITLE_LOGVIEWER 131 #define IDC_TITLE_INTERFACE 132 #define IDC_TITLE_ADVANCED 133 #define IDC_ALWAYSONTOP_CHK 134 #define IDC_LOADONSTARTUP_CHK 135 #define IDC_STARTMINIMIZED_CHK 136 #define IDC_SKIPUACWARNING_CHK 137 #define IDC_CHECKUPDATES_CHK 138 #define IDC_LANGUAGE_HINT 139 #define IDC_LANGUAGE 140 #define IDC_RULE_BLOCKOUTBOUND 141 #define IDC_RULE_BLOCKINBOUND 142 #define IDC_RULE_ALLOWLOOPBACK 143 #define IDC_RULE_ALLOW6TO4 144 #define IDC_USESTEALTHMODE_CHK 145 #define IDC_INSTALLBOOTTIMEFILTERS_CHK 146 #define IDC_USECERTIFICATES_CHK 147 #define IDC_USEHASHES_CHK 148 #define IDC_USENETWORKRESOLUTION_CHK 149 #define IDC_BLOCKLIST_SPY_DISABLE 150 #define IDC_BLOCKLIST_SPY_ALLOW 151 #define IDC_BLOCKLIST_SPY_BLOCK 152 #define IDC_BLOCKLIST_UPDATE_DISABLE 153 #define IDC_BLOCKLIST_UPDATE_ALLOW 154 #define IDC_BLOCKLIST_UPDATE_BLOCK 155 #define IDC_BLOCKLIST_EXTRA_DISABLE 156 #define IDC_BLOCKLIST_EXTRA_ALLOW 157 #define IDC_BLOCKLIST_EXTRA_BLOCK 158 #define IDC_BLOCKLIST_INFO 159 #define IDC_CONFIRMEXIT_CHK 160 #define IDC_CONFIRMEXITTIMER_CHK 161 #define IDC_CONFIRMLOGCLEAR_CHK 162 #define IDC_CONFIRMALLOW_CHK 163 #define IDC_TRAYICONSINGLECLICK_CHK 164 #define IDC_COLORS 165 #define IDC_COLORS_HINT 166 #define IDC_ENABLENOTIFICATIONS_CHK 167 #define IDC_NOTIFICATIONSOUND_CHK 168 #define IDC_NOTIFICATIONFULLSCREENSILENTMODE_CHK 169 #define IDC_NOTIFICATIONONTRAY_CHK 170 #define IDC_NOTIFICATIONTIMEOUT_HINT 171 #define IDC_NOTIFICATIONTIMEOUT_CTRL 172 #define IDC_NOTIFICATIONTIMEOUT 173 #define IDC_EXCLUDESTEALTH_CHK 174 #define IDC_EXCLUDECLASSIFYALLOW_CHK 175 #define IDC_EXCLUDEBLOCKLIST_CHK 176 #define IDC_EXCLUDECUSTOM_CHK 177 #define IDC_ENABLELOG_CHK 178 #define IDC_LOGPATH 179 #define IDC_LOGPATH_BTN 180 #define IDC_LOGVIEWER 181 #define IDC_LOGVIEWER_BTN 182 #define IDC_ENABLEUILOG_CHK 183 #define IDC_LOGSIZELIMIT_HINT 184 #define IDC_LOGSIZELIMIT_CTRL 185 #define IDC_LOGSIZELIMIT 186 // Notification Dlg #define IDC_HEADER_ID 187 #define IDC_FILE_TEXT 188 #define IDC_SIGNATURE_TEXT 189 #define IDC_ADDRESS_TEXT 190 #define IDC_HOST_TEXT 191 #define IDC_PORT_TEXT 192 #define IDC_DIRECTION_TEXT 193 #define IDC_FILTER_TEXT 194 #define IDC_DATE_TEXT 195 #define IDC_FILE_ID 196 #define IDC_SIGNATURE_ID 197 #define IDC_ADDRESS_ID 198 #define IDC_HOST_ID 199 #define IDC_PORT_ID 200 #define IDC_DIRECTION_ID 201 #define IDC_FILTER_ID 202 #define IDC_DATE_ID 203 #define IDC_RULES_BTN 204 #define IDC_KILLPROCESS_BTN 205 #define IDC_ALLOW_BTN 206 #define IDC_BLOCK_BTN 207 #define IDC_NEXT_BTN 208 // Editor Dlg #define IDC_RULE_NAME 209 #define IDC_RULE_NAME_ID 210 #define IDC_RULE_COMMENT 211 #define IDC_RULE_COMMENT_ID 212 #define IDC_RULE_PROTOCOL 213 #define IDC_RULE_PROTOCOL_ID 214 #define IDC_RULE_VERSION 215 #define IDC_RULE_VERSION_ID 216 #define IDC_RULE_DIRECTION 217 #define IDC_RULE_DIRECTION_ID 218 #define IDC_RULE_ACTION 219 #define IDC_RULE_ACTION_ID 220 #define IDC_RULE_REMOTE 221 #define IDC_RULE_REMOTE_ID 222 #define IDC_RULE_REMOTE_ADD 223 #define IDC_RULE_REMOTE_EDIT 224 #define IDC_RULE_REMOTE_DELETE 225 #define IDC_RULE_LOCAL 226 #define IDC_RULE_LOCAL_ID 227 #define IDC_RULE_LOCAL_ADD 228 #define IDC_RULE_LOCAL_EDIT 229 #define IDC_RULE_LOCAL_DELETE 230 #define IDC_RULE_APPS_ID 231 #define IDC_RULE_APPS_HINT 232 #define IDC_RULE 233 #define IDC_RULE_ID 234 #define IDC_RULE_HINT 235 #define IDC_APP_NAME 236 #define IDC_APP_ICON_ID 237 #define IDC_APP_NAME_ID 238 #define IDC_APP_SIGNATURE_ID 239 #define IDC_APP_PATH 240 #define IDC_APP_PATH_ID 241 #define IDC_APP_EXPLORE_ID 242 #define IDC_APP_COMMENT 243 #define IDC_APP_COMMENT_ID 244 #define IDC_APP_HASH 245 #define IDC_APP_HASH_ID 246 #define IDC_APP_HASH_RECHECK_ID 247 #define IDC_APP_RULES_ID 248 #define IDC_APP_HINT 249 #define IDC_ENABLE_CHK 250 // Main Menu #define IDM_SETTINGS 251 #define IDM_ADD_FILE 252 #define IDM_IMPORT 253 #define IDM_EXPORT 254 #define IDM_EXIT 255 #define IDM_PURGE_UNUSED 256 #define IDM_PURGE_TIMERS 257 #define IDM_LOGCLEAR 258 #define IDM_FIND 259 #define IDM_REFRESH 260 #define IDM_ALWAYSONTOP_CHK 261 #define IDM_SHOWFILENAMESONLY_CHK 262 #define IDM_SHOWSEARCHBAR_CHK 263 #define IDM_AUTOSIZECOLUMNS_CHK 264 #define IDM_VIEW_DETAILS 265 #define IDM_VIEW_ICON 266 #define IDM_VIEW_TILE 267 #define IDM_SIZE_SMALL 268 #define IDM_SIZE_LARGE 269 #define IDM_SIZE_EXTRALARGE 270 #define IDM_ICONSISHIDDEN 271 #define IDM_USEDARKTHEME_CHK 272 #define IDM_FONT 273 #define IDM_LOADONSTARTUP_CHK 274 #define IDM_STARTMINIMIZED_CHK 275 #define IDM_SKIPUACWARNING_CHK 276 #define IDM_CHECKUPDATES_CHK 277 #define IDM_RULE_BLOCKOUTBOUND 278 #define IDM_RULE_BLOCKINBOUND 279 #define IDM_RULE_ALLOWLOOPBACK 280 #define IDM_RULE_ALLOW6TO4 281 #define IDM_RULE_ALLOWWINDOWSUPDATE 282 #define IDM_PROFILETYPE_PLAIN 283 #define IDM_PROFILETYPE_COMPRESSED 284 #define IDM_PROFILETYPE_ENCRYPTED 285 #define IDM_USENETWORKRESOLUTION_CHK 286 #define IDM_USECERTIFICATES_CHK 287 #define IDM_KEEPUNUSED_CHK 288 #define IDM_USEHASHES_CHK 289 #define IDM_USEAPPMONITOR_CHK 290 #define IDM_BLOCKLIST_SPY_DISABLE 291 #define IDM_BLOCKLIST_SPY_ALLOW 292 #define IDM_BLOCKLIST_SPY_BLOCK 293 #define IDM_BLOCKLIST_UPDATE_DISABLE 294 #define IDM_BLOCKLIST_UPDATE_ALLOW 295 #define IDM_BLOCKLIST_UPDATE_BLOCK 296 #define IDM_BLOCKLIST_EXTRA_DISABLE 297 #define IDM_BLOCKLIST_EXTRA_ALLOW 298 #define IDM_BLOCKLIST_EXTRA_BLOCK 299 #define IDM_WEBSITE 300 #define IDM_CHECKUPDATES 301 #define IDM_DONATE 302 #define IDM_ABOUT 303 // Tray Menu #define IDM_TRAY_SHOW 304 #define IDM_TRAY_START 305 #define IDM_TRAY_ENABLENOTIFICATIONS_CHK 306 #define IDM_TRAY_ENABLENOTIFICATIONSSOUND_CHK 307 #define IDM_TRAY_NOTIFICATIONFULLSCREENSILENTMODE_CHK 308 #define IDM_TRAY_NOTIFICATIONONTRAY_CHK 309 #define IDM_TRAY_ENABLELOG_CHK 310 #define IDM_TRAY_ENABLEUILOG_CHK 311 #define IDM_TRAY_LOGSHOW 312 #define IDM_TRAY_LOGCLEAR 313 #define IDM_TRAY_LOGSHOW_ERR 314 #define IDM_TRAY_LOGCLEAR_ERR 315 #define IDM_TRAY_SETTINGS 316 #define IDM_TRAY_WEBSITE 317 #define IDM_TRAY_ABOUT 318 #define IDM_TRAY_EXIT 319 // Listview Menu #define IDM_EXPLORE 320 #define IDM_DISABLENOTIFICATIONS 321 #define IDM_DISABLEREMOVAL 322 #define IDM_OPENRULESEDITOR 323 #define IDM_COPY 324 #define IDM_COPY_VALUE 325 #define IDM_CHECK 326 #define IDM_UNCHECK 327 #define IDM_DELETE 328 #define IDM_DISABLETIMER 329 #define IDM_PROPERTIES 330 #define IDM_NOTIMER 331 #define IDM_SELECT_ALL 332 #define IDM_ZOOM 333 #define IDM_TAB_NEXT 334 #define IDM_TAB_PREV 335 #define IDX_LANGUAGE 1000 #define IDX_TIMER 1200 #define IDX_NOTIFICATIONS 1300 #define IDX_RULES_SPECIAL 1400 #define IDX_COLUMN 1500 // Strings #define IDS_TITLE_EXCLUDE 1 #define IDS_FILE 2 #define IDS_SETTINGS 3 #define IDS_EXIT 4 #define IDS_EDIT 5 #define IDS_PURGE_ERRORS 6 #define IDS_PURGE_UNUSED 7 #define IDS_PURGE_TIMERS 8 #define IDS_FIND 9 #define IDS_FINDNEXT 10 #define IDS_REFRESH 11 #define IDS_VIEW 12 #define IDS_ICONS 13 #define IDS_ICONSSMALL 14 #define IDS_ICONSLARGE 15 #define IDS_ICONSISHIDDEN 16 #define IDS_LANGUAGE 17 #define IDS_FONT 18 #define IDS_HELP 19 #define IDS_WEBSITE 20 #define IDS_CHECKUPDATES 21 #define IDS_DONATE 22 #define IDS_ABOUT 23 #define IDS_TRAY_SHOW 24 #define IDS_TRAY_START 25 #define IDS_TRAY_STOP 26 #define IDS_TRAY_MODE 27 #define IDS_TRAY_RULES 28 #define IDS_TRAY_BLOCKLIST_RULES 29 #define IDS_TRAY_SYSTEM_RULES 30 #define IDS_TRAY_USER_RULES 31 #define IDS_TRAY_LOG 32 #define IDS_TRAY_LOGERR 33 #define IDS_ADD_FILE 34 #define IDS_ADD_PROCESS 35 #define IDS_ADD_PACKAGE 36 #define IDS_ADD_SERVICE 37 #define IDS_ANY 38 #define IDS_DISABLENOTIFICATIONS 39 #define IDS_OPENRULESEDITOR 40 #define IDS_TIMER 41 #define IDS_NOTIMER 42 #define IDS_DISABLETIMER 43 #define IDS_EXPLORE 44 #define IDS_COPY 45 #define IDS_SELECT_ALL 46 #define IDS_CHECK 47 #define IDS_UNCHECK 48 #define IDS_ADD 49 #define IDS_EDIT2 50 #define IDS_DELETE 51 #define IDS_EXPORT 52 #define IDS_IMPORT 53 #define IDS_MODE_WHITELIST 54 #define IDS_MODE_BLACKLIST 55 #define IDS_RULE_ALLOWINBOUND 56 #define IDS_RULE_ALLOWLISTEN 57 #define IDS_RULE_ALLOWLOOPBACK 58 #define IDS_HIGHLIGHT_INVALID 59 #define IDS_HIGHLIGHT_NETWORK 60 #define IDS_HIGHLIGHT_PACKAGE 61 #define IDS_HIGHLIGHT_PICO 62 #define IDS_HIGHLIGHT_SERVICE 63 #define IDS_HIGHLIGHT_SIGNED 64 #define IDS_HIGHLIGHT_SILENT 65 #define IDS_HIGHLIGHT_SPECIAL 66 #define IDS_HIGHLIGHT_SYSTEM 67 #define IDS_GROUP_TIMER 68 #define IDS_EDITOR 69 #define IDS_NAME 70 #define IDS_RULE 71 #define IDS_PORTVERSION 72 #define IDS_PROTOCOL 73 #define IDS_DIRECTION 74 #define IDS_ACTION 75 #define IDS_DATE 76 #define IDS_FILEPATH 77 #define IDS_SIGNATURE 78 #define IDS_ADDRESS 79 #define IDS_FILTER 80 #define IDS_NOTES 81 #define IDS_ADDED 82 #define IDS_REGION 83 #define IDS_TIMELEFT 84 #define IDS_SIGN_SIGNED 85 #define IDS_SIGN_UNSIGNED 86 #define IDS_GROUP_ALLOWED 87 #define IDS_GROUP_BLOCKED 88 #define IDS_GROUP_ENABLED 89 #define IDS_GROUP_SPECIAL 90 #define IDS_GROUP_DISABLED 91 #define IDS_DIRECTION_1 92 #define IDS_DIRECTION_2 93 #define IDS_DIRECTION_3 94 #define IDS_ACTION_ALLOW 95 #define IDS_ACTION_BLOCK 96 #define IDS_ACTION_LATER 97 #define IDS_RULE_APPLY 98 #define IDS_DISABLE_CHK 99 #define IDS_ENABLE_CHK 100 #define IDS_ENABLEFORAPPS_CHK 101 #define IDS_WIKI 102 #define IDS_SAVE 103 #define IDS_CLOSE 104 #define IDS_SETTINGS_GENERAL 105 #define IDS_TITLE_GENERAL 106 #define IDS_TITLE_LANGUAGE 107 #define IDS_TITLE_CONFIRMATIONS 108 #define IDS_TITLE_INTERFACE 109 #define IDS_TITLE_HIGHLIGHTING 110 #define IDS_TITLE_EXPERTS 111 #define IDS_TITLE_LOGGING 112 #define IDS_TITLE_NOTIFICATIONS 113 #define IDS_TITLE_ADVANCED 114 #define IDS_ALWAYSONTOP_CHK 115 #define IDS_LOADONSTARTUP_CHK 116 #define IDS_STARTMINIMIZED_CHK 117 #define IDS_SHOWFILENAMESONLY_CHK 118 #define IDS_AUTOSIZECOLUMNS_CHK 119 #define IDS_SKIPUACWARNING_CHK 120 #define IDS_CHECKUPDATES_CHK 121 #define IDS_LANGUAGE_HINT 122 #define IDS_USEFULLBLOCKLIST_CHK 123 #define IDS_USEFULLBLOCKLIST_HINT 124 #define IDS_USESTEALTHMODE_CHK 125 #define IDS_USESTEALTHMODE_HINT 126 #define IDS_INSTALLBOOTTIMEFILTERS_CHK 127 #define IDS_INSTALLBOOTTIMEFILTERS_HINT 128 #define IDS_PROXYSUPPORT_CHK 129 #define IDS_PROXYSUPPORT_HINT 130 #define IDS_USEHOSTS_CHK 131 #define IDS_USECERTIFICATES_CHK 132 #define IDS_USENETWORKRESOLUTION_CHK 133 #define IDS_DISABLEWINDOWSFIREWALL_CHK 134 #define IDS_ENABLEWINDOWSFIREWALL_CHK 135 #define IDS_CONFIRMEXIT_CHK 136 #define IDS_CONFIRMEXITTIMER_CHK 137 #define IDS_CONFIRMDELETE_CHK 138 #define IDS_CONFIRMLOGCLEAR_CHK 139 #define IDS_COLORS_HINT 140 #define IDS_ENABLELOG_CHK 141 #define IDS_LOGSHOW 142 #define IDS_LOGCLEAR 143 #define IDS_LOGSIZELIMIT_HINT 144 #define IDS_ENABLENOTIFICATIONS_CHK 145 #define IDS_NOTIFICATIONSOUND_CHK 146 #define IDS_NOTIFICATIONNOBLOCKLIST_CHK 147 #define IDS_NOTIFICATIONDISPLAYTIMEOUT_HINT 148 #define IDS_NOTIFICATIONTIMEOUT_HINT 149 #define IDS_RULES_BLOCKLIST_HINT 150 #define IDS_RULES_SYSTEM_HINT 151 #define IDS_RULES_USER_HINT 152 #define IDS_NOTIFY_CREATERULE_ADDRESS 153 #define IDS_NOTIFY_CREATERULE_PORT 154 #define IDS_NOTIFY_DISABLENOTIFICATIONS 155 #define IDS_NOTIFY_TOOLTIP 156 #define IDS_QUESTION 157 #define IDS_QUESTION_DELETE 158 #define IDS_QUESTION_START 159 #define IDS_QUESTION_STOP 160 #define IDS_QUESTION_MODE 161 #define IDS_QUESTION_EXIT 162 #define IDS_QUESTION_LISTEN 163 #define IDS_QUESTION_EXPERT 164 #define IDS_QUESTION_TIMER 165 #define IDS_QUESTION_TIMERS 166 #define IDS_QUESTION_FLAG_CHK 167 #define IDS_STATUS_TOTAL 168 #define IDS_STATUS_SELECTED 169 #define IDS_STATUS_EMPTY 170 #define IDS_STATUS_ERROR 171 #define IDS_STATUS_SYNTAX_ERROR 172 #define IDS_ADDRESS_LOCAL 173 #define IDS_ADDRESS_REMOTE 174 #define IDS_UPDATE_ERROR 175 #define IDS_CHECKUPDATESBETA_CHK 176 #define IDS_CHECKUPDATES_LANGUAGE 177 #define IDS_CHECKUPDATES_BLOCKLIST 178 #define IDS_UPDATE_DOWNLOAD 179 #define IDS_UPDATE_DONE 180 #define IDS_GROUP_SPECIAL_APPS 181 #define IDS_RULE_ALLOWINBOUND_HINT 182 #define IDS_RULE_ALLOWLISTEN_HINT 183 #define IDS_RULE_ALLOWLOOPBACK_HINT 184 #define IDS_PROPERTIES 185 #define IDS_RESET 186 #define IDS_QUESTION_RESET 187 #define IDS_TITLE_EXCLUSION 188 #define IDS_EXCLUDESTEALTH_CHK 189 #define IDS_EXCLUDEBLOCKLIST_CHK 190 #define IDS_UPDATE_INIT 191 #define IDS_UPDATE_INSTALL 192 #define IDS_EXCLUDECUSTOM_CHK 193 #define IDS_ENABLESPECIALGROUP_CHK 194 #define IDS_EXCLUDECLASSIFYALLOW_CHK 195 #define IDS_STATUS_TIMER_DONE 196 #define IDS_ICONSEXTRALARGE 197 #define IDS_STATUS_UNUSED_APPS 198 #define IDS_STATUS_INVALID_APPS 199 #define IDS_STATUS_TIMER_APPS 200 #define IDS_SECUREFILTERS_CHK 201 #define IDS_SECUREFILTERS_HINT 202 #define IDS_USEREFRESHDEVICES_CHK 203 #define IDS_RULE_ALLOW6TO4 204 #define IDS_RECOMMENDED 205 #define IDS_ICONSISTABLEVIEW 206 #define IDS_ACTION_IGNORE 207 #define IDS_ACTION_ALLOW_HINT 208 #define IDS_ACTION_BLOCK_HINT 209 #define IDS_ACTION_LATER_HINT 210 #define IDS_RULE_APPLY_2 211 #define IDS_EDITRULES 212 #define IDS_TAB_APPS 213 #define IDS_TAB_SERVICES 214 #define IDS_TAB_PACKAGES 215 #define IDS_TAB_NETWORK 216 #define IDS_STATE 217 #define IDS_STATUS_FILTERS_ACTIVE 218 #define IDS_STATUS_FILTERS_INACTIVE 219 #define IDS_STATUS_FILTERS_PROCESSING 220 #define IDS_HIGHLIGHT_CONNECTION 221 #define IDS_SHOWINLIST 222 #define IDS_BLOCKLIST_SPY 223 #define IDS_BLOCKLIST_UPDATE 224 #define IDS_BLOCKLIST_EXTRA 225 #define IDS_PORT 226 #define IDS_NOTIFY_TITLE 227 #define IDS_NOTIFY_HEADER 228 #define IDS_DISABLE 229 #define IDS_TITLE_SECURITY 230 #define IDS_LOGVIEWER_HINT 231 #define IDS_NOTIFICATIONONTRAY_CHK 232 #define IDS_NETWORK_CLOSE 233 #define IDS_RULE_BLOCKOUTBOUND 234 #define IDS_RULE_BLOCKINBOUND 235 #define IDS_VIEW_ICON 236 #define IDS_VIEW_DETAILS 237 #define IDS_VIEW_TILE 238 #define IDS_RULE_HINT 239 #define IDS_RULE_APPS_HINT 240 #define IDS_STATUS_FILTERS_ACTIVE_TEMP 241 #define IDS_INSTALL_PERMANENT 242 #define IDS_INSTALL_TEMPORARY 243 #define IDS_ENABLEUILOG_CHK 244 #define IDS_NOTIFICATIONFULLSCREENSILENTMODE_CHK 245 #define IDS_TITLE_TRAY 246 #define IDS_TRAYICONSINGLECLICK_CHK 247 #define IDS_ENABLE_APP_CHK 248 #define IDS_APP_HINT 249 #define IDS_HOST 250 #define IDS_CONFIRMALLOW_CHK 251 #define IDS_QUESTION_ALLOW 252 #define IDS_SHOWSEARCHBAR_CHK 253 #define IDS_LAYER 254 #define IDS_RULE_ALLOWWINDOWSUPDATE 255 #define IDS_ACTION_TERMINATE_HINT 256 #define IDS_PROFILE_TYPE 257 #define IDS_USEAPPMONITOR_CHK 258 #define IDS_DISABLEREMOVAL 259 #define IDS_USEHASHES_CHK 260 #define IDS_COMMENT 261 #define IDS_USEDARKTHEME 262 #define IDS_KEEPUNUSED_CHK 263 #define IDS_UPDATE_NO 264 #define IDS_UPDATE_YES 265 #define IDS_UPDATE_SPEED 266 #define IDS_RULE_FOR_ALL 267 #define IDS_RULE_FOR_APPS 268 #define IDS_PROFILE_TYPE_PLAIN 269 #define IDS_PROFILE_TYPE_COMPRESSED 270 #define IDS_PROFILE_TYPE_ENCRYPTED 271 #define IDS_SESSION_ONLY 272 #define IDS_LIMIT_REACHED 273 #define IDS_INTERNAL_RULE 274 #define IDS_LOADING 275 #define IDS_DIRECTION_REMOTE 276 #define IDS_DIRECTION_LOCAL 277 // RC data #define IDR_PROFILE_INTERNAL 1 // PNG #define IDP_ADD 100 #define IDP_ALLOW 101 #define IDP_BLOCK 102 #define IDP_CROSS 103 #define IDP_NEXT 104 #define IDP_SHIELD_ENABLE 105 #define IDP_SHIELD_DISABLE 106 #define IDP_REFRESH 107 #define IDP_SETTINGS 108 #define IDP_NOTIFICATIONS 109 #define IDP_LOG 110 #define IDP_LOGOPEN 111 #define IDP_LOGCLEAR 112 #define IDP_DONATE 113 #define IDP_LOGUI 114 #define IDP_SEARCH_LIGHT 115 #define IDP_SEARCH_DARK 116 // Icons #define IDI_MAIN 100 #define IDI_ACTIVE IDI_MAIN #define IDI_INACTIVE 101 #endif // __RESOURCE_H__ ================================================ FILE: src/resource.rc ================================================ #include #include #include #include "resource.h" #include "rconfig.h" #include "app.h" LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT // // Accelerator resources // IDA_MAIN ACCELERATORS BEGIN "A", IDM_SELECT_ALL, CONTROL, VIRTKEY, NOINVERT "C", IDM_COPY, CONTROL, VIRTKEY, NOINVERT "E", IDM_EXPLORE, CONTROL, VIRTKEY, NOINVERT "F", IDM_FIND, CONTROL, VIRTKEY, NOINVERT "S", IDM_EXPORT, CONTROL, VIRTKEY, NOINVERT "O", IDM_IMPORT, CONTROL, VIRTKEY, NOINVERT "I", IDM_TRAY_LOGSHOW, CONTROL, VIRTKEY, NOINVERT "T", IDM_PURGE_TIMERS, CONTROL, SHIFT, VIRTKEY, NOINVERT "X", IDM_TRAY_LOGCLEAR, CONTROL, VIRTKEY, NOINVERT "X", IDM_PURGE_UNUSED, CONTROL, SHIFT, VIRTKEY, NOINVERT VK_RETURN, IDM_PROPERTIES, VIRTKEY, NOINVERT VK_DELETE, IDM_DELETE, VIRTKEY, NOINVERT VK_TAB, IDM_TAB_NEXT, VIRTKEY, CONTROL, NOINVERT VK_TAB, IDM_TAB_PREV, VIRTKEY, SHIFT, CONTROL, NOINVERT VK_F1, IDM_ABOUT, VIRTKEY, NOINVERT VK_F2, IDM_SETTINGS, VIRTKEY, NOINVERT VK_F4, IDM_TRAY_SHOW, ALT, VIRTKEY, NOINVERT VK_F5, IDM_REFRESH, VIRTKEY, NOINVERT VK_F11, IDM_ZOOM, VIRTKEY, NOINVERT END // // Menu resources // IDM_MAIN MENU BEGIN POPUP " " BEGIN MENUITEM " ", IDM_SETTINGS MENUITEM SEPARATOR MENUITEM " ", IDM_ADD_FILE MENUITEM SEPARATOR MENUITEM " ", IDM_IMPORT MENUITEM " ", IDM_EXPORT MENUITEM SEPARATOR MENUITEM " ", IDM_EXIT END POPUP " " BEGIN MENUITEM " ", IDM_PURGE_UNUSED MENUITEM " ", IDM_PURGE_TIMERS MENUITEM SEPARATOR MENUITEM " ", IDM_LOGCLEAR MENUITEM SEPARATOR MENUITEM " ", IDM_REFRESH END POPUP " " BEGIN MENUITEM " ", IDM_ALWAYSONTOP_CHK MENUITEM " ", IDM_USEDARKTHEME_CHK MENUITEM " ", IDM_AUTOSIZECOLUMNS_CHK MENUITEM " ", IDM_SHOWFILENAMESONLY_CHK MENUITEM " ", IDM_SHOWSEARCHBAR_CHK MENUITEM SEPARATOR POPUP " " BEGIN MENUITEM " ", IDM_VIEW_DETAILS MENUITEM " ", IDM_VIEW_ICON MENUITEM " ", IDM_VIEW_TILE MENUITEM SEPARATOR MENUITEM " ", IDM_SIZE_SMALL MENUITEM " ", IDM_SIZE_LARGE MENUITEM " ", IDM_SIZE_EXTRALARGE MENUITEM SEPARATOR MENUITEM " ", IDM_ICONSISHIDDEN END POPUP " " BEGIN MENUITEM " ", IDX_LANGUAGE END MENUITEM SEPARATOR MENUITEM " ", IDM_FONT END POPUP " " BEGIN MENUITEM " ", IDM_LOADONSTARTUP_CHK MENUITEM " ", IDM_STARTMINIMIZED_CHK MENUITEM " ", IDM_SKIPUACWARNING_CHK MENUITEM " ", IDM_CHECKUPDATES_CHK MENUITEM SEPARATOR POPUP " " BEGIN MENUITEM " ", IDM_RULE_BLOCKOUTBOUND MENUITEM " ", IDM_RULE_BLOCKINBOUND MENUITEM SEPARATOR MENUITEM " ", IDM_RULE_ALLOWLOOPBACK MENUITEM " ", IDM_RULE_ALLOW6TO4 MENUITEM " ", IDM_RULE_ALLOWWINDOWSUPDATE END POPUP " " BEGIN MENUITEM " ", IDM_PROFILETYPE_PLAIN MENUITEM " ", IDM_PROFILETYPE_COMPRESSED MENUITEM " ", IDM_PROFILETYPE_ENCRYPTED END MENUITEM SEPARATOR MENUITEM " ", IDM_USENETWORKRESOLUTION_CHK MENUITEM " ", IDM_USECERTIFICATES_CHK MENUITEM " ", IDM_KEEPUNUSED_CHK MENUITEM " ", IDM_USEHASHES_CHK MENUITEM " ", IDM_USEAPPMONITOR_CHK END POPUP " " BEGIN POPUP " " BEGIN MENUITEM " ", IDM_BLOCKLIST_SPY_DISABLE MENUITEM " ", IDM_BLOCKLIST_SPY_ALLOW MENUITEM " ", IDM_BLOCKLIST_SPY_BLOCK END POPUP " " BEGIN MENUITEM " ", IDM_BLOCKLIST_UPDATE_DISABLE MENUITEM " ", IDM_BLOCKLIST_UPDATE_ALLOW MENUITEM " ", IDM_BLOCKLIST_UPDATE_BLOCK END POPUP " " BEGIN MENUITEM " ", IDM_BLOCKLIST_EXTRA_DISABLE MENUITEM " ", IDM_BLOCKLIST_EXTRA_ALLOW MENUITEM " ", IDM_BLOCKLIST_EXTRA_BLOCK END END POPUP " " BEGIN MENUITEM " ", IDM_WEBSITE MENUITEM " ", IDM_CHECKUPDATES MENUITEM " ", IDM_ABOUT END END IDM_TRAY MENU BEGIN POPUP "" BEGIN MENUITEM " ", IDM_TRAY_SHOW MENUITEM SEPARATOR MENUITEM " ", IDM_TRAY_START MENUITEM SEPARATOR POPUP " " BEGIN MENUITEM " ", IDM_TRAY_ENABLENOTIFICATIONS_CHK MENUITEM SEPARATOR MENUITEM " ", IDM_TRAY_ENABLENOTIFICATIONSSOUND_CHK MENUITEM " ", IDM_TRAY_NOTIFICATIONFULLSCREENSILENTMODE_CHK MENUITEM " ", IDM_TRAY_NOTIFICATIONONTRAY_CHK END POPUP " " BEGIN MENUITEM " ", IDM_TRAY_ENABLELOG_CHK MENUITEM " ", IDM_TRAY_ENABLEUILOG_CHK MENUITEM SEPARATOR MENUITEM " ", IDM_TRAY_LOGSHOW MENUITEM " ", IDM_TRAY_LOGCLEAR END POPUP " " BEGIN MENUITEM " ", IDM_TRAY_LOGSHOW_ERR MENUITEM " ", IDM_TRAY_LOGCLEAR_ERR END MENUITEM SEPARATOR MENUITEM " ", IDM_TRAY_SETTINGS MENUITEM SEPARATOR MENUITEM " ", IDM_TRAY_WEBSITE MENUITEM " ", IDM_TRAY_ABOUT MENUITEM SEPARATOR MENUITEM " ", IDM_TRAY_EXIT END END // // Dialog resources // IDD_MAIN DIALOGEX 0, 0, 348, 196 STYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | DS_SHELLFONT | DS_MODALFRAME | NOT WS_VISIBLE CAPTION APP_NAME MENU IDM_MAIN FONT 8, "Ms Shell Dlg" BEGIN CONTROL "", IDC_REBAR, REBARCLASSNAME, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CCS_NODIVIDER | CCS_TOP | RBS_VARHEIGHT | RBS_AUTOSIZE, 0, 0, 0, 0 CONTROL "", IDC_TAB, WC_TABCONTROL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_HOTTRACK | TCS_TOOLTIPS | TCS_MULTILINE | TCS_FOCUSONBUTTONDOWN, 0, 0, 348, 158 CONTROL "", IDC_APPS_PROFILE, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_APPS_SERVICE, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_APPS_UWP, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_RULES_BLOCKLIST, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_RULES_SYSTEM, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_RULES_CUSTOM, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_NETWORK, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_LOG, WC_LISTVIEW, WS_CHILD | NOT WS_VISIBLE | WS_TABSTOP | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE, 0, 14, 348, 170 CONTROL "", IDC_STATUSBAR, STATUSCLASSNAME, SBARS_TOOLTIPS, 0, 0, 0, 0 END IDD_NOTIFICATION DIALOGEX 0, 0, 320, 192 STYLE WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | DS_SHELLFONT | NOT WS_VISIBLE EXSTYLE WS_EX_APPWINDOW FONT 8, "Ms Shell Dlg" BEGIN CONTROL "", IDC_HEADER_ID, WC_STATIC, SS_OWNERDRAW, 0, 0, 320, 40 LTEXT "", IDC_FILE_ID, 8, 46, 144, 12, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE LTEXT "", IDC_FILE_TEXT, 168, 46, 144, 12, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE | SS_NOTIFY | SS_RIGHT LTEXT "", IDC_SIGNATURE_ID, 8, 60, 144, 10, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE EDITTEXT IDC_SIGNATURE_TEXT, 168, 60, 144, 12, WS_CHILD | WS_VISIBLE | NOT WS_TABSTOP | NOT WS_BORDER | ES_READONLY | ES_AUTOHSCROLL | ES_RIGHT LTEXT "", IDC_ADDRESS_ID, 8, 74, 144, 10, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE EDITTEXT IDC_ADDRESS_TEXT, 168, 74, 144, 12, WS_CHILD | WS_VISIBLE | NOT WS_TABSTOP | NOT WS_BORDER | ES_READONLY | ES_AUTOHSCROLL | ES_RIGHT LTEXT "", IDC_HOST_ID, 8, 88, 144, 10, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE EDITTEXT IDC_HOST_TEXT, 168, 88, 144, 12, WS_CHILD | WS_VISIBLE | NOT WS_TABSTOP | NOT WS_BORDER | ES_READONLY | ES_AUTOHSCROLL | ES_RIGHT LTEXT "", IDC_PORT_ID, 8, 102, 144, 10, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE EDITTEXT IDC_PORT_TEXT, 168, 102, 144, 12, WS_CHILD | WS_VISIBLE | NOT WS_TABSTOP | NOT WS_BORDER | ES_READONLY | ES_AUTOHSCROLL | ES_RIGHT LTEXT "", IDC_DIRECTION_ID, 8, 116, 144, 10, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE EDITTEXT IDC_DIRECTION_TEXT, 168, 116, 144, 12, WS_CHILD | WS_VISIBLE | NOT WS_TABSTOP | NOT WS_BORDER | ES_READONLY | ES_AUTOHSCROLL | ES_RIGHT LTEXT "", IDC_FILTER_ID, 8, 130, 144, 10, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE EDITTEXT IDC_FILTER_TEXT, 168, 130, 144, 12, WS_CHILD | WS_VISIBLE | NOT WS_TABSTOP | NOT WS_BORDER | ES_READONLY | ES_AUTOHSCROLL | ES_RIGHT LTEXT "", IDC_DATE_ID, 8, 144, 144, 10, WS_CHILD | WS_VISIBLE | SS_ENDELLIPSIS | SS_CENTERIMAGE EDITTEXT IDC_DATE_TEXT, 168, 144, 144, 12, WS_CHILD | WS_VISIBLE | NOT WS_TABSTOP | NOT WS_BORDER | ES_READONLY | ES_AUTOHSCROLL | ES_RIGHT PUSHBUTTON "", IDC_RULES_BTN, 8, 170, 32, 15, WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_SPLITBUTTON | BS_ICON PUSHBUTTON "", IDC_KILLPROCESS_BTN, 44, 170, 26, 15, WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_ICON | BS_PUSHBUTTON PUSHBUTTON "", IDC_ALLOW_BTN, 114, 170, 82, 15, WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_SPLITBUTTON PUSHBUTTON "", IDC_BLOCK_BTN, 200, 170, 82, 15, WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON PUSHBUTTON "", IDC_NEXT_BTN, 286, 170, 26, 15, WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON END IDD_EDITOR DIALOGEX 0, 0, 292, 224 STYLE WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | DS_SHELLFONT | DS_MODALFRAME EXSTYLE WS_EX_APPWINDOW | WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN CONTROL "", IDC_TAB, WC_TABCONTROL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_HOTTRACK | TCS_TOOLTIPS, 0, 0, 292, 196 AUTOCHECKBOX "", IDC_ENABLE_CHK, 8, 202, 166, 14, BS_VCENTER DEFPUSHBUTTON "", IDC_SAVE, 180, 202, 50, 14, WS_TABSTOP PUSHBUTTON "", IDC_CLOSE, 234, 202, 50, 14, WS_TABSTOP END IDD_EDITOR_GENERAL DIALOGEX 0, 0, 292, 210 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_RULE_NAME, 6, 6, 274, 32, WS_GROUP EDITTEXT IDC_RULE_NAME_ID, 12, 18, 262, 12, WS_TABSTOP | ES_AUTOHSCROLL GROUPBOX "", IDC_RULE_COMMENT, 6, 40, 274, 32, WS_GROUP EDITTEXT IDC_RULE_COMMENT_ID, 12, 52, 262, 12, WS_TABSTOP | ES_AUTOHSCROLL GROUPBOX "", IDC_RULE_PROTOCOL, 6, 74, 134, 34, WS_GROUP COMBOBOX IDC_RULE_PROTOCOL_ID, 12, 86, 122, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP GROUPBOX "", IDC_RULE_VERSION, 146, 74, 134, 34, WS_GROUP COMBOBOX IDC_RULE_VERSION_ID, 152, 86, 122, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP GROUPBOX "", IDC_RULE_DIRECTION, 6, 108, 274, 34, WS_GROUP COMBOBOX IDC_RULE_DIRECTION_ID, 12, 120, 262, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP GROUPBOX "", IDC_RULE_ACTION, 6, 142, 274, 34, WS_GROUP COMBOBOX IDC_RULE_ACTION_ID, 12, 154, 262, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP END IDD_EDITOR_RULE DIALOGEX 0, 0, 292, 210 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_RULE_REMOTE, 6, 6, 274, 70, WS_GROUP CONTROL "", IDC_RULE_REMOTE_ID, WC_LISTVIEW, LVS_REPORT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP | WS_VSCROLL | LVS_SHAREIMAGELISTS, 14, 18, 202, 50 PUSHBUTTON "", IDC_RULE_REMOTE_ADD, 222, 18, 50, 14, WS_TABSTOP PUSHBUTTON "", IDC_RULE_REMOTE_EDIT, 222, 34, 50, 14, WS_TABSTOP PUSHBUTTON "", IDC_RULE_REMOTE_DELETE, 222, 50, 50, 14, WS_TABSTOP GROUPBOX "", IDC_RULE_LOCAL, 6, 78, 274, 70, WS_GROUP CONTROL "", IDC_RULE_LOCAL_ID, WC_LISTVIEW, LVS_REPORT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP | WS_VSCROLL | LVS_SHAREIMAGELISTS, 14, 90, 202, 50 PUSHBUTTON "", IDC_RULE_LOCAL_ADD, 222, 90, 50, 14, WS_TABSTOP PUSHBUTTON "", IDC_RULE_LOCAL_EDIT, 222, 106, 50, 14, WS_TABSTOP PUSHBUTTON "", IDC_RULE_LOCAL_DELETE, 222, 122, 50, 14, WS_TABSTOP LTEXT "", IDC_RULE_HINT, 6, 154, 256, 22 END IDD_EDITOR_APPS DIALOGEX 0, 0, 292, 210 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN EDITTEXT IDC_SEARCH, 0, 0, 290, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL CONTROL "", IDC_RULE_APPS_ID, WC_LISTVIEW, LVS_REPORT | WS_BORDER | WS_TABSTOP | WS_VSCROLL | LVS_SHAREIMAGELISTS, 0, 14, 290, 134 LTEXT "", IDC_RULE_APPS_HINT, 6, 154, 256, 22 END IDD_EDITOR_APPINFO DIALOGEX 0, 0, 272, 240 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_APP_NAME, 6, 6, 274, 42, WS_GROUP LTEXT "", IDC_APP_ICON_ID, 16, 18, 32, 32, SS_ICON EDITTEXT IDC_APP_NAME_ID, 48, 18, 224, 12, NOT WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY EDITTEXT IDC_APP_SIGNATURE_ID, 48, 30, 224, 12, NOT WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY GROUPBOX "", IDC_APP_PATH, 6, 50, 274, 34, WS_GROUP EDITTEXT IDC_APP_PATH_ID, 12, 62, 238, 12, WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY PUSHBUTTON ">", IDC_APP_EXPLORE_ID, 254, 62, 20, 12, WS_TABSTOP GROUPBOX "SHA-256:", IDC_APP_HASH, 6, 86, 274, 34, WS_GROUP EDITTEXT IDC_APP_HASH_ID, 12, 98, 238, 12, WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY PUSHBUTTON ">", IDC_APP_HASH_RECHECK_ID, 254, 98, 20, 12, WS_TABSTOP GROUPBOX "", IDC_APP_COMMENT, 6, 122, 274, 34, WS_GROUP EDITTEXT IDC_APP_COMMENT_ID, 12, 136, 262, 12, WS_TABSTOP | ES_AUTOHSCROLL END IDD_EDITOR_APPRULES DIALOGEX 0, 0, 272, 240 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN EDITTEXT IDC_SEARCH, 0, 0, 290, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL CONTROL "", IDC_APP_RULES_ID, WC_LISTVIEW, LVS_REPORT | NOT WS_BORDER | WS_TABSTOP | WS_VSCROLL | LVS_SHAREIMAGELISTS, 0, 14, 290, 134 LTEXT "", IDC_APP_HINT, 6, 154, 256, 22 END IDD_EDITOR_ADDRULE DIALOGEX 0, 0, 270, 148 STYLE WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | DS_SHELLFONT | DS_MODALFRAME FONT 8, "Ms Shell Dlg" BEGIN EDITTEXT IDC_RULE_ID, 8, 8, 254, 24, WS_TABSTOP | ES_AUTOHSCROLL | ES_MULTILINE EDITTEXT IDC_RULE_HINT, 8, 38, 254, 80, WS_VSCROLL | WS_BORDER | NOT WS_TABSTOP | ES_AUTOVSCROLL | ES_READONLY | ES_MULTILINE PUSHBUTTON "", IDC_SAVE, 158, 126, 50, 14, WS_TABSTOP PUSHBUTTON "", IDC_CLOSE, 212, 126, 50, 14, WS_TABSTOP END IDD_SETTINGS_GENERAL DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_GENERAL, 0, 0, 262, 78, WS_GROUP AUTOCHECKBOX "", IDC_ALWAYSONTOP_CHK, 8, 12, 246, 12 AUTOCHECKBOX "", IDC_LOADONSTARTUP_CHK, 8, 24, 246, 12 AUTOCHECKBOX "", IDC_STARTMINIMIZED_CHK, 8, 36, 246, 12 AUTOCHECKBOX "", IDC_SKIPUACWARNING_CHK, 8, 48, 246, 12 AUTOCHECKBOX "", IDC_CHECKUPDATES_CHK, 8, 60, 246, 12 GROUPBOX "", IDC_TITLE_LANGUAGE, 0, 80, 262, 36, WS_GROUP LTEXT "", IDC_LANGUAGE_HINT, 8, 94, 114, 12, SS_CENTERIMAGE COMBOBOX IDC_LANGUAGE, 130, 94, 124, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP END IDD_SETTINGS_INTERFACE DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_CONFIRMATIONS, 0, 0, 262, 64, WS_GROUP AUTOCHECKBOX "", IDC_CONFIRMEXIT_CHK, 8, 12, 246, 12 AUTOCHECKBOX "", IDC_CONFIRMEXITTIMER_CHK, 8, 24, 246, 12 AUTOCHECKBOX "", IDC_CONFIRMLOGCLEAR_CHK, 8, 36, 246, 12 AUTOCHECKBOX "", IDC_CONFIRMALLOW_CHK, 8, 48, 246, 12 GROUPBOX "", IDC_TITLE_TRAY, 0, 66, 262, 32, WS_GROUP AUTOCHECKBOX "", IDC_TRAYICONSINGLECLICK_CHK, 8, 78, 246, 12 END IDD_SETTINGS_HIGHLIGHTING DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_HIGHLIGHTING, 0, 0, 262, 172, WS_GROUP CONTROL "", IDC_COLORS, WC_LISTVIEW, LVS_REPORT | LVS_NOCOLUMNHEADER | LVS_SHAREIMAGELISTS | WS_BORDER | WS_TABSTOP | WS_VSCROLL, 8, 12, 246, 140 LTEXT "", IDC_COLORS_HINT, 8, 156, 246, 12, SS_CENTERIMAGE END IDD_SETTINGS_RULES DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_CONNECTIONS, 0, 0, 262, 64, WS_GROUP AUTOCHECKBOX "", IDC_RULE_BLOCKOUTBOUND, 8, 12, 246, 12 AUTOCHECKBOX "", IDC_RULE_BLOCKINBOUND, 8, 24, 246, 12 AUTOCHECKBOX "", IDC_RULE_ALLOWLOOPBACK, 8, 36, 246, 12 AUTOCHECKBOX "", IDC_RULE_ALLOW6TO4, 8, 48, 246, 12 GROUPBOX "", IDC_TITLE_SECURITY, 0, 66, 262, 40, WS_GROUP AUTOCHECKBOX "", IDC_USESTEALTHMODE_CHK, 8, 78, 246, 12 AUTOCHECKBOX "", IDC_INSTALLBOOTTIMEFILTERS_CHK, 8, 90, 246, 12 GROUPBOX "", IDC_TITLE_ADVANCED, 0, 108, 262, 52, WS_GROUP AUTOCHECKBOX "", IDC_USECERTIFICATES_CHK, 8, 120, 246, 12 AUTOCHECKBOX "", IDC_USEHASHES_CHK, 8, 132, 246, 12 AUTOCHECKBOX "", IDC_USENETWORKRESOLUTION_CHK, 8, 144, 246, 12 END IDD_SETTINGS_BLOCKLIST DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_BLOCKLIST_SPY, 0, 0, 262, 52, WS_GROUP AUTORADIOBUTTON "", IDC_BLOCKLIST_SPY_DISABLE, 8, 12, 246, 12 AUTORADIOBUTTON "", IDC_BLOCKLIST_SPY_ALLOW, 8, 24, 246, 12 AUTORADIOBUTTON "", IDC_BLOCKLIST_SPY_BLOCK, 8, 36, 246, 12 GROUPBOX "", IDC_TITLE_BLOCKLIST_UPDATE, 0, 54, 262, 52, WS_GROUP AUTORADIOBUTTON "", IDC_BLOCKLIST_UPDATE_DISABLE, 8, 66, 246, 12 AUTORADIOBUTTON "", IDC_BLOCKLIST_UPDATE_ALLOW, 8, 78, 246, 12 AUTORADIOBUTTON "", IDC_BLOCKLIST_UPDATE_BLOCK, 8, 90, 246, 12 GROUPBOX "", IDC_TITLE_BLOCKLIST_EXTRA, 0, 108, 262, 52, WS_GROUP AUTORADIOBUTTON "", IDC_BLOCKLIST_EXTRA_DISABLE, 8, 120, 246, 12 AUTORADIOBUTTON "", IDC_BLOCKLIST_EXTRA_ALLOW, 8, 132, 246, 12 AUTORADIOBUTTON "", IDC_BLOCKLIST_EXTRA_BLOCK, 8, 144, 246, 12 CONTROL "", IDC_BLOCKLIST_INFO, WC_LINK, 0, 0, 164, 262, 18 END IDD_SETTINGS_NOTIFICATIONS DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_GENERAL, 0, 0, 262, 86, WS_GROUP AUTOCHECKBOX "", IDC_ENABLENOTIFICATIONS_CHK, 8, 12, 246, 12 AUTOCHECKBOX "", IDC_NOTIFICATIONSOUND_CHK, 8, 24, 246, 12 AUTOCHECKBOX "", IDC_NOTIFICATIONFULLSCREENSILENTMODE_CHK, 8, 36, 246, 12 AUTOCHECKBOX "", IDC_NOTIFICATIONONTRAY_CHK, 8, 48, 246, 12 LTEXT "", IDC_NOTIFICATIONTIMEOUT_HINT, 8, 64, 198, 12, SS_CENTERIMAGE EDITTEXT IDC_NOTIFICATIONTIMEOUT_CTRL, 210, 64, 44, 12, ES_AUTOHSCROLL | ES_NUMBER | ES_MULTILINE CONTROL "", IDC_NOTIFICATIONTIMEOUT, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_AUTOBUDDY | UDS_HOTTRACK | UDS_SETBUDDYINT | UDS_WRAP, 0, 0, 0, 0 END IDD_SETTINGS_LOGGING DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_GENERAL, 0, 0, 262, 66, WS_GROUP AUTOCHECKBOX "", IDC_ENABLELOG_CHK, 8, 12, 246, 12 EDITTEXT IDC_LOGPATH, 8, 26, 218, 12, ES_AUTOHSCROLL | ES_MULTILINE PUSHBUTTON "...", IDC_LOGPATH_BTN, 230, 26, 24, 12, WS_TABSTOP LTEXT "", IDC_LOGSIZELIMIT_HINT, 8, 44, 198, 12, SS_CENTERIMAGE EDITTEXT IDC_LOGSIZELIMIT_CTRL, 210, 44, 44, 12, ES_AUTOHSCROLL | ES_NUMBER | ES_MULTILINE CONTROL "", IDC_LOGSIZELIMIT, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_AUTOBUDDY | UDS_HOTTRACK | UDS_SETBUDDYINT, 0, 0, 0, 0 GROUPBOX "", IDC_TITLE_LOGVIEWER, 0, 68, 262, 34, WS_GROUP EDITTEXT IDC_LOGVIEWER, 8, 80, 218, 12, ES_AUTOHSCROLL | ES_MULTILINE PUSHBUTTON "...", IDC_LOGVIEWER_BTN, 230, 80, 24, 12, WS_TABSTOP GROUPBOX "", IDC_TITLE_INTERFACE, 0, 106, 262, 32, WS_GROUP AUTOCHECKBOX "", IDC_ENABLEUILOG_CHK, 8, 118, 246, 12 END IDD_SETTINGS_EXCLUDE DIALOGEX 0, 0, 262, 172 STYLE WS_CHILD | WS_SYSMENU | WS_TABSTOP | WS_GROUP | DS_SHELLFONT | DS_CONTROL EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" BEGIN GROUPBOX "", IDC_TITLE_NOTIFICATIONS, 0, 0, 262, 42, WS_GROUP AUTOCHECKBOX "", IDC_EXCLUDEBLOCKLIST_CHK, 8, 12, 246, 12 AUTOCHECKBOX "", IDC_EXCLUDECUSTOM_CHK, 8, 24, 246, 12 GROUPBOX "", IDC_TITLE_LOGGING, 0, 46, 262, 42, WS_GROUP AUTOCHECKBOX "", IDC_EXCLUDESTEALTH_CHK, 8, 58, 246, 12 AUTOCHECKBOX "", IDC_EXCLUDECLASSIFYALLOW_CHK, 8, 70, 246, 12 END // // String resources // STRINGTABLE BEGIN IDS_UPDATE_NO "No updates available." IDS_UPDATE_YES "Update available. Download and install now?" IDS_UPDATE_DOWNLOAD "Downloading update..." IDS_UPDATE_DONE "Downloading update finished." IDS_UPDATE_ERROR "Update server connection error." IDS_UPDATE_INIT "Checking for new releases..." IDS_UPDATE_INSTALL "Update available. Do you want to install it now?" IDS_FILE "File" IDS_SETTINGS "Settings" IDS_EXIT "Exit" IDS_EDIT "Edit" IDS_FIND "Search" IDS_FINDNEXT "" IDS_PURGE_UNUSED "Purge unused apps" IDS_PURGE_TIMERS "Purge timers" IDS_REFRESH "Refresh" IDS_VIEW "View" IDS_ICONS "Icons" IDS_ICONSSMALL "Small" IDS_ICONSLARGE "Large" IDS_ICONSISHIDDEN "Do not load icons" IDS_LANGUAGE "Language" IDS_FONT "Font" IDS_HELP "Help" IDS_WEBSITE "Website" IDS_CHECKUPDATES "Check for updates" IDS_DONATE "Give thanks!" IDS_ABOUT "About" IDS_TRAY_SHOW "Show/Hide" IDS_TRAY_START "Enable filters" IDS_TRAY_STOP "Disable filters" IDS_TRAY_RULES "Rules" IDS_TRAY_BLOCKLIST_RULES "Blocklist" IDS_TRAY_SYSTEM_RULES "System rules" IDS_TRAY_USER_RULES "User rules" IDS_TRAY_LOGERR "Errors log" IDS_ADD_FILE "Add app" IDS_ANY "Any" IDS_DISABLENOTIFICATIONS "Disable notifications" IDS_OPENRULESEDITOR "Create rule" IDS_TIMER "Timer" IDS_DISABLETIMER "Disable timer" IDS_EXPLORE "Open containing folder" IDS_COPY "Copy" IDS_SELECT_ALL "Select all" IDS_CHECK "Enable selected" IDS_UNCHECK "Disable selected" IDS_ADD "Add" IDS_EDIT2 "Edit" IDS_DELETE "Delete" IDS_EXPORT "Export" IDS_IMPORT "Import" IDS_RULE_ALLOWLOOPBACK "Allow loopback connections for all" IDS_RULE_ALLOWLOOPBACK_HINT "This allows all loopback traffic." IDS_HIGHLIGHT_INVALID "Invalid (file not found or filter problem)" IDS_HIGHLIGHT_NETWORK "Shared network app" IDS_HIGHLIGHT_PICO "Pico app" IDS_HIGHLIGHT_SIGNED "Signed app" IDS_HIGHLIGHT_SILENT "Disabled notifications" IDS_HIGHLIGHT_SPECIAL "User rules" IDS_HIGHLIGHT_SYSTEM "System app" IDS_GROUP_TIMER "Apps with timer" IDS_EDITOR "Rules editor" IDS_NAME "Name" IDS_DIRECTION "Direction" IDS_PROTOCOL "Protocol" IDS_PORTVERSION "Family (ports only)" IDS_ACTION "Action" IDS_RULE "Rule" IDS_DATE "Date" IDS_FILEPATH "Path" IDS_SIGNATURE "Signature" IDS_ADDRESS "Address" IDS_FILTER "Filter" IDS_NOTES "Notes" IDS_ADDED "Added" IDS_TIMELEFT "Time left" IDS_SIGN_SIGNED "Signed" IDS_SIGN_UNSIGNED "Not signed" IDS_GROUP_ALLOWED "Apps with internet access" IDS_GROUP_SPECIAL_APPS "Apps with user rules" IDS_GROUP_BLOCKED "Apps without internet access" IDS_GROUP_ENABLED "Enabled rules" IDS_GROUP_DISABLED "Disabled rules" IDS_DIRECTION_1 "Outbound" IDS_DIRECTION_2 "Inbound" IDS_DIRECTION_3 "Both" IDS_ACTION_ALLOW "Allow" IDS_ACTION_BLOCK "Block" IDS_ENABLE_CHK "Enable rule" IDS_WIKI "Help" IDS_SAVE "Save" IDS_RESET "Reset" IDS_CLOSE "Close" IDS_SETTINGS_GENERAL "General" IDS_TITLE_GENERAL "General configuration" IDS_TITLE_LANGUAGE "Language" IDS_TITLE_CONFIRMATIONS "Confirmations" IDS_TITLE_INTERFACE "Interface" IDS_TITLE_HIGHLIGHTING "Highlighting" IDS_TITLE_LOGGING "Packets log" IDS_TITLE_NOTIFICATIONS "Notifications" IDS_TITLE_ADVANCED "Advanced" IDS_TITLE_EXCLUDE "Exclude" IDS_ALWAYSONTOP_CHK "Always on top" IDS_LOADONSTARTUP_CHK "Load on system startup" IDS_STARTMINIMIZED_CHK "Start minimized" IDS_SHOWFILENAMESONLY_CHK "Show filenames only" IDS_AUTOSIZECOLUMNS_CHK "Autosize columns" IDS_SKIPUACWARNING_CHK "Skip ""User Account Control"" prompt warning" IDS_CHECKUPDATES_CHK "Periodically check for updates (recommended)" IDS_CHECKUPDATESBETA_CHK "" IDS_LANGUAGE_HINT "Select language:" IDS_USESTEALTHMODE_CHK "Prevent port scanning" IDS_USESTEALTHMODE_HINT "Prevent TCP port scanning by silently dropping inbound TCP RST and UDP port scanning by responding to outbound ICMP with ""Destination Unreachable""." IDS_INSTALLBOOTTIMEFILTERS_CHK "Enable boot-time filters" IDS_INSTALLBOOTTIMEFILTERS_HINT "Prevent data leaks during system startup, even before the ""Base Filtering Engine"" (BFE) service starts." IDS_USECERTIFICATES_CHK "Check apps for digital signatures" IDS_USENETWORKRESOLUTION_CHK "Resolve network addresses" IDS_DISABLEWINDOWSFIREWALL_CHK "Disable Windows Firewall" IDS_ENABLEWINDOWSFIREWALL_CHK "Enable Windows Firewall" IDS_CONFIRMEXIT_CHK "Show confirmation dialog on exit" IDS_CONFIRMEXITTIMER_CHK "Show confirmation dialog on exit when timers are active" IDS_CONFIRMDELETE_CHK "" IDS_CONFIRMLOGCLEAR_CHK "Confirm when clearing the log file" IDS_COLORS_HINT "Double-click an item to change it." IDS_ENABLELOG_CHK "Enable packets logging to a file" IDS_LOGSHOW "Show log" IDS_LOGCLEAR "Clear log" IDS_LOGSIZELIMIT_HINT "Maximum log size: (kB)" IDS_ENABLENOTIFICATIONS_CHK "Enable packets notifications" IDS_NOTIFICATIONSOUND_CHK "Enable notifications sound" IDS_NOTIFICATIONTIMEOUT_HINT "Timeout between similar notifications (sec.):" IDS_EXCLUDESTEALTH_CHK "port scanner connections" IDS_EXCLUDECLASSIFYALLOW_CHK "allowed connections" IDS_EXCLUDEBLOCKLIST_CHK "blocklist" IDS_EXCLUDECUSTOM_CHK "user rules" IDS_NOTIFY_TOOLTIP "Set user rule to allow access to an address and/or port for this application." IDS_QUESTION "Are you sure?" IDS_QUESTION_DELETE "Delete selected item(s)?" IDS_QUESTION_START "This will deny network access to apps as defined by the current configuration. Continue?" IDS_QUESTION_STOP "This will restore network access for all apps that are currently blocked. Continue?" IDS_QUESTION_EXIT "Installed filters will continue to work even if you exit. Continue?" IDS_QUESTION_TIMER "Timer(s) activated. Timers will only work when the application is running. Exit?" IDS_QUESTION_TIMERS "Delete all timers?" IDS_QUESTION_RESET "" IDS_QUESTION_FLAG_CHK "Do not ask again" IDS_STATUS_TOTAL "" IDS_STATUS_UNUSED_APPS "Unused apps" IDS_STATUS_TIMER_APPS "Apps with timer" IDS_STATUS_EMPTY "Empty." IDS_STATUS_ERROR "" IDS_STATUS_SYNTAX_ERROR "Syntax error in rule!" IDS_STATUS_TIMER_DONE "Timer for application has been expired" IDS_ADDRESS_LOCAL "Source" IDS_ADDRESS_REMOTE "Destination" IDS_ICONSEXTRALARGE "Extra large" IDS_SECUREFILTERS_CHK "Enable protection of installed filters" //removed IDS_SECUREFILTERS_HINT "Prevent unauthorized applications from accessing the installed filters." //removed IDS_USEREFRESHDEVICES_CHK "Refresh filters when (storage) devices are connected" IDS_RULE_ALLOW6TO4 "Allow IPv6 redirections (6to4) for all" IDS_RECOMMENDED "recommended" IDS_ICONSISTABLEVIEW "Show as table" IDS_ACTION_ALLOW_HINT "Allow network access forever" IDS_ACTION_BLOCK_HINT "Block network access forever ('til kingdom come)" IDS_ACTION_LATER_HINT "Ignore and ask me later" IDS_RULE_APPLY_2 "Apply ""%s"" for this app" IDS_EDITRULES "Edit rules" IDS_TAB_APPS "Apps" IDS_TAB_SERVICES "Services" IDS_TAB_PACKAGES "UWP apps" IDS_TAB_NETWORK "Connections" IDS_STATE "State" IDS_STATUS_FILTERS_ACTIVE "Filters are enabled." IDS_STATUS_FILTERS_INACTIVE "Filters are disabled!" IDS_STATUS_FILTERS_PROCESSING "Applying filters" IDS_HIGHLIGHT_CONNECTION "Have network connections" IDS_SHOWINLIST "Show in list" IDS_BLOCKLIST_SPY "Microsoft spying and telemetry" IDS_BLOCKLIST_UPDATE "Microsoft update" IDS_BLOCKLIST_EXTRA "Microsoft applications" IDS_PORT "Port" IDS_NOTIFY_TITLE "Network alert" IDS_NOTIFY_HEADER "Network connection was blocked" IDS_DISABLE "Disable" IDS_TITLE_SECURITY "Security" IDS_LOGVIEWER_HINT "Log viewer app" IDS_NOTIFICATIONONTRAY_CHK "Show notification window on tray" IDS_NETWORK_CLOSE "Close connection" IDS_RULE_BLOCKOUTBOUND "Block outbound connections for all" IDS_RULE_BLOCKINBOUND "Block inbound connections for all" IDS_VIEW_ICON "Icons" IDS_VIEW_DETAILS "Details" IDS_VIEW_TILE "Tiles" IDS_RULE_HINT "If you leave fields blank, then rule will be applied for any address and port." IDS_RULE_APPS_HINT "If there is no apps selected, then rule will be applied for all apps." IDS_STATUS_FILTERS_ACTIVE_TEMP "Filters are enabled until reboot." IDS_INSTALL_PERMANENT "Permanent rules. Rules are working until you disable it manually." IDS_INSTALL_TEMPORARY "Temporary rules. Rules are reset after the next reboot." IDS_ENABLEUILOG_CHK "Enable packets logging interface" IDS_NOTIFICATIONFULLSCREENSILENTMODE_CHK "Enable silent-mode when full screen app in foreground" IDS_TITLE_TRAY "Tray icon" IDS_TRAYICONSINGLECLICK_CHK "Single click on tray icon to open" IDS_ENABLE_APP_CHK "Enable network access" IDS_APP_HINT "There is no reason to set any permissive rule for app with already enabled internet access." IDS_HOST "Host" IDS_CONFIRMALLOW_CHK "Confirm when allowing application" IDS_QUESTION_ALLOW "Are you sure you want to enable full internet access for this application?" IDS_SHOWSEARCHBAR_CHK "Show search bar" IDS_LAYER "Layer" IDS_RULE_ALLOWWINDOWSUPDATE "Allow Windows Update" IDS_ACTION_TERMINATE_HINT "Terminate process" IDS_PROFILE_TYPE "Profile type" IDS_USEAPPMONITOR_CHK "Monitor apps changing" IDS_DISABLEREMOVAL "Disable removal" IDS_USEHASHES_CHK "Check apps for sha-256 hash" IDS_COMMENT "Comments" IDS_USEDARKTHEME "Use dark theme" IDS_KEEPUNUSED_CHK "Keep unused apps" IDS_UPDATE_SPEED "Speed" IDS_RULE_FOR_ALL "for all" IDS_RULE_FOR_APPS "for apps" IDS_PROFILE_TYPE_PLAIN "Plain" IDS_PROFILE_TYPE_COMPRESSED "Compressed" IDS_PROFILE_TYPE_ENCRYPTED "Encrypted" IDS_SESSION_ONLY "session only" IDS_LIMIT_REACHED "Limit reached." IDS_INTERNAL_RULE "Internal rule" IDS_LOADING "Loading..." IDS_DIRECTION_REMOTE "Remote" IDS_DIRECTION_LOCAL "Local" END // // RC data // IDR_PROFILE_INTERNAL RCDATA "..\\bin\\profile_internal.bin" // // PNG resources // IDP_ADD PNG "res\\plus.png" IDP_ALLOW PNG "res\\accept_button.png" IDP_BLOCK PNG "res\\delete.png" IDP_CROSS PNG "res\\cross.png" IDP_NEXT PNG "res\\resultset_next.png" IDP_SHIELD_ENABLE PNG "res\\tick_shield.png" IDP_SHIELD_DISABLE PNG "res\\cross_shield.png" IDP_REFRESH PNG "res\\arrow_refresh.png" IDP_SETTINGS PNG "res\\cog_edit.png" IDP_NOTIFICATIONS PNG "res\\error.png" IDP_LOG PNG "res\\note.png" IDP_LOGOPEN PNG "res\\page_white_magnify.png" IDP_LOGCLEAR PNG "res\\page_white_delete.png" IDP_DONATE PNG "res\\paypal_fulllogo.png" IDP_LOGUI PNG "res\\eye.png" IDP_SEARCH_LIGHT PNG "res\\search_light.png" IDP_SEARCH_DARK PNG "res\\search_dark.png" // // Icon resources // IDI_MAIN ICON "res\\100.ico" IDI_INACTIVE ICON "res\\101.ico" // // Manifest resource // 1 RT_MANIFEST "res\\manifest.xml" // // Version Information resources // VS_VERSION_INFO VERSIONINFO FILEVERSION APP_VERSION_RES PRODUCTVERSION APP_VERSION_RES FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN FILEFLAGSMASK 0x00000000 FILEFLAGS VS_FF_PATCHED | VS_FF_PRERELEASE BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "Comments", APP_COMMENT VALUE "CompanyName", APP_AUTHOR VALUE "FileDescription", APP_NAME VALUE "FileVersion", APP_VERSION VALUE "InternalName", APP_NAME_SHORT VALUE "LegalCopyright", APP_COPYRIGHT VALUE "OriginalFilename", APP_NAME_SHORT ".exe" VALUE "ProductName", APP_NAME VALUE "ProductVersion", APP_VERSION END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END ================================================ FILE: src/search.c ================================================ // simplewall // Copyright (c) 2012-2021 dmex // Copyright (c) 2021-2025 Henry++ #include "global.h" VOID _app_search_initialize ( _Inout_ PSEARCH_CONTEXT context ) { RECT rect; HTHEME htheme; LONG cx_border; HRESULT status; GetWindowRect (context->hwnd, &rect); cx_border = _r_dc_getsystemmetrics (SM_CXBORDER, context->dpi_value); // initialize borders context->cx_width = _r_dc_getdpi (20, context->dpi_value); context->cx_border = cx_border; context->dc_brush = GetStockObject (DC_BRUSH); if (IsThemeActive ()) { htheme = _r_dc_openthemedata (context->hwnd, VSCLASS_EDIT, context->dpi_value); if (htheme) { status = GetThemeInt (htheme, 0, 0, TMT_BORDERSIZE, &context->cx_border); if (FAILED (status)) context->cx_border = cx_border; CloseThemeData (htheme); } } } VOID _app_search_create ( _In_ HWND hwnd ) { PSEARCH_CONTEXT context; WCHAR buffer[128]; context = _r_mem_allocate (sizeof (SEARCH_CONTEXT)); context->hwnd = hwnd; context->dpi_value = _r_dc_getwindowdpi (hwnd); _app_search_initialize (context); _r_wnd_setcontext (context->hwnd, SHORT_MAX, context); // Subclass the Edit control window procedure. context->wnd_proc = (WNDPROC)GetWindowLongPtrW (context->hwnd, GWLP_WNDPROC); SetWindowLongPtrW (context->hwnd, GWLP_WNDPROC, (LONG_PTR)&_app_search_subclass_proc); _r_str_printf (buffer, RTL_NUMBER_OF (buffer), L"%s...", _r_locale_getstring (IDS_FIND)); _r_edit_setcuebanner (context->hwnd, 0, buffer); // Initialize the theme parameters. _app_search_themechanged (hwnd, context); } VOID _app_search_initializeimages ( _In_ PSEARCH_CONTEXT context, _In_ HWND hwnd ) { HICON hicon_prev; HBITMAP hbitmap; NTSTATUS status; // initialize icons context->image_width = _r_dc_getsystemmetrics (SM_CXSMICON, context->dpi_value) + _r_dc_getdpi (4, context->dpi_value); context->image_height = _r_dc_getsystemmetrics (SM_CYSMICON, context->dpi_value) + _r_dc_getdpi (4, context->dpi_value); status = _r_res_loadimage ( _r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_SEARCH_LIGHT), &GUID_ContainerFormatPng, context->image_width, context->image_height, &hbitmap ); if (NT_SUCCESS (status)) { hicon_prev = context->hicon_light; context->hicon_light = _r_dc_bitmaptoicon (hbitmap, context->image_width, context->image_height); if (hicon_prev) DestroyIcon (hicon_prev); DeleteObject (hbitmap); } status = _r_res_loadimage ( _r_sys_getimagebase (), L"PNG", MAKEINTRESOURCE (IDP_SEARCH_DARK), &GUID_ContainerFormatPng, context->image_width, context->image_height, &hbitmap ); if (NT_SUCCESS (status)) { hicon_prev = context->hicon_dark; context->hicon_dark = _r_dc_bitmaptoicon (hbitmap, context->image_width, context->image_height); if (hicon_prev) DestroyIcon (hicon_prev); DeleteObject (hbitmap); } } VOID _app_search_themechanged ( _In_ HWND hwnd, _Inout_ PSEARCH_CONTEXT context ) { _app_search_initialize (context); _app_search_initializeimages (context, hwnd); // Reset the client area margins. _r_ctrl_settextmargin (hwnd, 0, 0, 0); // Refresh the non-client area. SetWindowPos (hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); // Force the edit control to update its non-client area. RedrawWindow (hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } VOID _app_search_setvisible ( _In_ HWND hwnd, _In_ HWND hsearch, _In_ LONG dpi_value ) { BOOLEAN is_visible; is_visible = _r_config_getboolean (L"IsShowSearchBar", TRUE, NULL); if (is_visible) { if (!_r_rebar_isbandexists (hwnd, IDC_REBAR, REBAR_SEARCH_ID)) _r_rebar_insertband (hwnd, IDC_REBAR, REBAR_SEARCH_ID, config.hsearchbar, RBBS_VARIABLEHEIGHT | RBBS_NOGRIPPER | RBBS_USECHEVRON, _r_dc_getdpi (180, dpi_value), 20); ShowWindow (hsearch, SW_SHOWNA); _r_wnd_sendmessage (hsearch, 0, WM_SIZE, 0, 0); if (_r_wnd_isvisible (hwnd, FALSE)) SetFocus (hsearch); } else { if (_r_rebar_isbandexists (hwnd, IDC_REBAR, REBAR_SEARCH_ID)) _r_rebar_deleteband (hwnd, IDC_REBAR, REBAR_SEARCH_ID); _r_ctrl_setstring (hsearch, 0, L""); ShowWindow (hsearch, SW_HIDE); } } VOID _app_search_drawwindow ( _Inout_ PSEARCH_CONTEXT context, _In_ LPCRECT wnd_rect ) { if (!_r_theme_isenabled ()) return; SetDCBrushColor (context->hdc, RGB (65, 65, 65)); SelectObject (context->hdc, context->dc_brush); PatBlt (context->hdc, wnd_rect->left, wnd_rect->top, 1, wnd_rect->bottom - wnd_rect->top, PATCOPY); PatBlt (context->hdc, wnd_rect->right - 1, wnd_rect->top, 1, wnd_rect->bottom - wnd_rect->top, PATCOPY); PatBlt (context->hdc, wnd_rect->left, wnd_rect->top, wnd_rect->right - wnd_rect->left, 1, PATCOPY); PatBlt (context->hdc, wnd_rect->left, wnd_rect->bottom - 1, wnd_rect->right - wnd_rect->left, 1, PATCOPY); SetDCBrushColor (context->hdc, RGB (60, 60, 60)); SelectObject (context->hdc, context->dc_brush); PatBlt (context->hdc, wnd_rect->left + 1, wnd_rect->top + 1, 1, wnd_rect->bottom - wnd_rect->top - 2, PATCOPY); PatBlt (context->hdc, wnd_rect->right - 2, wnd_rect->top + 1, 1, wnd_rect->bottom - wnd_rect->top - 2, PATCOPY); PatBlt (context->hdc, wnd_rect->left + 1, wnd_rect->top + 1, wnd_rect->right - wnd_rect->left - 2, 1, PATCOPY); PatBlt (context->hdc, wnd_rect->left + 1, wnd_rect->bottom - 2, wnd_rect->right - wnd_rect->left - 2, 1, PATCOPY); } VOID _app_search_drawbutton ( _Inout_ PSEARCH_CONTEXT context, _In_ HWND hwnd, _In_ LPCRECT wnd_rect ) { RECT btn_rect; _app_search_getbuttonrect (context, wnd_rect, &btn_rect); if (context->is_pushed) { _r_dc_fillrect (context->hdc, &btn_rect, _r_theme_isenabled () ? RGB (99, 99, 99) : RGB (153, 209, 255)); } else if (context->is_hot) { _r_dc_fillrect (context->hdc, &btn_rect, _r_theme_isenabled () ? RGB (78, 78, 78) : RGB (205, 232, 255)); } else { _r_dc_fillrect (context->hdc, &btn_rect, _r_theme_isenabled () ? RGB (60, 60, 60) : GetSysColor (COLOR_WINDOW)); } DrawIconEx ( context->hdc, btn_rect.left + 1, btn_rect.top, _r_theme_isenabled () ? context->hicon_light : context->hicon_dark, context->image_width, context->image_height, 0, NULL, DI_NORMAL ); } VOID _app_search_getbuttonrect ( _In_ PSEARCH_CONTEXT context, _In_ LPCRECT wnd_rect, _Out_ PRECT btn_rect ) { *btn_rect = *wnd_rect; btn_rect->left = ((btn_rect->right - context->cx_width) - context->cx_border - 1); btn_rect->top += context->cx_border; btn_rect->right -= context->cx_border; btn_rect->bottom -= context->cx_border; } BOOLEAN _app_search_isstringfound ( _In_opt_ PR_STRINGREF string, _In_ PR_STRINGREF search_string, _Inout_ PITEM_LISTVIEW_CONTEXT context, _Inout_ PBOOLEAN is_changed ) { if (!string) { if (context->is_hidden) { context->is_hidden = FALSE; *is_changed = TRUE; } return FALSE; } if (_r_str_findstring (string, search_string, TRUE) != SIZE_MAX) { if (context->is_hidden) { context->is_hidden = FALSE; *is_changed = TRUE; } return TRUE; } else { if (!context->is_hidden) { context->is_hidden = TRUE; *is_changed = TRUE; } } return FALSE; } BOOLEAN _app_search_applyfiltercallback ( _In_ HWND hwnd, _In_ INT listview_id, _In_opt_ PR_STRING search_string ) { PITEM_LISTVIEW_CONTEXT context; INT item_count; BOOLEAN is_changed = FALSE; item_count = _r_listview_getitemcount (hwnd, listview_id); if (!item_count) return FALSE; for (INT i = 0; i < item_count; i++) { context = (PITEM_LISTVIEW_CONTEXT)_r_listview_getitemlparam (hwnd, listview_id, i); if (!context) continue; if (_app_search_applyfilteritem (hwnd, listview_id, i, context, search_string)) is_changed = TRUE; } if (is_changed) _app_listview_updateby_id (hwnd, listview_id, PR_UPDATE_NOSETVIEW | PR_UPDATE_FORCE); return is_changed; } BOOLEAN _app_search_applyfilteritem ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _Inout_ PITEM_LISTVIEW_CONTEXT context, _In_opt_ PR_STRING search_string ) { PITEM_APP ptr_app = NULL; PITEM_RULE ptr_rule = NULL; PITEM_NETWORK ptr_network = NULL; PITEM_LOG ptr_log = NULL; PR_STRING string; BOOLEAN is_changed = FALSE; // reset hidden state if (context->is_hidden) { context->is_hidden = FALSE; is_changed = TRUE; } if (!search_string) goto CleanupExit; switch (listview_id) { case IDC_APPS_PROFILE: case IDC_APPS_SERVICE: case IDC_APPS_UWP: case IDC_RULE_APPS_ID: { ptr_app = _app_getappitem ((ULONG)context->id_code); if (!ptr_app) goto CleanupExit; // path if (ptr_app->real_path) { if (_app_search_isstringfound (&ptr_app->real_path->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // comment if (!_r_obj_isstringempty (ptr_app->comment)) { if (_app_search_isstringfound (&ptr_app->comment->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } break; } case IDC_RULES_BLOCKLIST: case IDC_RULES_SYSTEM: case IDC_RULES_CUSTOM: case IDC_APP_RULES_ID: { ptr_rule = _app_getrulebyid (context->id_code); if (!ptr_rule) goto CleanupExit; if (ptr_rule->name) { if (_app_search_isstringfound (&ptr_rule->name->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } if (ptr_rule->rule_remote) { if (_app_search_isstringfound (&ptr_rule->rule_remote->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } if (ptr_rule->rule_local) { if (_app_search_isstringfound (&ptr_rule->rule_local->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } if (ptr_rule->protocol_str) { if (_app_search_isstringfound (&ptr_rule->protocol_str->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // comment if (!_r_obj_isstringempty (ptr_rule->comment)) { if (_app_search_isstringfound (&ptr_rule->comment->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } break; } case IDC_NETWORK: { ptr_network = _app_network_getitem ((ULONG)context->id_code); if (!ptr_network) goto CleanupExit; // path if (ptr_network->path) { if (_app_search_isstringfound (&ptr_network->path->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // local address string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->local_addr_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // local host string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->local_host_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // remote address string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->remote_addr_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // remote host string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_network->remote_host_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // protocol if (ptr_network->protocol_str) { if (_app_search_isstringfound (&ptr_network->protocol_str->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } break; } case IDC_LOG: { ptr_log = _app_getlogitem ((ULONG)context->id_code); if (!ptr_log) goto CleanupExit; // path if (ptr_log->path) { if (_app_search_isstringfound (&ptr_log->path->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // filter name if (ptr_log->filter_name) { if (_app_search_isstringfound (&ptr_log->filter_name->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // layer name if (ptr_log->layer_name) { if (_app_search_isstringfound (&ptr_log->layer_name->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // user name if (ptr_log->username) { if (_app_search_isstringfound (&ptr_log->username->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // local address string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->local_addr_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // local host string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->local_host_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // remote address string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->remote_addr_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // remote host string = _InterlockedCompareExchangePointer ((volatile PVOID_PTR)&ptr_log->remote_host_str, NULL, NULL); if (string) { if (_app_search_isstringfound (&string->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } // protocol if (ptr_log->protocol_str) { if (_app_search_isstringfound (&ptr_log->protocol_str->sr, &search_string->sr, context, &is_changed)) goto CleanupExit; } break; } } CleanupExit: if (ptr_app) _r_obj_dereference (ptr_app); if (ptr_rule) _r_obj_dereference (ptr_rule); if (ptr_network) _r_obj_dereference (ptr_network); if (ptr_log) _r_obj_dereference (ptr_log); if (is_changed) _r_listview_setitem (hwnd, listview_id, item_id, 0, NULL, I_IMAGECALLBACK, I_GROUPIDCALLBACK, I_DEFAULT); return is_changed; } VOID _app_search_applyfilter ( _In_ HWND hwnd, _In_ INT listview_id, _In_opt_ PR_STRING search_string ) { if (!((listview_id >= IDC_APPS_PROFILE && listview_id <= IDC_LOG) || listview_id == IDC_RULE_APPS_ID || listview_id == IDC_APP_RULES_ID)) return; _app_search_applyfiltercallback (hwnd, listview_id, search_string); } VOID _app_search_createbufferedcontext ( _Inout_ PSEARCH_CONTEXT context, _In_ HDC hdc, _In_ LPCRECT buf_rect ) { context->hdc = CreateCompatibleDC (hdc); if (!context->hdc) return; CopyRect (&context->rect, buf_rect); context->hbitmap = CreateCompatibleBitmap (hdc, context->rect.right, context->rect.bottom); context->old_bitmap = SelectObject (context->hdc, context->hbitmap); } VOID _app_search_destroybufferedcontext ( _Inout_ PSEARCH_CONTEXT context ) { if (context->hdc && context->old_bitmap) SelectObject (context->hdc, context->old_bitmap); SAFE_DELETE_OBJECT (context->hbitmap); SAFE_DELETE_DC (context->hdc); } LRESULT CALLBACK _app_search_subclass_proc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ) { PSEARCH_CONTEXT context; WNDPROC wnd_proc; context = _r_wnd_getcontext (hwnd, SHORT_MAX); if (!context) return 0; wnd_proc = context->wnd_proc; switch (msg) { case WM_NCDESTROY: { SAFE_DELETE_ICON (context->hicon_light); SAFE_DELETE_ICON (context->hicon_dark); _r_wnd_removecontext (context->hwnd, SHORT_MAX); SetWindowLongPtrW (hwnd, GWLP_WNDPROC, (LONG_PTR)wnd_proc); _app_search_destroybufferedcontext (context); _r_mem_free (context); break; } case WM_ERASEBKGND: { return TRUE; } case WM_NCCALCSIZE: { LPNCCALCSIZE_PARAMS calc_size; calc_size = (LPNCCALCSIZE_PARAMS)lparam; // Let Windows handle the non-client defaults. CallWindowProcW (wnd_proc, hwnd, msg, wparam, lparam); // Deflate the client area to accommodate the custom button. calc_size->rgrc[0].right -= context->cx_width; return 0; } case WM_NCPAINT: { RECT wnd_rect; RECT buf_rect; HRGN hrgn; HDC hdc; ULONG flags = DCX_WINDOW | DCX_LOCKWINDOWUPDATE | DCX_USESTYLE; hrgn = (HRGN)wparam; if (hrgn == HRGN_FULL) hrgn = NULL; if (hrgn) flags |= DCX_INTERSECTRGN | DCX_NODELETERGN; hdc = GetDCEx (hwnd, hrgn, flags); if (hdc) { // Get the screen coordinates of the window. GetWindowRect (hwnd, &wnd_rect); // Adjust the coordinates (start from 0,0). OffsetRect (&wnd_rect, -wnd_rect.left, -wnd_rect.top); // Exclude client area. ExcludeClipRect ( hdc, wnd_rect.left + context->cx_border + 1, wnd_rect.top + context->cx_border + 1, wnd_rect.right - context->cx_width - (context->cx_border + 1), wnd_rect.bottom - (context->cx_border + 1) ); SetRect (&buf_rect, 0, 0, _r_calc_rectwidth (&wnd_rect), _r_calc_rectheight (&wnd_rect)); if (context->hdc && (context->rect.right < buf_rect.right || context->rect.bottom < buf_rect.bottom)) _app_search_destroybufferedcontext (context); if (!context->hdc) _app_search_createbufferedcontext (context, hdc, &buf_rect); if (!context->hdc) { ReleaseDC (hwnd, hdc); break; } if ((context->is_mouseactive && context->is_hot) || GetFocus () == hwnd) { _r_dc_framerect (context->hdc, &wnd_rect, _r_theme_isenabled () ? WND_HOT_CLR : GetSysColor (COLOR_HOTLIGHT)); InflateRect (&wnd_rect, -1, -1); _r_dc_framerect (context->hdc, &wnd_rect, GetSysColor (COLOR_WINDOW)); } else { _r_dc_framerect (context->hdc, &wnd_rect, GetSysColor (COLOR_WINDOWFRAME)); InflateRect (&wnd_rect, -1, -1); _r_dc_framerect (context->hdc, &wnd_rect, GetSysColor (COLOR_WINDOW)); } _app_search_drawwindow (context, &wnd_rect); _app_search_drawbutton (context, hwnd, &wnd_rect); BitBlt (hdc, buf_rect.left, buf_rect.top, buf_rect.right, buf_rect.bottom, context->hdc, 0, 0, SRCCOPY); ReleaseDC (hwnd, hdc); } return 0; } case WM_NCHITTEST: { RECT wnd_rect; RECT btn_rect; POINT point; // Get the screen coordinates of the mouse. if (!GetCursorPos (&point)) break; // Get the screen coordinates of the window. if (!GetWindowRect (hwnd, &wnd_rect)) break; // Get the position of the inserted button. _app_search_getbuttonrect (context, &wnd_rect, &btn_rect); // Check that the mouse is within the inserted button. if (PtInRect (&btn_rect, point)) return HTBORDER; break; } case WM_NCLBUTTONDOWN: { RECT wnd_rect; RECT btn_rect; POINT point; // Get the screen coordinates of the mouse. if (!GetCursorPos (&point)) break; // Get the screen coordinates of the window. if (!GetWindowRect (hwnd, &wnd_rect)) break; // Get the position of the inserted button. _app_search_getbuttonrect (context, &wnd_rect, &btn_rect); context->is_pushed = PtInRect (&btn_rect, point); SetCapture (hwnd); RedrawWindow (hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); break; } case WM_LBUTTONUP: { RECT wnd_rect; RECT btn_rect; POINT point; // Get the screen coordinates of the mouse. if (!GetCursorPos (&point)) break; // Get the screen coordinates of the window. if (!GetWindowRect (hwnd, &wnd_rect)) break; // Get the position of the inserted button. _app_search_getbuttonrect (context, &wnd_rect, &btn_rect); // Check that the mouse is within the inserted button. if (PtInRect (&btn_rect, point)) { SetFocus (hwnd); _r_ctrl_setstring (hwnd, 0, L""); } if (GetCapture () == hwnd) { context->is_pushed = FALSE; ReleaseCapture (); } RedrawWindow (hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); break; } case WM_CUT: case WM_CLEAR: case WM_PASTE: case WM_UNDO: case WM_KEYUP: case WM_SETTEXT: case WM_KILLFOCUS: { RedrawWindow (hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); break; } case WM_SETTINGCHANGE: case WM_SYSCOLORCHANGE: case WM_THEMECHANGED: case WM_DPICHANGED_AFTERPARENT: { if (msg == WM_DPICHANGED_AFTERPARENT) context->dpi_value = _r_dc_getwindowdpi (context->hwnd); _app_search_themechanged (hwnd, context); break; } case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: { TRACKMOUSEEVENT tme = {0}; RECT wnd_rect; RECT btn_rect; POINT pt; // Get the screen coordinates of the mouse. if (!GetCursorPos (&pt)) break; // Get the screen coordinates of the window. if (!GetWindowRect (hwnd, &wnd_rect)) break; context->is_hot = PtInRect (&wnd_rect, pt); // Get the position of the inserted button. _app_search_getbuttonrect (context, &wnd_rect, &btn_rect); // Check that the mouse is within the inserted button. if (!context->is_mouseactive) { tme.cbSize = sizeof (TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hwnd; tme.dwHoverTime = 0; context->is_mouseactive = TRUE; TrackMouseEvent (&tme); } RedrawWindow (hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); break; } case WM_MOUSELEAVE: case WM_NCMOUSELEAVE: { TRACKMOUSEEVENT tme = {0}; RECT wnd_rect; RECT btn_rect; POINT point; if (context->is_mouseactive) { tme.cbSize = sizeof (TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE | TME_CANCEL; tme.hwndTrack = hwnd; tme.dwHoverTime = 0; TrackMouseEvent (&tme); context->is_mouseactive = FALSE; } // Get the screen coordinates of the mouse. if (!GetCursorPos (&point)) break; // Get the screen coordinates of the window. if (!GetWindowRect (hwnd, &wnd_rect)) break; _app_search_getbuttonrect (context, &wnd_rect, &btn_rect); context->is_hot = PtInRect (&btn_rect, point); RedrawWindow (hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); break; } } return CallWindowProcW (wnd_proc, hwnd, msg, wparam, lparam); } ================================================ FILE: src/search.h ================================================ // simplewall // Copyright (c) 2012-2021 dmex // Copyright (c) 2021-2025 Henry++ #pragma once typedef struct _SEARCH_CONTEXT { RECT rect; HICON hicon_light; HICON hicon_dark; HBITMAP old_bitmap; HBITMAP hbitmap; HBRUSH dc_brush; HWND hwnd; HDC hdc; WNDPROC wnd_proc; union { ULONG flags; struct { ULONG is_hot : 1; ULONG is_pushed : 1; ULONG is_mouseactive : 1; ULONG spare_bits : 29; }; }; LONG dpi_value; LONG image_width; LONG image_height; INT cx_width; INT cx_border; } SEARCH_CONTEXT, *PSEARCH_CONTEXT; VOID _app_search_initialize ( _Inout_ PSEARCH_CONTEXT context ); VOID _app_search_create ( _In_ HWND hwnd ); VOID _app_search_initializeimages ( _In_ PSEARCH_CONTEXT context, _In_ HWND hwnd ); VOID _app_search_themechanged ( _In_ HWND hwnd, _Inout_ PSEARCH_CONTEXT context ); VOID _app_search_setvisible ( _In_ HWND hwnd, _In_ HWND hsearch, _In_ LONG dpi_value ); VOID _app_search_drawwindow ( _Inout_ PSEARCH_CONTEXT context, _In_ LPCRECT wnd_rect ); VOID _app_search_drawbutton ( _Inout_ PSEARCH_CONTEXT context, _In_ HWND hwnd, _In_ LPCRECT wnd_rect ); VOID _app_search_getbuttonrect ( _In_ PSEARCH_CONTEXT context, _In_ LPCRECT wnd_rect, _Out_ PRECT btn_rect ); BOOLEAN _app_search_applyfiltercallback ( _In_ HWND hwnd, _In_ INT listview_id, _In_opt_ PR_STRING search_string ); BOOLEAN _app_search_applyfilteritem ( _In_ HWND hwnd, _In_ INT listview_id, _In_ INT item_id, _Inout_ PITEM_LISTVIEW_CONTEXT context, _In_opt_ PR_STRING search_string ); VOID _app_search_applyfilter ( _In_ HWND hwnd, _In_ INT listview_id, _In_opt_ PR_STRING search_string ); LRESULT CALLBACK _app_search_subclass_proc ( _In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wparam, _In_ LPARAM lparam ); ================================================ FILE: src/security.c ================================================ // simplewall // Copyright (c) 2020-2026 Henry++ #include "global.h" _Ret_maybenull_ PSID _app_quyerybuiltinsid ( _In_ WELL_KNOWN_SID_TYPE sid_type ) { PSID sid; ULONG sid_length; sid_length = SECURITY_MAX_SID_SIZE; sid = _r_mem_allocate (sid_length); if (!CreateWellKnownSid (sid_type, NULL, sid, &sid_length)) { _r_log_v (LOG_LEVEL_ERROR, NULL, L"CreateWellKnownSid", NtLastError (), L"%d", sid_type); _r_mem_free (sid); return NULL; } return sid; } VOID _app_generate_credentials () { // For revoke current user (v3.0.5 Beta and lower) config.builtin_current_sid = _r_sys_getcurrenttoken ()->token_sid; // S-1-5-32-544 (BUILTIN\Administrators) config.builtin_admins_sid = _app_quyerybuiltinsid (WinBuiltinAdministratorsSid); // S-1-5-32-556 (BUILTIN\Network Configuration Operators) config.builtin_netops_sid = _app_quyerybuiltinsid (WinBuiltinNetworkConfigurationOperatorsSid); _r_sys_getservicesid (L"mpssvc", &config.service_mpssvc_sid); _r_sys_getservicesid (L"NlaSvc", &config.service_nlasvc_sid); _r_sys_getservicesid (L"PolicyAgent", &config.service_policyagent_sid); _r_sys_getservicesid (L"RpcSs", &config.service_rpcss_sid); _r_sys_getservicesid (L"WdiServiceHost", &config.service_wdiservicehost_sid); } _Ret_maybenull_ PACL _app_createaccesscontrollist ( _In_ PACL acl, _In_ BOOLEAN is_secure ) { PACCESS_ALLOWED_ACE ace = NULL; EXPLICIT_ACCESS ea[3] = {0}; PACL new_dacl = NULL; ULONG count = 0; BOOLEAN is_currentuserhaverights = FALSE; BOOLEAN is_openforeveryone = FALSE; BOOLEAN is_secured = FALSE; NTSTATUS status; for (WORD ace_index = 0; ace_index < acl->AceCount; ace_index++) { status = RtlGetAce (acl, ace_index, (PVOID_PTR)&ace); if (!NT_SUCCESS (status)) { _r_log_v (LOG_LEVEL_ERROR, NULL, L"RtlGetAce", status, L"%d", ace_index); continue; } if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { // versions of SW before v3.0.5 added Carte blanche for current user // // src: https://github.com/henrypp/simplewall/blob/v.2.3.12/src/main.cpp#L8273 // src: https://github.com/henrypp/simplewall/blob/v.2.3.13/src/main.cpp#L8354 // src: https://github.com/henrypp/simplewall/blob/v.2.4.6/src/main.cpp#L8828 // src: https://github.com/henrypp/simplewall/blob/v.3.0.5/src/wfp.cpp#L109 if (RtlEqualSid (&ace->SidStart, config.builtin_current_sid)) { if ((ace->Mask & (FWPM_GENERIC_EXECUTE | FWPM_GENERIC_WRITE | DELETE | WRITE_DAC | WRITE_OWNER)) != 0) is_currentuserhaverights = TRUE; } // versions of SW before v3.1.1 added Carte blanche for Everyone // // src: https://github.com/henrypp/simplewall/blob/v.2.4.6/src/main.cpp#L8833 // src: https://github.com/henrypp/simplewall/blob/v.3.0.5/src/wfp.cpp#L114 // src: https://github.com/henrypp/simplewall/blob/v.3.1.1/src/wfp.cpp#L150 else if (RtlEqualSid (&ace->SidStart, &SeEveryoneSid)) { if (((ace->Mask & ~(FWPM_ACTRL_CLASSIFY | FWPM_ACTRL_OPEN)) & (FWPM_GENERIC_EXECUTE | FWPM_GENERIC_READ)) != 0) is_openforeveryone = TRUE; } } else if (ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) { if (RtlEqualSid (&ace->SidStart, &SeEveryoneSid)) { if (ace->Mask == (FWPM_ACTRL_WRITE | DELETE | WRITE_DAC | WRITE_OWNER)) is_secured = TRUE; } } } if (is_openforeveryone || is_currentuserhaverights || is_secured != is_secure) { // revoke current user access rights if (is_currentuserhaverights) _app_setexplicitaccess (&ea[count++], REVOKE_ACCESS, 0, NO_INHERITANCE, config.builtin_current_sid); // revoke everyone access rights if (is_openforeveryone) _app_setexplicitaccess (&ea[count++], REVOKE_ACCESS, 0, NO_INHERITANCE, &SeEveryoneSid); // secure filter from deletion _app_setexplicitaccess ( &ea[count++], is_secure ? DENY_ACCESS : GRANT_ACCESS, FWPM_ACTRL_WRITE | DELETE | WRITE_DAC | WRITE_OWNER, is_secure ? CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE : NO_INHERITANCE, &SeEveryoneSid ); status = SetEntriesInAclW (count, ea, acl, &new_dacl); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_ERROR, NULL, L"SetEntriesInAclW", status, NULL); return new_dacl; } return NULL; } VOID _app_setexplicitaccess ( _Out_ PEXPLICIT_ACCESS ea, _In_ ACCESS_MODE mode, _In_ ULONG rights, _In_ ULONG inheritance, _In_opt_ PSID sid ) { RtlSecureZeroMemory (ea, sizeof (EXPLICIT_ACCESS)); ea->grfAccessMode = mode; ea->grfAccessPermissions = rights; ea->grfInheritance = inheritance; BuildTrusteeWithSidW (&(ea->Trustee), sid); } VOID _app_setenginesecurity ( _In_ HANDLE hengine ) { PSECURITY_DESCRIPTOR security_descriptor = NULL; PACCESS_ALLOWED_ACE ace = NULL; EXPLICIT_ACCESS ea[18] = {0}; PSID sid_owner = NULL; PSID sid_group = NULL; PACL new_dacl = NULL; PACL dacl = NULL; PACL sacl = NULL; ULONG count = 0; BOOLEAN is_currentuserhaverights = FALSE; BOOLEAN is_openforeveryone = FALSE; LONG status; status = FwpmEngineGetSecurityInfo0 (hengine, DACL_SECURITY_INFORMATION, &sid_owner, &sid_group, &dacl, &sacl, &security_descriptor); if (status != ERROR_SUCCESS) { _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmEngineGetSecurityInfo0", status, NULL); return; } if (dacl) { for (WORD ace_index = 0; ace_index < dacl->AceCount; ace_index++) { status = RtlGetAce (dacl, ace_index, (PVOID_PTR)&ace); if (!NT_SUCCESS (status)) { _r_log_v (LOG_LEVEL_ERROR, NULL, L"RtlGetAce", status, L"%d", ace_index); continue; } if (ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) continue; // versions of SW before v3.0.5 added Carte blanche for current user // // src: https://github.com/henrypp/simplewall/blob/v.2.3.12/src/main.cpp#L8273 // src: https://github.com/henrypp/simplewall/blob/v.2.3.13/src/main.cpp#L8354 // src: https://github.com/henrypp/simplewall/blob/v.2.4.6/src/main.cpp#L8815 // src: https://github.com/henrypp/simplewall/blob/v.3.0.5/src/wfp.cpp#L96 if (RtlEqualSid (&ace->SidStart, config.builtin_current_sid)) { if (ace->Mask == (FWPM_GENERIC_ALL | DELETE | WRITE_DAC | WRITE_OWNER)) is_currentuserhaverights = TRUE; } // versions of SW before v3.1.1 added Carte blanche for Everyone // // src: https://github.com/henrypp/simplewall/blob/v.2.4.6/src/main.cpp#L8820 // src: https://github.com/henrypp/simplewall/blob/v.3.0.5/src/wfp.cpp#L101 // src: https://github.com/henrypp/simplewall/blob/v.3.1.1/src/wfp.cpp#L137 else if (RtlEqualSid (&ace->SidStart, &SeEveryoneSid)) { if (((ace->Mask & ~(FWPM_ACTRL_CLASSIFY | FWPM_ACTRL_OPEN)) & (FWPM_GENERIC_ALL)) != 0) is_openforeveryone = TRUE; } } if (is_currentuserhaverights || is_openforeveryone) { FwpmEngineSetSecurityInfo0 (hengine, OWNER_SECURITY_INFORMATION, &SeLocalServiceSid, NULL, NULL, NULL); FwpmNetEventsSetSecurityInfo0 (hengine, OWNER_SECURITY_INFORMATION, &SeLocalServiceSid, NULL, NULL, NULL); // revoke current user access rights if (is_currentuserhaverights) { if (config.builtin_current_sid) _app_setexplicitaccess (&ea[count++], REVOKE_ACCESS, 0, NO_INHERITANCE, config.builtin_current_sid); } // reset default engine rights if (is_openforeveryone) { if (config.builtin_admins_sid) { _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, FWPM_GENERIC_ALL | DELETE | WRITE_DAC | WRITE_OWNER, NO_INHERITANCE, config.builtin_admins_sid ); _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, 0x10000000, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, config.builtin_admins_sid ); } if (config.builtin_netops_sid) { _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, FWPM_GENERIC_ALL | DELETE, NO_INHERITANCE, config.builtin_netops_sid ); _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, 0xE0000000, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, config.builtin_netops_sid ); } if (config.service_mpssvc_sid) { _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, FWPM_GENERIC_ALL | DELETE, NO_INHERITANCE, config.service_mpssvc_sid->buffer ); _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, 0xE0000000, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, config.service_mpssvc_sid->buffer ); } if (config.service_nlasvc_sid) { _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, FWPM_GENERIC_READ | FWPM_GENERIC_EXECUTE, NO_INHERITANCE, config.service_nlasvc_sid->buffer ); _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, 0xA0000000, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, config.service_nlasvc_sid->buffer ); } if (config.service_policyagent_sid) { _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, FWPM_GENERIC_ALL | DELETE, NO_INHERITANCE, config.service_policyagent_sid->buffer ); _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, 0xE0000000, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, config.service_policyagent_sid->buffer ); } if (config.service_rpcss_sid) { _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, FWPM_GENERIC_ALL | DELETE, NO_INHERITANCE, config.service_rpcss_sid->buffer ); _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, 0xE0000000, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, config.service_rpcss_sid->buffer ); } if (config.service_wdiservicehost_sid) { _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, FWPM_GENERIC_READ | FWPM_GENERIC_EXECUTE, NO_INHERITANCE, config.service_wdiservicehost_sid->buffer ); _app_setexplicitaccess ( &ea[count++], GRANT_ACCESS, 0xA0000000, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, config.service_wdiservicehost_sid->buffer ); } _app_setexplicitaccess ( &ea[count++], SET_ACCESS, FWPM_ACTRL_CLASSIFY | FWPM_ACTRL_OPEN, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, &SeEveryoneSid ); } status = SetEntriesInAclW (count, ea, dacl, &new_dacl); if (status != ERROR_SUCCESS) { _r_log (LOG_LEVEL_ERROR, NULL, L"SetEntriesInAclW", status, NULL); } else { status = FwpmEngineSetSecurityInfo0 (hengine, DACL_SECURITY_INFORMATION, NULL, NULL, new_dacl, NULL); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmEngineSetSecurityInfo0", status, NULL); status = FwpmNetEventsSetSecurityInfo0 (hengine, DACL_SECURITY_INFORMATION, NULL, NULL, new_dacl, NULL); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmNetEventsSetSecurityInfo0", status, NULL); LocalFree (new_dacl); } } } if (security_descriptor) FwpmFreeMemory0 ((PVOID_PTR)&security_descriptor); } VOID _app_setprovidersecurity ( _In_ HANDLE hengine, _In_ LPCGUID provider_guid, _In_ BOOLEAN is_secure ) { PSECURITY_DESCRIPTOR security_descriptor; PSID sid_owner; PSID sid_group; PACL dacl; PACL sacl; PACL new_dacl; ULONG status; status = FwpmProviderGetSecurityInfoByKey0 ( hengine, provider_guid, DACL_SECURITY_INFORMATION, &sid_owner, &sid_group, &dacl, &sacl, &security_descriptor ); if (status != ERROR_SUCCESS) { _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmProviderGetSecurityInfoByKey0", status, NULL); return; } if (dacl) { new_dacl = _app_createaccesscontrollist (dacl, is_secure); if (new_dacl) { status = FwpmProviderSetSecurityInfoByKey0 ( hengine, provider_guid, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PCSID)config.builtin_admins_sid, NULL, new_dacl, NULL ); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmProviderSetSecurityInfoByKey0", status, NULL); LocalFree (new_dacl); } } if (security_descriptor) FwpmFreeMemory0 ((PVOID_PTR)&security_descriptor); } VOID _app_setsublayersecurity ( _In_ HANDLE hengine, _In_ LPCGUID sublayer_guid, _In_ BOOLEAN is_secure ) { PSECURITY_DESCRIPTOR security_descriptor; PSID sid_owner; PSID sid_group; PACL dacl; PACL sacl; PACL new_dacl; ULONG status; status = FwpmSubLayerGetSecurityInfoByKey0 ( hengine, sublayer_guid, DACL_SECURITY_INFORMATION, &sid_owner, &sid_group, &dacl, &sacl, &security_descriptor ); if (status != ERROR_SUCCESS) { _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmSubLayerGetSecurityInfoByKey0", status, NULL); return; } if (dacl) { new_dacl = _app_createaccesscontrollist (dacl, is_secure); if (new_dacl) { status = FwpmSubLayerSetSecurityInfoByKey0 ( hengine, sublayer_guid, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PCSID)config.builtin_admins_sid, NULL, new_dacl, NULL ); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmSubLayerSetSecurityInfoByKey0", status, NULL); LocalFree (new_dacl); } } if (security_descriptor) FwpmFreeMemory0 ((PVOID_PTR)&security_descriptor); } VOID _app_setcalloutsecurity ( _In_ HANDLE hengine, _In_ LPCGUID callout_guid, _In_ BOOLEAN is_secure ) { PSECURITY_DESCRIPTOR security_descriptor; PSID sid_owner; PSID sid_group; PACL dacl; PACL sacl; PACL new_dacl; ULONG status; status = FwpmCalloutGetSecurityInfoByKey0 ( hengine, callout_guid, DACL_SECURITY_INFORMATION, &sid_owner, &sid_group, &dacl, &sacl, &security_descriptor ); if (status != ERROR_SUCCESS) { if (status != FWP_E_CALLOUT_NOT_FOUND) _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmCalloutGetSecurityInfoByKey0", status, NULL); return; } if (dacl) { new_dacl = _app_createaccesscontrollist (dacl, is_secure); if (new_dacl) { status = FwpmCalloutSetSecurityInfoByKey0 ( hengine, callout_guid, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PCSID)config.builtin_admins_sid, NULL, new_dacl, NULL ); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmCalloutSetSecurityInfoByKey0", status, NULL); LocalFree (new_dacl); } } if (security_descriptor) FwpmFreeMemory0 ((PVOID_PTR)&security_descriptor); } VOID _app_setfiltersecurity ( _In_ HANDLE hengine, _In_ LPCGUID filter_guid, _In_ BOOLEAN is_secure, _In_ LPCWSTR file_name, _In_ ULONG line ) { PSECURITY_DESCRIPTOR security_descriptor; PSID sid_owner; PSID sid_group; PACL dacl; PACL sacl; PACL new_dacl; ULONG status; status = FwpmFilterGetSecurityInfoByKey0 (hengine, filter_guid, DACL_SECURITY_INFORMATION, &sid_owner, &sid_group, &dacl, &sacl, &security_descriptor); if (status == ERROR_SUCCESS) { if (dacl) { new_dacl = _app_createaccesscontrollist (dacl, is_secure); if (new_dacl) { status = FwpmFilterSetSecurityInfoByKey0 (hengine, filter_guid, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, (PCSID)config.builtin_admins_sid, NULL, new_dacl, NULL); if (status != ERROR_SUCCESS) _r_log_v (LOG_LEVEL_ERROR, NULL, L"FwpmFilterSetSecurityInfoByKey0", status, L"#%d", line); LocalFree (new_dacl); } } } else { //if (status != FWP_E_FILTER_NOT_FOUND) _r_log_v (LOG_LEVEL_ERROR, NULL, L"FwpmFilterGetSecurityInfoByKey0", status, L"%s:%d", DBG_ARG_VAR); } if (security_descriptor) FwpmFreeMemory0 ((PVOID_PTR)&security_descriptor); } ================================================ FILE: src/security.h ================================================ // simplewall // Copyright (c) 2020-2026 Henry++ #pragma once _Ret_maybenull_ PSID _app_quyerybuiltinsid ( _In_ WELL_KNOWN_SID_TYPE sid_type ); VOID _app_generate_credentials (); _Ret_maybenull_ PACL _app_createaccesscontrollist ( _In_ PACL acl, _In_ BOOLEAN is_secure ); VOID _app_setexplicitaccess ( _Out_ PEXPLICIT_ACCESS ea, _In_ ACCESS_MODE mode, _In_ ULONG rights, _In_ ULONG inheritance, _In_opt_ PSID sid ); VOID _app_setenginesecurity ( _In_ HANDLE hengine ); VOID _app_setprovidersecurity ( _In_ HANDLE hengine, _In_ LPCGUID provider_guid, _In_ BOOLEAN is_secure ); VOID _app_setsublayersecurity ( _In_ HANDLE hengine, _In_ LPCGUID sublayer_guid, _In_ BOOLEAN is_secure ); VOID _app_setcalloutsecurity ( _In_ HANDLE hengine, _In_ LPCGUID callout_guid, _In_ BOOLEAN is_secure ); VOID _app_setfiltersecurity ( _In_ HANDLE hengine, _In_ LPCGUID filter_guid, _In_ BOOLEAN is_secure, _In_ LPCWSTR file_name, _In_ ULONG line ); ================================================ FILE: src/timer.c ================================================ // simplewall // Copyright (c) 2016-2024 Henry++ #include "global.h" BOOLEAN _app_istimersactive () { PITEM_APP ptr_app = NULL; ULONG_PTR enum_key = 0; _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (_app_istimerset (ptr_app)) { _r_queuedlock_releaseshared (&lock_apps); return TRUE; } } _r_queuedlock_releaseshared (&lock_apps); return FALSE; } BOOLEAN _app_istimerset ( _In_ PITEM_APP ptr_app ) { if (!ptr_app->htimer) return FALSE; return !!IsThreadpoolTimerSet (ptr_app->htimer); } VOID _app_timer_set ( _In_opt_ HWND hwnd, _Inout_ PITEM_APP ptr_app, _In_ LONG64 seconds ) { PTP_TIMER htimer; FILETIME file_time; LARGE_INTEGER li; LONG64 current_time; BOOLEAN is_created = FALSE; NTSTATUS status; if (seconds <= 0) { _app_timer_reset (NULL, ptr_app); } else { current_time = _r_unixtime_now (); _r_unixtime_to_filetime (current_time + seconds, &file_time); _r_calc_filetime2largeinteger (&file_time, &li); if (ptr_app->htimer) { TpSetTimer (ptr_app->htimer, &li, 0, 0); is_created = TRUE; } else { status = TpAllocTimer (&htimer, &_app_timer_callback, ULongToPtr (ptr_app->app_hash), NULL); if (NT_SUCCESS (status)) { TpSetTimer (htimer, &li, 0, 0); ptr_app->htimer = htimer; is_created = TRUE; } } if (is_created) { ptr_app->is_enabled = TRUE; ptr_app->timer = current_time + seconds; } else { _app_timer_reset (NULL, ptr_app); } } if (hwnd) _app_listview_updateitemby_param (hwnd, ptr_app->app_hash, TRUE); } VOID _app_timer_reset ( _In_opt_ HWND hwnd, _Inout_ PITEM_APP ptr_app ) { ptr_app->is_enabled = FALSE; ptr_app->is_haveerrors = FALSE; ptr_app->timer = 0; if (_app_istimerset (ptr_app)) _app_timer_remove (ptr_app); if (hwnd) _app_listview_updateitemby_param (hwnd, ptr_app->app_hash, TRUE); } VOID _app_timer_remove ( _Inout_ PITEM_APP ptr_app ) { PTP_TIMER current_timer; current_timer = ptr_app->htimer; ptr_app->htimer = NULL; if (current_timer) TpReleaseTimer (current_timer); } VOID CALLBACK _app_timer_callback ( _Inout_ PTP_CALLBACK_INSTANCE instance, _Inout_opt_ PVOID context, _Inout_ PTP_TIMER timer ) { HANDLE hengine; HWND hwnd; PITEM_APP ptr_app; PR_LIST rules; PR_STRING string; WCHAR buffer[256]; ULONG icon_id; HRESULT status; ptr_app = _app_getappitem (PtrToUlong (context)); if (!ptr_app) return; status = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); hwnd = _r_app_gethwnd (); _app_timer_reset (hwnd, ptr_app); hengine = _wfp_getenginehandle (); rules = _r_obj_createlist (2, NULL); _r_obj_addlistitem (rules, ptr_app, NULL); _wfp_create3filters (hengine, rules, DBG_ARG, FALSE); _app_listview_updateby_id (hwnd, ptr_app->type, PR_UPDATE_TYPE | PR_UPDATE_FORCE); _r_obj_dereference (ptr_app); _r_obj_dereference (rules); _app_profile_save (hwnd); if (_r_config_getboolean (L"IsNotificationsTimer", TRUE, NULL)) { icon_id = NIIF_INFO; if (!_r_config_getboolean (L"IsNotificationsSound", TRUE, NULL)) icon_id |= NIIF_NOSOUND; string = _app_getappdisplayname (ptr_app, TRUE); _r_str_printf ( buffer, RTL_NUMBER_OF (buffer), L"%s - %s", _r_app_getname (), _r_obj_getstringorempty (string) ); _r_tray_popup (hwnd, &GUID_TrayIcon, icon_id, buffer, _r_locale_getstring (IDS_STATUS_TIMER_DONE)); if (string) _r_obj_dereference (string); } if (status == S_OK || status == S_FALSE) CoUninitialize (); } ================================================ FILE: src/timer.h ================================================ // simplewall // Copyright (c) 2016-2024 Henry++ #pragma once BOOLEAN _app_istimersactive (); BOOLEAN _app_istimerset ( _In_ PITEM_APP ptr_app ); VOID _app_timer_set ( _In_opt_ HWND hwnd, _Inout_ PITEM_APP ptr_app, _In_ LONG64 seconds ); VOID _app_timer_reset ( _In_opt_ HWND hwnd, _Inout_ PITEM_APP ptr_app ); VOID _app_timer_remove ( _Inout_ PITEM_APP ptr_app ); VOID CALLBACK _app_timer_callback ( _Inout_ PTP_CALLBACK_INSTANCE instance, _Inout_opt_ PVOID context, _Inout_ PTP_TIMER timer ); ================================================ FILE: src/uwp.cpp ================================================ // simplewall // Copyright (c) 2022-2024 Henry++ #include "routine.h" #include #include #include #include #include #include #include "uwp.h" _Success_ (return) BOOLEAN _app_uwp_loadpackageinfo ( _In_ PR_STRING package_name, _Inout_ PR_STRING_PTR name_ptr, _Inout_ PR_STRING_PTR path_ptr ) { winrt::Windows::ApplicationModel::Package package = NULL; winrt::Windows::ApplicationModel::PackageStatus status = 0; winrt::hstring display_name; winrt::hstring path; package = winrt::Windows::Management::Deployment::PackageManager{}.FindPackage (package_name->buffer); if (!package) return FALSE; if (_r_sys_isosversiongreaterorequal (WINDOWS_10)) { status = package.Status (); if (status.Disabled () || status.NotAvailable ()) return FALSE; } display_name = package.DisplayName (); path = package.InstalledLocation ().Path (); if (display_name.empty ()) display_name = package.Id ().Name (); if (display_name.empty ()) { *name_ptr = _r_obj_createstring2 (&package_name->sr); } else { if (display_name == L"1527c705-839a-4832-9118-54d4Bd6a0c89") display_name = L"File Picker"; // HACK!!! *name_ptr = _r_obj_createstring_ex (display_name.c_str (), display_name.size () * sizeof (WCHAR)); } if (!path.empty ()) *path_ptr = _r_obj_createstring_ex (path.c_str (), path.size () * sizeof (WCHAR)); return TRUE; } _Success_ (return) BOOLEAN _app_uwp_getpackageinfo ( _In_ PR_STRING package_name, _Out_ PR_STRING_PTR name_ptr, _Out_ PR_STRING_PTR path_ptr ) { BOOLEAN status = FALSE; *name_ptr = NULL; *path_ptr = NULL; __try { status = _app_uwp_loadpackageinfo (package_name, name_ptr, path_ptr); } __except (EXCEPTION_EXECUTE_HANDLER) { *name_ptr = _r_obj_createstring2 (&package_name->sr); return TRUE; } return status; } ================================================ FILE: src/uwp.h ================================================ // simplewall // Copyright (c) 2022-2024 Henry++ #pragma once #ifdef __cplusplus extern "C" { #endif _Success_ (return) BOOLEAN _app_uwp_loadpackageinfo ( _In_ PR_STRING package_name, _Inout_ PR_STRING_PTR name_ptr, _Inout_ PR_STRING_PTR path_ptr ); _Success_ (return) BOOLEAN _app_uwp_getpackageinfo ( _In_ PR_STRING package_name, _Out_ PR_STRING_PTR name_ptr, _Out_ PR_STRING_PTR path_ptr ); #ifdef __cplusplus } #endif ================================================ FILE: src/wfp.c ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #include "global.h" BOOLEAN _wfp_isfiltersapplying () { return _r_queuedlock_islocked (&lock_apply) || _r_queuedlock_islocked (&lock_transaction); } ENUM_INSTALL_TYPE _wfp_isproviderinstalled ( _In_ HANDLE engine_handle ) { FWPM_PROVIDER0 *ptr_provider; ENUM_INSTALL_TYPE install_type; ULONG status; status = FwpmProviderGetByKey0 (engine_handle, &GUID_WfpProvider, &ptr_provider); if (status != ERROR_SUCCESS || !ptr_provider) return INSTALL_DISABLED; if ((ptr_provider->flags & FWPM_PROVIDER_FLAG_DISABLED) == FWPM_PROVIDER_FLAG_DISABLED) { install_type = INSTALL_DISABLED; } else if ((ptr_provider->flags & FWPM_PROVIDER_FLAG_PERSISTENT) == FWPM_PROVIDER_FLAG_PERSISTENT) { install_type = INSTALL_ENABLED; } else { install_type = INSTALL_ENABLED_TEMPORARY; } FwpmFreeMemory0 ((PVOID_PTR)&ptr_provider); return install_type; } ENUM_INSTALL_TYPE _wfp_issublayerinstalled ( _In_ HANDLE engine_handle ) { FWPM_SUBLAYER0 *ptr_sublayer; ENUM_INSTALL_TYPE install_type; ULONG status; status = FwpmSubLayerGetByKey0 (engine_handle, &GUID_WfpSublayer, &ptr_sublayer); if (status != ERROR_SUCCESS || !ptr_sublayer) return INSTALL_DISABLED; if ((ptr_sublayer->flags & FWPM_SUBLAYER_FLAG_PERSISTENT) == FWPM_SUBLAYER_FLAG_PERSISTENT) { install_type = INSTALL_ENABLED; } else { install_type = INSTALL_ENABLED_TEMPORARY; } FwpmFreeMemory0 ((PVOID_PTR)&ptr_sublayer); return install_type; } BOOLEAN _wfp_isfiltersinstalled () { ENUM_INSTALL_TYPE install_type; install_type = _wfp_getinstalltype (); return (install_type != INSTALL_DISABLED); } HANDLE _wfp_getenginehandle () { static R_INITONCE init_once = PR_INITONCE_INIT; static HANDLE engine_handle = NULL; FWPM_SESSION0 session; ULONG attempts = 6; ULONG status; if (_r_initonce_begin (&init_once)) { _r_math_generateguid (&config.session_key); do { RtlZeroMemory (&session, sizeof (FWPM_SESSION0)); session.displayData.name = _r_app_getname (); session.displayData.description = _r_app_getname (); session.sessionKey = config.session_key; session.txnWaitTimeoutInMSec = TRANSACTION_TIMEOUT; status = FwpmEngineOpen0 (NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine_handle); if (status == ERROR_SUCCESS) { break; } else { if (status == EPT_S_NOT_REGISTERED) { // The error say that BFE service is not in the running state, so we wait. if (attempts) { _r_sys_sleep (500); attempts -= 1; continue; } } _r_show_errormessage (_r_app_gethwnd (), L"WFP engine initialization failed! Try again later.", status, NULL, ET_WINDOWS); _r_log (LOG_LEVEL_CRITICAL, NULL, L"FwpmEngineOpen0", status, NULL); NtTerminateProcess (NtCurrentProcess (), status); break; } } while (--attempts); _r_initonce_end (&init_once); } return engine_handle; } ENUM_INSTALL_TYPE _wfp_getinstalltype () { return _wfp_isproviderinstalled (_wfp_getenginehandle ()); } PR_STRING _wfp_getlayername ( _In_ LPGUID layer_guid ) { LPCGUID layer_guids[] = { &FWPM_LAYER_ALE_AUTH_CONNECT_V4, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, &FWPM_LAYER_ALE_CONNECT_REDIRECT_V4, &FWPM_LAYER_ALE_CONNECT_REDIRECT_V6, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, &FWPM_LAYER_ALE_AUTH_LISTEN_V4, &FWPM_LAYER_ALE_AUTH_LISTEN_V6, &FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4, &FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4, &FWPM_LAYER_OUTBOUND_TRANSPORT_V6, &FWPM_LAYER_INBOUND_TRANSPORT_V4, &FWPM_LAYER_INBOUND_TRANSPORT_V6, &FWPM_LAYER_IPFORWARD_V4, &FWPM_LAYER_IPFORWARD_V6, &FWPM_LAYER_INBOUND_ICMP_ERROR_V4, &FWPM_LAYER_INBOUND_ICMP_ERROR_V6, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6, }; R_STRINGREF layer_names[] = { PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_AUTH_CONNECT_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_AUTH_CONNECT_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_CONNECT_REDIRECT_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_CONNECT_REDIRECT_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_AUTH_LISTEN_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_AUTH_LISTEN_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_OUTBOUND_TRANSPORT_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_OUTBOUND_TRANSPORT_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_INBOUND_TRANSPORT_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_INBOUND_TRANSPORT_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_IPFORWARD_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_IPFORWARD_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_INBOUND_ICMP_ERROR_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_INBOUND_ICMP_ERROR_V6"), PR_STRINGREF_INIT (L"FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4"), PR_STRINGREF_INIT (L"FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6"), }; C_ASSERT (RTL_NUMBER_OF (layer_guids) == RTL_NUMBER_OF (layer_names)); PR_STRING string; for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (layer_guids); i++) { if (IsEqualGUID (layer_guid, layer_guids[i])) return _r_obj_createstring2 (&layer_names[i]); } _r_str_fromguid (layer_guid, TRUE, &string); return string; } BOOLEAN _wfp_initialize ( _In_opt_ HWND hwnd, _In_ HANDLE engine_handle ) { FWPM_PROVIDER0 provider; FWPM_SUBLAYER0 sublayer; FWP_VALUE0* fwp_query = NULL; FWP_VALUE0 val; BOOLEAN is_success = TRUE; // already initialized BOOLEAN is_providerexist; BOOLEAN is_sublayerexist; BOOLEAN is_intransact; LONG status; _r_queuedlock_acquireshared (&lock_transaction); _app_setenginesecurity (engine_handle); // install engine provider and it's sublayer is_providerexist = (_wfp_isproviderinstalled (engine_handle) != INSTALL_DISABLED); is_sublayerexist = (_wfp_issublayerinstalled (engine_handle) != INSTALL_DISABLED); if (!is_providerexist || !is_sublayerexist) { is_intransact = _wfp_transact_start (engine_handle, DBG_ARG); if (!is_providerexist) { // create provider RtlZeroMemory (&provider, sizeof (FWPM_PROVIDER0)); provider.displayData.name = _r_app_getname (); provider.displayData.description = _r_app_getname (); provider.providerKey = GUID_WfpProvider; if (!config.is_filterstemporary) provider.flags = FWPM_PROVIDER_FLAG_PERSISTENT; status = FwpmProviderAdd0 (engine_handle, &provider, NULL); if (status != ERROR_SUCCESS && status != FWP_E_ALREADY_EXISTS) { if (is_intransact) { FwpmTransactionAbort0 (engine_handle); is_intransact = FALSE; } _r_log (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmProviderAdd0", status, NULL); is_success = FALSE; goto CleanupExit; } else { is_providerexist = TRUE; } } if (!is_sublayerexist) { // create sublayer RtlZeroMemory (&sublayer, sizeof (FWPM_SUBLAYER0)); sublayer.displayData.name = _r_app_getname (); sublayer.displayData.description = _r_app_getname (); sublayer.providerKey = (LPGUID)&GUID_WfpProvider; sublayer.subLayerKey = GUID_WfpSublayer; // highest weight for UINT16 sublayer.weight = (UINT16)_r_config_getlong (L"SublayerWeight", FW_SUBLAYER_WEIGHT, NULL); if (!config.is_filterstemporary) sublayer.flags = FWPM_SUBLAYER_FLAG_PERSISTENT; status = FwpmSubLayerAdd0 (engine_handle, &sublayer, NULL); if (status != ERROR_SUCCESS && status != FWP_E_ALREADY_EXISTS) { if (is_intransact) { FwpmTransactionAbort0 (engine_handle); is_intransact = FALSE; } _r_log (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmSubLayerAdd0", status, NULL); is_success = FALSE; goto CleanupExit; } else { is_sublayerexist = TRUE; } } if (is_intransact) { if (!_wfp_transact_commit (engine_handle, DBG_ARG)) is_success = FALSE; } } // set provider security information _app_setprovidersecurity (engine_handle, &GUID_WfpProvider, TRUE); // set sublayer security information _app_setsublayersecurity (engine_handle, &GUID_WfpSublayer, TRUE); // dropped packets logging (win7+) if (!config.is_neteventset) { // query net events state config.is_neteventenabled = FALSE; status = FwpmEngineGetOption0 (engine_handle, FWPM_ENGINE_COLLECT_NET_EVENTS, &fwp_query); if (status == ERROR_SUCCESS && fwp_query) { config.is_neteventenabled = (fwp_query->type == FWP_UINT32) && (!!fwp_query->uint32); FwpmFreeMemory0 ((PVOID_PTR)&fwp_query); } // enable net events (if it is disabled) if (config.is_neteventenabled) { config.is_neteventset = TRUE; } else { RtlZeroMemory (&val, sizeof (FWP_VALUE0)); val.type = FWP_UINT32; val.uint32 = TRUE; status = FwpmEngineSetOption0 (engine_handle, FWPM_ENGINE_COLLECT_NET_EVENTS, &val); if (status != ERROR_SUCCESS) { _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmEngineSetOption0", status, L"FWPM_ENGINE_COLLECT_NET_EVENTS"); } else { config.is_neteventset = TRUE; } } if (config.is_neteventset) { _wfp_logsetoption (engine_handle); _wfp_logsubscribe (hwnd, engine_handle); } } // packet queuing (win8+) if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { if (_r_config_getboolean (L"IsPacketQueuingEnabled", TRUE, NULL)) { // Enables inbound or forward packet queuing independently. // when enabled, the system is able to evenly distribute cpu load // to multiple cpus for site-to-site ipsec tunnel scenarios. RtlZeroMemory (&val, sizeof (FWP_VALUE0)); val.type = FWP_UINT32; val.uint32 = FWPM_ENGINE_OPTION_PACKET_QUEUE_INBOUND | FWPM_ENGINE_OPTION_PACKET_QUEUE_FORWARD; status = FwpmEngineSetOption0 (engine_handle, FWPM_ENGINE_PACKET_QUEUING, &val); if (status != ERROR_SUCCESS) _r_log (LOG_LEVEL_WARNING, NULL, L"FwpmEngineSetOption0", status, L"FWPM_ENGINE_PACKET_QUEUING"); } } CleanupExit: _r_queuedlock_releaseshared (&lock_transaction); return is_success; } VOID _wfp_uninitialize ( _In_ HANDLE engine_handle, _In_ BOOLEAN is_full ) { PR_ARRAY callouts; PR_STRING string; LPGUID guid; FWP_VALUE0 val; BOOLEAN is_intransact; ULONG status; _r_queuedlock_acquireshared (&lock_transaction); // dropped packets logging (win7+) if (config.is_neteventset) _wfp_logunsubscribe (engine_handle); if (!config.is_neteventenabled && config.is_neteventset) { RtlZeroMemory (&val, sizeof (FWP_VALUE0)); val.type = FWP_UINT32; val.uint32 = FALSE; status = FwpmEngineSetOption0 (engine_handle, FWPM_ENGINE_COLLECT_NET_EVENTS, &val); if (status == ERROR_SUCCESS) config.is_neteventset = FALSE; } if (is_full) { _app_setprovidersecurity (engine_handle, &GUID_WfpProvider, FALSE); _app_setsublayersecurity (engine_handle, &GUID_WfpSublayer, FALSE); status = _wfp_dumpcallouts (engine_handle, &GUID_WfpProvider, &callouts); if (status == ERROR_SUCCESS && callouts) { for (ULONG_PTR i = 0; i < _r_obj_getarraysize (callouts); i++) { guid = (LPGUID)_r_obj_getarrayitem (callouts, i); if (guid) _app_setcalloutsecurity (engine_handle, guid, FALSE); } } is_intransact = _wfp_transact_start (engine_handle, DBG_ARG); // destroy callouts (deprecated) if (callouts) { for (ULONG_PTR i = 0; i < _r_obj_getarraysize (callouts); i++) { guid = (LPGUID)_r_obj_getarrayitem (callouts, i); if (!guid) continue; status = FwpmCalloutDeleteByKey0 (engine_handle, guid); if (status != ERROR_SUCCESS) { _r_str_fromguid (guid, TRUE, &string); _r_log (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmCalloutDeleteByKey0", status, _r_obj_getstring (string)); if (string) _r_obj_dereference (string); } } } // destroy sublayer status = FwpmSubLayerDeleteByKey0 (engine_handle, &GUID_WfpSublayer); if (status != ERROR_SUCCESS && status != FWP_E_SUBLAYER_NOT_FOUND) _r_log (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmSubLayerDeleteByKey0", status, NULL); // destroy provider status = FwpmProviderDeleteByKey0 (engine_handle, &GUID_WfpProvider); if (status != ERROR_SUCCESS && status != FWP_E_PROVIDER_NOT_FOUND) _r_log (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmProviderDeleteByKey0", status, NULL); if (is_intransact) _wfp_transact_commit (engine_handle, DBG_ARG); if (callouts) _r_obj_dereference (callouts); } _r_queuedlock_releaseshared (&lock_transaction); } VOID _wfp_installfilters ( _In_ HANDLE engine_handle ) { // dump all filters into array PR_ARRAY guids; PR_LIST rules; LPGUID guid; PITEM_APP ptr_app = NULL; PITEM_RULE ptr_rule; ULONG_PTR enum_key = 0; BOOLEAN is_intransact; ULONG status; // set security information _app_setprovidersecurity (engine_handle, &GUID_WfpProvider, FALSE); _app_setsublayersecurity (engine_handle, &GUID_WfpSublayer, FALSE); _wfp_clearfilter_ids (); _r_queuedlock_acquireshared (&lock_transaction); status = _wfp_dumpfilters (engine_handle, &GUID_WfpProvider, &guids); // restore filters security if (status == ERROR_SUCCESS) { for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _app_setfiltersecurity (engine_handle, guid, FALSE, DBG_ARG); } } is_intransact = _wfp_transact_start (engine_handle, DBG_ARG); // destroy all filters if (status == ERROR_SUCCESS) { for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _wfp_deletefilter (engine_handle, guid); } _r_obj_dereference (guids); } rules = _r_obj_createlist (10, &_r_obj_dereference); // apply apps rules _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { if (ptr_app->is_enabled) _r_obj_addlistitem (rules, _r_obj_reference (ptr_app), NULL); } _r_queuedlock_releaseshared (&lock_apps); if (!_r_obj_isempty2 (rules)) { _wfp_create3filters (engine_handle, rules, DBG_ARG, is_intransact); _r_obj_clearlist (rules); } // apply blocklist/system/user rules _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (ptr_rule) { if (ptr_rule->is_enabled) _r_obj_addlistitem (rules, _r_obj_reference (ptr_rule), NULL); } } _r_queuedlock_releaseshared (&lock_rules); if (!_r_obj_isempty2 (rules)) { _wfp_create4filters (engine_handle, rules, DBG_ARG, is_intransact); _r_obj_clearlist (rules); } // apply internal rules _wfp_create2filters (engine_handle, DBG_ARG, is_intransact); if (is_intransact) _wfp_transact_commit (engine_handle, DBG_ARG); // secure filters status = _wfp_dumpfilters (engine_handle, &GUID_WfpProvider, &guids); if (status == ERROR_SUCCESS) { for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _app_setfiltersecurity (engine_handle, guid, TRUE, DBG_ARG); } _r_obj_dereference (guids); } _app_setprovidersecurity (engine_handle, &GUID_WfpProvider, TRUE); _app_setsublayersecurity (engine_handle, &GUID_WfpSublayer, TRUE); _r_queuedlock_releaseshared (&lock_transaction); _r_obj_dereference (rules); } BOOLEAN _wfp_transact_start ( _In_ HANDLE engine_handle, _In_ LPCWSTR file_name, _In_ ULONG line ) { ULONG status; status = FwpmTransactionBegin0 (engine_handle, 0); if (status == FWP_E_TXN_IN_PROGRESS) return FALSE; if (status != ERROR_SUCCESS) { _r_log_v (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmTransactionBegin0", status, L"%s:%d", DBG_ARG_VAR); return FALSE; } return TRUE; } BOOLEAN _wfp_transact_commit ( _In_ HANDLE engine_handle, _In_ LPCWSTR file_name, _In_ ULONG line ) { ULONG status; status = FwpmTransactionCommit0 (engine_handle); if (status != ERROR_SUCCESS) { _r_log_v (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmTransactionCommit0", status, L"%s:%d", DBG_ARG_VAR); FwpmTransactionAbort0 (engine_handle); return FALSE; } return TRUE; } BOOLEAN _wfp_deletefilter ( _In_ HANDLE engine_handle, _In_ LPGUID filter_id ) { PR_STRING string; ULONG status; status = FwpmFilterDeleteByKey0 (engine_handle, filter_id); if (status != ERROR_SUCCESS && status != FWP_E_FILTER_NOT_FOUND) { _r_str_fromguid (filter_id, TRUE, &string); _r_log (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmFilterDeleteByKey0", status, _r_obj_getstringordefault (string, L"")); if (string) _r_obj_dereference (string); return FALSE; } return TRUE; } FORCEINLINE LPCWSTR _wfp_filtertypetostring ( _In_ ENUM_TYPE_DATA filter_type ) { switch (filter_type) { case DATA_APP_REGULAR: case DATA_APP_DEVICE: case DATA_APP_NETWORK: case DATA_APP_PICO: case DATA_APP_SERVICE: case DATA_APP_UWP: { return L"App"; } case DATA_RULE_BLOCKLIST: { return L"Blocklist"; } case DATA_RULE_SYSTEM: { return L"System rule"; } case DATA_RULE_SYSTEM_USER: case DATA_RULE_USER: { return L"User rule"; } case DATA_FILTER_GENERAL: { return L"Internal"; } default: { FALLTHROUGH; } } return NULL; } ULONG _wfp_createcallout ( _In_ HANDLE engine_handle, _In_ LPCGUID layer_key, _In_ LPCGUID callout_key ) { FWPM_CALLOUT0 callout = {0}; ULONG status; callout.displayData.name = _r_app_getname (); callout.displayData.description = _r_app_getname (); if (!config.is_filterstemporary) callout.flags = FWPM_CALLOUT_FLAG_PERSISTENT; callout.providerKey = (LPGUID)&GUID_WfpProvider; RtlCopyMemory (&callout.calloutKey, callout_key, sizeof (GUID)); RtlCopyMemory (&callout.applicableLayer, layer_key, sizeof (GUID)); status = FwpmCalloutAdd0 (engine_handle, &callout, NULL, NULL); if (status != ERROR_SUCCESS && status != FWP_E_ALREADY_EXISTS) _r_log (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmCalloutAdd0", status, NULL); return status; } ULONG _wfp_createfilter ( _In_ HANDLE engine_handle, _In_ ENUM_TYPE_DATA type, _In_opt_ LPCWSTR filter_name, _In_reads_ (count) FWPM_FILTER_CONDITION0 *lpcond, _In_ UINT32 count, _In_ LPCGUID layer_id, _In_opt_ LPCGUID callout_id, _In_ UINT8 weight, _In_ FWP_ACTION_TYPE action, _In_ UINT32 flags, _Inout_opt_ PR_ARRAY guids ) { FWPM_FILTER0 filter = {0}; WCHAR filter_description[128]; PR_STRING layer_name; LPCWSTR filter_type; UINT64 filter_id; ULONG status; // create filter guid _r_math_generateguid (&filter.filterKey); filter_type = _wfp_filtertypetostring (type); if (filter_type && filter_name) { _r_str_printf (filter_description, RTL_NUMBER_OF (filter_description), L"%s\\%s", filter_type, filter_name); } else if (filter_name) { _r_str_copy (filter_description, RTL_NUMBER_OF (filter_description), filter_name); } else { _r_str_copy (filter_description, RTL_NUMBER_OF (filter_description), _r_locale_getstring (IDS_STATUS_EMPTY)); } // reset action rights if (weight == FW_WEIGHT_HIGHEST_IMPORTANT || action == FWP_ACTION_BLOCK || action == FWP_ACTION_CALLOUT_TERMINATING) filter.flags = FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT; // set filter flags if ((flags & FWPM_FILTER_FLAG_BOOTTIME) == 0) { if (!config.is_filterstemporary) filter.flags |= FWPM_FILTER_FLAG_PERSISTENT; // filter is indexed to help enable faster lookup during classification (win8+) if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) filter.flags |= FWPM_FILTER_FLAG_INDEXED; } if (flags) filter.flags |= flags; filter.displayData.name = _r_app_getname (); filter.displayData.description = filter_description; RtlCopyMemory (&filter.subLayerKey, &GUID_WfpSublayer, sizeof (GUID)); RtlCopyMemory (&filter.layerKey, layer_id, sizeof (GUID)); if (callout_id) RtlCopyMemory (&filter.action.calloutKey, callout_id, sizeof (GUID)); filter.providerKey = (LPGUID)&GUID_WfpProvider; filter.weight.type = FWP_UINT8; filter.weight.uint8 = weight; filter.action.type = action; if (count) { filter.numFilterConditions = count; filter.filterCondition = lpcond; } status = FwpmFilterAdd0 (engine_handle, &filter, NULL, &filter_id); if (status == ERROR_SUCCESS) { if (guids) _r_obj_addarrayitem (guids, &filter.filterKey, NULL); } else { layer_name = _wfp_getlayername ((LPGUID)layer_id); _r_log_v (LOG_LEVEL_ERROR, &GUID_TrayIcon, L"FwpmFilterAdd0", status, L"%s\\%s", _r_obj_getstring (layer_name), filter.displayData.description); if (layer_name) _r_obj_dereference (layer_name); } return status; } VOID _wfp_clearfilter_ids () { PITEM_APP ptr_app = NULL; PITEM_RULE ptr_rule; ULONG_PTR enum_key = 0; // clear common filters _r_obj_cleararray (filter_ids); // clear apps filters _r_queuedlock_acquireshared (&lock_apps); while (_r_obj_enumhashtablepointer (apps_table, (PVOID_PTR)&ptr_app, NULL, &enum_key)) { ptr_app->is_haveerrors = FALSE; if (ptr_app->guids) _r_obj_cleararray (ptr_app->guids); } _r_queuedlock_releaseshared (&lock_apps); // clear rules filters _r_queuedlock_acquireshared (&lock_rules); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules_list); i++) { ptr_rule = _r_obj_getlistitem (rules_list, i); if (!ptr_rule) continue; ptr_rule->is_haveerrors = FALSE; _r_obj_cleararray (ptr_rule->guids); } _r_queuedlock_releaseshared (&lock_rules); } VOID _wfp_destroyfilters ( _In_ HANDLE engine_handle ) { PR_ARRAY guids; ULONG status; _wfp_clearfilter_ids (); // destroy all filters _r_queuedlock_acquireshared (&lock_transaction); status = _wfp_dumpfilters (engine_handle, &GUID_WfpProvider, &guids); _r_queuedlock_releaseshared (&lock_transaction); if (status != ERROR_SUCCESS) return; _wfp_destroyfilters_array (engine_handle, guids, DBG_ARG); _r_obj_dereference (guids); } VOID _wfp_destroyfilters_array ( _In_ HANDLE engine_handle, _In_ PR_ARRAY guids, _In_ LPCWSTR file_name, _In_ ULONG line ) { LPGUID guid; BOOLEAN is_enabled; BOOLEAN is_intransact; is_enabled = _app_initinterfacestate (_r_app_gethwnd (), FALSE); _r_queuedlock_acquireshared (&lock_transaction); for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _app_setfiltersecurity (engine_handle, guid, FALSE, DBG_ARG_VAR); } is_intransact = _wfp_transact_start (engine_handle, DBG_ARG_VAR); for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _wfp_deletefilter (engine_handle, guid); } if (is_intransact) _wfp_transact_commit (engine_handle, DBG_ARG_VAR); _r_queuedlock_releaseshared (&lock_transaction); _app_restoreinterfacestate (_r_app_gethwnd (), is_enabled); } BOOLEAN _wfp_createrulefilter ( _In_ HANDLE engine_handle, _In_ ENUM_TYPE_DATA filter_type, _In_opt_ LPCWSTR filter_name, _In_opt_ ULONG app_hash, _In_opt_ PITEM_FILTER_CONFIG filter_config, _In_opt_ PR_STRINGREF rule_remote, _In_opt_ PR_STRINGREF rule_local, _In_ UINT8 weight, _In_ FWP_ACTION_TYPE action, _In_ UINT32 flags, _Inout_opt_ PR_ARRAY guids ) { FWPM_FILTER_CONDITION0 fwfc[8] = {0}; UINT32 count = 0; ITEM_ADDRESS address; FWP_V4_ADDR_AND_MASK fwp_addr4_and_mask1; FWP_V4_ADDR_AND_MASK fwp_addr4_and_mask2; FWP_V6_ADDR_AND_MASK fwp_addr6_and_mask1; FWP_V6_ADDR_AND_MASK fwp_addr6_and_mask2; FWP_RANGE0 fwp_range1; FWP_RANGE0 fwp_range2; FWP_BYTE_BLOB *byte_blob = NULL; PITEM_APP ptr_app = NULL; FWP_DIRECTION direction; UINT8 protocol; ADDRESS_FAMILY af; PR_STRINGREF rules[] = { rule_remote, rule_local }; //BOOLEAN is_remoteaddr_set = FALSE; //BOOLEAN is_remoteport_set = FALSE; BOOLEAN is_success = FALSE; NTSTATUS status; if (filter_config) { direction = filter_config->direction; protocol = filter_config->protocol; af = filter_config->af; } else { direction = FWP_DIRECTION_MAX; protocol = 0; af = AF_UNSPEC; } // set path condition if (app_hash) { ptr_app = _app_getappitem (app_hash); if (!ptr_app) { _r_log_v (LOG_LEVEL_WARNING, NULL, TEXT (__FUNCTION__), 0, L"App \"%" TEXT (PR_ULONG) L"\" was not found!", app_hash); goto CleanupExit; } if (ptr_app->type == DATA_APP_SERVICE) // windows service { if (ptr_app->bytes) { ByteBlobAlloc (ptr_app->bytes->buffer, RtlLengthSecurityDescriptor (ptr_app->bytes->buffer), (PVOID_PTR)&byte_blob); fwfc[count].fieldKey = FWPM_CONDITION_ALE_USER_ID; fwfc[count].matchType = FWP_MATCH_EQUAL; fwfc[count].conditionValue.type = FWP_SECURITY_DESCRIPTOR_TYPE; fwfc[count].conditionValue.sd = byte_blob; count += 1; } else { _r_log (LOG_LEVEL_ERROR, NULL, TEXT (__FUNCTION__), 0, _r_obj_getstring (ptr_app->original_path)); goto CleanupExit; } } else if (ptr_app->type == DATA_APP_UWP) // uwp app (win8+) { if (ptr_app->bytes) { fwfc[count].fieldKey = FWPM_CONDITION_ALE_PACKAGE_ID; fwfc[count].matchType = FWP_MATCH_EQUAL; fwfc[count].conditionValue.type = FWP_SID; fwfc[count].conditionValue.sid = (PSID)ptr_app->bytes->buffer; count += 1; } else { _r_log (LOG_LEVEL_ERROR, NULL, TEXT (__FUNCTION__), 0, _r_obj_getstring (ptr_app->original_path)); goto CleanupExit; } } else { status = _FwpmGetAppIdFromFileName1 (ptr_app->original_path, ptr_app->type, (PVOID_PTR)&byte_blob); if (NT_SUCCESS (status)) { fwfc[count].fieldKey = FWPM_CONDITION_ALE_APP_ID; fwfc[count].matchType = FWP_MATCH_EQUAL; fwfc[count].conditionValue.type = FWP_BYTE_BLOB_TYPE; fwfc[count].conditionValue.byteBlob = byte_blob; count += 1; } else { // do not log file not found to error log if (status != STATUS_OBJECT_NAME_NOT_FOUND && status != STATUS_OBJECT_PATH_NOT_FOUND) _r_log (LOG_LEVEL_ERROR, NULL, L"FwpmGetAppIdFromFileName", status, _r_obj_getstring (ptr_app->original_path)); goto CleanupExit; } } } // set ip/port condition for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (rules); i++) { if (_r_obj_isstringempty (rules[i])) continue; if (!_app_parserulestring (rules[i], &address)) goto CleanupExit; if (i == 0) { if (address.type == DATA_TYPE_PORT) { //is_remoteport_set = TRUE; } else if (address.type == DATA_TYPE_IP) { //is_remoteaddr_set = TRUE; } } if (address.is_range) { if (address.type == DATA_TYPE_IP) { if (address.format == NET_ADDRESS_IPV4) { af = AF_INET; } else if (address.format == NET_ADDRESS_IPV6) { af = AF_INET6; } else { goto CleanupExit; } } if (address.type == DATA_TYPE_PORT) { if (i == 0) { fwfc[count].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT; } else { fwfc[count].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT; } } else { if (i == 0) { fwfc[count].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS; } else { fwfc[count].fieldKey = FWPM_CONDITION_IP_LOCAL_ADDRESS; } } fwfc[count].matchType = FWP_MATCH_RANGE; fwfc[count].conditionValue.type = FWP_RANGE_TYPE; if (i == 0) { fwp_range1 = address.range; fwfc[count].conditionValue.rangeValue = &fwp_range1; } else { fwp_range2 = address.range; fwfc[count].conditionValue.rangeValue = &fwp_range2; } count += 1; } else { if (address.type == DATA_TYPE_PORT) { if (i == 0) { fwfc[count].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT; } else { fwfc[count].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT; } fwfc[count].matchType = FWP_MATCH_EQUAL; fwfc[count].conditionValue.type = FWP_UINT16; fwfc[count].conditionValue.uint16 = address.port; count += 1; } else if (address.type == DATA_TYPE_IP) { if (i == 0) { fwfc[count].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS; } else { fwfc[count].fieldKey = FWPM_CONDITION_IP_LOCAL_ADDRESS; } fwfc[count].matchType = FWP_MATCH_EQUAL; if (address.format == NET_ADDRESS_IPV4) { af = AF_INET; fwfc[count].conditionValue.type = FWP_V4_ADDR_MASK; //fwfc[count].conditionValue.v4AddrMask = &address.addr4; if (i == 0) { fwp_addr4_and_mask1 = address.addr4; fwfc[count].conditionValue.v4AddrMask = &fwp_addr4_and_mask1; } else { fwp_addr4_and_mask2 = address.addr4; fwfc[count].conditionValue.v4AddrMask = &fwp_addr4_and_mask2; } count += 1; } else if (address.format == NET_ADDRESS_IPV6) { af = AF_INET6; fwfc[count].conditionValue.type = FWP_V6_ADDR_MASK; //fwfc[count].conditionValue.v6AddrMask = &address.addr6; if (i == 0) { fwp_addr6_and_mask1 = address.addr6; fwfc[count].conditionValue.v6AddrMask = &fwp_addr6_and_mask1; } else { fwp_addr6_and_mask2 = address.addr6; fwfc[count].conditionValue.v6AddrMask = &fwp_addr6_and_mask2; } count += 1; } else { goto CleanupExit; } } else { goto CleanupExit; } } // set port if available if (address.type == DATA_TYPE_IP) { if (address.port) { if (i == 0) { fwfc[count].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT; } else { fwfc[count].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT; } fwfc[count].matchType = FWP_MATCH_EQUAL; fwfc[count].conditionValue.type = FWP_UINT16; fwfc[count].conditionValue.uint16 = address.port; count += 1; } } } // set protocol condition if (protocol) { fwfc[count].fieldKey = FWPM_CONDITION_IP_PROTOCOL; fwfc[count].matchType = FWP_MATCH_EQUAL; fwfc[count].conditionValue.type = FWP_UINT8; fwfc[count].conditionValue.uint8 = protocol; count += 1; } // create outbound layer filter if (direction == FWP_DIRECTION_OUTBOUND || direction == FWP_DIRECTION_MAX) { if (af == AF_INET || af == AF_UNSPEC) { _wfp_createfilter ( engine_handle, filter_type, filter_name, fwfc, count, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, NULL, weight, action, flags, guids ); } if (af == AF_INET6 || af == AF_UNSPEC) { _wfp_createfilter ( engine_handle, filter_type, filter_name, fwfc, count, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, NULL, weight, action, flags, guids ); } } // create inbound layer filter if (direction == FWP_DIRECTION_INBOUND || direction == FWP_DIRECTION_MAX) { if (af == AF_INET || af == AF_UNSPEC) { _wfp_createfilter ( engine_handle, filter_type, filter_name, fwfc, count, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, weight, action, flags, guids ); } if (af == AF_INET6 || af == AF_UNSPEC) { _wfp_createfilter ( engine_handle, filter_type, filter_name, fwfc, count, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, weight, action, flags, guids ); } } is_success = TRUE; CleanupExit: if (ptr_app) _r_obj_dereference (ptr_app); if (byte_blob) ByteBlobFree ((PVOID_PTR)&byte_blob); return is_success; } BOOLEAN _wfp_create4filters ( _In_ HANDLE engine_handle, _In_ PR_LIST rules, _In_ LPCWSTR file_name, _In_ ULONG line, _In_ BOOLEAN is_intransact ) { R_STRINGREF remote_remaining_part; R_STRINGREF local_remaining_part; R_STRINGREF rule_remote_part; R_STRINGREF rule_local_part; LPCWSTR rule_name; PR_ARRAY guids; LPGUID guid; PITEM_RULE ptr_rule; ULONG_PTR enum_key; ULONG hash_code; BOOLEAN is_enabled; if (_r_obj_isempty (rules)) return FALSE; is_enabled = _app_initinterfacestate (_r_app_gethwnd (), FALSE); if (!is_intransact && _wfp_isfiltersapplying ()) is_intransact = TRUE; guids = _r_obj_createarray (sizeof (GUID), 10, NULL); if (!is_intransact) { for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules); i++) { ptr_rule = _r_obj_getlistitem (rules, i); if (!ptr_rule) continue; if (!_r_obj_isempty (ptr_rule->guids)) { _r_obj_addarrayitems (guids, ptr_rule->guids->items, ptr_rule->guids->count); _r_obj_cleararray (ptr_rule->guids); } } for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _app_setfiltersecurity (engine_handle, guid, FALSE, DBG_ARG_VAR); } _r_queuedlock_acquireshared (&lock_transaction); is_intransact = !_wfp_transact_start (engine_handle, DBG_ARG_VAR); } for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _wfp_deletefilter (engine_handle, guid); } for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules); i++) { ptr_rule = _r_obj_getlistitem (rules, i); if (!ptr_rule) continue; ptr_rule->is_haveerrors = FALSE; _r_obj_cleararray (ptr_rule->guids); if (!ptr_rule->is_enabled) continue; rule_name = _r_obj_getstring (ptr_rule->name); if (!_r_obj_isstringempty (ptr_rule->rule_remote)) { _r_str_splitatchar (&ptr_rule->rule_remote->sr, DIVIDER_RULE[0], &rule_remote_part, &remote_remaining_part); } else { _r_obj_initializestringrefempty (&rule_remote_part); _r_obj_initializestringrefempty (&remote_remaining_part); } if (!_r_obj_isstringempty (ptr_rule->rule_local)) { _r_str_splitatchar (&ptr_rule->rule_local->sr, DIVIDER_RULE[0], &rule_local_part, &local_remaining_part); } else { _r_obj_initializestringrefempty (&rule_local_part); _r_obj_initializestringrefempty (&local_remaining_part); } while (TRUE) { // apply rules for services hosts if (ptr_rule->is_forservices) { if (!_wfp_createrulefilter ( engine_handle, ptr_rule->type, rule_name, config.ntoskrnl_hash, &ptr_rule->config, &rule_remote_part, &rule_local_part, ptr_rule->weight, ptr_rule->action, 0, ptr_rule->guids)) { ptr_rule->is_haveerrors = TRUE; } if (!_wfp_createrulefilter ( engine_handle, ptr_rule->type, rule_name, config.svchost_hash, &ptr_rule->config, &rule_remote_part, &rule_local_part, ptr_rule->weight, ptr_rule->action, 0, ptr_rule->guids)) { ptr_rule->is_haveerrors = TRUE; } } if (!_r_obj_isempty (ptr_rule->apps)) { enum_key = 0; while (_r_obj_enumhashtable (ptr_rule->apps, NULL, &hash_code, &enum_key)) { if (ptr_rule->is_forservices && _app_issystemhash (hash_code)) continue; if (!_wfp_createrulefilter ( engine_handle, ptr_rule->type, rule_name, hash_code, &ptr_rule->config, &rule_remote_part, &rule_local_part, ptr_rule->weight, ptr_rule->action, 0, ptr_rule->guids)) { ptr_rule->is_haveerrors = TRUE; } } } else { if (!_wfp_createrulefilter ( engine_handle, ptr_rule->type, rule_name, 0, &ptr_rule->config, &rule_remote_part, &rule_local_part, ptr_rule->weight, ptr_rule->action, 0, ptr_rule->guids)) { ptr_rule->is_haveerrors = TRUE; } } if (remote_remaining_part.length == 0 && local_remaining_part.length == 0) break; if (remote_remaining_part.length != 0) _r_str_splitatchar (&remote_remaining_part, DIVIDER_RULE[0], &rule_remote_part, &remote_remaining_part); if (local_remaining_part.length != 0) _r_str_splitatchar (&local_remaining_part, DIVIDER_RULE[0], &rule_local_part, &local_remaining_part); } } if (!is_intransact) { _wfp_transact_commit (engine_handle, DBG_ARG_VAR); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules); i++) { ptr_rule = _r_obj_getlistitem (rules, i); if (ptr_rule && ptr_rule->is_enabled) { for (ULONG_PTR j = 0; j < _r_obj_getarraysize (ptr_rule->guids); j++) { guid = (LPGUID)_r_obj_getarrayitem (ptr_rule->guids, j); if (guid) _app_setfiltersecurity (engine_handle, guid, TRUE, DBG_ARG_VAR); } } } _r_queuedlock_releaseshared (&lock_transaction); } _app_restoreinterfacestate (_r_app_gethwnd (), is_enabled); _r_obj_dereference (guids); return TRUE; } BOOLEAN _wfp_create3filters ( _In_ HANDLE engine_handle, _In_ PR_LIST rules, _In_ LPCWSTR file_name, _In_ ULONG line, _In_ BOOLEAN is_intransact ) { PR_ARRAY guids; LPGUID guid; PITEM_APP ptr_app; PR_STRING string; BOOLEAN is_enabled; if (_r_obj_isempty (rules)) return FALSE; if (!is_intransact && _wfp_isfiltersapplying ()) is_intransact = TRUE; guids = _r_obj_createarray (sizeof (GUID), 10, NULL); is_enabled = _app_initinterfacestate (_r_app_gethwnd (), FALSE); if (!is_intransact) { for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules); i++) { ptr_app = _r_obj_getlistitem (rules, i); if (ptr_app && !_r_obj_isempty (ptr_app->guids)) { _r_obj_addarrayitems (guids, ptr_app->guids->items, ptr_app->guids->count); _r_obj_cleararray (ptr_app->guids); } } for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _app_setfiltersecurity (engine_handle, guid, FALSE, DBG_ARG_VAR); } _r_queuedlock_acquireshared (&lock_transaction); is_intransact = !_wfp_transact_start (engine_handle, DBG_ARG_VAR); } for (ULONG_PTR i = 0; i < _r_obj_getarraysize (guids); i++) { guid = (LPGUID)_r_obj_getarrayitem (guids, i); if (guid) _wfp_deletefilter (engine_handle, guid); } for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules); i++) { ptr_app = _r_obj_getlistitem (rules, i); if (ptr_app && ptr_app->is_enabled) { string = _app_getappdisplayname (ptr_app, TRUE); if (!_wfp_createrulefilter ( engine_handle, ptr_app->type, _r_obj_getstring (string), ptr_app->app_hash, NULL, NULL, NULL, FW_WEIGHT_APP, FWP_ACTION_PERMIT, 0, ptr_app->guids)) { ptr_app->is_haveerrors = TRUE; } if (string) _r_obj_dereference (string); } } if (!is_intransact) { _wfp_transact_commit (engine_handle, DBG_ARG_VAR); for (ULONG_PTR i = 0; i < _r_obj_getlistsize (rules); i++) { ptr_app = _r_obj_getlistitem (rules, i); if (ptr_app) { for (ULONG_PTR j = 0; j < _r_obj_getarraysize (ptr_app->guids); j++) { guid = (LPGUID)_r_obj_getarrayitem (ptr_app->guids, j); if (guid) _app_setfiltersecurity (engine_handle, guid, TRUE, DBG_ARG_VAR); } } } _r_queuedlock_releaseshared (&lock_transaction); } _app_restoreinterfacestate (_r_app_gethwnd (), is_enabled); _r_obj_dereference (guids); return TRUE; } BOOLEAN _wfp_create2filters ( _In_ HANDLE engine_handle, _In_ LPCWSTR file_name, _In_ ULONG line, _In_ BOOLEAN is_intransact ) { // ipv4/ipv6 loopback R_STRINGREF loopback_list[] = { PR_STRINGREF_INIT (L"0.0.0.0/8"), PR_STRINGREF_INIT (L"10.0.0.0/8"), PR_STRINGREF_INIT (L"100.64.0.0/10"), PR_STRINGREF_INIT (L"127.0.0.0/8"), PR_STRINGREF_INIT (L"169.254.0.0/16"), PR_STRINGREF_INIT (L"172.16.0.0/12"), PR_STRINGREF_INIT (L"192.0.0.0/24"), PR_STRINGREF_INIT (L"192.0.2.0/24"), PR_STRINGREF_INIT (L"192.88.99.0/24"), PR_STRINGREF_INIT (L"192.168.0.0/16"), PR_STRINGREF_INIT (L"198.18.0.0/15"), PR_STRINGREF_INIT (L"198.51.100.0/24"), PR_STRINGREF_INIT (L"203.0.113.0/24"), PR_STRINGREF_INIT (L"224.0.0.0/4"), PR_STRINGREF_INIT (L"240.0.0.0/4"), PR_STRINGREF_INIT (L"255.255.255.255/32"), PR_STRINGREF_INIT (L"[::]/0"), PR_STRINGREF_INIT (L"[::]/128"), PR_STRINGREF_INIT (L"[::1]/128"), PR_STRINGREF_INIT (L"[::ffff:0:0]/96"), PR_STRINGREF_INIT (L"[::ffff:0:0:0]/96"), PR_STRINGREF_INIT (L"[64:ff9b::]/96"), PR_STRINGREF_INIT (L"[100::]/64"), PR_STRINGREF_INIT (L"[2001::]/32"), PR_STRINGREF_INIT (L"[2001:20::]/28"), PR_STRINGREF_INIT (L"[2001:db8::]/32"), PR_STRINGREF_INIT (L"[2002::]/16"), PR_STRINGREF_INIT (L"[fc00::]/7"), PR_STRINGREF_INIT (L"[fe80::]/10"), PR_STRINGREF_INIT (L"[ff00::]/8") }; FWPM_FILTER_CONDITION0 fwfc[3] = {0}; ITEM_ADDRESS address; LPGUID guid; FWP_ACTION_TYPE action; BOOLEAN is_enabled; is_enabled = _app_initinterfacestate (_r_app_gethwnd (), FALSE); if (!is_intransact && _wfp_isfiltersapplying ()) is_intransact = TRUE; if (!is_intransact) { if (!_r_obj_isempty (filter_ids)) { for (ULONG_PTR i = 0; i < _r_obj_getarraysize (filter_ids); i++) { guid = (LPGUID)_r_obj_getarrayitem (filter_ids, i); if (guid) _app_setfiltersecurity (engine_handle, guid, FALSE, DBG_ARG_VAR); } } _r_queuedlock_acquireshared (&lock_transaction); is_intransact = !_wfp_transact_start (engine_handle, DBG_ARG_VAR); } if (!_r_obj_isempty (filter_ids)) { for (ULONG_PTR i = 0; i < _r_obj_getarraysize (filter_ids); i++) { guid = (LPGUID)_r_obj_getarrayitem (filter_ids, i); if (guid) _wfp_deletefilter (engine_handle, guid); } _r_obj_cleararray (filter_ids); } // add loopback connections permission if (_r_config_getboolean (L"AllowLoopbackConnections", TRUE, NULL)) { // match all loopback (localhost) data // tests if the network traffic is (non-)app container loopback traffic (win8+) fwfc[0].fieldKey = FWPM_CONDITION_FLAGS; fwfc[0].matchType = FWP_MATCH_FLAGS_ALL_SET; fwfc[0].conditionValue.type = FWP_UINT32; fwfc[0].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_LOOPBACK; // tests if the network traffic is (non-)app container loopback traffic (win8+) if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { fwfc[0].matchType = FWP_MATCH_FLAGS_ANY_SET; fwfc[0].conditionValue.uint32 |= FWP_CONDITION_FLAG_IS_APPCONTAINER_LOOPBACK; } _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 1, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 1, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (loopback_list); i++) { if (!_app_parserulestring (&loopback_list[i], &address)) continue; fwfc[1].matchType = FWP_MATCH_EQUAL; if (address.format == NET_ADDRESS_IPV4) { fwfc[1].conditionValue.type = FWP_V4_ADDR_MASK; fwfc[1].conditionValue.v4AddrMask = &address.addr4; fwfc[1].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 2, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); fwfc[1].fieldKey = FWPM_CONDITION_IP_LOCAL_ADDRESS; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 2, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); } else if (address.format == NET_ADDRESS_IPV6) { fwfc[1].conditionValue.type = FWP_V6_ADDR_MASK; fwfc[1].conditionValue.v6AddrMask = &address.addr6; fwfc[1].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 2, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); fwfc[1].fieldKey = FWPM_CONDITION_IP_LOCAL_ADDRESS; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_LOOPBACK, fwfc, 2, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); } } } // firewall service rules // https://msdn.microsoft.com/en-us/library/gg462153.aspx if (_r_config_getboolean (L"AllowIPv6", TRUE, NULL)) { // allows 6to4 tunneling, which enables ipv6 to run over an ipv4 network fwfc[0].fieldKey = FWPM_CONDITION_IP_PROTOCOL; fwfc[0].matchType = FWP_MATCH_EQUAL; fwfc[0].conditionValue.type = FWP_UINT8; fwfc[0].conditionValue.uint8 = IPPROTO_IPV6; // ipv6 header _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, L"Allow6to4", fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); // allows icmpv6 router solicitation messages, which are // required for the ipv6 stack to work properly fwfc[0].fieldKey = FWPM_CONDITION_ICMP_TYPE; fwfc[0].matchType = FWP_MATCH_EQUAL; fwfc[0].conditionValue.type = FWP_UINT16; fwfc[0].conditionValue.uint16 = 0x85; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, L"AllowIcmpV6Type133", fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); // allows icmpv6 router advertise messages, which are required // for the ipv6 stack to work properly fwfc[0].conditionValue.uint16 = 0x86; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, L"AllowIcmpV6Type134", fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); // allows icmpv6 neighbor solicitation messages, which // are required for the ipv6 stack to work properly fwfc[0].conditionValue.uint16 = 0x87; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, L"AllowIcmpV6Type135", fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); // allows icmpv6 neighbor advertise messages, which are // required for the ipv6 stack to work properly fwfc[0].conditionValue.uint16 = 0x88; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, L"AllowIcmpV6Type136", fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, 0, filter_ids ); } // prevent port scanning using stealth discards and silent drops // https://docs.microsoft.com/ru-ru/windows/desktop/FWP/preventing-port-scanning if (_r_config_getboolean (L"UseStealthMode", TRUE, NULL)) { // blocks udp port scanners fwfc[0].fieldKey = FWPM_CONDITION_FLAGS; fwfc[0].matchType = FWP_MATCH_FLAGS_NONE_SET; fwfc[0].conditionValue.type = FWP_UINT32; fwfc[0].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_LOOPBACK; // tests if the network traffic is (non-)app container loopback traffic (win8+) if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) fwfc[0].conditionValue.uint32 |= FWP_CONDITION_FLAG_IS_APPCONTAINER_LOOPBACK; fwfc[1].fieldKey = FWPM_CONDITION_ICMP_TYPE; fwfc[1].matchType = FWP_MATCH_EQUAL; fwfc[1].conditionValue.type = FWP_UINT16; fwfc[1].conditionValue.uint16 = 0x03; // destination unreachable _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_ICMP_ERROR, fwfc, 2, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4, NULL, FW_WEIGHT_HIGHEST, FWP_ACTION_BLOCK, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_ICMP_ERROR, fwfc, 2, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6, NULL, FW_WEIGHT_HIGHEST, FWP_ACTION_BLOCK, 0, filter_ids ); // blocks tcp port scanners (exclude loopback) fwfc[0].conditionValue.uint32 |= FWP_CONDITION_FLAG_IS_IPSEC_SECURED; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_TCP_RST_ONCLOSE, fwfc, 1, &FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD, &FWPM_CALLOUT_WFP_TRANSPORT_LAYER_V4_SILENT_DROP, FW_WEIGHT_HIGHEST, FWP_ACTION_CALLOUT_TERMINATING, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_TCP_RST_ONCLOSE, fwfc, 1, &FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD, &FWPM_CALLOUT_WFP_TRANSPORT_LAYER_V6_SILENT_DROP, FW_WEIGHT_HIGHEST, FWP_ACTION_CALLOUT_TERMINATING, 0, filter_ids ); } // install boot-time filters (enforced at boot-time, // even before "base filtering engine" service starts) if (_r_config_getboolean (L"InstallBoottimeFilters", TRUE, NULL) && !config.is_filterstemporary) { fwfc[0].fieldKey = FWPM_CONDITION_FLAGS; fwfc[0].matchType = FWP_MATCH_FLAGS_ALL_SET; fwfc[0].conditionValue.type = FWP_UINT32; fwfc[0].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_LOOPBACK; // tests if the network traffic is (non-)app container loopback traffic (win8+) if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { fwfc[0].matchType = FWP_MATCH_FLAGS_ANY_SET; fwfc[0].conditionValue.uint32 |= FWP_CONDITION_FLAG_IS_APPCONTAINER_LOOPBACK; } _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_IPFORWARD_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_IPFORWARD_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_INBOUND_ICMP_ERROR_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_INBOUND_ICMP_ERROR_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6, NULL, FW_WEIGHT_HIGHEST_IMPORTANT, FWP_ACTION_PERMIT, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, NULL, 0, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, FW_WEIGHT_LOWEST, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, NULL, 0, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_LOWEST, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, NULL, 0, &FWPM_LAYER_INBOUND_ICMP_ERROR_V4, NULL, FW_WEIGHT_LOWEST, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, NULL, 0, &FWPM_LAYER_INBOUND_ICMP_ERROR_V6, NULL, FW_WEIGHT_LOWEST, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, NULL, 0, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4, NULL, FW_WEIGHT_LOWEST, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, NULL, 0, &FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6, NULL, FW_WEIGHT_LOWEST, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); // win7+ boot-time features fwfc[0].fieldKey = FWPM_CONDITION_FLAGS; fwfc[0].matchType = FWP_MATCH_FLAGS_NONE_SET; fwfc[0].conditionValue.type = FWP_UINT32; fwfc[0].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_OUTBOUND_PASS_THRU | FWP_CONDITION_FLAG_IS_INBOUND_PASS_THRU; _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_IPFORWARD_V4, NULL, FW_WEIGHT_APP, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BOOTTIME, fwfc, 1, &FWPM_LAYER_IPFORWARD_V6, NULL, FW_WEIGHT_APP, FWP_ACTION_BLOCK, FWPM_FILTER_FLAG_BOOTTIME, filter_ids ); } action = _r_config_getboolean (L"BlockOutboundConnections", TRUE, NULL) ? FWP_ACTION_BLOCK : FWP_ACTION_PERMIT; // block outbound connection if (action == FWP_ACTION_BLOCK) { // workaround #689 if (_r_sys_isosversiongreaterorequal (WINDOWS_8)) { _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BLOCK_CONNECTION, NULL, 0, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, &FWPM_CALLOUT_TCP_TEMPLATES_CONNECT_LAYER_V4, FW_WEIGHT_LOWEST, FWP_ACTION_CALLOUT_TERMINATING, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BLOCK_CONNECTION, NULL, 0, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, &FWPM_CALLOUT_TCP_TEMPLATES_CONNECT_LAYER_V6, FW_WEIGHT_LOWEST, FWP_ACTION_CALLOUT_TERMINATING, 0, filter_ids ); } } // fallback _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BLOCK_CONNECTION, NULL, 0, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, NULL, FW_WEIGHT_LOWEST, action, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BLOCK_CONNECTION, NULL, 0, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, NULL, FW_WEIGHT_LOWEST, action, 0, filter_ids ); // block inbound connections if (_r_config_getboolean (L"UseStealthMode", TRUE, NULL) || _r_config_getboolean (L"BlockInboundConnections", TRUE, NULL)) { action = FWP_ACTION_BLOCK; } else { action = FWP_ACTION_PERMIT; } _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BLOCK_RECVACCEPT, NULL, 0, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, FW_WEIGHT_LOWEST, action, 0, filter_ids ); _wfp_createfilter ( engine_handle, DATA_FILTER_GENERAL, FW_NAME_BLOCK_RECVACCEPT, NULL, 0, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, FW_WEIGHT_LOWEST, action, 0, filter_ids ); if (!is_intransact) { _wfp_transact_commit (engine_handle, DBG_ARG_VAR); for (ULONG_PTR i = 0; i < _r_obj_getarraysize (filter_ids); i++) { guid = (LPGUID)_r_obj_getarrayitem (filter_ids, i); if (guid) _app_setfiltersecurity (engine_handle, guid, TRUE, DBG_ARG_VAR); } _r_queuedlock_releaseshared (&lock_transaction); } _app_restoreinterfacestate (_r_app_gethwnd (), is_enabled); return TRUE; } _Success_ (return == ERROR_SUCCESS) ULONG _wfp_dumpcallouts ( _In_ HANDLE engine_handle, _In_ LPCGUID provider_id, _Outptr_ PR_ARRAY_PTR out_buffer ) { FWPM_CALLOUT0 **callouts_enum = NULL; FWPM_CALLOUT0 *callout; PR_ARRAY guids = NULL; HANDLE enum_handle = NULL; UINT32 return_count; ULONG status; *out_buffer = NULL; status = FwpmCalloutCreateEnumHandle0 (engine_handle, NULL, &enum_handle); if (status != ERROR_SUCCESS) return status; status = FwpmCalloutEnum0 (engine_handle, enum_handle, UINT32_MAX, &callouts_enum, &return_count); if (status != ERROR_SUCCESS) goto CleanupExit; if (!callouts_enum) { status = ERROR_NOT_FOUND; goto CleanupExit; } guids = _r_obj_createarray (sizeof (GUID), return_count, NULL); for (UINT32 i = 0; i < return_count; i++) { callout = callouts_enum[i]; if (!callout || !callout->providerKey) continue; if (IsEqualGUID (callout->providerKey, provider_id)) _r_obj_addarrayitem (guids, &callout->calloutKey, NULL); } if (_r_obj_isempty2 (guids)) status = ERROR_NOT_FOUND; CleanupExit: if (status == ERROR_SUCCESS) { *out_buffer = guids; } else { if (guids) _r_obj_dereference (guids); } if (enum_handle) FwpmCalloutDestroyEnumHandle0 (engine_handle, enum_handle); if (callouts_enum) FwpmFreeMemory0 ((PVOID_PTR)&callouts_enum); return status; } _Success_ (return == ERROR_SUCCESS) ULONG _wfp_dumpfilters ( _In_ HANDLE engine_handle, _In_ LPCGUID provider_id, _Outptr_ PR_ARRAY_PTR out_buffer ) { FWPM_FILTER0 **filters_enum = NULL; FWPM_FILTER0 *filter; PR_ARRAY guids = NULL; HANDLE enum_handle = NULL; UINT32 return_count; ULONG status; *out_buffer = NULL; status = FwpmFilterCreateEnumHandle0 (engine_handle, NULL, &enum_handle); if (status != ERROR_SUCCESS) return status; status = FwpmFilterEnum0 (engine_handle, enum_handle, UINT32_MAX, &filters_enum, &return_count); if (status != ERROR_SUCCESS) goto CleanupExit; if (!filters_enum) { status = ERROR_NOT_FOUND; goto CleanupExit; } guids = _r_obj_createarray (sizeof (GUID), return_count, NULL); for (UINT32 i = 0; i < return_count; i++) { filter = filters_enum[i]; if (!filter || !filter->providerKey) continue; if (IsEqualGUID (filter->providerKey, provider_id)) _r_obj_addarrayitem (guids, &filter->filterKey, NULL); } if (_r_obj_isempty2 (guids)) { status = ERROR_NOT_FOUND; _r_obj_dereference (guids); } CleanupExit: if (status == ERROR_SUCCESS) *out_buffer = guids; if (enum_handle) FwpmFilterDestroyEnumHandle0 (engine_handle, enum_handle); if (filters_enum) FwpmFreeMemory0 ((PVOID_PTR)&filters_enum); return status; } VOID NTAPI _wfp_applythread ( _In_ PVOID arglist ) { PITEM_CONTEXT context; HANDLE engine_handle; LONG dpi_value; _r_queuedlock_acquireshared (&lock_apply); context = (PITEM_CONTEXT)arglist; engine_handle = _wfp_getenginehandle (); // dropped packets logging (win7+) if (config.is_neteventset) _wfp_logunsubscribe (engine_handle); if (context->is_install) { if (_wfp_initialize (context->hwnd, engine_handle)) _wfp_installfilters (engine_handle); } else { if (_r_sys_isosversiongreaterorequal (WINDOWS_10)) _app_wufixenable (context->hwnd, FALSE); _wfp_destroyfilters (engine_handle); _wfp_uninitialize (engine_handle, TRUE); } // dropped packets logging (win7+) if (config.is_neteventset) _wfp_logsubscribe (context->hwnd, engine_handle); if (_r_sys_isosversiongreaterorequal (WINDOWS_10)) _app_wufixenable (context->hwnd, _r_config_getboolean (L"IsWUFixEnabled", FALSE, NULL)); dpi_value = _r_dc_getwindowdpi (context->hwnd); _app_restoreinterfacestate (context->hwnd, TRUE); _app_setinterfacestate (context->hwnd, dpi_value); _r_freelist_deleteitem (&context_free_list, context); _app_profile_save (context->hwnd); _r_queuedlock_releaseshared (&lock_apply); } VOID _wfp_firewallenable ( _In_ BOOLEAN is_enable ) { NET_FW_PROFILE_TYPE2 profile_types[] = { NET_FW_PROFILE2_DOMAIN, NET_FW_PROFILE2_PRIVATE, NET_FW_PROFILE2_PUBLIC }; INetFwPolicy2 *INetFwPolicy = NULL; HRESULT status; status = CoCreateInstance (&CLSID_NetFwPolicy2, NULL, CLSCTX_INPROC_SERVER, &IID_INetFwPolicy2, (PVOID_PTR)&INetFwPolicy); if (FAILED (status)) return; for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (profile_types); i++) { status = INetFwPolicy2_put_FirewallEnabled (INetFwPolicy, profile_types[i], is_enable ? VARIANT_TRUE : VARIANT_FALSE); if (FAILED (status)) _r_log_v (LOG_LEVEL_INFO, NULL, L"INetFwPolicy2_put_FirewallEnabled", status, L"%d", profile_types[i]); } INetFwPolicy2_Release (INetFwPolicy); } BOOLEAN _wfp_firewallisenabled () { NET_FW_PROFILE_TYPE2 profile_types[] = { NET_FW_PROFILE2_DOMAIN, NET_FW_PROFILE2_PRIVATE, NET_FW_PROFILE2_PUBLIC }; INetFwPolicy2 *INetFwPolicy = NULL; VARIANT_BOOL result = VARIANT_FALSE; HRESULT status; status = CoCreateInstance (&CLSID_NetFwPolicy2, NULL, CLSCTX_INPROC_SERVER, &IID_INetFwPolicy2, (PVOID_PTR)&INetFwPolicy); if (SUCCEEDED (status)) { for (ULONG_PTR i = 0; i < RTL_NUMBER_OF (profile_types); i++) { status = INetFwPolicy2_get_FirewallEnabled (INetFwPolicy, profile_types[i], &result); if (SUCCEEDED (status)) { if (result == VARIANT_TRUE) break; } } INetFwPolicy2_Release (INetFwPolicy); } if (result == VARIANT_TRUE) return TRUE; return FALSE; } _Success_ (NT_SUCCESS (return)) NTSTATUS _FwpmGetAppIdFromFileName1 ( _In_ PR_STRING path, _In_ ENUM_TYPE_DATA type, _Out_ PVOID_PTR byte_blob ) { R_STRINGREF path_skip_root; PR_STRING original_path; PR_STRING path_root; NTSTATUS status; *byte_blob = NULL; if (type == DATA_APP_REGULAR || type == DATA_APP_NETWORK || type == DATA_APP_SERVICE) { if (_r_str_gethash (&path->sr, TRUE) == config.ntoskrnl_hash) { ByteBlobAlloc (path->buffer, path->length + sizeof (UNICODE_NULL), byte_blob); return STATUS_SUCCESS; } else { status = _r_path_ntpathfromdos (&path->sr, TRUE, &original_path); if (!NT_SUCCESS (status)) { // file is inaccessible or not found, maybe low-level // driver preventing file access? try another way! if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_FILE_IS_A_DIRECTORY || status == STATUS_ACCESS_DENIED) { if (!_app_isappvalidpath (path)) { return status; } else { // file path (without root) path_root = _r_obj_createstring2 (&path->sr); PathStripToRootW (path_root->buffer); _r_str_trimtonullterminator (&path_root->sr); status = _r_path_ntpathfromdos (&path_root->sr, FALSE, &original_path); if (!NT_SUCCESS (status)) { _r_obj_dereference (path_root); return status; } // file path (without root) _r_obj_initializestringref (&path_skip_root, PathSkipRootW (path->buffer)); _r_obj_movereference ((PVOID_PTR)&original_path, _r_obj_concatstringrefs (2, &original_path->sr, &path_skip_root)); _r_str_tolower (&original_path->sr); // lower is important! _r_obj_dereference (path_root); } } else { return status; } } ByteBlobAlloc (original_path->buffer, original_path->length + sizeof (UNICODE_NULL), byte_blob); _r_obj_dereference (original_path); return STATUS_SUCCESS; } } else if (type == DATA_APP_PICO || type == DATA_APP_DEVICE) { original_path = _r_obj_createstring2 (&path->sr); if (type == DATA_APP_DEVICE) _r_str_tolower (&original_path->sr); // lower is important! ByteBlobAlloc (original_path->buffer, original_path->length + sizeof (UNICODE_NULL), byte_blob); _r_obj_dereference (original_path); return STATUS_SUCCESS; } return STATUS_FILE_NOT_AVAILABLE; } VOID ByteBlobAlloc ( _In_ LPCVOID data, _In_ ULONG_PTR bytes_count, _Out_ PVOID_PTR byte_blob ) { FWP_BYTE_BLOB *blob; blob = _r_mem_allocate (sizeof (FWP_BYTE_BLOB) + bytes_count); blob->size = (UINT)(UINT_PTR)bytes_count; blob->data = PTR_ADD_OFFSET (blob, sizeof (FWP_BYTE_BLOB)); RtlCopyMemory (blob->data, data, bytes_count); *byte_blob = blob; } VOID ByteBlobFree ( _Inout_ PVOID_PTR byte_blob ) { FWP_BYTE_BLOB *original_blob; original_blob = *byte_blob; *byte_blob = NULL; if (original_blob) _r_mem_free (original_blob); } ================================================ FILE: src/wfp.h ================================================ // simplewall // Copyright (c) 2016-2026 Henry++ #pragma once // guids DEFINE_GUID (GUID_WfpProvider, 0xB0D553E2, 0xC6A0, 0x4A9A, 0xAE, 0xB8, 0xC7, 0x52, 0x48, 0x3E, 0xD6, 0x2F); DEFINE_GUID (GUID_WfpSublayer, 0x9FEE6F59, 0xB951, 0x4F9A, 0xB5, 0x2F, 0x13, 0x3D, 0xCF, 0x7A, 0x42, 0x79); // filter names #define FW_NAME_BLOCK_CONNECTION L"BlockConnection" #define FW_NAME_BLOCK_RECVACCEPT L"BlockRecvAccept" #define FW_NAME_ICMP_ERROR L"BlockIcmpError" #define FW_NAME_TCP_RST_ONCLOSE L"BlockTcpRstOnClose" #define FW_NAME_BOOTTIME L"BlockBoottime" #define FW_NAME_LOOPBACK L"AllowLoopback" // sublayer weight #define FW_SUBLAYER_WEIGHT 0xFFFF // filter weights #define FW_WEIGHT_HIGHEST_IMPORTANT 0x0F #define FW_WEIGHT_HIGHEST 0x0E #define FW_WEIGHT_RULE_BLOCKLIST 0x0D #define FW_WEIGHT_RULE_USER_BLOCK 0x0C #define FW_WEIGHT_RULE_USER 0x0B #define FW_WEIGHT_RULE_SYSTEM 0x0A #define FW_WEIGHT_APP 0x09 #define FW_WEIGHT_LOWEST 0x08 ENUM_INSTALL_TYPE _wfp_isproviderinstalled ( _In_ HANDLE engine_handle ); ENUM_INSTALL_TYPE _wfp_issublayerinstalled ( _In_ HANDLE engine_handle ); BOOLEAN _wfp_isfiltersapplying (); BOOLEAN _wfp_isfiltersinstalled (); HANDLE _wfp_getenginehandle (); ENUM_INSTALL_TYPE _wfp_getinstalltype (); PR_STRING _wfp_getlayername ( _In_ LPGUID layer_guid ); BOOLEAN _wfp_initialize ( _In_opt_ HWND hwnd, _In_ HANDLE engine_handle ); VOID _wfp_uninitialize ( _In_ HANDLE engine_handle, _In_ BOOLEAN is_full ); VOID _wfp_installfilters ( _In_ HANDLE engine_handle ); BOOLEAN _wfp_transact_start ( _In_ HANDLE engine_handle, _In_ LPCWSTR file_name, _In_ ULONG line ); BOOLEAN _wfp_transact_commit ( _In_ HANDLE engine_handle, _In_ LPCWSTR file_name, _In_ ULONG line ); ULONG _wfp_createcallout ( _In_ HANDLE engine_handle, _In_ LPCGUID layer_key, _In_ LPCGUID callout_key ); BOOLEAN _wfp_deletefilter ( _In_ HANDLE engine_handle, _In_ LPGUID filter_id ); ULONG _wfp_createfilter ( _In_ HANDLE engine_handle, _In_ ENUM_TYPE_DATA type, _In_opt_ LPCWSTR filter_name, _In_reads_ (count) FWPM_FILTER_CONDITION0 *lpcond, _In_ UINT32 count, _In_ LPCGUID layer_id, _In_opt_ LPCGUID callout_id, _In_ UINT8 weight, _In_ FWP_ACTION_TYPE action, _In_ UINT32 flags, _Inout_opt_ PR_ARRAY guids ); VOID _wfp_clearfilter_ids (); VOID _wfp_destroyfilters ( _In_ HANDLE engine_handle ); VOID _wfp_destroyfilters_array ( _In_ HANDLE engine_handle, _In_ PR_ARRAY guids, _In_ LPCWSTR file_name, _In_ ULONG line ); BOOLEAN _wfp_createrulefilter ( _In_ HANDLE engine_handle, _In_ ENUM_TYPE_DATA filter_type, _In_opt_ LPCWSTR filter_name, _In_opt_ ULONG app_hash, _In_opt_ PITEM_FILTER_CONFIG filter_config, _In_opt_ PR_STRINGREF rule_remote, _In_opt_ PR_STRINGREF rule_local, _In_ UINT8 weight, _In_ FWP_ACTION_TYPE action, _In_ UINT32 flags, _Inout_opt_ PR_ARRAY guids ); BOOLEAN _wfp_create4filters ( _In_ HANDLE engine_handle, _In_ PR_LIST rules, _In_ LPCWSTR file_name, _In_ ULONG line, _In_ BOOLEAN is_intransact ); BOOLEAN _wfp_create3filters ( _In_ HANDLE engine_handle, _In_ PR_LIST rules, _In_ LPCWSTR file_name, _In_ ULONG line, _In_ BOOLEAN is_intransact ); BOOLEAN _wfp_create2filters ( _In_ HANDLE engine_handle, _In_ LPCWSTR file_name, _In_ ULONG line, _In_ BOOLEAN is_intransact ); _Success_ (return == ERROR_SUCCESS) ULONG _wfp_dumpcallouts ( _In_ HANDLE engine_handle, _In_ LPCGUID provider_id, _Outptr_ PR_ARRAY_PTR out_buffer ); _Success_ (return == ERROR_SUCCESS) ULONG _wfp_dumpfilters ( _In_ HANDLE engine_handle, _In_ LPCGUID provider_id, _Outptr_ PR_ARRAY_PTR out_buffer ); VOID NTAPI _wfp_applythread ( _In_ PVOID arglist ); VOID _wfp_firewallenable ( _In_ BOOLEAN is_enable ); BOOLEAN _wfp_firewallisenabled (); _Success_ (NT_SUCCESS (return)) NTSTATUS _FwpmGetAppIdFromFileName1 ( _In_ PR_STRING path, _In_ ENUM_TYPE_DATA type, _Out_ PVOID_PTR byte_blob ); VOID ByteBlobAlloc ( _In_ LPCVOID data, _In_ ULONG_PTR bytes_count, _Out_ PVOID_PTR byte_blob ); VOID ByteBlobFree ( _Inout_ PVOID_PTR byte_blob );