From da9280dc37ed907356654889bb1334a13e7dfa04 Mon Sep 17 00:00:00 2001 From: Abhi <19635345+ph33nx@users.noreply.github.com> Date: Mon, 11 May 2026 01:12:31 +0530 Subject: [PATCH] v2.0.0: ci, lefthook, license, readme rewrite, release workflow --- .editorconfig | 15 + .gitattributes | 17 + .github/ISSUE_TEMPLATE/bug_report.yml | 65 +++ .github/workflows/ci.yml | 173 +++++++ .github/workflows/e2e.yml | 272 ++++++++++ .gitignore | 26 + CITATION.cff | 25 + LICENSE | 21 + README.md | 171 ++++--- SECURITY.md | 13 + WinMasterBlocker.bat | 697 +++++++++++++++++--------- assets/banner.png | Bin 0 -> 330898 bytes assets/banner.svg | 59 +++ lefthook.yml | 21 + llms.txt | 51 ++ tools/audit-coverage.sh | 92 ++++ tools/format-check.sh | 47 ++ tools/lint-bat.sh | 95 ++++ 18 files changed, 1549 insertions(+), 311 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/e2e.yml create mode 100644 .gitignore create mode 100644 CITATION.cff create mode 100644 LICENSE create mode 100644 SECURITY.md create mode 100644 assets/banner.png create mode 100644 assets/banner.svg create mode 100644 lefthook.yml create mode 100644 llms.txt create mode 100755 tools/audit-coverage.sh create mode 100755 tools/format-check.sh create mode 100755 tools/lint-bat.sh diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..46b47d5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +[*.{bat,cmd}] +end_of_line = crlf + +[*.{md,yml,yaml}] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bf84a14 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +* text=auto eol=lf + +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +*.sh text eol=lf +*.md text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.cff text eol=lf +*.txt text eol=lf + +*.png binary +*.jpg binary +*.ico binary + +*.svg text diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..0accf8a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,65 @@ +name: Bug report +description: An executable is still reaching the internet, or the script errored out. +title: "[bug] " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report this. Please attach the transcript log + (`%TEMP%\WinMasterBlocker-*.log`). Reports without the log usually need a + round-trip to triage; with the log, most issues are resolved on first reply. + + - type: input + id: windows-version + attributes: + label: Windows version + description: "Run `winver` and paste the version string (for example, Windows 11 24H2 build 26100.4202)." + placeholder: "Windows 11 24H2 build 26100.xxxx" + validations: + required: true + + - type: input + id: app + attributes: + label: Application and version + description: "The vendor and the specific app + version that is still phoning home." + placeholder: "Adobe Acrobat DC 2026.001.20245" + validations: + required: true + + - type: input + id: exe-path + attributes: + label: Full path to the offending executable + placeholder: "C:\\Program Files\\Adobe\\Acrobat DC\\Acrobat\\acrocef_1\\acrocef.exe" + validations: + required: true + + - type: dropdown + id: ran-update + attributes: + label: After the most recent application update, did you re-run the script (or option 98)? + options: + - "Yes, re-ran after update" + - "No, did not re-run after update" + - "Not sure" + validations: + required: true + + - type: textarea + id: transcript + attributes: + label: Transcript log excerpt + description: "Paste the contents of %TEMP%\\WinMasterBlocker-*.log, or the relevant section." + render: text + validations: + required: false + + - type: textarea + id: extra + attributes: + label: Anything else worth knowing + description: "Custom install path, non-default drive, group policy involvement, etc." + validations: + required: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..bceaa5f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,173 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: false + +jobs: + lint: + name: lint + format + audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: lint + run: bash tools/lint-bat.sh WinMasterBlocker.bat + + - name: format-check + run: bash tools/format-check.sh WinMasterBlocker.bat + + - name: audit-coverage + run: bash tools/audit-coverage.sh WinMasterBlocker.bat + + integration: + name: WHATIF integration on Windows + runs-on: windows-latest + steps: + - uses: actions/checkout@v6 + + - name: stage fake vendor tree + shell: pwsh + run: | + $root = Join-Path $env:RUNNER_TEMP 'wmb-fake' + New-Item -ItemType Directory -Force -Path $root | Out-Null + + $adobe = Join-Path $root 'Program Files\Adobe\Acrobat DC\Acrobat\acrocef_1' + New-Item -ItemType Directory -Force -Path $adobe | Out-Null + New-Item -ItemType File -Force -Path (Join-Path $adobe 'acrocef.exe') | Out-Null + + $rdr = Join-Path $root 'Program Files\Adobe\Reader DC\Reader' + New-Item -ItemType Directory -Force -Path $rdr | Out-Null + New-Item -ItemType File -Force -Path (Join-Path $rdr 'RdrCEF.exe') | Out-Null + + New-Item -ItemType Directory -Force -Path (Join-Path $root 'Program Files (x86)\Adobe') | Out-Null + New-Item -ItemType Directory -Force -Path (Join-Path $root 'Common Files\Adobe') | Out-Null + New-Item -ItemType Directory -Force -Path (Join-Path $root 'Common Files (x86)\Adobe') | Out-Null + New-Item -ItemType Directory -Force -Path (Join-Path $root 'ProgramData\Adobe') | Out-Null + New-Item -ItemType Directory -Force -Path (Join-Path $root 'AppData\Local\Adobe') | Out-Null + New-Item -ItemType Directory -Force -Path (Join-Path $root 'AppData\Roaming\Adobe') | Out-Null + + "FAKE_ROOT=$root" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: run script in WHATIF mode + shell: cmd + env: + WHATIF: "1" + WMB_VENDOR: "Adobe" + WMB_QUIET: "1" + # WMB_TEST_ROOT redirects every path lookup to the fake tree we + # staged above. Cleaner than trying to override %ProgramFiles% + # from the workflow: GitHub Actions Windows runners ignore + # workflow-level overrides for well-known Windows system vars. + WMB_TEST_ROOT: ${{ runner.temp }}\wmb-fake + run: | + echo 0& WinMasterBlocker.bat + + - name: assert rules emitted in transcript + shell: pwsh + run: | + $log = Get-ChildItem $env:TEMP -Filter 'WinMasterBlocker-*.log' | Sort-Object LastWriteTime -Descending | Select-Object -First 1 + if (-not $log) { Write-Error 'no transcript log produced'; exit 1 } + Write-Host "transcript: $($log.FullName)" + $body = Get-Content $log.FullName -Raw + Write-Host "----- transcript -----" + Write-Host $body + Write-Host "----- /transcript -----" + # Tightened: require an actual rule emission, not just a path walk. + if ($body -notmatch 'add ".*acrocef.*Adobe-block"') { Write-Error 'transcript missing acrocef rule emission'; exit 1 } + if ($body -notmatch 'add ".*RdrCEF.*Adobe-block"') { Write-Error 'transcript missing RdrCEF rule emission'; exit 1 } + if ($body -notmatch 'WHATIF') { Write-Error 'transcript missing WHATIF marker'; exit 1 } + Write-Host 'integration ok' + + release: + name: GitHub Release on version bump + needs: [lint, integration] + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Extract WMB_VERSION + id: ver + run: | + V=$(grep -oE 'WMB_VERSION=[0-9]+\.[0-9]+\.[0-9]+' WinMasterBlocker.bat | head -1 | cut -d= -f2) + if [ -z "$V" ]; then + echo "::error::WMB_VERSION not found in WinMasterBlocker.bat" + exit 1 + fi + echo "version=$V" >> "$GITHUB_OUTPUT" + echo "tag=v$V" >> "$GITHUB_OUTPUT" + echo "Script version: $V" + + - name: Skip if release already exists + id: check + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if gh release view "${{ steps.ver.outputs.tag }}" >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + echo "Release ${{ steps.ver.outputs.tag }} already exists, skipping." + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Verify CITATION.cff version matches + if: steps.check.outputs.exists == 'false' + run: | + CFF=$(grep -oE '^version: "?[0-9]+\.[0-9]+\.[0-9]+"?' CITATION.cff | head -1 | awk '{print $2}' | tr -d '"') + if [ "$CFF" != "${{ steps.ver.outputs.version }}" ]; then + echo "::error::CITATION.cff version ($CFF) does not match WMB_VERSION (${{ steps.ver.outputs.version }})" + exit 1 + fi + + - name: SHA-256 checksums + if: steps.check.outputs.exists == 'false' + run: | + sha256sum WinMasterBlocker.bat LICENSE CITATION.cff > SHA256SUMS.txt + cat SHA256SUMS.txt + + - name: Release notes since previous tag + if: steps.check.outputs.exists == 'false' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PREV=$(gh release list --limit 1 --json tagName -q '.[0].tagName' 2>/dev/null || true) + { + echo "## Changes since ${PREV:-initial}" + echo + if [ -n "$PREV" ]; then + git log --pretty='* %s (%h)' "${PREV}..HEAD" + else + git log --pretty='* %s (%h)' + fi + } > RELEASE_NOTES.md + cat RELEASE_NOTES.md + + - name: Publish release + if: steps.check.outputs.exists == 'false' + uses: softprops/action-gh-release@v3 + with: + tag_name: ${{ steps.ver.outputs.tag }} + name: WinMasterBlocker ${{ steps.ver.outputs.tag }} + body_path: RELEASE_NOTES.md + files: | + WinMasterBlocker.bat + LICENSE + CITATION.cff + SHA256SUMS.txt + fail_on_unmatched_files: true + make_latest: true diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000..3340855 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,272 @@ +name: e2e + +# Real end-to-end test on a windows-latest runner. Drops WHATIF, runs the +# script in real-mode, creates actual Windows Firewall rules, verifies via +# Get-NetFirewallRule, exercises the menu, delete, idempotency, WHATIF, and +# the known-CEF sweep against a custom drive. Manual trigger only — heavy. +# +# To trigger: +# gh workflow run e2e.yml --ref maintenance-2026-05 +# or use the "Run workflow" button on the Actions tab. Set `enable_tmate=true` +# if you want an interactive SSH session opened just before cleanup. + +on: + workflow_dispatch: + inputs: + enable_tmate: + description: "Open a tmate SSH session before cleanup (interactive)" + type: boolean + default: false + tmate_only: + description: "Skip all tests, just open a tmate session immediately" + type: boolean + default: false + # Auto-run on PRs that touch the script or this workflow. Manual + # triggers via workflow_dispatch only register against the default + # branch, so this is how we run real-mode tests before merging. + pull_request: + branches: [main] + paths: + - "WinMasterBlocker.bat" + - ".github/workflows/e2e.yml" + +permissions: + contents: read + +concurrency: + group: e2e-${{ github.ref }} + cancel-in-progress: true + +jobs: + e2e: + name: End-to-end on real Windows + runs-on: windows-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v6 + + - name: Tmate (immediate, if requested) + if: ${{ inputs.tmate_only }} + uses: mxschmitt/action-tmate@v3 + with: + detached: false + + - name: Pre-clean any stale *-block rules from previous runs + shell: pwsh + run: | + $stale = Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue + if ($stale) { + Write-Host "Removing $($stale.Count) stale rule(s)" + $stale | Remove-NetFirewallRule + } else { + Write-Host "No stale rules" + } + + - name: Stage fake install trees + shell: pwsh + run: | + # Empty fake tree for WMB_TEST_ROOT (keeps the main path-table walk + # from picking up unrelated runner binaries). + $fake = Join-Path $env:RUNNER_TEMP 'wmb-fake' + New-Item -ItemType Directory -Force -Path $fake | Out-Null + foreach ($sub in @( + 'Program Files\Adobe', + 'Program Files (x86)\Adobe', + 'Common Files\Adobe', + 'Common Files (x86)\Adobe', + 'ProgramData\Adobe', + 'AppData\Local\Adobe', + 'AppData\Roaming\Adobe' + )) { + New-Item -ItemType Directory -Force -Path (Join-Path $fake $sub) | Out-Null + } + + # Custom-drive install: D:\Adobe\ is what the new known-sweep alphabet + # walk catches. We seed acrocef.exe and RdrCEF.exe here so the only + # path that can produce rules is the sweep. + $custom = 'D:\Adobe\Acrobat DC\Acrobat\acrocef_1' + New-Item -ItemType Directory -Force -Path $custom | Out-Null + fsutil file createnew (Join-Path $custom 'acrocef.exe') 1024 | Out-Null + + $rdr = 'D:\Adobe\Reader DC\Reader' + New-Item -ItemType Directory -Force -Path $rdr | Out-Null + fsutil file createnew (Join-Path $rdr 'RdrCEF.exe') 1024 | Out-Null + + # User-profile install (second known-sweep target). Acrobat.exe is + # in the script's known-exe list; the sweep matches by literal name. + $up = Join-Path $env:USERPROFILE 'Adobe\Acrobat\bin' + New-Item -ItemType Directory -Force -Path $up | Out-Null + fsutil file createnew (Join-Path $up 'Acrobat.exe') 1024 | Out-Null + + "FAKE_ROOT=$fake" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + Write-Host "FAKE_ROOT=$fake" + Write-Host "Custom drive seeded: D:\Adobe\..." + Write-Host "User-profile seeded: $up" + + # --------------------------------------------------------------------- + # SCENARIO 1 — real block via unattended mode. + # --------------------------------------------------------------------- + - name: "S1: block creates real firewall rules" + if: ${{ !inputs.tmate_only }} + shell: cmd + env: + WMB_VENDOR: "Adobe" + WMB_QUIET: "1" + WMB_TEST_ROOT: ${{ runner.temp }}\wmb-fake + run: WinMasterBlocker.bat + + - name: "S1: verify acrocef Adobe-block exists (in + out)" + if: ${{ !inputs.tmate_only }} + shell: pwsh + run: | + $rules = Get-NetFirewallRule -DisplayName 'acrocef Adobe-block' -ErrorAction SilentlyContinue + if ($rules.Count -ne 2) { + Write-Host "::error::expected 2 rules (in+out) for acrocef, got $($rules.Count)" + $all = Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue + Write-Host "All *-block rules on host:" + $all | Select-Object DisplayName,Direction,Action | Format-Table + exit 1 + } + foreach ($r in $rules) { + if ($r.Action -ne 'Block') { + Write-Host "::error::rule $($r.DisplayName) dir=$($r.Direction) action=$($r.Action), expected Block" + exit 1 + } + } + Write-Host "S1 ok: 2 acrocef rules, both Block" + + - name: "S1: verify RdrCEF + Acrobat (known-sweep proof)" + if: ${{ !inputs.tmate_only }} + shell: pwsh + run: | + $missing = @() + foreach ($name in @('RdrCEF Adobe-block','Acrobat Adobe-block')) { + $rules = Get-NetFirewallRule -DisplayName $name -ErrorAction SilentlyContinue + if ($rules.Count -ne 2) { + $missing += "$name (got $($rules.Count))" + } + } + if ($missing.Count -gt 0) { + Write-Host "::error::known-sweep regression: $($missing -join '; ')" + Write-Host "All *-block rules currently on host:" + Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue | Select-Object DisplayName,Direction,Action | Format-Table + exit 1 + } + Write-Host "S1 ok: known-sweep caught D:\Adobe\ + %USERPROFILE%\Adobe\" + + # --------------------------------------------------------------------- + # SCENARIO 2 — idempotency. Re-running adds zero new rules. + # --------------------------------------------------------------------- + - name: "S2: count rules before re-run" + if: ${{ !inputs.tmate_only }} + shell: pwsh + run: | + $n = (Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue).Count + "BEFORE_COUNT=$n" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + Write-Host "BEFORE_COUNT=$n" + + - name: "S2: re-run script (should be idempotent)" + if: ${{ !inputs.tmate_only }} + shell: cmd + env: + WMB_VENDOR: "Adobe" + WMB_QUIET: "1" + WMB_TEST_ROOT: ${{ runner.temp }}\wmb-fake + run: WinMasterBlocker.bat + + - name: "S2: verify count unchanged" + if: ${{ !inputs.tmate_only }} + shell: pwsh + run: | + $after = (Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue).Count + if ($after -ne [int]$env:BEFORE_COUNT) { + Write-Host "::error::idempotency broken: before=$env:BEFORE_COUNT after=$after" + exit 1 + } + Write-Host "S2 ok: $after rules (unchanged)" + + # --------------------------------------------------------------------- + # SCENARIO 3 — delete via unattended mode. + # --------------------------------------------------------------------- + - name: "S3: delete all via WMB_ACTION=delete" + if: ${{ !inputs.tmate_only }} + shell: cmd + env: + WMB_VENDOR: "Adobe" + WMB_ACTION: "delete" + WMB_QUIET: "1" + run: WinMasterBlocker.bat + + - name: "S3: verify zero *-block rules remain" + if: ${{ !inputs.tmate_only }} + shell: pwsh + run: | + $remaining = Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue + if ($remaining) { + Write-Host "::error::delete left $($remaining.Count) rule(s) behind:" + $remaining | Select-Object DisplayName,Direction | Format-Table + exit 1 + } + Write-Host "S3 ok: all -block rules removed" + + # --------------------------------------------------------------------- + # SCENARIO 4 — WHATIF makes zero firewall changes. + # --------------------------------------------------------------------- + - name: "S4: WHATIF mode creates no rules" + if: ${{ !inputs.tmate_only }} + shell: cmd + env: + WHATIF: "1" + WMB_VENDOR: "Adobe" + WMB_QUIET: "1" + WMB_TEST_ROOT: ${{ runner.temp }}\wmb-fake + run: WinMasterBlocker.bat + + - name: "S4: verify firewall untouched" + if: ${{ !inputs.tmate_only }} + shell: pwsh + run: | + $rules = Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue + if ($rules) { + Write-Host "::error::WHATIF created $($rules.Count) real rule(s)!" + exit 1 + } + $log = Get-ChildItem $env:TEMP -Filter 'WinMasterBlocker-*.log' | Sort-Object LastWriteTime -Descending | Select-Object -First 1 + $body = Get-Content $log.FullName -Raw + if ($body -notmatch '\[WHATIF\] add ".*acrocef.*Adobe-block"') { + Write-Host "::error::WHATIF transcript missing acrocef line" + exit 1 + } + Write-Host "S4 ok: no real rules, transcript has [WHATIF] entries" + + # --------------------------------------------------------------------- + # Cleanup before tmate / exit. Always runs. + # --------------------------------------------------------------------- + # Manual opt-in only. Auto-opening on failure() blocks the job + # waiting for an SSH client; surfacing the transcript log below is + # enough for most diagnoses. + - name: Tmate (debug, before cleanup) + if: ${{ inputs.enable_tmate }} + uses: mxschmitt/action-tmate@v3 + with: + detached: false + limit-access-to-actor: true + + - name: Final cleanup + if: always() + shell: pwsh + run: | + Get-NetFirewallRule -DisplayName '*-block' -ErrorAction SilentlyContinue | Remove-NetFirewallRule -ErrorAction SilentlyContinue + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue D:\Adobe + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue (Join-Path $env:USERPROFILE 'Adobe') + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue (Join-Path $env:RUNNER_TEMP 'wmb-fake') + Write-Host "Cleanup done." + + - name: Surface transcript log on failure + if: failure() + shell: pwsh + run: | + Get-ChildItem $env:TEMP -Filter 'WinMasterBlocker-*.log' | Sort-Object LastWriteTime -Descending | ForEach-Object { + Write-Host "=== $($_.FullName) ===" + Get-Content $_.FullName -Raw + } diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c094587 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Local AI agent instructions (not for public repo) +CLAUDE.md +AGENTS.md +.cursorrules +.aider* + +# Editor / OS +.vscode/ +.idea/ +*.swp +*.swo +.DS_Store +Thumbs.db +desktop.ini + +# Local tooling +node_modules/ +.env +.env.local +*.log + +# Temp files the script itself writes (just in case anyone runs it inside the repo) +WinMasterBlocker-*.log +wmb-uac-*.env +SHA256SUMS.txt +RELEASE_NOTES.md diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..8582946 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,25 @@ +cff-version: 1.2.0 +title: WinMasterBlocker +message: "If you reference this tool in research, articles, or other software, please cite it using the metadata below." +type: software +authors: + - alias: ph33nx + website: "https://github.com/ph33nx" +repository-code: "https://github.com/ph33nx/WinMasterBlocker" +url: "https://github.com/ph33nx/WinMasterBlocker" +abstract: "A Windows batch script that uses the built-in Windows Firewall command line to block telemetry and license-server traffic from desktop applications such as Adobe Acrobat, Photoshop, Autodesk, Corel and Maxon, with no third-party dependencies." +keywords: + - windows-firewall + - netsh + - adobe-blocker + - acrocef + - firewall-rules + - internet-blocker + - windows-batch + - simplewall-alternative + - outbound-firewall + - application-firewall + - windows-sysadmin +license: MIT +version: 2.0.0 +date-released: "2026-05-11" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..07d2777 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024-2026 ph33nx + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 0bb049b..a0499e1 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,145 @@ -### 🟢🔵🔴 Contributions welcome in expanding the list of vendors and installation paths! +# WinMasterBlocker -👉 If you know additional paths for app vendors or have information on other vendors, please consider contributing. (See the **Contributing** section below for details.) +
+
+
4XM+^CWaN#vgxNm%1C}~f!#}fGLMSgsVO8@&4tCIO;-3;=dL`VAP<618Y<+)ZR=)
z=D8M|_1yWj3A`3ABwPn4IiZ|LEC`!}@O^0UhY4m#VAhl&R
zc3mLL=OzTE=M~De3lFlo%)_yA
z6LbgXA%y1DwK=jH72-j?)rt&y{q?o6C+kWwI$H-O(@Lr}h-8-L!8G{a>D!1jqgvac
zR_31zEUyB#Pp%FVAhm{lBV!$=Pt;*@Cw|uLIL&FJ|E3{r&W=c?$;)O<2%CwjQ6}YO
zLo6#eotk9j{?h
~zEETu(Wt*YeubMJNJQ;tG4BGB8cD`gK^NUUUDj#_v65hiSafz;+7ZHmAn4yqSa;
zcB4*O(5*oOaz(j;sYLe})0-kACZF%{wAP2X(&~%oJ{<=5Y3mA*JP$4ds5Vzujm>;&
zhNR&qzWNnkLi_!wk9oj}a;q$(vLkSkFrt1jqJuG6gjXJw2qGF}2N(NeCOkKYLS)7E
zBB^)!YmQ=a2MR9{vxVA9kTi8xHPH>_dGEpzqG^z0Od$tVzVTbGED5_p_T>0UTT#|o
zG=pNFrRRDLq1@ow2B&|O1LqLysBYu1ba3@w;D)e#2DSZ?l5~93SS1-_(MEN}9ZA&*
z+ZOBZazp7Xb%#(7JGDN0n_64joN!QvgSV|*0}0-xDn&yTnZPMTQJg~Vg6*k*Ylv@D
zsh)TA^|@n;vdOZ!`Xi^SpQL0tfzc^^xLVBCwpuMDPs>})#WFNoJyO)pA0xItfDV-8
zCE!;+_s+kEr5Qx(tWdNd%^1`Z`3MOCbv6%4qN{|AU0=-9YBUG={K;{&Yx5?Xy(CnUZ~=FUaf;Mp2|F
zv~4kM?qCZ=5Y7*c%1tPc;5pMI8Fw#F@cF`JAf@RDHdo
F1Rn9uYWTl*nC`fL
zsc#4yyQ*R`ZjNtJTH#vWLe4aZw$l5}_W15pCA4tVEyJqSqT~^q&U#tUvehMQ!N8DH
zj_FZHtYR%WDf