diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..a41d6d9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,25 @@ +# CODEOWNERS +# GitHub automatically requests a review from the listed owners whenever a PR +# modifies files matching the pattern. More specific rules override less specific +# ones (last match wins), so list broad patterns first. +# +# Docs: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +# Catch-all: maintainer reviews everything +* @sjackson0109 + +# C++ DLL source +src-x86-x64-Fusix/ @sjackson0109 + +# C# tools (installer, configurator, checker, offset-finder) +src-csharp/ @sjackson0109 + +# WiX MSI packaging +msi/ @sjackson0109 + +# CI/CD pipelines +.github/ @sjackson0109 + +# Documentation +docs/ @sjackson0109 +README.md @sjackson0109 diff --git a/.github/DISCUSSION_TEMPLATE/announcements.md b/.github/DISCUSSION_TEMPLATE/announcements.md new file mode 100644 index 0000000..f074719 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/announcements.md @@ -0,0 +1,12 @@ +--- +title: "[Announcement] " +--- + + + +## Summary + +## Details + +## Action required (if any) diff --git a/.github/DISCUSSION_TEMPLATE/general.md b/.github/DISCUSSION_TEMPLATE/general.md new file mode 100644 index 0000000..cd3ea70 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/general.md @@ -0,0 +1,6 @@ +--- +title: "" +--- + + diff --git a/.github/DISCUSSION_TEMPLATE/ideas.md b/.github/DISCUSSION_TEMPLATE/ideas.md new file mode 100644 index 0000000..fef29df --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/ideas.md @@ -0,0 +1,26 @@ +--- +title: "[Idea] " +--- + +## Problem or motivation + + + +## Proposed solution + + + +## Alternatives considered + + + +## Component this relates to + + diff --git a/.github/DISCUSSION_TEMPLATE/q-a.md b/.github/DISCUSSION_TEMPLATE/q-a.md new file mode 100644 index 0000000..9675f6f --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/q-a.md @@ -0,0 +1,25 @@ +--- +title: "[Q&A] " +--- + +## What are you trying to do? + + + +## What have you already tried? + + + +## System information + +| Field | Value | +|---|---| +| Windows version (winver) | | +| termsrv.dll version | | +| Architecture | | +| RDPConf status | | +| RDP Wrapper release | | + +## Error or unexpected behaviour + + diff --git a/.github/DISCUSSION_TEMPLATE/show-and-tell.md b/.github/DISCUSSION_TEMPLATE/show-and-tell.md new file mode 100644 index 0000000..eed8346 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/show-and-tell.md @@ -0,0 +1,16 @@ +--- +title: "[Show] " +--- + +## What are you sharing? + + + +## Details + + + +## System or environment + + diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..5e1061f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,89 @@ +name: Bug Report +description: RDP Wrapper is not working correctly on your machine. +labels: [bug] +body: + - type: markdown + attributes: + value: | + Before submitting, please confirm: + - You are running the latest release from https://github.com/sjackson0109/rdpwrap/releases/latest + - Your termsrv.dll version is listed in `rdpwrap.ini` (check RDPConf for the status colour) + - You have excluded `C:\Program Files\RDP Wrapper\` from your antivirus + + - type: dropdown + id: status + attributes: + label: RDPConf status + description: What colour/status does RDPConf show? + options: + - Fully supported (green) — but RDP still fails + - Partially supported (yellow) + - Not supported (red) + - Not installed + - Wrapper DLL not found + validations: + required: true + + - type: input + id: windows_version + attributes: + label: Windows version + description: "Run: winver — paste the full string e.g. Windows 11 Version 24H2 (OS Build 26100.xxxx)" + placeholder: "Windows 11 Version 24H2 (OS Build 26100.3915)" + validations: + required: true + + - type: input + id: termsrv_version + attributes: + label: termsrv.dll version + description: "Run: (Get-Item C:\\Windows\\System32\\termsrv.dll).VersionInfo.FileVersion" + placeholder: "10.0.26100.3915" + validations: + required: true + + - type: input + id: rdpwrap_version + attributes: + label: RDP Wrapper version + description: Version shown in RDPConf or the release tag you downloaded. + placeholder: "ini-2026.03.29.1400" + validations: + required: true + + - type: dropdown + id: architecture + attributes: + label: System architecture + options: + - x64 (64-bit) + - x86 (32-bit) + - ARM64 + validations: + required: true + + - type: textarea + id: description + attributes: + label: Describe the problem + description: What happens? What did you expect to happen? + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + placeholder: | + 1. Run install.bat as administrator + 2. Open RDPConf + 3. Status shows ... + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Paste any output from the install/update bat scripts or Event Viewer (optional). + render: text diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..879ea22 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,20 @@ +blank_issues_enabled: false +contact_links: + - name: Q&A — ask a setup or usage question + url: https://github.com/sjackson0109/rdpwrap/discussions/new?category=q-a + about: Not sure why it is not working? Ask in Discussions rather than opening an issue. + - name: Ideas — suggest an improvement + url: https://github.com/sjackson0109/rdpwrap/discussions/new?category=ideas + about: Have an idea that is not ready to be a formal feature request? Start a discussion. + - name: General discussion + url: https://github.com/sjackson0109/rdpwrap/discussions/new?category=general + about: Anything that does not fit the other categories. + - name: Existing INI offset database + url: https://github.com/sjackson0109/rdpwrap/releases/latest + about: Check whether your Windows build is already covered before opening an INI request. + - name: Original project (stascorp, archived) + url: https://github.com/stascorp/rdpwrap + about: Historical reference only — no longer maintained. + - name: sergiye/rdpWrapper (C# rewrite) + url: https://github.com/sergiye/rdpWrapper + about: Alternative C# implementation with auto-offset generation. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..4db544a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,41 @@ +name: Feature Request +description: Suggest an improvement or new capability. +labels: [enhancement] +body: + - type: textarea + id: problem + attributes: + label: Problem or motivation + description: What problem does this feature solve? Who is affected? + placeholder: "At the moment there is no way to ..." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed solution + description: Describe the behaviour or change you would like to see. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Any other approaches you have thought about (optional). + + - type: dropdown + id: component + attributes: + label: Component this relates to + options: + - rdpwrap.dll (C++ wrapper library) + - RDPWInst / installer (Delphi) + - rdpWrapper GUI (sergiye C# app) + - rdpwrap.ini (offset database) + - CI/CD pipelines + - Documentation + - Other + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/ini_request.yml b/.github/ISSUE_TEMPLATE/ini_request.yml new file mode 100644 index 0000000..6cf1d70 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ini_request.yml @@ -0,0 +1,71 @@ +name: INI Update Request — New Windows Build +description: Your termsrv.dll version is not in the INI database and auto-generation failed. +labels: [ini-update] +body: + - type: markdown + attributes: + value: | + Use this template when RDPConf shows **Not supported (red)** and the automatic + offset-generation step in the installer could not resolve your build. + + If you have the technical skills, please consider following + [HOW-TO-ADD-NEW-WINDOWS-BUILDS.md](../docs/HOW-TO-ADD-NEW-WINDOWS-BUILDS.md) + and submitting a pull request instead. + + - type: input + id: termsrv_version + attributes: + label: termsrv.dll version + description: "Run: (Get-Item C:\\Windows\\System32\\termsrv.dll).VersionInfo.FileVersion" + placeholder: "10.0.26100.3915" + validations: + required: true + + - type: input + id: windows_version + attributes: + label: Windows version string + description: "Run: winver — paste the full string" + placeholder: "Windows 11 Version 24H2 (OS Build 26100.3915)" + validations: + required: true + + - type: dropdown + id: architecture + attributes: + label: System architecture + options: + - x64 (64-bit) + - x86 (32-bit) + - ARM64 + validations: + required: true + + - type: dropdown + id: auto_gen + attributes: + label: Did the auto-generation step run? + description: The installer prints a message about TryAutoGenerateOffsets during install or update. + options: + - "Yes — it ran but failed with an error" + - "Yes — it ran and reported success, but wrapper still shows Not supported" + - "No — it was skipped or I installed offline" + - Not sure + validations: + required: true + + - type: textarea + id: auto_gen_output + attributes: + label: Auto-generation output (if any) + description: Paste the console output from the installer relating to offset generation. + render: text + + - type: textarea + id: ini_section + attributes: + label: Generated INI section (if available) + description: | + If you ran RDPWrapOffsetFinder manually, paste the output here. + Run: .\RDPWrapOffsetFinder.exe C:\Windows\System32\termsrv.dll + render: ini diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d97f5ed --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,34 @@ +version: 2 + +updates: + # Keep GitHub Actions pinned to their latest minor/patch releases + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 10 + groups: + actions-minor: + patterns: ["*"] + + # Keep .NET SDK NuGet dependencies up to date (for src-csharp/) + - package-ecosystem: nuget + directory: /src-csharp + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 10 + + # Monitor git submodules for upstream releases + # Covers: src-csharp/RDPOffsetFinder (llccd/RDPWrapOffsetFinder) + # src-csharp/RDPOffsetFinder/zydis (zyantific/zydis) + # Note: gitsubmodule ecosystem is currently in Dependabot beta. + # Enable once the feature is available for the repository, or track + # submodule versions manually via the pinned SHA in .gitmodules. + - package-ecosystem: gitsubmodule + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 5 diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml new file mode 100644 index 0000000..0479973 --- /dev/null +++ b/.github/workflows/build-and-release.yml @@ -0,0 +1,782 @@ +name: Build and Release + +on: + push: + branches: [main, master] + paths: + - 'msi/rdpwrap.ini' + - 'msi/rdpwrap-arm-kb.ini' + - 'msi/**' + - 'src-x86-x64-Fusix/**' + - 'src-csharp/**' + workflow_dispatch: + inputs: + tag: + description: 'Release tag (e.g. v2026.4.2). Leave blank to auto-generate from date.' + required: false + default: '' + prerelease: + description: 'Mark as pre-release' + type: boolean + required: false + default: false + +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }} + cancel-in-progress: true + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +permissions: + contents: write + +# ──────────────────────────────────────────────────────────────────────────── +# Job dependency / parallelism map +# +# build-dll ───────────────► build-csharp ──────────► build-msi ──┐ +# build-offsetfinder ───────────────────────────────────────────► release +# download-sergiye ───────────────────────────────────────────► release +# build-dll ─┘ +# ──────────────────────────────────────────────────────────────────────────── + +jobs: + + # ── Job 1: Build rdpwrap.dll (x64, x86, ARM64) ──────────────────────────── + # No job dependencies — starts immediately. + build-dll: + name: Build rdpwrap DLL + runs-on: windows-2022 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v3 + + - name: Build rdpwrap.dll (x64, Win32, ARM64) + shell: pwsh + run: | + foreach ($platform in @('x64', 'Win32', 'ARM64')) { + msbuild src-x86-x64-Fusix/RDPWrap.vcxproj ` + /p:Configuration=Release ` + /p:Platform="$platform" ` + /p:PlatformToolset=v143 ` + /p:WindowsTargetPlatformVersion=10.0 ` + /v:minimal + } + Copy-Item src-x86-x64-Fusix/Release/x64/rdpwrap.dll .\rdpwrap_x64.dll + Copy-Item src-x86-x64-Fusix/Release/x86/rdpwrap.dll .\rdpwrap_x86.dll + Copy-Item src-x86-x64-Fusix/Release/arm64/rdpwrap.dll .\rdpwrap_arm64.dll + Write-Host "Built DLLs:" + Get-Item .\rdpwrap_x64.dll, .\rdpwrap_x86.dll, .\rdpwrap_arm64.dll | Format-Table Name, Length + + - name: Upload rdpwrap DLLs + uses: actions/upload-artifact@v4 + with: + name: rdpwrap-dlls + path: | + rdpwrap_x64.dll + rdpwrap_x86.dll + rdpwrap_arm64.dll + if-no-files-found: error + + + # ── Job 2: Build RDPWrapOffsetFinder (x64, x86) — parallel to build-dll ─── + # No job dependencies — starts immediately. + build-offsetfinder: + name: Build OffsetFinder + runs-on: windows-2022 + outputs: + finder_ver: ${{ steps.finder.outputs.finder_ver }} + + steps: + - name: Checkout repository (with submodules) + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v3 + + - name: Build RDPWrapOffsetFinder from submodule + id: finder + shell: pwsh + run: | + $version = (git -C src-csharp/RDPOffsetFinder describe --tags --always).Trim() + Write-Host "Submodule version: $version" + + foreach ($cfg in @( + @{ Platform = 'x64'; SlnPlatform = 'x64'; OutDir = 'x64/Release'; ZydisCfg = 'Release MD DLL'; ZydisBin = 'ReleaseX64'; Arch = 'x64' } + @{ Platform = 'Win32'; SlnPlatform = 'x86'; OutDir = 'Release'; ZydisCfg = 'Release MD DLL'; ZydisBin = 'ReleaseX86'; Arch = 'x86' } + )) { + # Build Zydis DLL + msbuild src-csharp/RDPOffsetFinder/zydis/msvc/zydis/Zydis.vcxproj ` + /p:Configuration="$($cfg.ZydisCfg)" ` + /p:Platform="$($cfg.Platform)" ` + /p:PlatformToolset=v143 ` + /v:minimal + + # Build via .sln so $(SolutionDir) resolves to the submodule root + # where zydis/ lives - vcxproj AdditionalIncludeDirectories and + # AdditionalDependencies both use $(SolutionDir)\zydis\... and + # fail with C1083 when the vcxproj is targeted directly. + # NB: the solution uses x86/x64 platform names (not Win32) - use SlnPlatform. + msbuild src-csharp/RDPOffsetFinder/RDPWrapOffsetFinder.sln ` + /t:RDPWrapOffsetFinder ` + /p:Configuration=Release ` + /p:Platform="$($cfg.SlnPlatform)" ` + /p:PlatformToolset=v143 ` + /v:minimal + + $arch = $cfg.Arch + # Win32 OutDir = Release\ (no platform prefix); x64 OutDir = x64\Release\ + $exeSrc = "src-csharp/RDPOffsetFinder/$($cfg.OutDir)/RDPWrapOffsetFinder.exe" + $dllSrc = "src-csharp/RDPOffsetFinder/zydis/msvc/bin/$($cfg.ZydisBin)/Zydis.dll" + Copy-Item $exeSrc ".\RDPWrapOffsetFinder_$arch.exe" + Copy-Item $dllSrc ".\Zydis_$arch.dll" + } + + Write-Host "Built finder tools (version $version):" + Get-Item .\RDPWrapOffsetFinder_*.exe, .\Zydis_*.dll | Format-Table Name, Length + + echo "finder_ver=$version" >> $env:GITHUB_OUTPUT + + - name: Upload OffsetFinder binaries + uses: actions/upload-artifact@v4 + with: + name: offsetfinder-binaries + path: | + RDPWrapOffsetFinder_x64.exe + RDPWrapOffsetFinder_x86.exe + Zydis_x64.dll + Zydis_x86.dll + if-no-files-found: error + + + # ── Job 3: Download rdpWrapper GUI from sergiye — parallel to build-dll ──── + # No job dependencies — starts immediately. + download-sergiye: + name: Download sergiye rdpWrapper + runs-on: windows-2022 + outputs: + wrapper_ver: ${{ steps.wrapper.outputs.wrapper_ver }} + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Download rdpWrapper (sergiye) + id: wrapper + shell: pwsh + run: | + $apiUrl = "https://api.github.com/repos/sergiye/rdpWrapper/releases/latest" + $release = Invoke-RestMethod -Uri $apiUrl -Headers @{ "User-Agent" = "rdpwrap-ci" } + + foreach ($arch in @('x64', 'x86')) { + $asset = $release.assets | + Where-Object { $_.name -eq "rdpWrapper_$arch.exe" } | + Select-Object -First 1 + if (-not $asset) { + throw "Could not find rdpWrapper_$arch.exe in sergiye release $($release.tag_name)" + } + Write-Host "Downloading $($asset.browser_download_url)" + Invoke-WebRequest -Uri $asset.browser_download_url -OutFile ".\rdpWrapper_$arch.exe" + } + + Write-Host "Wrapper exes:" + Get-Item .\rdpWrapper_x64.exe, .\rdpWrapper_x86.exe | Format-Table Name, Length + echo "wrapper_ver=$($release.tag_name)" >> $env:GITHUB_OUTPUT + + # ── SHA-256 audit log for third-party binaries ────────────────────────── + # Records the hash of every downloaded sergiye binary in the workflow log. + # This provides a tamper-evident paper trail without blocking the release. + - name: Audit SHA-256 of downloaded binaries + shell: pwsh + run: | + $files = Get-Item .\rdpWrapper_x64.exe, .\rdpWrapper_x86.exe + Write-Host "SHA-256 audit (third-party downloads from sergiye/rdpWrapper):" + foreach ($f in $files) { + $hash = (Get-FileHash $f.FullName -Algorithm SHA256).Hash + Write-Host " $($f.Name) $hash" + } + + # ── Verify hashes against pinned values in tools/sergiye-hashes.json ──── + # If the file contains a non-empty 'release' key, hashes must match exactly. + # If 'release' is empty this step is skipped (bootstrap scenario). + - name: Verify sergiye binary hashes + shell: pwsh + run: | + $pinFile = 'tools/sergiye-hashes.json' + $pin = Get-Content $pinFile -Raw | ConvertFrom-Json + if ([string]::IsNullOrEmpty($pin.release)) { + Write-Host "Hash pinning not yet configured (tools/sergiye-hashes.json 'release' is empty) — skipping." + Write-Host "To enable pinning: download the binaries, compute hashes with Get-FileHash, and update $pinFile." + } else { + Write-Host "Verifying against pinned release: $($pin.release)" + $pass = $true + foreach ($name in @('rdpWrapper_x64.exe', 'rdpWrapper_x86.exe')) { + $expected = $pin.$name + $actual = (Get-FileHash ".\$name" -Algorithm SHA256).Hash + if ($actual -ne $expected) { + Write-Error "Hash mismatch for $name!" + Write-Error " Expected: $expected" + Write-Error " Actual: $actual" + $pass = $false + } else { + Write-Host " $name OK ($actual)" + } + } + if (-not $pass) { throw "One or more sergiye binary hashes did not match the pinned values." } + } + + - name: Upload sergiye wrappers + uses: actions/upload-artifact@v4 + with: + name: sergiye-wrappers + path: | + rdpWrapper_x64.exe + rdpWrapper_x86.exe + if-no-files-found: error + + + # ── Job 4: Build C# tools (FD + SC) — waits for build-dll ──────────────── + # Waits for build-dll so the DLLs can be embedded into single-file EXEs. + build-csharp: + name: Build C# Tools + runs-on: windows-2022 + needs: [build-dll] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Download rdpwrap DLLs + uses: actions/download-artifact@v4 + with: + name: rdpwrap-dlls + path: . + + # Stage embedded resources for RDPWInst offline/bundled mode. + # RDPWInst.csproj embeds these files when present (Condition="Exists(...)"). + # Copying them here ensures the single-file EXE can install without network. + - name: Stage RDPWInst embedded resources + shell: pwsh + run: | + $res = 'src-csharp/RDPWInst/Resources' + New-Item -ItemType Directory -Path $res -Force | Out-Null + Copy-Item .\rdpwrap_x86.dll "$res\rdpw32.dll" -Force + Copy-Item .\rdpwrap_x64.dll "$res\rdpw64.dll" -Force + Copy-Item msi\rdpwrap.ini "$res\rdpwrap.ini" -Force + Copy-Item LICENSE "$res\license.txt" -Force + Write-Host "Staged resources:" + Get-ChildItem $res | Format-Table Name, Length + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.x' + + - name: Cache NuGet packages + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: nuget-${{ runner.os }}-${{ hashFiles('**/Directory.Build.props', '**/*.csproj') }} + restore-keys: | + nuget-${{ runner.os }}- + + # Compute version once so it's consistent across all publish and sign steps + - name: Get build version + id: build_ver + shell: pwsh + run: | + $v = Get-Date -Format "yyyy.M.d" + echo "version=$v" >> $env:GITHUB_OUTPUT + Write-Host "Build version: $v" + + # ── Build framework-dependent variants ────────────────────────────────── + - name: Publish C# tools (x64, x86, arm64) + shell: pwsh + env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + run: | + $projects = @('RDPWInst', 'RDPConf', 'RDPCheck') + $rids = [ordered]@{ x64 = 'win-x64'; x86 = 'win-x86'; arm64 = 'win-arm64' } + $ver = '${{ steps.build_ver.outputs.version }}' + foreach ($proj in $projects) { + foreach ($plat in $rids.Keys) { + $rid = $rids[$plat] + dotnet publish "src-csharp/$proj/$proj.csproj" ` + -c Release ` + -r $rid ` + -p:Platform=$plat ` + -p:PublishSingleFile=true ` + -p:SelfContained=false ` + -p:Version=$ver ` + -p:AssemblyVersion="$ver.0" ` + -p:FileVersion="$ver.0" ` + --output "dist_cs\$plat\$proj" + Copy-Item "dist_cs\$plat\$proj\$proj.exe" ".\${proj}_${plat}.exe" + } + } + Write-Host "C# tool executables:" + Get-Item .\RDPWInst_*.exe, .\RDPConf_*.exe, .\RDPCheck_*.exe | Format-Table Name, Length + + # ── Build self-contained variants (no .NET runtime required) ───────────── + # Self-contained exes are larger (~60 MB) but work without a .NET install. + # Suffixed with _sc to distinguish from the framework-dependent versions. + - name: Publish self-contained C# tools (x64, x86, arm64) + shell: pwsh + env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + run: | + $projects = @('RDPWInst', 'RDPConf', 'RDPCheck') + $rids = [ordered]@{ x64 = 'win-x64'; x86 = 'win-x86'; arm64 = 'win-arm64' } + $ver = '${{ steps.build_ver.outputs.version }}' + foreach ($proj in $projects) { + foreach ($plat in $rids.Keys) { + $rid = $rids[$plat] + dotnet publish "src-csharp/$proj/$proj.csproj" ` + -c Release ` + -r $rid ` + -p:Platform=$plat ` + -p:PublishSingleFile=true ` + -p:SelfContained=true ` + -p:Version=$ver ` + -p:AssemblyVersion="$ver.0" ` + -p:FileVersion="$ver.0" ` + --output "dist_cs_sc\$plat\$proj" + Copy-Item "dist_cs_sc\$plat\$proj\$proj.exe" ".\${proj}_${plat}_sc.exe" + } + } + Write-Host "Self-contained executables:" + Get-Item .\RDPWInst_*_sc.exe, .\RDPConf_*_sc.exe, .\RDPCheck_*_sc.exe | Format-Table Name, Length + + # ── Optional: code-sign all C# executables ────────────────────────────── + # Enable by setting repository variable USE_CERT_SIGNING=true and adding + # secrets CODESIGN_CERT_BASE64 (PFX as base64) and CODESIGN_CERT_PASSWORD. + - name: Sign C# executables + if: vars.USE_CERT_SIGNING == 'true' + env: + CODESIGN_CERT_BASE64: ${{ secrets.CODESIGN_CERT_BASE64 }} + CODESIGN_CERT_PASSWORD: ${{ secrets.CODESIGN_CERT_PASSWORD }} + shell: pwsh + run: | + $pfxPath = "$env:RUNNER_TEMP\codesign.pfx" + [IO.File]::WriteAllBytes($pfxPath, + [Convert]::FromBase64String($env:CODESIGN_CERT_BASE64)) + $signtool = (Resolve-Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\signtool.exe" | + Sort-Object | Select-Object -Last 1).Path + # Sign both framework-dependent and self-contained variants (glob picks up all _*.exe files) + $exes = Get-Item .\RDPWInst_*.exe, .\RDPConf_*.exe, .\RDPCheck_*.exe + foreach ($exe in $exes) { + & $signtool sign /fd SHA256 /f $pfxPath ` + /p $env:CODESIGN_CERT_PASSWORD ` + /tr http://timestamp.digicert.com /td SHA256 $exe.FullName + } + Remove-Item $pfxPath -Force + + - name: Upload C# tools + uses: actions/upload-artifact@v4 + with: + name: csharp-tools + path: | + RDPWInst_*.exe + RDPConf_*.exe + RDPCheck_*.exe + if-no-files-found: error + + + # ── Job 5: Build MSI packages — waits for build-csharp (implies build-dll) ─ + build-msi: + name: Build MSI Packages + runs-on: windows-2022 + needs: [build-csharp] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Download rdpwrap DLLs + uses: actions/download-artifact@v4 + with: + name: rdpwrap-dlls + path: . + + - name: Download C# tools + uses: actions/download-artifact@v4 + with: + name: csharp-tools + path: . + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.x' + + - name: Cache NuGet packages (WiX restore) + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: nuget-${{ runner.os }}-${{ hashFiles('msi/global.json', 'msi/*.wixproj') }} + restore-keys: | + nuget-${{ runner.os }}- + + # Get version (same formula as build-csharp for filename consistency) + - name: Get build version + id: build_ver + shell: pwsh + run: | + $v = Get-Date -Format "yyyy.M.d" + echo "version=$v" >> $env:GITHUB_OUTPUT + Write-Host "Build version: $v" + + # ── Build MSI installers (WiX v5, x64 / x86 / arm64) ────────────────── + - name: Build MSI packages + shell: pwsh + run: | + $ver = '${{ steps.build_ver.outputs.version }}' + # MSI ProductVersion requires major<256; strip century: "2026.4.2" -> "26.4.2" + $msiVer = $ver.Substring(2) + foreach ($arch in @('x64', 'x86', 'arm64')) { + # Stage arch-specific inputs next to the .wixproj + Copy-Item ".\rdpwrap_$arch.dll" "msi\rdpwrap_$arch.dll" -Force + Copy-Item ".\RDPWInst_$arch.exe" "msi\RDPWInst_$arch.exe" -Force + Copy-Item ".\RDPConf_$arch.exe" "msi\RDPConf_$arch.exe" -Force + Copy-Item ".\RDPCheck_$arch.exe" "msi\RDPCheck_$arch.exe" -Force + + dotnet build msi/RDPWInst.wixproj ` + -c Release ` + /p:Platform=$arch ` + /p:OutputName="RDPWrapper-$arch" ` + /p:PackageVersion=$msiVer ` + /p:OutputPath="$PWD/msi_out/$arch" + if ($LASTEXITCODE -ne 0) { throw "WiX build failed for $arch" } + + $msiSrc = Get-Item "msi_out\$arch\RDPWrapper-$arch.msi" -ErrorAction SilentlyContinue + if (-not $msiSrc) { + $msiSrc = Get-ChildItem "msi\bin" -Recurse -Filter "RDPWrapper-$arch.msi" | + Sort-Object LastWriteTime -Descending | Select-Object -First 1 + } + if (-not $msiSrc) { throw "Could not locate RDPWrapper-$arch.msi after WiX build" } + Copy-Item $msiSrc.FullName ".\RDPWrapper-${ver}-$arch.msi" + Write-Host "Produced: RDPWrapper-${ver}-$arch.msi ($([math]::Round($msiSrc.Length/1MB,1)) MB)" + } + Write-Host "MSI packages:" + Get-Item .\RDPWrapper-*-*.msi | Format-Table Name, Length + + # ── Optional: sign the MSI packages ──────────────────────────────────── + # Enable by setting repository variable USE_CERT_SIGNING=true and adding + # secrets CODESIGN_CERT_BASE64 (PFX as base64) and CODESIGN_CERT_PASSWORD. + - name: Sign MSI packages + if: vars.USE_CERT_SIGNING == 'true' + env: + CODESIGN_CERT_BASE64: ${{ secrets.CODESIGN_CERT_BASE64 }} + CODESIGN_CERT_PASSWORD: ${{ secrets.CODESIGN_CERT_PASSWORD }} + shell: pwsh + run: | + $pfxPath = "$env:RUNNER_TEMP\codesign.pfx" + [IO.File]::WriteAllBytes($pfxPath, + [Convert]::FromBase64String($env:CODESIGN_CERT_BASE64)) + $signtool = (Resolve-Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\signtool.exe" | + Sort-Object | Select-Object -Last 1).Path + foreach ($msi in (Get-Item .\RDPWrapper-*-*.msi)) { + & $signtool sign /fd SHA256 /f $pfxPath ` + /p $env:CODESIGN_CERT_PASSWORD ` + /tr http://timestamp.digicert.com /td SHA256 ` + $msi.FullName + } + Remove-Item $pfxPath -Force + + - name: Upload MSI packages + uses: actions/upload-artifact@v4 + with: + name: msi-packages + path: RDPWrapper-*-*.msi + if-no-files-found: error + + + # ── Job 6: Publish GitHub Release — waits for all build jobs ────────────── + release: + name: Publish Release + runs-on: windows-2022 + needs: [build-dll, build-csharp, build-offsetfinder, download-sergiye, build-msi] + # Attach to the 'release' GitHub Environment so repository admins can add + # required-reviewer gates in Settings → Environments → release. + # If the environment doesn't exist yet it will be created without gates. + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Download rdpwrap DLLs + uses: actions/download-artifact@v4 + with: + name: rdpwrap-dlls + path: . + + - name: Download C# tools + uses: actions/download-artifact@v4 + with: + name: csharp-tools + path: . + + - name: Download OffsetFinder binaries + uses: actions/download-artifact@v4 + with: + name: offsetfinder-binaries + path: . + + - name: Download sergiye wrappers + uses: actions/download-artifact@v4 + with: + name: sergiye-wrappers + path: . + + - name: Download MSI packages + uses: actions/download-artifact@v4 + with: + name: msi-packages + path: . + + - name: Verify all release assets are present + shell: pwsh + run: | + $required = @( + 'rdpwrap_x64.dll', 'rdpwrap_x86.dll', 'rdpwrap_arm64.dll', + 'RDPWInst_x64.exe', 'RDPWInst_x86.exe', 'RDPWInst_arm64.exe', + 'RDPConf_x64.exe', 'RDPConf_x86.exe', 'RDPConf_arm64.exe', + 'RDPCheck_x64.exe', 'RDPCheck_x86.exe', 'RDPCheck_arm64.exe', + 'RDPWrapOffsetFinder_x64.exe', 'RDPWrapOffsetFinder_x86.exe', + 'Zydis_x64.dll', 'Zydis_x86.dll', + 'rdpWrapper_x64.exe', 'rdpWrapper_x86.exe' + ) + $missing = $required | Where-Object { -not (Test-Path $_) } + if ($missing) { + throw "Missing required release assets: $($missing -join ', ')" + } + Write-Host "All required assets present." + Get-ChildItem *.exe, *.dll, *.msi | Format-Table Name, Length + + # ── Extract the date string used for tagging and the updated field ─────── + - name: Get release metadata + id: meta + shell: pwsh + run: | + $date = Get-Date -Format "yyyy.MM.dd.HHmm" + $stamp = Get-Date -Format "yyyy-MM-dd HH:mm UTC" + + # Pull the Updated= line out of the INI to surface in release notes + $iniContent = Get-Content msi/rdpwrap.ini -Raw + $iniDate = if ($iniContent -match 'Updated=([^\r\n]+)') { $Matches[1] } else { 'unknown' } + + $inputTag = '${{ inputs.tag }}'.Trim() + $tagName = if ($inputTag -ne '') { $inputTag } else { "ini-$date" } + $outputName = if ($inputTag -ne '') { "Release $inputTag" } else { "INI Update $date" } + + echo "date=$date" >> $env:GITHUB_OUTPUT + echo "stamp=$stamp" >> $env:GITHUB_OUTPUT + echo "inidate=$iniDate" >> $env:GITHUB_OUTPUT + echo "tag_name=$tagName" >> $env:GITHUB_OUTPUT + echo "release_name=$outputName" >> $env:GITHUB_OUTPUT + + # ── Validate the INI has required sections and mandatory per-version keys ─ + - name: Validate INI + shell: pwsh + run: | + $ini = Get-Content msi/rdpwrap.ini -Raw + $lines = Get-Content msi/rdpwrap.ini + + # 1) Check mandatory top-level sections exist + foreach ($section in @('[Main]', '[SLPolicy]', '[PatchCodes]')) { + if ($ini -notmatch [regex]::Escape($section)) { + throw "INI validation failed: missing required section $section" + } + } + + # 2) Parse every Windows-version section and verify it contains the + # mandatory keys LocalOnlyPatch and SLInitHook. + $sectionKeys = [System.Collections.Generic.Dictionary[string, System.Collections.Generic.List[string]]]::new() + $currentSection = $null + + foreach ($line in $lines) { + if ($line -match '^\[(\d[\d\.]+)\]') { + $currentSection = $Matches[1] + $sectionKeys[$currentSection] = [System.Collections.Generic.List[string]]::new() + } elseif ($null -ne $currentSection -and $line -match '^([A-Za-z][A-Za-z0-9_]*)[\s]*=') { + $sectionKeys[$currentSection].Add($Matches[1]) + } + } + + $mandatoryKeys = @('LocalOnlyPatch', 'SLInitHook') + $errors = [System.Collections.Generic.List[string]]::new() + + foreach ($sec in $sectionKeys.Keys) { + foreach ($key in $mandatoryKeys) { + if (-not $sectionKeys[$sec].Contains($key)) { + $errors.Add(" Section [$sec] is missing mandatory key: $key") + } + } + } + + if ($errors.Count -gt 0) { + Write-Error "INI mandatory-key check failed ($($errors.Count) issue(s)):" + $errors | ForEach-Object { Write-Error $_ } + throw "INI validation failed — see errors above." + } + + $sectionCount = $sectionKeys.Count + Write-Host "INI is valid. Windows-version sections: $sectionCount (all contain LocalOnlyPatch + SLInitHook)" + + # ── Auto-generate changelog from merged PRs since last release ─────────── + - name: Generate changelog + id: changelog + shell: pwsh + env: + GH_TOKEN: ${{ github.token }} + run: | + # Get the tag of the previous release so we can scope the PR list + $prevTag = (gh release list --limit 1 --json tagName --jq '.[0].tagName' 2>$null) ?? '' + if ($prevTag) { + Write-Host "Generating changelog since: $prevTag" + $since = gh release view $prevTag --json publishedAt --jq .publishedAt + $prs = gh pr list --state merged --base main --search "merged:>=$since" ` + --json number,title,author --limit 50 | ConvertFrom-Json + } else { + Write-Host "No previous release found; skipping per-PR changelog." + $prs = @() + } + if ($prs.Count -gt 0) { + $lines = $prs | ForEach-Object { "- #$($_.number) $($_.title) (@$($_.author.login))" } + $body = $lines -join "`n" + } else { + $body = "_No merged pull requests found since the previous release._" + } + # Write multi-line output safely + $delim = [guid]::NewGuid().ToString('N') + echo "prs<<$delim" >> $env:GITHUB_OUTPUT + echo $body >> $env:GITHUB_OUTPUT + echo $delim >> $env:GITHUB_OUTPUT + + # ── Assemble the three user-facing distribution bundles ────────────────── + - name: Create distribution bundles + shell: pwsh + run: | + # RDPWrapper.zip - complete install package (all arches, framework-dependent) + $d = ".\bundle_wrapper" + New-Item -ItemType Directory -Path $d -Force | Out-Null + Copy-Item .\rdpwrap_x64.dll "$d\rdpwrap_x64.dll" + Copy-Item .\rdpwrap_x86.dll "$d\rdpwrap_x86.dll" + Copy-Item .\rdpwrap_arm64.dll "$d\rdpwrap_arm64.dll" + Copy-Item .\rdpWrapper_x64.exe "$d\rdpWrapper_x64.exe" + Copy-Item .\rdpWrapper_x86.exe "$d\rdpWrapper_x86.exe" + # Framework-dependent C# tools (require .NET 10 Desktop Runtime) + foreach ($proj in @('RDPWInst', 'RDPConf', 'RDPCheck')) { + foreach ($arch in @('x64', 'x86', 'arm64')) { + $src = ".\${proj}_${arch}.exe" + if (Test-Path $src) { Copy-Item $src "$d\${proj}_${arch}.exe" } + } + } + Copy-Item msi\rdpwrap.ini "$d\rdpwrap.ini" + Compress-Archive -Path "$d\*" -DestinationPath ".\RDPWrapper.zip" -Force + Remove-Item $d -Recurse -Force + + # RDPWrapper-SelfContained.zip - apps bundled with .NET runtime (~60 MB each) + $sc = ".\bundle_sc" + New-Item -ItemType Directory -Path $sc -Force | Out-Null + foreach ($proj in @('RDPWInst', 'RDPConf', 'RDPCheck')) { + foreach ($arch in @('x64', 'x86', 'arm64')) { + $src = ".\${proj}_${arch}_sc.exe" + if (Test-Path $src) { Copy-Item $src "$sc\${proj}_${arch}_sc.exe" } + } + } + Copy-Item msi\rdpwrap.ini "$sc\rdpwrap.ini" + Compress-Archive -Path "$sc\*" -DestinationPath ".\RDPWrapper-SelfContained.zip" -Force + Remove-Item $sc -Recurse -Force + + # RDPWrapOffsetFinder.zip - offset finder with per-arch subfolders + $f = ".\bundle_finder" + foreach ($arch in @('x64', 'x86')) { + $dir = "$f\$arch" + New-Item -ItemType Directory -Path $dir -Force | Out-Null + Copy-Item ".\RDPWrapOffsetFinder_$arch.exe" "$dir\RDPWrapOffsetFinder.exe" + Copy-Item ".\Zydis_$arch.dll" "$dir\Zydis.dll" + } + Compress-Archive -Path "$f\*" -DestinationPath ".\RDPWrapOffsetFinder.zip" -Force + Remove-Item $f -Recurse -Force + + Write-Host "Distribution bundles:" + Get-Item .\RDPWrapper.zip, .\RDPWrapper-SelfContained.zip, .\RDPWrapOffsetFinder.zip | Format-Table Name, Length + + # ── Create/update a versioned GitHub Release with all assets ───────────── + - name: Publish release + # Pinned to v2 tag SHA for supply-chain safety. + # Bump this SHA when upgrading: https://github.com/softprops/action-gh-release/releases + uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 + with: + tag_name: "${{ steps.meta.outputs.tag_name }}" + name: "${{ steps.meta.outputs.release_name }}" + prerelease: ${{ inputs.prerelease || false }} + make_latest: true + body: | + ## RDP Wrapper - Automated Release + + | Field | Value | + |---|---| + | INI `Updated` date | `${{ steps.meta.outputs.inidate }}` | + | Published | ${{ steps.meta.outputs.stamp }} | + | rdpWrapper (sergiye) | ${{ needs.download-sergiye.outputs.wrapper_ver }} | + | RDPWrapOffsetFinder (llccd) | ${{ needs.build-offsetfinder.outputs.finder_ver }} | + + > **Framework-dependent tools** (default) require **.NET 10 Desktop Runtime** on the target machine. + > Download: https://dotnet.microsoft.com/download/dotnet/10.0 + > For environments without a runtime install, use the `*_sc.exe` files from `RDPWrapper-SelfContained.zip`. + + ### Downloads + + | File | Contents | Use | + |---|---|---| + | `RDPWrapper.zip` | rdpwrap DLLs, C# tools (x64/x86/arm64), rdpWrapper GUI, rdpwrap.ini | **Main install package** — extract and run `RDPWInst_x64.exe -i -o` (or matching arch) | + | `RDPWrapper-SelfContained.zip` | Same C# tools bundled with .NET runtime (no separate runtime install needed) | Use when .NET 10 Desktop Runtime cannot be deployed | + | `RDPWrapper--x64.msi` / `x86` / `arm64` | Windows Installer packages — GUI-friendly, self-registering uninstall | Preferred for managed/enterprise deployments | + | `RDPWrapOffsetFinder.zip` | RDPWrapOffsetFinder.exe + Zydis.dll for x64 and x86 | Generate offsets for an unknown termsrv.dll version manually | + + ### Merged pull requests + + ${{ steps.changelog.outputs.prs }} + + ### Individual loose files (used by the automated installer) + + | File | Purpose | + |---|---| + | `rdpwrap.ini` | Offset database fetched automatically by the installer | + | `RDPWrapOffsetFinder_x64.exe` / `Zydis_x64.dll` | Loose x64 binaries downloaded by `TryAutoGenerateOffsets` | + | `RDPWrapOffsetFinder_x86.exe` / `Zydis_x86.dll` | Loose x86 binaries downloaded by `TryAutoGenerateOffsets` | + files: | + RDPWrapper.zip + RDPWrapper-SelfContained.zip + RDPWrapper-*-x64.msi + RDPWrapper-*-x86.msi + RDPWrapper-*-arm64.msi + RDPWrapOffsetFinder.zip + msi/rdpwrap.ini + msi/rdpwrap-arm-kb.ini + rdpwrap_x64.dll + rdpwrap_x86.dll + rdpwrap_arm64.dll + RDPWInst_x64.exe + RDPWInst_x86.exe + RDPWInst_arm64.exe + RDPConf_x64.exe + RDPConf_x86.exe + RDPConf_arm64.exe + RDPCheck_x64.exe + RDPCheck_x86.exe + RDPCheck_arm64.exe + RDPWrapOffsetFinder_x64.exe + RDPWrapOffsetFinder_x86.exe + Zydis_x64.dll + Zydis_x86.dll diff --git a/.github/workflows/build-cpp.yml b/.github/workflows/build-cpp.yml new file mode 100644 index 0000000..e0c2d36 --- /dev/null +++ b/.github/workflows/build-cpp.yml @@ -0,0 +1,63 @@ +name: Build C++ DLL + +# Trigger on: +# - PRs targeting main/master that touch C++ source (compile check before merge) +# - Version tag pushes (e.g. v1.7.0) +# - Manual dispatch +on: + pull_request: + branches: [main, master] + push: + tags: + - 'v*' + workflow_dispatch: + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +permissions: + contents: write + +jobs: + # ── Build x64 and Win32 release DLLs ───────────────────────────────────────── + build: + runs-on: windows-2022 + strategy: + matrix: + include: + - platform: x64 + msbuild_platform: x64 + - platform: x86 + msbuild_platform: Win32 + - platform: arm64 + msbuild_platform: ARM64 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v3 + + # Override the v120 platform toolset with the VS 2022 toolset (v143). + # The rdpwrap C++ source is standard Win32 API code and compiles cleanly + # with any modern MSVC version. + - name: Build rdpwrap.dll (${{ matrix.platform }}) + working-directory: src-x86-x64-Fusix + run: | + msbuild RDPWrap.vcxproj ` + /p:Configuration=Release ` + /p:Platform="${{ matrix.msbuild_platform }}" ` + /p:PlatformToolset=v143 ` + /p:WindowsTargetPlatformVersion=10.0 + + - name: Upload ${{ matrix.platform }} artifact + uses: actions/upload-artifact@v4 + with: + name: rdpwrap-dll-${{ matrix.platform }} + path: src-x86-x64-Fusix/Release/${{ matrix.platform }}/rdpwrap.dll + if-no-files-found: error + + # NOTE: Full GitHub Releases (including rdpwrap DLLs) are published by build-and-release.yml. + # This workflow stops at the artifact upload step so that partial releases are never + # created on tag pushes. Run build-and-release.yml to produce the canonical release. diff --git a/.github/workflows/build-csharp.yml b/.github/workflows/build-csharp.yml new file mode 100644 index 0000000..1d0d5e4 --- /dev/null +++ b/.github/workflows/build-csharp.yml @@ -0,0 +1,139 @@ +name: Build C# Tools + +# Trigger on: +# - PRs targeting main/master that touch C# source (compile check before merge) +# - Version tag pushes (e.g. v1.7.0) +# - Manual dispatch +# Produces self-contained, single-file RDPWInst / RDPConf / RDPCheck +# executables for x64 and x86. +on: + pull_request: + branches: [main, master] + push: + tags: + - 'v*' + workflow_dispatch: + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + +permissions: + contents: write + +jobs: + # ── Publish self-contained executables ──────────────────────────────────────── + build: + runs-on: windows-2022 + strategy: + matrix: + platform: [x64, x86, arm64] + include: + - platform: x64 + rid: win-x64 + - platform: x86 + rid: win-x86 + - platform: arm64 + rid: win-arm64 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.x' + + - name: Cache NuGet packages + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: nuget-${{ runner.os }}-${{ hashFiles('**/Directory.Build.props', '**/*.csproj') }} + restore-keys: | + nuget-${{ runner.os }}- + + - name: Publish RDPWInst (${{ matrix.platform }}) + run: | + dotnet publish src-csharp/RDPWInst/RDPWInst.csproj ` + -c Release ` + -r ${{ matrix.rid }} ` + -p:Platform=${{ matrix.platform }} ` + -p:PublishSingleFile=true ` + -p:SelfContained=false ` + --output dist/${{ matrix.platform }}/RDPWInst + + - name: Publish RDPConf (${{ matrix.platform }}) + run: | + dotnet publish src-csharp/RDPConf/RDPConf.csproj ` + -c Release ` + -r ${{ matrix.rid }} ` + -p:Platform=${{ matrix.platform }} ` + -p:PublishSingleFile=true ` + -p:SelfContained=false ` + --output dist/${{ matrix.platform }}/RDPConf + + - name: Publish RDPCheck (${{ matrix.platform }}) + run: | + dotnet publish src-csharp/RDPCheck/RDPCheck.csproj ` + -c Release ` + -r ${{ matrix.rid }} ` + -p:Platform=${{ matrix.platform }} ` + -p:PublishSingleFile=true ` + -p:SelfContained=false ` + --output dist/${{ matrix.platform }}/RDPCheck + + # ── Optional: code-sign all three executables ───────────────────────────── + # Enable by setting repository variable USE_CERT_SIGNING=true and adding + # secrets CODESIGN_CERT_BASE64 (PFX as base64) and CODESIGN_CERT_PASSWORD. + - name: Sign executables (${{ matrix.platform }}) + if: vars.USE_CERT_SIGNING == 'true' + env: + CODESIGN_CERT_BASE64: ${{ secrets.CODESIGN_CERT_BASE64 }} + CODESIGN_CERT_PASSWORD: ${{ secrets.CODESIGN_CERT_PASSWORD }} + shell: pwsh + run: | + $pfxPath = "$env:RUNNER_TEMP\codesign.pfx" + [IO.File]::WriteAllBytes($pfxPath, + [Convert]::FromBase64String($env:CODESIGN_CERT_BASE64)) + + $exes = @( + "dist\${{ matrix.platform }}\RDPWInst\RDPWInst.exe", + "dist\${{ matrix.platform }}\RDPConf\RDPConf.exe", + "dist\${{ matrix.platform }}\RDPCheck\RDPCheck.exe" + ) + + $signtool = (Resolve-Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\signtool.exe" | + Sort-Object | Select-Object -Last 1).Path + foreach ($exe in $exes) { + & $signtool sign ` + /fd SHA256 ` + /f $pfxPath ` + /p $env:CODESIGN_CERT_PASSWORD ` + /tr http://timestamp.digicert.com ` + /td SHA256 ` + $exe + } + Remove-Item $pfxPath -Force + + - name: Collect artifacts (${{ matrix.platform }}) + run: | + Copy-Item dist/${{ matrix.platform }}/RDPWInst/RDPWInst.exe RDPWInst_${{ matrix.platform }}.exe + Copy-Item dist/${{ matrix.platform }}/RDPConf/RDPConf.exe RDPConf_${{ matrix.platform }}.exe + Copy-Item dist/${{ matrix.platform }}/RDPCheck/RDPCheck.exe RDPCheck_${{ matrix.platform }}.exe + + - name: Upload ${{ matrix.platform }} artifacts + uses: actions/upload-artifact@v4 + with: + name: csharp-tools-${{ matrix.platform }} + path: | + RDPWInst_${{ matrix.platform }}.exe + RDPConf_${{ matrix.platform }}.exe + RDPCheck_${{ matrix.platform }}.exe + if-no-files-found: error + + # NOTE: Full GitHub Releases (including C# tools) are published by publish-ini.yml. + # This workflow intentionally stops at the artifact upload step so that partial + # releases are never created on the tag. Run publish-ini.yml manually or let it + # fire from an INI push to produce the canonical release. diff --git a/.github/workflows/build-msi-check.yml b/.github/workflows/build-msi-check.yml new file mode 100644 index 0000000..1fd943a --- /dev/null +++ b/.github/workflows/build-msi-check.yml @@ -0,0 +1,70 @@ +name: Build MSI Check + +# Lightweight PR check that validates msi/RDPWInst.wxs compiles cleanly. +# We stub the binary inputs (DLL/EXE) with placeholder files so WiX can +# validate the package structure without needing a full C++ / C# build. +# For the real release build with actual binaries, see build-and-release.yml. +on: + pull_request: + branches: [main, master] + workflow_dispatch: + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +permissions: + contents: read + +jobs: + wix-check: + runs-on: windows-2022 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.x' + + - name: Cache NuGet packages + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: nuget-${{ runner.os }}-${{ hashFiles('**/Directory.Build.props', '**/*.csproj', '**/global.json') }} + restore-keys: | + nuget-${{ runner.os }}- + + # Create minimal placeholder files so WiX can resolve all File references + # in RDPWInst.wxs without requiring an actual C++ or C# build. + # WiX v5 harvests file size at build time but does not validate binary content. + - name: Create placeholder binary inputs + shell: pwsh + run: | + $arch = 'x64' + # Placeholder DLL and EXEs — WiX only needs the files to exist + foreach ($name in @("rdpwrap_$arch.dll", "RDPWInst_$arch.exe", "RDPConf_$arch.exe", "RDPCheck_$arch.exe")) { + $dest = "msi\$name" + if (-not (Test-Path $dest)) { + [System.IO.File]::WriteAllBytes($dest, [byte[]](0x4D, 0x5A)) # MZ stub + Write-Host "Created stub: $dest" + } + } + Write-Host "Placeholder files in msi\:" + Get-ChildItem msi\ -File | Format-Table Name, Length + + # Build only the x64 MSI — enough to validate WXS structure and WiX rules. + # A failure here means a real WiX schema/syntax/reference error that would + # also break the release build. + - name: Build MSI (x64 WiX check) + shell: pwsh + run: | + dotnet build msi/RDPWInst.wixproj ` + -c Release ` + /p:Platform=x64 ` + /p:PackageVersion=0.0.1 ` + /p:OutputPath="$PWD/msi_check_out/x64" + if ($LASTEXITCODE -ne 0) { throw "WiX build failed — review errors above" } + Write-Host "WiX check passed." + Get-ChildItem msi_check_out -Recurse -Filter "*.msi" | Format-Table FullName, Length diff --git a/.github/workflows/build-offsetfinder.yml b/.github/workflows/build-offsetfinder.yml new file mode 100644 index 0000000..6dbd10c --- /dev/null +++ b/.github/workflows/build-offsetfinder.yml @@ -0,0 +1,97 @@ +name: Build RDPWrapOffsetFinder + +# Trigger on: +# - PRs targeting main/master that touch the OffsetFinder submodule or Zydis +# - Version tag pushes (e.g. v1.7.0) +# - Manual dispatch +on: + pull_request: + branches: [main, master] + push: + tags: + - 'v*' + workflow_dispatch: + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +permissions: + contents: write + +jobs: + # ── Build x64 and Win32 release exes ───────────────────────────────────────── + build: + runs-on: windows-2022 + strategy: + matrix: + include: + - platform: x64 + sln_platform: x64 + zydis_cfg: "Release MD DLL" + zydis_bin: ReleaseX64 + out_dir: x64/Release + - platform: Win32 + sln_platform: x86 + zydis_cfg: "Release MD DLL" + zydis_bin: ReleaseX86 + out_dir: Release + + steps: + - name: Checkout repository (with submodules) + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v3 + + # Build Zydis as a shared DLL so we can ship Zydis.dll alongside the exe + - name: Build Zydis (${{ matrix.platform }}) + working-directory: src-csharp/RDPOffsetFinder + run: | + msbuild zydis\msvc\zydis\Zydis.vcxproj ` + /p:Configuration="${{ matrix.zydis_cfg }}" ` + /p:Platform="${{ matrix.platform }}" ` + /p:PlatformToolset=v143 ` + /v:minimal + + # Build via .sln so $(SolutionDir) resolves to the submodule root where + # AdditionalIncludeDirectories and AdditionalDependencies reference zydis/ + # NB: the solution uses x86/x64 platform names (not Win32) - use sln_platform. + - name: Build RDPWrapOffsetFinder (${{ matrix.platform }}) + working-directory: src-csharp/RDPOffsetFinder + run: | + msbuild RDPWrapOffsetFinder.sln ` + /t:RDPWrapOffsetFinder ` + /p:Configuration=Release ` + /p:Platform="${{ matrix.sln_platform }}" ` + /p:PlatformToolset=v143 ` + /v:minimal + + - name: Collect outputs + shell: pwsh + run: | + $arch = if ("${{ matrix.platform }}" -eq "Win32") { "x86" } else { "x64" } + $root = "src-csharp/RDPOffsetFinder" + # Win32 OutDir = Release\ (no platform prefix); x64 OutDir = x64\Release\ + $exe = "$root/${{ matrix.out_dir }}/RDPWrapOffsetFinder.exe" + $dll = "$root/zydis/msvc/bin/${{ matrix.zydis_bin }}/Zydis.dll" + + Write-Host "Exe: $(Get-Item $exe | Select-Object -Exp Length) bytes" + Write-Host "Dll: $(Get-Item $dll | Select-Object -Exp Length) bytes" + + Copy-Item $exe ".\RDPWrapOffsetFinder_$arch.exe" + Copy-Item $dll ".\Zydis_$arch.dll" + + - name: Upload ${{ matrix.platform }} artifact + uses: actions/upload-artifact@v4 + with: + name: finder-${{ matrix.platform }} + path: | + RDPWrapOffsetFinder_*.exe + Zydis_*.dll + if-no-files-found: error + + # NOTE: Full GitHub Releases (including OffsetFinder binaries) are published by build-and-release.yml. + # This workflow stops at the artifact upload step so that partial releases are never + # created on tag pushes. Run build-and-release.yml to produce the canonical release. diff --git a/.gitignore b/.gitignore index 56e5ba3..10e5e1a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ __history/ *.~* +# Local build output (produced by local builds; not committed) +build/ + # Compiled binaries *.dcu *.exe @@ -15,3 +18,24 @@ __history/ # MSI local stuff *.wixobj *.wixpdb +msi/bin/ +msi/obj/ +msi_out/ + +# Staged CI inputs inside msi/ (DLLs and EXEs copied there before WiX runs; +# generated at build time — not source files) +msi/*.dll +msi/*.exe + +# C# build outputs +src-csharp/**/bin/ +src-csharp/**/obj/ +# Staged resource: copied from msi/rdpwrap.ini at build time, not source +src-csharp/RDPWInst/Resources/rdpwrap.ini +src-csharp/RDPWInst/Resources/rdpw32.dll +src-csharp/RDPWInst/Resources/rdpw64.dll +src-csharp/RDPWInst/Resources/license.txt + +# C++ build outputs +src-x86-x64-Fusix/Release/ +src-x86-x64-Fusix/obj/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c7ed6aa --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "src-csharp/RDPOffsetFinder"] + path = src-csharp/RDPOffsetFinder + url = https://github.com/llccd/RDPWrapOffsetFinder + shallow = true diff --git a/README.md b/README.md index 837e679..0cd83fb 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,37 @@ -# RDP Wrapper Library by Stas'M +# RDP Wrapper Library -[![Telegram](https://img.shields.io/badge/chat-Telegram-blue.svg)](https://t.me/rdpwrap) -![Environment](https://img.shields.io/badge/Windows-Vista,%207,%208,%2010-brightgreen.svg) -[![Release](https://img.shields.io/github/release/stascorp/rdpwrap.svg)](https://github.com/stascorp/rdpwrap/releases) -![License](https://img.shields.io/github/license/stascorp/rdpwrap.svg) -![Downloads](https://img.shields.io/github/downloads/stascorp/rdpwrap/latest/total.svg) -![TotalDownloads](https://img.shields.io/github/downloads/stascorp/rdpwrap/total.svg) +> **Maintained fork** by [@sjackson0109](https://github.com/sjackson0109) — based on the original work by [Stas'M / binarymaster](https://github.com/stascorp/rdpwrap). + +![Environment](https://img.shields.io/badge/Windows-Vista%20through%2011-brightgreen.svg) +[![Release](https://img.shields.io/github/release/sjackson0109/rdpwrap.svg)](https://github.com/sjackson0109/rdpwrap/releases) +[![Build and Release](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-and-release.yml/badge.svg)](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-and-release.yml) +[![Build C++ DLL](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-cpp.yml/badge.svg)](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-cpp.yml) +[![Build C# tools](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-csharp.yml/badge.svg)](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-csharp.yml) +[![Build OffsetFinder](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-offsetfinder.yml/badge.svg)](https://github.com/sjackson0109/rdpwrap/actions/workflows/build-offsetfinder.yml) +![License](https://img.shields.io/github/license/sjackson0109/rdpwrap.svg) +![Downloads](https://img.shields.io/github/downloads/sjackson0109/rdpwrap/latest/total.svg) +![TotalDownloads](https://img.shields.io/github/downloads/sjackson0109/rdpwrap/total.svg) The goal of this project is to enable Remote Desktop Host support and concurrent RDP sessions on reduced functionality systems for home usage. RDP Wrapper works as a layer between Service Control Manager and Terminal Services, so the original termsrv.dll file remains untouched. Also this method is very strong against Windows Update. -[pVistaST]: http://stascorp.com/images/rdpwrap/pVistaST.jpg -[pVistaHB]: http://stascorp.com/images/rdpwrap/pVistaHB.jpg -[pWin7ST]: http://stascorp.com/images/rdpwrap/pWin7ST.jpg -[pWin7HB]: http://stascorp.com/images/rdpwrap/pWin7HB.jpg -[pWin8DP]: http://stascorp.com/images/rdpwrap/pWin8DP.jpg -[pWin8CP]: http://stascorp.com/images/rdpwrap/pWin8CP.jpg -[pWin8RP]: http://stascorp.com/images/rdpwrap/pWin8RP.jpg -[pWin8]: http://stascorp.com/images/rdpwrap/pWin8.jpg -[pWin81P]: http://stascorp.com/images/rdpwrap/pWin81P.jpg -[pWin81]: http://stascorp.com/images/rdpwrap/pWin81.jpg -[pWin10TP]: http://stascorp.com/images/rdpwrap/pWin10TP.jpg -[pWin10PTP]: http://stascorp.com/images/rdpwrap/pWin10PTP.jpg -[pWin10]: http://stascorp.com/images/rdpwrap/pWin10.jpg - -[fVistaST]: http://stascorp.com/images/rdpwrap/VistaST.png -[fVistaHB]: http://stascorp.com/images/rdpwrap/VistaHB.png -[fWin7ST]: http://stascorp.com/images/rdpwrap/Win7ST.png -[fWin7HB]: http://stascorp.com/images/rdpwrap/Win7HB.png -[fWin8DP]: http://stascorp.com/images/rdpwrap/Win8DP.png -[fWin8CP]: http://stascorp.com/images/rdpwrap/Win8CP.png -[fWin8RP]: http://stascorp.com/images/rdpwrap/Win8RP.png -[fWin8]: http://stascorp.com/images/rdpwrap/Win8.png -[fWin81P]: http://stascorp.com/images/rdpwrap/Win81P.png -[fWin81]: http://stascorp.com/images/rdpwrap/Win81.png -[fWin10TP]: http://stascorp.com/images/rdpwrap/Win10TP.png -[fWin10PTP]: http://stascorp.com/images/rdpwrap/Win10PTP.png -[fWin10]: http://stascorp.com/images/rdpwrap/Win10.png - -| NT Version | Screenshots | -| ------------- | ----------- | -| Windows Vista | [![Windows Vista Starter][pVistaST]][fVistaST] [![Windows Vista Home Basic][pVistaHB]][fVistaHB] | -| Windows 7 | [![Windows 7 Starter][pWin7ST]][fWin7ST] [![Windows 7 Home Basic][pWin7HB]][fWin7HB] | -| Windows 8 | [![Windows 8 Developer Preview][pWin8DP]][fWin8DP] [![Windows 8 Consumer Preview][pWin8CP]][fWin8CP] [![Windows 8 Release Preview][pWin8RP]][fWin8RP] [![Windows 8][pWin8]][fWin8] | -| Windows 8.1 | [![Windows 8.1 Preview][pWin81P]][fWin81P] [![Windows 8.1][pWin81]][fWin81] | -| Windows 10 | [![Windows 10 Technical Preview][pWin10TP]][fWin10TP] [![Windows 10 Pro Technical Preview][pWin10PTP]][fWin10PTP] [![Windows 10][pWin10]][fWin10] | +> **Historical screenshots** (Vista / 7 / 8 / 10 from the original Stas'M project) are archived at: +> https://web.archive.org/web/2015*/http://stascorp.com/images/rdpwrap/* + +### Screenshots + +> Screenshots are captured on Windows 11 after a successful install. +> Source files live in [`docs/images/`](docs/images/) — see the [capture guide](docs/images/README.md) if you want to contribute updated screenshots. + +| RDPConf — configuration | RDPCheck — supported | RDPCheck — warning | +|:---:|:---:|:---:| +| ![RDPConf configuration window](docs/images/RDPWrapperConfig.png) | ![RDPCheck showing Supported](docs/images/RDPWrapperCheck.png) | ![RDPCheck showing Warning](docs/images/RDPWrapperCheckWarning.png) | + +| MSI Installer — welcome | MSI Installer — complete | +|:---:|:---:| +| ![MSI installer welcome screen](docs/images/RDPWrapperMSI1.png) | ![MSI installer completion screen](docs/images/RDPWrapperMSI2.png) | + --- [WinPPE]: http://forums.mydigitallife.info/threads/39411-Windows-Product-Policy-Editor @@ -64,21 +50,86 @@ It's recommended to have original termsrv.dll file with the RDP Wrapper installa - Windows 2000, XP and Server 2003 will not be supported ### Key features: -- RDP host server on any Windows edition beginning from Vista +- RDP host server on any Windows edition beginning from Vista through Windows 11 - Console and remote sessions at the same time - Using the same user simultaneously for local and remote logon (see configuration app) - Up to [15 concurrent sessions](https://github.com/stascorp/rdpwrap/issues/192) (the actual limitation depends on your hardware and OS version) - Console and RDP session shadowing (using [Task Manager in Windows 7](http://cdn.freshdesk.com/data/helpdesk/attachments/production/1009641577/original/remote_control.png?1413476051) and lower, and [Remote Desktop Connection in Windows 8](http://woshub.com/rds-shadow-how-to-connect-to-a-user-session-in-windows-server-2012-r2/) and higher) - Full [multi-monitor support](https://github.com/stascorp/rdpwrap/issues/163) for RDP host -- ...and if you find a new feature not listed here, [tell us](https://github.com/stascorp/rdpwrap/issues/new) ;) +- **Automatic INI updates** — the installer fetches the latest `rdpwrap.ini` directly from [GitHub Releases](https://github.com/sjackson0109/rdpwrap/releases/latest), published automatically by CI/CD on every change +- **Auto-generation of offsets for unknown builds** — if your `termsrv.dll` version is not yet in the INI, the installer downloads [RDPWrapOffsetFinder](https://github.com/llccd/RDPWrapOffsetFinder) and generates the missing section on-the-fly (inspired by [sergiye/rdpWrapper](https://github.com/sergiye/rdpWrapper)) +- ...and if you find a new feature not listed here, [tell us](https://github.com/sjackson0109/rdpwrap/issues/new) ;) ### Porting to other platforms: - **ARM** for Windows RT (see links below) - **IA-64** for Itanium-based Windows Server? *Well, I have no idea* :) +### Repository structure: + +``` +├── msi/ # WiX v5 MSI project + INI offset databases (rdpwrap.ini, rdpwrap-arm-kb.ini) +├── docs/ # Developer documentation +├── src-x86-x64-Fusix/ # C++ — core rdpwrap.dll (native Win32, MSVC) +└── src-csharp/ # C# .NET 10 — all management-plane tools + ├── Directory.Build.props # Shared build settings (framework, author metadata) + ├── RDPWrap.sln # Visual Studio solution + ├── RDPWrap/ # Shared helper library (P/Invoke, registry, service helpers) + ├── RDPWInst/ # Command-line installer / uninstaller + ├── RDPConf/ # WinForms configuration GUI + ├── RDPCheck/ # WinForms RDP loopback tester + └── RDPOffsetFinder/ # Git submodule — llccd/RDPWrapOffsetFinder (C++) + └── zydis/ # Git submodule — zyantific/zydis disassembler +``` + ### Building the binaries: -- **x86 Delphi version** can be built with *Embarcadero RAD Studio 2010* -- **x86/x64 C++ version** can be built with *Microsoft Visual Studio 2013* + +#### Prerequisites +- **.NET SDK 10** — all C# tools (`src-csharp/`) + - Download: https://dotnet.microsoft.com/download/dotnet/10.0 +- **Visual Studio 2022 / MSVC Build Tools v143** — two C++ components: + - `src-x86-x64-Fusix/` — core `rdpwrap.dll` + - `src-csharp/RDPOffsetFinder/` — offset finder (pulled via git submodule) + +#### Clone with submodules +```powershell +git clone --recurse-submodules https://github.com/sjackson0109/rdpwrap.git +# or if already cloned: +git submodule update --init --recursive +``` + +#### Build C# tools locally +```powershell +# Debug build (both platforms) +dotnet build src-csharp/RDPWrap.sln -p:Platform=x64 +dotnet build src-csharp/RDPWrap.sln -p:Platform=x86 + +# Release publish — single-file EXE (requires .NET 10 Desktop Runtime on target) +dotnet publish src-csharp/RDPWInst/RDPWInst.csproj -c Release -r win-x64 -p:PublishSingleFile=true -p:SelfContained=false +dotnet publish src-csharp/RDPConf/RDPConf.csproj -c Release -r win-x64 -p:PublishSingleFile=true -p:SelfContained=false +dotnet publish src-csharp/RDPCheck/RDPCheck.csproj -c Release -r win-x64 -p:PublishSingleFile=true -p:SelfContained=false +``` + +#### Build `rdpwrap.dll` locally +```powershell +msbuild src-x86-x64-Fusix/RDPWrap.vcxproj /p:Configuration=Release /p:Platform=x64 /p:PlatformToolset=v143 +``` + +#### Build `RDPWrapOffsetFinder` locally +```powershell +# Build Zydis DLL first +msbuild src-csharp/RDPOffsetFinder/zydis/msvc/zydis/Zydis.vcxproj /p:Configuration="Release MD DLL" /p:Platform=x64 /p:PlatformToolset=v143 +# Then build the offset finder +msbuild src-csharp/RDPOffsetFinder/RDPWrapOffsetFinder/RDPWrapOffsetFinder.vcxproj /p:Configuration=Release /p:Platform=x64 /p:PlatformToolset=v143 +``` + +### CI/CD Pipelines: + +| Workflow | Trigger | Output | +|---|---|---| +| [build-and-release.yml](.github/workflows/build-and-release.yml) | Push to `main`/`master` touching any source, INI, or the workflow file itself; or manual | **Canonical GitHub Release** — DLLs (x64/x86/arm64), C# tools, MSI packages, self-contained bundles, OffsetFinder, `rdpwrap.ini`, `rdpwrap-arm-kb.ini` | +| [build-csharp.yml](.github/workflows/build-csharp.yml) | PR to `main`/`master` touching `src-csharp/**`; version tag push (`v*`); or manual | PR compile check + artifact upload (no release) — use `build-and-release.yml` for a full release | +| [build-cpp.yml](.github/workflows/build-cpp.yml) | PR to `main`/`master` touching `src-x86-x64-Fusix/**`; version tag push (`v*`); or manual | PR compile check + artifact upload (no release) — use `build-and-release.yml` for a full release | +| [build-offsetfinder.yml](.github/workflows/build-offsetfinder.yml) | PR to `main`/`master` touching `src-csharp/RDPOffsetFinder/**`; version tag push (`v*`); or manual | PR compile check + artifact upload (no release) — use `build-and-release.yml` for a full release | [andrewblock]: http://web.archive.org/web/20150810054558/http://andrewblock.net/enable-remote-desktop-on-windows-8-core/ [mydigitallife]: http://forums.mydigitallife.info/threads/55935-RDP-Wrapper-Library-(works-with-Windows-8-1-Basic) @@ -87,8 +138,14 @@ It's recommended to have original termsrv.dll file with the RDP Wrapper installa [yt-offsets]: http://www.youtube.com/watch?v=FiD86tmRBtk ### Links: -- Official GitHub repository: +- **This fork (maintained):** +
https://github.com/sjackson0109/rdpwrap/ +- Original upstream repository (archived / unmaintained):
https://github.com/stascorp/rdpwrap/ +- Inspiration for auto-offset generation: +
[sergiye/rdpWrapper](https://github.com/sergiye/rdpWrapper) +- Offset finder tool used for auto-generation: +
[llccd/RDPWrapOffsetFinder](https://github.com/llccd/RDPWrapOffsetFinder) - Official Telegram chat:
https://t.me/rdpwrap - Active discussion in the comments here: @@ -106,20 +163,23 @@ It's recommended to have original termsrv.dll file with the RDP Wrapper installa ### Files in release package: -| File name | Description | -| --------- | ----------- | -| `RDPWInst.exe` | RDP Wrapper Library installer/uninstaller | -| `RDPCheck.exe` | Local RDP Checker (you can check the RDP is working) | -| `RDPConf.exe` | RDP Wrapper Configuration | -| `install.bat` | Quick install batch file | -| `uninstall.bat` | Quick uninstall batch file | -| `update.bat` | Quick update batch file | +| File name | Architecture | Description | +| --------- | ------------ | ----------- | +| `RDPWInst_x64.exe` | x64 | RDP Wrapper Library installer/uninstaller (C#, requires .NET 10) | +| `RDPWInst_x86.exe` | x86 | RDP Wrapper Library installer/uninstaller (C#, requires .NET 10) | +| `RDPCheck_x64.exe` | x64 | Local RDP Checker — verify RDP is working (C#, requires .NET 10) | +| `RDPCheck_x86.exe` | x86 | Local RDP Checker — verify RDP is working (C#, requires .NET 10) | +| `RDPConf_x64.exe` | x64 | RDP Wrapper Configuration GUI (C#, requires .NET 10) | +| `RDPConf_x86.exe` | x86 | RDP Wrapper Configuration GUI (C#, requires .NET 10) | +| `rdpwrap_x64.dll` | x64 | Core RDP Wrapper DLL (C++, no runtime required) | +| `rdpwrap_x86.dll` | x86 | Core RDP Wrapper DLL (C++, no runtime required) | +| `rdpwrap.ini` | — | Offset database (updated automatically on every INI push) | ### Frequently Asked Questions > Where can I download the installer or binaries? -In the [GitHub Releases](https://github.com/stascorp/rdpwrap/releases) section. +In the [GitHub Releases](https://github.com/sjackson0109/rdpwrap/releases) section. > Is it legal to use this application? @@ -127,11 +187,11 @@ There is no definitive answer, see [this discussion](https://github.com/stascorp > The installer tries to access the Internet, is it normal behaviour? -Yes, it works in online mode by default. You may disable it by removing `-o` flag in the `install.bat` file. +Yes, it works in online mode by default. You may disable it by passing `-i` without the `-o` flag: `RDPWInst_x64.exe -i`. > What is online install mode? -Online install mode introduced in version 1.6.1. When you installing RDP Wrapper first time using this mode, it will download [latest INI file](https://github.com/stascorp/rdpwrap/blob/master/res/rdpwrap.ini) from GitHub. See [this discussion](https://github.com/stascorp/rdpwrap/issues/132). +Online install mode was introduced in version 1.6.1. When installing for the first time using this mode, the installer downloads the [latest `rdpwrap.ini`](https://github.com/sjackson0109/rdpwrap/releases/latest/download/rdpwrap.ini) from this repository's GitHub Releases — published automatically by CI/CD whenever `msi/rdpwrap.ini` is updated. If your `termsrv.dll` version is not yet listed in the downloaded INI, the installer will additionally download [RDPWrapOffsetFinder](https://github.com/llccd/RDPWrapOffsetFinder) and attempt to auto-generate the missing offsets on the spot. > What is INI file and why we need it? @@ -143,11 +203,11 @@ Beginning with version 1.5 the `rdpwrap.dll` is not updated anymore, since all s > Config Tool shows `[not supported]` and RDP doesn't work. What can I do? -Make sure you're connected to the Internet and run `update.bat`. +Make sure you're connected to the Internet and run `RDPWInst_x64.exe -w` from an Administrator command prompt. This will download the latest INI from GitHub Releases and, if your `termsrv.dll` version is still missing, will automatically run [RDPWrapOffsetFinder](https://github.com/llccd/RDPWrapOffsetFinder) to generate offsets for your specific build. > Update doesn't help, it still shows `[not supported]`. -Visit [issues](https://github.com/stascorp/rdpwrap/issues) section, and check whether your `termsrv.dll` build is listed here. If you can't find such issue, create a new — specify your build version for adding to support. +Check the [issues](https://github.com/sjackson0109/rdpwrap/issues) section to see if your `termsrv.dll` build is mentioned. If not, please open a new issue with your exact build version (shown by the Config Tool). You can also run `RDPWInst.exe -w` from an Administrator command prompt to see the full output of the update and auto-generation steps. > Why `RDPCheck` doesn't allow to change resolution and other settings? @@ -168,6 +228,45 @@ Visit [issues](https://github.com/stascorp/rdpwrap/issues) section, and check wh ### Change log: +#### 2026.03.31 +- **Repository housekeeping** — removed six obsolete files: `res/legacy.install.bat`, `res/clearres.bat`, `res/build_wxs.bat`, `res/RDPWInst.wxs` (WiX v3.11 MSI, unmaintained), `res/rdpwrap-ini-kb.txt` (stale 2018 INI snapshot), and empty `src-csharp/RDPWrap.Common/` stub directory +- `bin/install.bat`, `bin/uninstall.bat`, `bin/update.bat` — rewritten with architecture detection; now invoke the correct `RDPWInst_x64.exe` / `RDPWInst_x86.exe` (previously called non-existent `RDPWInst.exe`); later removed in favour of the MSI installer +- CI/CD: `build-cpp.yml`, `build-csharp.yml`, `build-offsetfinder.yml` — standalone `release` jobs removed; `build-and-release.yml` is now the sole release publisher, eliminating duplicate partial releases on tag pushes +- `build-csharp.yml` runner harmonised to `windows-2022`; hardcoded `signtool.exe` SDK path replaced with glob-based discovery +- `build-and-release.yml` — added **embedded-resource staging** step (copies built DLLs + INI into `RDPWInst/Resources/` before `dotnet publish`, enabling offline bundled install); added **SHA-256 audit log** for third-party sergiye binaries; `msi/rdpwrap-arm-kb.ini` added to release assets +- **ARM64 support** — `Release|ARM64` added to `src-x86-x64-Fusix/RDPWrap.vcxproj`; `build-cpp.yml` and `build-and-release.yml` now build and ship `rdpwrap_arm64.dll`; `build-csharp.yml` and `build-and-release.yml` publish `RDPWInst_arm64.exe`, `RDPConf_arm64.exe`, `RDPCheck_arm64.exe`; `Directory.Build.props` adds `arm64` to `Platforms` +- **WiX v5 MSI packaging** — new `msi/RDPWInst.wxs` (WiX v5 schema v4, dual-arch, MajorUpgrade) and `msi/RDPWInst.wixproj`; replaces the deleted v3.11 artefacts; MSI build steps are now inlined into `build-and-release.yml` (a standalone `build-msi.yml` was created then removed as redundant) +- **Self-contained publish** — `build-and-release.yml` produces `*_x64_sc.exe`, `*_x86_sc.exe`, `*_arm64_sc.exe` for all three C# tools and bundles them into `RDPWrapper-SelfContained.zip`; users without .NET 10 Desktop Runtime can use these +- **Version stamp automation** — `build-and-release.yml` computes a `yyyy.M.d` stamp and passes `-p:Version=` to every `dotnet publish` call; `Directory.Build.props` documents the CI override pattern +- **Changelog automation** — `build-and-release.yml` now includes a `Generate changelog` step that queries merged PRs since the previous release and embeds them in the GitHub Release body +- **Dependabot** — `.github/dependabot.yml` added for `github-actions` and `nuget` ecosystems (weekly, Monday schedule) +- **Sergiye hash-pin scaffold** — `tools/sergiye-hashes.json` created; `build-and-release.yml` validates downloaded `rdpWrapper_*.exe` hashes against this file when populated +- **Code-signing guide** added — `docs/CODE-SIGNING.md` documents certificate acquisition, PFX export, base64 encoding, and GitHub secret upload; the signing step in `build-and-release.yml` and `build-csharp.yml` fires automatically once `CODESIGN_CERT_BASE64` and `CODESIGN_CERT_PASSWORD` secrets are set +- **Sergiye hash pins live** — `tools/update-sergiye-hashes.ps1` automation script created; `tools/sergiye-hashes.json` populated with verified SHA-256 hashes for `sergiye/rdpWrapper` release `2.10`; `build-and-release.yml` hash-verification step is now enforcing the pinned values +- **Screenshot infrastructure** — `docs/images/` directory and capture guide created; README restored with four-cell screenshot table using relative in-repo paths (PNG files pending first capture) +- **Submodule shallow-clone** — `shallow = true` added to `.gitmodules`; `docs/SUBMODULE-UPDATE.md` documents check-out, update, and rollback procedures (`RDPOffsetFinder` is already pinned to `v0.9`) +- **`tools/` reference added to `docs/`** — `update-sergiye-hashes.ps1` is self-documenting via `Get-Help`; `CODE-SIGNING.md`, `SUBMODULE-UPDATE.md`, `images/README.md` added to `docs/` + +#### 2026.03.30 +- **Full C# port complete** — `RDPWInst`, `RDPConf`, `RDPCheck`, and shared library all ported from Delphi to C# / .NET 10; Delphi is no longer required to build +- Obsolete Delphi source folders removed (`src-installer/`, `src-rdpcheck/`, `src-rdpconfig/`, `src-x86-binarymaster/`) +- Shared library renamed from `RDPWrap.Common/` to `RDPWrap/` for a cleaner folder layout; namespace `RDPWrap.Common` preserved for source compatibility +- **[llccd/RDPWrapOffsetFinder](https://github.com/llccd/RDPWrapOffsetFinder) added as a git submodule** at `src-csharp/RDPOffsetFinder/` (including nested `zydis` → `zycore` submodules) — offset finder now built from source rather than fetching pre-built binaries +- Pre-built binary cache (`tools/RDPWrapOffsetFinder/`) and `update-finder-tools.yml` workflow removed; `build-and-release.yml` now builds the offset finder directly from the submodule +- New workflow [`build-offsetfinder.yml`](.github/workflows/build-offsetfinder.yml) — builds `RDPWrapOffsetFinder` + `Zydis.dll` for x64 and Win32 from source on version tag push +- New workflow [`build-csharp.yml`](.github/workflows/build-csharp.yml) — publishes self-contained single-file x64/x86 EXEs on version tag push; optional `signtool.exe` code-signing step wired to `CODESIGN_CERT_BASE64` / `CODESIGN_CERT_PASSWORD` repository secrets +- [`build-and-release.yml`](.github/workflows/build-and-release.yml) updated — checkout uses `submodules: recursive`; builds and bundles `RDPWInst`, `RDPConf`, `RDPCheck`, and `RDPWrapOffsetFinder` (all x64 + x86) alongside the existing DLL and INI assets +- Author metadata (`Simon Jackson / @sjackson0109`, copyright, repository URL) embedded into all four C# assemblies via `Directory.Build.props` +- `src-csharp/Directory.Build.props` targets `net10.0-windows`; `x86` and `x64` platforms; `Nullable` + `ImplicitUsings` enabled + +#### 2026.03.29 +- Fork maintained by [@sjackson0109](https://github.com/sjackson0109) +- INI source redirected from unmaintained stascorp upstream to this repository's GitHub Releases +- **CI/CD pipeline added** — [`build-and-release.yml`](.github/workflows/build-and-release.yml) publishes `rdpwrap.ini` and the `RDPWrapOffsetFinder` tools as release assets on every INI change +- **CI/CD pipeline added** — [`build-cpp.yml`](.github/workflows/build-cpp.yml) builds `rdpwrap_x64.dll` / `rdpwrap_x86.dll` via MSVC v143 (VS 2022) on version tag push +- **Auto-offset generation** added to `RDPWInst.dpr` — on install (`-i`) and update (`-w`), if the running `termsrv.dll` version is absent from the INI the installer downloads `RDPWrapOffsetFinder` from release assets and appends the generated `[x.x.xxxxx.xxxxx]` section automatically; inspired by [sergiye/rdpWrapper](https://github.com/sergiye/rdpWrapper) +- New installer helpers: `DownloadFileToDisk`, `INIHasSection`, `TryAutoGenerateOffsets` + #### 2017.12.27 - Version 1.6.2 - Installer updated @@ -449,15 +548,15 @@ Visit [issues](https://github.com/stascorp/rdpwrap/issues) section, and check wh - Windows Server 2016 Technical Preview Installation instructions: -- Download latest release binaries and unpack files -- Right-click on **`install.bat`** and select Run as Administrator +- Download `RDPWrapper-.msi` from the [GitHub Releases](https://github.com/sjackson0109/rdpwrap/releases) page +- Double-click the MSI and accept the UAC prompt — the installer detects your architecture automatically - See command output for details To update INI file: -- Right-click on **`update.bat`** and select Run as Administrator +- Open an Administrator command prompt in `%ProgramFiles%\RDP Wrapper` +- Run `RDPWInst_x64.exe -w` (or `RDPWInst_x86.exe -w` on 32-bit Windows) - See command output for details To uninstall: -- Go to the directory where you extracted the files -- Right-click on **`uninstall.bat`** and select Run as Administrator -- See command output for details +- Open **Add or Remove Programs** and uninstall **RDP Wrapper Library** +- Alternatively run `msiexec /x RDPWrapper-.msi` from an elevated prompt diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..0371884 --- /dev/null +++ b/TODO.md @@ -0,0 +1,3 @@ +# TODO + +All items complete. Nothing pending. diff --git a/bin/install.bat b/bin/install.bat deleted file mode 100644 index 5e6ed34..0000000 --- a/bin/install.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off -if not exist "%~dp0RDPWInst.exe" goto :error -"%~dp0RDPWInst" -i -o -echo ______________________________________________________________ -echo. -echo You can check RDP functionality with RDPCheck program. -echo Also you can configure advanced settings with RDPConf program. -echo. -goto :anykey -:error -echo [-] Installer executable not found. -echo Please extract all files from the downloaded package or check your anti-virus. -:anykey -pause diff --git a/bin/uninstall.bat b/bin/uninstall.bat deleted file mode 100644 index 1c72289..0000000 --- a/bin/uninstall.bat +++ /dev/null @@ -1,10 +0,0 @@ -@echo off -if not exist "%~dp0RDPWInst.exe" goto :error -"%~dp0RDPWInst" -u -echo. -goto :anykey -:error -echo [-] Installer executable not found. -echo Please extract all files from the downloaded package or check your anti-virus. -:anykey -pause diff --git a/bin/update.bat b/bin/update.bat deleted file mode 100644 index f3874aa..0000000 --- a/bin/update.bat +++ /dev/null @@ -1,10 +0,0 @@ -@echo off -if not exist "%~dp0RDPWInst.exe" goto :error -"%~dp0RDPWInst" -w -echo. -goto :anykey -:error -echo [-] Installer executable not found. -echo Please extract all files from the downloaded package or check your anti-virus. -:anykey -pause diff --git a/docs/BUILDING.md b/docs/BUILDING.md new file mode 100644 index 0000000..9d2ee66 --- /dev/null +++ b/docs/BUILDING.md @@ -0,0 +1,255 @@ +# Building RDP Wrapper Locally + +This document covers the full local build pipeline — from prerequisites to the final `./build/` artefacts. + +--- + +## Prerequisites + +| Component | Version | Notes | +|---|---|---| +| Windows 10/11 x64 | any | Host OS | +| .NET SDK | 10.0+ | `winget install Microsoft.DotNet.SDK.10` | +| Visual Studio 2019 Build Tools | 16.x | For C++ DLL only | +| MSVC v142 toolset | 14.29+ | Installed via VS Build Tools installer | +| Windows SDK | 10.0.19041+ | Installed via VS Build Tools installer | + +> **ARM64 DLL note:** Building `rdpwrap_arm64.dll` locally requires Visual Studio 2022 +> with the "MSVC v143 — VS 2022 C++ ARM64 build tools" component. The GitHub Actions +> CI uses a hosted `windows-latest` runner which provides this. For local work, the +> x64 and Win32 DLLs are sufficient for testing. + +--- + +## 1. Clone the repository + +```powershell +git clone --recurse-submodules https://github.com//rdpwrap.git +cd rdpwrap +``` + +If you already cloned without `--recurse-submodules`: + +```powershell +git submodule update --init --recursive +``` + +--- + +## 2. Generate application icons + +The C# tool icons are generated programmatically via a helper script and are **not** +committed to source control. Run this once after cloning (and again if you delete them): + +```powershell +.\tools\make-icons.ps1 +``` + +This creates: + +- `src-csharp/RDPConf/app.ico` — blue "C" icon for RDPConf +- `src-csharp/RDPCheck/app.ico` — green "K" icon for RDPCheck + +Both files are `.gitignore`-exempt (not listed) so they persist in your working tree. + +--- + +## 3. Build the C++ DLL (`rdpwrap.dll`) + +### Locate MSBuild + +Visual Studio 2019 Build Tools installs MSBuild to a non-standard path. +Add it to your session PATH once (or use the full path as shown below): + +```powershell +$msbuild = "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.exe" +``` + +> If you have Visual Studio IDE installed instead of Build Tools, the path is: +> `C:\Program Files\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\amd64\MSBuild.exe` + +### One-time vcxproj fix + +The Windows SDK 10.0.19041 headers emit a C2338 packing warning that is treated as an +error under `/WX`. It has **no behavioural effect** — the fix is already applied in +`src-x86-x64-Fusix/RDPWrap.vcxproj` via the `WINDOWS_IGNORE_PACKING_MISMATCH` define. +No manual action is required. + +### Build x64 and Win32 + +```powershell +$msbuild = "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.exe" + +& $msbuild src-x86-x64-Fusix\RDPWrap.sln ` + /p:Configuration=Release /p:Platform=x64 ` + /p:PlatformToolset=v142 ` + /p:WindowsTargetPlatformVersion=10.0.19041.0 ` + /m /v:m + +& $msbuild src-x86-x64-Fusix\RDPWrap.sln ` + /p:Configuration=Release /p:Platform=Win32 ` + /p:PlatformToolset=v142 ` + /p:WindowsTargetPlatformVersion=10.0.19041.0 ` + /m /v:m +``` + +> Expect `C4244` / `C4267` type-conversion warnings from the Zydis disassembler +> submodule — these are benign and can be ignored. + +### Output locations + +| Platform | Output path | +|---|---| +| x64 | `src-x86-x64-Fusix/x64/Release/RDPWrap.dll` | +| Win32 | `src-x86-x64-Fusix/Release/RDPWrap.dll` | + +--- + +## 4. Build C# tools + +All three C# tools are published as self-contained single-file executables using +`dotnet publish`. + +### Architectures + +| RID | Description | +|---|---| +| `win-x64` | 64-bit Intel/AMD | +| `win-x86` | 32-bit Intel/AMD | +| `win-arm64` | ARM64 (cross-compiled, no native toolchain needed) | + +### Commands + +```powershell +$TOOLS = @("RDPConf", "RDPCheck", "RDPWInst") +$RIDS = @("win-x64", "win-x86", "win-arm64") + +foreach ($tool in $TOOLS) { + foreach ($rid in $RIDS) { + $arch = $rid -replace "win-", "" + $out = "build\staging\$tool\$rid" + dotnet publish "src-csharp\$tool\$tool.csproj" ` + -c Release -r $rid ` + --self-contained true ` + -p:PublishSingleFile=true ` + -p:IncludeNativeLibrariesForSelfExtract=true ` + -p:PublishTrimmed=false ` + -p:Version=1.0.0 ` + -o $out + } +} +``` + +### Output + +After publishing, executables are in `build/staging///`: + +``` +build\staging\RDPConf\win-x64\RDPConf.exe +build\staging\RDPConf\win-x86\RDPConf.exe +build\staging\RDPConf\win-arm64\RDPConf.exe +build\staging\RDPCheck\win-x64\RDPCheck.exe +... +``` + +--- + +## 5. Assemble `./build/` + +Copy all artefacts to a flat `./build/` directory: + +```powershell +New-Item -Force -ItemType Directory build | Out-Null + +# DLLs +Copy-Item src-x86-x64-Fusix\x64\Release\RDPWrap.dll build\rdpwrap_x64.dll +Copy-Item src-x86-x64-Fusix\Release\RDPWrap.dll build\rdpwrap_x86.dll + +# C# executables +foreach ($tool in @("RDPConf","RDPCheck","RDPWInst")) { + foreach ($rid in @("win-x64","win-x86","win-arm64")) { + $arch = $rid -replace "win-","" + Copy-Item "build\staging\$tool\$rid\$tool.exe" ` + "build\${tool}_${arch}.exe" + } +} + +# Cleanup staging +Remove-Item -Recurse -Force build\staging +``` + +### Final `./build/` layout + +``` +build/ + rdpwrap_x64.dll # x64 termsrv.dll hook + rdpwrap_x86.dll # x86 termsrv.dll hook + RDPConf_x64.exe # GUI config tool (x64) + RDPConf_x86.exe # GUI config tool (x86) + RDPConf_arm64.exe # GUI config tool (ARM64) + RDPCheck_x64.exe # RDP loopback tester (x64) + RDPCheck_x86.exe # RDP loopback tester (x86) + RDPCheck_arm64.exe # RDP loopback tester (ARM64) + RDPWInst_x64.exe # CLI installer (x64) + RDPWInst_x86.exe # CLI installer (x86) + RDPWInst_arm64.exe # CLI installer (ARM64) +``` + +> `./build/` is listed in `.gitignore` — artefacts are not committed. + +--- + +## 6. Automated script + +All steps 2–5 are automated in `tools/build-local.ps1`. +Run it from the repo root: + +```powershell +.\tools\build-local.ps1 +``` + +Optional flag to skip the DLL rebuild (faster during C# iteration): + +```powershell +.\tools\build-local.ps1 -SkipCpp +``` + +--- + +## 7. Troubleshooting + +### MSBuild not found +Verify VS 2019 Build Tools are installed. +Open the **Visual Studio Installer** → Modify → ensure +"Desktop development with C++" and "MSVC v142 build tools" are checked. + +### ARM64 DLL: `error MSB8013` +No ARM64 cross-compiler found. Either install VS 2022 with ARM64 tools or skip ARM64 +(`-SkipArm64Dll` flag in `build-local.ps1`). The ARM64 DLL is produced by CI. + +### `error C2338: Windows headers require the default packing option` +`WINDOWS_IGNORE_PACKING_MISMATCH` is missing from `PreprocessorDefinitions`. +Run the following once then rebuild: + +```powershell +(Get-Content src-x86-x64-Fusix\RDPWrap.vcxproj) ` + -replace '()([^<]+)(<)', ` + '$1$2;WINDOWS_IGNORE_PACKING_MISMATCH$3' | + Set-Content src-x86-x64-Fusix\RDPWrap.vcxproj +``` + +### `dotnet publish` fails with SDK not found +Ensure .NET 10 SDK is installed: `dotnet --version` should print `10.x.x`. + +--- + +## Appendix: CI vs local comparison + +| Feature | Local build | GitHub Actions CI | +|---|---|---| +| x64 DLL | ✅ | ✅ | +| x86 DLL | ✅ | ✅ | +| ARM64 DLL | ❌ (needs VS 2022) | ✅ | +| C# x64/x86/arm64 | ✅ (cross-compiled) | ✅ | +| Code signing | ❌ | ✅ (if cert configured) | +| GitHub Release | ❌ | ✅ (on tag push) | diff --git a/docs/CODE-SIGNING.md b/docs/CODE-SIGNING.md new file mode 100644 index 0000000..000faa7 --- /dev/null +++ b/docs/CODE-SIGNING.md @@ -0,0 +1,100 @@ +# Code Signing Guide + +Both `build-and-release.yml` and `build-csharp.yml` include a code-signing step that is already wired up and waiting. The step fires automatically as soon as the two secrets below are present in the repository — no workflow edits are needed. + +--- + +## What gets signed + +All six framework-dependent executables and all six self-contained executables produced per release: + +| File | Contents | +|---|---| +| `RDPWInst_x64.exe`, `RDPWInst_x86.exe`, `RDPWInst_arm64.exe` | CLI installer | +| `RDPConf_x64.exe`, `RDPConf_x86.exe`, `RDPConf_arm64.exe` | GUI configuration tool | +| `RDPCheck_x64.exe`, `RDPCheck_x86.exe`, `RDPCheck_arm64.exe` | GUI connection tester | +| `*_sc.exe` variants | Self-contained copies of the above | + +The signing step runs on every `build-and-release.yml` and `build-csharp.yml` triggered build (tag push and manual dispatch), and is **skipped silently** when the secrets are absent. + +--- + +## Obtaining a code-signing certificate + +### Option A — Commercial certificate (recommended for public distribution) + +Purchase an **EV (Extended Validation) Code Signing Certificate** from a trusted CA: + +- [DigiCert Code Signing](https://www.digicert.com/signing/code-signing-certificates) +- [Sectigo (Comodo)](https://sectigo.com/ssl-certificates-tls/code-signing) +- [GlobalSign](https://www.globalsign.com/en/code-signing-certificate/) + +> **Windows SmartScreen** initially blocks unsigned or low-reputation executables. A commercial EV certificate builds reputation immediately; a standard OV certificate requires time to accumulate reputation through user downloads. Self-signed certificates (Option B) will always trigger SmartScreen warnings. + +### Option B — Self-signed certificate (testing / internal use only) + +```powershell +# Run in an elevated PowerShell session +$cert = New-SelfSignedCertificate ` + -Type CodeSigningCert ` + -Subject "CN=RDP Wrapper" ` + -KeySpec Signature ` + -KeyAlgorithm RSA ` + -KeyLength 4096 ` + -HashAlgorithm SHA256 ` + -CertStoreLocation "Cert:\CurrentUser\My" ` + -NotAfter (Get-Date).AddYears(3) + +# Export to PFX (set a strong password) +$pw = Read-Host "PFX password" -AsSecureString +Export-PfxCertificate -Cert $cert -FilePath "rdpwrap-codesign.pfx" -Password $pw +``` + +--- + +## Preparing the PFX for GitHub Actions + +```powershell +# Base64-encode the PFX so it can be stored as a secret +$b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes(".\rdpwrap-codesign.pfx")) +$b64 | Set-Clipboard +Write-Host "Base64 PFX copied to clipboard" +``` + +--- + +## Adding the secrets to GitHub + +Navigate to: **Settings → Secrets and variables → Actions → New repository secret** + +| Secret name | Value | +|---|---| +| `CODESIGN_CERT_BASE64` | Paste the base64-encoded PFX string | +| `CODESIGN_CERT_PASSWORD` | The password chosen when exporting the PFX | + +> ⚠️ **Security:** Never commit the `.pfx` file or raw base64 string to the repository. Revoke and reissue the certificate if it is accidentally exposed. + +--- + +## Verifying a signed executable + +After a signed release is published: + +```powershell +# Check signature status +Get-AuthenticodeSignature .\RDPWInst_x64.exe | Format-List + +# Expected output (commercial cert): +# Status : Valid +# SignerCertificate : [CN=Your Name, O=Your Org, ...] +# TimeStamperCertificate : [CN=DigiCert Timestamp 2023, ...] +``` + +--- + +## Renewing / rotating the certificate + +1. Export the new PFX and base64-encode it (see above). +2. Update both `CODESIGN_CERT_BASE64` and `CODESIGN_CERT_PASSWORD` via **Settings → Secrets**. +3. No workflow changes are needed — the `Sign C# executables` step always reads from secrets at runtime. +4. Remove the old PFX from your local machine and revoke the old certificate with the CA if it has not expired. diff --git a/docs/HOW-TO-ADD-NEW-WINDOWS-BUILDS.md b/docs/HOW-TO-ADD-NEW-WINDOWS-BUILDS.md new file mode 100644 index 0000000..b6826d8 --- /dev/null +++ b/docs/HOW-TO-ADD-NEW-WINDOWS-BUILDS.md @@ -0,0 +1,457 @@ +# How to Add Support for New Windows Builds + +This guide explains the technical process for reverse engineering new Windows builds to extract the necessary RDP Wrapper configuration parameters. + +## Overview + +When Microsoft releases new Windows updates, the `termsrv.dll` file changes, and RDP Wrapper needs updated offset configurations to function properly. This document covers **two paths**: + +1. **[Quick path — RDPWrapOffsetFinder (recommended)](#quick-path-rdpwrapoffsetfinder-automated):** the compiled tool bundled in every release can generate a valid INI section in seconds on most builds. +2. **[Manual path — disassembly and reverse engineering](#manual-path-disassembly-and-reverse-engineering):** used when the automated tool cannot find all offsets for a new or unusual build. + +--- + +## Quick path: RDPWrapOffsetFinder (automated) + +> **TL;DR** — run the tool, copy the generated INI block, open a PR. + +RDPWrapOffsetFinder (by **llccd**, bundled in every release as `RDPWrapOffsetFinder_x64.exe` and `RDPWrapOffsetFinder_x86.exe`) performs automated static analysis on the installed `termsrv.dll` and emits a ready-to-use INI section. + +### Step A: Run RDPWrapOffsetFinder + +```powershell +# Locate termsrv.dll version (so you know what tag to add) +(Get-Item C:\Windows\System32\termsrv.dll).VersionInfo.ProductVersion + +# Run the tool (run as Administrator; it reads the locked DLL via sharing flags) +.\RDPWrapOffsetFinder_x64.exe +``` + +On success the tool prints an INI block similar to: + +```ini +[10.0.26100.3915] +SingleUserPatch.x64=1 +SingleUserOffset.x64=0A1B2C +... +``` + +If the tool exits with `Unsupported version`, try the nosym (no-symbols) variant: + +```powershell +.\RDPWrapOffsetFinder_nosym_x64.exe +``` + +### Step B: Use the autoupdate helper (optional) + +The `autoupdate/` directory in `src-csharp/RDPOffsetFinder/` contains a convenience script that wraps the tool, appends the output to a local copy of `rdpwrap.ini`, and validates the result: + +```batch +cd src-csharp\RDPOffsetFinder\RDPWrapOffsetFinder\autoupdate +autoupdate.bat +``` + +The script will: +1. Run `RDPWrapOffsetFinder.exe` against the current system's `termsrv.dll`. +2. Merge the new section into `rdpwrap_template.ini`. +3. Print the diff so you can review before committing. + +### Step C: Validate the generated block + +Before opening a pull request: + +```powershell +# Quick sanity check — restart Terminal Services with the new INI +net stop TermService +Copy-Item .\rdpwrap_updated.ini "C:\Program Files\RDP Wrapper\rdpwrap.ini" +net start TermService + +# Visual validation +.\RDPCheck.exe # should show "Installed", "Listening", and "Supported" +``` + +### Step D: Submit a pull request + +1. Add (or update) the version block in `msi/rdpwrap.ini`. +2. Commit with message: `ini: add support for 10.0.XXXXX.YYYY`. +3. Open a pull request against the `main` branch using the [bug_report](.github/ISSUE_TEMPLATE/bug_report.yml) template. + Include: the output of `RDPWrapOffsetFinder.exe`, your `termsrv.dll` version, and a screenshot of `RDPCheck.exe` showing "Supported". + +> **Security note:** Never attach the actual `termsrv.dll` binary — this would infringe Microsoft's licence. The version string and SHA-256 hash are sufficient for reproducibility. + +--- + +## Manual path: disassembly and reverse engineering + +Use this path when: +- RDPWrapOffsetFinder cannot find all offsets (prints partial output or crashes), **or** +- You want to understand *why* a patch works, not just *where* to apply it. + +## Prerequisites + +### Required Tools + +**Disassemblers (Choose one):** +- **Ghidra** (Free, recommended) - NSA's reverse engineering tool +- **IDA Pro** (Commercial) - Industry standard +- **x64dbg** (Free) - Good for dynamic analysis +- **Radare2** (Free) - Command-line focused + +**Supporting Tools:** +- **HxD** or similar hex editor +- **PE Explorer** - For PE structure analysis +- **Process Monitor** - Runtime file/registry monitoring +- **API Monitor** - Function call tracing +- **RDPCheck.exe** - For testing configurations + +### Required Knowledge + +- Assembly language (x86/x64) +- PE file format basics +- Windows API understanding +- Basic cryptography concepts + +## Step 1: Obtain the Target File + +### Extract termsrv.dll + +```powershell +# Navigate to System32 directory +cd C:\Windows\System32 + +# Copy termsrv.dll to analysis directory +copy termsrv.dll C:\Analysis\termsrv.dll + +# Get file version information +Get-ItemProperty C:\Analysis\termsrv.dll | Select-Object VersionInfo +``` + +### Determine Version Number + +```powershell +# PowerShell method +(Get-Item C:\Analysis\termsrv.dll).VersionInfo.ProductVersion + +# Alternative: WMIC method +wmic datafile where name="C:\\Windows\\System32\\termsrv.dll" get Version +``` + +The version format will be: `10.0.XXXXX.YYYY` (e.g., `10.0.26100.7623`) + +## Step 2: Initial Analysis + +### Load in Disassembler + +1. Open termsrv.dll in your chosen disassembler +2. Let it complete initial analysis (auto-analysis) +3. Examine the import table for key functions +4. Identify the main code sections + +### Key Function Identification + +Search for these critical functions that RDP Wrapper needs to patch: + +1. `CSessionArbitrationHelper::IsSingleSessionPerUserEnabled` +2. `CDefPolicy::Query` +3. `CEnforcementCore::GetInstanceOfTSLicense` +4. `CSLQuery::Initialize` + +## Step 3: Finding Function Offsets + +### Method 1: String Reference Analysis + +``` +1. Search for relevant strings: + - "Terminal Services" + - "Session" + - "Licence" + - "Policy" + - Error messages related to licensing + +2. Follow cross-references from strings to functions +3. Analyse the functions that reference these strings +``` + +### Method 2: Import Table Analysis + +``` +1. Examine imported functions: + - GetTokenInformation + - WinStationQueryInformationW + - RegQueryValueExW + - Licence-related APIs + +2. Find functions that call these imports +3. Trace backwards to find policy validation logic +``` + +### Method 3: Pattern Matching + +Look for specific assembly patterns that indicate the functions we need to patch: + +#### Single User Patch Pattern +```asm +; Look for patterns like: +BB 01 00 00 00 ; mov ebx, 1 (single session enabled) +; Or: +B8 01 00 00 00 ; mov eax, 1 +``` + +#### DefPolicy Patch Pattern +```asm +; Look for licence policy validation: +B8 01 00 00 00 ; mov eax, 1 (policy result) +89 81 38 06 00 00 ; mov [rcx+638h], eax (store result) +; Or similar patterns with different registers +``` + +## Step 4: Extracting Configuration Parameters + +### Single User Offset + +1. Find `CSessionArbitrationHelper::IsSingleSessionPerUserEnabled` +2. Look for the instruction that returns 1 (single session restriction) +3. Note the file offset of this instruction +4. The patch will change this to return 0 (allow multiple sessions) + +### DefPolicy Offset + +1. Find `CDefPolicy::Query` +2. Look for licence validation logic +3. Find where it sets the result to indicate "licenced" +4. Note the offset for the instruction to patch + +### LocalOnly Offset + +1. Find `CEnforcementCore::GetInstanceOfTSLicense` +2. Look for local connection restrictions +3. Find the jump/conditional that enforces local-only policy +4. Note the offset to patch this restriction + +### SLInit Parameters + +1. Find `CSLQuery::Initialize` +2. Analyse the data structure it initializes +3. Find the memory offsets for these fields: + - `bInitialized` + - `bServerSku` + - `lMaxUserSessions` + - `bAppServerAllowed` + - `bRemoteConnAllowed` + - `bMultimonAllowed` + - `ulMaxDebugSessions` + - `bFUSEnabled` + +## Step 5: Creating the Configuration + +### Basic INI Structure + +```ini +[10.0.XXXXX.YYYY] +; Single user session patch +SingleUserPatch.x64=1 +SingleUserOffset.x64=OFFSET_HEX +SingleUserCode.x64=PATCH_CODE + +; Licence policy patch +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=OFFSET_HEX +DefPolicyCode.x64=PATCH_CODE + +; Local-only restriction patch +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=OFFSET_HEX +LocalOnlyCode.x64=PATCH_CODE + +; Software licensing hook +SLInitHook.x64=1 +SLInitOffset.x64=OFFSET_HEX +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.XXXXX.YYYY-SLInit] +bServerSku.x64=OFFSET_HEX +bRemoteConnAllowed.x64=OFFSET_HEX +bFUSEnabled.x64=OFFSET_HEX +bAppServerAllowed.x64=OFFSET_HEX +bMultimonAllowed.x64=OFFSET_HEX +lMaxUserSessions.x64=OFFSET_HEX +ulMaxDebugSessions.x64=OFFSET_HEX +bInitialized.x64=OFFSET_HEX +``` + +### Common Patch Codes + +```ini +; Available patch codes (defined in [PatchCodes] section): +Zero=00 ; Set to zero +nop=90 ; No operation +jmpshort=EB ; Short jump +mov_eax_1_nop_2=B8010000009090 ; mov eax,1 + 2 NOPs +CDefPolicy_Query_eax_rcx_jmp=B80001000089813806000090EB ; Policy bypass +``` + +## Step 6: Testing and Validation + +### Initial Testing + +1. Create a test INI file with your calculated offsets +2. Back up the original rdpwrap.ini +3. Replace with your test configuration +4. Restart Terminal Services +5. Run RDPCheck.exe to verify status + +### Dynamic Analysis + +1. Use x64dbg to attach to the running termsrv.exe process +2. Set breakpoints at your calculated offsets +3. Verify that your patches are being applied correctly +3. Monitor for any crashes or unexpected behaviour + +### Validation Steps + +```powershell +# Stop Terminal Services +net stop TermService + +# Apply new configuration +copy test_rdpwrap.ini C:\Program Files\RDP Wrapper\rdpwrap.ini + +# Start Terminal Services +net start TermService + +# Test with RDPCheck +RDPCheck.exe + +# Test actual RDP connection +mstsc /v:localhost +``` + +## Step 7: Documentation and Sharing + +### Document Your Findings + +Create a detailed report including: +- Windows build version and SHA256 of termsrv.dll +- Methodology used +- Specific offsets found +- Testing results +- Any challenges encountered + +### Share with Community + +1. Post your configuration in a GitHub issue +2. Include the termsrv.dll file (zipped) for verification +3. Provide testing evidence (screenshots from RDPCheck) +4. Document any system-specific requirements + +## Common Challenges + +### Address Space Layout Randomization (ASLR) + +Modern Windows uses ASLR, but the relative offsets within the DLL remain constant. Always work with file offsets, not memory addresses. + +### Compiler Optimisations + +Microsoft's compiler optimisations can: +- Inline functions +- Reorder code +- Change calling conventions +- Merge similar functions + +### Code Signing + +Windows verifies code signatures, so: +- Patches must be applied at runtime, not to the file +- Use the RDP Wrapper's hooking mechanism +- Never modify the original termsrv.dll + +### Function Variations + +The same logical function might be implemented differently across builds: +- Different assembly patterns +- Different register usage +- Inlined vs separate functions + +## Advanced Techniques + +### Comparative Analysis + +When analysing a new build: +1. Compare with a known working build +2. Look for similar patterns and structures +3. Use diff tools on disassembled code + +### Automated Pattern Detection + +Some community members have created scripts to: +- Search for common assembly patterns +- Compare function signatures +- Suggest likely offset candidates + +### Binary Diffing + +Tools like BinDiff can help identify: +- Changed functions between builds +- Similar code blocks +- Function renaming/reorganisation + +## Community Resources + +### Trusted Contributors + +Community members known for accurate analysis: +- **@Fabliv** - Consistently provides verified configurations +- **@sebaxakerhtc** - Regular contributor with detailed analysis +- **@maxpiva** - Historical configurations and tools + +### Useful Repositories + +- Main project: `stascorp/rdpwrap` +- Community tools: Various forks with analysis scripts +- Configuration databases: Community-maintained INI collections + +## Contributing Your Analysis + +### GitHub Issue Format + +When posting a new configuration: + +```markdown +## Windows Build: 10.0.XXXXX.YYYY + +**System Information:** +- Edition: Windows 11 Pro/Home/Enterprise +- Architecture: x64 +- Installation: Clean/Update from X.X.X + +**Analysis Results:** +[Paste your INI configuration here] + +**Verification:** +- ✅ RDPCheck shows "Installed" and "Listening" +- ✅ Multiple simultaneous connections tested +- ✅ No crashes or stability issues + +**Files:** +[Attach termsrv.dll.zip] +``` + +### Testing by Others + +Before a configuration is accepted: +1. Multiple community members should test +2. Verify on different system configurations +3. Confirm no regressions on existing functionality +4. Test edge cases (different user accounts, domain environments) + +## Conclusion + +Adding support for new Windows builds requires: +- Technical reverse engineering skills +- Patience for trial-and-error testing +- Community collaboration for verification +- Detailed documentation for maintainability + +While this process cannot be easily automated due to Microsoft's security measures and varying compilation patterns, the community has developed efficient workflows that typically produce working configurations within days of new Windows releases. + +The key to success is methodical analysis, thorough testing, and collaboration with the experienced community members who have mastered this process. \ No newline at end of file diff --git a/docs/SUBMODULE-UPDATE.md b/docs/SUBMODULE-UPDATE.md new file mode 100644 index 0000000..0ba02df --- /dev/null +++ b/docs/SUBMODULE-UPDATE.md @@ -0,0 +1,101 @@ +# Submodule Update Guide + +This repository includes one git submodule (with nested sub-submodules): + +| Submodule | Upstream | Current tag | +|---|---|---| +| `src-csharp/RDPOffsetFinder` | [llccd/RDPWrapOffsetFinder](https://github.com/llccd/RDPWrapOffsetFinder) | `v0.9` | +| `src-csharp/RDPOffsetFinder/zydis` | [zyantific/zydis](https://github.com/zyantific/zydis) | (pinned by upstream) | +| `src-csharp/RDPOffsetFinder/zydis/dependencies/zycore` | [zyantific/zycore-c](https://github.com/zyantific/zycore-c) | (pinned by upstream) | + +The nested `zydis` and `zycore` submodule commits are controlled by llccd's repository — update only the outer submodule and the inner ones follow automatically. + +--- + +## Cloning with submodules + +```bash +# Full clone (recommended for builds) +git clone --recurse-submodules https://github.com/sjackson0109/rdpwrap + +# If you already cloned without --recurse-submodules: +git submodule update --init --recursive +``` + +--- + +## Checking current submodule version + +```powershell +git submodule status --recursive +# Expected output (one line per submodule): +# 68da37acab6593c329776644944f55695a131731 src-csharp/RDPOffsetFinder (v0.9) +# 5a68f639e4f01604cc7bfc8d313f583a8137e3d3 src-csharp/RDPOffsetFinder/zydis (...) +# fb69402566a15a719e5df7a64a3db95105590b7e src-csharp/RDPOffsetFinder/zydis/dependencies/zycore (...) +``` + +--- + +## Updating to a new upstream release + +> **Do this only when a new tagged release of [llccd/RDPWrapOffsetFinder](https://github.com/llccd/RDPWrapOffsetFinder) is published** and you have verified that the new version produces correct INI sections for a known Windows build. + +```powershell +# 1. Fetch all tags from upstream +cd src-csharp/RDPOffsetFinder +git fetch --tags origin + +# 2. List available tags to find the new release +git tag --list --sort=-version:refname | Select-Object -First 10 + +# 3. Check out the desired tag +git checkout # e.g. v1.0 + +# 4. Update nested submodules to match the new tag's references +git submodule update --init --recursive + +# 5. Return to repo root and record the new pointer +cd ../.. +git add src-csharp/RDPOffsetFinder +git commit -m "chore: update RDPOffsetFinder submodule to " +git push +``` + +--- + +## Verifying the updated submodule builds + +```powershell +# From repo root — builds x64 and x86 offset finder binaries +cd src-csharp/RDPOffsetFinder + +cmake -B build-x64 -A x64 . +cmake --build build-x64 --config Release + +cmake -B build-x86 -A Win32 . +cmake --build build-x86 --config Release +``` + +Or trigger the `build-offsetfinder.yml` workflow on your push branch to let CI validate it. + +--- + +## Rollback + +If the update causes build failures, revert the submodule pointer: + +```powershell +git revert HEAD # creates a revert commit +git push +``` + +Or manually: + +```powershell +cd src-csharp/RDPOffsetFinder +git checkout v0.9 # previous known-good tag +cd ../.. +git add src-csharp/RDPOffsetFinder +git commit -m "chore: rollback RDPOffsetFinder submodule to v0.9" +git push +``` diff --git a/docs/images/RDPWrapperCheck.png b/docs/images/RDPWrapperCheck.png new file mode 100644 index 0000000..81b02e9 Binary files /dev/null and b/docs/images/RDPWrapperCheck.png differ diff --git a/docs/images/RDPWrapperCheckWarning.png b/docs/images/RDPWrapperCheckWarning.png new file mode 100644 index 0000000..263a879 Binary files /dev/null and b/docs/images/RDPWrapperCheckWarning.png differ diff --git a/docs/images/RDPWrapperConfig.png b/docs/images/RDPWrapperConfig.png new file mode 100644 index 0000000..9a03ec0 Binary files /dev/null and b/docs/images/RDPWrapperConfig.png differ diff --git a/docs/images/RDPWrapperMSI1.png b/docs/images/RDPWrapperMSI1.png new file mode 100644 index 0000000..d62f59d Binary files /dev/null and b/docs/images/RDPWrapperMSI1.png differ diff --git a/docs/images/RDPWrapperMSI2.png b/docs/images/RDPWrapperMSI2.png new file mode 100644 index 0000000..594c7eb Binary files /dev/null and b/docs/images/RDPWrapperMSI2.png differ diff --git a/docs/images/README.md b/docs/images/README.md new file mode 100644 index 0000000..f687bfd --- /dev/null +++ b/docs/images/README.md @@ -0,0 +1,51 @@ +# Screenshots — `docs/images/` + +This directory holds in-repo screenshot assets referenced by the project README. + +--- + +## Files present + +The following PNG screenshots are committed and referenced by the README: + +| Filename | Contents | +|---|---| +| `RDPWrapperConfig.png` | RDPConf.exe configuration window | +| `RDPWrapperCheck.png` | RDPCheck.exe showing green "Supported" status | +| `RDPWrapperCheckWarning.png` | RDPCheck.exe showing "Warning" / not-yet-supported state | +| `RDPWrapperMSI1.png` | MSI installer welcome / licence screen | +| `RDPWrapperMSI2.png` | MSI installer completion screen | + +--- + +## Files that would still be welcome + +The following screenshots would improve documentation coverage but are not blocking any CI step: + +| Filename | What to capture | +|---|---| +| `RDPWrapperConfig-advanced.png` | RDPConf.exe Advanced / License tab — SL policy and licensing status fields | +| `rdpwrapper-gui.png` | sergiye/rdpWrapper GUI — main window with connection status | +| `install-success.png` | Terminal output of `RDPWInst_x64.exe -i -o` completing successfully | + +--- + +## Capture tips + +- Use **1:1 scaling** (100 % DPI) so button labels are legible at small display size. +- Crop to exclude desktop wallpaper — show only the tool window, with a 4 px neutral border all round. +- Use PNG format (lossless); aim for < 200 KB each (resize if needed — 900 px wide is more than enough). +- Redact any username, hostname, or licence strings visible in the window before committing. +- Filename convention: `tool-state.png` — all lowercase, hyphen-delimited. + +--- + +## Adding a new screenshot + +```bash +# After copying the PNG here: +git add docs/images/.png +git commit -m "docs: add screenshot" +``` + +The README references each file with a relative path, so the image will render automatically on GitHub once committed. diff --git a/msi/RDPWInst.wixproj b/msi/RDPWInst.wixproj new file mode 100644 index 0000000..94a9575 --- /dev/null +++ b/msi/RDPWInst.wixproj @@ -0,0 +1,24 @@ + + + + + RDPWrapper-$(Platform) + + 26.3.31 + + PackageVersion=$(PackageVersion) + + ICE61 + + diff --git a/msi/RDPWInst.wxs b/msi/RDPWInst.wxs new file mode 100644 index 0000000..664acea --- /dev/null +++ b/msi/RDPWInst.wxs @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msi/global.json b/msi/global.json new file mode 100644 index 0000000..cb8627f --- /dev/null +++ b/msi/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "WixToolset.Sdk": "5.0.2" + } +} diff --git a/res/rdpwrap-arm-kb.ini b/msi/rdpwrap-arm-kb.ini similarity index 100% rename from res/rdpwrap-arm-kb.ini rename to msi/rdpwrap-arm-kb.ini diff --git a/res/rdpwrap.ini b/msi/rdpwrap.ini similarity index 93% rename from res/rdpwrap.ini rename to msi/rdpwrap.ini index 40e1b54..b651523 100644 --- a/res/rdpwrap.ini +++ b/msi/rdpwrap.ini @@ -2,7 +2,7 @@ ; Do not modify without special knowledge [Main] -Updated=2018-10-10 +Updated=2026-04-02 LogFile=\rdpwrap.txt SLPolicyHookNT60=1 SLPolicyHookNT61=1 @@ -28,6 +28,7 @@ nop=90 Zero=00 jmpshort=EB nopjmp=90E9 +mov_eax_1_nop_2=B8010000009090 CDefPolicy_Query_edx_ecx=BA000100008991200300005E90 CDefPolicy_Query_eax_rcx_jmp=B80001000089813806000090EB CDefPolicy_Query_eax_esi=B80001000089862003000090 @@ -4996,3 +4997,376 @@ bRemoteConnAllowed.x64=ECAC4 bMultimonAllowed.x64 =ECAC8 ulMaxDebugSessions.x64=ECACC bFUSEnabled.x64 =ECAD0 + +; ====================================================================== +; Windows 11 Configurations (Latest Community Updates) +; ====================================================================== + +[10.0.26100.6899] +SingleUserPatch.x64=1 +SingleUserOffset.x64=9EFEB +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9C40F +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=92381 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B2C88 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.6899-SLInit] +bServerSku.x64=125F74 +bRemoteConnAllowed.x64=125F88 +bFUSEnabled.x64=125F98 +bAppServerAllowed.x64=125F80 +bMultimonAllowed.x64=125F8C +lMaxUserSessions.x64=125F78 +ulMaxDebugSessions.x64=125F94 +bInitialized.x64=125F70 + +[10.0.26100.7051] +SingleUserPatch.x64=1 +SingleUserOffset.x64=9F23B +SingleUserCode.x64=Zero +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9C68F +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=92601 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B2FB8 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7051-SLInit] +bServerSku.x64=125F84 +bRemoteConnAllowed.x64=125F98 +bFUSEnabled.x64=125FA8 +bAppServerAllowed.x64=125F90 +bMultimonAllowed.x64=125F9C +lMaxUserSessions.x64=125F88 +ulMaxDebugSessions.x64=125FA4 +bInitialized.x64=125F80 + +[10.0.26100.7262] +SingleUserPatch.x64=1 +SingleUserOffset.x64=A04AB +SingleUserCode.x64=Zero +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9D8FF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=93841 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B4228 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7262-SLInit] +bServerSku.x64=127F94 +bRemoteConnAllowed.x64=127FA8 +bFUSEnabled.x64=127FB8 +bAppServerAllowed.x64=127FA0 +bMultimonAllowed.x64=127FAC +lMaxUserSessions.x64=127F98 +ulMaxDebugSessions.x64=127FB4 +bInitialized.x64=127F90 + +[10.0.26100.7271] +SingleUserPatch.x64=1 +SingleUserOffset.x64=A04AB +SingleUserCode.x64=Zero +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9D8FF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=93841 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B4228 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7271-SLInit] +bServerSku.x64=127F94 +bRemoteConnAllowed.x64=127FA8 +bFUSEnabled.x64=127FB8 +bAppServerAllowed.x64=127FA0 +bMultimonAllowed.x64=127FAC +lMaxUserSessions.x64=127F98 +ulMaxDebugSessions.x64=127FB4 +bInitialized.x64=127F90 + +[10.0.26100.7296] +SingleUserPatch.x64=1 +SingleUserOffset.x64=A05DB +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9CB3F +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=92AC1 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B4844 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7296-SLInit] +bServerSku.x64=127094 +bRemoteConnAllowed.x64=1270AC +bFUSEnabled.x64=1270BC +bAppServerAllowed.x64=1270A0 +bMultimonAllowed.x64=1270B0 +lMaxUserSessions.x64=127098 +ulMaxDebugSessions.x64=1270B8 +bInitialized.x64=127090 + +[10.0.26100.7309] +; Windows 11 25H2 build 7309 - community configuration +SingleUserPatch.x64=1 +SingleUserOffset.x64=A05DB +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9CB3F +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=92AC1 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B4844 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7309-SLInit] +bServerSku.x64=127094 +bRemoteConnAllowed.x64=1270AC +bFUSEnabled.x64=1270BC +bAppServerAllowed.x64=1270A0 +bMultimonAllowed.x64=1270B0 +lMaxUserSessions.x64=127098 +ulMaxDebugSessions.x64=1270B8 +bInitialized.x64=127090 + +[10.0.26100.7344] +SingleUserPatch.x64=1 +SingleUserOffset.x64=A020B +SingleUserCode.x64=Zero +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9D65F +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=935A1 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B3F88 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7344-SLInit] +bServerSku.x64=127F84 +bRemoteConnAllowed.x64=127F98 +bFUSEnabled.x64=127FA8 +bAppServerAllowed.x64=127F90 +bMultimonAllowed.x64=127F9C +lMaxUserSessions.x64=127F88 +ulMaxDebugSessions.x64=127FA4 +bInitialized.x64=127F80 + +[10.0.26100.7523] +SingleUserPatch.x64=1 +SingleUserOffset.x64=9F96B +SingleUserCode.x64=Zero +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9BEFF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=91E81 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B3B48 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7523-SLInit] +bServerSku.x64=126054 +bRemoteConnAllowed.x64=126068 +bFUSEnabled.x64=126078 +bAppServerAllowed.x64=12605C +bMultimonAllowed.x64=12606C +lMaxUserSessions.x64=126058 +ulMaxDebugSessions.x64=126074 +bInitialized.x64=126050 + +[10.0.26100.7535] +SingleUserPatch.x64=1 +SingleUserOffset.x64=A059B +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9CAFF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=92A81 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B4804 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7535-SLInit] +bServerSku.x64=127094 +bRemoteConnAllowed.x64=1270AC +bFUSEnabled.x64=1270BC +bAppServerAllowed.x64=1270A0 +bMultimonAllowed.x64=1270B0 +lMaxUserSessions.x64=127098 +ulMaxDebugSessions.x64=1270B8 +bInitialized.x64=127090 + +[10.0.26100.7623] +; Windows 11 25H2 build 7623 - LATEST BUILD (January 2026) +SingleUserPatch.x64=1 +SingleUserOffset.x64=A059B +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9CAFF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=92A81 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B4804 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.26100.7623-SLInit] +bServerSku.x64=127094 +bRemoteConnAllowed.x64=1270AC +bFUSEnabled.x64=1270BC +bAppServerAllowed.x64=1270A0 +bMultimonAllowed.x64=1270B0 +lMaxUserSessions.x64=127098 +ulMaxDebugSessions.x64=1270B8 +bInitialized.x64=127090 + +; ====================================================================== +; Windows 11 26H1 Insider Preview Builds +; ====================================================================== + +[10.0.28000.1340] +SingleUserPatch.x64=1 +SingleUserOffset.x64=9BA6B +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=98E0F +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=8F277 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=AE66C +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.28000.1340-SLInit] +bServerSku.x64=129FD4 +bRemoteConnAllowed.x64=129FE8 +bFUSEnabled.x64=129FF8 +bAppServerAllowed.x64=129FE0 +bMultimonAllowed.x64=129FEC +lMaxUserSessions.x64=129FD8 +ulMaxDebugSessions.x64=129FF4 +bInitialized.x64=129FD0 + +[10.0.28000.1362] +SingleUserPatch.x64=1 +SingleUserOffset.x64=9D44B +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9A7EF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=90C37 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B010C +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.28000.1362-SLInit] +bServerSku.x64=12B024 +bRemoteConnAllowed.x64=12B038 +bFUSEnabled.x64=12B048 +bAppServerAllowed.x64=12B030 +bMultimonAllowed.x64=12B03C +lMaxUserSessions.x64=12B028 +ulMaxDebugSessions.x64=12B044 +bInitialized.x64=12B020 + +[10.0.28000.1371] +; Windows 11 Insider Preview 26H1 - derived from 1362 +SingleUserPatch.x64=1 +SingleUserOffset.x64=9D44B +SingleUserCode.x64=mov_eax_1_nop_2 +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=9A7EF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=90C37 +LocalOnlyCode.x64=jmpshort +SLInitHook.x64=1 +SLInitOffset.x64=B010C +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.28000.1371-SLInit] +bServerSku.x64=12B024 +bRemoteConnAllowed.x64=12B038 +bFUSEnabled.x64=12B048 +bAppServerAllowed.x64=12B030 +bMultimonAllowed.x64=12B03C +lMaxUserSessions.x64=12B028 +ulMaxDebugSessions.x64=12B044 +bInitialized.x64=12B020 + +[10.0.19041.6456] +; Windows 10 21H1/21H2/22H2 with latest updates +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=8F511 +LocalOnlyCode.x64=jmpshort +SingleUserPatch.x64=1 +SingleUserOffset.x64=97CCB +SingleUserCode.x64=Zero +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=950FF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +SLInitHook.x64=1 +SLInitOffset.x64=AA2A8 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.19041.6456-SLInit] +bServerSku.x64=121F84 +bRemoteConnAllowed.x64=121F98 +bFUSEnabled.x64=121FA8 +bAppServerAllowed.x64=121F90 +bMultimonAllowed.x64=121F9C +lMaxUserSessions.x64=121F88 +ulMaxDebugSessions.x64=121FA4 +bInitialized.x64=121F80 + +[10.0.19045.6466] +; Windows 10 22H2 Latest +LocalOnlyPatch.x64=1 +LocalOnlyOffset.x64=8F511 +LocalOnlyCode.x64=jmpshort +SingleUserPatch.x64=1 +SingleUserOffset.x64=97CCB +SingleUserCode.x64=Zero +DefPolicyPatch.x64=1 +DefPolicyOffset.x64=950FF +DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp +SLInitHook.x64=1 +SLInitOffset.x64=AA2A8 +SLInitFunc.x64=New_CSLQuery_Initialize + +[10.0.19045.6466-SLInit] +bServerSku.x64=121F84 +bRemoteConnAllowed.x64=121F98 +bFUSEnabled.x64=121FA8 +bAppServerAllowed.x64=121F90 +bMultimonAllowed.x64=121F9C +lMaxUserSessions.x64=121F88 +ulMaxDebugSessions.x64=121FA4 +bInitialized.x64=121F80 diff --git a/res/RDPWInst.wxs b/res/RDPWInst.wxs deleted file mode 100644 index 9352ffc..0000000 --- a/res/RDPWInst.wxs +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NOT Installed AND NOT WIX_UPGRADE_DETECTED - REMOVE AND NOT UPGRADINGPRODUCTCODE - UPGRADINGPRODUCTCODE - - - - - diff --git a/res/build_wxs.bat b/res/build_wxs.bat deleted file mode 100644 index 9eeef72..0000000 --- a/res/build_wxs.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off -"%ProgramFiles%\WiX Toolset v3.11\bin\candle" RDPWInst.wxs -"%ProgramFiles%\WiX Toolset v3.11\bin\light" RDPWInst.wixobj diff --git a/res/clearres.bat b/res/clearres.bat deleted file mode 100644 index 278e6cd..0000000 --- a/res/clearres.bat +++ /dev/null @@ -1,19 +0,0 @@ -@echo off -echo [FILENAMES]> clearres.txt -echo Exe=%1>> clearres.txt -echo SaveAs=%1>> clearres.txt -echo Log=>> clearres.txt -echo.>> clearres.txt -echo [COMMANDS]>> clearres.txt -echo -delete RCDATA,CHARTABLE,>> clearres.txt -echo -delete RCDATA,DVCLAL,>> clearres.txt -echo -delete RCDATA,PACKAGEINFO,>> clearres.txt -echo -delete CURSORGROUP,32761,>> clearres.txt -echo -delete CURSORGROUP,32762,>> clearres.txt -echo -delete CURSORGROUP,32763,>> clearres.txt -echo -delete CURSORGROUP,32764,>> clearres.txt -echo -delete CURSORGROUP,32765,>> clearres.txt -echo -delete CURSORGROUP,32766,>> clearres.txt -echo -delete CURSORGROUP,32767,>> clearres.txt -"C:\Program Files\Resource Hacker\ResHacker.exe" -script clearres.txt -del clearres.txt diff --git a/res/legacy.install.bat b/res/legacy.install.bat deleted file mode 100644 index 303cc32..0000000 --- a/res/legacy.install.bat +++ /dev/null @@ -1,92 +0,0 @@ -@echo off -setlocal EnableDelayedExpansion -echo RDP Wrapper Library Installer v1.0 -echo Copyright (C) Stas'M Corp. 2013 -echo. - -set PROCESSOR_ARCHITECTURE | find "x86" > nul -if !errorlevel!==0 ( - goto WOW64CHK -) else ( - goto UNSUPPORTED -) - -:WOW64CHK -echo [*] Check if running WOW64 subsystem... -set PROCESSOR_ARCHITEW6432 > nul -if !errorlevel!==0 ( - goto UNSUPPORTED -) else ( - goto SUPPORTED -) - -:SUPPORTED -echo [+] Processor architecture is Intel x86 [supported] -goto INSTALL - -:UNSUPPORTED -echo [-] Unsupported processor architecture -goto END - -:INSTALL -echo [*] Installing... -if not exist rdpwrap.dll ( - echo [-] Error: rdpwrap.dll file not found - goto END -) -echo [*] Copying file to Program Files... -md "%ProgramFiles%\RDP Wrapper" -xcopy /y rdpwrap.dll "%ProgramFiles%\RDP Wrapper\" -if not !errorlevel!==0 ( - echo [-] Failed to copy rdpwrap.dll to Program Files folder - goto END -) -echo [*] Modifying registry... -reg add "HKLM\SYSTEM\CurrentControlSet\Services\TermService\Parameters" /v ServiceDll /t REG_EXPAND_SZ /d "%ProgramFiles%\RDP Wrapper\rdpwrap.dll" /f -if not !errorlevel!==0 ( - echo [-] Failed to modify registry - goto END -) -echo [*] Setting firewall configuration... -reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f -netsh advfirewall firewall add rule name="Remote Desktop" dir=in protocol=tcp localport=3389 profile=any action=allow -netsh advfirewall firewall add rule name="Remote Desktop" dir=in protocol=udp localport=3389 profile=any action=allow -echo [*] Looking for TermService PID... -tasklist /SVC /FI "SERVICES eq TermService" | find "PID" /V -echo. -if !errorlevel!==0 ( - goto DONE -) else ( - goto SVCSTART -) - -:SVCSTART -echo [*] TermService is stopped. Starting it... -sc config TermService start= auto | find "1060" > nul -if !errorlevel!==0 ( - echo [-] TermService is not installed. You need to install it manually. - goto END -) else ( - net start TermService - goto DONE -) - -:DONE -echo [+] Installation complete! -echo Now reboot or restart service. -echo. -echo To reboot computer type: -echo shutdown /r -echo. -echo To restart TermService type: -echo taskkill /f /pid 1234 ^(replace 1234 with real PID which is shown above^) -echo net start TermService -echo. -echo If second method is used, and there are another services sharing svchost.exe, -echo you must start it too: -echo net start Service1 -echo net start Service2 -echo etc. -goto END - -:END diff --git a/res/rdpwrap-ini-kb.txt b/res/rdpwrap-ini-kb.txt deleted file mode 100644 index a258ab4..0000000 --- a/res/rdpwrap-ini-kb.txt +++ /dev/null @@ -1,6289 +0,0 @@ -[Main] -; Last updated date -Updated=2018-10-10 -; Address to log file (RDP Wrapper will write it, if exists) -LogFile=\rdpwrap.txt -; Hook SLPolicy API on Windows NT 6.0 -SLPolicyHookNT60=1 -; Hook SLPolicy API on Windows NT 6.1 -SLPolicyHookNT61=1 - -[SLPolicy] -; Allow Remote Connections -TerminalServices-RemoteConnectionManager-AllowRemoteConnections=1 -; Allow Multiple Sessions -TerminalServices-RemoteConnectionManager-AllowMultipleSessions=1 -; Allow Multiple Sessions (Application Server Mode) -TerminalServices-RemoteConnectionManager-AllowAppServerMode=1 -; Allow Multiple Monitors -TerminalServices-RemoteConnectionManager-AllowMultimon=1 -; Max User Sessions (0 = unlimited) -TerminalServices-RemoteConnectionManager-MaxUserSessions=0 -; Max Debug Sessions (Windows 8, 0 = unlimited) -TerminalServices-RemoteConnectionManager-ce0ad219-4670-4988-98fb-89b14c2f072b-MaxSessions=0 -; Max Sessions -; 0 - logon not possible even from console -; 1 - only one active user (console or remote) -; 2 - allow concurrent sessions -TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-MaxSessions=2 -; Allow Advanced Compression with RDP 7 Protocol -TerminalServices-RDP-7-Advanced-Compression-Allowed=1 -; IsTerminalTypeLocalOnly = 0 -TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-LocalOnly=0 -; Max Sessions (hard limit) -TerminalServices-RemoteConnectionManager-8dc86f1d-9969-4379-91c1-06fe1dc60575-MaxSessions=1000 -; Allow EasyPrint -TerminalServices-DeviceRedirection-Licenses-TSEasyPrintAllowed=1 -; Allow PnP Redirection -TerminalServices-DeviceRedirection-Licenses-PnpRedirectionAllowed=1 -; Allow Media Foundation plugins -TerminalServices-DeviceRedirection-Licenses-TSMFPluginAllowed=1 -; Allow DWM Remoting -TerminalServices-RemoteConnectionManager-UiEffects-DWMRemotingAllowed=1 - -[PatchCodes] -nop=90 -Zero=00 -jmpshort=EB -nopjmp=90E9 -CDefPolicy_Query_edx_ecx=BA000100008991200300005E90 -CDefPolicy_Query_eax_rcx_jmp=B80001000089813806000090EB -CDefPolicy_Query_eax_esi=B80001000089862003000090 -CDefPolicy_Query_eax_rdi=B80001000089873806000090 -CDefPolicy_Query_eax_ecx=B80001000089812003000090 -CDefPolicy_Query_eax_ecx_jmp=B800010000898120030000EB0E -CDefPolicy_Query_eax_rcx=B80001000089813806000090 -CDefPolicy_Query_edi_rcx=BF0001000089B938060000909090 - -[6.0.6000.16386] -; HOW TO search CSessionArbitrationHelper::IsSingleSessionPerUserEnabled function in IDA Pro: -; 1. Search text: CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; 2. All xrefs will point to this function (in x64 version xref points to subroutine, so you need to go one level up) -; 3. Go to first graph block and find memset, VersionInformation, call GetVersionExW, and so on - -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F320000 -; .text:6F3360B9 lea eax, [ebp+VersionInformation] -; .text:6F3360BF inc ebx <- nop -; .text:6F3360C0 push eax ; lpVersionInformation -; .text:6F3360C1 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F3360CB mov [esi], ebx -; .text:6F3360CD call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=160BF -SingleUserCode.x86=nop -; Imagebase: 7FF756E0000 -; .text:000007FF75745E38 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75745E3D mov ebx, 1 <- 0 -; .text:000007FF75745E42 mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75745E4A mov [rdi], ebx -; .text:000007FF75745E4C call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=65E3E -SingleUserCode.x64=Zero -; HOW TO search CDefPolicy::Query function in IDA Pro: -; 1. Search text: CDefPolicy::Query -; 2. All xrefs will point to this function (in x64 version xref sometimes points to subroutine, so you need to go one level up) -; 3. Go to first graph block and find cmp/jz instructions on the bottom of block - -; Patch CDefPolicy::Query -; Original -; .text:6F335CD8 cmp edx, [ecx+320h] -; .text:6F335CDE pop esi -; .text:6F335CDF jz loc_6F3426F1 -; Changed -; .text:6F335CD8 mov edx, 100h -; .text:6F335CDD mov [ecx+320h], edx -; .text:6F335CE3 pop esi -; .text:6F335CE4 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=15CD8 -DefPolicyCode.x86=CDefPolicy_Query_edx_ecx -; Original -; .text:000007FF7573C88F mov eax, [rcx+638h] -; .text:000007FF7573C895 cmp [rcx+63Ch], eax -; .text:000007FF7573C89B jnz short loc_7FF7573C8B3 -; Changed -; .text:000007FF7573C88F mov eax, 100h -; .text:000007FF7573C894 mov [rcx+638h], eax -; .text:000007FF7573C89A nop -; .text:000007FF7573C89B jmp short loc_7FF7573C8B3 -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=5C88F -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp - -[6.0.6001.18000] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6E800000 -; .text:6E8185DE lea eax, [ebp+VersionInformation] -; .text:6E8185E4 inc ebx <- nop -; .text:6E8185E5 push eax ; lpVersionInformation -; .text:6E8185E6 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6E8185F0 mov [esi], ebx -; .text:6E8185F2 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=185E4 -SingleUserCode.x86=nop -; Imagebase: 7FF76220000 -; .text:000007FF76290DB4 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF76290DB9 mov ebx, 1 <- 0 -; .text:000007FF76290DBE mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF76290DC6 mov [rdi], ebx -; .text:000007FF76290DC8 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=70DBA -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6E817FD8 cmp edx, [ecx+320h] -; .text:6E817FDE pop esi -; .text:6E817FDF jz loc_6E826F16 -; Changed -; .text:6E817FD8 mov edx, 100h -; .text:6E817FDD mov [ecx+320h], edx -; .text:6E817FE3 pop esi -; .text:6E817FE4 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=17FD8 -DefPolicyCode.x86=CDefPolicy_Query_edx_ecx -; Original -; .text:000007FF76285BD7 mov eax, [rcx+638h] -; .text:000007FF76285BDD cmp [rcx+63Ch], eax -; .text:000007FF76285BE3 jnz short loc_7FF76285BFB -; Changed -; .text:000007FF76285BD7 mov eax, 100h -; .text:000007FF76285BDC mov [rcx+638h], eax -; .text:000007FF76285BE2 nop -; .text:000007FF76285BE3 jmp short loc_7FF76285BFB -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=65BD7 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp - -[6.0.6002.18005] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F580000 -; .text:6F597FA2 lea eax, [ebp+VersionInformation] -; .text:6F597FA8 inc ebx <- nop -; .text:6F597FA9 push eax ; lpVersionInformation -; .text:6F597FAA mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F597FB4 mov [esi], ebx -; .text:6F597FB6 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=17FA8 -SingleUserCode.x86=nop -; Imagebase: 7FF766C0000 -; .text:000007FF76730FF0 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF76730FF5 mov ebx, 1 <- 0 -; .text:000007FF76730FFA mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF76731002 mov [rdi], ebx -; .text:000007FF76731004 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=70FF6 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F5979C0 cmp edx, [ecx+320h] -; .text:6F5979C6 pop esi -; .text:6F5979C7 jz loc_6F5A6F26 -; Changed -; .text:6F5979C0 mov edx, 100h -; .text:6F5979C5 mov [ecx+320h], edx -; .text:6F5979CB pop esi -; .text:6F5979CC nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=179C0 -DefPolicyCode.x86=CDefPolicy_Query_edx_ecx -; Original -; .text:000007FF76725E83 mov eax, [rcx+638h] -; .text:000007FF76725E89 cmp [rcx+63Ch], eax -; .text:000007FF76725E8F jz short loc_7FF76725EA7 -; Changed -; .text:000007FF76725E83 mov eax, 100h -; .text:000007FF76725E88 mov [rcx+638h], eax -; .text:000007FF76725E8E nop -; .text:000007FF76725E8F jmp short loc_7FF76725EA7 -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=65E83 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp - -[6.0.6002.19214] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F580000 -; .text:6F597FBE lea eax, [ebp+VersionInformation] -; .text:6F597FC4 inc ebx <- nop -; .text:6F597FC5 push eax ; lpVersionInformation -; .text:6F597FC6 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F597FD0 mov [esi], ebx -; .text:6F597FD2 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=17FC4 -SingleUserCode.x86=nop -; Imagebase: 7FF75AC0000 -; .text:000007FF75B312A4 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75B312A9 mov ebx, 1 <- 0 -; .text:000007FF75B312AE mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75B312B6 mov [rdi], ebx -; .text:000007FF75B312B8 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=712AA -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F5979B8 cmp edx, [ecx+320h] -; .text:6F5979BE pop esi -; .text:6F5979BF jz loc_6F5A6F3E -; Changed -; .text:6F5979B8 mov edx, 100h -; .text:6F5979BD mov [ecx+320h], edx -; .text:6F5979C3 pop esi -; .text:6F5979C4 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=179B8 -DefPolicyCode.x86=CDefPolicy_Query_edx_ecx -; Original -; .text:000007FF75B25FF7 mov eax, [rcx+638h] -; .text:000007FF75B25FFD cmp [rcx+63Ch], eax -; .text:000007FF75B26003 jnz short loc_7FF75B2601B -; Changed -; .text:000007FF75B25FF7 mov eax, 100h -; .text:000007FF75B25FFC mov [rcx+638h], eax -; .text:000007FF75B26002 nop -; .text:000007FF75B26003 jmp short loc_7FF75B2601B -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=65FF7 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp - -[6.0.6002.23521] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F580000 -; .text:6F597FAE lea eax, [ebp+VersionInformation] -; .text:6F597FB4 inc ebx <- nop -; .text:6F597FB5 push eax ; lpVersionInformation -; .text:6F597FB6 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F597FC0 mov [esi], ebx -; .text:6F597FC2 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=17FB4 -SingleUserCode.x86=nop -; Imagebase: 7FF75AC0000 -; .text:000007FF75B31EA4 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75B31EA9 mov ebx, 1 <- 0 -; .text:000007FF75B31EAE mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75B31EB6 mov [rdi], ebx -; .text:000007FF75B31EB8 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=71EAA -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F5979CC cmp edx, [ecx+320h] -; .text:6F5979D2 pop esi -; .text:6F5979D3 jz loc_6F5A6F2E -; Changed -; .text:6F5979CC mov edx, 100h -; .text:6F5979D1 mov [ecx+320h], edx -; .text:6F5979D7 pop esi -; .text:6F5979D8 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=179CC -DefPolicyCode.x86=CDefPolicy_Query_edx_ecx -; Original -; .text:000007FF75B269CB mov eax, [rcx+638h] -; .text:000007FF75B269D1 cmp [rcx+63Ch], eax -; .text:000007FF75B269D7 jnz short loc_7FF75B269EF -; Changed -; .text:000007FF75B269CB mov eax, 100h -; .text:000007FF75B269D0 mov [rcx+638h], eax -; .text:000007FF75B269D6 nop -; .text:000007FF75B269D7 jmp short loc_7FF75B269EF -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=669CB -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx_jmp - -[6.1.7600.16385] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F2E0000 -; .text:6F2F9E1F lea eax, [ebp+VersionInformation] -; .text:6F2F9E25 inc ebx <- nop -; .text:6F2F9E26 push eax ; lpVersionInformation -; .text:6F2F9E27 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F2F9E31 mov [esi], ebx -; .text:6F2F9E33 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=19E25 -SingleUserCode.x86=nop -; Imagebase: 7FF75A80000 -; .text:000007FF75A97D90 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75A97D95 mov ebx, 1 <- 0 -; .text:000007FF75A97D9A mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75A97DA2 mov [rdi], ebx -; .text:000007FF75A97DA4 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=17D96 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F2F96F3 cmp eax, [esi+320h] -; .text:6F2F96F9 jz loc_6F30E256 -; Changed -; .text:6F2F96F3 mov eax, 100h -; .text:6F2F96F8 mov [esi+320h], eax -; .text:6F2F96FE nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=196F3 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000007FF75A97AD2 cmp [rdi+63Ch], eax -; .text:000007FF75A97AD8 jz loc_7FF75AA4978 -; Changed -; .text:000007FF75A97AD2 mov eax, 100h -; .text:000007FF75A97AD7 mov [rdi+638h], eax -; .text:000007FF75A97ADD nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17AD2 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7600.20890] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=19E2D -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=17DF2 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=196FB -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17B0E -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7600.21316] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=19E2D -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=17E3E -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=196FB -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17B5E -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.17514] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F2E0000 -; .text:6F2FA497 lea eax, [ebp+VersionInformation] -; .text:6F2FA49D inc ebx <- nop -; .text:6F2FA49E push eax ; lpVersionInformation -; .text:6F2FA49F mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F2FA4A9 mov [esi], ebx -; .text:6F2FA4AB call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A49D -SingleUserCode.x86=nop -; Imagebase: 7FF75A80000 -; .text:000007FF75A980DC lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75A980E1 mov ebx, 1 <- 0 -; .text:000007FF75A980E6 mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75A980EE mov [rdi], ebx -; .text:000007FF75A980F0 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=180E2 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F2F9D53 cmp eax, [esi+320h] -; .text:6F2F9D59 jz loc_6F30B25E -; Changed -; .text:6F2F9D53 mov eax, 100h -; .text:6F2F9D58 mov [esi+320h], eax -; .text:6F2F9D5E nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19D53 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000007FF75A97D8A cmp [rdi+63Ch], eax -; .text:000007FF75A97D90 jz loc_7FF75AA40F4 -; Changed -; .text:000007FF75A97D8A mov eax, 100h -; .text:000007FF75A97D8F mov [rdi+638h], eax -; .text:000007FF75A97D95 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17D8A -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.18540] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F2E0000 -; .text:6F2FA4DF lea eax, [ebp+VersionInformation] -; .text:6F2FA4E5 inc ebx <- nop -; .text:6F2FA4E6 push eax ; lpVersionInformation -; .text:6F2FA4E7 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F2FA4F1 mov [esi], ebx -; .text:6F2FA4F3 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A4E5 -SingleUserCode.x86=nop -; Imagebase: 7FF75A80000 -; .text:000007FF75A98000 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75A98005 mov ebx, 1 <- 0 -; .text:000007FF75A9800A mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75A98012 mov [rdi], ebx -; .text:000007FF75A98014 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=18006 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F2F9D9F cmp eax, [esi+320h] -; .text:6F2F9DA5 jz loc_6F30B2AE -; Changed -; .text:6F2F9D9F mov eax, 100h -; .text:6F2F9DA4 mov [esi+320h], eax -; .text:6F2F9DAA nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19D9F -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000007FF75A97C82 cmp [rdi+63Ch], eax -; .text:000007FF75A97C88 jz loc_7FF75AA3FBD -; Changed -; .text:000007FF75A97C82 mov eax, 100h -; .text:000007FF75A97C87 mov [rdi+638h], eax -; .text:000007FF75A97C8D nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17C82 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.22750] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F2E0000 -; .text:6F2FA64F lea eax, [ebp+VersionInformation] -; .text:6F2FA655 inc ebx <- nop -; .text:6F2FA656 push eax ; lpVersionInformation -; .text:6F2FA657 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F2FA661 mov [esi], ebx -; .text:6F2FA663 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A655 -SingleUserCode.x86=nop -; Imagebase: 7FF75A80000 -; .text:000007FF75A97E88 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75A97E8D mov ebx, 1 <- 0 -; .text:000007FF75A97E92 mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75A97E9A mov [rdi], ebx -; .text:000007FF75A97E9C call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=17E8E -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F2F9E21 cmp eax, [esi+320h] -; .text:6F2F9E27 jz loc_6F30B6CE -; Changed -; .text:6F2F9E21 mov eax, 100h -; .text:6F2F9E26 mov [esi+320h], eax -; .text:6F2F9E2C nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19E21 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000007FF75A97C92 cmp [rdi+63Ch], eax -; .text:000007FF75A97C98 jz loc_7FF75AA40A2 -; Changed -; .text:000007FF75A97C92 mov eax, 100h -; .text:000007FF75A97C97 mov [rdi+638h], eax -; .text:000007FF75A97C9D nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17C92 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.18637] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F2E0000 -; .text:6F2FA4D7 lea eax, [ebp+VersionInformation] -; .text:6F2FA4DD inc ebx <- nop -; .text:6F2FA4DE push eax ; lpVersionInformation -; .text:6F2FA4DF mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F2FA4E9 mov [esi], ebx -; .text:6F2FA4EB call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A4DD -SingleUserCode.x86=nop -; Imagebase: 7FF75A80000 -; .text:000007FF75A980F4 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75A980F9 mov ebx, 1 <- 0 -; .text:000007FF75A980FE mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75A98106 mov [rdi], ebx -; .text:000007FF75A98108 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=180FA -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F2F9DBB cmp eax, [esi+320h] -; .text:6F2F9DC1 jz loc_6F30B2A6 -; Changed -; .text:6F2F9DBB mov eax, 100h -; .text:6F2F9DC0 mov [esi+320h], eax -; .text:6F2F9DC6 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19DBB -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000007FF75A97DC6 cmp [rdi+63Ch], eax -; .text:000007FF75A97DCC jz loc_7FF75AA40BD -; Changed -; .text:000007FF75A97DC6 mov eax, 100h -; .text:000007FF75A97DCB mov [rdi+638h], eax -; .text:000007FF75A97DD1 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17DC6 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.21650] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A49D -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=180BE -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19D53 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17D5A -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.21866] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A49D -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=180BE -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19D53 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17D5A -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.22104] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A49D -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=180C6 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19D53 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17D5E -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.22843] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; Imagebase: 6F2E0000 -; .text:6F2FA64F lea eax, [ebp+VersionInformation] -; .text:6F2FA655 inc ebx <- nop -; .text:6F2FA656 push eax ; lpVersionInformation -; .text:6F2FA657 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:6F2FA661 mov [esi], ebx -; .text:6F2FA663 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A655 -SingleUserCode.x86=nop -; Imagebase: 7FF75A80000 -; .text:000007FF75A97F90 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation -; .text:000007FF75A97F95 mov ebx, 1 <- 0 -; .text:000007FF75A97F9A mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000007FF75A97FA2 mov [rdi], ebx -; .text:000007FF75A97FA4 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=17F96 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:6F2F9E25 cmp eax, [esi+320h] -; .text:6F2F9E2B jz loc_6F30B6D6 -; Changed -; .text:6F2F9E25 mov eax, 100h -; .text:6F2F9E2A mov [esi+320h], eax -; .text:6F2F9E30 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19E25 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000007FF75A97D6E cmp [rdi+63Ch], eax -; .text:000007FF75A97D74 jz loc_7FF75AA4182 -; Changed -; .text:000007FF75A97D6E mov eax, 100h -; .text:000007FF75A97D73 mov [rdi+638h], eax -; .text:000007FF75A97D79 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17D6E -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.23403] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A65D -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=17F62 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19E29 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17CE2 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.1.7601.24234] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=1A675 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=17F56 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=19E41 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17D2E -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi - -[6.2.8102.0] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:1000F7E5 lea eax, [esp+150h+VersionInformation] -; .text:1000F7E9 inc esi <- nop -; .text:1000F7EA push eax ; lpVersionInformation -; .text:1000F7EB mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:1000F7F3 mov [edi], esi -; .text:1000F7F5 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=F7E9 -SingleUserCode.x86=nop -; .text:000000018000D83A lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation -; .text:000000018000D83F mov ebx, 1 <- 0 -; .text:000000018000D844 mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000000018000D84C mov [rdi], ebx -; .text:000000018000D84E call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=D840 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1000E47C cmp eax, [esi+320h] -; .text:1000E482 jz loc_1002D775 -; Changed -; .text:1000E47C mov eax, 100h -; .text:1000E481 mov [esi+320h], eax -; .text:1000E487 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=E47C -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000000018000D3E6 cmp [rdi+63Ch], eax -; .text:000000018000D3EC jz loc_180027792 -; Changed -; .text:000000018000D3E6 mov eax, 100h -; .text:000000018000D3EB mov [rdi+638h], eax -; .text:000000018000D3F1 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=D3E6 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi -; Hook SLGetWindowsInformationDWORDWrapper -SLPolicyInternal.x86=1 -SLPolicyOffset.x86=1B909 -SLPolicyFunc.x86=New_Win8SL -SLPolicyInternal.x64=1 -SLPolicyOffset.x64=1A484 -SLPolicyFunc.x64=New_Win8SL - -[6.2.8250.0] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:100159C5 lea eax, [esp+150h+VersionInformation] -; .text:100159C9 inc esi <- nop -; .text:100159CA push eax ; lpVersionInformation -; .text:100159CB mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:100159D3 mov [edi], esi -; .text:100159D5 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=159C9 -SingleUserCode.x86=nop -; .text:0000000180011E6E lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation -; .text:0000000180011E73 mov ebx, 1 <- 0 -; .text:0000000180011E78 mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180011E80 mov [rdi], ebx -; .text:0000000180011E82 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=11E74 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:10013520 cmp eax, [esi+320h] -; .text:10013526 jz loc_1002DB85 -; Changed -; .text:10013520 mov eax, 100h -; .text:10013525 mov [esi+320h], eax -; .text:1001352B nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=13520 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000000018001187A cmp [rdi+63Ch], eax -; .text:0000000180011880 jz loc_1800273A2 -; Changed -; .text:000000018001187A mov eax, 100h -; .text:000000018001187F mov [rdi+638h], eax -; .text:0000000180011885 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1187A -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi -; Hook SLGetWindowsInformationDWORDWrapper -SLPolicyInternal.x86=1 -SLPolicyOffset.x86=1A0A9 -SLPolicyFunc.x86=New_Win8SL_CP -SLPolicyInternal.x64=1 -SLPolicyOffset.x64=18FAC -SLPolicyFunc.x64=New_Win8SL - -[6.2.8400.0] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:1001547E lea eax, [esp+150h+VersionInformation] -; .text:10015482 inc esi <- nop -; .text:10015483 push eax ; lpVersionInformation -; .text:10015484 mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:1001548C mov [edi], esi -; .text:1001548E call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=15482 -SingleUserCode.x86=nop -; .text:000000018002081E lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation -; .text:0000000180020823 mov ebx, 1 <- 0 -; .text:0000000180020828 mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180020830 mov [rdi], ebx -; .text:0000000180020832 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=20824 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:10013E48 cmp eax, [esi+320h] -; .text:10013E4E jz loc_1002E079 -; Changed -; .text:10013E48 mov eax, 100h -; .text:10013E4D mov [esi+320h], eax -; .text:10013E53 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=13E48 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000000018001F102 cmp [rdi+63Ch], eax -; .text:000000018001F108 jz loc_18003A02E -; Changed -; .text:000000018001F102 mov eax, 100h -; .text:000000018001F107 mov [rdi+638h], eax -; .text:000000018001F10D nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1F102 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi -; Hook SLGetWindowsInformationDWORDWrapper -SLPolicyInternal.x86=1 -SLPolicyOffset.x86=19629 -SLPolicyFunc.x86=New_Win8SL -SLPolicyInternal.x64=1 -SLPolicyOffset.x64=2492C -SLPolicyFunc.x64=New_Win8SL - -[6.2.9200.16384] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:1001554E lea eax, [esp+150h+VersionInformation] -; .text:10015552 inc esi <- nop -; .text:10015553 push eax ; lpVersionInformation -; .text:10015554 mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:1001555C mov [edi], esi -; .text:1001555E call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=15552 -SingleUserCode.x86=nop -; .text:000000018002BAA2 lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation -; .text:000000018002BAA7 mov ebx, 1 <- 0 -; .text:000000018002BAAC mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000000018002BAB4 mov [rdi], ebx -; .text:000000018002BAB6 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=2BAA8 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:10013F08 cmp eax, [esi+320h] -; .text:10013F0E jz loc_1002E161 -; Changed -; .text:10013F08 mov eax, 100h -; .text:10013F0D mov [esi+320h], eax -; .text:10013F13 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=13F08 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000000018002A31A cmp [rdi+63Ch], eax -; .text:000000018002A320 jz loc_18003A0F9 -; Changed -; .text:000000018002A31A mov eax, 100h -; .text:000000018002A31F mov [rdi+638h], eax -; .text:000000018002A325 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=2A31A -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi -; Hook SLGetWindowsInformationDWORDWrapper -SLPolicyInternal.x86=1 -SLPolicyOffset.x86=19559 -SLPolicyFunc.x86=New_Win8SL -SLPolicyInternal.x64=1 -SLPolicyOffset.x64=21FA8 -SLPolicyFunc.x64=New_Win8SL - -[6.2.9200.17048] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:1002058E lea eax, [esp+150h+VersionInformation] -; .text:10020592 inc esi <- nop -; .text:10020593 push eax ; lpVersionInformation -; .text:10020594 mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:1002059C mov [edi], esi -; .text:1002059E call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=20592 -SingleUserCode.x86=nop -; .text:0000000180020942 lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation -; .text:0000000180020947 mov ebx, 1 <- 0 -; .text:000000018002094C mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180020954 mov [rdi], ebx -; .text:0000000180020956 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=20948 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1001F408 cmp eax, [esi+320h] -; .text:1001F40E jz loc_1002E201 -; Changed -; .text:1001F408 mov eax, 100h -; .text:1001F40D mov [esi+320h], eax -; .text:1001F413 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=1F408 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000000018001F206 cmp [rdi+63Ch], eax -; .text:000000018001F20C jz loc_18003A1B4 -; Changed -; .text:000000018001F206 mov eax, 100h -; .text:000000018001F20B mov [rdi+638h], eax -; .text:000000018001F211 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1F206 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi -; Hook SLGetWindowsInformationDWORDWrapper -SLPolicyInternal.x86=1 -SLPolicyOffset.x86=17059 -SLPolicyFunc.x86=New_Win8SL -SLPolicyInternal.x64=1 -SLPolicyOffset.x64=24570 -SLPolicyFunc.x64=New_Win8SL - -[6.2.9200.21166] -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10015576 lea eax, [esp+150h+VersionInformation] -; .text:1001557A inc esi <- nop -; .text:1001557B push eax ; lpVersionInformation -; .text:1001557C mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:10015584 mov [edi], esi -; .text:10015586 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=1557A -SingleUserCode.x86=nop -; .text:000000018002BAF2 lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation -; .text:000000018002BAF7 mov ebx, 1 <- 0 -; .text:000000018002BAFC mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000000018002BB04 mov [rdi], ebx -; .text:000000018002BB06 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=2BAF8 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:10013F30 cmp eax, [esi+320h] -; .text:10013F36 jz loc_1002E189 -; Changed -; .text:10013F30 mov eax, 100h -; .text:10013F35 mov [esi+320h], eax -; .text:10013F3B nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=13F30 -DefPolicyCode.x86=CDefPolicy_Query_eax_esi -; Original -; .text:000000018002A3B6 cmp [rdi+63Ch], eax -; .text:000000018002A3BC jz loc_18003A174 -; Changed -; .text:000000018002A3B6 mov eax, 100h -; .text:000000018002A3BB mov [rdi+638h], eax -; .text:000000018002A3C1 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=2A3B6 -DefPolicyCode.x64=CDefPolicy_Query_eax_rdi -; Hook SLGetWindowsInformationDWORDWrapper -SLPolicyInternal.x86=1 -SLPolicyOffset.x86=19581 -SLPolicyFunc.x86=New_Win8SL -SLPolicyInternal.x64=1 -SLPolicyOffset.x64=21FD0 -SLPolicyFunc.x64=New_Win8SL - -[6.3.9431.0] -; HOW TO search CEnforcementCore::GetInstanceOfTSLicense function in IDA Pro: -; 1. Search text: CSLQuery::IsLicenseTypeLocalOnly -; 2. All xrefs will point to this function -; 3. Go to function beginning and check ; CODE XREF string, it will point to GetInstanceOfTSLicense function -; 4. Follow CODE XREF, switch to graph view, the next block below is to patch -; Another way: -; 1. Search text: CEnforcementCore::GetInstanceOfTSLicense FAILED - License type me -; 2. All xrefs will point to GetInstanceOfTSLicense -; 3. Follow xref, the previous block above is to patch - -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:1008A604 call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:1008A609 test eax, eax -; .text:1008A60B js short loc_1008A628 -; .text:1008A60D cmp [ebp+var_8], 0 -; .text:1008A611 jz short loc_1008A628 <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=8A611 -LocalOnlyCode.x86=jmpshort -; .text:000000018009F713 call ?IsLicenseTypeLocalOnly@CSLQuery@@SAJAEAU_GUID@@PEAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:000000018009F718 test eax, eax -; .text:000000018009F71A js short loc_18009F73B -; .text:000000018009F71C cmp [rsp+48h+arg_18], 0 -; .text:000000018009F721 jz short loc_18009F73B <- jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=9F721 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:100306A4 lea eax, [esp+150h+VersionInformation] -; .text:100306A8 inc ebx <- nop -; .text:100306A9 mov [edi], ebx -; .text:100306AB push eax ; lpVersionInformation -; .text:100306AC call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=306A8 -SingleUserCode.x86=nop -; .text:00000001800367F3 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:00000001800367F8 mov ebx, 1 <- 0 -; .text:00000001800367FD mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180036805 mov [rdi], ebx -; .text:0000000180036807 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=367F9 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1002EA25 cmp eax, [ecx+320h] -; .text:1002EA2B jz loc_100348C1 -; Changed -; .text:1002EA25 mov eax, 100h -; .text:1002EA2A mov [ecx+320h], eax -; .text:1002EA30 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2EA25 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:00000001800350FD cmp [rcx+63Ch], eax -; .text:0000000180035103 jz loc_18004F6AE -; Changed -; .text:00000001800350FD mov eax, 100h -; .text:0000000180035102 mov [rcx+638h], eax -; .text:0000000180035108 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=350FD -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; HOW TO search CSLQuery::Initialize function in IDA Pro: -; 1. Search text: CSLQuery::Initialize - SLGetWindowsInformationDWORD failed -; 2. All xrefs will point to this function - -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=196B0 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2F9C0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.3.9600.16384] -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:100A271C call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:100A2721 test eax, eax -; .text:100A2723 js short loc_100A2740 -; .text:100A2725 cmp [ebp+var_8], 0 -; .text:100A2729 jz short loc_100A2740 <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A2729 -LocalOnlyCode.x86=jmpshort -; .text:000000018008181F cmp [rsp+48h+arg_18], 0 -; .text:0000000180081824 jz loc_180031DEF <- nop + jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=81824 -LocalOnlyCode.x64=nopjmp -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10018024 lea eax, [esp+150h+VersionInformation] -; .text:10018028 inc ebx <- nop -; .text:10018029 mov [edi], ebx -; .text:1001802B push eax ; lpVersionInformation -; .text:1001802C call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=18028 -SingleUserCode.x86=nop -; .text:000000018002023B lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:0000000180020240 mov ebx, 1 <- 0 -; .text:0000000180020245 mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:000000018002024D mov [rdi], ebx -; .text:000000018002024F call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=20241 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:10016115 cmp eax, [ecx+320h] -; .text:1001611B jz loc_10034DE1 -; Changed -; .text:10016115 mov eax, 100h -; .text:1001611A mov [ecx+320h], eax -; .text:10016120 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=16115 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:0000000180057829 cmp [rcx+63Ch], eax -; .text:000000018005782F jz loc_18005E850 -; Changed -; .text:0000000180057829 mov eax, 100h -; .text:000000018005782E mov [rcx+638h], eax -; .text:0000000180057834 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=57829 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=1CEB0 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=554C0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.3.9600.17095] -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:100A36C4 call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:100A36C9 test eax, eax -; .text:100A36CB js short loc_100A36E8 -; .text:100A36CD cmp [ebp+var_8], 0 -; .text:100A36D1 jz short loc_100A36E8 <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A36D1 -LocalOnlyCode.x86=jmpshort -; .text:00000001800B914B call ?IsLicenseTypeLocalOnly@CSLQuery@@SAJAEAU_GUID@@PEAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:00000001800B9150 test eax, eax -; .text:00000001800B9152 js short loc_1800B9173 -; .text:00000001800B9154 cmp [rsp+48h+arg_18], 0 -; .text:00000001800B9159 jz short loc_1800B9173 <- jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=B9159 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10036BA5 lea eax, [esp+150h+VersionInformation] -; .text:10036BA9 inc ebx <- nop -; .text:10036BAA mov [edi], ebx -; .text:10036BAC push eax ; lpVersionInformation -; .text:10036BAD call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=36BA9 -SingleUserCode.x86=nop -; .text:0000000180021823 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:0000000180021828 mov ebx, 1 <- 0 -; .text:000000018002182D mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180021835 mov [rdi], ebx -; .text:0000000180021837 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=21829 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:10037529 cmp eax, [ecx+320h] -; .text:1003752F jz loc_10043662 -; Changed -; .text:10037529 mov eax, 100h -; .text:1003752E mov [ecx+320h], eax -; .text:10037534 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=37529 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:000000018001F6A1 cmp [rcx+63Ch], eax -; .text:000000018001F6A7 jz loc_18007284B -; Changed -; .text:000000018001F6A1 mov eax, 100h -; .text:000000018001F6A6 mov [rcx+638h], eax -; .text:000000018001F6AC nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1F6A1 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=117F1 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=3B110 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.3.9600.17415] -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:100B33EB call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:100B33F0 test eax, eax -; .text:100B33F2 js short loc_100B340F -; .text:100B33F4 cmp [ebp+var_C], 0 -; .text:100B33F8 jz short loc_100B340F <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=B33F8 -LocalOnlyCode.x86=jmpshort -; .text:000000018008B2D4 cmp [rsp+58h+arg_18], 0 -; .text:000000018008B2D9 jz loc_180025C39 <- nop + jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8B2D9 -LocalOnlyCode.x64=nopjmp -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10037111 lea eax, [esp+150h+VersionInformation] -; .text:10037115 inc ebx <- nop -; .text:10037116 mov [edi], ebx -; .text:10037118 push eax ; lpVersionInformation -; .text:10037119 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=37115 -SingleUserCode.x86=nop -; .text:0000000180033CE3 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:0000000180033CE8 mov ebx, 1 <- 0 -; .text:0000000180033CED mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180033CF5 mov [rdi], ebx -; .text:0000000180033CF7 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=33CE9 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1003CFF9 cmp eax, [ecx+320h] -; .text:1003CFFF jz loc_1004A52F -; Changed -; .text:1003CFF9 mov eax, 100h -; .text:1003CFFE mov [ecx+320h], eax -; .text:1003D004 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3CFF9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:0000000180045825 cmp [rcx+63Ch], eax -; .text:000000018004582B jz loc_180067704 -; Changed -; .text:0000000180045825 mov eax, 100h -; .text:000000018004582A mov [rcx+638h], eax -; .text:0000000180045830 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=45825 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=18478 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=5DBC0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.3.9600.18692] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=B3458 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8B2E9 -LocalOnlyCode.x64=nopjmp -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=37105 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=37039 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3CFE9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=45835 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=18488 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=5DBD0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.3.9600.18708] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=B35D8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8B376 -LocalOnlyCode.x64=nopjmp -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=370F5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=36FE9 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3CFD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=457D5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=18308 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=5DB70 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.3.9600.18928] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=B39D8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8B25D -LocalOnlyCode.x64=nopjmp -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=37D25 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=36C09 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3D6F9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=45495 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=18328 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=5D830 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.3.9600.19093] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=B3958 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8AE4E -LocalOnlyCode.x64=nopjmp -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3F045 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=36BC9 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3D899 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=45305 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=18288 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=5D660 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.4.9841.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:1009569B call sub_100B7EE5 -; .text:100956A0 test eax, eax -; .text:100956A2 js short loc_100956BF -; .text:100956A4 cmp [ebp+var_C], 0 -; .text:100956A8 jz short loc_100956BF <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=956A8 -LocalOnlyCode.x86=jmpshort -; .text:0000000180081133 call sub_1800A9048 -; .text:0000000180081138 test eax, eax -; .text:000000018008113A js short loc_18008115B -; .text:000000018008113C cmp [rsp+58h+arg_18], 0 -; .text:0000000180081141 jz short loc_18008115B <- jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=81141 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10030121 lea eax, [esp+150h+VersionInformation] -; .text:10030125 inc ebx <- nop -; .text:10030126 mov [edi], ebx -; .text:10030128 push eax ; lpVersionInformation -; .text:10030129 call ds:GetVersionExW -SingleUserPatch.x86=1 -SingleUserOffset.x86=30125 -SingleUserCode.x86=nop -; .text:0000000180012153 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:0000000180012158 mov ebx, 1 <- 0 -; .text:000000018001215D mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180012165 mov [rdi], ebx -; .text:0000000180012167 call cs:GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=12159 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1003B989 cmp eax, [ecx+320h] -; .text:1003B98F jz loc_1005E809 -; Changed -; .text:1003B989 mov eax, 100h -; .text:1003B98E mov [ecx+320h], eax -; .text:1003B994 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3B989 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:000000018000C125 cmp [rcx+63Ch], eax -; .text:000000018000C12B jz sub_18003BABC -; Changed -; .text:000000018000C125 mov eax, 100h -; .text:000000018000C12A mov [rcx+638h], eax -; .text:000000018000C130 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=C125 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46A68 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=1EA50 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.4.9860.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:100962BB call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:100962C0 test eax, eax -; .text:100962C2 js short loc_100962DF -; .text:100962C4 cmp [ebp+var_C], 0 -; .text:100962C8 jz short loc_100962DF <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=962C8 -LocalOnlyCode.x86=jmpshort -; .text:0000000180081083 call ?IsLicenseTypeLocalOnly@CSLQuery@@SAJAEAU_GUID@@PEAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:0000000180081088 test eax, eax -; .text:000000018008108A js short loc_1800810AB -; .text:000000018008108C cmp [rsp+58h+arg_18], 0 -; .text:0000000180081091 jz short loc_1800810AB <- jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=81091 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10030841 lea eax, [esp+150h+VersionInformation] -; .text:10030845 inc ebx <- nop -; .text:10030846 mov [edi], ebx -; .text:10030848 push eax ; lpVersionInformation -; .text:10030849 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=30845 -SingleUserCode.x86=nop -; .text:0000000180011AA3 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:0000000180011AA8 mov ebx, 1 <- 0 -; .text:0000000180011AAD mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180011AB5 mov [rdi], ebx -; .text:0000000180011AB7 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=11AA9 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1003BEC9 cmp eax, [ecx+320h] -; .text:1003BECF jz loc_1005EE1A -; Changed -; .text:1003BEC9 mov eax, 100h -; .text:1003BECE mov [ecx+320h], eax -; .text:1003BED4 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3BEC9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:000000018000B9F5 cmp [rcx+63Ch], eax -; .text:000000018000B9FB jz sub_18003B9C8 -; Changed -; .text:000000018000B9F5 mov eax, 100h -; .text:000000018000B9FA mov [rcx+638h], eax -; .text:000000018000BA00 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=B9F5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46F18 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=1EB00 -SLInitFunc.x64=New_CSLQuery_Initialize - -[6.4.9879.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:100A9CBB call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:100A9CC0 test eax, eax -; .text:100A9CC2 js short loc_100A9CDF -; .text:100A9CC4 cmp [ebp+var_C], 0 -; .text:100A9CC8 jz short loc_100A9CDF <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9CC8 -LocalOnlyCode.x86=jmpshort -; .text:0000000180095603 call ?IsLicenseTypeLocalOnly@CSLQuery@@SAJAEAU_GUID@@PEAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:0000000180095608 test eax, eax -; .text:000000018009560A js short loc_18009562B -; .text:000000018009560C cmp [rsp+58h+arg_18], 0 -; .text:0000000180095611 jz short loc_18009562B <- jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=95611 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10030C51 lea eax, [esp+150h+VersionInformation] -; .text:10030C55 inc ebx <- nop -; .text:10030C56 mov [edi], ebx -; .text:10030C58 push eax ; lpVersionInformation -; .text:10030C59 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=30C55 -SingleUserCode.x86=nop -; .text:0000000180016A2E call memset_0 -; .text:0000000180016A33 mov ebx, 1 <- 0 -; .text:0000000180016A38 mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180016A40 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:0000000180016A45 mov [rdi], ebx -; .text:0000000180016A47 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=16A34 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1002DAB9 cmp eax, [ecx+320h] -; .text:1002DABF jz loc_1006C38A -; Changed -; .text:1002DAB9 mov eax, 100h -; .text:1002DABE mov [ecx+320h], eax -; .text:1002DAC4 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2DAB9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:000000018001BDC5 cmp [rcx+63Ch], eax -; .text:000000018001BDCB jz sub_180045540 -; Changed -; .text:000000018001BDC5 mov eax, 100h -; .text:000000018001BDCA mov [rcx+638h], eax -; .text:000000018001BDD0 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1BDC5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=41132 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=24750 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.9926.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8C28 -LocalOnlyCode.x86=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=31725 -SingleUserCode.x86=nop -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3CF99 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=3F140 -SLInitFunc.x86=New_CSLQuery_Initialize -; x64 contributed by v-yadli -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x64=1 -;;;OFFSET = 0x61 -;;;BASE = 0x95F90 -LocalOnlyOffset.x64=95FF1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x64=1 -;;;OFFSET = 0x43 -;;;BASE = 0x12F90 -;;;;instruction = 0xBB 0x01 0x00 0x00 0x00 -;;; ^^^ +1 offset -SingleUserOffset.x64=12A34 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x64=1 -;;; -;;;BASE = 0xBDF0 -;;;OFFSET = 0x15 -DefPolicyOffset.x64=BE05 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x64=1 -SLInitOffset.x64=24EC0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.10041.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -; .text:100A9D7B call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:100A9D80 test eax, eax -; .text:100A9D82 js short loc_100A9D9F -; .text:100A9D84 cmp [ebp+var_C], 0 -; .text:100A9D88 jz short loc_100A9D9F <- jmp -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9D88 -LocalOnlyCode.x86=jmpshort -; .text:0000000180097133 call ?IsLicenseTypeLocalOnly@CSLQuery@@SAJAEAU_GUID@@PEAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) -; .text:0000000180097138 test eax, eax -; .text:000000018009713A js short loc_18009715B -; .text:000000018009713C cmp [rsp+58h+arg_18], 0 -; .text:0000000180097141 jz short loc_18009715B <- jmp -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=97141 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -; .text:10032211 lea eax, [esp+150h+VersionInformation] -; .text:10032215 inc ebx <- nop -; .text:10032216 mov [edi], ebx -; .text:10032218 push eax ; lpVersionInformation -; .text:10032219 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) -SingleUserPatch.x86=1 -SingleUserOffset.x86=32215 -SingleUserCode.x86=nop -; .text:0000000180015C5E call memset_0 -; .text:0000000180015C63 mov ebx, 1 <- 0 -; .text:0000000180015C68 mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch -; .text:0000000180015C70 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation -; .text:0000000180015C75 mov [rdi], ebx -; .text:0000000180015C77 call cs:__imp_GetVersionExW -SingleUserPatch.x64=1 -SingleUserOffset.x64=15C64 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -; Original -; .text:1002DFC9 cmp eax, [ecx+320h] -; .text:1002DFCF jz loc_10056550 -; Changed -; .text:1002DFC9 mov eax, 100h -; .text:1002DFCE mov [ecx+320h], eax -; .text:1002DFD4 nop -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2DFC9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Original -; .text:000000018000B795 cmp [rcx+63Ch], eax -; .text:000000018000B79B jz sub_18003A79A -; Changed -; .text:000000018000B795 mov eax, 100h -; .text:000000018000B79A mov [rcx+638h], eax -; .text:000000018000B7A0 nop -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=B795 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46960 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22E40 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.10240.16384] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7D38 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=96901 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=32A95 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=18F74 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2F5B9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=22865 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46581 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=250F0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.10586.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7C18 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=96AA1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=353B5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=190D4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30B69 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=229A5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=469DE -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=25220 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.10586.589] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7BE8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=96A51 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=353B5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=190D4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30B69 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=229A5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=469DE -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=25220 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.11082.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7C98 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=96AB1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35405 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=190D4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30BB9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=229A5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46A3E -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=25220 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.11102.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5D58 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=95CD1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35A85 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=2A9C4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30159 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B5D5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=44FD2 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D160 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14251.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5D58 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=95CD1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35A85 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=2A9C4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30159 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B5D5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=44FD2 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D160 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14271.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A4CE8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=941E1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35915 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=263F4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF79 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1C185 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=47725 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CE50 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14279.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A4D28 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=94191 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35915 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=263F4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF79 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1C185 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=47725 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CE50 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14295.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A4D28 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D691 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35925 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=25514 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1BA35 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=47748 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C860 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14300.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F5F1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x64=1 -SingleUserOffset.x64=26B04 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1D125 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CC60 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14316.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E88 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F5F1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=32B55 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=26B04 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3C1C9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1D295 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46ABD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CC60 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14328.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E88 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F5F1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=32B55 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=26B04 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3C1C9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1D365 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46ABD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CC60 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14332.1001] -; contributed by maxpiva -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E98 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F601 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=357E5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=2AE44 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=316A9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1C025 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4755F -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CAD0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14342.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E98 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8EF31 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=357E5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=26774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=316A9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1CEF5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4755F -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CA20 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14352.1002] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A4478 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D911 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35465 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=24474 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30099 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1AC05 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=44792 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CDB0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14366.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9088 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FB01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34F65 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=21DE4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=316E9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1A855 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4793E -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CCE0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14367.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9088 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FB01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34F65 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=21DE4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=316E9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1A855 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4793E -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CCE0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14372.0] -; x64 contributed by kbmorris -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7698 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F931 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34635 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=295A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF69 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B295 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=460D2 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CC10 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14379.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7698 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F941 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34635 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=295A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF69 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B295 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=460D2 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CC10 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14383.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7698 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F941 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34635 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=295A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF69 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B295 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=460D2 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CC10 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14385.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7698 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F941 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34635 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=295A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF69 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B295 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=460D2 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CC10 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14388.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6038 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D781 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=359C5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=299A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF29 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1AFC5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45636 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C930 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14393.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6038 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D781 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=359C5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=299A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF29 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1AFC5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45636 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C930 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14393.1198] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6088 -LocalOnlyCode.x86=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=359C5 -SingleUserCode.x86=nop -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF29 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45636 -SLInitFunc.x86=New_CSLQuery_Initialize - -[10.0.14393.1737] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6198 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D861 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35AD5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=299A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30039 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1AFC5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45724 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C930 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14393.2457] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6248 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D811 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36CE5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=29CF4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31209 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B545 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45824 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C920 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14901.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6038 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D781 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=359C5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=299A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF29 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1AFC5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45636 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C930 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14905.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6038 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D781 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=359C5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=299A4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF29 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1AFC5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45636 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C930 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14915.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6D98 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E241 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35E35 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=29EB4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=30399 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B4A5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46092 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CE40 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14926.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A6D18 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E071 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35E55 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=29EB4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=303B9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1B4A5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=460A2 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=CE40 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14931.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A4908 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8B411 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35705 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=29264 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FF69 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1AD05 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=452FD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C7FC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14936.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A3F38 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8B9A1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35355 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=25174 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FCD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1BB55 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=44CFE -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=C62C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14942.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A3F38 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=9115B -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35355 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=199BD -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FCD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1064E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=44CFE -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=258EC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14946.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A4018 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=911AB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35355 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=199AD -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FCD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1064E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=44CFD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=258DC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14951.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A78D8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=94A6B -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3BA85 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1CEDD -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=32629 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=11E9E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=3F680 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22EE0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14955.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A78D8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=94A6B -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3BA85 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1CEDD -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=32629 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=11E9E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=3F680 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22EE0 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14959.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A79B8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=934AB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=2EF05 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=16A0D -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2A4E9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10A8E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=448A0 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=26960 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14965.1001] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7868 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=9345B -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3BA85 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=17DFD -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=32A59 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1212E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=3F680 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=26610 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14971.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7968 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=925FB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36FE5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1803D -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3D9A9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=11FBE -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46500 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=26180 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14986.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7878 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=926BB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36FA5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=17FFD -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3D979 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=11F7E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=464A0 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=26140 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.14997.1001] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=931EB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x64=1 -SingleUserOffset.x64=274ED -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1D95E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x64=1 -SLInitOffset.x64=E000 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15002.1001] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9698 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=931EB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=346B5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=274ED -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3D779 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1D95E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=47D90 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=E000 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15007.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9648 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=931EB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34665 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=274ED -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3D719 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1D95E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=47D30 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=E000 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15014.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9648 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=931EB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34685 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=274ED -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3D739 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1D95E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=47D50 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=E000 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15019.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A39F8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=928FB -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=BADF5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=FBDD -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=A8479 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx_jmp -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=20AAE -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=3C240 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=24480 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15025.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=9259B -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x64=1 -SingleUserOffset.x64=2C08D -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1DD0E -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x64=1 -SLInitOffset.x64=E5B8 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15031.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5BA8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E221 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=30A75 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=2A114 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2B1D9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1C7B5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4532D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D80C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15042.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5BA8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E221 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=30A75 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=2A114 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2B1D9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1C7B5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4532D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D80C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15046.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=80BB8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E361 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=31E95 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=15E14 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=38A19 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=E745 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=9422D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=21FFC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15048.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=80BB8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E361 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=31E95 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=15E14 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=38A19 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=E745 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=9422D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=21FFC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15055.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5348 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8D2E1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=374C5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=181E4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3BAD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10B65 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=44EFF -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22AEC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15058.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5D68 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8CAA1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35075 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=24E74 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FCD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=2DD65 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4549D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D1EC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15061.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5D68 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8CAA1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35075 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=24E74 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FCD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=2DD65 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4549D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D1EC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15063.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5D68 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8CAA1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35075 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=24E74 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FCD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=2DD65 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4549D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D1EC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15063.296] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A5D68 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8CAA1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=35075 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=24E74 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=2FCD9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=2DD65 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4549D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=D1EC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15063.994] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8CB01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x64=1 -SingleUserOffset.x64=15EA4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=FAE5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x64=1 -SLInitOffset.x64=234DC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.15063.1155] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8CB01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x64=1 -SingleUserOffset.x64=15EA4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=FAE5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x64=1 -SLInitOffset.x64=234DC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16179.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AA568 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8C141 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34425 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=16F84 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31219 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1E7F5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45F30 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=21700 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16184.1001] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AA568 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8C141 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=34425 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=16F84 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31219 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1E7F5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45F30 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=21700 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16199.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=ABA68 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8CED1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=348C5 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=28C14 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=319B9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=CB25 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=469B0 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=FA30 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16215.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7CE8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8DE21 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39F05 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=28724 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3E019 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=CC15 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=46462 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=FB00 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16232.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7D38 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8DD41 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39F35 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=287B4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3E0C9 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=CC15 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4650F -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=FB00 -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16237.1001] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7F38 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E911 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39F85 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1BC84 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3E119 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=DA55 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4655D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2180C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16241.1001] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A7F38 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E911 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39F85 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1BC84 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3E119 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=DA55 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4655D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2180C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16251.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=ABC88 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8EC21 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3A525 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1BCB4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31779 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=DAF5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=447FD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2183C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16251.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=ABC88 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8EC21 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3A525 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1BCB4 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31779 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=DAF5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=447FD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2183C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16257.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AB718 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E841 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=33925 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=11364 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3C409 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1EFD5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4504D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2495C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16257.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AB718 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E841 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=33925 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=11364 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3C409 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1EFD5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4504D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2495C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16273.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AB798 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8E871 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=33925 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=11364 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3C409 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=1EFD5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4504D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2495C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16275.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9388 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=90001 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39435 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C724 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DE89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D75 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=463D4 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D0C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16278.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9388 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=90001 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39435 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C724 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DE89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D75 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=463D4 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D0C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16281.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E08 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FD01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39215 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DC89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=461BD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D5C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16288.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E08 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FD01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39215 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DC89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=461BD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D5C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16291.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E08 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FD01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39215 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DC89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=461BD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D5C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16294.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E08 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FD01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39215 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DC89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=461BD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D5C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16296.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E08 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FD01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39215 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DC89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=461BD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D5C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16299.0] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E08 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FD01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39215 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DC89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=461BD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D5C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16299.15] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E08 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FD01 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39215 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C774 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DC89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=461BD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D5C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16353.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A9388 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=90001 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=39435 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1C724 -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DE89 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D75 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=463D4 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D0C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.16362.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8E38 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FBA1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=2F61C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=19D1C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DE99 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=463D4 -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D9C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17004.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=A8EB8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8FB41 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=2F65C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=19D1C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=3DF09 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=12D85 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=4643F -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22D9C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17017.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AB388 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F291 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3477C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1977C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31049 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=125A5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45CDD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=227DC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17025.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AB498 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F291 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=3477C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1977C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31049 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=125A5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45CDD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=227DC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17035.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AB3F8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F271 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=354AC -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=14E7C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31F19 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10CB5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45C4D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22AEC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17046.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AB3F8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=8F281 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=354AC -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=14E8C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=31F19 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10CC5 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=45C4D -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22AFC -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17063.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AD7F8 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=92671 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36B0C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=153CC -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=33569 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=111CE -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=474AD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=2318C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17115.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AD738 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=925D1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36B0C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1511C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=33569 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10E78 -DefPolicyCode.x64=CDefPolicy_Query_edi_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=474AD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22E6C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17128.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AD738 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=925D1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36B0C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1511C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=33569 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10E78 -DefPolicyCode.x64=CDefPolicy_Query_edi_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=474AD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22E6C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17133.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AD738 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=925D1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36B0C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1511C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=33569 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10E78 -DefPolicyCode.x64=CDefPolicy_Query_edi_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=474AD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22E6C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17134.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AD738 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=925D1 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=36B0C -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1511C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=33569 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=10E78 -DefPolicyCode.x64=CDefPolicy_Query_edi_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=474AD -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=22E6C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17723.1000] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=75D91 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelperMgr::IsSingleSessionPerUserEnabled -SingleUserPatch.x64=1 -SingleUserOffset.x64=1296C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17A45 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x64=1 -SLInitOffset.x64=1B10C -SLInitFunc.x64=New_CSLQuery_Initialize - -[10.0.17763.1] -; Patch CEnforcementCore::GetInstanceOfTSLicense -LocalOnlyPatch.x86=1 -LocalOnlyOffset.x86=AF8E4 -LocalOnlyCode.x86=jmpshort -LocalOnlyPatch.x64=1 -LocalOnlyOffset.x64=77941 -LocalOnlyCode.x64=jmpshort -; Patch CSessionArbitrationHelperMgr::IsSingleSessionPerUserEnabled -SingleUserPatch.x86=1 -SingleUserOffset.x86=4D505 -SingleUserCode.x86=nop -SingleUserPatch.x64=1 -SingleUserOffset.x64=1322C -SingleUserCode.x64=Zero -; Patch CDefPolicy::Query -DefPolicyPatch.x86=1 -DefPolicyOffset.x86=4BD09 -DefPolicyCode.x86=CDefPolicy_Query_eax_ecx -DefPolicyPatch.x64=1 -DefPolicyOffset.x64=17F45 -DefPolicyCode.x64=CDefPolicy_Query_eax_rcx -; Hook CSLQuery::Initialize -SLInitHook.x86=1 -SLInitOffset.x86=5B02A -SLInitFunc.x86=New_CSLQuery_Initialize -SLInitHook.x64=1 -SLInitOffset.x64=1ABFC -SLInitFunc.x64=New_CSLQuery_Initialize - -[SLInit] -; Is server -bServerSku=1 -; Enable listener - allow remote connections -bRemoteConnAllowed=1 -; Allow fast user switching -bFUSEnabled=1 -; Allow RemoteApp server -bAppServerAllowed=1 -; Allow multi monitor -bMultimonAllowed=1 -; Maximum user sessions (0 - unlimited) -lMaxUserSessions=0 -; Maximum debug/glass sessions (0 - unlimited) -ulMaxDebugSessions=0 -; SLInit function is succeeded -bInitialized=1 - -[6.3.9431.0-SLInit] -; HOW TO search SLInit global variables in IDA Pro: -; 1. Search text: The SL policy for ',27h,'Allow Multiple Sessions',27h,' is not defined -; 2. Xref will point to CSLQuery::Initialize function -; 3. Follow xref, look for cmp instruction nearby -; 4. It will be comparsion with CSLQuery::bServerSku constant -; 5. Now it's easy to find other constants - -; Strings to find other values: -; CSLQuery::GetMaxUserSessions -; CSLQuery::IsAppServerInstalled failed: -; CSLQuery::AreRemoteConnectionsAllowed f -; CSLQuery::IsMultimonAllowed -; CSLQuery::GetMaxDebugSessions -; CSLQuery::IsFUSEnabled - -bFUSEnabled.x86 =A22A8 -lMaxUserSessions.x86 =A22AC -bAppServerAllowed.x86 =A22B0 -bInitialized.x86 =A22B4 -bMultimonAllowed.x86 =A22B8 -bServerSku.x86 =A22BC -ulMaxDebugSessions.x86=A22C0 -bRemoteConnAllowed.x86=A22C4 - -bFUSEnabled.x64 =C4490 -lMaxUserSessions.x64 =C4494 -bAppServerAllowed.x64 =C4498 -bInitialized.x64 =C449C -bMultimonAllowed.x64 =C44A0 -bServerSku.x64 =C44A4 -ulMaxDebugSessions.x64=C44A8 -bRemoteConnAllowed.x64=C44AC - -[6.3.9600.16384-SLInit] -bFUSEnabled.x86 =C02A8 -lMaxUserSessions.x86 =C02AC -bAppServerAllowed.x86 =C02B0 -bInitialized.x86 =C02B4 -bMultimonAllowed.x86 =C02B8 -bServerSku.x86 =C02BC -ulMaxDebugSessions.x86=C02C0 -bRemoteConnAllowed.x86=C02C4 - -bServerSku.x64 =E6494 -ulMaxDebugSessions.x64=E6498 -bRemoteConnAllowed.x64=E649C -bFUSEnabled.x64 =E64A0 -lMaxUserSessions.x64 =E64A4 -bAppServerAllowed.x64 =E64A8 -bInitialized.x64 =E64AC -bMultimonAllowed.x64 =E64B0 - -[6.3.9600.17095-SLInit] -bFUSEnabled.x86 =C12A8 -lMaxUserSessions.x86 =C12AC -bAppServerAllowed.x86 =C12B0 -bInitialized.x86 =C12B4 -bMultimonAllowed.x86 =C12B8 -bServerSku.x86 =C12BC -ulMaxDebugSessions.x86=C12C0 -bRemoteConnAllowed.x86=C12C4 - -bServerSku.x64 =E4494 -ulMaxDebugSessions.x64=E4498 -bRemoteConnAllowed.x64=E449C -bFUSEnabled.x64 =E44A0 -lMaxUserSessions.x64 =E44A4 -bAppServerAllowed.x64 =E44A8 -bInitialized.x64 =E44AC -bMultimonAllowed.x64 =E44B0 - -[6.3.9600.17415-SLInit] -bFUSEnabled.x86 =D3068 -lMaxUserSessions.x86 =D306C -bAppServerAllowed.x86 =D3070 -bInitialized.x86 =D3074 -bMultimonAllowed.x86 =D3078 -bServerSku.x86 =D307C -ulMaxDebugSessions.x86=D3080 -bRemoteConnAllowed.x86=D3084 - -bFUSEnabled.x64 =F9054 -lMaxUserSessions.x64 =F9058 -bAppServerAllowed.x64 =F905C -bInitialized.x64 =F9060 -bMultimonAllowed.x64 =F9064 -bServerSku.x64 =F9068 -ulMaxDebugSessions.x64=F906C -bRemoteConnAllowed.x64=F9070 - -[6.3.9600.18692-SLInit] -bFUSEnabled.x86 =D3068 -lMaxUserSessions.x86 =D306C -bAppServerAllowed.x86 =D3070 -bInitialized.x86 =D3074 -bMultimonAllowed.x86 =D3078 -bServerSku.x86 =D307C -ulMaxDebugSessions.x86=D3080 -bRemoteConnAllowed.x86=D3084 - -bFUSEnabled.x64 =F9054 -lMaxUserSessions.x64 =F9058 -bAppServerAllowed.x64 =F905C -bInitialized.x64 =F9060 -bMultimonAllowed.x64 =F9064 -bServerSku.x64 =F9068 -ulMaxDebugSessions.x64=F906C -bRemoteConnAllowed.x64=F9070 - -[6.3.9600.18708-SLInit] -bFUSEnabled.x86 =D3068 -lMaxUserSessions.x86 =D306C -bAppServerAllowed.x86 =D3070 -bInitialized.x86 =D3074 -bMultimonAllowed.x86 =D3078 -bServerSku.x86 =D307C -ulMaxDebugSessions.x86=D3080 -bRemoteConnAllowed.x86=D3084 - -bFUSEnabled.x64 =FA054 -lMaxUserSessions.x64 =FA058 -bAppServerAllowed.x64 =FA05C -bInitialized.x64 =FA060 -bMultimonAllowed.x64 =FA064 -bServerSku.x64 =FA068 -ulMaxDebugSessions.x64=FA06C -bRemoteConnAllowed.x64=FA070 - -[6.3.9600.18928-SLInit] -bFUSEnabled.x86 =D3068 -lMaxUserSessions.x86 =D306C -bAppServerAllowed.x86 =D3070 -bInitialized.x86 =D3074 -bMultimonAllowed.x86 =D3078 -bServerSku.x86 =D307C -ulMaxDebugSessions.x86=D3080 -bRemoteConnAllowed.x86=D3084 - -bFUSEnabled.x64 =FA054 -lMaxUserSessions.x64 =FA058 -bAppServerAllowed.x64 =FA05C -bInitialized.x64 =FA060 -bMultimonAllowed.x64 =FA064 -bServerSku.x64 =FA068 -ulMaxDebugSessions.x64=FA06C -bRemoteConnAllowed.x64=FA070 - -[6.3.9600.19093-SLInit] -bFUSEnabled.x86 =D3068 -lMaxUserSessions.x86 =D306C -bAppServerAllowed.x86 =D3070 -bInitialized.x86 =D3074 -bMultimonAllowed.x86 =D3078 -bServerSku.x86 =D307C -ulMaxDebugSessions.x86=D3080 -bRemoteConnAllowed.x86=D3084 - -bFUSEnabled.x64 =FA054 -lMaxUserSessions.x64 =FA058 -bAppServerAllowed.x64 =FA05C -bInitialized.x64 =FA060 -bMultimonAllowed.x64 =FA064 -bServerSku.x64 =FA068 -ulMaxDebugSessions.x64=FA06C -bRemoteConnAllowed.x64=FA070 - -[6.4.9841.0-SLInit] -bFUSEnabled.x86 =BF9F0 -lMaxUserSessions.x86 =BF9F4 -bAppServerAllowed.x86 =BF9F8 -bInitialized.x86 =BF9FC -bMultimonAllowed.x86 =BFA00 -bServerSku.x86 =BFA04 -ulMaxDebugSessions.x86=BFA08 -bRemoteConnAllowed.x86=BFA0C - -bFUSEnabled.x64 =ECFF8 -lMaxUserSessions.x64 =ECFFC -bAppServerAllowed.x64 =ED000 -bInitialized.x64 =ED004 -bMultimonAllowed.x64 =ED008 -bServerSku.x64 =ED00C -ulMaxDebugSessions.x64=ED010 -bRemoteConnAllowed.x64=ED014 - -[6.4.9860.0-SLInit] -bFUSEnabled.x86 =BF7E0 -lMaxUserSessions.x86 =BF7E4 -bAppServerAllowed.x86 =BF7E8 -bInitialized.x86 =BF7EC -bMultimonAllowed.x86 =BF7F0 -bServerSku.x86 =BF7F4 -ulMaxDebugSessions.x86=BF7F8 -bRemoteConnAllowed.x86=BF7FC - -bFUSEnabled.x64 =ECBD8 -lMaxUserSessions.x64 =ECBDC -bAppServerAllowed.x64 =ECBE0 -bInitialized.x64 =ECBE4 -bMultimonAllowed.x64 =ECBE8 -bServerSku.x64 =ECBEC -ulMaxDebugSessions.x64=ECBF0 -bRemoteConnAllowed.x64=ECBF4 - -[6.4.9879.0-SLInit] -bFUSEnabled.x86 =C27D8 -lMaxUserSessions.x86 =C27DC -bAppServerAllowed.x86 =C27E0 -bInitialized.x86 =C27E4 -bMultimonAllowed.x86 =C27E8 -bServerSku.x86 =C27EC -ulMaxDebugSessions.x86=C27F0 -bRemoteConnAllowed.x86=C27F4 - -bFUSEnabled.x64 =EDBF0 -lMaxUserSessions.x64 =EDBF4 -bAppServerAllowed.x64 =EDBF8 -bInitialized.x64 =EDBFC -bMultimonAllowed.x64 =EDC00 -bServerSku.x64 =EDC04 -ulMaxDebugSessions.x64=EDC08 -bRemoteConnAllowed.x64=EDC0C - -[10.0.9926.0-SLInit] -bFUSEnabled.x86 =C17D8 -lMaxUserSessions.x86 =C17DC -bAppServerAllowed.x86 =C17E0 -bInitialized.x86 =C17E4 -bMultimonAllowed.x86 =C17E8 -bServerSku.x86 =C17EC -ulMaxDebugSessions.x86=C17F0 -bRemoteConnAllowed.x86=C17F4 -; x64 contributed by v-yadli -bFUSEnabled.x64 =EEBF0 -lMaxUserSessions.x64 =EEBF4 -bAppServerAllowed.x64 =EEBF8 -bInitialized.x64 =EEBFC -bMultimonAllowed.x64 =EEC00 -bServerSku.x64 =EEC04 -ulMaxDebugSessions.x64=EEC08 -bRemoteConnAllowed.x64=EEC0C - -[10.0.10041.0-SLInit] -bFUSEnabled.x86 =C5F60 -lMaxUserSessions.x86 =C5F64 -bAppServerAllowed.x86 =C5F68 -bInitialized.x86 =C5F6C -bMultimonAllowed.x86 =C5F70 -bServerSku.x86 =C5F74 -ulMaxDebugSessions.x86=C5F78 -bRemoteConnAllowed.x86=C5F7C - -bFUSEnabled.x64 =F3448 -lMaxUserSessions.x64 =F344C -bAppServerAllowed.x64 =F3450 -bInitialized.x64 =F3454 -bMultimonAllowed.x64 =F3458 -bServerSku.x64 =F345C -ulMaxDebugSessions.x64=F3460 -bRemoteConnAllowed.x64=F3464 - -[10.0.10240.16384-SLInit] -bFUSEnabled.x86 =C3F60 -lMaxUserSessions.x86 =C3F64 -bAppServerAllowed.x86 =C3F68 -bInitialized.x86 =C3F6C -bMultimonAllowed.x86 =C3F70 -bServerSku.x86 =C3F74 -ulMaxDebugSessions.x86=C3F78 -bRemoteConnAllowed.x86=C3F7C - -lMaxUserSessions.x64 =F23B0 -bAppServerAllowed.x64 =F23B4 -bServerSku.x64 =F23B8 -bFUSEnabled.x64 =F3460 -bInitialized.x64 =F3464 -bMultimonAllowed.x64 =F3468 -ulMaxDebugSessions.x64=F346C -bRemoteConnAllowed.x64=F3470 - -[10.0.10586.0-SLInit] -bFUSEnabled.x86 =C3F60 -lMaxUserSessions.x86 =C3F64 -bAppServerAllowed.x86 =C3F68 -bInitialized.x86 =C3F6C -bMultimonAllowed.x86 =C3F70 -bServerSku.x86 =C3F74 -ulMaxDebugSessions.x86=C3F78 -bRemoteConnAllowed.x86=C3F7C - -lMaxUserSessions.x64 =F23B0 -bAppServerAllowed.x64 =F23B4 -bServerSku.x64 =F23B8 -bFUSEnabled.x64 =F3460 -bInitialized.x64 =F3464 -bMultimonAllowed.x64 =F3468 -ulMaxDebugSessions.x64=F346C -bRemoteConnAllowed.x64=F3470 - -[10.0.10586.589-SLInit] -bFUSEnabled.x86 =C3F60 -lMaxUserSessions.x86 =C3F64 -bAppServerAllowed.x86 =C3F68 -bInitialized.x86 =C3F6C -bMultimonAllowed.x86 =C3F70 -bServerSku.x86 =C3F74 -ulMaxDebugSessions.x86=C3F78 -bRemoteConnAllowed.x86=C3F7C - -lMaxUserSessions.x64 =F23B0 -bAppServerAllowed.x64 =F23B4 -bServerSku.x64 =F23B8 -bFUSEnabled.x64 =F3460 -bInitialized.x64 =F3464 -bMultimonAllowed.x64 =F3468 -ulMaxDebugSessions.x64=F346C -bRemoteConnAllowed.x64=F3470 - -[10.0.11082.1000-SLInit] -bFUSEnabled.x86 =C3F60 -lMaxUserSessions.x86 =C3F64 -bAppServerAllowed.x86 =C3F68 -bInitialized.x86 =C3F6C -bMultimonAllowed.x86 =C3F70 -bServerSku.x86 =C3F74 -ulMaxDebugSessions.x86=C3F78 -bRemoteConnAllowed.x86=C3F7C - -lMaxUserSessions.x64 =F23B0 -bAppServerAllowed.x64 =F23B4 -bServerSku.x64 =F23B8 -bFUSEnabled.x64 =F3460 -bInitialized.x64 =F3464 -bMultimonAllowed.x64 =F3468 -ulMaxDebugSessions.x64=F346C -bRemoteConnAllowed.x64=F3470 - -[10.0.11102.1000-SLInit] -bInitialized.x86 =C1F5C -bServerSku.x86 =C1F60 -lMaxUserSessions.x86 =C1F64 -bAppServerAllowed.x86 =C1F68 -bRemoteConnAllowed.x86=C1F6C -bMultimonAllowed.x86 =C1F70 -ulMaxDebugSessions.x86=C1F74 -bFUSEnabled.x86 =C1F78 - -bInitialized.x64 =F2430 -bRemoteConnAllowed.x64=F2434 -bMultimonAllowed.x64 =F2438 -ulMaxDebugSessions.x64=F243C -bFUSEnabled.x64 =F2440 -bServerSku.x64 =F244C -lMaxUserSessions.x64 =F2450 -bAppServerAllowed.x64 =F2454 - -[10.0.14251.1000-SLInit] -bInitialized.x86 =C1F5C -bServerSku.x86 =C1F60 -lMaxUserSessions.x86 =C1F64 -bAppServerAllowed.x86 =C1F68 -bRemoteConnAllowed.x86=C1F6C -bMultimonAllowed.x86 =C1F70 -ulMaxDebugSessions.x86=C1F74 -bFUSEnabled.x86 =C1F78 - -bInitialized.x64 =F2430 -bRemoteConnAllowed.x64=F2434 -bMultimonAllowed.x64 =F2438 -ulMaxDebugSessions.x64=F243C -bFUSEnabled.x64 =F2440 -bServerSku.x64 =F244C -lMaxUserSessions.x64 =F2450 -bAppServerAllowed.x64 =F2454 - -[10.0.14271.1000-SLInit] -bInitialized.x86 =C0F5C -bServerSku.x86 =C0F60 -lMaxUserSessions.x86 =C0F64 -bAppServerAllowed.x86 =C0F68 -bRemoteConnAllowed.x86=C0F6C -bMultimonAllowed.x86 =C0F70 -ulMaxDebugSessions.x86=C0F74 -bFUSEnabled.x86 =C0F78 - -bServerSku.x64 =EF3C0 -lMaxUserSessions.x64 =EF3C4 -bAppServerAllowed.x64 =EF3C8 -bInitialized.x64 =F0460 -bRemoteConnAllowed.x64=F0464 -bMultimonAllowed.x64 =F0468 -ulMaxDebugSessions.x64=F046C -bFUSEnabled.x64 =F0470 - -[10.0.14279.1000-SLInit] -bInitialized.x86 =C0F5C -bServerSku.x86 =C0F60 -lMaxUserSessions.x86 =C0F64 -bAppServerAllowed.x86 =C0F68 -bRemoteConnAllowed.x86=C0F6C -bMultimonAllowed.x86 =C0F70 -ulMaxDebugSessions.x86=C0F74 -bFUSEnabled.x86 =C0F78 - -bServerSku.x64 =EF3C0 -lMaxUserSessions.x64 =EF3C4 -bAppServerAllowed.x64 =EF3C8 -bInitialized.x64 =F0460 -bRemoteConnAllowed.x64=F0464 -bMultimonAllowed.x64 =F0468 -ulMaxDebugSessions.x64=F046C -bFUSEnabled.x64 =F0470 - -[10.0.14295.1000-SLInit] -bInitialized.x86 =C0F5C -bServerSku.x86 =C0F60 -lMaxUserSessions.x86 =C0F64 -bAppServerAllowed.x86 =C0F68 -bRemoteConnAllowed.x86=C0F6C -bMultimonAllowed.x86 =C0F70 -ulMaxDebugSessions.x86=C0F74 -bFUSEnabled.x86 =C0F78 - -bServerSku.x64 =E73C0 -lMaxUserSessions.x64 =E73C4 -bAppServerAllowed.x64 =E73C8 -bInitialized.x64 =E8460 -bRemoteConnAllowed.x64=E8464 -bMultimonAllowed.x64 =E8468 -ulMaxDebugSessions.x64=E846C -bFUSEnabled.x64 =E8470 - -[10.0.14300.1000-SLInit] -bServerSku.x64 =E93C0 -lMaxUserSessions.x64 =E93C4 -bAppServerAllowed.x64 =E93C8 -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 - -[10.0.14316.1000-SLInit] -bInitialized.x86 =C4F58 -bServerSku.x86 =C4F5C -lMaxUserSessions.x86 =C4F60 -bAppServerAllowed.x86 =C4F64 -bRemoteConnAllowed.x86=C4F68 -bMultimonAllowed.x86 =C4F6C -ulMaxDebugSessions.x86=C4F70 -bFUSEnabled.x86 =C4F74 - -bServerSku.x64 =E93C0 -lMaxUserSessions.x64 =E93C4 -bAppServerAllowed.x64 =E93C8 -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 - -[10.0.14328.1000-SLInit] -bInitialized.x86 =C4F58 -bServerSku.x86 =C4F5C -lMaxUserSessions.x86 =C4F60 -bAppServerAllowed.x86 =C4F64 -bRemoteConnAllowed.x86=C4F68 -bMultimonAllowed.x86 =C4F6C -ulMaxDebugSessions.x86=C4F70 -bFUSEnabled.x86 =C4F74 - -bServerSku.x64 =E93C0 -lMaxUserSessions.x64 =E93C4 -bAppServerAllowed.x64 =E93C8 -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 - -[10.0.14332.1001-SLInit] -; contributed by maxpiva -bInitialized.x86 =C4F58 -bServerSku.x86 =C4F5C -lMaxUserSessions.x86 =C4F60 -bAppServerAllowed.x86 =C4F64 -bRemoteConnAllowed.x86=C4F68 -bMultimonAllowed.x86 =C4F6C -ulMaxDebugSessions.x86=C4F70 -bFUSEnabled.x86 =C4F74 - -bServerSku.x64 =E93C0 -lMaxUserSessions.x64 =E93C4 -bAppServerAllowed.x64 =E93C8 -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 - -[10.0.14342.1000-SLInit] -bInitialized.x86 =C4F58 -bServerSku.x86 =C4F5C -lMaxUserSessions.x86 =C4F60 -bAppServerAllowed.x86 =C4F64 -bRemoteConnAllowed.x86=C4F68 -bMultimonAllowed.x86 =C4F6C -ulMaxDebugSessions.x86=C4F70 -bFUSEnabled.x86 =C4F74 - -bInitialized.x64 =E9430 -bRemoteConnAllowed.x64=E9434 -bMultimonAllowed.x64 =E9438 -ulMaxDebugSessions.x64=E943C -bFUSEnabled.x64 =E9440 -bServerSku.x64 =E944C -lMaxUserSessions.x64 =E9450 -bAppServerAllowed.x64 =E9454 - -[10.0.14352.1002-SLInit] -bInitialized.x86 =C0F5C -bServerSku.x86 =C0F60 -lMaxUserSessions.x86 =C0F64 -bAppServerAllowed.x86 =C0F68 -bRemoteConnAllowed.x86=C0F6C -bMultimonAllowed.x86 =C0F70 -ulMaxDebugSessions.x86=C0F74 -bFUSEnabled.x86 =C0F78 - -bServerSku.x64 =E73C0 -lMaxUserSessions.x64 =E73C4 -bAppServerAllowed.x64 =E73C8 -bInitialized.x64 =E8460 -bRemoteConnAllowed.x64=E8464 -bMultimonAllowed.x64 =E8468 -ulMaxDebugSessions.x64=E846C -bFUSEnabled.x64 =E8470 - -[10.0.14366.0-SLInit] -bInitialized.x86 =C4F68 -bServerSku.x86 =C4F6C -lMaxUserSessions.x86 =C4F70 -bAppServerAllowed.x86 =C4F74 -bRemoteConnAllowed.x86=C4F78 -bMultimonAllowed.x86 =C4F7C -ulMaxDebugSessions.x86=C4F80 -bFUSEnabled.x86 =C4F84 - -bServerSku.x64 =E93E0 -lMaxUserSessions.x64 =E93E4 -bAppServerAllowed.x64 =E93E8 -bInitialized.x64 =EA480 -bRemoteConnAllowed.x64=EA484 -bMultimonAllowed.x64 =EA488 -ulMaxDebugSessions.x64=EA48C -bFUSEnabled.x64 =EA490 - -[10.0.14367.0-SLInit] -bInitialized.x86 =C4F68 -bServerSku.x86 =C4F6C -lMaxUserSessions.x86 =C4F70 -bAppServerAllowed.x86 =C4F74 -bRemoteConnAllowed.x86=C4F78 -bMultimonAllowed.x86 =C4F7C -ulMaxDebugSessions.x86=C4F80 -bFUSEnabled.x86 =C4F84 - -bServerSku.x64 =E93E0 -lMaxUserSessions.x64 =E93E4 -bAppServerAllowed.x64 =E93E8 -bInitialized.x64 =EA480 -bRemoteConnAllowed.x64=EA484 -bMultimonAllowed.x64 =EA488 -ulMaxDebugSessions.x64=EA48C -bFUSEnabled.x64 =EA490 - -[10.0.14372.0-SLInit] -bInitialized.x86 =C3F68 -bServerSku.x86 =C3F6C -lMaxUserSessions.x86 =C3F70 -bAppServerAllowed.x86 =C3F74 -bRemoteConnAllowed.x86=C3F78 -bMultimonAllowed.x86 =C3F7C -ulMaxDebugSessions.x86=C3F80 -bFUSEnabled.x86 =C3F84 -; x64 contributed by kbmorris -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 -bServerSku.x64 =EA47C -lMaxUserSessions.x64 =EA480 -bAppServerAllowed.x64 =EA484 - -[10.0.14379.0-SLInit] -bInitialized.x86 =C3F68 -bServerSku.x86 =C3F6C -lMaxUserSessions.x86 =C3F70 -bAppServerAllowed.x86 =C3F74 -bRemoteConnAllowed.x86=C3F78 -bMultimonAllowed.x86 =C3F7C -ulMaxDebugSessions.x86=C3F80 -bFUSEnabled.x86 =C3F84 - -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 -bServerSku.x64 =EA47C -lMaxUserSessions.x64 =EA480 -bAppServerAllowed.x64 =EA484 - -[10.0.14383.0-SLInit] -bInitialized.x86 =C3F68 -bServerSku.x86 =C3F6C -lMaxUserSessions.x86 =C3F70 -bAppServerAllowed.x86 =C3F74 -bRemoteConnAllowed.x86=C3F78 -bMultimonAllowed.x86 =C3F7C -ulMaxDebugSessions.x86=C3F80 -bFUSEnabled.x86 =C3F84 - -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 -bServerSku.x64 =EA47C -lMaxUserSessions.x64 =EA480 -bAppServerAllowed.x64 =EA484 - -[10.0.14385.0-SLInit] -bInitialized.x86 =C3F68 -bServerSku.x86 =C3F6C -lMaxUserSessions.x86 =C3F70 -bAppServerAllowed.x86 =C3F74 -bRemoteConnAllowed.x86=C3F78 -bMultimonAllowed.x86 =C3F7C -ulMaxDebugSessions.x86=C3F80 -bFUSEnabled.x86 =C3F84 - -bInitialized.x64 =EA460 -bRemoteConnAllowed.x64=EA464 -bMultimonAllowed.x64 =EA468 -ulMaxDebugSessions.x64=EA46C -bFUSEnabled.x64 =EA470 -bServerSku.x64 =EA47C -lMaxUserSessions.x64 =EA480 -bAppServerAllowed.x64 =EA484 - -[10.0.14388.0-SLInit] -bInitialized.x86 =C1F6C -bServerSku.x86 =C1F70 -lMaxUserSessions.x86 =C1F74 -bAppServerAllowed.x86 =C1F78 -bRemoteConnAllowed.x86=C1F7C -bMultimonAllowed.x86 =C1F80 -ulMaxDebugSessions.x86=C1F84 -bFUSEnabled.x86 =C1F88 - -bServerSku.x64 =E73D0 -lMaxUserSessions.x64 =E73D4 -bAppServerAllowed.x64 =E73D8 -bInitialized.x64 =E8470 -bRemoteConnAllowed.x64=E8474 -bMultimonAllowed.x64 =E8478 -ulMaxDebugSessions.x64=E847C -bFUSEnabled.x64 =E8480 - -[10.0.14393.0-SLInit] -bInitialized.x86 =C1F6C -bServerSku.x86 =C1F70 -lMaxUserSessions.x86 =C1F74 -bAppServerAllowed.x86 =C1F78 -bRemoteConnAllowed.x86=C1F7C -bMultimonAllowed.x86 =C1F80 -ulMaxDebugSessions.x86=C1F84 -bFUSEnabled.x86 =C1F88 - -bServerSku.x64 =E73D0 -lMaxUserSessions.x64 =E73D4 -bAppServerAllowed.x64 =E73D8 -bInitialized.x64 =E8470 -bRemoteConnAllowed.x64=E8474 -bMultimonAllowed.x64 =E8478 -ulMaxDebugSessions.x64=E847C -bFUSEnabled.x64 =E8480 - -[10.0.14393.1198-SLInit] -bInitialized.x86 =C1F6C -bServerSku.x86 =C1F70 -lMaxUserSessions.x86 =C1F74 -bAppServerAllowed.x86 =C1F78 -bRemoteConnAllowed.x86=C1F7C -bMultimonAllowed.x86 =C1F80 -ulMaxDebugSessions.x86=C1F84 -bFUSEnabled.x86 =C1F88 - -[10.0.14393.1737-SLInit] -bInitialized.x86 =C1F6C -bServerSku.x86 =C1F70 -lMaxUserSessions.x86 =C1F74 -bAppServerAllowed.x86 =C1F78 -bRemoteConnAllowed.x86=C1F7C -bMultimonAllowed.x86 =C1F80 -ulMaxDebugSessions.x86=C1F84 -bFUSEnabled.x86 =C1F88 - -bServerSku.x64 =E73D0 -lMaxUserSessions.x64 =E73D4 -bAppServerAllowed.x64 =E73D8 -bInitialized.x64 =E8470 -bRemoteConnAllowed.x64=E8474 -bMultimonAllowed.x64 =E8478 -ulMaxDebugSessions.x64=E847C -bFUSEnabled.x64 =E8480 - -[10.0.14393.2457-SLInit] -bInitialized.x86 =C1F94 -bServerSku.x86 =C1F98 -lMaxUserSessions.x86 =C1F9C -bAppServerAllowed.x86 =C1FA0 -bRemoteConnAllowed.x86=C1FA4 -bMultimonAllowed.x86 =C1FA8 -ulMaxDebugSessions.x86=C1FAC -bFUSEnabled.x86 =C1FB0 - -bServerSku.x64 =E73D0 -lMaxUserSessions.x64 =E73D4 -bAppServerAllowed.x64 =E73D8 -bInitialized.x64 =E8470 -bRemoteConnAllowed.x64=E8474 -bMultimonAllowed.x64 =E8478 -ulMaxDebugSessions.x64=E847C -bFUSEnabled.x64 =E8480 - -[10.0.14901.1000-SLInit] -bInitialized.x86 =C1F6C -bServerSku.x86 =C1F70 -lMaxUserSessions.x86 =C1F74 -bAppServerAllowed.x86 =C1F78 -bRemoteConnAllowed.x86=C1F7C -bMultimonAllowed.x86 =C1F80 -ulMaxDebugSessions.x86=C1F84 -bFUSEnabled.x86 =C1F88 - -bServerSku.x64 =E73D0 -lMaxUserSessions.x64 =E73D4 -bAppServerAllowed.x64 =E73D8 -bInitialized.x64 =E8470 -bRemoteConnAllowed.x64=E8474 -bMultimonAllowed.x64 =E8478 -ulMaxDebugSessions.x64=E847C -bFUSEnabled.x64 =E8480 - -[10.0.14905.1000-SLInit] -bInitialized.x86 =C1F6C -bServerSku.x86 =C1F70 -lMaxUserSessions.x86 =C1F74 -bAppServerAllowed.x86 =C1F78 -bRemoteConnAllowed.x86=C1F7C -bMultimonAllowed.x86 =C1F80 -ulMaxDebugSessions.x86=C1F84 -bFUSEnabled.x86 =C1F88 - -bServerSku.x64 =E73D0 -lMaxUserSessions.x64 =E73D4 -bAppServerAllowed.x64 =E73D8 -bInitialized.x64 =E8470 -bRemoteConnAllowed.x64=E8474 -bMultimonAllowed.x64 =E8478 -ulMaxDebugSessions.x64=E847C -bFUSEnabled.x64 =E8480 - -[10.0.14915.1000-SLInit] -bInitialized.x86 =C4F6C -bServerSku.x86 =C4F70 -lMaxUserSessions.x86 =C4F74 -bAppServerAllowed.x86 =C4F78 -bRemoteConnAllowed.x86=C4F7C -bMultimonAllowed.x86 =C4F80 -ulMaxDebugSessions.x86=C4F84 -bFUSEnabled.x86 =C4F88 - -bServerSku.x64 =E93D0 -lMaxUserSessions.x64 =E93D4 -bAppServerAllowed.x64 =E93D8 -bInitialized.x64 =EA470 -bRemoteConnAllowed.x64=EA474 -bMultimonAllowed.x64 =EA478 -ulMaxDebugSessions.x64=EA47C -bFUSEnabled.x64 =EA480 - -[10.0.14926.1000-SLInit] -bInitialized.x86 =C4F6C -bServerSku.x86 =C4F70 -lMaxUserSessions.x86 =C4F74 -bAppServerAllowed.x86 =C4F78 -bRemoteConnAllowed.x86=C4F7C -bMultimonAllowed.x86 =C4F80 -ulMaxDebugSessions.x86=C4F84 -bFUSEnabled.x86 =C4F88 - -bServerSku.x64 =E93D0 -lMaxUserSessions.x64 =E93D4 -bAppServerAllowed.x64 =E93D8 -bInitialized.x64 =EA470 -bRemoteConnAllowed.x64=EA474 -bMultimonAllowed.x64 =EA478 -ulMaxDebugSessions.x64=EA47C -bFUSEnabled.x64 =EA480 - -[10.0.14931.1000-SLInit] -bInitialized.x86 =C1F6C -bServerSku.x86 =C1F70 -lMaxUserSessions.x86 =C1F74 -bAppServerAllowed.x86 =C1F78 -bRemoteConnAllowed.x86=C1F7C -bMultimonAllowed.x86 =C1F80 -ulMaxDebugSessions.x86=C1F84 -bFUSEnabled.x86 =C1F88 - -bServerSku.x64 =E63D0 -lMaxUserSessions.x64 =E63D4 -bAppServerAllowed.x64 =E63D8 -bInitialized.x64 =E7470 -bRemoteConnAllowed.x64=E7474 -bMultimonAllowed.x64 =E7478 -ulMaxDebugSessions.x64=E747C -bFUSEnabled.x64 =E7480 - -[10.0.14936.1000-SLInit] -bInitialized.x86 =C0F6C -bServerSku.x86 =C0F70 -lMaxUserSessions.x86 =C0F74 -bAppServerAllowed.x86 =C0F78 -bRemoteConnAllowed.x86=C0F7C -bMultimonAllowed.x86 =C0F80 -ulMaxDebugSessions.x86=C0F84 -bFUSEnabled.x86 =C0F88 - -bInitialized.x64 =E8460 -bRemoteConnAllowed.x64=E8464 -bMultimonAllowed.x64 =E8468 -ulMaxDebugSessions.x64=E846C -bFUSEnabled.x64 =E8470 -bServerSku.x64 =E847C -lMaxUserSessions.x64 =E8480 -bAppServerAllowed.x64 =E8484 - -[10.0.14942.1000-SLInit] -bInitialized.x86 =C0F6C -bServerSku.x86 =C0F70 -lMaxUserSessions.x86 =C0F74 -bAppServerAllowed.x86 =C0F78 -bRemoteConnAllowed.x86=C0F7C -bMultimonAllowed.x86 =C0F80 -ulMaxDebugSessions.x86=C0F84 -bFUSEnabled.x86 =C0F88 - -bInitialized.x64 =EC460 -bRemoteConnAllowed.x64=EC464 -bMultimonAllowed.x64 =EC468 -ulMaxDebugSessions.x64=EC46C -bFUSEnabled.x64 =EC470 -bServerSku.x64 =EC47C -lMaxUserSessions.x64 =EC480 -bAppServerAllowed.x64 =EC484 - -[10.0.14946.1000-SLInit] -bInitialized.x86 =C0F6C -bServerSku.x86 =C0F70 -lMaxUserSessions.x86 =C0F74 -bAppServerAllowed.x86 =C0F78 -bRemoteConnAllowed.x86=C0F7C -bMultimonAllowed.x86 =C0F80 -ulMaxDebugSessions.x86=C0F84 -bFUSEnabled.x86 =C0F88 - -bInitialized.x64 =EC460 -bRemoteConnAllowed.x64=EC464 -bMultimonAllowed.x64 =EC468 -ulMaxDebugSessions.x64=EC46C -bFUSEnabled.x64 =EC470 -bServerSku.x64 =EC47C -lMaxUserSessions.x64 =EC480 -bAppServerAllowed.x64 =EC484 - -[10.0.14951.1000-SLInit] -bInitialized.x86 =C5F68 -bServerSku.x86 =C5F6C -lMaxUserSessions.x86 =C5F70 -bAppServerAllowed.x86 =C5F74 -bRemoteConnAllowed.x86=C5F78 -bMultimonAllowed.x86 =C5F7C -ulMaxDebugSessions.x86=C5F80 -bFUSEnabled.x86 =C5F84 - -bServerSku.x64 =EF3D0 -lMaxUserSessions.x64 =EF3D4 -bAppServerAllowed.x64 =EF3D8 -bInitialized.x64 =F0470 -bRemoteConnAllowed.x64=F0474 -bMultimonAllowed.x64 =F0478 -ulMaxDebugSessions.x64=F047C -bFUSEnabled.x64 =F0480 - -[10.0.14955.1000-SLInit] -bInitialized.x86 =C5F68 -bServerSku.x86 =C5F6C -lMaxUserSessions.x86 =C5F70 -bAppServerAllowed.x86 =C5F74 -bRemoteConnAllowed.x86=C5F78 -bMultimonAllowed.x86 =C5F7C -ulMaxDebugSessions.x86=C5F80 -bFUSEnabled.x86 =C5F84 - -bServerSku.x64 =EF3D0 -lMaxUserSessions.x64 =EF3D4 -bAppServerAllowed.x64 =EF3D8 -bInitialized.x64 =F0470 -bRemoteConnAllowed.x64=F0474 -bMultimonAllowed.x64 =F0478 -ulMaxDebugSessions.x64=F047C -bFUSEnabled.x64 =F0480 - -[10.0.14959.1000-SLInit] -bInitialized.x86 =C4F68 -bServerSku.x86 =C4F6C -lMaxUserSessions.x86 =C4F70 -bAppServerAllowed.x86 =C4F74 -bRemoteConnAllowed.x86=C4F78 -bMultimonAllowed.x86 =C4F7C -ulMaxDebugSessions.x86=C4F80 -bFUSEnabled.x86 =C4F84 - -bServerSku.x64 =EE3D0 -lMaxUserSessions.x64 =EE3D4 -bAppServerAllowed.x64 =EE3D8 -bInitialized.x64 =EF470 -bRemoteConnAllowed.x64=EF474 -bMultimonAllowed.x64 =EF478 -ulMaxDebugSessions.x64=EF47C -bFUSEnabled.x64 =EF480 - -[10.0.14965.1001-SLInit] -bInitialized.x86 =C5F68 -bServerSku.x86 =C5F6C -lMaxUserSessions.x86 =C5F70 -bAppServerAllowed.x86 =C5F74 -bRemoteConnAllowed.x86=C5F78 -bMultimonAllowed.x86 =C5F7C -ulMaxDebugSessions.x86=C5F80 -bFUSEnabled.x86 =C5F84 - -bInitialized.x64 =EF460 -bRemoteConnAllowed.x64=EF464 -bMultimonAllowed.x64 =EF468 -ulMaxDebugSessions.x64=EF46C -bFUSEnabled.x64 =EF470 -bServerSku.x64 =EF47C -lMaxUserSessions.x64 =EF480 -bAppServerAllowed.x64 =EF484 - -[10.0.14971.1000-SLInit] -bInitialized.x86 =C5F68 -bServerSku.x86 =C5F6C -lMaxUserSessions.x86 =C5F70 -bAppServerAllowed.x86 =C5F74 -bRemoteConnAllowed.x86=C5F78 -bMultimonAllowed.x86 =C5F7C -ulMaxDebugSessions.x86=C5F80 -bFUSEnabled.x86 =C5F84 - -bServerSku.x64 =EE3C0 -lMaxUserSessions.x64 =EE3C4 -bAppServerAllowed.x64 =EE3C8 -bInitialized.x64 =EE470 -bRemoteConnAllowed.x64=EE474 -bMultimonAllowed.x64 =EE478 -ulMaxDebugSessions.x64=EE47C -bFUSEnabled.x64 =EE480 - -[10.0.14986.1000-SLInit] -bInitialized.x86 =C5F68 -bServerSku.x86 =C5F6C -lMaxUserSessions.x86 =C5F70 -bAppServerAllowed.x86 =C5F74 -bRemoteConnAllowed.x86=C5F78 -bMultimonAllowed.x86 =C5F7C -ulMaxDebugSessions.x86=C5F80 -bFUSEnabled.x86 =C5F84 - -bServerSku.x64 =EE3C0 -lMaxUserSessions.x64 =EE3C4 -bAppServerAllowed.x64 =EE3C8 -bInitialized.x64 =EE470 -bRemoteConnAllowed.x64=EE474 -bMultimonAllowed.x64 =EE478 -ulMaxDebugSessions.x64=EE47C -bFUSEnabled.x64 =EE480 - -[10.0.14997.1001-SLInit] -bServerSku.x64 =F0408 -lMaxUserSessions.x64 =F040C -bAppServerAllowed.x64 =F0410 -bInitialized.x64 =F0480 -bRemoteConnAllowed.x64=F0484 -bMultimonAllowed.x64 =F0488 -ulMaxDebugSessions.x64=F048C -bFUSEnabled.x64 =F0490 - -[10.0.15002.1001-SLInit] -bInitialized.x86 =C6F74 -bServerSku.x86 =C6F78 -lMaxUserSessions.x86 =C6F7C -bAppServerAllowed.x86 =C6F80 -bRemoteConnAllowed.x86=C6F84 -bMultimonAllowed.x86 =C6F88 -ulMaxDebugSessions.x86=C6F8C -bFUSEnabled.x86 =C6F90 - -bServerSku.x64 =F0408 -lMaxUserSessions.x64 =F040C -bAppServerAllowed.x64 =F0410 -bInitialized.x64 =F0480 -bRemoteConnAllowed.x64=F0484 -bMultimonAllowed.x64 =F0488 -ulMaxDebugSessions.x64=F048C -bFUSEnabled.x64 =F0490 - -[10.0.15007.1000-SLInit] -bInitialized.x86 =C6F74 -bServerSku.x86 =C6F78 -lMaxUserSessions.x86 =C6F7C -bAppServerAllowed.x86 =C6F80 -bRemoteConnAllowed.x86=C6F84 -bMultimonAllowed.x86 =C6F88 -ulMaxDebugSessions.x86=C6F8C -bFUSEnabled.x86 =C6F90 - -bServerSku.x64 =F0408 -lMaxUserSessions.x64 =F040C -bAppServerAllowed.x64 =F0410 -bInitialized.x64 =F0480 -bRemoteConnAllowed.x64=F0484 -bMultimonAllowed.x64 =F0488 -ulMaxDebugSessions.x64=F048C -bFUSEnabled.x64 =F0490 - -[10.0.15014.1000-SLInit] -bInitialized.x86 =C6F74 -bServerSku.x86 =C6F78 -lMaxUserSessions.x86 =C6F7C -bAppServerAllowed.x86 =C6F80 -bRemoteConnAllowed.x86=C6F84 -bMultimonAllowed.x86 =C6F88 -ulMaxDebugSessions.x86=C6F8C -bFUSEnabled.x86 =C6F90 - -bServerSku.x64 =F0408 -lMaxUserSessions.x64 =F040C -bAppServerAllowed.x64 =F0410 -bInitialized.x64 =F0480 -bRemoteConnAllowed.x64=F0484 -bMultimonAllowed.x64 =F0488 -ulMaxDebugSessions.x64=F048C -bFUSEnabled.x64 =F0490 - -[10.0.15019.1000-SLInit] -bInitialized.x86 =C5F68 -bServerSku.x86 =C5F6C -lMaxUserSessions.x86 =C5F70 -bAppServerAllowed.x86 =C5F74 -bRemoteConnAllowed.x86=C5F78 -bMultimonAllowed.x86 =C5F7C -ulMaxDebugSessions.x86=C5F80 -bFUSEnabled.x86 =C5F84 - -bServerSku.x64 =ECBDC -lMaxUserSessions.x64 =ECBE0 -bAppServerAllowed.x64 =ECBE4 -bInitialized.x64 =F0490 -bRemoteConnAllowed.x64=F0494 -bMultimonAllowed.x64 =F0498 -ulMaxDebugSessions.x64=F049C -bFUSEnabled.x64 =F04A0 - -[10.0.15025.1000-SLInit] -bServerSku.x64 =EE3E0 -lMaxUserSessions.x64 =EE3E4 -bAppServerAllowed.x64 =EE3E8 -bInitialized.x64 =EF488 -bRemoteConnAllowed.x64=EF48C -bMultimonAllowed.x64 =EF490 -ulMaxDebugSessions.x64=EF494 -bFUSEnabled.x64 =EF498 - -[10.0.15031.0-SLInit] -bInitialized.x86 =C2F6C -bServerSku.x86 =C2F70 -lMaxUserSessions.x86 =C2F74 -bAppServerAllowed.x86 =C2F78 -bRemoteConnAllowed.x86=C2F7C -bMultimonAllowed.x86 =C2F80 -ulMaxDebugSessions.x86=C2F84 -bFUSEnabled.x86 =C2F88 - -bServerSku.x64 =E93E0 -lMaxUserSessions.x64 =E93E4 -bAppServerAllowed.x64 =E93E8 -bInitialized.x64 =EA488 -bRemoteConnAllowed.x64=EA48C -bMultimonAllowed.x64 =EA490 -ulMaxDebugSessions.x64=EA494 -bFUSEnabled.x64 =EA498 - -[10.0.15042.0-SLInit] -bInitialized.x86 =C2F6C -bServerSku.x86 =C2F70 -lMaxUserSessions.x86 =C2F74 -bAppServerAllowed.x86 =C2F78 -bRemoteConnAllowed.x86=C2F7C -bMultimonAllowed.x86 =C2F80 -ulMaxDebugSessions.x86=C2F84 -bFUSEnabled.x86 =C2F88 - -bServerSku.x64 =E93E0 -lMaxUserSessions.x64 =E93E4 -bAppServerAllowed.x64 =E93E8 -bInitialized.x64 =EA488 -bRemoteConnAllowed.x64=EA48C -bMultimonAllowed.x64 =EA490 -ulMaxDebugSessions.x64=EA494 -bFUSEnabled.x64 =EA498 - -[10.0.15046.0-SLInit] -bInitialized.x86 =C4F18 -bServerSku.x86 =C4F1C -lMaxUserSessions.x86 =C4F20 -bAppServerAllowed.x86 =C4F24 -bRemoteConnAllowed.x86=C4F28 -ulMaxDebugSessions.x86=C4F2C -bMultimonAllowed.x86 =C5010 -bFUSEnabled.x86 =C5014 - -bInitialized.x64 =EB468 -bRemoteConnAllowed.x64=EB46C -bMultimonAllowed.x64 =EB470 -ulMaxDebugSessions.x64=EB474 -bFUSEnabled.x64 =EB478 -bServerSku.x64 =EB484 -lMaxUserSessions.x64 =EB488 -bAppServerAllowed.x64 =EB48C - -[10.0.15048.0-SLInit] -bInitialized.x86 =C4F18 -bServerSku.x86 =C4F1C -lMaxUserSessions.x86 =C4F20 -bAppServerAllowed.x86 =C4F24 -bRemoteConnAllowed.x86=C4F28 -ulMaxDebugSessions.x86=C4F2C -bMultimonAllowed.x86 =C5010 -bFUSEnabled.x86 =C5014 - -bInitialized.x64 =EB468 -bRemoteConnAllowed.x64=EB46C -bMultimonAllowed.x64 =EB470 -ulMaxDebugSessions.x64=EB474 -bFUSEnabled.x64 =EB478 -bServerSku.x64 =EB484 -lMaxUserSessions.x64 =EB488 -bAppServerAllowed.x64 =EB48C - -[10.0.15055.0-SLInit] -bInitialized.x86 =C2F70 -bServerSku.x86 =C2F74 -lMaxUserSessions.x86 =C2F78 -bAppServerAllowed.x86 =C2F7C -bRemoteConnAllowed.x86=C2F80 -bMultimonAllowed.x86 =C2F84 -ulMaxDebugSessions.x86=C2F88 -bFUSEnabled.x86 =C2F8C - -bServerSku.x64 =E83D8 -lMaxUserSessions.x64 =E83DC -bAppServerAllowed.x64 =E83E0 -bInitialized.x64 =E9490 -bRemoteConnAllowed.x64=E9494 -bMultimonAllowed.x64 =E9498 -ulMaxDebugSessions.x64=E949C -bFUSEnabled.x64 =E94A0 - -[10.0.15058.0-SLInit] -bInitialized.x86 =C2F70 -bServerSku.x86 =C2F74 -lMaxUserSessions.x86 =C2F78 -bAppServerAllowed.x86 =C2F7C -bRemoteConnAllowed.x86=C2F80 -bMultimonAllowed.x86 =C2F84 -ulMaxDebugSessions.x86=C2F88 -bFUSEnabled.x86 =C2F8C - -bInitialized.x64 =E9468 -bRemoteConnAllowed.x64=E946C -bMultimonAllowed.x64 =E9470 -ulMaxDebugSessions.x64=E9474 -bFUSEnabled.x64 =E9478 -bServerSku.x64 =E9484 -lMaxUserSessions.x64 =E9488 -bAppServerAllowed.x64 =E948C - -[10.0.15061.0-SLInit] -bInitialized.x86 =C2F70 -bServerSku.x86 =C2F74 -lMaxUserSessions.x86 =C2F78 -bAppServerAllowed.x86 =C2F7C -bRemoteConnAllowed.x86=C2F80 -bMultimonAllowed.x86 =C2F84 -ulMaxDebugSessions.x86=C2F88 -bFUSEnabled.x86 =C2F8C - -bInitialized.x64 =E9468 -bRemoteConnAllowed.x64=E946C -bMultimonAllowed.x64 =E9470 -ulMaxDebugSessions.x64=E9474 -bFUSEnabled.x64 =E9478 -bServerSku.x64 =E9484 -lMaxUserSessions.x64 =E9488 -bAppServerAllowed.x64 =E948C - -[10.0.15063.0-SLInit] -bInitialized.x86 =C2F70 -bServerSku.x86 =C2F74 -lMaxUserSessions.x86 =C2F78 -bAppServerAllowed.x86 =C2F7C -bRemoteConnAllowed.x86=C2F80 -bMultimonAllowed.x86 =C2F84 -ulMaxDebugSessions.x86=C2F88 -bFUSEnabled.x86 =C2F8C - -bInitialized.x64 =E9468 -bRemoteConnAllowed.x64=E946C -bMultimonAllowed.x64 =E9470 -ulMaxDebugSessions.x64=E9474 -bFUSEnabled.x64 =E9478 -bServerSku.x64 =E9484 -lMaxUserSessions.x64 =E9488 -bAppServerAllowed.x64 =E948C - -[10.0.15063.296-SLInit] -bInitialized.x86 =C2F70 -bServerSku.x86 =C2F74 -lMaxUserSessions.x86 =C2F78 -bAppServerAllowed.x86 =C2F7C -bRemoteConnAllowed.x86=C2F80 -bMultimonAllowed.x86 =C2F84 -ulMaxDebugSessions.x86=C2F88 -bFUSEnabled.x86 =C2F8C - -bInitialized.x64 =E9468 -bRemoteConnAllowed.x64=E946C -bMultimonAllowed.x64 =E9470 -ulMaxDebugSessions.x64=E9474 -bFUSEnabled.x64 =E9478 -bServerSku.x64 =E9484 -lMaxUserSessions.x64 =E9488 -bAppServerAllowed.x64 =E948C - -[10.0.15063.994-SLInit] -bInitialized.x64 =E9468 -bRemoteConnAllowed.x64=E946C -bMultimonAllowed.x64 =E9470 -ulMaxDebugSessions.x64=E9474 -bFUSEnabled.x64 =E9478 -bServerSku.x64 =E9484 -lMaxUserSessions.x64 =E9488 -bAppServerAllowed.x64 =E948C - -[10.0.15063.1155-SLInit] -bInitialized.x64 =E9468 -bRemoteConnAllowed.x64=E946C -bMultimonAllowed.x64 =E9470 -ulMaxDebugSessions.x64=E9474 -bFUSEnabled.x64 =E9478 -bServerSku.x64 =E9484 -lMaxUserSessions.x64 =E9488 -bAppServerAllowed.x64 =E948C - -[10.0.16179.1000-SLInit] -bInitialized.x86 =C7F6C -bServerSku.x86 =C7F70 -lMaxUserSessions.x86 =C7F74 -bAppServerAllowed.x86 =C7F78 -bRemoteConnAllowed.x86=C7F7C -bMultimonAllowed.x86 =C7F80 -ulMaxDebugSessions.x86=C7F84 -bFUSEnabled.x86 =C7F88 - -bServerSku.x64 =E83D8 -lMaxUserSessions.x64 =E83DC -bAppServerAllowed.x64 =E83E0 -bInitialized.x64 =E9490 -bRemoteConnAllowed.x64=E9494 -bMultimonAllowed.x64 =E9498 -ulMaxDebugSessions.x64=E949C -bFUSEnabled.x64 =E94A0 - -[10.0.16184.1001-SLInit] -bInitialized.x86 =C7F6C -bServerSku.x86 =C7F70 -lMaxUserSessions.x86 =C7F74 -bAppServerAllowed.x86 =C7F78 -bRemoteConnAllowed.x86=C7F7C -bMultimonAllowed.x86 =C7F80 -ulMaxDebugSessions.x86=C7F84 -bFUSEnabled.x86 =C7F88 - -bServerSku.x64 =E83D8 -lMaxUserSessions.x64 =E83DC -bAppServerAllowed.x64 =E83E0 -bInitialized.x64 =E9490 -bRemoteConnAllowed.x64=E9494 -bMultimonAllowed.x64 =E9498 -ulMaxDebugSessions.x64=E949C -bFUSEnabled.x64 =E94A0 - -[10.0.16199.1000-SLInit] -bInitialized.x86 =C8F74 -bServerSku.x86 =C8F78 -lMaxUserSessions.x86 =C8F7C -bAppServerAllowed.x86 =C8F80 -bRemoteConnAllowed.x86=C8F84 -bMultimonAllowed.x86 =C8F88 -ulMaxDebugSessions.x86=C8F8C -bFUSEnabled.x86 =C8F90 - -bServerSku.x64 =E83E8 -lMaxUserSessions.x64 =E83EC -bAppServerAllowed.x64 =E83F0 -bInitialized.x64 =E94A0 -bRemoteConnAllowed.x64=E94A4 -bMultimonAllowed.x64 =E94A8 -ulMaxDebugSessions.x64=E94AC -bFUSEnabled.x64 =E94B0 - -[10.0.16215.1000-SLInit] -bInitialized.x86 =C5F78 -bServerSku.x86 =C5F7C -lMaxUserSessions.x86 =C5F80 -bAppServerAllowed.x86 =C5F84 -bRemoteConnAllowed.x86=C5F88 -bMultimonAllowed.x86 =C5F8C -ulMaxDebugSessions.x86=C5F90 -bFUSEnabled.x86 =C5F94 - -bServerSku.x64 =EA3E8 -lMaxUserSessions.x64 =EA3EC -bAppServerAllowed.x64 =EA3F0 -bInitialized.x64 =EB4A0 -bRemoteConnAllowed.x64=EB4A4 -bMultimonAllowed.x64 =EB4A8 -ulMaxDebugSessions.x64=EB4AC -bFUSEnabled.x64 =EB4B0 - -[10.0.16232.1000-SLInit] -bInitialized.x86 =C5F78 -bServerSku.x86 =C5F7C -lMaxUserSessions.x86 =C5F80 -bAppServerAllowed.x86 =C5F84 -bRemoteConnAllowed.x86=C5F88 -bMultimonAllowed.x86 =C5F8C -ulMaxDebugSessions.x86=C5F90 -bFUSEnabled.x86 =C5F94 - -bServerSku.x64 =EA3E8 -lMaxUserSessions.x64 =EA3EC -bAppServerAllowed.x64 =EA3F0 -bInitialized.x64 =EB4A0 -bRemoteConnAllowed.x64=EB4A4 -bMultimonAllowed.x64 =EB4A8 -ulMaxDebugSessions.x64=EB4AC -bFUSEnabled.x64 =EB4B0 - -[10.0.16237.1001-SLInit] -bInitialized.x86 =C5F78 -bServerSku.x86 =C5F7C -lMaxUserSessions.x86 =C5F80 -bAppServerAllowed.x86 =C5F84 -bRemoteConnAllowed.x86=C5F88 -bMultimonAllowed.x86 =C5F8C -ulMaxDebugSessions.x86=C5F90 -bFUSEnabled.x86 =C5F94 - -bServerSku.x64 =EB3EC -lMaxUserSessions.x64 =EB3F0 -bAppServerAllowed.x64 =EB3F4 -bInitialized.x64 =EC4A0 -bRemoteConnAllowed.x64=EC4A4 -bMultimonAllowed.x64 =EC4A8 -ulMaxDebugSessions.x64=EC4AC -bFUSEnabled.x64 =EC4B0 - -[10.0.16241.1001-SLInit] -bInitialized.x86 =C5F78 -bServerSku.x86 =C5F7C -lMaxUserSessions.x86 =C5F80 -bAppServerAllowed.x86 =C5F84 -bRemoteConnAllowed.x86=C5F88 -bMultimonAllowed.x86 =C5F8C -ulMaxDebugSessions.x86=C5F90 -bFUSEnabled.x86 =C5F94 - -bServerSku.x64 =EB3EC -lMaxUserSessions.x64 =EB3F0 -bAppServerAllowed.x64 =EB3F4 -bInitialized.x64 =EC4A0 -bRemoteConnAllowed.x64=EC4A4 -bMultimonAllowed.x64 =EC4A8 -ulMaxDebugSessions.x64=EC4AC -bFUSEnabled.x64 =EC4B0 - -[10.0.16251.0-SLInit] -bInitialized.x86 =C9F78 -bServerSku.x86 =C9F7C -lMaxUserSessions.x86 =C9F80 -bAppServerAllowed.x86 =C9F84 -bRemoteConnAllowed.x86=C9F88 -bMultimonAllowed.x86 =C9F8C -ulMaxDebugSessions.x86=C9F90 -bFUSEnabled.x86 =C9F94 - -bServerSku.x64 =EB3EC -lMaxUserSessions.x64 =EB3F0 -bAppServerAllowed.x64 =EB3F4 -bInitialized.x64 =EC4A0 -bRemoteConnAllowed.x64=EC4A4 -bMultimonAllowed.x64 =EC4A8 -ulMaxDebugSessions.x64=EC4AC -bFUSEnabled.x64 =EC4B0 - -[10.0.16251.1000-SLInit] -bInitialized.x86 =C9F78 -bServerSku.x86 =C9F7C -lMaxUserSessions.x86 =C9F80 -bAppServerAllowed.x86 =C9F84 -bRemoteConnAllowed.x86=C9F88 -bMultimonAllowed.x86 =C9F8C -ulMaxDebugSessions.x86=C9F90 -bFUSEnabled.x86 =C9F94 - -bServerSku.x64 =EB3EC -lMaxUserSessions.x64 =EB3F0 -bAppServerAllowed.x64 =EB3F4 -bInitialized.x64 =EC4A0 -bRemoteConnAllowed.x64=EC4A4 -bMultimonAllowed.x64 =EC4A8 -ulMaxDebugSessions.x64=EC4AC -bFUSEnabled.x64 =EC4B0 - -[10.0.16257.1-SLInit] -bInitialized.x86 =C9F7C -bServerSku.x86 =C9F80 -lMaxUserSessions.x86 =C9F84 -bAppServerAllowed.x86 =C9F88 -bRemoteConnAllowed.x86=C9F8C -bMultimonAllowed.x86 =C9F90 -ulMaxDebugSessions.x86=C9F94 -bFUSEnabled.x86 =C9F98 - -bServerSku.x64 =EB3F0 -lMaxUserSessions.x64 =EB3F4 -bAppServerAllowed.x64 =EB3F8 -bInitialized.x64 =EC4A0 -bRemoteConnAllowed.x64=EC4A4 -bMultimonAllowed.x64 =EC4A8 -ulMaxDebugSessions.x64=EC4AC -bFUSEnabled.x64 =EC4B0 - -[10.0.16257.1000-SLInit] -bInitialized.x86 =C9F7C -bServerSku.x86 =C9F80 -lMaxUserSessions.x86 =C9F84 -bAppServerAllowed.x86 =C9F88 -bRemoteConnAllowed.x86=C9F8C -bMultimonAllowed.x86 =C9F90 -ulMaxDebugSessions.x86=C9F94 -bFUSEnabled.x86 =C9F98 - -bServerSku.x64 =EB3F0 -lMaxUserSessions.x64 =EB3F4 -bAppServerAllowed.x64 =EB3F8 -bInitialized.x64 =EC4A0 -bRemoteConnAllowed.x64=EC4A4 -bMultimonAllowed.x64 =EC4A8 -ulMaxDebugSessions.x64=EC4AC -bFUSEnabled.x64 =EC4B0 - -[10.0.16273.1000-SLInit] -bInitialized.x86 =C9F7C -bServerSku.x86 =C9F80 -lMaxUserSessions.x86 =C9F84 -bAppServerAllowed.x86 =C9F88 -bRemoteConnAllowed.x86=C9F8C -bMultimonAllowed.x86 =C9F90 -ulMaxDebugSessions.x86=C9F94 -bFUSEnabled.x86 =C9F98 - -bServerSku.x64 =EB3F0 -lMaxUserSessions.x64 =EB3F4 -bAppServerAllowed.x64 =EB3F8 -bInitialized.x64 =EC4A0 -bRemoteConnAllowed.x64=EC4A4 -bMultimonAllowed.x64 =EC4A8 -ulMaxDebugSessions.x64=EC4AC -bFUSEnabled.x64 =EC4B0 - -[10.0.16275.1000-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16278.1000-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16281.1000-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16288.1-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16291.0-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16294.1-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16296.0-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16299.0-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16299.15-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16353.1000-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.16362.1000-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.17004.1000-SLInit] -bInitialized.x86 =C6F7C -bServerSku.x86 =C6F80 -lMaxUserSessions.x86 =C6F84 -bAppServerAllowed.x86 =C6F88 -bRemoteConnAllowed.x86=C6F8C -bMultimonAllowed.x86 =C6F90 -ulMaxDebugSessions.x86=C6F94 -bFUSEnabled.x86 =C6F98 - -bServerSku.x64 =ED3E8 -lMaxUserSessions.x64 =ED3EC -bAppServerAllowed.x64 =ED3F0 -bInitialized.x64 =EE4A0 -bRemoteConnAllowed.x64=EE4A4 -bMultimonAllowed.x64 =EE4A8 -ulMaxDebugSessions.x64=EE4AC -bFUSEnabled.x64 =EE4B0 - -[10.0.17017.1000-SLInit] -bInitialized.x86 =C9EB8 -bServerSku.x86 =C9EBC -lMaxUserSessions.x86 =C9EC0 -bAppServerAllowed.x86 =C9EC4 -bRemoteConnAllowed.x86=C9EC8 -bMultimonAllowed.x86 =C9ECC -ulMaxDebugSessions.x86=C9ED0 -bFUSEnabled.x86 =C9ED4 - -bServerSku.x64 =EC2E8 -lMaxUserSessions.x64 =EC2EC -bAppServerAllowed.x64 =EC2F0 -bInitialized.x64 =ED3A0 -bRemoteConnAllowed.x64=ED3A4 -bMultimonAllowed.x64 =ED3A8 -ulMaxDebugSessions.x64=ED3AC -bFUSEnabled.x64 =ED3B0 - -[10.0.17025.1000-SLInit] -bInitialized.x86 =C9EB8 -bServerSku.x86 =C9EBC -lMaxUserSessions.x86 =C9EC0 -bAppServerAllowed.x86 =C9EC4 -bRemoteConnAllowed.x86=C9EC8 -bMultimonAllowed.x86 =C9ECC -ulMaxDebugSessions.x86=C9ED0 -bFUSEnabled.x86 =C9ED4 - -bServerSku.x64 =EC2E8 -lMaxUserSessions.x64 =EC2EC -bAppServerAllowed.x64 =EC2F0 -bInitialized.x64 =ED3A0 -bRemoteConnAllowed.x64=ED3A4 -bMultimonAllowed.x64 =ED3A8 -ulMaxDebugSessions.x64=ED3AC -bFUSEnabled.x64 =ED3B0 - -[10.0.17035.1000-SLInit] -bInitialized.x86 =C9ED8 -bServerSku.x86 =C9EDC -lMaxUserSessions.x86 =C9EE0 -bAppServerAllowed.x86 =C9EE4 -bRemoteConnAllowed.x86=C9EE8 -bMultimonAllowed.x86 =C9EEC -ulMaxDebugSessions.x86=C9EF0 -bFUSEnabled.x86 =C9EF4 - -bServerSku.x64 =EC2E8 -lMaxUserSessions.x64 =EC2EC -bAppServerAllowed.x64 =EC2F0 -bInitialized.x64 =ED3A0 -bRemoteConnAllowed.x64=ED3A4 -bMultimonAllowed.x64 =ED3A8 -ulMaxDebugSessions.x64=ED3AC -bFUSEnabled.x64 =ED3B0 - -[10.0.17046.1000-SLInit] -bInitialized.x86 =C9ED8 -bServerSku.x86 =C9EDC -lMaxUserSessions.x86 =C9EE0 -bAppServerAllowed.x86 =C9EE4 -bRemoteConnAllowed.x86=C9EE8 -bMultimonAllowed.x86 =C9EEC -ulMaxDebugSessions.x86=C9EF0 -bFUSEnabled.x86 =C9EF4 - -bServerSku.x64 =EC2E8 -lMaxUserSessions.x64 =EC2EC -bAppServerAllowed.x64 =EC2F0 -bInitialized.x64 =ED3A0 -bRemoteConnAllowed.x64=ED3A4 -bMultimonAllowed.x64 =ED3A8 -ulMaxDebugSessions.x64=ED3AC -bFUSEnabled.x64 =ED3B0 - -[10.0.17063.1000-SLInit] -bInitialized.x86 =CBF38 -bServerSku.x86 =CBF3C -lMaxUserSessions.x86 =CBF40 -bAppServerAllowed.x86 =CBF44 -bRemoteConnAllowed.x86=CBF48 -bMultimonAllowed.x86 =CBF4C -ulMaxDebugSessions.x86=CBF50 -bFUSEnabled.x86 =CBF54 - -bServerSku.x64 =F1378 -lMaxUserSessions.x64 =F137C -bAppServerAllowed.x64 =F1380 -bInitialized.x64 =F2430 -bRemoteConnAllowed.x64=F2434 -bMultimonAllowed.x64 =F2438 -ulMaxDebugSessions.x64=F243C -bFUSEnabled.x64 =F2440 - -[10.0.17115.1-SLInit] -bInitialized.x86 =CBF38 -bServerSku.x86 =CBF3C -lMaxUserSessions.x86 =CBF40 -bAppServerAllowed.x86 =CBF44 -bRemoteConnAllowed.x86=CBF48 -bMultimonAllowed.x86 =CBF4C -ulMaxDebugSessions.x86=CBF50 -bFUSEnabled.x86 =CBF54 - -bServerSku.x64 =F1378 -lMaxUserSessions.x64 =F137C -bAppServerAllowed.x64 =F1380 -bInitialized.x64 =F2430 -bRemoteConnAllowed.x64=F2434 -bMultimonAllowed.x64 =F2438 -ulMaxDebugSessions.x64=F243C -bFUSEnabled.x64 =F2440 - -[10.0.17128.1-SLInit] -bInitialized.x86 =CBF38 -bServerSku.x86 =CBF3C -lMaxUserSessions.x86 =CBF40 -bAppServerAllowed.x86 =CBF44 -bRemoteConnAllowed.x86=CBF48 -bMultimonAllowed.x86 =CBF4C -ulMaxDebugSessions.x86=CBF50 -bFUSEnabled.x86 =CBF54 - -bServerSku.x64 =F1378 -lMaxUserSessions.x64 =F137C -bAppServerAllowed.x64 =F1380 -bInitialized.x64 =F2430 -bRemoteConnAllowed.x64=F2434 -bMultimonAllowed.x64 =F2438 -ulMaxDebugSessions.x64=F243C -bFUSEnabled.x64 =F2440 - -[10.0.17133.1-SLInit] -bInitialized.x86 =CBF38 -bServerSku.x86 =CBF3C -lMaxUserSessions.x86 =CBF40 -bAppServerAllowed.x86 =CBF44 -bRemoteConnAllowed.x86=CBF48 -bMultimonAllowed.x86 =CBF4C -ulMaxDebugSessions.x86=CBF50 -bFUSEnabled.x86 =CBF54 - -bServerSku.x64 =F1378 -lMaxUserSessions.x64 =F137C -bAppServerAllowed.x64 =F1380 -bInitialized.x64 =F2430 -bRemoteConnAllowed.x64=F2434 -bMultimonAllowed.x64 =F2438 -ulMaxDebugSessions.x64=F243C -bFUSEnabled.x64 =F2440 - -[10.0.17134.1-SLInit] -bInitialized.x86 =CBF38 -bServerSku.x86 =CBF3C -lMaxUserSessions.x86 =CBF40 -bAppServerAllowed.x86 =CBF44 -bRemoteConnAllowed.x86=CBF48 -bMultimonAllowed.x86 =CBF4C -ulMaxDebugSessions.x86=CBF50 -bFUSEnabled.x86 =CBF54 - -bServerSku.x64 =F1378 -lMaxUserSessions.x64 =F137C -bAppServerAllowed.x64 =F1380 -bInitialized.x64 =F2430 -bRemoteConnAllowed.x64=F2434 -bMultimonAllowed.x64 =F2438 -ulMaxDebugSessions.x64=F243C -bFUSEnabled.x64 =F2440 - -[10.0.17723.1000-SLInit] -bInitialized.x64 =E9AB0 -bServerSku.x64 =E9AB4 -lMaxUserSessions.x64 =E9AB8 -bAppServerAllowed.x64 =E9AC0 -bRemoteConnAllowed.x64=E9AC4 -bMultimonAllowed.x64 =E9AC8 -ulMaxDebugSessions.x64=E9ACC -bFUSEnabled.x64 =E9AD0 - -[10.0.17763.1-SLInit] -bInitialized.x86 =CD798 -bServerSku.x86 =CD79C -lMaxUserSessions.x86 =CD7A0 -bAppServerAllowed.x86 =CD7A8 -bRemoteConnAllowed.x86=CD7AC -bMultimonAllowed.x86 =CD7B0 -ulMaxDebugSessions.x86=CD7B4 -bFUSEnabled.x86 =CD7B8 - -bInitialized.x64 =ECAB0 -bServerSku.x64 =ECAB4 -lMaxUserSessions.x64 =ECAB8 -bAppServerAllowed.x64 =ECAC0 -bRemoteConnAllowed.x64=ECAC4 -bMultimonAllowed.x64 =ECAC8 -ulMaxDebugSessions.x64=ECACC -bFUSEnabled.x64 =ECAD0 diff --git a/src-csharp/Directory.Build.props b/src-csharp/Directory.Build.props new file mode 100644 index 0000000..48868ce --- /dev/null +++ b/src-csharp/Directory.Build.props @@ -0,0 +1,44 @@ + + + net10.0-windows + x86;x64;arm64 + latest + enable + enable + true + $(Platform) + + false + + true + + + $([System.DateTime]::Now.ToString("yyyy.M.d")) + $([System.DateTime]::Now.ToString("yyyy.M.d")).0 + $([System.DateTime]::Now.ToString("yyyy.M.d")).0 + + Simon Jackson + Simon Jackson (@sjackson0109) + Copyright © 2026 Simon Jackson (@sjackson0109) + RDP Wrapper + https://github.com/sjackson0109/rdpwrap + git + https://github.com/sjackson0109/rdpwrap + + + true + + diff --git a/src-csharp/RDPCheck/MainForm.cs b/src-csharp/RDPCheck/MainForm.cs new file mode 100644 index 0000000..bc33caf --- /dev/null +++ b/src-csharp/RDPCheck/MainForm.cs @@ -0,0 +1,160 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// Hosts the MsRdpClient2 ActiveX control, connects to 127.0.0.2, and +// reports the disconnect reason, mirroring the Delphi RDPDisconnected handler. + +using RDPWrap.Common; + +namespace RDPCheck; + +internal sealed class MainForm : Form +{ + private readonly AxRdpClient2 _rdp; + + // Registry values saved on load — restored on disconnect + private int _savedSecurityLayer; + private int _savedUserAuthentication; + + // ── Constructor / Layout ────────────────────────────────────────────────── + + public MainForm() + { + SuspendLayout(); + + Text = "RDP Wrapper Check"; + ClientSize = new Size(800, 600); + StartPosition = FormStartPosition.CenterScreen; + FormBorderStyle = FormBorderStyle.Sizable; + + _rdp = new AxRdpClient2 + { + Dock = DockStyle.Fill + }; + + Controls.Add(_rdp); + ResumeLayout(false); + + _rdp.Disconnected += OnRdpDisconnected; + Load += OnFormLoad; + } + + // ── FormLoad — mirrors TFrm.FormCreate ──────────────────────────────────── + + private void OnFormLoad(object? sender, EventArgs e) + { + const string rdpTcpKey = + @"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"; + + _rdp.DisconnectedText = "Disconnected."; + _rdp.ConnectingText = "Connecting..."; + _rdp.ConnectedStatusText = "Connected."; + _rdp.UserName = string.Empty; + _rdp.Server = "127.0.0.2"; + + // Read, then zero-out SecurityLayer / UserAuthentication + _savedSecurityLayer = RegistryHelper.ReadInt(rdpTcpKey, "SecurityLayer", 0); + _savedUserAuthentication = RegistryHelper.ReadInt(rdpTcpKey, "UserAuthentication", 0); + + try + { + RegistryHelper.WriteInt(rdpTcpKey, "SecurityLayer", 0); + RegistryHelper.WriteInt(rdpTcpKey, "UserAuthentication", 0); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"[RDP] Registry write failed: {ex.Message}"); + } + + // Read port + int port = RegistryHelper.ReadInt(rdpTcpKey, "PortNumber", 3389); + _rdp.SetPort(port); + + // Subscribe to COM events now that the handle exists + _rdp.SubscribeEvents(); + + // Brief delay then connect — matches Delphi Sleep(1000); RDP.Connect; + Task.Delay(1000).ContinueWith(_ => Invoke((Action)_rdp.Connect)); + } + + // ── OnDisconnected — mirrors TFrm.RDPDisconnected ───────────────────────── + + private void OnRdpDisconnected(object? sender, int discReason) + { + string errStr = discReason switch + { + 0x001 => "Local disconnection.", + 0x002 => "Disconnected by user.", + 0x003 => "Disconnected by server.", + 0x904 => "Socket closed.", + 0xC08 => "Decompress error.", + 0x108 => "Connection timed out.", + 0xC06 => "Decryption error.", + 0x104 => "DNS name lookup failure.", + 0x508 => "DNS lookup failed.", + 0xB06 => "Encryption error.", + 0x604 => "Windows Sockets gethostbyname() call failed.", + 0x208 => "Host not found error.", + 0x408 => "Internal error.", + 0x906 => "Internal security error.", + 0xA06 => "Internal security error.", + 0x506 => "The encryption method specified is not valid.", + 0x804 => "Bad IP address specified.", + 0x606 => "Server security data is not valid.", + 0x406 => "Security data is not valid.", + 0x308 => "The IP address specified is not valid.", + 0x808 => "License negotiation failed.", + 0x908 => "Licensing time-out.", + 0x106 => "Out of memory.", + 0x206 => "Out of memory.", + 0x306 => "Out of memory.", + 0x706 => "Failed to unpack server certificate.", + 0x204 => "Socket connection failed.", + 0x404 => "Windows Sockets recv() call failed.", + 0x704 => "Time-out occurred.", + 0x608 => "Internal timer error.", + 0x304 => "Windows Sockets send() call failed.", + 0xB07 => "The account is disabled.", + 0xE07 => "The account is expired.", + 0xD07 => "The account is locked out.", + 0xC07 => "The account is restricted.", + 0x1B07 => "The received certificate is expired.", + 0x1607 => "The policy does not support delegation of credentials to the target server.", + 0x2107 => "The server authentication policy does not allow connection requests using saved credentials. The user must enter new credentials.", + 0x807 => "Login failed.", + 0x1807 => "No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could be unreachable, or there might have been a trust relationship failure.", + 0xA07 => "The specified user has no account.", + 0xF07 => "The password is expired.", + 0x1207 => "The user password must be changed before logging on for the first time.", + 0x1707 => "Delegation of credentials to the target server is not allowed unless mutual authentication has been achieved.", + 0x2207 => "The smart card is blocked.", + 0x1C07 => "An incorrect PIN was presented to the smart card.", + 0xB09 => "Network Level Authentication is required, run RDPCheck as administrator.", + 0x708 => "RDP is working, but the client doesn't allow loopback connections. Try to connect to your PC from another device in the network.", + _ => $"Unknown code 0x{discReason:X}" + }; + + if (discReason > 2) + { + MessageBox.Show(errStr, "Disconnected", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + // Restore registry + const string rdpTcpKey = + @"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"; + try + { + RegistryHelper.WriteInt(rdpTcpKey, "SecurityLayer", _savedSecurityLayer); + RegistryHelper.WriteInt(rdpTcpKey, "UserAuthentication", _savedUserAuthentication); + } + catch { } + + Application.Exit(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) _rdp.Dispose(); + base.Dispose(disposing); + } +} diff --git a/src-csharp/RDPCheck/Program.cs b/src-csharp/RDPCheck/Program.cs new file mode 100644 index 0000000..f4af297 --- /dev/null +++ b/src-csharp/RDPCheck/Program.cs @@ -0,0 +1,15 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// RDPCheck — WinForms RDP tester entry point. + +namespace RDPCheck; + +internal static class Program +{ + [STAThread] + internal static void Main() + { + ApplicationConfiguration.Initialize(); + Application.Run(new MainForm()); + } +} diff --git a/src-csharp/RDPCheck/RDPCheck.csproj b/src-csharp/RDPCheck/RDPCheck.csproj new file mode 100644 index 0000000..a97d497 --- /dev/null +++ b/src-csharp/RDPCheck/RDPCheck.csproj @@ -0,0 +1,32 @@ + + + WinExe + true + RDPCheck + RDPCheck + app.manifest + app.ico + WinForms RDP loopback connection tester — validates that RDP Wrapper is installed and accepting connections correctly. + + + + + + + + + + + + diff --git a/src-csharp/RDPCheck/RdpComInterop.cs b/src-csharp/RDPCheck/RdpComInterop.cs new file mode 100644 index 0000000..84a6ea2 --- /dev/null +++ b/src-csharp/RDPCheck/RdpComInterop.cs @@ -0,0 +1,147 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// COM interop helpers for hosting the MsRdpClient2 ActiveX control and +// receiving its disconnection event without requiring pre-generated TLB wrappers. + +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace RDPCheck; + +// ── COM interfaces needed for connection-point event subscription ──────────── + +[ComImport] +[Guid("B196B284-BAB4-101A-B69C-00AA00341D07")] +[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal interface IConnectionPointContainer +{ + void EnumConnectionPoints(out IntPtr ppEnum); + void FindConnectionPoint(ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IConnectionPoint ppCP); +} + +[ComImport] +[Guid("B196B287-BAB4-101A-B69C-00AA00341D07")] +[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal interface IConnectionPoint +{ + void GetConnectionInterface(out Guid pIID); + void GetConnectionPointContainer([MarshalAs(UnmanagedType.Interface)] out IConnectionPointContainer ppCPC); + void Advise([MarshalAs(UnmanagedType.Interface)] object pUnkSink, out uint pdwCookie); + void Unadvise(uint dwCookie); + void EnumConnections(out IntPtr ppEnum); +} + +// ── IDispatch-based event interface (dispinterface) ────────────────────────── +// Matching the DIID of IMsTscAxEvents so the RDP control can route events here. + +[ComVisible(true)] +[Guid("336D5562-EBA6-11D0-B0B0-00C04FD610D0")] +[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] +internal interface IRdpEvents +{ + [DispId(1)] void OnConnecting(); + [DispId(2)] void OnConnected(); + [DispId(3)] void OnLoginComplete(); + [DispId(4)] void OnDisconnected(int discReason); + // Additional high-DISPID events are ignored (not listed here) +} + +// ── Managed event sink ──────────────────────────────────────────────────────── + +[ComVisible(true)] +[ClassInterface(ClassInterfaceType.None)] +internal sealed class RdpEventSink : IRdpEvents +{ + private readonly Action _onDisconnected; + + public RdpEventSink(Action onDisconnected) => _onDisconnected = onDisconnected; + + public void OnConnecting() { } + public void OnConnected() { } + public void OnLoginComplete() { } + public void OnDisconnected(int discReason) => _onDisconnected(discReason); +} + +// ── AxHost wrapper for MsRdpClient2 ────────────────────────────────────────── + +internal sealed class AxRdpClient2 : AxHost +{ + // CLSID for MsRdpClient2 (msrdp.ocx / mstscax.dll) + private static readonly Guid Clsid = new("9059F30F-4EB1-4BD2-9FDC-36F43A218F4A"); + // DIID for the default source interface (IMsTscAxEvents / DIMsTscAxEvents) + private static readonly Guid DiidEvents = new("336D5562-EBA6-11D0-B0B0-00C04FD610D0"); + + private dynamic? _ocx; + private IConnectionPoint? _cp; + private uint _cookie; + private RdpEventSink? _sink; + + /// Raised on the UI thread when the RDP control disconnects. + public event EventHandler? Disconnected; + + public AxRdpClient2() : base(Clsid.ToString("B")) { } + + protected override void AttachInterfaces() + { + _ocx = GetOcx() as dynamic; + } + + /// + /// Wires up the COM event sink. Call once after the handle has been created + /// (i.e. after the form is shown). + /// + public void SubscribeEvents() + { + if (_ocx is null) return; + try + { + var cpContainer = (IConnectionPointContainer)_ocx; + var eventsIid = DiidEvents; + cpContainer.FindConnectionPoint(ref eventsIid, out var cp); + _sink = new RdpEventSink(reason => Invoke( + (Action)(() => Disconnected?.Invoke(this, reason)))); + cp.Advise(_sink, out _cookie); + _cp = cp; + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"[RDP] SubscribeEvents failed: {ex.Message}"); + } + } + + /// Unsubscribes the event sink. + public void UnsubscribeEvents() + { + try { _cp?.Unadvise(_cookie); } catch { } + _cp = null; + } + + // ── Typed property / method wrappers ──────────────────────────────────── + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string Server { set { if (_ocx != null) _ocx.Server = value; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string UserName { set { if (_ocx != null) _ocx.UserName = value; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string DisconnectedText { set { if (_ocx != null) _ocx.DisconnectedText = value; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string ConnectingText { set { if (_ocx != null) _ocx.ConnectingText = value; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string ConnectedStatusText { set { if (_ocx != null) _ocx.ConnectedStatusText = value; } } + + public void SetPort(int port) + { + try { if (_ocx != null) _ocx.AdvancedSettings2.RDPPort = port; } catch { } + } + + public void Connect() + { + try { _ocx?.Connect(); } catch { } + } + + protected override void Dispose(bool disposing) + { + if (disposing) UnsubscribeEvents(); + base.Dispose(disposing); + } +} diff --git a/src-csharp/RDPCheck/app.ico b/src-csharp/RDPCheck/app.ico new file mode 100644 index 0000000..2a72a4d Binary files /dev/null and b/src-csharp/RDPCheck/app.ico differ diff --git a/src-csharp/RDPCheck/app.manifest b/src-csharp/RDPCheck/app.manifest new file mode 100644 index 0000000..c0e2d9b --- /dev/null +++ b/src-csharp/RDPCheck/app.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src-csharp/RDPCheck/packages.lock.json b/src-csharp/RDPCheck/packages.lock.json new file mode 100644 index 0000000..59ebcea --- /dev/null +++ b/src-csharp/RDPCheck/packages.lock.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "dependencies": { + "net10.0-windows7.0": { + "rdpwrap": { + "type": "Project" + } + } + } +} \ No newline at end of file diff --git a/src-csharp/RDPConf/LicenseForm.cs b/src-csharp/RDPConf/LicenseForm.cs new file mode 100644 index 0000000..bff9b94 --- /dev/null +++ b/src-csharp/RDPConf/LicenseForm.cs @@ -0,0 +1,53 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// LicenseForm — mirrors LicenseUnit.pas (TLicenseForm). +// Shows a readonly multiline license text with Accept / Decline buttons. + +namespace RDPConf; + +internal sealed class LicenseForm : Form +{ + public LicenseForm(string licenseText) + { + Text = "License Agreement"; + ClientSize = new Size(600, 440); + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + MinimizeBox = false; + StartPosition = FormStartPosition.CenterParent; + Font = new Font("Segoe UI", 9f); + + var mText = new TextBox + { + Multiline = true, + ReadOnly = true, + ScrollBars = ScrollBars.Vertical, + Text = licenseText, + Location = new Point(8, 8), + Size = new Size(576, 380), + Font = new Font("Courier New", 8.5f), + BackColor = SystemColors.Window + }; + + var bAccept = new Button + { + Text = "Accept", + DialogResult = DialogResult.OK, + Location = new Point(428, 398), + Size = new Size(75, 26) + }; + + var bDecline = new Button + { + Text = "Decline", + DialogResult = DialogResult.Cancel, + Location = new Point(509, 398), + Size = new Size(75, 26) + }; + + AcceptButton = bAccept; + CancelButton = bDecline; + + Controls.AddRange(new Control[] { mText, bAccept, bDecline }); + } +} diff --git a/src-csharp/RDPConf/MainForm.cs b/src-csharp/RDPConf/MainForm.cs new file mode 100644 index 0000000..57bc5ad --- /dev/null +++ b/src-csharp/RDPConf/MainForm.cs @@ -0,0 +1,540 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// All logic, registry keys, and label text match the Delphi original. + +using System.Runtime.InteropServices; +using RDPWrap.Common; + +namespace RDPConf; + +internal sealed class MainForm : Form +{ + // ── Controls ────────────────────────────────────────────────────────────── + private readonly CheckBox cbAllowTSConnections = new(); + private readonly CheckBox cbSingleSessionPerUser = new(); + private readonly CheckBox cbHideUsers = new(); + private readonly CheckBox cbCustomPrg = new(); + private readonly NumericUpDown seRDPPort = new(); + private readonly Label lRDPPort = new(); + private readonly GroupBox gbGeneral = new(); + + // NLA radio group + private readonly GroupBox gbNLA = new(); + private readonly RadioButton rbNLA0 = new(); + private readonly RadioButton rbNLA1 = new(); + private readonly RadioButton rbNLA2 = new(); + + // Shadow radio group + private readonly GroupBox gbShadow = new(); + private readonly RadioButton rbShadow0 = new(); + private readonly RadioButton rbShadow1 = new(); + private readonly RadioButton rbShadow2 = new(); + private readonly RadioButton rbShadow3 = new(); + private readonly RadioButton rbShadow4 = new(); + + // Diagnostics + private readonly GroupBox gbDiag = new(); + private readonly Label lService = new(); + private readonly Label lsService = new(); + private readonly Label lListener = new(); + private readonly Label lsListener = new(); + private readonly Label lWrapper = new(); + private readonly Label lsWrapper = new(); + private readonly Label lTSVer = new(); + private readonly Label lsTSVer = new(); + private readonly Label lWrapVer = new(); + private readonly Label lsWrapVer = new(); + private readonly Label lsSuppVer = new(); + + // Buttons / Timer + private readonly Button bOK = new(); + private readonly Button bCancel = new(); + private readonly Button bApply = new(); + private readonly Button bLicense = new(); + private readonly System.Windows.Forms.Timer timer = new(); + + // State (mirrors Delphi globals) + private bool _ready; + private int _oldPort; + + // ── Constructor ─────────────────────────────────────────────────────────── + + public MainForm() + { + SuspendLayout(); + BuildLayout(); + ResumeLayout(false); + PerformLayout(); + + // Wire events + cbAllowTSConnections.CheckedChanged += OnAnyChange; + cbSingleSessionPerUser.CheckedChanged += OnAnyChange; + cbHideUsers.CheckedChanged += OnAnyChange; + cbCustomPrg.CheckedChanged += OnAnyChange; + seRDPPort.ValueChanged += OnAnyChange; + rbNLA0.CheckedChanged += OnAnyChange; + rbNLA1.CheckedChanged += OnAnyChange; + rbNLA2.CheckedChanged += OnAnyChange; + rbShadow0.CheckedChanged += OnAnyChange; + rbShadow1.CheckedChanged += OnAnyChange; + rbShadow2.CheckedChanged += OnAnyChange; + rbShadow3.CheckedChanged += OnAnyChange; + rbShadow4.CheckedChanged += OnAnyChange; + bApply.Click += (_, _) => { WriteSettings(); bApply.Enabled = false; }; + bOK.Click += (_, _) => { if (bApply.Enabled) { WriteSettings(); bApply.Enabled = false; } Close(); }; + bCancel.Click += (_, _) => Close(); + bLicense.Click += OnLicenseClick; + timer.Interval = 1000; + timer.Tick += TimerTimer; + FormClosing += OnFormClosing; + Shown += OnShown; + FormClosed += (_, _) => { if (ArchHelper.Is64Bit) ArchHelper.RevertWow64Redirection(); timer.Stop(); }; + + if (ArchHelper.Is64Bit) ArchHelper.DisableWow64Redirection(); + ReadSettings(); + _ready = true; + } + + private void OnShown(object? sender, EventArgs e) + { + TimerTimer(sender, e); // immediate first tick + timer.Start(); + } + + // ── Layout ──────────────────────────────────────────────────────────────── + + private void BuildLayout() + { + Text = "RDP Wrapper Configuration"; + ClientSize = new Size(540, 383); + FormBorderStyle = FormBorderStyle.FixedSingle; + MaximizeBox = false; + StartPosition = FormStartPosition.CenterScreen; + Font = new Font("Segoe UI", 9f); + + // ── General GroupBox ────────────────────────────────────────────────── + gbGeneral.Text = "General"; + gbGeneral.Location = new Point(8, 8); + gbGeneral.Size = new Size(260, 175); + + cbAllowTSConnections.Text = "Allow Remote Desktop connections"; + cbAllowTSConnections.Location = new Point(10, 22); + cbAllowTSConnections.AutoSize = true; + + cbSingleSessionPerUser.Text = "Single session per user"; + cbSingleSessionPerUser.Location = new Point(10, 46); + cbSingleSessionPerUser.AutoSize = true; + + cbHideUsers.Text = "Hide users on logon screen"; + cbHideUsers.Location = new Point(10, 70); + cbHideUsers.AutoSize = true; + + cbCustomPrg.Text = "Custom program support (HonorLegacySettings)"; + cbCustomPrg.Location = new Point(10, 94); + cbCustomPrg.AutoSize = true; + + lRDPPort.Text = "RDP Port:"; + lRDPPort.Location = new Point(10, 124); + lRDPPort.AutoSize = true; + + seRDPPort.Location = new Point(80, 121); + seRDPPort.Minimum = 1; + seRDPPort.Maximum = 65535; + seRDPPort.Value = 3389; + seRDPPort.Width = 70; + + gbGeneral.Controls.AddRange(new Control[] + { + cbAllowTSConnections, cbSingleSessionPerUser, cbHideUsers, + cbCustomPrg, lRDPPort, seRDPPort + }); + + // ── NLA GroupBox ────────────────────────────────────────────────────── + gbNLA.Text = "Network Level Authentication"; + gbNLA.Location = new Point(276, 8); + gbNLA.Size = new Size(254, 88); + + rbNLA0.Text = "No NLA"; + rbNLA0.Location = new Point(10, 20); + rbNLA0.AutoSize = true; + + rbNLA1.Text = "Negotiate (server-side NLA)"; + rbNLA1.Location = new Point(10, 42); + rbNLA1.AutoSize = true; + + rbNLA2.Text = "Require NLA (client + server)"; + rbNLA2.Location = new Point(10, 64); + rbNLA2.AutoSize = true; + + gbNLA.Controls.AddRange(new Control[] { rbNLA0, rbNLA1, rbNLA2 }); + + // ── Shadow GroupBox ─────────────────────────────────────────────────── + gbShadow.Text = "Shadowing"; + gbShadow.Location = new Point(276, 100); + gbShadow.Size = new Size(254, 135); + + rbShadow0.Text = "Disabled"; + rbShadow0.Location = new Point(10, 20); rbShadow0.AutoSize = true; + rbShadow1.Text = "Full Access (with confirmation)"; + rbShadow1.Location = new Point(10, 42); rbShadow1.AutoSize = true; + rbShadow2.Text = "Full Access (no confirmation)"; + rbShadow2.Location = new Point(10, 62); rbShadow2.AutoSize = true; + rbShadow3.Text = "View Only (with confirmation)"; + rbShadow3.Location = new Point(10, 82); rbShadow3.AutoSize = true; + rbShadow4.Text = "View Only (no confirmation)"; + rbShadow4.Location = new Point(10, 102); rbShadow4.AutoSize = true; + + gbShadow.Controls.AddRange(new Control[] + { rbShadow0, rbShadow1, rbShadow2, rbShadow3, rbShadow4 }); + + // ── Diagnostics GroupBox ────────────────────────────────────────────── + gbDiag.Text = "Diagnostics"; + gbDiag.Location = new Point(8, 190); + gbDiag.Size = new Size(522, 140); + + AddDiagRow(gbDiag, "Service:", lService, lsService, new Point(10, 22)); + AddDiagRow(gbDiag, "Listener:", lListener, lsListener, new Point(10, 44)); + AddDiagRow(gbDiag, "Wrapper:", lWrapper, lsWrapper, new Point(10, 66)); + AddDiagRow(gbDiag, "TS version:", lTSVer, lsTSVer, new Point(10, 88)); + AddDiagRow(gbDiag, "Wrapper version:", lWrapVer, lsWrapVer, new Point(10, 110)); + + lsSuppVer.Location = new Point(280, 88); + lsSuppVer.AutoSize = true; + lsSuppVer.Visible = false; + gbDiag.Controls.Add(lsSuppVer); + + // ── Buttons ─────────────────────────────────────────────────────────── + bLicense.Text = "License"; + bLicense.Size = new Size(80, 26); + bLicense.Location = new Point(8, 345); + + bApply.Text = "Apply"; + bApply.Enabled = false; + bApply.Size = new Size(80, 26); + bApply.Location = new Point(276, 345); + + bOK.Text = "OK"; + bOK.Size = new Size(80, 26); + bOK.Location = new Point(364, 345); + + bCancel.Text = "Cancel"; + bCancel.Size = new Size(80, 26); + bCancel.Location = new Point(452, 345); + + Controls.AddRange(new Control[] + { + gbGeneral, gbNLA, gbShadow, gbDiag, + bLicense, bApply, bOK, bCancel + }); + } + + private static void AddDiagRow(GroupBox parent, string labelText, + Label lbl, Label status, Point origin) + { + lbl.Text = labelText; + lbl.Location = new Point(origin.X, origin.Y); + lbl.AutoSize = true; + + status.Text = "..."; + status.Location = new Point(origin.X + 120, origin.Y); + status.AutoSize = true; + status.ForeColor = SystemColors.GrayText; + + parent.Controls.Add(lbl); + parent.Controls.Add(status); + } + + private void OnAnyChange(object? sender, EventArgs e) + { + if (_ready) bApply.Enabled = true; + } + + // ── ReadSettings (mirrors Delphi ReadSettings) ──────────────────────────── + + private void ReadSettings() + { + const string tsKey = @"SYSTEM\CurrentControlSet\Control\Terminal Server"; + const string rdpTcp = @"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"; + const string policies = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"; + + cbAllowTSConnections.Checked = !RegistryHelper.ReadBool(tsKey, "fDenyTSConnections", false); + cbSingleSessionPerUser.Checked = RegistryHelper.ReadBool(tsKey, "fSingleSessionPerUser", false); + cbCustomPrg.Checked = RegistryHelper.ReadBool(tsKey, "HonorLegacySettings", false); + + int port = RegistryHelper.ReadInt(rdpTcp, "PortNumber", 3389); + seRDPPort.Value = Math.Clamp(port, 1, 65535); + _oldPort = port; + + int secLayer = RegistryHelper.ReadInt(rdpTcp, "SecurityLayer", 0); + int userAuth = RegistryHelper.ReadInt(rdpTcp, "UserAuthentication", 0); + int shadow = RegistryHelper.ReadInt(rdpTcp, "Shadow", -1); + + _ = (secLayer, userAuth) switch + { + (0, 0) => rbNLA0.Checked = true, + (1, 0) => rbNLA1.Checked = true, + (2, 1) => rbNLA2.Checked = true, + _ => rbNLA0.Checked = true + }; + + SetShadowRadio(shadow); + + cbHideUsers.Checked = RegistryHelper.ReadBool(policies, "dontdisplaylastusername", false); + } + + private void SetShadowRadio(int idx) + { + RadioButton[] rbs = { rbShadow0, rbShadow1, rbShadow2, rbShadow3, rbShadow4 }; + if (idx >= 0 && idx < rbs.Length) + rbs[idx].Checked = true; + } + + private int GetShadowIndex() + { + RadioButton[] rbs = { rbShadow0, rbShadow1, rbShadow2, rbShadow3, rbShadow4 }; + for (int i = 0; i < rbs.Length; i++) + if (rbs[i].Checked) return i; + return -1; + } + + // ── WriteSettings (mirrors Delphi WriteSettings) ────────────────────────── + + private void WriteSettings() + { + const string tsKey = @"SYSTEM\CurrentControlSet\Control\Terminal Server"; + const string rdpTcp = @"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"; + const string policiesRdp = @"SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services"; + const string policies = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"; + + RegistryHelper.WriteBool(tsKey, "fDenyTSConnections", !cbAllowTSConnections.Checked); + RegistryHelper.WriteBool(tsKey, "fSingleSessionPerUser", cbSingleSessionPerUser.Checked); + RegistryHelper.WriteBool(tsKey, "HonorLegacySettings", cbCustomPrg.Checked); + + int newPort = (int)seRDPPort.Value; + RegistryHelper.WriteInt(rdpTcp, "PortNumber", newPort); + if (_oldPort != newPort) + { + _oldPort = newPort; + ProcessHelper.ExecWait( + $"netsh advfirewall firewall set rule name=\"Remote Desktop\" new localport={newPort}"); + } + + // NLA + (int sl, int ua) = (rbNLA0.Checked, rbNLA1.Checked, rbNLA2.Checked) switch + { + (true, _, _ ) => (0, 0), + (_, true, _ ) => (1, 0), + (_, _, true) => (2, 1), + _ => (-1, -1) + }; + if (sl >= 0) + { + RegistryHelper.WriteInt(rdpTcp, "SecurityLayer", sl); + RegistryHelper.WriteInt(rdpTcp, "UserAuthentication", ua); + } + + // Shadow + int shadowIdx = GetShadowIndex(); + if (shadowIdx >= 0) + { + RegistryHelper.WriteInt(rdpTcp, "Shadow", shadowIdx); + RegistryHelper.WriteInt(policiesRdp, "Shadow", shadowIdx); + } + + RegistryHelper.WriteBool(policies, "dontdisplaylastusername", cbHideUsers.Checked); + } + + // ── TimerTimer (mirrors Delphi TimerTimer) ──────────────────────────────── + + private void TimerTimer(object? sender, EventArgs e) + { + // ── Wrapper state ── + string wrapperPath = string.Empty; + int wrapState = IsWrapperInstalled(ref wrapperPath); + bool checkSupp = false; + string iniPath = string.Empty; + + switch (wrapState) + { + case -1: + SetStatus(lsWrapper, "Unknown", SystemColors.GrayText); + break; + case 0: + SetStatus(lsWrapper, "Not installed", SystemColors.GrayText); + break; + case 1: + SetStatus(lsWrapper, "Installed", Color.Green); + iniPath = Path.Combine( + Path.GetDirectoryName(ArchHelper.ExpandPath(wrapperPath))!, + "rdpwrap.ini"); + checkSupp = File.Exists(iniPath); + break; + case 2: + SetStatus(lsWrapper, "3rd-party", Color.Red); + break; + } + + // ── Service state ── + int svcState = GetTermSrvState(); + // dwCurrentState constants (mirrors NativeMethods SERVICE_* constants) + string svcText = svcState switch + { + 1 => "Stopped", + 2 => "Starting...", + 3 => "Stopping...", + 4 => "Running", + 5 => "Resuming...", + 6 => "Suspending...", + 7 => "Suspended", + _ => "Unknown" + }; + Color svcColor = svcState == 4 ? Color.Green // SERVICE_RUNNING + : svcState == 1 ? Color.Red // SERVICE_STOPPED + : SystemColors.GrayText; + SetStatus(lsService, svcText, svcColor); + + // ── Listener ── + bool listening = IsListenerWorking(); + SetStatus(lsListener, + listening ? "Listening" : "Not listening", + listening ? Color.Green : Color.Red); + + // ── Wrapper version ── + string wrapExp = ArchHelper.ExpandPath(wrapperPath); + var wrapVer = string.IsNullOrEmpty(wrapperPath) ? null + : FileVersionHelper.GetVersion(wrapExp); + if (wrapVer is null) + SetStatus(lsWrapVer, "N/A", SystemColors.GrayText); + else + SetStatus(lsWrapVer, wrapVer.ToString(), SystemColors.WindowText); + + // ── TS version ── + var tsVer = FileVersionHelper.GetVersionExpanded(@"%SystemRoot%\System32\termsrv.dll"); + if (tsVer is null) + { + SetStatus(lsTSVer, "N/A", SystemColors.GrayText); + lsSuppVer.Visible = false; + return; + } + + SetStatus(lsTSVer, tsVer.ToString(), SystemColors.WindowText); + lsSuppVer.Visible = checkSupp; + + if (checkSupp) + { + string iniContent = IniHelper.LoadText(iniPath); + int level = IniHelper.CheckSupportLevel(iniContent, tsVer); + (string suppText, Color suppColor) = level switch + { + 0 => ("[not supported]", Color.Red), + 1 => ("[supported partially]", Color.Olive), + _ => ("[fully supported]", Color.Green) + }; + lsSuppVer.Text = suppText; + lsSuppVer.ForeColor = suppColor; + } + } + + // ── Helper: IsWrapperInstalled ──────────────────────────────────────────── + + /// -1=error, 0=not installed, 1=installed, 2=3rd-party + private static int IsWrapperInstalled(ref string wrapperPath) + { + wrapperPath = string.Empty; + var host = RegistryHelper.ReadString( + @"SYSTEM\CurrentControlSet\Services\TermService", "ImagePath") ?? string.Empty; + + if (!host.Contains("svchost.exe", StringComparison.OrdinalIgnoreCase)) return 2; + + var svcDll = RegistryHelper.ReadString( + @"SYSTEM\CurrentControlSet\Services\TermService\Parameters", "ServiceDll") ?? string.Empty; + + if (svcDll.Length == 0) return -1; + + if (!svcDll.Contains("termsrv.dll", StringComparison.OrdinalIgnoreCase) && + !svcDll.Contains("rdpwrap.dll", StringComparison.OrdinalIgnoreCase)) + return 2; + + if (svcDll.Contains("rdpwrap.dll", StringComparison.OrdinalIgnoreCase)) + { + wrapperPath = svcDll; + return 1; + } + return 0; + } + + // ── Helper: GetTermSrvState (via SCM) ───────────────────────────────────── + + private static int GetTermSrvState() + => ServiceHelper.GetCurrentState("TermService"); + + // ── Helper: IsListenerWorking (via WinStationEnumerateW) ────────────────── + + private static bool IsListenerWorking() + { + if (!NativeMethods.WinStationEnumerate(IntPtr.Zero, + out IntPtr pSessions, out uint count)) return false; + + bool found = false; + try + { + // Each entry is { DWORD SessionId; WCHAR[34] Name; DWORD State } + // = 4 + 68 + 4 = 76 bytes on x64 (with natural alignment the struct is 76 bytes) + const int stride = 76; // sizeof(WTS_SESSION_INFOW) — matches Delphi packed array + for (uint i = 0; i < count; i++) + { + IntPtr entry = pSessions + (int)(i * stride); + // Name is at offset 4, WCHAR[34] + string name = Marshal.PtrToStringUni(entry + 4, 34).TrimEnd('\0'); + if (name.Equals("RDP-Tcp", StringComparison.Ordinal)) + { + found = true; + break; + } + } + } + finally + { + NativeMethods.WinStationFreeMemory(pSessions); + } + + return found; + } + + // ── Helper: SetStatus ───────────────────────────────────────────────────── + + private static void SetStatus(Label lbl, string text, Color color) + { + lbl.Text = text; + lbl.ForeColor = color; + } + + // ── OnFormClosing — unsaved-changes guard ───────────────────────────────── + + private void OnFormClosing(object? sender, FormClosingEventArgs e) + { + if (bApply.Enabled) + { + var result = MessageBox.Show( + "Settings are not saved. Do you want to exit?", + "Warning", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + e.Cancel = result != DialogResult.Yes; + } + } + + // ── License button ──────────────────────────────────────────────────────── + + private void OnLicenseClick(object? sender, EventArgs e) + { + var text = ResourceHelper.ReadText( + "RDPConf.Resources.license.txt", + System.Reflection.Assembly.GetExecutingAssembly()); + text ??= ResourceHelper.ReadText("RDPWInst.Resources.license.txt") ?? "(license not found)"; + + using var dlg = new LicenseForm(text); + if (dlg.ShowDialog(this) != DialogResult.OK) + Application.Exit(); + } +} diff --git a/src-csharp/RDPConf/Program.cs b/src-csharp/RDPConf/Program.cs new file mode 100644 index 0000000..9270d84 --- /dev/null +++ b/src-csharp/RDPConf/Program.cs @@ -0,0 +1,15 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// RDPConf — WinForms configuration GUI entry point. + +namespace RDPConf; + +internal static class Program +{ + [STAThread] + internal static void Main() + { + ApplicationConfiguration.Initialize(); + Application.Run(new MainForm()); + } +} diff --git a/src-csharp/RDPConf/RDPConf.csproj b/src-csharp/RDPConf/RDPConf.csproj new file mode 100644 index 0000000..96725c9 --- /dev/null +++ b/src-csharp/RDPConf/RDPConf.csproj @@ -0,0 +1,24 @@ + + + WinExe + true + RDPConf + RDPConf + app.manifest + app.ico + WinForms configuration GUI for RDP Wrapper — manage concurrent session limits, RDP port, and security settings. + + + + + + + + + + + + + + + diff --git a/src-csharp/RDPConf/app.ico b/src-csharp/RDPConf/app.ico new file mode 100644 index 0000000..b083a31 Binary files /dev/null and b/src-csharp/RDPConf/app.ico differ diff --git a/src-csharp/RDPConf/app.manifest b/src-csharp/RDPConf/app.manifest new file mode 100644 index 0000000..a24b3eb --- /dev/null +++ b/src-csharp/RDPConf/app.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src-csharp/RDPConf/packages.lock.json b/src-csharp/RDPConf/packages.lock.json new file mode 100644 index 0000000..59ebcea --- /dev/null +++ b/src-csharp/RDPConf/packages.lock.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "dependencies": { + "net10.0-windows7.0": { + "rdpwrap": { + "type": "Project" + } + } + } +} \ No newline at end of file diff --git a/src-csharp/RDPOffsetFinder b/src-csharp/RDPOffsetFinder new file mode 160000 index 0000000..68da37a --- /dev/null +++ b/src-csharp/RDPOffsetFinder @@ -0,0 +1 @@ +Subproject commit 68da37acab6593c329776644944f55695a131731 diff --git a/src-csharp/RDPWInst/InstallerEngine.cs b/src-csharp/RDPWInst/InstallerEngine.cs new file mode 100644 index 0000000..d22b93d --- /dev/null +++ b/src-csharp/RDPWInst/InstallerEngine.cs @@ -0,0 +1,744 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// InstallerEngine — translates every procedure in RDPWInst.dpr to C#. + +using System.Reflection; +using RDPWrap.Common; + +namespace RDPWInst; + +/// +/// Orchestrates install / uninstall / update / restart of the RDP Wrapper. +/// All public methods return an exit code (0 = success). +/// +internal sealed class InstallerEngine +{ + // ── State (mirrors Delphi globals) ──────────────────────────────────────── + + private bool _installed; + private bool _online; + private string _wrapPath = string.Empty; + private string _termServicePath = string.Empty; + private string _termSrvVerTxt = string.Empty; + private uint _termServicePid; + private string[] _shareServices = Array.Empty(); + + private const string TermService = "TermService"; + + // Latest release download base URL + private const string ReleaseBaseUrl = + "https://github.com/sjackson0109/rdpwrap/releases/latest/download/"; + + // ── Public entry points ─────────────────────────────────────────────────── + + /// + /// Install the wrapper. Mirrors the -i branch in RDPWInst.dpr. + /// + public int Install(bool toSystem32, bool online, bool force = false) + { + if (_installed) + { + if (!force) + { + Console.WriteLine("[*] RDP Wrapper Library is already installed."); + return unchecked((int)NativeMethods.ERROR_ACCESS_DENIED); + } + + Console.WriteLine("[*] Existing installation detected -- uninstalling first (force mode)..."); + int urc = Uninstall(keepSettings: true); + if (urc != 0) + { + Console.Error.WriteLine($"[-] Force-uninstall failed (code {urc}) -- aborting install."); + return urc; + } + // Refresh state: after a successful uninstall _installed should now be false. + CheckInstall(); + } + + Console.WriteLine("[*] Notice to user:"); + Console.WriteLine(" - By using all or any portion of this software, you are agreeing"); + Console.WriteLine(" to be bound by all the terms and conditions of the license agreement."); + Console.WriteLine(" - To read the license agreement, run the installer with -l parameter."); + Console.WriteLine(" - If you do not agree to any terms of the license agreement,"); + Console.WriteLine(" do not use the software."); + Console.WriteLine("[*] Installing..."); + + _wrapPath = toSystem32 + ? @"%SystemRoot%\system32\rdpwrap.dll" + : @"%ProgramFiles%\RDP Wrapper\rdpwrap.dll"; + + if (ArchHelper.Is64Bit) ArchHelper.DisableWow64Redirection(); + + CheckTermsrvVersion(); + CheckTermsrvProcess(); + + Console.WriteLine("[*] Extracting files..."); + _online = online; + ExtractFiles(); + + Console.WriteLine("[*] Checking INI coverage for installed termsrv.dll version..."); + TryAutoGenerateOffsets(); + + Console.WriteLine("[*] Configuring service library..."); + SetWrapperDll(); + + Console.WriteLine("[*] Checking dependencies..."); + CheckTermsrvDependencies(); + + Console.WriteLine("[*] Terminating service..."); + SecurityHelper.AddPrivilege(NativeMethods.SE_DEBUG_NAME); + ProcessHelper.KillProcess(_termServicePid); + Thread.Sleep(1000); + + RestartSharedServices(); + Thread.Sleep(500); + ServiceHelper.StartService(TermService); + Thread.Sleep(500); + + Console.WriteLine("[*] Configuring registry..."); + TSConfigRegistry(enable: true); + Console.WriteLine("[*] Configuring firewall..."); + TSConfigFirewall(enable: true); + + Console.WriteLine("[+] Successfully installed."); + + if (ArchHelper.Is64Bit) ArchHelper.RevertWow64Redirection(); + return 0; + } + + /// + /// Uninstall the wrapper. Mirrors the -u branch. + /// + public int Uninstall(bool keepSettings) + { + if (!_installed) + { + Console.WriteLine("[*] RDP Wrapper Library is not installed."); + return unchecked((int)NativeMethods.ERROR_ACCESS_DENIED); + } + + Console.WriteLine("[*] Uninstalling..."); + if (ArchHelper.Is64Bit) ArchHelper.DisableWow64Redirection(); + + CheckTermsrvProcess(); + + Console.WriteLine("[*] Resetting service library..."); + ResetServiceDll(); + + Console.WriteLine("[*] Terminating service..."); + SecurityHelper.AddPrivilege(NativeMethods.SE_DEBUG_NAME); + ProcessHelper.KillProcess(_termServicePid); + Thread.Sleep(1000); + + Console.WriteLine("[*] Removing files..."); + DeleteFiles(); + + RestartSharedServices(); + Thread.Sleep(500); + ServiceHelper.StartService(TermService); + Thread.Sleep(500); + + if (!keepSettings) + { + Console.WriteLine("[*] Configuring registry..."); + TSConfigRegistry(enable: false); + Console.WriteLine("[*] Configuring firewall..."); + TSConfigFirewall(enable: false); + } + + if (ArchHelper.Is64Bit) ArchHelper.RevertWow64Redirection(); + Console.WriteLine("[+] Successfully uninstalled."); + return 0; + } + + /// + /// Download the latest rdpwrap.ini. Mirrors the -w / CheckUpdate branch. + /// + public int Update() + { + if (!_installed) + { + Console.WriteLine("[*] RDP Wrapper Library is not installed."); + return unchecked((int)NativeMethods.ERROR_ACCESS_DENIED); + } + + Console.WriteLine("[*] Checking for updates..."); + return CheckUpdate(); + } + + /// + /// Force-restart Terminal Services. Mirrors the -r branch. + /// + public int Restart() + { + Console.WriteLine("[*] Restarting..."); + CheckTermsrvProcess(); + + Console.WriteLine("[*] Terminating service..."); + SecurityHelper.AddPrivilege(NativeMethods.SE_DEBUG_NAME); + ProcessHelper.KillProcess(_termServicePid); + Thread.Sleep(1000); + + RestartSharedServices(); + Thread.Sleep(500); + ServiceHelper.StartService(TermService); + + Console.WriteLine("[+] Done."); + return 0; + } + + // ── CheckInstall ────────────────────────────────────────────────────────── + + /// + /// Validates the TermService registry image path and sets + /// and . + /// Mirrors the Delphi CheckInstall procedure. + /// + public void CheckInstall() + { + const string svcKey = @"SYSTEM\CurrentControlSet\Services\TermService"; + const string paramsKey = @"SYSTEM\CurrentControlSet\Services\TermService\Parameters"; + + var imagePath = RegistryHelper.ReadString(svcKey, "ImagePath") ?? string.Empty; + if (!imagePath.Contains("svchost.exe", StringComparison.OrdinalIgnoreCase) && + !imagePath.Contains("svchost -k", StringComparison.OrdinalIgnoreCase)) + { + Console.Error.WriteLine("[-] TermService is hosted in a custom application (BeTwin, etc.) - unsupported."); + Console.Error.WriteLine($"[*] ImagePath: \"{imagePath}\"."); + Environment.Exit(unchecked((int)NativeMethods.ERROR_NOT_SUPPORTED)); + } + + var serviceDll = RegistryHelper.ReadString(paramsKey, "ServiceDll") ?? string.Empty; + if (!serviceDll.Contains("termsrv.dll", StringComparison.OrdinalIgnoreCase) && + !serviceDll.Contains("rdpwrap.dll", StringComparison.OrdinalIgnoreCase)) + { + Console.Error.WriteLine("[-] Another third-party TermService library is installed."); + Console.Error.WriteLine($"[*] ServiceDll: \"{serviceDll}\"."); + Environment.Exit(unchecked((int)NativeMethods.ERROR_NOT_SUPPORTED)); + } + + _termServicePath = serviceDll; + _installed = serviceDll.Contains("rdpwrap.dll", StringComparison.OrdinalIgnoreCase); + } + + // ── CheckTermsrvProcess ──────────────────────────────────────────────────── + + /// + /// Finds the TermService process ID, auto-starts the service if needed, + /// and collects co-hosted service names. Mirrors CheckTermsrvProcess. + /// + private void CheckTermsrvProcess() + { + bool started = false; + retry: + var services = ServiceHelper.EnumServiceProcesses(); + var ts = services.FirstOrDefault(s => + s.ServiceName.Equals(TermService, StringComparison.OrdinalIgnoreCase)); + + if (ts is null) + { + Console.Error.WriteLine($"[-] {TermService} not found."); + Environment.Exit(unchecked((int)NativeMethods.ERROR_SERVICE_DOES_NOT_EXIST)); + return; + } + + if (ts.ProcessId == 0) + { + if (started) + { + Console.Error.WriteLine("[-] Failed to set up TermService. Unknown error."); + Environment.Exit(unchecked((int)NativeMethods.ERROR_SERVICE_NOT_ACTIVE)); + return; + } + ServiceHelper.SetStartType(TermService, NativeMethods.SERVICE_AUTO_START); + ServiceHelper.StartService(TermService); + started = true; + goto retry; + } + + _termServicePid = ts.ProcessId; + Console.WriteLine($"[+] TermService found (pid {_termServicePid})."); + + _shareServices = services + .Where(s => s.ProcessId == _termServicePid && + !s.ServiceName.Equals(TermService, StringComparison.OrdinalIgnoreCase)) + .Select(s => s.ServiceName) + .ToArray(); + + if (_shareServices.Length > 0) + Console.WriteLine($"[*] Shared services found: {string.Join(", ", _shareServices)}"); + else + Console.WriteLine("[*] No shared services found."); + } + + // ── CheckTermsrvDependencies ─────────────────────────────────────────────── + + /// + /// Ensures CertPropSvc and SessionEnv are not disabled. + /// Mirrors the Delphi CheckTermsrvDependencies procedure. + /// + private static void CheckTermsrvDependencies() + { + foreach (var svc in new[] { "CertPropSvc", "SessionEnv" }) + { + if (ServiceHelper.GetStartType(svc) == (int)NativeMethods.SERVICE_DISABLED) + ServiceHelper.SetStartType(svc, NativeMethods.SERVICE_DEMAND_START); + } + } + + // ── CheckTermsrvVersion ──────────────────────────────────────────────────── + + /// + /// Reads the termsrv.dll version and classifies support level. + /// Mirrors the Delphi CheckTermsrvVersion procedure. + /// + private void CheckTermsrvVersion() + { + var fv = FileVersionHelper.GetVersionExpanded(_termServicePath); + if (fv is null) + { + Console.Error.WriteLine("[-] Could not read termsrv.dll version."); + return; + } + + _termSrvVerTxt = fv.ToString(); + Console.WriteLine($"[*] Terminal Services version: {_termSrvVerTxt}"); + + // Unsupported legacy versions + if (fv.Major == 5) + { + var label = (ArchHelper.Arch == 32) ? "x86" : "x64"; + Console.WriteLine($"[!] Windows XP / Server 2003 ({label}) is not supported."); + return; + } + + // Load the built-in INI to check support level + var builtInIni = ResourceHelper.ReadText( + "RDPWInst.Resources.rdpwrap.ini", + Assembly.GetExecutingAssembly()) ?? string.Empty; + + int level = IniHelper.CheckSupportLevel(builtInIni, fv); + + switch (level) + { + case 0: + Console.WriteLine("[-] This version of Terminal Services is not supported."); + Console.WriteLine("Try running \"update.bat\" or \"RDPWInst -w\" to download latest INI file."); + break; + case 1: + Console.WriteLine("[!] This version of Terminal Services is supported partially."); + Console.WriteLine("It means you may have some limitations such as only 2 concurrent sessions."); + Console.WriteLine("Try running \"update.bat\" or \"RDPWInst -w\" to download latest INI file."); + break; + case 2: + Console.WriteLine("[+] This version of Terminal Services is fully supported."); + break; + } + } + + // ── TSConfigRegistry ────────────────────────────────────────────────────── + + /// + /// Writes (or clears) the TS-enable registry values. + /// Mirrors the Delphi TSConfigRegistry procedure. + /// + private static void TSConfigRegistry(bool enable) + { + const string tsKey = @"SYSTEM\CurrentControlSet\Control\Terminal Server"; + const string licKey = @"SYSTEM\CurrentControlSet\Control\Terminal Server\Licensing Core"; + const string winlogon = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"; + const string addInsBase = @"SYSTEM\CurrentControlSet\Control\Terminal Server\AddIns"; + + RegistryHelper.WriteBool(tsKey, "fDenyTSConnections", !enable); + + if (enable) + { + RegistryHelper.WriteBool(licKey, "EnableConcurrentSessions", true); + RegistryHelper.WriteBool(winlogon, "AllowMultipleTSSessions", true); + RegistryHelper.WriteBool(tsKey, "AllowRemoteRPC", true); + RegistryHelper.WriteBool(tsKey, "EnableLinkedConnections", true); + + // AddIns sub-keys (only create if the parent key is absent) + if (Microsoft.Win32.Registry.LocalMachine.OpenSubKey(addInsBase) is null) + { + RegistryHelper.WriteString(addInsBase + @"\Clip Redirector", "Name", "RDPClip"); + RegistryHelper.WriteInt (addInsBase + @"\Clip Redirector", "Type", 3); + RegistryHelper.WriteString(addInsBase + @"\DND Redirector", "Name", "RDPDND"); + RegistryHelper.WriteInt (addInsBase + @"\DND Redirector", "Type", 3); + RegistryHelper.WriteInt (addInsBase + @"\Dynamic VC", "Type", -1); + } + } + } + + // ── TSConfigFirewall ────────────────────────────────────────────────────── + + private static void TSConfigFirewall(bool enable) + { + if (enable) + { + ProcessHelper.ExecWait( + "netsh advfirewall firewall add rule name=\"Remote Desktop\" " + + "dir=in protocol=tcp localport=3389 profile=any action=allow"); + ProcessHelper.ExecWait( + "netsh advfirewall firewall add rule name=\"Remote Desktop\" " + + "dir=in protocol=udp localport=3389 profile=any action=allow"); + } + else + { + ProcessHelper.ExecWait( + "netsh advfirewall firewall delete rule name=\"Remote Desktop\""); + } + } + + // ── ExtractFiles ────────────────────────────────────────────────────────── + + /// + /// Creates the install directory, sets ACLs, downloads or extracts the + /// INI file, and extracts the correct rdpwrap DLL + optional helpers. + /// Mirrors the Delphi ExtractFiles procedure. + /// + private void ExtractFiles() + { + var asm = Assembly.GetExecutingAssembly(); + var fullPath = ArchHelper.ExpandPath(_wrapPath); + var dir = Path.GetDirectoryName(fullPath)!; + + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + Console.WriteLine($"[+] Folder created: {dir}"); + SecurityHelper.GrantSidFullAccess(dir, "S-1-5-18"); // Local System + SecurityHelper.GrantSidFullAccess(dir, "S-1-5-6"); // Service group + } + + // ── INI file ── + var iniPath = Path.Combine(dir, "rdpwrap.ini"); + if (_online) + { + Console.WriteLine("[*] Downloading latest INI file..."); + var content = HttpHelper.DownloadString(ReleaseBaseUrl + "rdpwrap.ini"); + if (content is not null) + { + File.WriteAllText(iniPath, content, System.Text.Encoding.UTF8); + Console.WriteLine($"[+] Latest INI file -> {iniPath}"); + } + else + { + Console.WriteLine("[-] Failed to get online INI file, using built-in."); + _online = false; + } + } + + if (!_online) + { + // Try a local rdpwrap.ini beside the installer first + var localIni = Path.Combine( + Path.GetDirectoryName(Environment.ProcessPath ?? string.Empty) ?? ".", + "rdpwrap.ini"); + + if (File.Exists(localIni)) + { + File.Copy(localIni, iniPath, overwrite: true); + Console.WriteLine($"[+] Current INI file -> {iniPath}"); + } + else + { + ResourceHelper.ExtractToDisk("RDPWInst.Resources.rdpwrap.ini", iniPath, asm); + } + } + + // ── Core DLL ── + var dllRes = ArchHelper.Is64Bit ? "RDPWInst.Resources.rdpw64.dll" + : "RDPWInst.Resources.rdpw32.dll"; + ResourceHelper.ExtractToDisk(dllRes, fullPath, asm); + + // ── Optional helpers (Vista / Win7 clipboard redirect, Win10 RFX codec) ── + ExtractOptionalHelper(asm, dir); + } + + private void ExtractOptionalHelper(Assembly asm, string dir) + { + var fv = FileVersionHelper.GetVersionExpanded(_termServicePath); + if (fv is null) return; + + var arch = ArchHelper.Is64Bit ? "64" : "32"; + + // rdpclip: Vista 6.0 and Win7 6.1 + string? clipRes = (fv.Major, fv.Minor) switch + { + (6, 0) => $"RDPWInst.Resources.rdpclip60{arch}.exe", + (6, 1) => $"RDPWInst.Resources.rdpclip61{arch}.exe", + _ => null + }; + if (clipRes is not null) + { + var dest = ArchHelper.ExpandPath(@"%SystemRoot%\System32\rdpclip.exe"); + if (!File.Exists(dest)) + ResourceHelper.ExtractToDisk(clipRes, dest, asm); + } + + // rfxvmt.dll: Windows 10 (6.10.x maps to 10.0 in NT versioning) + if (fv.Major == 10 && fv.Minor == 0) + { + var rfxRes = $"RDPWInst.Resources.rfxvmt{arch}.dll"; + var rfxDest = ArchHelper.ExpandPath(@"%SystemRoot%\System32\rfxvmt.dll"); + if (!File.Exists(rfxDest)) + ResourceHelper.ExtractToDisk(rfxRes, rfxDest, asm); + } + } + + // ── SetWrapperDll / ResetServiceDll ────────────────────────────────────── + + private void SetWrapperDll() + { + const string key = @"SYSTEM\CurrentControlSet\Services\TermService\Parameters"; + RegistryHelper.WriteExpandString(key, "ServiceDll", _wrapPath); + + // Vista 6.0 workaround — reg.exe write to bypass WOW64 quirk + var fv = FileVersionHelper.GetVersionExpanded(_termServicePath); + if (fv is { Major: 6, Minor: 0 } && ArchHelper.Is64Bit) + { + ProcessHelper.ExecWait( + $"\"{ArchHelper.ExpandPath("%SystemRoot%")}\\system32\\reg.exe\" " + + $"add HKLM\\SYSTEM\\CurrentControlSet\\Services\\TermService\\Parameters " + + $"/v ServiceDll /t REG_EXPAND_SZ /d \"{_wrapPath}\" /f"); + } + } + + private static void ResetServiceDll() + { + const string key = @"SYSTEM\CurrentControlSet\Services\TermService\Parameters"; + RegistryHelper.WriteExpandString(key, "ServiceDll", + @"%SystemRoot%\System32\termsrv.dll"); + } + + // ── DeleteFiles ─────────────────────────────────────────────────────────── + + private void DeleteFiles() + { + var fullPath = ArchHelper.ExpandPath(_termServicePath); + var dir = Path.GetDirectoryName(fullPath)!; + var iniPath = Path.Combine(dir, "rdpwrap.ini"); + + TryDelete(iniPath); + TryDelete(fullPath); + TryRemoveDir(dir); + } + + private static void TryDelete(string path) + { + try + { + File.Delete(path); + Console.WriteLine($"[+] Removed file: {path}"); + } + catch (Exception ex) + { + Console.Error.WriteLine($"[-] DeleteFile error: {ex.Message}"); + } + } + + private static void TryRemoveDir(string dir) + { + try + { + Directory.Delete(dir); + Console.WriteLine($"[+] Removed folder: {dir}"); + } + catch (Exception ex) + { + Console.Error.WriteLine($"[-] RemoveDirectory error: {ex.Message}"); + } + } + + // ── TryAutoGenerateOffsets ──────────────────────────────────────────────── + + /// + /// If the running termsrv.dll version is absent from rdpwrap.ini, downloads + /// RDPWrapOffsetFinder + Zydis from the release assets and runs the finder + /// to append generated offsets. Mirrors the Delphi TryAutoGenerateOffsets. + /// + private void TryAutoGenerateOffsets() + { + if (string.IsNullOrEmpty(_termSrvVerTxt)) return; + + var fullPath = ArchHelper.ExpandPath(_wrapPath); + var iniPath = Path.Combine(Path.GetDirectoryName(fullPath)!, "rdpwrap.ini"); + + if (IniHelper.HasSection(iniPath, _termSrvVerTxt)) + { + Console.WriteLine($"[+] Version {_termSrvVerTxt} is covered in INI."); + return; + } + + Console.WriteLine($"[!] Version {_termSrvVerTxt} not found in INI."); + Console.WriteLine("[*] Attempting automatic offset generation via RDPWrapOffsetFinder..."); + + var archSuffix = ArchHelper.Is64Bit ? "_x64" : "_x86"; + var tempDir = Path.Combine(Path.GetTempPath(), "rdpwrapoffset"); + + try { Directory.CreateDirectory(tempDir); } + catch + { + Console.Error.WriteLine("[-] Could not create temp directory. Skipping auto-generation."); + return; + } + + var exePath = Path.Combine(tempDir, "RDPWrapOffsetFinder.exe"); + var dllPath = Path.Combine(tempDir, "Zydis.dll"); + + Console.WriteLine($"[*] Downloading RDPWrapOffsetFinder{archSuffix}.exe ..."); + if (!HttpHelper.DownloadFile(ReleaseBaseUrl + $"RDPWrapOffsetFinder{archSuffix}.exe", exePath)) + { + Console.Error.WriteLine("[-] Download failed. The release asset may not yet be published."); + Console.Error.WriteLine("[!] Run the publish-ini workflow on the sjackson0109/rdpwrap repository,"); + Console.Error.WriteLine("[!] then re-run this installer to enable auto-generation."); + return; + } + + Console.WriteLine($"[*] Downloading Zydis{archSuffix}.dll ..."); + if (!HttpHelper.DownloadFile(ReleaseBaseUrl + $"Zydis{archSuffix}.dll", dllPath)) + { + Console.Error.WriteLine("[-] Zydis download failed. Skipping auto-generation."); + File.Delete(exePath); + return; + } + + Console.WriteLine($"[*] Running offset finder for termsrv.dll {_termSrvVerTxt} ..."); + // Run via cmd.exe so that >> redirect to the INI file functions correctly + var sysCmd = ArchHelper.ExpandPath(@"%SystemRoot%\System32\cmd.exe"); + ProcessHelper.ExecWait($"\"{sysCmd}\" /c \"\"{exePath}\" >> \"{iniPath}\"\""); + + if (IniHelper.HasSection(iniPath, _termSrvVerTxt)) + Console.WriteLine($"[+] Offsets generated successfully for version {_termSrvVerTxt}"); + else + Console.WriteLine($"[!] Offset finder ran but [{_termSrvVerTxt}] was not added. " + + "Session may be limited or unstable for this build."); + + // Clean up temporary tool files + try + { + File.Delete(exePath); + File.Delete(dllPath); + Directory.Delete(tempDir); + } + catch { /* best-effort */ } + } + + // ── CheckUpdate (GitINIFile path) ───────────────────────────────────────── + + private int CheckUpdate() + { + var fullPath = ArchHelper.ExpandPath(_termServicePath); + var iniPath = Path.Combine(Path.GetDirectoryName(fullPath)!, "rdpwrap.ini"); + + if (!TryGetIniDate(iniPath, null, out int oldDate)) + return unchecked((int)NativeMethods.ERROR_ACCESS_DENIED); + + Console.WriteLine($"[*] Current update date: {FormatDate(oldDate)}"); + + var latest = HttpHelper.DownloadString(ReleaseBaseUrl + "rdpwrap.ini"); + if (latest is null) + { + Console.Error.WriteLine("[-] Failed to download latest INI from GitHub."); + return unchecked((int)NativeMethods.ERROR_ACCESS_DENIED); + } + + if (!TryGetIniDate(null, latest, out int newDate)) + return unchecked((int)NativeMethods.ERROR_ACCESS_DENIED); + + Console.WriteLine($"[*] Latest update date: {FormatDate(newDate)}"); + + if (newDate == oldDate) + { + Console.WriteLine("[*] Everything is up to date."); + return 0; + } + + if (newDate > oldDate) + { + Console.WriteLine("[+] New update is available, updating..."); + CheckTermsrvProcess(); + + Console.WriteLine("[*] Terminating service..."); + SecurityHelper.AddPrivilege(NativeMethods.SE_DEBUG_NAME); + ProcessHelper.KillProcess(_termServicePid); + Thread.Sleep(1000); + + RestartSharedServices(); + Thread.Sleep(500); + + File.WriteAllText(iniPath, latest, System.Text.Encoding.UTF8); + Console.WriteLine($"[+] INI file updated: {iniPath}"); + + // Recompute version for offset generation + var fv = FileVersionHelper.GetVersionExpanded(_termServicePath); + if (fv is not null) _termSrvVerTxt = fv.ToString(); + + Console.WriteLine("[*] Checking INI coverage for installed termsrv.dll version..."); + TryAutoGenerateOffsets(); + + ServiceHelper.StartService(TermService); + Console.WriteLine("[+] Update completed."); + } + else + { + Console.WriteLine("[*] Your INI file is newer than public file. Are you a developer? :)"); + } + + return 0; + } + + // ── Helpers ─────────────────────────────────────────────────────────────── + + private void RestartSharedServices() + { + foreach (var svc in _shareServices) + ServiceHelper.StartService(svc); + } + + /// + /// Parses the Updated=YYYYMMDD line from an INI file or string. + /// Mirrors the Delphi CheckINIDate function. + /// + private static bool TryGetIniDate(string? filePath, string? content, out int date) + { + date = 0; + IEnumerable lines; + + if (filePath is not null) + { + if (!File.Exists(filePath)) + { + Console.Error.WriteLine("[-] Failed to read INI file."); + return false; + } + lines = File.ReadLines(filePath); + } + else + { + lines = (content ?? string.Empty).Split('\n'); + } + + foreach (var line in lines) + { + var trimmed = line.TrimEnd('\r'); + if (!trimmed.StartsWith("Updated=", StringComparison.Ordinal)) continue; + + var raw = trimmed["Updated=".Length..].Replace("-", ""); + if (int.TryParse(raw, out date)) return true; + + Console.Error.WriteLine("[-] Wrong INI date format."); + return false; + } + + Console.Error.WriteLine("[-] Failed to check INI date (Updated= line not found)."); + return false; + } + + private static string FormatDate(int d) + { + int y = d / 10000, m = (d / 100) % 100, day = d % 100; + return $"{y}.{m:D2}.{day:D2}"; + } +} diff --git a/src-csharp/RDPWInst/Program.cs b/src-csharp/RDPWInst/Program.cs new file mode 100644 index 0000000..f6dc5cb --- /dev/null +++ b/src-csharp/RDPWInst/Program.cs @@ -0,0 +1,114 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +// +// RDPWInst — RDP Wrapper Library Installer + +using RDPWrap.Common; + +namespace RDPWInst; + +internal static class Program +{ + private static string Banner + { + get + { + var v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; + string version = v is null ? "unknown" : $"{v.Major}.{v.Minor}.{v.Build}"; + return + $"RDP Wrapper Library\r\n" + + $"Installer v{version} (C# edition)\r\n" + + "Copyright (C) Stas'M Corp. 2018\r\n" + + "Maintained by sjackson0109 2026\r\n"; + } + } + + private const string Usage = + "USAGE:\r\n" + + "RDPWInst.exe [-l|-i[-s][-o][-f]|-w|-u[-k]|-r]\r\n\r\n" + + "-l display the license agreement\r\n" + + "-i install wrapper to Program Files folder (default)\r\n" + + "-i -s install wrapper to System32 folder\r\n" + + "-i -o online install mode (loads latest INI file)\r\n" + + "-i -f force install: silently uninstall existing installation first\r\n" + + "-w get latest update for INI file\r\n" + + "-u uninstall wrapper\r\n" + + "-u -k uninstall wrapper and keep settings\r\n" + + "-r force restart Terminal Services\r\n"; + + internal static int Main(string[] args) + { + Console.OutputEncoding = System.Text.Encoding.UTF8; + Console.WriteLine(Banner); + + // Validate args + if (args.Length < 1 || + (args[0] != "-l" && + args[0] != "-i" && + args[0] != "-w" && + args[0] != "-u" && + args[0] != "-r")) + { + Console.WriteLine(Usage); + Pause(); + return 0; + } + + // -l print license + if (args[0] == "-l") + { + var license = ResourceHelper.ReadText("RDPWInst.Resources.license.txt", + System.Reflection.Assembly.GetExecutingAssembly()); + Console.WriteLine(license ?? "(license resource not found)"); + Pause(); + return 0; + } + + // Windows Vista / Server 2008 minimum check + if (Environment.OSVersion.Version < new Version(6, 0)) + { + Console.Error.WriteLine("[-] Unsupported Windows version:"); + Console.Error.WriteLine(" only >= 6.0 (Vista, Server 2008 and newer) are supported."); + Pause(); + return 1; + } + + if (!ArchHelper.IsSupported) + { + Console.Error.WriteLine("[-] Unsupported processor architecture."); + Pause(); + return 1; + } + + var engine = new InstallerEngine(); + engine.CheckInstall(); + + int rc = args[0] switch + { + "-i" => engine.Install( + toSystem32: args.Contains("-s"), + online: args.Contains("-o"), + force: args.Contains("-f")), + "-u" => engine.Uninstall(keepSettings: args.Contains("-k")), + "-w" => engine.Update(), + "-r" => engine.Restart(), + _ => 0 + }; + + Pause(); + return rc; + } + + /// + /// Waits for a keypress only when the process owns its console window + /// (i.e. was launched via double-click or UAC elevation rather than + /// piped/redirected from a script). + /// + private static void Pause() + { + if (!Console.IsInputRedirected && !Console.IsOutputRedirected) + { + Console.WriteLine("\nPress any key to exit..."); + Console.ReadKey(intercept: true); + } + } +} diff --git a/src-csharp/RDPWInst/RDPWInst.csproj b/src-csharp/RDPWInst/RDPWInst.csproj new file mode 100644 index 0000000..648a500 --- /dev/null +++ b/src-csharp/RDPWInst/RDPWInst.csproj @@ -0,0 +1,41 @@ + + + Exe + RDPWInst + RDPWInst + app.manifest + Command-line installer and manager for RDP Wrapper — installs rdpwrap.dll and configures the Terminal Services layer. + + + + + + + + + + + + + + + + + + + + diff --git a/src-csharp/RDPWInst/Resources/README.md b/src-csharp/RDPWInst/Resources/README.md new file mode 100644 index 0000000..556200b --- /dev/null +++ b/src-csharp/RDPWInst/Resources/README.md @@ -0,0 +1,31 @@ +# RDPWInst/Resources + +Place the compiled binary payloads here before building RDPWInst.exe. +These files are embedded as manifest resources at build time via `` entries in `RDPWInst.csproj` — if a file is absent the resource is simply omitted and the build still succeeds (online install mode is used as fallback). + +## CI-staged files (automatically copied by `build-and-release.yml`) + +| File | Source | Used when | +|---------------|--------------------------------------------------|-----------------------------| +| `rdpw32.dll` | Build output of `src-x86-x64-Fusix/` (Win32) | Always — 32-bit install | +| `rdpw64.dll` | Build output of `src-x86-x64-Fusix/` (x64) | Always — 64-bit install | +| `rdpwrap.ini` | `msi/rdpwrap.ini` from repo | Always — offline fallback | +| `license.txt` | Repo `LICENSE` (copied as plain text) | `RDPWInst -l` flag | + +## Optional legacy files (not in VCS, not staged by CI) + +| File | Purpose | Status / action required | +|-------------------|--------------------------------------------|--------------------------------------------------------------------------------------| +| `rdpclip6032.exe` | Updated rdpclip for Vista x86 | Not redistributable by this project — obtain from original stascorp release if needed | +| `rdpclip6064.exe` | Updated rdpclip for Vista x64 | Same as above | +| `rdpclip6132.exe` | Updated rdpclip for Win7 x86 | Same as above | +| `rdpclip6164.exe` | Updated rdpclip for Win7 x64 | Same as above | +| `rfxvmt32.dll` | RemoteFX codec for Win10 Home x86 | **Not redistributable** — must be extracted from a Windows 10 Home installation at `C:\Windows\System32\rfxvmt.dll`. See [#194](https://github.com/stascorp/rdpwrap/issues/194) for context. | +| `rfxvmt64.dll` | RemoteFX codec for Win10 Home x64 | Same as above | + +> **Decision note:** `rfxvmt.dll` is a Microsoft-owned component and cannot be legally bundled. +> `InstallerEngine.cs` handles the missing-rfxvmt case at runtime: if the file is absent from +> the embedded resources and absent from the install directory, a warning is printed and the +> user is directed to copy it manually. No CI step attempts to source or stage these files. + +All binary files in this folder are excluded from version control via `.gitignore`. diff --git a/src-csharp/RDPWInst/app.manifest b/src-csharp/RDPWInst/app.manifest new file mode 100644 index 0000000..4fcaaba --- /dev/null +++ b/src-csharp/RDPWInst/app.manifest @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src-csharp/RDPWInst/packages.lock.json b/src-csharp/RDPWInst/packages.lock.json new file mode 100644 index 0000000..59ebcea --- /dev/null +++ b/src-csharp/RDPWInst/packages.lock.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "dependencies": { + "net10.0-windows7.0": { + "rdpwrap": { + "type": "Project" + } + } + } +} \ No newline at end of file diff --git a/src-csharp/RDPWrap.sln b/src-csharp/RDPWrap.sln new file mode 100644 index 0000000..2a0b5fc --- /dev/null +++ b/src-csharp/RDPWrap.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35303.130 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RDPWrap", "RDPWrap\RDPWrap.csproj", "{A1B2C3D4-0001-4000-8000-000000000001}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RDPWInst", "RDPWInst\RDPWInst.csproj", "{A1B2C3D4-0001-4000-8000-000000000002}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RDPConf", "RDPConf\RDPConf.csproj", "{A1B2C3D4-0001-4000-8000-000000000003}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RDPCheck", "RDPCheck\RDPCheck.csproj", "{A1B2C3D4-0001-4000-8000-000000000004}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A1B2C3D4-0001-4000-8000-000000000001}.Debug|x64.ActiveCfg = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000001}.Debug|x64.Build.0 = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000001}.Debug|x86.ActiveCfg = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000001}.Debug|x86.Build.0 = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000001}.Release|x64.ActiveCfg = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000001}.Release|x64.Build.0 = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000001}.Release|x86.ActiveCfg = Release|x86 + {A1B2C3D4-0001-4000-8000-000000000001}.Release|x86.Build.0 = Release|x86 + {A1B2C3D4-0001-4000-8000-000000000002}.Debug|x64.ActiveCfg = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000002}.Debug|x64.Build.0 = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000002}.Debug|x86.ActiveCfg = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000002}.Debug|x86.Build.0 = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000002}.Release|x64.ActiveCfg = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000002}.Release|x64.Build.0 = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000002}.Release|x86.ActiveCfg = Release|x86 + {A1B2C3D4-0001-4000-8000-000000000002}.Release|x86.Build.0 = Release|x86 + {A1B2C3D4-0001-4000-8000-000000000003}.Debug|x64.ActiveCfg = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000003}.Debug|x64.Build.0 = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000003}.Debug|x86.ActiveCfg = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000003}.Debug|x86.Build.0 = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000003}.Release|x64.ActiveCfg = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000003}.Release|x64.Build.0 = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000003}.Release|x86.ActiveCfg = Release|x86 + {A1B2C3D4-0001-4000-8000-000000000003}.Release|x86.Build.0 = Release|x86 + {A1B2C3D4-0001-4000-8000-000000000004}.Debug|x64.ActiveCfg = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000004}.Debug|x64.Build.0 = Debug|x64 + {A1B2C3D4-0001-4000-8000-000000000004}.Debug|x86.ActiveCfg = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000004}.Debug|x86.Build.0 = Debug|x86 + {A1B2C3D4-0001-4000-8000-000000000004}.Release|x64.ActiveCfg = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000004}.Release|x64.Build.0 = Release|x64 + {A1B2C3D4-0001-4000-8000-000000000004}.Release|x86.ActiveCfg = Release|x86 + {A1B2C3D4-0001-4000-8000-000000000004}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src-csharp/RDPWrap/ArchHelper.cs b/src-csharp/RDPWrap/ArchHelper.cs new file mode 100644 index 0000000..f6a8971 --- /dev/null +++ b/src-csharp/RDPWrap/ArchHelper.cs @@ -0,0 +1,80 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +using System.Runtime.InteropServices; + +namespace RDPWrap.Common; + +/// +/// Architecture detection and WOW64 file-system redirection control. +/// Mirrors the Arch / DisableWowRedirection / RevertWowRedirection logic +/// from RDPWInst.dpr and RDPConf MainUnit.pas. +/// +public static class ArchHelper +{ + private static readonly Lazy _arch = new(DetectArch); + + /// Raw architecture byte: 32 or 64. 0 = unsupported. + public static byte Arch => _arch.Value; + + /// true when running on a 64-bit Windows installation. + public static bool Is64Bit => Arch == 64; + + /// + /// Returns true when the processor architecture is supported + /// (x86 or x64). Itanium and unknown architectures return false. + /// + public static bool IsSupported => Arch != 0; + + private static byte DetectArch() + { + NativeMethods.GetNativeSystemInfo(out var si); + return si.wProcessorArchitecture switch + { + NativeMethods.PROCESSOR_ARCHITECTURE_INTEL => 32, + NativeMethods.PROCESSOR_ARCHITECTURE_AMD64 => 64, + _ => 0 // Itanium or unknown — unsupported + }; + } + + // ── WOW64 filesystem redirection ───────────────────────────────────────── + + private static IntPtr _wow64OldValue = IntPtr.Zero; + + /// + /// Disables WOW64 filesystem redirection so that 32-bit processes can + /// reach the real %SystemRoot%\System32. Call only on 64-bit hosts. + /// Returns true on success. + /// + public static bool DisableWow64Redirection() + { + if (!Is64Bit) return false; + return NativeMethods.Wow64DisableWow64FsRedirection(out _wow64OldValue); + } + + /// + /// Reverts the WOW64 filesystem redirection state saved by the last call + /// to . + /// + public static bool RevertWow64Redirection() + { + if (!Is64Bit) return false; + return NativeMethods.Wow64RevertWow64FsRedirection(_wow64OldValue); + } + + // ── Environment path expansion ──────────────────────────────────────────── + + /// + /// Expands environment strings in , replacing + /// %ProgramFiles% with %ProgramW6432% on 64-bit hosts + /// to avoid redirection to the x86 Program Files folder. + /// + public static string ExpandPath(string path) + { + if (Is64Bit) + path = path.Replace("%ProgramFiles%", "%ProgramW6432%", + StringComparison.OrdinalIgnoreCase); + + var buf = new System.Text.StringBuilder(1024); + NativeMethods.ExpandEnvironmentStrings(path, buf, (uint)buf.Capacity); + return buf.ToString(); + } +} diff --git a/src-csharp/RDPWrap/FileVersionHelper.cs b/src-csharp/RDPWrap/FileVersionHelper.cs new file mode 100644 index 0000000..cb98d64 --- /dev/null +++ b/src-csharp/RDPWrap/FileVersionHelper.cs @@ -0,0 +1,64 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +using System.Diagnostics; + +namespace RDPWrap.Common; + +/// +/// File-version reading helper. Mirrors the GetFileVersion function used in +/// RDPWInst.dpr and RDPConf MainUnit.pas. +/// +public static class FileVersionHelper +{ + /// + /// Strongly-typed representation of a Windows file version. + /// + public record FileVersionInfo( + ushort Major, + ushort Minor, + ushort Release, + ushort Build, + bool IsDebug, + bool IsPrerelease, + bool IsPrivate, + bool IsSpecial) + { + /// e.g. "10.0.26100.3476" + public override string ToString() => $"{Major}.{Minor}.{Release}.{Build}"; + } + + /// + /// Returns the file version of , or null + /// if the file does not exist or has no version resource. + /// Uses the BCL which does + /// not require loading the DLL as executable — safe for locked DLLs. + /// + public static FileVersionInfo? GetVersion(string filePath) + { + if (!File.Exists(filePath)) return null; + + try + { + var fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(filePath); + return new FileVersionInfo( + (ushort)(fvi.FileMajorPart), + (ushort)(fvi.FileMinorPart), + (ushort)(fvi.FileBuildPart), + (ushort)(fvi.FilePrivatePart), + fvi.IsDebug, + fvi.IsPreRelease, + fvi.IsPrivateBuild, + fvi.IsSpecialBuild); + } + catch + { + return null; + } + } + + /// + /// Convenience overload: resolves the path via + /// before reading. + /// + public static FileVersionInfo? GetVersionExpanded(string pathWithEnvVars) + => GetVersion(ArchHelper.ExpandPath(pathWithEnvVars)); +} diff --git a/src-csharp/RDPWrap/HttpHelper.cs b/src-csharp/RDPWrap/HttpHelper.cs new file mode 100644 index 0000000..a95aa4a --- /dev/null +++ b/src-csharp/RDPWrap/HttpHelper.cs @@ -0,0 +1,80 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 + +namespace RDPWrap.Common; + +/// +/// HTTP download helpers that replace the WinInet-based GitINIFile / +/// DownloadFileToDisk procedures from RDPWInst.dpr. +/// Uses with a shared static instance. +/// +public static class HttpHelper +{ + // Single shared instance — HttpClient is designed to be reused. + private static readonly HttpClient _client = new(new HttpClientHandler + { + AllowAutoRedirect = true, + MaxAutomaticRedirections = 5, + }) + { + Timeout = TimeSpan.FromSeconds(60), + DefaultRequestHeaders = { { "User-Agent", "RDP-Wrapper-Updater/1.0" } } + }; + + /// + /// Downloads the text content at and returns it as + /// a string. Returns null on any failure. + /// Mirrors the Delphi GitINIFile function. + /// + public static async Task DownloadStringAsync(string url) + { + try + { + return await _client.GetStringAsync(url).ConfigureAwait(false); + } + catch (Exception ex) + { + Console.Error.WriteLine($"[-] HTTP download failed ({url}): {ex.Message}"); + return null; + } + } + + /// + /// Downloads the binary content at and saves it to + /// . Returns true when the file exists + /// and is non-empty after download. + /// Mirrors the Delphi DownloadFileToDisk function. + /// + public static async Task DownloadFileAsync(string url, string destPath) + { + try + { + using var response = await _client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead) + .ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var file = File.Create(destPath); + await stream.CopyToAsync(file).ConfigureAwait(false); + + return new FileInfo(destPath).Length > 0; + } + catch (Exception ex) + { + Console.Error.WriteLine($"[-] HTTP file download failed ({url}): {ex.Message}"); + return false; + } + } + + /// + /// Synchronous wrapper for — suitable + /// for the installer's purely-sequential flow. + /// + public static string? DownloadString(string url) + => DownloadStringAsync(url).GetAwaiter().GetResult(); + + /// + /// Synchronous wrapper for . + /// + public static bool DownloadFile(string url, string destPath) + => DownloadFileAsync(url, destPath).GetAwaiter().GetResult(); +} diff --git a/src-csharp/RDPWrap/IniHelper.cs b/src-csharp/RDPWrap/IniHelper.cs new file mode 100644 index 0000000..f6c0919 --- /dev/null +++ b/src-csharp/RDPWrap/IniHelper.cs @@ -0,0 +1,61 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 + +namespace RDPWrap.Common; + +/// +/// Lightweight INI-file helpers used to check whether a specific version +/// section exists in rdpwrap.ini. Mirrors the INIHasSection function and +/// CheckSupport version-lookup logic from RDPWInst.dpr and RDPConf MainUnit.pas. +/// +public static class IniHelper +{ + /// + /// Returns true when the INI file at + /// contains the section header []. + /// Mirrors the Delphi INIHasSection function. + /// + public static bool HasSection(string iniPath, string section) + { + if (!File.Exists(iniPath)) return false; + var needle = $"[{section}]"; + foreach (var line in File.ReadLines(iniPath)) + { + if (line.Contains(needle, StringComparison.Ordinal)) + return true; + } + return false; + } + + /// + /// Loads the full text of and returns it, + /// or an empty string if the file does not exist. + /// + public static string LoadText(string iniPath) + => File.Exists(iniPath) ? File.ReadAllText(iniPath) : string.Empty; + + /// + /// Checks the support level of a given termsrv.dll version against the + /// INI content string . + /// + /// + /// 0 = not supported, 1 = partially supported (Vista/7 legacy), + /// 2 = fully supported (entry found in ini). + /// + public static int CheckSupportLevel(string iniContent, + FileVersionHelper.FileVersionInfo fv) + { + int level = 0; + + // Vista (6.0) and Windows 7 (6.1) are "partially" supported without + // a specific INI entry — mirrors the Delphi CheckSupport logic. + if ((fv.Major == 6 && fv.Minor == 0) || + (fv.Major == 6 && fv.Minor == 1)) + level = 1; + + var verTxt = fv.ToString(); // "major.minor.release.build" + if (iniContent.Contains($"[{verTxt}]", StringComparison.Ordinal)) + level = 2; + + return level; + } +} diff --git a/src-csharp/RDPWrap/NativeMethods.cs b/src-csharp/RDPWrap/NativeMethods.cs new file mode 100644 index 0000000..1312a72 --- /dev/null +++ b/src-csharp/RDPWrap/NativeMethods.cs @@ -0,0 +1,467 @@ +// Copyright 2026 sjackson0109 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Runtime.InteropServices; + +namespace RDPWrap.Common; + +/// +/// All P/Invoke declarations used across RDPWInst, RDPConf and RDPCheck. +/// Mirrors the unhooked Win32 imports from the original Delphi sources. +/// +internal static class NativeMethods +{ + // ─── DLL names ──────────────────────────────────────────────────────────── + internal const string Kernel32 = "kernel32.dll"; + internal const string Advapi32 = "advapi32.dll"; + internal const string WinSta = "winsta.dll"; + + // ─── Constants ──────────────────────────────────────────────────────────── + + // Architecture + internal const ushort PROCESSOR_ARCHITECTURE_INTEL = 0; + internal const ushort PROCESSOR_ARCHITECTURE_IA64 = 6; + internal const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9; + + // Registry + internal const uint KEY_WOW64_64KEY = 0x0100; + internal const uint KEY_WOW64_32KEY = 0x0200; + internal const uint KEY_READ = 0x20019; + internal const uint KEY_WRITE = 0x20006; + internal const uint KEY_QUERY_VALUE = 0x0001; + internal const uint KEY_SET_VALUE = 0x0002; + + // Service control manager + internal const uint SC_MANAGER_CONNECT = 0x0001; + internal const uint SC_MANAGER_CREATE_SERVICE = 0x0002; + internal const uint SC_MANAGER_ENUMERATE_SERVICE = 0x0004; + internal const uint SC_MANAGER_ALL_ACCESS = 0xF003F; + + internal const uint SERVICE_QUERY_CONFIG = 0x0001; + internal const uint SERVICE_CHANGE_CONFIG = 0x0002; + internal const uint SERVICE_QUERY_STATUS = 0x0004; + internal const uint SERVICE_START = 0x0010; + internal const uint SERVICE_STOP = 0x0020; + internal const uint SERVICE_ALL_ACCESS = 0xF01FF; + + internal const uint SERVICE_WIN32 = 0x30; + internal const uint SERVICE_STATE_ALL = 0x03; + internal const uint SERVICE_NO_CHANGE = 0xFFFFFFFF; + internal const uint SERVICE_AUTO_START = 0x02; + internal const uint SERVICE_DEMAND_START = 0x03; + internal const uint SERVICE_DISABLED = 0x04; + + internal const uint SERVICE_STOPPED = 0x00000001; + internal const uint SERVICE_START_PENDING = 0x00000002; + internal const uint SERVICE_STOP_PENDING = 0x00000003; + internal const uint SERVICE_RUNNING = 0x00000004; + internal const uint SERVICE_CONTINUE_PENDING = 0x00000005; + internal const uint SERVICE_PAUSE_PENDING = 0x00000006; + internal const uint SERVICE_PAUSED = 0x00000007; + + internal const uint SC_ENUM_PROCESS_INFO = 0; + internal const uint SC_STATUS_PROCESS_INFO = 0; + internal const uint ERROR_MORE_DATA = 234; + internal const uint ERROR_SERVICE_DOES_NOT_EXIST = 1060; + internal const uint ERROR_SERVICE_NOT_ACTIVE = 1062; + + // Process/Thread + internal const uint PROCESS_TERMINATE = 0x0001; + internal const uint THREAD_SUSPEND_RESUME = 0x0002; + internal const uint TH32CS_SNAPTHREAD = 0x00000004; + + // Token privileges + internal const uint TOKEN_ADJUST_PRIVILEGES = 0x0020; + internal const uint TOKEN_QUERY = 0x0008; + internal const uint SE_PRIVILEGE_ENABLED = 0x00000002; + + // Privilege names + internal const string SE_DEBUG_NAME = "SeDebugPrivilege"; + internal const string SE_RESTORE_NAME = "SeRestorePrivilege"; + internal const string SE_BACKUP_NAME = "SeBackupPrivilege"; + + // Security + internal const uint DACL_SECURITY_INFORMATION = 0x00000004; + internal const uint SE_FILE_OBJECT = 1; + internal const uint GRANT_ACCESS = 1; + internal const uint SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3; + internal const uint NO_MULTIPLE_TRUSTEE = 0; + internal const uint TRUSTEE_IS_SID = 0; + internal const uint TRUSTEE_IS_WELL_KNOWN_GROUP = 5; + internal const uint GENERIC_ALL = 0x10000000; + + // LoadLibraryEx flags + internal const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002; + + // Version resource type + internal const uint RT_VERSION = 16; + + // CreateProcess - STARTUPINFO flags + internal const uint STARTF_USESHOWWINDOW = 0x00000001; + internal const ushort SW_HIDE = 0; + + // GetModuleHandleEx + internal const uint GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 0x00000004; + internal const uint GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002; + + // Error codes + internal const uint ERROR_SUCCESS = 0; + internal const uint ERROR_ACCESS_DENIED = 5; + internal const uint ERROR_NOT_SUPPORTED = 50; + internal const uint ERROR_SERVICE_ALREADY_RUNNING = 1056; + + // ─── Structures ─────────────────────────────────────────────────────────── + + [StructLayout(LayoutKind.Sequential)] + internal struct SYSTEM_INFO + { + internal ushort wProcessorArchitecture; + internal ushort wReserved; + internal uint dwPageSize; + internal IntPtr lpMinimumApplicationAddress; + internal IntPtr lpMaximumApplicationAddress; + internal UIntPtr dwActiveProcessorMask; + internal uint dwNumberOfProcessors; + internal uint dwProcessorType; + internal uint dwAllocationGranularity; + internal ushort wProcessorLevel; + internal ushort wProcessorRevision; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct STARTUPINFO + { + internal uint cb; + internal string? lpReserved; + internal string? lpDesktop; + internal string? lpTitle; + internal uint dwX, dwY, dwXSize, dwYSize, dwXCountChars, dwYCountChars; + internal uint dwFillAttribute; + internal uint dwFlags; + internal ushort wShowWindow; + internal ushort cbReserved2; + internal IntPtr lpReserved2; + internal IntPtr hStdInput, hStdOutput, hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct PROCESS_INFORMATION + { + internal IntPtr hProcess; + internal IntPtr hThread; + internal uint dwProcessId; + internal uint dwThreadId; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct THREADENTRY32 + { + internal uint dwSize; + internal uint cntUsage; + internal uint th32ThreadID; + internal uint th32OwnerProcessID; + internal int tpBasePri; + internal int tpDeltaPri; + internal uint dwFlags; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct SERVICE_STATUS_PROCESS + { + internal uint dwServiceType; + internal uint dwCurrentState; + internal uint dwControlsAccepted; + internal uint dwWin32ExitCode; + internal uint dwServiceSpecificExitCode; + internal uint dwCheckPoint; + internal uint dwWaitHint; + internal uint dwProcessId; + internal uint dwServiceFlags; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct ENUM_SERVICE_STATUS_PROCESS + { + internal string lpServiceName; + internal string lpDisplayName; + internal SERVICE_STATUS_PROCESS ServiceStatusProcess; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct QUERY_SERVICE_CONFIG + { + internal uint dwServiceType; + internal uint dwStartType; + internal uint dwErrorControl; + internal string lpBinaryPathName; + internal string lpLoadOrderGroup; + internal uint dwTagId; + internal string lpDependencies; + internal string lpServiceStartName; + internal string lpDisplayName; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct LUID + { + internal uint LowPart; + internal int HighPart; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct LUID_AND_ATTRIBUTES + { + internal LUID Luid; + internal uint Attributes; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct TOKEN_PRIVILEGES + { + internal uint PrivilegeCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + internal LUID_AND_ATTRIBUTES[] Privileges; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct EXPLICIT_ACCESS + { + internal uint grfAccessPermissions; + internal uint grfAccessMode; + internal uint grfInheritance; + internal TRUSTEE Trustee; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct TRUSTEE + { + internal IntPtr pMultipleTrustee; + internal uint MultipleTrusteeOperation; + internal uint TrusteeForm; + internal uint TrusteeType; + internal IntPtr ptstrName; // SID pointer or string pointer + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct WTS_SESSION_INFO + { + internal uint SessionId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)] + internal string Name; + internal uint State; + } + + // ─── kernel32.dll ───────────────────────────────────────────────────────── + + [DllImport(Kernel32, SetLastError = true)] + internal static extern void GetNativeSystemInfo(out SYSTEM_INFO lpSystemInfo); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Wow64DisableWow64FsRedirection(out IntPtr oldValue); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Wow64RevertWow64FsRedirection(IntPtr oldValue); + + [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool FreeLibrary(IntPtr hModule); + + [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern IntPtr LockResource(IntPtr hResData); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo); + + [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool CreateProcess( + string? lpApplicationName, + string lpCommandLine, + IntPtr lpProcessAttributes, + IntPtr lpThreadAttributes, + [MarshalAs(UnmanagedType.Bool)] bool bInheritHandles, + uint dwCreationFlags, + IntPtr lpEnvironment, + string? lpCurrentDirectory, + ref STARTUPINFO lpStartupInfo, + out PROCESS_INFORMATION lpProcessInformation); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool CloseHandle(IntPtr hObject); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern IntPtr OpenProcess(uint dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern uint GetCurrentProcessId(); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern uint GetCurrentThreadId(); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Thread32First(IntPtr hSnapshot, ref THREADENTRY32 lpte); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Thread32Next(IntPtr hSnapshot, ref THREADENTRY32 lpte); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern IntPtr OpenThread(uint dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwThreadId); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern uint SuspendThread(IntPtr hThread); + + [DllImport(Kernel32, SetLastError = true)] + internal static extern uint ResumeThread(IntPtr hThread); + + [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern uint GetModuleFileName(IntPtr hModule, + System.Text.StringBuilder lpFilename, uint nSize); + + [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool GetModuleHandleEx(uint dwFlags, IntPtr lpModuleName, + out IntPtr phModule); + + [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern uint ExpandEnvironmentStrings(string lpSrc, + System.Text.StringBuilder lpDst, uint nSize); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool DeleteFile(string lpFileName); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool RemoveDirectory(string lpPathName); + + [DllImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool OpenProcessToken(IntPtr processHandle, + uint desiredAccess, out IntPtr tokenHandle); + + // ─── advapi32.dll ───────────────────────────────────────────────────────── + + [DllImport(Advapi32, SetLastError = true)] + internal static extern IntPtr OpenSCManager(string? lpMachineName, + string? lpDatabaseName, uint dwDesiredAccess); + + [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern IntPtr OpenService(IntPtr hSCManager, + string lpServiceName, uint dwDesiredAccess); + + [DllImport(Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool CloseServiceHandle(IntPtr hSCObject); + + [DllImport(Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool QueryServiceConfig(IntPtr hService, + IntPtr lpServiceConfig, uint cbBufSize, out uint pcbBytesNeeded); + + [DllImport(Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool QueryServiceStatusEx(IntPtr hService, + uint InfoLevel, IntPtr lpBuffer, uint cbBufSize, out uint pcbBytesNeeded); + + [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool ChangeServiceConfig(IntPtr hService, + uint dwServiceType, uint dwStartType, uint dwErrorControl, + string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, + string? lpDependencies, string? lpServiceStartName, string? lpPassword, + string? lpDisplayName); + + [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool StartService(IntPtr hService, + uint dwNumServiceArgs, string[]? lpServiceArgVectors); + + [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool EnumServicesStatusEx( + IntPtr hSCManager, uint InfoLevel, uint dwServiceType, uint dwServiceState, + IntPtr lpServices, uint cbBufSize, + out uint pcbBytesNeeded, out uint lpServicesReturned, + ref uint lpResumeHandle, string? pszGroupName); + + [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool LookupPrivilegeValue(string? lpSystemName, + string lpName, out LUID lpLuid); + + [DllImport(Advapi32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool AdjustTokenPrivileges(IntPtr tokenHandle, + [MarshalAs(UnmanagedType.Bool)] bool disableAllPrivileges, + ref TOKEN_PRIVILEGES newState, uint bufferLength, + IntPtr previousState, IntPtr returnLength); + + [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool ConvertStringSidToSid(string stringSid, out IntPtr sid); + + [DllImport(Advapi32, SetLastError = true)] + internal static extern uint SetEntriesInAcl(uint cCountOfExplicitEntries, + ref EXPLICIT_ACCESS pListOfExplicitEntries, IntPtr oldAcl, out IntPtr newAcl); + + [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern uint SetNamedSecurityInfo(string pObjectName, + uint ObjectType, uint SecurityInfo, + IntPtr psidOwner, IntPtr psidGroup, IntPtr pDacl, IntPtr pSacl); + + [DllImport(Advapi32, SetLastError = true)] + internal static extern IntPtr LocalFree(IntPtr hMem); + + // ─── winsta.dll ─────────────────────────────────────────────────────────── + + /// + /// Enumerates WTS sessions on the local server. + /// Pass IntPtr.Zero as hServer for the local machine. + /// + [DllImport(WinSta, EntryPoint = "WinStationEnumerateW", + CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool WinStationEnumerate(IntPtr hServer, + out IntPtr ppSessionInfo, out uint pCount); + + [DllImport(WinSta, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool WinStationFreeMemory(IntPtr p); +} diff --git a/src-csharp/RDPWrap/ProcessHelper.cs b/src-csharp/RDPWrap/ProcessHelper.cs new file mode 100644 index 0000000..8cee8fc --- /dev/null +++ b/src-csharp/RDPWrap/ProcessHelper.cs @@ -0,0 +1,63 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +using System.Runtime.InteropServices; + +namespace RDPWrap.Common; + +/// +/// Process creation and termination helpers. Mirrors ExecWait and KillProcess +/// from RDPWInst.dpr (console variant) and RDPConf MainUnit.pas (GUI variant). +/// +public static class ProcessHelper +{ + /// + /// Creates a process from , waits for it to + /// exit, then returns true. The process window is hidden. + /// Mirrors the Delphi ExecWait procedure. + /// + public static bool ExecWait(string commandLine, bool hideWindow = true) + { + var si = new NativeMethods.STARTUPINFO + { + cb = (uint)Marshal.SizeOf(), + dwFlags = hideWindow ? NativeMethods.STARTF_USESHOWWINDOW : 0u, + wShowWindow = hideWindow ? NativeMethods.SW_HIDE : (ushort)1 + }; + + // CommandLine must be mutable — pass a copy + string cmdCopy = new(commandLine); + + if (!NativeMethods.CreateProcess(null, cmdCopy, IntPtr.Zero, IntPtr.Zero, + true, 0, IntPtr.Zero, null, ref si, out var pi)) + { + Console.Error.WriteLine( + $"[-] CreateProcess error (code {Marshal.GetLastWin32Error()})."); + return false; + } + + NativeMethods.WaitForSingleObject(pi.hProcess, 0xFFFFFFFF); + NativeMethods.CloseHandle(pi.hThread); + NativeMethods.CloseHandle(pi.hProcess); + return true; + } + + /// + /// Terminates the process with . Mirrors the Delphi + /// KillProcess procedure. + /// + public static void KillProcess(uint pid) + { + var hProc = NativeMethods.OpenProcess(NativeMethods.PROCESS_TERMINATE, false, pid); + if (hProc == IntPtr.Zero) + { + Console.Error.WriteLine( + $"[-] OpenProcess error (code {Marshal.GetLastWin32Error()})."); + return; + } + + if (!NativeMethods.TerminateProcess(hProc, 0)) + Console.Error.WriteLine( + $"[-] TerminateProcess error (code {Marshal.GetLastWin32Error()})."); + + NativeMethods.CloseHandle(hProc); + } +} diff --git a/src-csharp/RDPWrap/RDPWrap.csproj b/src-csharp/RDPWrap/RDPWrap.csproj new file mode 100644 index 0000000..bee8351 --- /dev/null +++ b/src-csharp/RDPWrap/RDPWrap.csproj @@ -0,0 +1,15 @@ + + + Library + RDPWrap.Common + RDPWrap + Shared helper library (P/Invoke, registry, service, security helpers) for the RDP Wrapper tool suite. + + + + + + + + + diff --git a/src-csharp/RDPWrap/RegistryHelper.cs b/src-csharp/RDPWrap/RegistryHelper.cs new file mode 100644 index 0000000..49bc306 --- /dev/null +++ b/src-csharp/RDPWrap/RegistryHelper.cs @@ -0,0 +1,97 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +using Microsoft.Win32; + +namespace RDPWrap.Common; + +/// +/// Thin wrappers around that mirror the +/// Delphi TRegistry usage in RDPWInst and RDPConf, with optional WOW64 flag +/// support (KEY_WOW64_64KEY) for 64-bit registry views from 32-bit processes. +/// +public static class RegistryHelper +{ + // On 64-bit Windows we always open the 64-bit view to match the Delphi code + // that passes KEY_WOW64_64KEY when Arch = 64. + private static RegistryView ViewForArch() => + ArchHelper.Is64Bit ? RegistryView.Registry64 : RegistryView.Default; + + // ── Convenience open helpers ────────────────────────────────────────────── + + /// Opens a read-only key under HKLM, respecting the host architecture. + public static RegistryKey? OpenHklmRead(string subKey) + { + using var hive = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, ViewForArch()); + return hive.OpenSubKey(subKey, writable: false); + } + + /// Opens a writable key under HKLM (creates if absent). + public static RegistryKey OpenHklmWrite(string subKey) + { + using var hive = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, ViewForArch()); + return hive.CreateSubKey(subKey, writable: true) + ?? throw new InvalidOperationException($"Cannot open/create HKLM\\{subKey}"); + } + + // ── Typed read helpers ──────────────────────────────────────────────────── + + /// + /// Reads a string value from HKLM. Returns null if the key or + /// value does not exist. + /// + public static string? ReadString(string subKey, string valueName) + { + using var key = OpenHklmRead(subKey); + return key?.GetValue(valueName) as string; + } + + /// + /// Reads a DWORD value from HKLM. Returns + /// if the key or value does not exist. + /// + public static int ReadInt(string subKey, string valueName, int defaultValue = 0) + { + using var key = OpenHklmRead(subKey); + if (key is null) return defaultValue; + var raw = key.GetValue(valueName); + return raw is int i ? i : defaultValue; + } + + /// + /// Reads a DWORD as a bool (non-zero = true). Returns + /// if absent. + /// + public static bool ReadBool(string subKey, string valueName, bool defaultValue = false) + { + using var key = OpenHklmRead(subKey); + if (key is null) return defaultValue; + var raw = key.GetValue(valueName); + return raw is int i ? i != 0 : defaultValue; + } + + // ── Typed write helpers ─────────────────────────────────────────────────── + + /// Writes a REG_SZ string value. + public static void WriteString(string subKey, string valueName, string value) + { + using var key = OpenHklmWrite(subKey); + key.SetValue(valueName, value, RegistryValueKind.String); + } + + /// Writes a REG_EXPAND_SZ string value (mirrors Delphi WriteExpandString). + public static void WriteExpandString(string subKey, string valueName, string value) + { + using var key = OpenHklmWrite(subKey); + key.SetValue(valueName, value, RegistryValueKind.ExpandString); + } + + /// Writes a DWORD integer value. + public static void WriteInt(string subKey, string valueName, int value) + { + using var key = OpenHklmWrite(subKey); + key.SetValue(valueName, value, RegistryValueKind.DWord); + } + + /// Writes a boolean as a DWORD (1/0). + public static void WriteBool(string subKey, string valueName, bool value) + => WriteInt(subKey, valueName, value ? 1 : 0); +} diff --git a/src-csharp/RDPWrap/ResourceHelper.cs b/src-csharp/RDPWrap/ResourceHelper.cs new file mode 100644 index 0000000..51d1015 --- /dev/null +++ b/src-csharp/RDPWrap/ResourceHelper.cs @@ -0,0 +1,88 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +using System.Reflection; + +namespace RDPWrap.Common; + +/// +/// Helpers for reading and extracting managed embedded resources. +/// Mirrors the Delphi ExtractRes / ExtractResText procedures from RDPWInst.dpr +/// and RDPConf MainUnit.pas, translated to the .NET manifest-resource model. +/// +public static class ResourceHelper +{ + /// + /// Reads the contents of the embedded resource named + /// from + /// and returns it as a UTF-8 string. Returns null if not found. + /// + public static string? ReadText(string resourceName, + Assembly? assembly = null) + { + assembly ??= Assembly.GetCallingAssembly(); + using var stream = assembly.GetManifestResourceStream(resourceName); + if (stream is null) return null; + using var reader = new StreamReader(stream, System.Text.Encoding.UTF8); + return reader.ReadToEnd(); + } + + /// + /// Reads the contents of the embedded resource named + /// and returns the raw bytes. + /// Returns null if not found. + /// + public static byte[]? ReadBytes(string resourceName, + Assembly? assembly = null) + { + assembly ??= Assembly.GetCallingAssembly(); + using var stream = assembly.GetManifestResourceStream(resourceName); + if (stream is null) return null; + using var ms = new MemoryStream(); + stream.CopyTo(ms); + return ms.ToArray(); + } + + /// + /// Extracts the embedded resource to disk + /// at , creating parent directories as needed. + /// Returns true on success. Mirrors the Delphi ExtractRes procedure. + /// + public static bool ExtractToDisk(string resourceName, string destPath, + Assembly? assembly = null) + { + assembly ??= Assembly.GetCallingAssembly(); + using var stream = assembly.GetManifestResourceStream(resourceName); + if (stream is null) + { + Console.Error.WriteLine($"[-] Resource not found: {resourceName}"); + return false; + } + + var dir = Path.GetDirectoryName(destPath); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + try + { + using var file = File.Create(destPath); + stream.CopyTo(file); + Console.WriteLine($"[+] Extracted {resourceName} -> {destPath}"); + return true; + } + catch (Exception ex) + { + Console.Error.WriteLine( + $"[-] Failed to extract resource {resourceName} to {destPath}: {ex.Message}"); + return false; + } + } + + /// + /// Lists all manifest resource names in + /// — useful for debugging resource name mismatches. + /// + public static IEnumerable ListResources(Assembly? assembly = null) + { + assembly ??= Assembly.GetCallingAssembly(); + return assembly.GetManifestResourceNames(); + } +} diff --git a/src-csharp/RDPWrap/SecurityHelper.cs b/src-csharp/RDPWrap/SecurityHelper.cs new file mode 100644 index 0000000..3535834 --- /dev/null +++ b/src-csharp/RDPWrap/SecurityHelper.cs @@ -0,0 +1,168 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +using System.Runtime.InteropServices; + +namespace RDPWrap.Common; + +/// +/// Security helpers: granting SID-based DACL entries (GrantSidFullAccess) and +/// adjusting process token privileges (AddPrivilege). Mirrors the Delphi +/// implementations in RDPWInst.dpr. +/// +public static class SecurityHelper +{ + // ── DACL: grant a well-known SID full access to a file/folder ───────────── + + /// + /// Grants GENERIC_ALL access to the well-known SID string + /// on the file/directory at + /// . Mirrors the Delphi GrantSidFullAccess + /// procedure (used for "S-1-5-18" = Local System, "S-1-5-6" = Service). + /// + public static void GrantSidFullAccess(string path, string stringSid) + { + if (!NativeMethods.ConvertStringSidToSid(stringSid, out IntPtr pSid)) + { + Console.Error.WriteLine( + $"[-] ConvertStringSidToSid error (code {Marshal.GetLastWin32Error()}) " + + $"for SID {stringSid}."); + return; + } + + try + { + var ea = new NativeMethods.EXPLICIT_ACCESS + { + grfAccessPermissions = NativeMethods.GENERIC_ALL, + grfAccessMode = NativeMethods.GRANT_ACCESS, + grfInheritance = NativeMethods.SUB_CONTAINERS_AND_OBJECTS_INHERIT, + Trustee = new NativeMethods.TRUSTEE + { + pMultipleTrustee = IntPtr.Zero, + MultipleTrusteeOperation = NativeMethods.NO_MULTIPLE_TRUSTEE, + TrusteeForm = NativeMethods.TRUSTEE_IS_SID, + TrusteeType = NativeMethods.TRUSTEE_IS_WELL_KNOWN_GROUP, + ptstrName = pSid + } + }; + + uint result = NativeMethods.SetEntriesInAcl(1, ref ea, IntPtr.Zero, out IntPtr pNewAcl); + if (result == NativeMethods.ERROR_SUCCESS) + { + uint secResult = NativeMethods.SetNamedSecurityInfo( + path, + NativeMethods.SE_FILE_OBJECT, + NativeMethods.DACL_SECURITY_INFORMATION, + IntPtr.Zero, IntPtr.Zero, pNewAcl, IntPtr.Zero); + + if (secResult != NativeMethods.ERROR_SUCCESS) + Console.Error.WriteLine( + $"[-] SetNamedSecurityInfo error (code {secResult})."); + + NativeMethods.LocalFree(pNewAcl); + } + else + { + Console.Error.WriteLine($"[-] SetEntriesInAcl error (code {result})."); + } + } + finally + { + NativeMethods.LocalFree(pSid); + } + } + + // ── Token privileges ────────────────────────────────────────────────────── + + /// + /// Enables the named privilege (e.g. SeDebugPrivilege) for the + /// current process token. Mirrors the Delphi AddPrivilege function. + /// Returns true on success. + /// + public static bool AddPrivilege(string privilegeName) + { + if (!NativeMethods.OpenProcessToken( + System.Diagnostics.Process.GetCurrentProcess().Handle, + NativeMethods.TOKEN_ADJUST_PRIVILEGES | NativeMethods.TOKEN_QUERY, + out IntPtr hToken)) + { + Console.Error.WriteLine( + $"[-] OpenProcessToken error (code {Marshal.GetLastWin32Error()})."); + return false; + } + + try + { + if (!NativeMethods.LookupPrivilegeValue(null, privilegeName, out var luid)) + { + Console.Error.WriteLine( + $"[-] LookupPrivilegeValue error (code {Marshal.GetLastWin32Error()})."); + return false; + } + + var tp = new NativeMethods.TOKEN_PRIVILEGES + { + PrivilegeCount = 1, + Privileges = new[] + { + new NativeMethods.LUID_AND_ATTRIBUTES + { + Luid = luid, + Attributes = NativeMethods.SE_PRIVILEGE_ENABLED + } + } + }; + + if (!NativeMethods.AdjustTokenPrivileges( + hToken, false, ref tp, + (uint)Marshal.SizeOf(tp), + IntPtr.Zero, IntPtr.Zero)) + { + Console.Error.WriteLine( + $"[-] AdjustTokenPrivileges error (code {Marshal.GetLastWin32Error()})."); + return false; + } + + return true; + } + finally + { + NativeMethods.CloseHandle(hToken); + } + } + + // ── RDP-Tcp listener ────────────────────────────────────────────────────── + + /// + /// Returns true when there is an active "RDP-Tcp" WTS listener on + /// the local machine — i.e. WinStationEnumerateW returns a session + /// named "RDP-Tcp". Mirrors the Delphi IsListenerWorking function. + /// + public static bool IsRdpListenerWorking() + { + if (!NativeMethods.WinStationEnumerate(IntPtr.Zero, + out IntPtr ppInfo, out uint count)) + return false; + + try + { + int ptrSize = IntPtr.Size; + // WTS_SESSION_INFO is: DWORD SessionId + 34 WCHARs (Name) + DWORD State + // = 4 + 68 + 4 = 76 bytes, but aligned to 4-byte boundary → 76 bytes. + int entrySize = 4 + 34 * 2 + 4; // = 76 + + for (uint i = 0; i < count; i++) + { + IntPtr entry = ppInfo + (int)(i * (uint)entrySize); + // Name starts at offset 4 + string name = Marshal.PtrToStringUni(entry + 4, 34).TrimEnd('\0'); + if (name == "RDP-Tcp") return true; + } + } + finally + { + NativeMethods.WinStationFreeMemory(ppInfo); + } + + return false; + } +} diff --git a/src-csharp/RDPWrap/ServiceHelper.cs b/src-csharp/RDPWrap/ServiceHelper.cs new file mode 100644 index 0000000..486ad93 --- /dev/null +++ b/src-csharp/RDPWrap/ServiceHelper.cs @@ -0,0 +1,219 @@ +// Copyright 2026 sjackson0109 — Apache License 2.0 +using System.Runtime.InteropServices; + +namespace RDPWrap.Common; + +/// +/// Wrappers around the Windows Service Control Manager API, mirroring the +/// SvcGetStart / SvcConfigStart / SvcStart / CheckTermsrvProcess helpers +/// in RDPWInst.dpr and GetTermSrvState in RDPConf MainUnit.pas. +/// +public static class ServiceHelper +{ + // ── Start-type query / change ───────────────────────────────────────────── + + /// + /// Returns the configured start type of + /// (e.g. SERVICE_AUTO_START) or -1 on failure. + /// + public static int GetStartType(string serviceName) + { + var hSC = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_CONNECT); + if (hSC == IntPtr.Zero) return -1; + try + { + var hSvc = NativeMethods.OpenService(hSC, serviceName, + NativeMethods.SERVICE_QUERY_CONFIG); + if (hSvc == IntPtr.Zero) return -1; + try + { + NativeMethods.QueryServiceConfig(hSvc, IntPtr.Zero, 0, out uint needed); + var buf = Marshal.AllocHGlobal((int)needed); + try + { + if (!NativeMethods.QueryServiceConfig(hSvc, buf, needed, out _)) + return -1; + // dwStartType is the second DWORD in QUERY_SERVICE_CONFIG + return Marshal.ReadInt32(buf, 4); + } + finally { Marshal.FreeHGlobal(buf); } + } + finally { NativeMethods.CloseServiceHandle(hSvc); } + } + finally { NativeMethods.CloseServiceHandle(hSC); } + } + + /// + /// Changes the start type of to + /// (one of the SERVICE_*_START constants). + /// + public static bool SetStartType(string serviceName, uint startType) + { + var hSC = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_CONNECT); + if (hSC == IntPtr.Zero) return false; + try + { + var hSvc = NativeMethods.OpenService(hSC, serviceName, + NativeMethods.SERVICE_CHANGE_CONFIG); + if (hSvc == IntPtr.Zero) return false; + try + { + return NativeMethods.ChangeServiceConfig(hSvc, + NativeMethods.SERVICE_NO_CHANGE, startType, + NativeMethods.SERVICE_NO_CHANGE, + null, null, IntPtr.Zero, null, null, null, null); + } + finally { NativeMethods.CloseServiceHandle(hSvc); } + } + finally { NativeMethods.CloseServiceHandle(hSC); } + } + + // ── Start a service ─────────────────────────────────────────────────────── + + /// + /// Starts . If the service is already + /// running (error 1056) it waits 2 s and retries once, matching the + /// original Delphi SvcStart behaviour. + /// Returns true on success. + /// + public static bool StartService(string serviceName) + { + var hSC = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_CONNECT); + if (hSC == IntPtr.Zero) return false; + try + { + var hSvc = NativeMethods.OpenService(hSC, serviceName, + NativeMethods.SERVICE_START); + if (hSvc == IntPtr.Zero) return false; + try + { + if (NativeMethods.StartService(hSvc, 0, null)) return true; + + var err = Marshal.GetLastWin32Error(); + if (err == (int)NativeMethods.ERROR_SERVICE_ALREADY_RUNNING) + { + Thread.Sleep(2000); + return NativeMethods.StartService(hSvc, 0, null); + } + return false; + } + finally { NativeMethods.CloseServiceHandle(hSvc); } + } + finally { NativeMethods.CloseServiceHandle(hSC); } + } + + // ── Status query ────────────────────────────────────────────────────────── + + /// + /// Returns the dwCurrentState for + /// (e.g. SERVICE_RUNNING = 4) or -1 on failure. + /// + public static int GetCurrentState(string serviceName) + { + var hSC = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_CONNECT); + if (hSC == IntPtr.Zero) return -1; + try + { + var hSvc = NativeMethods.OpenService(hSC, serviceName, + NativeMethods.SERVICE_QUERY_STATUS); + if (hSvc == IntPtr.Zero) return -1; + try + { + NativeMethods.QueryServiceStatusEx(hSvc, + NativeMethods.SC_STATUS_PROCESS_INFO, + IntPtr.Zero, 0, out uint needed); + + var buf = Marshal.AllocHGlobal((int)needed); + try + { + if (!NativeMethods.QueryServiceStatusEx(hSvc, + NativeMethods.SC_STATUS_PROCESS_INFO, + buf, needed, out _)) return -1; + + // dwCurrentState is the second DWORD in SERVICE_STATUS_PROCESS + return Marshal.ReadInt32(buf, 4); + } + finally { Marshal.FreeHGlobal(buf); } + } + finally { NativeMethods.CloseServiceHandle(hSvc); } + } + finally { NativeMethods.CloseServiceHandle(hSC); } + } + + // ── Process-info enumeration ────────────────────────────────────────────── + + /// + /// Represents the name and PID of a service process returned by + /// . + /// + public record ServiceProcessInfo(string ServiceName, string DisplayName, uint ProcessId, uint CurrentState); + + /// + /// Enumerates all Win32 services (all states) and returns their + /// process information. Mirrors the EnumServicesStatusEx loop in + /// CheckTermsrvProcess. + /// + public static IReadOnlyList EnumServiceProcesses() + { + var result = new List(); + + var hSC = NativeMethods.OpenSCManager(null, null, + NativeMethods.SC_MANAGER_CONNECT | NativeMethods.SC_MANAGER_ENUMERATE_SERVICE); + if (hSC == IntPtr.Zero) return result; + + try + { + uint resumeHandle = 0; + // Ask for the required buffer size + NativeMethods.EnumServicesStatusEx(hSC, + NativeMethods.SC_ENUM_PROCESS_INFO, + NativeMethods.SERVICE_WIN32, + NativeMethods.SERVICE_STATE_ALL, + IntPtr.Zero, 0, + out uint needed, out _, ref resumeHandle, null); + + if (needed == 0) return result; + + var buf = Marshal.AllocHGlobal((int)needed); + try + { + resumeHandle = 0; + if (!NativeMethods.EnumServicesStatusEx(hSC, + NativeMethods.SC_ENUM_PROCESS_INFO, + NativeMethods.SERVICE_WIN32, + NativeMethods.SERVICE_STATE_ALL, + buf, needed, + out _, out uint returned, ref resumeHandle, null)) + return result; + + // ENUM_SERVICE_STATUS_PROCESS layout (Unicode, packed): + // IntPtr lpServiceName (pointer to string) + // IntPtr lpDisplayName (pointer to string) + // SERVICE_STATUS_PROCESS (9 × DWORD = 36 bytes) + int ptrSize = IntPtr.Size; + int entrySize = ptrSize * 2 + 36; // 2 string pointers + status struct + + for (int i = 0; i < (int)returned; i++) + { + var entryPtr = buf + i * entrySize; + var namePtr = Marshal.ReadIntPtr(entryPtr); + var dispPtr = Marshal.ReadIntPtr(entryPtr + ptrSize); + + var svcName = Marshal.PtrToStringUni(namePtr) ?? string.Empty; + var dispName = Marshal.PtrToStringUni(dispPtr) ?? string.Empty; + + // dwCurrentState at offset 4, dwProcessId at offset 28 + var statusBase = entryPtr + ptrSize * 2; + uint currentState = (uint)Marshal.ReadInt32(statusBase + 4); + uint pid = (uint)Marshal.ReadInt32(statusBase + 28); + + result.Add(new ServiceProcessInfo(svcName, dispName, pid, currentState)); + } + } + finally { Marshal.FreeHGlobal(buf); } + } + finally { NativeMethods.CloseServiceHandle(hSC); } + + return result; + } +} diff --git a/src-csharp/RDPWrap/packages.lock.json b/src-csharp/RDPWrap/packages.lock.json new file mode 100644 index 0000000..2a64009 --- /dev/null +++ b/src-csharp/RDPWrap/packages.lock.json @@ -0,0 +1,6 @@ +{ + "version": 1, + "dependencies": { + "net10.0-windows7.0": {} + } +} \ No newline at end of file diff --git a/src-installer/RDPWInst.dpr b/src-installer/RDPWInst.dpr deleted file mode 100644 index 6c95f3f..0000000 --- a/src-installer/RDPWInst.dpr +++ /dev/null @@ -1,1315 +0,0 @@ -{ - Copyright 2018 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -program RDPWInst; - -{$APPTYPE CONSOLE} - -{$R resource.res} - -uses - SysUtils, - Windows, - Classes, - WinSvc, - Registry, - WinInet, - AccCtrl, - AclAPI; - -function EnumServicesStatusEx( - hSCManager: SC_HANDLE; - InfoLevel, - dwServiceType, - dwServiceState: DWORD; - lpServices: PByte; - cbBufSize: DWORD; - var pcbBytesNeeded, - lpServicesReturned, - lpResumeHandle: DWORD; - pszGroupName: PWideChar): BOOL; stdcall; - external advapi32 name 'EnumServicesStatusExW'; - -function ConvertStringSidToSid( - StringSid: PWideChar; - var Sid: PSID): BOOL; stdcall; - external advapi32 name 'ConvertStringSidToSidW'; - -type - FILE_VERSION = record - Version: record case Boolean of - True: (dw: DWORD); - False: (w: record - Minor, Major: Word; - end;) - end; - Release, Build: Word; - bDebug, bPrerelease, bPrivate, bSpecial: Boolean; - end; - SERVICE_STATUS_PROCESS = packed record - dwServiceType, - dwCurrentState, - dwControlsAccepted, - dwWin32ExitCode, - dwServiceSpecificExitCode, - dwCheckPoint, - dwWaitHint, - dwProcessId, - dwServiceFlags: DWORD; - end; - PSERVICE_STATUS_PROCESS = ^SERVICE_STATUS_PROCESS; - ENUM_SERVICE_STATUS_PROCESS = packed record - lpServiceName, - lpDisplayName: PWideChar; - ServiceStatusProcess: SERVICE_STATUS_PROCESS; - end; - PENUM_SERVICE_STATUS_PROCESS = ^ENUM_SERVICE_STATUS_PROCESS; - -const - SC_ENUM_PROCESS_INFO = 0; - TermService = 'TermService'; -var - Installed: Boolean; - Online: Boolean; - WrapPath: String; - Arch: Byte; - OldWow64RedirectionValue: LongBool; - - TermServicePath: String; - FV: FILE_VERSION; - TermServicePID: DWORD; - ShareSvc: Array of String; - sShareSvc: String; - -function SupportedArchitecture: Boolean; -var - SI: TSystemInfo; -begin - GetNativeSystemInfo(SI); - case SI.wProcessorArchitecture of - 0: - begin - Arch := 32; - Result := True; // Intel x86 - end; - 6: Result := False; // Itanium-based x64 - 9: begin - Arch := 64; - Result := True; // Intel/AMD x64 - end; - else Result := False; - end; -end; - -function DisableWowRedirection: Boolean; -type - TFunc = function(var Wow64FsEnableRedirection: LongBool): LongBool; stdcall; -var - hModule: THandle; - Wow64DisableWow64FsRedirection: TFunc; -begin - Result := False; - hModule := GetModuleHandle(kernel32); - if hModule <> 0 then - Wow64DisableWow64FsRedirection := GetProcAddress(hModule, 'Wow64DisableWow64FsRedirection') - else - Exit; - if @Wow64DisableWow64FsRedirection <> nil then - Result := Wow64DisableWow64FsRedirection(OldWow64RedirectionValue); -end; - -function RevertWowRedirection: Boolean; -type - TFunc = function(var Wow64RevertWow64FsRedirection: LongBool): LongBool; stdcall; -var - hModule: THandle; - Wow64RevertWow64FsRedirection: TFunc; -begin - Result := False; - hModule := GetModuleHandle(kernel32); - if hModule <> 0 then - Wow64RevertWow64FsRedirection := GetProcAddress(hModule, 'Wow64RevertWow64FsRedirection') - else - Exit; - if @Wow64RevertWow64FsRedirection <> nil then - Result := Wow64RevertWow64FsRedirection(OldWow64RedirectionValue); -end; - -procedure CheckInstall; -var - Code: DWORD; - TermServiceHost: String; - Reg: TRegistry; -begin - if Arch = 64 then - Reg := TRegistry.Create(KEY_WOW64_64KEY) - else - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - if not Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\TermService') then - begin - Reg.Free; - Code := GetLastError; - Writeln('[-] OpenKeyReadOnly error (code ', Code, ').'); - Halt(Code); - end; - TermServiceHost := Reg.ReadString('ImagePath'); - Reg.CloseKey; - if (Pos('svchost.exe', LowerCase(TermServiceHost)) = 0) - and (Pos('svchost -k', LowerCase(TermServiceHost)) = 0) then - begin - Reg.Free; - Writeln('[-] TermService is hosted in a custom application (BeTwin, etc.) - unsupported.'); - Writeln('[*] ImagePath: "', TermServiceHost, '".'); - Halt(ERROR_NOT_SUPPORTED); - end; - if not Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\TermService\Parameters') then - begin - Reg.Free; - Code := GetLastError; - Writeln('[-] OpenKeyReadOnly error (code ', Code, ').'); - Halt(Code); - end; - TermServicePath := Reg.ReadString('ServiceDll'); - Reg.CloseKey; - if (Pos('termsrv.dll', LowerCase(TermServicePath)) = 0) - and (Pos('rdpwrap.dll', LowerCase(TermServicePath)) = 0) then - begin - Reg.Free; - Writeln('[-] Another third-party TermService library is installed.'); - Writeln('[*] ServiceDll: "', TermServicePath, '".'); - Halt(ERROR_NOT_SUPPORTED); - end; - Reg.Free; - - Installed := Pos('rdpwrap.dll', LowerCase(TermServicePath)) > 0; -end; - -function SvcGetStart(SvcName: String): Integer; -var - hSC: SC_HANDLE; - hSvc: THandle; - Code: DWORD; - lpServiceConfig: PQueryServiceConfig; - Buf: Pointer; - cbBufSize, pcbBytesNeeded: Cardinal; -begin - Result := -1; - Writeln('[*] Checking ', SvcName, '...'); - hSC := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); - if hSC = 0 then - begin - Code := GetLastError; - Writeln('[-] OpenSCManager error (code ', Code, ').'); - Exit; - end; - - hSvc := OpenService(hSC, PWideChar(SvcName), SERVICE_QUERY_CONFIG); - if hSvc = 0 then - begin - CloseServiceHandle(hSC); - Code := GetLastError; - Writeln('[-] OpenService error (code ', Code, ').'); - Exit; - end; - - if QueryServiceConfig(hSvc, nil, 0, pcbBytesNeeded) then begin - Writeln('[-] QueryServiceConfig failed.'); - Exit; - end; - - cbBufSize := pcbBytesNeeded; - GetMem(Buf, cbBufSize); - - if not QueryServiceConfig(hSvc, Buf, cbBufSize, pcbBytesNeeded) then begin - FreeMem(Buf, cbBufSize); - CloseServiceHandle(hSvc); - CloseServiceHandle(hSC); - Code := GetLastError; - Writeln('[-] QueryServiceConfig error (code ', Code, ').'); - Exit; - end else begin - lpServiceConfig := Buf; - Result := Integer(lpServiceConfig^.dwStartType); - end; - FreeMem(Buf, cbBufSize); - CloseServiceHandle(hSvc); - CloseServiceHandle(hSC); -end; - -procedure SvcConfigStart(SvcName: String; dwStartType: Cardinal); -var - hSC: SC_HANDLE; - hSvc: THandle; - Code: DWORD; -begin - Writeln('[*] Configuring ', SvcName, '...'); - hSC := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); - if hSC = 0 then - begin - Code := GetLastError; - Writeln('[-] OpenSCManager error (code ', Code, ').'); - Exit; - end; - - hSvc := OpenService(hSC, PWideChar(SvcName), SERVICE_CHANGE_CONFIG); - if hSvc = 0 then - begin - CloseServiceHandle(hSC); - Code := GetLastError; - Writeln('[-] OpenService error (code ', Code, ').'); - Exit; - end; - - if not ChangeServiceConfig(hSvc, SERVICE_NO_CHANGE, dwStartType, - SERVICE_NO_CHANGE, nil, nil, nil, nil, nil, nil, nil) then begin - CloseServiceHandle(hSvc); - CloseServiceHandle(hSC); - Code := GetLastError; - Writeln('[-] ChangeServiceConfig error (code ', Code, ').'); - Exit; - end; - CloseServiceHandle(hSvc); - CloseServiceHandle(hSC); -end; - -procedure SvcStart(SvcName: String); -var - hSC: SC_HANDLE; - hSvc: THandle; - Code: DWORD; - pch: PWideChar; - procedure ExitError(Func: String; ErrorCode: DWORD); - begin - if hSC > 0 then - CloseServiceHandle(hSC); - if hSvc > 0 then - CloseServiceHandle(hSvc); - Writeln('[-] ', Func, ' error (code ', ErrorCode, ').'); - end; -begin - hSC := 0; - hSvc := 0; - Writeln('[*] Starting ', SvcName, '...'); - hSC := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); - if hSC = 0 then - begin - ExitError('OpenSCManager', GetLastError); - Exit; - end; - - hSvc := OpenService(hSC, PWideChar(SvcName), SERVICE_START); - if hSvc = 0 then - begin - ExitError('OpenService', GetLastError); - Exit; - end; - - pch := nil; - if not StartService(hSvc, 0, pch) then begin - Code := GetLastError; - if Code = 1056 then begin // Service already started - Sleep(2000); // or SCM hasn't registered killed process - if not StartService(hSvc, 0, pch) then begin - ExitError('StartService', Code); - Exit; - end; - end else begin - ExitError('StartService', Code); - Exit; - end; - end; - CloseServiceHandle(hSvc); - CloseServiceHandle(hSC); -end; - -procedure CheckTermsrvProcess; -label - back; -var - hSC: SC_HANDLE; - dwNeedBytes, dwReturnBytes, dwResumeHandle, Code: DWORD; - Svc: Array of ENUM_SERVICE_STATUS_PROCESS; - I: Integer; - Found, Started: Boolean; - TermServiceName: String; -begin - Started := False; - back: - hSC := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT or SC_MANAGER_ENUMERATE_SERVICE); - if hSC = 0 then - begin - Code := GetLastError; - Writeln('[-] OpenSCManager error (code ', Code, ').'); - Halt(Code); - end; - - dwResumeHandle := 0; - - SetLength(Svc, 1489); - FillChar(Svc[0], sizeof(Svc[0])*Length(Svc), 0); - if not EnumServicesStatusEx(hSC, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, - @Svc[0], sizeof(Svc[0])*Length(Svc), dwNeedBytes, dwReturnBytes, dwResumeHandle, nil) then begin - Code := GetLastError; - if Code <> ERROR_MORE_DATA then - begin - CloseServiceHandle(hSC); - Writeln('[-] EnumServicesStatusEx error (code ', Code, ').'); - Halt(Code); - end - else - begin - SetLength(Svc, 5957); - FillChar(Svc[0], sizeof(Svc[0])*Length(Svc), 0); - if not EnumServicesStatusEx(hSC, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, - @Svc[0], sizeof(Svc[0])*Length(Svc), dwNeedBytes, dwReturnBytes, dwResumeHandle, nil) then begin - CloseServiceHandle(hSC); - Code := GetLastError; - Writeln('[-] EnumServicesStatusEx error (code ', Code, ').'); - Halt(Code); - end; - end; - end; - CloseServiceHandle(hSC); - - Found := False; - for I := 0 to Length(Svc) - 1 do - begin - if Svc[I].lpServiceName = nil then - Break; - if LowerCase(Svc[I].lpServiceName) = LowerCase(TermService) then - begin - Found := True; - TermServiceName := Svc[I].lpServiceName; - TermServicePID := Svc[I].ServiceStatusProcess.dwProcessId; - Break; - end; - end; - if not Found then - begin - Writeln('[-] TermService not found.'); - Halt(ERROR_SERVICE_DOES_NOT_EXIST); - end; - if TermServicePID = 0 then - begin - if Started then begin - Writeln('[-] Failed to set up TermService. Unknown error.'); - Halt(ERROR_SERVICE_NOT_ACTIVE); - end; - SvcConfigStart(TermService, SERVICE_AUTO_START); - SvcStart(TermService); - Started := True; - goto back; - end - else - Writeln('[+] TermService found (pid ', TermServicePID, ').'); - - SetLength(ShareSvc, 0); - for I := 0 to Length(Svc) - 1 do - begin - if Svc[I].lpServiceName = nil then - Break; - if Svc[I].ServiceStatusProcess.dwProcessId = TermServicePID then - if Svc[I].lpServiceName <> TermServiceName then - begin - SetLength(ShareSvc, Length(ShareSvc)+1); - ShareSvc[Length(ShareSvc)-1] := Svc[I].lpServiceName; - end; - end; - sShareSvc := ''; - for I := 0 to Length(ShareSvc) - 1 do - if sShareSvc = '' then - sShareSvc := ShareSvc[I] - else - sShareSvc := sShareSvc + ', ' + ShareSvc[I]; - if sShareSvc <> '' then - Writeln('[*] Shared services found: ', sShareSvc) - else - Writeln('[*] No shared services found.'); -end; - -function AddPrivilege(SePriv: String): Boolean; -var - hToken: THandle; - SeNameValue: Int64; - tkp: TOKEN_PRIVILEGES; - ReturnLength: Cardinal; - ErrorCode: Cardinal; -begin - Result := False; - if not OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES - or TOKEN_QUERY, hToken) then begin - ErrorCode := GetLastError; - Writeln('[-] OpenProcessToken error (code ' + IntToStr(ErrorCode) + ').'); - Exit; - end; - if not LookupPrivilegeValue(nil, PWideChar(SePriv), SeNameValue) then begin - ErrorCode := GetLastError; - Writeln('[-] LookupPrivilegeValue error (code ' + IntToStr(ErrorCode) + ').'); - Exit; - end; - tkp.PrivilegeCount := 1; - tkp.Privileges[0].Luid := SeNameValue; - tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; - if not AdjustTokenPrivileges(hToken, False, tkp, SizeOf(tkp), tkp, ReturnLength) then begin - ErrorCode := GetLastError; - Writeln('[-] AdjustTokenPrivileges error (code ' + IntToStr(ErrorCode) + ').'); - Exit; - end; - Result := True; -end; - -procedure KillProcess(PID: DWORD); -var - hProc: THandle; - Code: DWORD; -begin - hProc := OpenProcess(PROCESS_TERMINATE, False, PID); - if hProc = 0 then - begin - Code := GetLastError; - Writeln('[-] OpenProcess error (code ', Code, ').'); - Halt(Code); - end; - if not TerminateProcess(hProc, 0) then - begin - CloseHandle(hProc); - Code := GetLastError; - Writeln('[-] TerminateProcess error (code ', Code, ').'); - Halt(Code); - end; - CloseHandle(hProc); -end; - -function ExecWait(Cmdline: String): Boolean; -var - si: STARTUPINFO; - pi: PROCESS_INFORMATION; -begin - Result := False; - ZeroMemory(@si, sizeof(si)); - si.cb := sizeof(si); - UniqueString(Cmdline); - if not CreateProcess(nil, PWideChar(Cmdline), nil, nil, True, 0, nil, nil, si, pi) then begin - Writeln('[-] CreateProcess error (code: ', GetLastError, ').'); - Exit; - end; - CloseHandle(pi.hThread); - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - Result := True; -end; - -function ExpandPath(Path: String): String; -var - Str: Array[0..511] of Char; -begin - Result := ''; - FillChar(Str, 512, 0); - if Arch = 64 then - Path := StringReplace(Path, '%ProgramFiles%', '%ProgramW6432%', [rfReplaceAll, rfIgnoreCase]); - if ExpandEnvironmentStrings(PWideChar(Path), Str, 512) > 0 then - Result := Str; -end; - -procedure SetWrapperDll; -var - Reg: TRegistry; - Code: DWORD; -begin - if Arch = 64 then - Reg := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY) - else - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\TermService\Parameters', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteExpandString('ServiceDll', WrapPath); - if (Arch = 64) and (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 0) then - ExecWait('"'+ExpandPath('%SystemRoot%')+'\system32\reg.exe" add HKLM\SYSTEM\CurrentControlSet\Services\TermService\Parameters /v ServiceDll /t REG_EXPAND_SZ /d "'+WrapPath+'" /f'); - except - Writeln('[-] WriteExpandString error.'); - Halt(ERROR_ACCESS_DENIED); - end; - - Reg.CloseKey; - Reg.Free; -end; - -procedure ResetServiceDll; -var - Reg: TRegistry; - Code: DWORD; -begin - if Arch = 64 then - Reg := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY) - else - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\TermService\Parameters', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteExpandString('ServiceDll', '%SystemRoot%\System32\termsrv.dll'); - except - Writeln('[-] WriteExpandString error.'); - Halt(ERROR_ACCESS_DENIED); - end; - Reg.CloseKey; - Reg.Free; -end; - -procedure ExtractRes(ResName, Path: String); -var - ResStream: TResourceStream; -begin - ResStream := TResourceStream.Create(HInstance, ResName, RT_RCDATA); - try - ResStream.SaveToFile(Path); - except - Writeln('[-] Failed to extract file.'); - Writeln('[*] Resource name: ' + ResName); - Writeln('[*] Destination path: ' + Path); - ResStream.Free; - Exit; - end; - Writeln('[+] Extracted ', ResName, ' -> ', Path); - ResStream.Free; -end; - -function ExtractResText(ResName: String): String; -var - ResStream: TResourceStream; - Str: TStringList; -begin - ResStream := TResourceStream.Create(HInstance, ResName, RT_RCDATA); - Str := TStringList.Create; - try - Str.LoadFromStream(ResStream); - except - - end; - ResStream.Free; - Result := Str.Text; - Str.Free; -end; - -function GitINIFile(var Content: String): Boolean; -const - URL = 'https://raw.githubusercontent.com/stascorp/rdpwrap/master/res/rdpwrap.ini'; -var - NetHandle: HINTERNET; - UrlHandle: HINTERNET; - Str: String; - Buf: Array[0..1023] of Byte; - BytesRead: DWORD; -begin - Result := False; - Content := ''; - NetHandle := InternetOpen('RDP Wrapper Update', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); - if not Assigned(NetHandle) then - Exit; - UrlHandle := InternetOpenUrl(NetHandle, PChar(URL), nil, 0, INTERNET_FLAG_RELOAD, 0); - if not Assigned(UrlHandle) then - begin - InternetCloseHandle(NetHandle); - Exit; - end; - repeat - InternetReadFile(UrlHandle, @Buf[0], SizeOf(Buf), BytesRead); - SetString(Str, PAnsiChar(@Buf[0]), BytesRead); - Content := Content + Str; - until BytesRead = 0; - InternetCloseHandle(UrlHandle); - InternetCloseHandle(NetHandle); - Result := True; -end; - -procedure GrantSidFullAccess(Path, SID: String); -var - p_SID: PSID; - pDACL: PACL; - EA: EXPLICIT_ACCESS; - Code, Result: DWORD; -begin - p_SID := nil; - if not ConvertStringSidToSid(PChar(SID), p_SID) then - begin - Code := GetLastError; - Writeln('[-] ConvertStringSidToSid error (code ', Code, ').'); - Exit; - end; - EA.grfAccessPermissions := GENERIC_ALL; - EA.grfAccessMode := GRANT_ACCESS; - EA.grfInheritance := SUB_CONTAINERS_AND_OBJECTS_INHERIT; - EA.Trustee.pMultipleTrustee := nil; - EA.Trustee.MultipleTrusteeOperation := NO_MULTIPLE_TRUSTEE; - EA.Trustee.TrusteeForm := TRUSTEE_IS_SID; - EA.Trustee.TrusteeType := TRUSTEE_IS_WELL_KNOWN_GROUP; - EA.Trustee.ptstrName := p_SID; - - Result := SetEntriesInAcl(1, @EA, nil, pDACL); - if Result = ERROR_SUCCESS then - begin - if SetNamedSecurityInfo(pchar(Path), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, pDACL, nil) <> ERROR_SUCCESS then - begin - Code := GetLastError; - Writeln('[-] SetNamedSecurityInfo error (code ', Code, ').'); - end; - LocalFree(Cardinal(pDACL)); - end - else begin - Code := GetLastError; - Writeln('[-] SetEntriesInAcl error (code ', Code, ').'); - end; -end; - -procedure ExtractFiles; -var - RDPClipRes, RfxvmtRes, S: String; - OnlineINI: TStringList; -begin - if not DirectoryExists(ExtractFilePath(ExpandPath(WrapPath))) then - if ForceDirectories(ExtractFilePath(ExpandPath(WrapPath))) then begin - S := ExtractFilePath(ExpandPath(WrapPath)); - Writeln('[+] Folder created: ', S); - GrantSidFullAccess(S, 'S-1-5-18'); // Local System account - GrantSidFullAccess(S, 'S-1-5-6'); // Service group - end - else begin - Writeln('[-] ForceDirectories error.'); - Writeln('[*] Path: ', ExtractFilePath(ExpandPath(WrapPath))); - Halt(0); - end; - if Online then - begin - Writeln('[*] Downloading latest INI file...'); - OnlineINI := TStringList.Create; - if GitINIFile(S) then begin - OnlineINI.Text := S; - S := ExtractFilePath(ExpandPath(WrapPath)) + 'rdpwrap.ini'; - OnlineINI.SaveToFile(S); - Writeln('[+] Latest INI file -> ', S); - end - else - begin - Writeln('[-] Failed to get online INI file, using built-in.'); - Online := False; - end; - OnlineINI.Free; - end; - if not Online then - begin - S := ExtractFilePath(ParamStr(0)) + 'rdpwrap.ini'; - if FileExists(S) then - begin - OnlineINI := TStringList.Create; - OnlineINI.LoadFromFile(S); - S := ExtractFilePath(ExpandPath(WrapPath)) + 'rdpwrap.ini'; - OnlineINI.SaveToFile(S); - Writeln('[+] Current INI file -> ', S); - OnlineINI.Free; - end else - ExtractRes('config', ExtractFilePath(ExpandPath(WrapPath)) + 'rdpwrap.ini'); - end; - - RDPClipRes := ''; - RfxvmtRes := ''; - case Arch of - 32: begin - ExtractRes('rdpw32', ExpandPath(WrapPath)); - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 0) then - RDPClipRes := 'rdpclip6032'; - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 1) then - RDPClipRes := 'rdpclip6132'; - if (FV.Version.w.Major = 10) and (FV.Version.w.Minor = 0) then - RfxvmtRes := 'rfxvmt32'; - end; - 64: begin - ExtractRes('rdpw64', ExpandPath(WrapPath)); - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 0) then - RDPClipRes := 'rdpclip6064'; - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 1) then - RDPClipRes := 'rdpclip6164'; - if (FV.Version.w.Major = 10) and (FV.Version.w.Minor = 0) then - RfxvmtRes := 'rfxvmt64'; - end; - end; - if RDPClipRes <> '' then - if not FileExists(ExpandPath('%SystemRoot%\System32\rdpclip.exe')) then - ExtractRes(RDPClipRes, ExpandPath('%SystemRoot%\System32\rdpclip.exe')); - if RfxvmtRes <> '' then - if not FileExists(ExpandPath('%SystemRoot%\System32\rfxvmt.dll')) then - ExtractRes(RfxvmtRes, ExpandPath('%SystemRoot%\System32\rfxvmt.dll')); -end; - -procedure DeleteFiles; -var - Code: DWORD; - FullPath, Path: String; -begin - FullPath := ExpandPath(TermServicePath); - Path := ExtractFilePath(FullPath); - - if not DeleteFile(PWideChar(Path + 'rdpwrap.ini')) then - begin - Code := GetLastError; - Writeln('[-] DeleteFile error (code ', Code, ').'); - Exit; - end; - Writeln('[+] Removed file: ', Path + 'rdpwrap.ini'); - - if not DeleteFile(PWideChar(FullPath)) then - begin - Code := GetLastError; - Writeln('[-] DeleteFile error (code ', Code, ').'); - Exit; - end; - Writeln('[+] Removed file: ', FullPath); - - if not RemoveDirectory(PWideChar(ExtractFilePath(ExpandPath(TermServicePath)))) then - begin - Code := GetLastError; - Writeln('[-] RemoveDirectory error (code ', Code, ').'); - Exit; - end; - Writeln('[+] Removed folder: ', ExtractFilePath(ExpandPath(TermServicePath))); -end; - -function GetFileVersion(const FileName: TFileName; var FileVersion: FILE_VERSION): Boolean; -type - VS_VERSIONINFO = record - wLength, wValueLength, wType: Word; - szKey: Array[1..16] of WideChar; - Padding1: Word; - Value: VS_FIXEDFILEINFO; - Padding2, Children: Word; - end; - PVS_VERSIONINFO = ^VS_VERSIONINFO; -const - VFF_DEBUG = 1; - VFF_PRERELEASE = 2; - VFF_PRIVATE = 8; - VFF_SPECIAL = 32; -var - hFile: HMODULE; - hResourceInfo: HRSRC; - VersionInfo: PVS_VERSIONINFO; -begin - Result := False; - - hFile := LoadLibraryEx(PWideChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE); - if hFile = 0 then - Exit; - - hResourceInfo := FindResource(hFile, PWideChar(1), PWideChar($10)); - if hResourceInfo = 0 then - Exit; - - VersionInfo := Pointer(LoadResource(hFile, hResourceInfo)); - if VersionInfo = nil then - Exit; - - FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS; - FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16); - FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS); - FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG; - FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE; - FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE; - FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL; - - FreeLibrary(hFile); - Result := True; -end; - -procedure CheckTermsrvVersion; -var - SuppLvl: Byte; - VerTxt: String; - - procedure UpdateMsg; - begin - Writeln('Try running "update.bat" or "RDPWInst -w" to download latest INI file.'); - Writeln('If it doesn''t help, send your termsrv.dll to project developer for support.'); - end; -begin - GetFileVersion(ExpandPath(TermServicePath), FV); - VerTxt := Format('%d.%d.%d.%d', - [FV.Version.w.Major, FV.Version.w.Minor, FV.Release, FV.Build]); - Writeln('[*] Terminal Services version: ', VerTxt); - - if (FV.Version.w.Major = 5) and (FV.Version.w.Minor = 1) then - begin - if Arch = 32 then - begin - Writeln('[!] Windows XP is not supported.'); - Writeln('You may take a look at RDP Realtime Patch by Stas''M for Windows XP'); - Writeln('Link: http://stascorp.com/load/1-1-0-62'); - end; - if Arch = 64 then - Writeln('[!] Windows XP 64-bit Edition is not supported.'); - Exit; - end; - if (FV.Version.w.Major = 5) and (FV.Version.w.Minor = 2) then - begin - if Arch = 32 then - Writeln('[!] Windows Server 2003 is not supported.'); - if Arch = 64 then - Writeln('[!] Windows Server 2003 or XP 64-bit Edition is not supported.'); - Exit; - end; - SuppLvl := 0; - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 0) then begin - SuppLvl := 1; - if (Arch = 32) and (FV.Release = 6000) and (FV.Build = 16386) then begin - Writeln('[!] This version of Terminal Services may crash on logon attempt.'); - Writeln('It''s recommended to upgrade to Service Pack 1 or higher.'); - end; - end; - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 1) then - SuppLvl := 1; - if Pos('[' + VerTxt + ']', ExtractResText('config')) > 0 then - SuppLvl := 2; - case SuppLvl of - 0: begin - Writeln('[-] This version of Terminal Services is not supported.'); - UpdateMsg; - end; - 1: begin - Writeln('[!] This version of Terminal Services is supported partially.'); - Writeln('It means you may have some limitations such as only 2 concurrent sessions.'); - UpdateMsg; - end; - 2: begin - Writeln('[+] This version of Terminal Services is fully supported.'); - end; - end; -end; - -procedure CheckTermsrvDependencies; -const - CertPropSvc = 'CertPropSvc'; - SessionEnv = 'SessionEnv'; -begin - if SvcGetStart(CertPropSvc) = SERVICE_DISABLED then - SvcConfigStart(CertPropSvc, SERVICE_DEMAND_START); - if SvcGetStart(SessionEnv) = SERVICE_DISABLED then - SvcConfigStart(SessionEnv, SERVICE_DEMAND_START); -end; - -procedure TSConfigRegistry(Enable: Boolean); -var - Reg: TRegistry; - Code: DWORD; -begin - if Arch = 64 then - Reg := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY) - else - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteBool('fDenyTSConnections', not Enable); - except - Writeln('[-] WriteBool error.'); - Halt(ERROR_ACCESS_DENIED); - end; - Reg.CloseKey; - if Enable then - begin - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\Licensing Core', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteBool('EnableConcurrentSessions', True); - except - Writeln('[-] WriteBool error.'); - Halt(ERROR_ACCESS_DENIED); - end; - Reg.CloseKey; - - if not Reg.OpenKey('\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteBool('AllowMultipleTSSessions', True); - except - Writeln('[-] WriteBool error.'); - Halt(ERROR_ACCESS_DENIED); - end; - Reg.CloseKey; - - if not Reg.KeyExists('\SYSTEM\CurrentControlSet\Control\Terminal Server\AddIns') then begin - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\AddIns', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - Reg.CloseKey; - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\AddIns\Clip Redirector', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteString('Name', 'RDPClip'); - Reg.WriteInteger('Type', 3); - except - Writeln('[-] WriteInteger error.'); - Halt(ERROR_ACCESS_DENIED); - end; - Reg.CloseKey; - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\AddIns\DND Redirector', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteString('Name', 'RDPDND'); - Reg.WriteInteger('Type', 3); - except - Writeln('[-] WriteInteger error.'); - Halt(ERROR_ACCESS_DENIED); - end; - Reg.CloseKey; - if not Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\AddIns\Dynamic VC', True) then - begin - Code := GetLastError; - Writeln('[-] OpenKey error (code ', Code, ').'); - Halt(Code); - end; - try - Reg.WriteInteger('Type', -1); - except - Writeln('[-] WriteInteger error.'); - Halt(ERROR_ACCESS_DENIED); - end; - Reg.CloseKey; - end; - end; - Reg.Free; -end; - -procedure TSConfigFirewall(Enable: Boolean); -begin - if Enable then - begin - ExecWait('netsh advfirewall firewall add rule name="Remote Desktop" dir=in protocol=tcp localport=3389 profile=any action=allow'); - ExecWait('netsh advfirewall firewall add rule name="Remote Desktop" dir=in protocol=udp localport=3389 profile=any action=allow'); - end else - ExecWait('netsh advfirewall firewall delete rule name="Remote Desktop"'); -end; - -function CheckINIDate(Filename, Content: String; var Date: Integer): Boolean; -var - Str: TStringList; - I: Integer; -begin - Result := False; - Str := TStringList.Create; - if Filename <> '' then begin - try - Str.LoadFromFile(Filename); - except - Writeln('[-] Failed to read INI file.'); - Exit; - end; - end else - Str.Text := Content; - for I := 0 to Str.Count - 1 do - if Pos('Updated=', Str[I]) = 1 then - Break; - if I >= Str.Count then begin - Writeln('[-] Failed to check INI date.'); - Exit; - end; - Content := StringReplace(Str[I], 'Updated=', '', []); - Content := StringReplace(Content, '-', '', [rfReplaceAll]); - Str.Free; - try - Date := StrToInt(Content); - except - Writeln('[-] Wrong INI date format.'); - Exit; - end; - Result := True; -end; - -procedure CheckUpdate; -var - INIPath, S: String; - Str: TStringList; - I, OldDate, NewDate: Integer; -begin - INIPath := ExtractFilePath(ExpandPath(TermServicePath)) + 'rdpwrap.ini'; - if not CheckINIDate(INIPath, '', OldDate) then - Halt(ERROR_ACCESS_DENIED); - Writeln('[*] Current update date: ', - Format('%d.%.2d.%.2d', [OldDate div 10000, OldDate div 100 mod 100, OldDate mod 100])); - - if not GitINIFile(S) then begin - Writeln('[-] Failed to download latest INI from GitHub.'); - Halt(ERROR_ACCESS_DENIED); - end; - if not CheckINIDate('', S, NewDate) then - Halt(ERROR_ACCESS_DENIED); - Writeln('[*] Latest update date: ', - Format('%d.%.2d.%.2d', [NewDate div 10000, NewDate div 100 mod 100, NewDate mod 100])); - - if NewDate = OldDate then - Writeln('[*] Everything is up to date.') - else - if NewDate > OldDate then begin - Writeln('[+] New update is available, updating...'); - - CheckTermsrvProcess; - - Writeln('[*] Terminating service...'); - AddPrivilege('SeDebugPrivilege'); - KillProcess(TermServicePID); - Sleep(1000); - - if Length(ShareSvc) > 0 then - for I := 0 to Length(ShareSvc) - 1 do - SvcStart(ShareSvc[I]); - Sleep(500); - - Str := TStringList.Create; - Str.Text := S; - try - Str.SaveToFile(INIPath); - except - Writeln('[-] Failed to write INI file.'); - Halt(ERROR_ACCESS_DENIED); - end; - Str.Free; - - SvcStart(TermService); - - Writeln('[+] Update completed.'); - end else - Writeln('[*] Your INI file is newer than public file. Are you a developer? :)'); -end; - -var - I: Integer; -begin - Writeln('RDP Wrapper Library v1.6.2'); - Writeln('Installer v2.6'); - Writeln('Copyright (C) Stas''M Corp. 2018'); - Writeln(''); - - if (ParamCount < 1) - or ( - (ParamStr(1) <> '-l') - and (ParamStr(1) <> '-i') - and (ParamStr(1) <> '-w') - and (ParamStr(1) <> '-u') - and (ParamStr(1) <> '-r') - ) then - begin - Writeln('USAGE:'); - Writeln('RDPWInst.exe [-l|-i[-s][-o]|-w|-u[-k]|-r]'); - Writeln(''); - Writeln('-l display the license agreement'); - Writeln('-i install wrapper to Program Files folder (default)'); - Writeln('-i -s install wrapper to System32 folder'); - Writeln('-i -o online install mode (loads latest INI file)'); - Writeln('-w get latest update for INI file'); - Writeln('-u uninstall wrapper'); - Writeln('-u -k uninstall wrapper and keep settings'); - Writeln('-r force restart Terminal Services'); - Exit; - end; - - if ParamStr(1) = '-l' then - begin - Writeln(ExtractResText('license')); - Exit; - end; - - if not CheckWin32Version(6,0) then - begin - Writeln('[-] Unsupported Windows version:'); - Writeln(' only >= 6.0 (Vista, Server 2008 and newer) are supported.'); - Exit; - end; - - if not SupportedArchitecture then - begin - Writeln('[-] Unsupported processor architecture.'); - Exit; - end; - - CheckInstall; - - if ParamStr(1) = '-i' then - begin - if Installed then - begin - Writeln('[*] RDP Wrapper Library is already installed.'); - Halt(ERROR_INVALID_FUNCTION); - end; - Writeln('[*] Notice to user:'); - Writeln(' - By using all or any portion of this software, you are agreeing'); - Writeln(' to be bound by all the terms and conditions of the license agreement.'); - Writeln(' - To read the license agreement, run the installer with -l parameter.'); - Writeln(' - If you do not agree to any terms of the license agreement,'); - Writeln(' do not use the software.'); - - Writeln('[*] Installing...'); - if ParamStr(2) = '-s' then - WrapPath := '%SystemRoot%\system32\rdpwrap.dll' - else - WrapPath := '%ProgramFiles%\RDP Wrapper\rdpwrap.dll'; - - if Arch = 64 then - DisableWowRedirection; - - CheckTermsrvVersion; - CheckTermsrvProcess; - - Writeln('[*] Extracting files...'); - Online := (ParamStr(2) = '-o') or (ParamStr(3) = '-o'); - ExtractFiles; - - Writeln('[*] Configuring service library...'); - SetWrapperDll; - - Writeln('[*] Checking dependencies...'); - CheckTermsrvDependencies; - - Writeln('[*] Terminating service...'); - AddPrivilege('SeDebugPrivilege'); - KillProcess(TermServicePID); - Sleep(1000); - - if Length(ShareSvc) > 0 then - for I := 0 to Length(ShareSvc) - 1 do - SvcStart(ShareSvc[I]); - Sleep(500); - SvcStart(TermService); - Sleep(500); - - Writeln('[*] Configuring registry...'); - TSConfigRegistry(True); - Writeln('[*] Configuring firewall...'); - TSConfigFirewall(True); - - Writeln('[+] Successfully installed.'); - - if Arch = 64 then - RevertWowRedirection; - end; - if ParamStr(1) = '-u' then - begin - if not Installed then - begin - Writeln('[*] RDP Wrapper Library is not installed.'); - Halt(ERROR_INVALID_FUNCTION); - end; - Writeln('[*] Uninstalling...'); - - if Arch = 64 then - DisableWowRedirection; - - CheckTermsrvProcess; - - Writeln('[*] Resetting service library...'); - ResetServiceDll; - - Writeln('[*] Terminating service...'); - AddPrivilege('SeDebugPrivilege'); - KillProcess(TermServicePID); - Sleep(1000); - - Writeln('[*] Removing files...'); - DeleteFiles; - - if Length(ShareSvc) > 0 then - for I := 0 to Length(ShareSvc) - 1 do - SvcStart(ShareSvc[I]); - Sleep(500); - SvcStart(TermService); - Sleep(500); - - if ParamStr(2) <> '-k' then - begin - Writeln('[*] Configuring registry...'); - TSConfigRegistry(False); - Writeln('[*] Configuring firewall...'); - TSConfigFirewall(False); - end; - - if Arch = 64 then - RevertWowRedirection; - - Writeln('[+] Successfully uninstalled.'); - end; - - if ParamStr(1) = '-w' then - begin - if not Installed then - begin - Writeln('[*] RDP Wrapper Library is not installed.'); - Halt(ERROR_INVALID_FUNCTION); - end; - Writeln('[*] Checking for updates...'); - CheckUpdate; - end; - - if ParamStr(1) = '-r' then - begin - Writeln('[*] Restarting...'); - - CheckTermsrvProcess; - - Writeln('[*] Terminating service...'); - AddPrivilege('SeDebugPrivilege'); - KillProcess(TermServicePID); - Sleep(1000); - - if Length(ShareSvc) > 0 then - for I := 0 to Length(ShareSvc) - 1 do - SvcStart(ShareSvc[I]); - Sleep(500); - SvcStart(TermService); - - Writeln('[+] Done.'); - end; -end. diff --git a/src-installer/RDPWInst.dproj b/src-installer/RDPWInst.dproj deleted file mode 100644 index 6afda06..0000000 --- a/src-installer/RDPWInst.dproj +++ /dev/null @@ -1,106 +0,0 @@ - - - {AF9BEAA3-99CD-4B2E-BE67-3F3BD27B961A} - 12.0 - RDPWInst.dpr - Release - DCC32 - - - true - - - true - Base - true - - - true - Base - true - - - ..\bin\ - WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias) - ..\bin\RDPWInst.exe - 00400000 - x86 - - - false - RELEASE;$(DCC_Define) - 0 - false - - - DEBUG;$(DCC_Define) - - - - MainSource - - - Base - - - Cfg_1 - Base - - - Cfg_2 - Base - - - - - Delphi.Personality.12 - - - - - False - True - False - -w - - - False - False - 1 - 0 - 0 - 0 - False - False - False - False - False - 1049 - 1251 - - - - - 1.0.0.0 - - - - - - 1.0.0.0 - - - - Embarcadero C++Builder Office 2000 Servers Package - Embarcadero C++Builder Office XP Servers Package - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - - - RDPWInst.dpr - - - - 12 - - diff --git a/src-installer/resource.res b/src-installer/resource.res deleted file mode 100644 index 0e896e1..0000000 Binary files a/src-installer/resource.res and /dev/null differ diff --git a/src-rdpcheck/MainUnit.dfm b/src-rdpcheck/MainUnit.dfm deleted file mode 100644 index 2533973..0000000 --- a/src-rdpcheck/MainUnit.dfm +++ /dev/null @@ -1,29 +0,0 @@ -object Frm: TFrm - Left = 0 - Top = 0 - BorderIcons = [biSystemMenu, biMinimize] - BorderStyle = bsSingle - Caption = 'Local RDP Checker' - ClientHeight = 480 - ClientWidth = 640 - Color = clBtnFace - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'Tahoma' - Font.Style = [] - OldCreateOrder = False - Position = poDesktopCenter - OnCreate = FormCreate - PixelsPerInch = 96 - TextHeight = 13 - object RDP: TMsRdpClient2 - Left = 0 - Top = 0 - Width = 640 - Height = 480 - TabOrder = 0 - OnDisconnected = RDPDisconnected - ControlData = {0003000008000200000000000B0000000B000000} - end -end diff --git a/src-rdpcheck/MainUnit.pas b/src-rdpcheck/MainUnit.pas deleted file mode 100644 index 3c4655f..0000000 --- a/src-rdpcheck/MainUnit.pas +++ /dev/null @@ -1,160 +0,0 @@ -{ - Copyright 2015 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -unit MainUnit; - -interface - -uses - Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, - Dialogs, OleServer, MSTSCLib_TLB, OleCtrls, Registry; - -type - TFrm = class(TForm) - RDP: TMsRdpClient2; - procedure RDPDisconnected(ASender: TObject; discReason: Integer); - procedure FormCreate(Sender: TObject); - private - { Private declarations } - public - { Public declarations } - end; - -var - Frm: TFrm; - SecurityLayer, UserAuthentication: DWORD; - -implementation - -{$R *.dfm} - -procedure TFrm.FormCreate(Sender: TObject); -var - Reg: TRegistry; -begin - RDP.DisconnectedText := 'Disconnected.'; - RDP.ConnectingText := 'Connecting...'; - RDP.ConnectedStatusText := 'Connected.'; - RDP.UserName := ''; - RDP.Server := '127.0.0.2'; - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - - if Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp', True) then - begin - try - SecurityLayer := Reg.ReadInteger('SecurityLayer'); - UserAuthentication := Reg.ReadInteger('UserAuthentication'); - Reg.WriteInteger('SecurityLayer', 0); - Reg.WriteInteger('UserAuthentication', 0); - except - - end; - Reg.CloseKey; - end; - - if Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp') then begin - try - RDP.AdvancedSettings2.RDPPort := Reg.ReadInteger('PortNumber'); - except - - end; - Reg.CloseKey; - end; - Reg.Free; - Sleep(1000); - RDP.Connect; -end; - -procedure TFrm.RDPDisconnected(ASender: TObject; discReason: Integer); -var - ErrStr: String; - Reg: TRegistry; -begin - case discReason of - 1: ErrStr := 'Local disconnection.'; - 2: ErrStr := 'Disconnected by user.'; - 3: ErrStr := 'Disconnected by server.'; - $904: ErrStr := 'Socket closed.'; - $C08: ErrStr := 'Decompress error.'; - $108: ErrStr := 'Connection timed out.'; - $C06: ErrStr := 'Decryption error.'; - $104: ErrStr := 'DNS name lookup failure.'; - $508: ErrStr := 'DNS lookup failed.'; - $B06: ErrStr := 'Encryption error.'; - $604: ErrStr := 'Windows Sockets gethostbyname() call failed.'; - $208: ErrStr := 'Host not found error.'; - $408: ErrStr := 'Internal error.'; - $906: ErrStr := 'Internal security error.'; - $A06: ErrStr := 'Internal security error.'; - $506: ErrStr := 'The encryption method specified is not valid.'; - $804: ErrStr := 'Bad IP address specified.'; - $606: ErrStr := 'Server security data is not valid.'; - $406: ErrStr := 'Security data is not valid.'; - $308: ErrStr := 'The IP address specified is not valid.'; - $808: ErrStr := 'License negotiation failed.'; - $908: ErrStr := 'Licensing time-out.'; - $106: ErrStr := 'Out of memory.'; - $206: ErrStr := 'Out of memory.'; - $306: ErrStr := 'Out of memory.'; - $706: ErrStr := 'Failed to unpack server certificate.'; - $204: ErrStr := 'Socket connection failed.'; - $404: ErrStr := 'Windows Sockets recv() call failed.'; - $704: ErrStr := 'Time-out occurred.'; - $608: ErrStr := 'Internal timer error.'; - $304: ErrStr := 'Windows Sockets send() call failed.'; - $B07: ErrStr := 'The account is disabled.'; - $E07: ErrStr := 'The account is expired.'; - $D07: ErrStr := 'The account is locked out.'; - $C07: ErrStr := 'The account is restricted.'; - $1B07: ErrStr := 'The received certificate is expired.'; - $1607: ErrStr := 'The policy does not support delegation of credentials to the target server.'; - $2107: ErrStr := 'The server authentication policy does not allow connection requests using saved credentials. The user must enter new credentials.'; - $807: ErrStr := 'Login failed.'; - $1807: ErrStr := 'No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could be unreachable, or there might have been a trust relationship failure.'; - $A07: ErrStr := 'The specified user has no account.'; - $F07: ErrStr := 'The password is expired.'; - $1207: ErrStr := 'The user password must be changed before logging on for the first time.'; - $1707: ErrStr := 'Delegation of credentials to the target server is not allowed unless mutual authentication has been achieved.'; - $2207: ErrStr := 'The smart card is blocked.'; - $1C07: ErrStr := 'An incorrect PIN was presented to the smart card.'; - $B09: ErrStr := 'Network Level Authentication is required, run RDPCheck as administrator.'; - $708: ErrStr := 'RDP is working, but the client doesn''t allow loopback connections. Try to connect to your PC from another device in the network.'; - else ErrStr := 'Unknown code 0x'+IntToHex(discReason, 1); - end; - if (discReason > 2) then - MessageBox(Handle, PWideChar(ErrStr), 'Disconnected', mb_Ok or mb_IconError); - - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - - if Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp', True) then - begin - try - Reg.WriteInteger('SecurityLayer', SecurityLayer); - Reg.WriteInteger('UserAuthentication', UserAuthentication); - except - - end; - Reg.CloseKey; - end; - - Reg.Free; - - Halt(0); -end; - -end. diff --git a/src-rdpcheck/RDP.ico b/src-rdpcheck/RDP.ico deleted file mode 100644 index 05a7b71..0000000 Binary files a/src-rdpcheck/RDP.ico and /dev/null differ diff --git a/src-rdpcheck/RDPCheck.dpr b/src-rdpcheck/RDPCheck.dpr deleted file mode 100644 index 5f4c5ad..0000000 --- a/src-rdpcheck/RDPCheck.dpr +++ /dev/null @@ -1,31 +0,0 @@ -{ - Copyright 2014 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -program RDPCheck; - -uses - Forms, - MainUnit in 'MainUnit.pas' {Frm}; - -{$R *.res} - -begin - Application.Initialize; - Application.MainFormOnTaskbar := True; - Application.Title := 'Local RDP Checker'; - Application.CreateForm(TFrm, Frm); - Application.Run; -end. diff --git a/src-rdpcheck/RDPCheck.dproj b/src-rdpcheck/RDPCheck.dproj deleted file mode 100644 index c5027ce..0000000 --- a/src-rdpcheck/RDPCheck.dproj +++ /dev/null @@ -1,108 +0,0 @@ - - - {90AE83F6-26B8-45D4-92FE-CF4ACCDE9F68} - 12.0 - RDPCheck.dpr - Release - DCC32 - - - true - - - true - Base - true - - - true - Base - true - - - ..\bin\ - WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias) - ..\bin\RDPCheck.exe - 00400000 - x86 - - - false - RELEASE;$(DCC_Define) - 0 - false - - - DEBUG;$(DCC_Define) - - - - MainSource - - -
Frm
-
- - Base - - - Cfg_1 - Base - - - Cfg_2 - Base - -
- - - Delphi.Personality.12 - - - - - False - True - False - - - True - False - 2 - 2 - 0 - 0 - False - False - False - False - False - 1033 - 1252 - - - Stas'M Corp. - Local RDP Checker - 2.2.0.0 - RDPCheck - Copyright © Stas'M Corp. 2015 - Stas'M Corp. - RDPCheck.exe - RDP Host Support - 1.6.0.0 - http://stascorp.com - - - Embarcadero C++Builder Office 2000 Servers Package - Embarcadero C++Builder Office XP Servers Package - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - - - RDPCheck.dpr - - - - 12 - -
diff --git a/src-rdpcheck/RDPCheck.res b/src-rdpcheck/RDPCheck.res deleted file mode 100644 index 724bf2e..0000000 Binary files a/src-rdpcheck/RDPCheck.res and /dev/null differ diff --git a/src-rdpconfig/LicenseUnit.dfm b/src-rdpconfig/LicenseUnit.dfm deleted file mode 100644 index fae5719..0000000 --- a/src-rdpconfig/LicenseUnit.dfm +++ /dev/null @@ -1,47 +0,0 @@ -object LicenseForm: TLicenseForm - Left = 0 - Top = 0 - BorderIcons = [] - BorderStyle = bsDialog - Caption = 'License Agreement' - ClientHeight = 344 - ClientWidth = 386 - Color = clBtnFace - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'Tahoma' - Font.Style = [] - OldCreateOrder = False - Position = poOwnerFormCenter - PixelsPerInch = 96 - TextHeight = 13 - object mText: TMemo - Left = 8 - Top = 8 - Width = 370 - Height = 297 - ReadOnly = True - ScrollBars = ssBoth - TabOrder = 0 - WordWrap = False - end - object bAccept: TButton - Left = 115 - Top = 311 - Width = 75 - Height = 25 - Caption = '&Accept' - ModalResult = 1 - TabOrder = 1 - end - object bDecline: TButton - Left = 196 - Top = 311 - Width = 75 - Height = 25 - Caption = '&Decline' - ModalResult = 2 - TabOrder = 2 - end -end diff --git a/src-rdpconfig/LicenseUnit.pas b/src-rdpconfig/LicenseUnit.pas deleted file mode 100644 index a44a2ad..0000000 --- a/src-rdpconfig/LicenseUnit.pas +++ /dev/null @@ -1,43 +0,0 @@ -{ - Copyright 2014 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -unit LicenseUnit; - -interface - -uses - Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, - Dialogs, StdCtrls; - -type - TLicenseForm = class(TForm) - mText: TMemo; - bAccept: TButton; - bDecline: TButton; - private - { Private declarations } - public - { Public declarations } - end; - -var - LicenseForm: TLicenseForm; - -implementation - -{$R *.dfm} - -end. diff --git a/src-rdpconfig/MainUnit.dfm b/src-rdpconfig/MainUnit.dfm deleted file mode 100644 index c077af1..0000000 --- a/src-rdpconfig/MainUnit.dfm +++ /dev/null @@ -1,241 +0,0 @@ -object MainForm: TMainForm - Left = 0 - Top = 0 - BorderStyle = bsDialog - Caption = 'RDP Wrapper Configuration' - ClientHeight = 314 - ClientWidth = 404 - Color = clBtnFace - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'Tahoma' - Font.Style = [] - OldCreateOrder = False - Position = poDesktopCenter - OnCloseQuery = FormCloseQuery - OnCreate = FormCreate - OnDestroy = FormDestroy - PixelsPerInch = 96 - TextHeight = 13 - object bOK: TButton - Left = 40 - Top = 281 - Width = 75 - Height = 25 - Caption = 'OK' - ModalResult = 1 - TabOrder = 4 - OnClick = bOKClick - end - object bCancel: TButton - Left = 121 - Top = 281 - Width = 75 - Height = 25 - Caption = 'Cancel' - ModalResult = 2 - TabOrder = 5 - OnClick = bCancelClick - end - object bApply: TButton - Left = 202 - Top = 281 - Width = 75 - Height = 25 - Caption = 'Apply' - Enabled = False - TabOrder = 6 - OnClick = bApplyClick - end - object rgNLA: TRadioGroup - Left = 202 - Top = 89 - Width = 194 - Height = 73 - Caption = 'Authentication Mode' - Items.Strings = ( - 'GUI Authentication Only' - 'Default RDP Authentication' - 'Network Level Authentication') - TabOrder = 2 - OnClick = cbAllowTSConnectionsClick - end - object rgShadow: TRadioGroup - Left = 202 - Top = 168 - Width = 194 - Height = 105 - Caption = 'Session Shadowing Mode' - Items.Strings = ( - 'Disable Shadowing' - 'Full access with user'#39's permission' - 'Full access without permission' - 'View only with user'#39's permission' - 'View only without permission') - TabOrder = 3 - OnClick = cbAllowTSConnectionsClick - end - object bLicense: TButton - Left = 283 - Top = 281 - Width = 87 - Height = 25 - Caption = 'View license...' - TabOrder = 7 - OnClick = bLicenseClick - end - object gbDiag: TGroupBox - Left = 8 - Top = 6 - Width = 388 - Height = 77 - Caption = 'Diagnostics' - TabOrder = 0 - object lListener: TLabel - Left = 11 - Top = 55 - Width = 70 - Height = 13 - Caption = 'Listener state:' - end - object lService: TLabel - Left = 11 - Top = 36 - Width = 67 - Height = 13 - Caption = 'Service state:' - end - object lsListener: TLabel - Left = 91 - Top = 55 - Width = 44 - Height = 13 - Caption = 'Unknown' - end - object lsService: TLabel - Left = 91 - Top = 36 - Width = 44 - Height = 13 - Caption = 'Unknown' - end - object lsTSVer: TLabel - Left = 226 - Top = 36 - Width = 44 - Height = 13 - Caption = 'Unknown' - end - object lsWrapper: TLabel - Left = 91 - Top = 17 - Width = 44 - Height = 13 - Caption = 'Unknown' - end - object lsWrapVer: TLabel - Left = 226 - Top = 17 - Width = 44 - Height = 13 - Caption = 'Unknown' - end - object lTSVer: TLabel - Left = 202 - Top = 36 - Width = 20 - Height = 13 - Caption = 'ver.' - end - object lWrapper: TLabel - Left = 11 - Top = 17 - Width = 74 - Height = 13 - Caption = 'Wrapper state:' - end - object lWrapVer: TLabel - Left = 202 - Top = 17 - Width = 20 - Height = 13 - Caption = 'ver.' - end - object lsSuppVer: TLabel - Left = 202 - Top = 55 - Width = 70 - Height = 13 - Caption = '[support level]' - end - end - object gbGeneral: TGroupBox - Left = 8 - Top = 89 - Width = 188 - Height = 184 - Caption = 'General Settings' - TabOrder = 1 - object lRDPPort: TLabel - Left = 8 - Top = 44 - Width = 47 - Height = 13 - Caption = 'RDP port:' - end - object cbAllowTSConnections: TCheckBox - Left = 8 - Top = 18 - Width = 132 - Height = 17 - Caption = 'Enable Remote Desktop' - TabOrder = 0 - OnClick = cbAllowTSConnectionsClick - end - object cbSingleSessionPerUser: TCheckBox - Left = 8 - Top = 69 - Width = 129 - Height = 17 - Caption = 'Single session per user' - TabOrder = 2 - OnClick = cbAllowTSConnectionsClick - end - object cbHideUsers: TCheckBox - Left = 8 - Top = 92 - Width = 149 - Height = 17 - Caption = 'Hide users on logon screen' - TabOrder = 3 - OnClick = cbAllowTSConnectionsClick - end - object seRDPPort: TSpinEdit - Left = 61 - Top = 41 - Width = 62 - Height = 22 - MaxValue = 65535 - MinValue = 0 - TabOrder = 1 - Value = 0 - OnChange = seRDPPortChange - end - object cbCustomPrg: TCheckBox - Left = 8 - Top = 115 - Width = 169 - Height = 17 - Caption = 'Allow to start custom programs' - TabOrder = 4 - OnClick = cbAllowTSConnectionsClick - end - end - object Timer: TTimer - Interval = 250 - OnTimer = TimerTimer - Left = 352 - Top = 27 - end -end diff --git a/src-rdpconfig/MainUnit.pas b/src-rdpconfig/MainUnit.pas deleted file mode 100644 index 48aa051..0000000 --- a/src-rdpconfig/MainUnit.pas +++ /dev/null @@ -1,722 +0,0 @@ -{ - Copyright 2017 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -unit MainUnit; - -interface - -uses - Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, - Dialogs, StdCtrls, Spin, ExtCtrls, Registry, WinSvc; - -type - TMainForm = class(TForm) - bOK: TButton; - bCancel: TButton; - bApply: TButton; - cbSingleSessionPerUser: TCheckBox; - rgNLA: TRadioGroup; - cbAllowTSConnections: TCheckBox; - rgShadow: TRadioGroup; - seRDPPort: TSpinEdit; - lRDPPort: TLabel; - lService: TLabel; - lListener: TLabel; - lWrapper: TLabel; - lsListener: TLabel; - lsService: TLabel; - lsWrapper: TLabel; - Timer: TTimer; - lTSVer: TLabel; - lsTSVer: TLabel; - lWrapVer: TLabel; - lsWrapVer: TLabel; - bLicense: TButton; - gbDiag: TGroupBox; - lsSuppVer: TLabel; - cbHideUsers: TCheckBox; - gbGeneral: TGroupBox; - cbCustomPrg: TCheckBox; - procedure FormCreate(Sender: TObject); - procedure cbAllowTSConnectionsClick(Sender: TObject); - procedure seRDPPortChange(Sender: TObject); - procedure bApplyClick(Sender: TObject); - procedure bCancelClick(Sender: TObject); - procedure bOKClick(Sender: TObject); - procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); - procedure bLicenseClick(Sender: TObject); - procedure TimerTimer(Sender: TObject); - procedure FormDestroy(Sender: TObject); - private - { Private declarations } - public - { Public declarations } - function ExecWait(Cmdline: String): Boolean; - procedure ReadSettings; - procedure WriteSettings; - end; - FILE_VERSION = record - Version: record case Boolean of - True: (dw: DWORD); - False: (w: record - Minor, Major: Word; - end;) - end; - Release, Build: Word; - bDebug, bPrerelease, bPrivate, bSpecial: Boolean; - end; - WTS_SESSION_INFOW = record - SessionId: DWORD; - Name: packed array [0..33] of WideChar; - State: DWORD; - end; - WTS_SESSION = Array[0..0] of WTS_SESSION_INFOW; - PWTS_SESSION_INFOW = ^WTS_SESSION; - -const - winstadll = 'winsta.dll'; -var - MainForm: TMainForm; - Ready: Boolean = False; - Arch: Byte; - OldWow64RedirectionValue: LongBool; - OldPort: Word; - INI: String; - -function WinStationEnumerateW(hServer: THandle; - var ppSessionInfo: PWTS_SESSION_INFOW; var pCount: DWORD): BOOL; stdcall; - external winstadll name 'WinStationEnumerateW'; -function WinStationFreeMemory(P: Pointer): BOOL; stdcall; external winstadll; - -implementation - -{$R *.dfm} -{$R resource.res} - -uses - LicenseUnit; - -function ExpandPath(Path: String): String; -var - Str: Array[0..511] of Char; -begin - Result := ''; - FillChar(Str, 512, 0); - if Arch = 64 then - Path := StringReplace(Path, '%ProgramFiles%', '%ProgramW6432%', [rfReplaceAll, rfIgnoreCase]); - if ExpandEnvironmentStrings(PWideChar(Path), Str, 512) > 0 then - Result := Str; -end; - -function DisableWowRedirection: Boolean; -type - TFunc = function(var Wow64FsEnableRedirection: LongBool): LongBool; stdcall; -var - hModule: THandle; - Wow64DisableWow64FsRedirection: TFunc; -begin - Result := False; - hModule := GetModuleHandle(kernel32); - if hModule <> 0 then - Wow64DisableWow64FsRedirection := GetProcAddress(hModule, 'Wow64DisableWow64FsRedirection') - else - Exit; - if @Wow64DisableWow64FsRedirection <> nil then - Result := Wow64DisableWow64FsRedirection(OldWow64RedirectionValue); -end; - -function RevertWowRedirection: Boolean; -type - TFunc = function(var Wow64RevertWow64FsRedirection: LongBool): LongBool; stdcall; -var - hModule: THandle; - Wow64RevertWow64FsRedirection: TFunc; -begin - Result := False; - hModule := GetModuleHandle(kernel32); - if hModule <> 0 then - Wow64RevertWow64FsRedirection := GetProcAddress(hModule, 'Wow64RevertWow64FsRedirection') - else - Exit; - if @Wow64RevertWow64FsRedirection <> nil then - Result := Wow64RevertWow64FsRedirection(OldWow64RedirectionValue); -end; - -function GetFileVersion(const FileName: TFileName; var FileVersion: FILE_VERSION): Boolean; -type - VS_VERSIONINFO = record - wLength, wValueLength, wType: Word; - szKey: Array[1..16] of WideChar; - Padding1: Word; - Value: VS_FIXEDFILEINFO; - Padding2, Children: Word; - end; - PVS_VERSIONINFO = ^VS_VERSIONINFO; -const - VFF_DEBUG = 1; - VFF_PRERELEASE = 2; - VFF_PRIVATE = 8; - VFF_SPECIAL = 32; -var - hFile: HMODULE; - hResourceInfo: HRSRC; - VersionInfo: PVS_VERSIONINFO; -begin - Result := False; - - hFile := LoadLibraryEx(PWideChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE); - if hFile = 0 then - Exit; - - hResourceInfo := FindResource(hFile, PWideChar(1), PWideChar($10)); - if hResourceInfo = 0 then - Exit; - - VersionInfo := Pointer(LoadResource(hFile, hResourceInfo)); - if VersionInfo = nil then - Exit; - - FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS; - FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16); - FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS); - FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG; - FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE; - FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE; - FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL; - - FreeLibrary(hFile); - Result := True; -end; - -function IsWrapperInstalled(var WrapperPath: String): ShortInt; -var - TermServiceHost, - TermServicePath: String; - Reg: TRegistry; -begin - Result := -1; - WrapperPath := ''; - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - if not Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\TermService') then begin - Reg.Free; - Exit; - end; - TermServiceHost := Reg.ReadString('ImagePath'); - Reg.CloseKey; - if Pos('svchost.exe', LowerCase(TermServiceHost)) = 0 then - begin - Result := 2; - Reg.Free; - Exit; - end; - if not Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\TermService\Parameters') then - begin - Reg.Free; - Exit; - end; - TermServicePath := Reg.ReadString('ServiceDll'); - Reg.CloseKey; - Reg.Free; - if (Pos('termsrv.dll', LowerCase(TermServicePath)) = 0) - and (Pos('rdpwrap.dll', LowerCase(TermServicePath)) = 0) then - begin - Result := 2; - Exit; - end; - - if Pos('rdpwrap.dll', LowerCase(TermServicePath)) > 0 then begin - WrapperPath := TermServicePath; - Result := 1; - end else - Result := 0; -end; - -function GetTermSrvState: ShortInt; -type - SERVICE_STATUS_PROCESS = record - dwServiceType, - dwCurrentState, - dwControlsAccepted, - dwWin32ExitCode, - dwServiceSpecificExitCode, - dwCheckPoint, - dwWaitHint, - dwProcessId, - dwServiceFlags: DWORD; - end; - PSERVICE_STATUS_PROCESS = ^SERVICE_STATUS_PROCESS; -const - SvcName = 'TermService'; -var - hSC: SC_HANDLE; - hSvc: THandle; - lpServiceStatusProcess: PSERVICE_STATUS_PROCESS; - Buf: Pointer; - cbBufSize, pcbBytesNeeded: Cardinal; -begin - Result := -1; - hSC := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); - if hSC = 0 then - Exit; - - hSvc := OpenService(hSC, PWideChar(SvcName), SERVICE_QUERY_STATUS); - if hSvc = 0 then - begin - CloseServiceHandle(hSC); - Exit; - end; - - if QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO, nil, 0, pcbBytesNeeded) then - Exit; - - cbBufSize := pcbBytesNeeded; - GetMem(Buf, cbBufSize); - - if not QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO, Buf, cbBufSize, pcbBytesNeeded) then begin - FreeMem(Buf, cbBufSize); - CloseServiceHandle(hSvc); - CloseServiceHandle(hSC); - Exit; - end else begin - lpServiceStatusProcess := Buf; - Result := ShortInt(lpServiceStatusProcess^.dwCurrentState); - end; - FreeMem(Buf, cbBufSize); - CloseServiceHandle(hSvc); - CloseServiceHandle(hSC); -end; - -function IsListenerWorking: Boolean; -var - pCount: DWORD; - SessionInfo: PWTS_SESSION_INFOW; - I: Integer; -begin - Result := False; - if not WinStationEnumerateW(0, SessionInfo, pCount) then - Exit; - for I := 0 to pCount - 1 do - if SessionInfo^[I].Name = 'RDP-Tcp' then begin - Result := True; - Break; - end; - WinStationFreeMemory(SessionInfo); -end; - -function ExtractResText(ResName: String): String; -var - ResStream: TResourceStream; - Str: TStringList; -begin - ResStream := TResourceStream.Create(HInstance, ResName, RT_RCDATA); - Str := TStringList.Create; - try - Str.LoadFromStream(ResStream); - except - - end; - ResStream.Free; - Result := Str.Text; - Str.Free; -end; - -function TMainForm.ExecWait(Cmdline: String): Boolean; -var - si: STARTUPINFO; - pi: PROCESS_INFORMATION; -begin - Result := False; - ZeroMemory(@si, sizeof(si)); - si.cb := sizeof(si); - si.dwFlags := STARTF_USESHOWWINDOW; - si.wShowWindow := SW_HIDE; - UniqueString(Cmdline); - if not CreateProcess(nil, PWideChar(Cmdline), nil, nil, True, 0, nil, nil, si, pi) then begin - MessageBox(Handle, - PWideChar('CreateProcess error (code: ' + IntToStr(GetLastError) + ').'), - 'Error', MB_ICONERROR or MB_OK); - Exit; - end; - CloseHandle(pi.hThread); - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - Result := True; -end; - -procedure TMainForm.ReadSettings; -var - Reg: TRegistry; - SecurityLayer, UserAuthentication: Integer; -begin - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Terminal Server'); - try - cbAllowTSConnections.Checked := not Reg.ReadBool('fDenyTSConnections'); - except - - end; - try - cbSingleSessionPerUser.Checked := Reg.ReadBool('fSingleSessionPerUser'); - except - - end; - try - cbCustomPrg.Checked := Reg.ReadBool('HonorLegacySettings'); - except - - end; - Reg.CloseKey; - - Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'); - seRDPPort.Value := 3389; - try - seRDPPort.Value := Reg.ReadInteger('PortNumber'); - except - - end; - OldPort := seRDPPort.Value; - SecurityLayer := 0; - UserAuthentication := 0; - try - SecurityLayer := Reg.ReadInteger('SecurityLayer'); - UserAuthentication := Reg.ReadInteger('UserAuthentication'); - except - - end; - if (SecurityLayer = 0) and (UserAuthentication = 0) then - rgNLA.ItemIndex := 0; - if (SecurityLayer = 1) and (UserAuthentication = 0) then - rgNLA.ItemIndex := 1; - if (SecurityLayer = 2) and (UserAuthentication = 1) then - rgNLA.ItemIndex := 2; - try - rgShadow.ItemIndex := Reg.ReadInteger('Shadow'); - except - - end; - Reg.CloseKey; - Reg.OpenKeyReadOnly('\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'); - try - cbHideUsers.Checked := Reg.ReadBool('dontdisplaylastusername'); - except - - end; - Reg.CloseKey; - Reg.Free; -end; - -procedure TMainForm.WriteSettings; -var - Reg: TRegistry; - SecurityLayer, UserAuthentication: Integer; -begin - Reg := TRegistry.Create; - Reg.RootKey := HKEY_LOCAL_MACHINE; - Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server', True); - try - Reg.WriteBool('fDenyTSConnections', not cbAllowTSConnections.Checked); - except - - end; - try - Reg.WriteBool('fSingleSessionPerUser', cbSingleSessionPerUser.Checked); - except - - end; - try - Reg.WriteBool('HonorLegacySettings', cbCustomPrg.Checked); - except - - end; - Reg.CloseKey; - - Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp', True); - try - Reg.WriteInteger('PortNumber', seRDPPort.Value); - except - - end; - if OldPort <> seRDPPort.Value then - begin - OldPort := seRDPPort.Value; - ExecWait('netsh advfirewall firewall set rule name="Remote Desktop" new localport=' + IntToStr(OldPort)); - end; - case rgNLA.ItemIndex of - 0: begin - SecurityLayer := 0; - UserAuthentication := 0; - end; - 1: begin - SecurityLayer := 1; - UserAuthentication := 0; - end; - 2: begin - SecurityLayer := 2; - UserAuthentication := 1; - end; - else begin - SecurityLayer := -1; - UserAuthentication := -1; - end; - end; - if SecurityLayer >= 0 then begin - try - Reg.WriteInteger('SecurityLayer', SecurityLayer); - Reg.WriteInteger('UserAuthentication', UserAuthentication); - except - - end; - end; - if rgShadow.ItemIndex >= 0 then begin - try - Reg.WriteInteger('Shadow', rgShadow.ItemIndex); - except - - end; - end; - Reg.CloseKey; - Reg.OpenKey('\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services', True); - if rgShadow.ItemIndex >= 0 then begin - try - Reg.WriteInteger('Shadow', rgShadow.ItemIndex); - except - - end; - end; - Reg.CloseKey; - Reg.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System', True); - try - Reg.WriteBool('dontdisplaylastusername', cbHideUsers.Checked); - except - - end; - Reg.CloseKey; - Reg.Free; -end; - -function CheckSupport(FV: FILE_VERSION): Byte; -var - VerTxt: String; -begin - Result := 0; - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 0) then - Result := 1; - if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 1) then - Result := 1; - VerTxt := Format('%d.%d.%d.%d', - [FV.Version.w.Major, FV.Version.w.Minor, FV.Release, FV.Build]); - if Pos('[' + VerTxt + ']', INI) > 0 then - Result := 2; -end; - -procedure TMainForm.TimerTimer(Sender: TObject); -var - WrapperPath, INIPath: String; - FV: FILE_VERSION; - L: TStringList; - CheckSupp: Boolean; -begin - CheckSupp := False; - case IsWrapperInstalled(WrapperPath) of - -1: begin - lsWrapper.Caption := 'Unknown'; - lsWrapper.Font.Color := clGrayText; - end; - 0: begin - lsWrapper.Caption := 'Not installed'; - lsWrapper.Font.Color := clGrayText; - end; - 1: begin - lsWrapper.Caption := 'Installed'; - lsWrapper.Font.Color := clGreen; - CheckSupp := True; - INIPath := ExtractFilePath(ExpandPath(WrapperPath)) + 'rdpwrap.ini'; - if not FileExists(INIPath) then - CheckSupp := False; - end; - 2: begin - lsWrapper.Caption := '3rd-party'; - lsWrapper.Font.Color := clRed; - end; - end; - case GetTermSrvState of - -1, 0: begin - lsService.Caption := 'Unknown'; - lsService.Font.Color := clGrayText; - end; - SERVICE_STOPPED: begin - lsService.Caption := 'Stopped'; - lsService.Font.Color := clRed; - end; - SERVICE_START_PENDING: begin - lsService.Caption := 'Starting...'; - lsService.Font.Color := clGrayText; - end; - SERVICE_STOP_PENDING: begin - lsService.Caption := 'Stopping...'; - lsService.Font.Color := clGrayText; - end; - SERVICE_RUNNING: begin - lsService.Caption := 'Running'; - lsService.Font.Color := clGreen; - end; - SERVICE_CONTINUE_PENDING: begin - lsService.Caption := 'Resuming...'; - lsService.Font.Color := clGrayText; - end; - SERVICE_PAUSE_PENDING: begin - lsService.Caption := 'Suspending...'; - lsService.Font.Color := clGrayText; - end; - SERVICE_PAUSED: begin - lsService.Caption := 'Suspended'; - lsService.Font.Color := clWindowText; - end; - end; - if IsListenerWorking then begin - lsListener.Caption := 'Listening'; - lsListener.Font.Color := clGreen; - end else begin - lsListener.Caption := 'Not listening'; - lsListener.Font.Color := clRed; - end; - if WrapperPath = '' then begin - lsWrapVer.Caption := 'N/A'; - lsWrapVer.Font.Color := clGrayText; - end else - if not GetFileVersion(ExpandPath(WrapperPath), FV) then begin - lsWrapVer.Caption := 'N/A'; - lsWrapVer.Font.Color := clGrayText; - end else begin - lsWrapVer.Caption := - IntToStr(FV.Version.w.Major)+'.'+ - IntToStr(FV.Version.w.Minor)+'.'+ - IntToStr(FV.Release)+'.'+ - IntToStr(FV.Build); - lsWrapVer.Font.Color := clWindowText; - end; - if not GetFileVersion('termsrv.dll', FV) then begin - lsTSVer.Caption := 'N/A'; - lsTSVer.Font.Color := clGrayText; - end else begin - lsTSVer.Caption := - IntToStr(FV.Version.w.Major)+'.'+ - IntToStr(FV.Version.w.Minor)+'.'+ - IntToStr(FV.Release)+'.'+ - IntToStr(FV.Build); - lsTSVer.Font.Color := clWindowText; - lsSuppVer.Visible := CheckSupp; - if CheckSupp then begin - if INI = '' then begin - L := TStringList.Create; - try - L.LoadFromFile(INIPath); - except - - end; - INI := L.Text; - L.Free; - end; - case CheckSupport(FV) of - 0: begin - lsSuppVer.Caption := '[not supported]'; - lsSuppVer.Font.Color := clRed; - end; - 1: begin - lsSuppVer.Caption := '[supported partially]'; - lsSuppVer.Font.Color := clOlive; - end; - 2: begin - lsSuppVer.Caption := '[fully supported]'; - lsSuppVer.Font.Color := clGreen; - end; - end; - end; - end; -end; - -procedure TMainForm.bLicenseClick(Sender: TObject); -begin - LicenseForm.mText.Text := ExtractResText('LICENSE'); - if LicenseForm.ShowModal <> mrOk then - Halt(0); -end; - -procedure TMainForm.cbAllowTSConnectionsClick(Sender: TObject); -begin - if Ready then - bApply.Enabled := True; -end; - -procedure TMainForm.seRDPPortChange(Sender: TObject); -begin - if Ready then - bApply.Enabled := True; -end; - -procedure TMainForm.FormCreate(Sender: TObject); -var - SI: TSystemInfo; -begin - GetNativeSystemInfo(SI); - case SI.wProcessorArchitecture of - 0: Arch := 32; - 6: Arch := 64; // Itanium-based x64 - 9: Arch := 64; // Intel/AMD x64 - else Arch := 0; - end; - if Arch = 64 then - DisableWowRedirection; - ReadSettings; - Ready := True; -end; - -procedure TMainForm.FormDestroy(Sender: TObject); -begin - if Arch = 64 then - RevertWowRedirection; -end; - -procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); -begin - if bApply.Enabled then - CanClose := MessageBox(Handle, 'Settings are not saved. Do you want to exit?', - 'Warning', mb_IconWarning or mb_YesNo) = mrYes; -end; - -procedure TMainForm.bOKClick(Sender: TObject); -begin - if bApply.Enabled then begin - WriteSettings; - bApply.Enabled := False; - end; - Close; -end; - -procedure TMainForm.bCancelClick(Sender: TObject); -begin - Close; -end; - -procedure TMainForm.bApplyClick(Sender: TObject); -begin - WriteSettings; - bApply.Enabled := False; -end; - -end. diff --git a/src-rdpconfig/RDPConf.dpr b/src-rdpconfig/RDPConf.dpr deleted file mode 100644 index 3fd645f..0000000 --- a/src-rdpconfig/RDPConf.dpr +++ /dev/null @@ -1,33 +0,0 @@ -{ - Copyright 2014 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -program RDPConf; - -uses - Forms, - MainUnit in 'MainUnit.pas' {MainForm}, - LicenseUnit in 'LicenseUnit.pas' {LicenseForm}; - -{$R *.res} - -begin - Application.Initialize; - Application.MainFormOnTaskbar := True; - Application.Title := 'Remote Desktop Protocol Configuration'; - Application.CreateForm(TMainForm, MainForm); - Application.CreateForm(TLicenseForm, LicenseForm); - Application.Run; -end. diff --git a/src-rdpconfig/RDPConf.dproj b/src-rdpconfig/RDPConf.dproj deleted file mode 100644 index aa9ab96..0000000 --- a/src-rdpconfig/RDPConf.dproj +++ /dev/null @@ -1,111 +0,0 @@ - - - {A7CB4C30-85F5-4D96-B510-6F0CDCF7C2DA} - 12.0 - RDPConf.dpr - Debug - DCC32 - - - true - - - true - Base - true - - - true - Base - true - - - ..\bin\ - WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias) - ..\bin\RDPConf.exe - 00400000 - x86 - - - false - RELEASE;$(DCC_Define) - 0 - false - - - DEBUG;$(DCC_Define) - - - - MainSource - - -
MainForm
-
- -
LicenseForm
-
- - Base - - - Cfg_1 - Base - - - Cfg_2 - Base - -
- - - Delphi.Personality.12 - - - - - RDPConf.dpr - - - False - True - False - - - False - False - 1 - 0 - 0 - 0 - False - False - False - False - False - 1033 - 1252 - - - Stas'M Corp. - RDP Configuration Program - 1.0.0.0 - RDPConf - Copyright © Stas'M Corp. 2014 - Stas'M Corp. - RDPConf.exe - RDP Host Support - 1.4.0.0 - http://stascorp.com - - - Embarcadero C++Builder Office 2000 Servers Package - Embarcadero C++Builder Office XP Servers Package - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - - - - 12 - -
diff --git a/src-rdpconfig/RDPConf.res b/src-rdpconfig/RDPConf.res deleted file mode 100644 index f987dd9..0000000 Binary files a/src-rdpconfig/RDPConf.res and /dev/null differ diff --git a/src-rdpconfig/resource.res b/src-rdpconfig/resource.res deleted file mode 100644 index 68f82f2..0000000 Binary files a/src-rdpconfig/resource.res and /dev/null differ diff --git a/src-x86-binarymaster/LiteINI.pas b/src-x86-binarymaster/LiteINI.pas deleted file mode 100644 index 08d144d..0000000 --- a/src-x86-binarymaster/LiteINI.pas +++ /dev/null @@ -1,375 +0,0 @@ -{ - Copyright 2014 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -unit LiteINI; - -interface - -uses - SysUtils; - -type - SList = Array of String; - INIValue = record - Name: String; - Value: String; - end; - INISection = record - Name: String; - Values: Array of INIValue; - end; - INIFile = Array of INISection; - -procedure SListClear(var List: SList); -function SListAppend(var List: SList; S: String): Integer; -function SListFind(List: SList; Value: String): Integer; -function INIFindSection(INI: INIFile; Section: String): Integer; -function INIFindValue(INI: INIFile; Section: Integer; Value: String): Integer; -function INIAddSection(var INI: INIFile; Section: String): Integer; -function INIAddValue(var INI: INIFile; Section: Integer; ValueName, Value: String): Integer; -procedure INIUnload(var INI: INIFile); -procedure INILoad(var INI: INIFile; FileName: String); -function INISectionExists(INI: INIFile; Section: String): Boolean; -function INIValueExists(INI: INIFile; Section: String; Value: String): Boolean; -function INIReadSectionLowAPI(INI: INIFile; Section: Integer; var List: SList): Boolean; -function INIReadSection(INI: INIFile; Section: String): SList; -function INIReadStringLowAPI(INI: INIFile; Section, Value: Integer; var Str: String): Boolean; -function INIReadString(INI: INIFile; Section, Value, Default: String): String; -function INIReadInt(INI: INIFile; Section, Value: String; Default: Integer): Integer; -function INIReadDWord(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal; -function INIReadIntHex(INI: INIFile; Section, Value: String; Default: Integer): Integer; -function INIReadDWordHex(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal; -function INIReadBool(INI: INIFile; Section, Value: String; Default: Boolean): Boolean; -function INIReadBytes(INI: INIFile; Section, Value: String): TBytes; -function INIReadBytesDef(INI: INIFile; Section, Value: String; Default: TBytes): TBytes; - -implementation - -procedure SListClear(var List: SList); -begin - SetLength(List, 0); -end; - -function SListAppend(var List: SList; S: String): Integer; -begin - SetLength(List, Length(List) + 1); - List[Length(List) - 1] := S; - Result := Length(List) - 1; -end; - -function SListFind(List: SList; Value: String): Integer; -var - I: Integer; -begin - Result := -1; - for I := 0 to Length(List) - 1 do - if List[I] = Value then begin - Result := I; - Break; - end; -end; - -function INIFindSection(INI: INIFile; Section: String): Integer; -var - I: Integer; -begin - Result := -1; - for I := 0 to Length(INI) - 1 do - if INI[I].Name = Section then begin - Result := I; - Exit; - end; -end; - -function INIFindValue(INI: INIFile; Section: Integer; Value: String): Integer; -var - I: Integer; -begin - Result := -1; - if (Section < 0) or (Section >= Length(INI)) then - Exit; - for I := 0 to Length(INI[Section].Values) - 1 do - if INI[Section].Values[I].Name = Value then begin - Result := I; - Exit; - end; -end; - -function INIAddSection(var INI: INIFile; Section: String): Integer; -begin - Result := INIFindSection(INI, Section); - if Result >= 0 then - Exit; - Result := Length(INI); - SetLength(INI, Result + 1); - INI[Result].Name := Section; - SetLength(INI[Result].Values, 0); -end; - -function INIAddValue(var INI: INIFile; Section: Integer; ValueName, Value: String): Integer; -var - I: Integer; -begin - Result := -1; - if (Section < 0) or (Section >= Length(INI)) then - Exit; - I := INIFindValue(INI, Section, ValueName); - if I = -1 then begin - Result := Length(INI[Section].Values); - SetLength(INI[Section].Values, Result + 1); - INI[Section].Values[Result].Name := ValueName; - INI[Section].Values[Result].Value := Value; - end else begin - INI[Section].Values[I].Value := Value; - Result := I; - end; -end; - -procedure INIUnload(var INI: INIFile); -begin - SetLength(INI, 0); -end; - -procedure INILoad(var INI: INIFile; FileName: String); -var - F: TextFile; - S, ValueName, Value: String; - INIList: SList; - I, Sect: Integer; -begin - INIUnload(INI); - if not FileExists(FileName) then - Exit; - AssignFile(F, FileName); - Reset(F); - // Read and filter lines - while not EOF(F) do begin - Readln(F, S); - if (Pos(';', S) <> 1) - and (Pos('#', S) <> 1) - and ( - ((Pos('[', S) > 0) and (Pos(']', S) > 0)) or - (Pos('=', S) > 0) - ) - then - SListAppend(INIList, S); - end; - CloseFile(F); - // Parse 2 (parse format) - Sect := -1; - for I := 0 to Length(INIList) - 1 do begin - S := Trim(INIList[I]); - if Length(S) >= 2 then - if (S[1] = '[') and (S[Length(S)] = ']') then begin - S := Trim(Copy(S, 2, Length(S) - 2)); - Sect := INIAddSection(INI, S); - Continue; - end; - S := INIList[I]; - if Pos('=', S) > 0 then begin - ValueName := Trim(Copy(S, 1, Pos('=', S) - 1)); - Value := Copy(S, Pos('=', S) + 1, Length(S) - Pos('=', S)); - if Sect = -1 then - Sect := INIAddSection(INI, ''); - INIAddValue(INI, Sect, ValueName, Value); - end; - end; -end; - -function INISectionExists(INI: INIFile; Section: String): Boolean; -begin - Result := INIFindSection(INI, Section) > -1; -end; - -function INIValueExists(INI: INIFile; Section: String; Value: String): Boolean; -var - Sect: Integer; -begin - Sect := INIFindSection(INI, Section); - Result := INIFindValue(INI, Sect, Value) > -1; -end; - -function INIReadSectionLowAPI(INI: INIFile; Section: Integer; var List: SList): Boolean; -var - I: Integer; -begin - Result := False; - SetLength(List, 0); - if (Section < 0) or (Section >= Length(INI)) then - Exit; - for I := 0 to Length(INI[Section].Values) - 1 do - SListAppend(List, INI[Section].Values[I].Name); - Result := True; -end; - -function INIReadSection(INI: INIFile; Section: String): SList; -var - Sect: Integer; -begin - Sect := INIFindSection(INI, Section); - INIReadSectionLowAPI(INI, Sect, Result); -end; - -function INIReadStringLowAPI(INI: INIFile; Section, Value: Integer; var Str: String): Boolean; -begin - Result := False; - if (Section < 0) or (Section >= Length(INI)) then - Exit; - if (Value < 0) or (Value >= Length(INI[Section].Values)) then - Exit; - Str := INI[Section].Values[Value].Value; - Result := True; -end; - -function INIReadString(INI: INIFile; Section, Value, Default: String): String; -var - Sect, Val: Integer; -begin - Sect := INIFindSection(INI, Section); - Val := INIFindValue(INI, Sect, Value); - if not INIReadStringLowAPI(INI, Sect, Val, Result) then - Result := Default; -end; - -function INIReadInt(INI: INIFile; Section, Value: String; Default: Integer): Integer; -var - S: String; - E: Integer; -begin - S := INIReadString(INI, Section, Value, ''); - Val(S, Result, E); - if E <> 0 then - Result := Default; -end; - -function INIReadDWord(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal; -var - S: String; - E: Integer; -begin - S := INIReadString(INI, Section, Value, ''); - Val(S, Result, E); - if E <> 0 then - Result := Default; -end; - -function INIReadIntHex(INI: INIFile; Section, Value: String; Default: Integer): Integer; -var - S: String; - E: Integer; -begin - S := INIReadString(INI, Section, Value, ''); - Val('$'+S, Result, E); - if E <> 0 then - Result := Default; -end; - -function INIReadDWordHex(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal; -var - S: String; - E: Integer; -begin - S := INIReadString(INI, Section, Value, ''); - Val('$'+S, Result, E); - if E <> 0 then - Result := Default; -end; - -function INIReadBool(INI: INIFile; Section, Value: String; Default: Boolean): Boolean; -var - S: String; - I: Cardinal; - E: Integer; -begin - S := INIReadString(INI, Section, Value, ''); - Val(S, I, E); - if E <> 0 then - Result := Default - else - Result := I > 0; -end; - -function StringToBytes(S: String; var B: TBytes): Boolean; -var - I: Integer; -begin - Result := False; - if Odd(Length(S)) then - Exit; - SetLength(B, Length(S) div 2); - for I := 0 to Length(B) - 1 do begin - B[I] := 0; - case S[(I*2)+2] of - '0': ; - '1': B[I] := B[I] or $1; - '2': B[I] := B[I] or $2; - '3': B[I] := B[I] or $3; - '4': B[I] := B[I] or $4; - '5': B[I] := B[I] or $5; - '6': B[I] := B[I] or $6; - '7': B[I] := B[I] or $7; - '8': B[I] := B[I] or $8; - '9': B[I] := B[I] or $9; - 'A','a': B[I] := B[I] or $A; - 'B','b': B[I] := B[I] or $B; - 'C','c': B[I] := B[I] or $C; - 'D','d': B[I] := B[I] or $D; - 'E','e': B[I] := B[I] or $E; - 'F','f': B[I] := B[I] or $F; - else Exit; - end; - case S[(I*2)+1] of - '0': ; - '1': B[I] := B[I] or $10; - '2': B[I] := B[I] or $20; - '3': B[I] := B[I] or $30; - '4': B[I] := B[I] or $40; - '5': B[I] := B[I] or $50; - '6': B[I] := B[I] or $60; - '7': B[I] := B[I] or $70; - '8': B[I] := B[I] or $80; - '9': B[I] := B[I] or $90; - 'A','a': B[I] := B[I] or $A0; - 'B','b': B[I] := B[I] or $B0; - 'C','c': B[I] := B[I] or $C0; - 'D','d': B[I] := B[I] or $D0; - 'E','e': B[I] := B[I] or $E0; - 'F','f': B[I] := B[I] or $F0; - else Exit; - end; - end; - Result := True; -end; - -function INIReadBytes(INI: INIFile; Section, Value: String): TBytes; -var - S: String; -begin - S := INIReadString(INI, Section, Value, ''); - if not StringToBytes(S, Result) then - SetLength(Result, 0); -end; - -function INIReadBytesDef(INI: INIFile; Section, Value: String; Default: TBytes): TBytes; -var - S: String; -begin - S := INIReadString(INI, Section, Value, ''); - if not StringToBytes(S, Result) then - Result := Default; -end; - -end. diff --git a/src-x86-binarymaster/rdpwrap.dpr b/src-x86-binarymaster/rdpwrap.dpr deleted file mode 100644 index 38b85f6..0000000 --- a/src-x86-binarymaster/rdpwrap.dpr +++ /dev/null @@ -1,737 +0,0 @@ -{ - Copyright 2014 Stas'M Corp. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -} - -library rdpwrap; - -uses - SysUtils, - Windows, - TlHelp32, - LiteINI; - -{$R rdpwrap.res} - -// Hook core definitions - -type - OldCode = packed record - One: DWORD; - two: Word; - end; - - far_jmp = packed record - PushOp: Byte; - PushArg: Pointer; - RetOp: Byte; - end; - - mov_far_jmp = packed record - MovOp: Byte; - MovArg: Byte; - PushOp: Byte; - PushArg: Pointer; - RetOp: Byte; - end; - - TTHREADENTRY32 = packed record - dwSize: DWORD; - cntUsage: DWORD; - th32ThreadID: DWORD; - th32OwnerProcessID: DWORD; - tpBasePri: LongInt; - tpDeltaPri: LongInt; - dwFlags: DWORD; - end; - //IntArray = Array of Integer; - FILE_VERSION = record - Version: record case Boolean of - True: (dw: DWORD); - False: (w: record - Minor, Major: Word; - end;) - end; - Release, Build: Word; - bDebug, bPrerelease, bPrivate, bSpecial: Boolean; - end; - -const - THREAD_SUSPEND_RESUME = 2; - TH32CS_SNAPTHREAD = 4; -var - INI: INIFile; - LogFile: String = '\rdpwrap.txt'; - bw: {$if CompilerVersion>=16} NativeUInt {$else} DWORD {$endif}; - IsHooked: Boolean = False; - -// Unhooked import - -function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; - dwThreadId: DWORD): DWORD; stdcall; external kernel32; - -function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): DWORD; - stdcall; external kernel32; - -function Thread32First(hSnapshot: THandle; var lpte: TTHREADENTRY32): bool; - stdcall; external kernel32; - -function Thread32Next(hSnapshot: THandle; var lpte: TTHREADENTRY32): bool; - stdcall; external kernel32; - -// Wrapped import - -var - TSMain: function(dwArgc: DWORD; lpszArgv: PWideChar): DWORD; stdcall; - TSGlobals: function(lpGlobalData: Pointer): DWORD; stdcall; - -// Hooked import and vars - -var - SLGetWindowsInformationDWORD: function(pwszValueName: PWideChar; - pdwValue: PDWORD): HRESULT; stdcall; - TermSrvBase: Pointer; - FV: FILE_VERSION; - -var - Stub_SLGetWindowsInformationDWORD: far_jmp; - Old_SLGetWindowsInformationDWORD: OldCode; - -// Main code - -procedure WriteLog(S: AnsiString); -var - F: TextFile; -begin - if not FileExists(LogFile) then - Exit; - AssignFile(F, LogFile); - Append(F); - Write(F, S+#13#10); - CloseFile(F); -end; - -function GetModuleHandleEx(dwFlags: DWORD; lpModuleName: PWideChar; - var phModule: HMODULE): BOOL; stdcall; external kernel32 name 'GetModuleHandleExW'; - -function GetCurrentModule: HMODULE; -const - GET_MODULE_HANDLE_EX_FLAG_PIN = 1; - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2; - GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4; -begin - Result := 0; - GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, @GetCurrentModule, Result); -end; - -function GetBinaryPath: String; -var - Buf: Array[0..511] of Byte; -begin - ZeroMemory(@Buf[0], Length(Buf)); - GetModuleFileName(GetCurrentModule, PWideChar(@Buf[0]), Length(Buf)); - Result := PWideChar(@Buf[0]); -end; - -procedure StopThreads; -var - h, CurrTh, ThrHandle, CurrPr: DWORD; - Thread: TTHREADENTRY32; -begin - CurrTh := GetCurrentThreadId; - CurrPr := GetCurrentProcessId; - h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if h <> INVALID_HANDLE_VALUE then - begin - Thread.dwSize := SizeOf(TTHREADENTRY32); - if Thread32First(h, Thread) then - repeat - if (Thread.th32ThreadID <> CurrTh) and - (Thread.th32OwnerProcessID = CurrPr) then - begin - ThrHandle := OpenThread(THREAD_SUSPEND_RESUME, false, - Thread.th32ThreadID); - if ThrHandle > 0 then - begin - SuspendThread(ThrHandle); - CloseHandle(ThrHandle); - end; - end; - until not Thread32Next(h, Thread); - CloseHandle(h); - end; -end; - -procedure RunThreads; -var - h, CurrTh, ThrHandle, CurrPr: DWORD; - Thread: TTHREADENTRY32; -begin - CurrTh := GetCurrentThreadId; - CurrPr := GetCurrentProcessId; - h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if h <> INVALID_HANDLE_VALUE then - begin - Thread.dwSize := SizeOf(TTHREADENTRY32); - if Thread32First(h, Thread) then - repeat - if (Thread.th32ThreadID <> CurrTh) and - (Thread.th32OwnerProcessID = CurrPr) then - begin - ThrHandle := OpenThread(THREAD_SUSPEND_RESUME, false, - Thread.th32ThreadID); - if ThrHandle > 0 then - begin - ResumeThread(ThrHandle); - CloseHandle(ThrHandle); - end; - end; - until not Thread32Next(h, Thread); - CloseHandle(h); - end; -end; - -function GetModuleAddress(ModuleName: String; ProcessId: DWORD; var BaseAddr: Pointer; var BaseSize: DWORD): Boolean; -var - hSnap: THandle; - md: MODULEENTRY32; -begin - Result := False; - hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId); - if hSnap = INVALID_HANDLE_VALUE Then - Exit; - md.dwSize := SizeOf(MODULEENTRY32); - if Module32First(hSnap, md) then - begin - if LowerCase(ExtractFileName(md.szExePath)) = LowerCase(ModuleName) then - begin - Result := True; - BaseAddr := Pointer(md.modBaseAddr); - BaseSize := md.modBaseSize; - CloseHandle(hSnap); - Exit; - end; - while Module32Next(hSnap, md) Do - begin - if LowerCase(ExtractFileName(md.szExePath)) = LowerCase(ModuleName) then - begin - Result := True; - BaseAddr := Pointer(md.modBaseAddr); - BaseSize := md.modBaseSize; - Break; - end; - end; - end; - CloseHandle(hSnap); -end; - -{procedure FindMem(Mem: Pointer; MemSz: DWORD; Buf: Pointer; BufSz: DWORD; - From: DWORD; var A: IntArray); -var - I: Integer; -begin - SetLength(A, 0); - I:=From; - if From>0 then - Inc(PByte(Mem), From); - while I < MemSz - BufSz + 1 do - begin - if (not IsBadReadPtr(Mem, BufSz)) and (CompareMem(Mem, Buf, BufSz)) then - begin - SetLength(A, Length(A)+1); - A[Length(A)-1] := I; - end; - Inc(I); - Inc(PByte(Mem)); - end; -end;} - -function GetModuleVersion(const ModuleName: String; var FileVersion: FILE_VERSION): Boolean; -type - VS_VERSIONINFO = record - wLength, wValueLength, wType: Word; - szKey: Array[1..16] of WideChar; - Padding1: Word; - Value: VS_FIXEDFILEINFO; - Padding2, Children: Word; - end; - PVS_VERSIONINFO = ^VS_VERSIONINFO; -const - VFF_DEBUG = 1; - VFF_PRERELEASE = 2; - VFF_PRIVATE = 8; - VFF_SPECIAL = 32; -var - hMod: HMODULE; - hResourceInfo: HRSRC; - VersionInfo: PVS_VERSIONINFO; -begin - Result := False; - - if ModuleName = '' then - hMod := GetModuleHandle(nil) - else - hMod := GetModuleHandle(PWideChar(ModuleName)); - if hMod = 0 then - Exit; - - hResourceInfo := FindResource(hMod, PWideChar(1), PWideChar($10)); - if hResourceInfo = 0 then - Exit; - - VersionInfo := Pointer(LoadResource(hMod, hResourceInfo)); - if VersionInfo = nil then - Exit; - - FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS; - FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16); - FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS); - FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG; - FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE; - FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE; - FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL; - - Result := True; -end; - -function GetFileVersion(const FileName: String; var FileVersion: FILE_VERSION): Boolean; -type - VS_VERSIONINFO = record - wLength, wValueLength, wType: Word; - szKey: Array[1..16] of WideChar; - Padding1: Word; - Value: VS_FIXEDFILEINFO; - Padding2, Children: Word; - end; - PVS_VERSIONINFO = ^VS_VERSIONINFO; -const - VFF_DEBUG = 1; - VFF_PRERELEASE = 2; - VFF_PRIVATE = 8; - VFF_SPECIAL = 32; -var - hFile: HMODULE; - hResourceInfo: HRSRC; - VersionInfo: PVS_VERSIONINFO; -begin - Result := False; - - hFile := LoadLibraryEx(PWideChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE); - if hFile = 0 then - Exit; - - hResourceInfo := FindResource(hFile, PWideChar(1), PWideChar($10)); - if hResourceInfo = 0 then - Exit; - - VersionInfo := Pointer(LoadResource(hFile, hResourceInfo)); - if VersionInfo = nil then - Exit; - - FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS; - FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16); - FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS); - FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG; - FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE; - FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE; - FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL; - - Result := True; -end; - -function OverrideSL(ValueName: String; var Value: DWORD): Boolean; -begin - Result := True; - if INIValueExists(INI, 'SLPolicy', ValueName) then begin - Value := INIReadDWord(INI, 'SLPolicy', ValueName, 0); - Exit; - end; - Result := False; -end; - -function New_SLGetWindowsInformationDWORD(pwszValueName: PWideChar; - pdwValue: PDWORD): HRESULT; stdcall; -var - dw: DWORD; -begin - // wrapped SLGetWindowsInformationDWORD function - // termsrv.dll will call this function instead of original SLC.dll - - // Override SL Policy - - WriteLog('Policy query: ' + pwszValueName); - if OverrideSL(pwszValueName, dw) then begin - pdwValue^ := dw; - Result := S_OK; - WriteLog('Policy rewrite: ' + IntToStr(pdwValue^)); - Exit; - end; - - // If the requested value name is not defined above - - // revert to original SL Policy function - WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD, - @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw); - - // get result - Result := SLGetWindowsInformationDWORD(pwszValueName, pdwValue); - if Result = S_OK then - WriteLog('Policy result: ' + IntToStr(pdwValue^)) - else - WriteLog('Policy request failed'); - // wrap it back - WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD, - @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw); -end; - -function New_Win8SL(pwszValueName: PWideChar; pdwValue: PDWORD): HRESULT; register; -var - dw: DWORD; -begin - // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll - // for Windows 8 support - - // Override SL Policy - - WriteLog('Policy query: ' + pwszValueName); - if OverrideSL(pwszValueName, dw) then begin - pdwValue^ := dw; - Result := S_OK; - WriteLog('Policy rewrite: ' + IntToStr(pdwValue^)); - Exit; - end; - - // If the requested value name is not defined above - // use function from SLC.dll - - Result := SLGetWindowsInformationDWORD(pwszValueName, pdwValue); - if Result = S_OK then - WriteLog('Policy result: ' + IntToStr(pdwValue^)) - else - WriteLog('Policy request failed'); -end; - -function New_Win8SL_CP(eax: DWORD; pdwValue: PDWORD; ecx: DWORD; pwszValueName: PWideChar): HRESULT; register; -begin - // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll - // for Windows 8 Consumer Preview support - - Result := New_Win8SL(pwszValueName, pdwValue); -end; - -function New_CSLQuery_Initialize: HRESULT; stdcall; -var - Sect: String; - bServerSku, - bRemoteConnAllowed, - bFUSEnabled, - bAppServerAllowed, - bMultimonAllowed, - lMaxUserSessions, - ulMaxDebugSessions, - bInitialized: PDWORD; -begin - bServerSku := nil; - bRemoteConnAllowed := nil; - bFUSEnabled := nil; - bAppServerAllowed := nil; - bMultimonAllowed := nil; - lMaxUserSessions := nil; - ulMaxDebugSessions := nil; - bInitialized := nil; - WriteLog('>>> CSLQuery::Initialize'); - Sect := IntToStr(FV.Version.w.Major)+'.'+IntToStr(FV.Version.w.Minor)+'.'+ - IntToStr(FV.Release)+'.'+IntToStr(FV.Build)+'-SLInit'; - if INISectionExists(INI, Sect) then begin - bServerSku := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bServerSku.x86', 0)); - bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bRemoteConnAllowed.x86', 0)); - bFUSEnabled := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bFUSEnabled.x86', 0)); - bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bAppServerAllowed.x86', 0)); - bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bMultimonAllowed.x86', 0)); - lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'lMaxUserSessions.x86', 0)); - ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'ulMaxDebugSessions.x86', 0)); - bInitialized := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bInitialized.x86', 0)); - end; - - if bServerSku <> nil then begin - bServerSku^ := INIReadDWord(INI, 'SLInit', 'bServerSku', 1); - WriteLog('SLInit [0x'+IntToHex(DWORD(bServerSku), 1)+'] bServerSku = ' + IntToStr(bServerSku^)); - end; - if bRemoteConnAllowed <> nil then begin - bRemoteConnAllowed^ := INIReadDWord(INI, 'SLInit', 'bRemoteConnAllowed', 1); - WriteLog('SLInit [0x'+IntToHex(DWORD(bRemoteConnAllowed), 1)+'] bRemoteConnAllowed = ' + IntToStr(bRemoteConnAllowed^)); - end; - if bFUSEnabled <> nil then begin - bFUSEnabled^ := INIReadDWord(INI, 'SLInit', 'bFUSEnabled', 1); - WriteLog('SLInit [0x'+IntToHex(DWORD(bFUSEnabled), 1)+'] bFUSEnabled = ' + IntToStr(bFUSEnabled^)); - end; - if bAppServerAllowed <> nil then begin - bAppServerAllowed^ := INIReadDWord(INI, 'SLInit', 'bAppServerAllowed', 1); - WriteLog('SLInit [0x'+IntToHex(DWORD(bAppServerAllowed), 1)+'] bAppServerAllowed = ' + IntToStr(bAppServerAllowed^)); - end; - if bMultimonAllowed <> nil then begin - bMultimonAllowed^ := INIReadDWord(INI, 'SLInit', 'bMultimonAllowed', 1); - WriteLog('SLInit [0x'+IntToHex(DWORD(bMultimonAllowed), 1)+'] bMultimonAllowed = ' + IntToStr(bMultimonAllowed^)); - end; - if lMaxUserSessions <> nil then begin - lMaxUserSessions^ := INIReadDWord(INI, 'SLInit', 'lMaxUserSessions', 0); - WriteLog('SLInit [0x'+IntToHex(DWORD(lMaxUserSessions), 1)+'] lMaxUserSessions = ' + IntToStr(lMaxUserSessions^)); - end; - if ulMaxDebugSessions <> nil then begin - ulMaxDebugSessions^ := INIReadDWord(INI, 'SLInit', 'ulMaxDebugSessions', 0); - WriteLog('SLInit [0x'+IntToHex(DWORD(ulMaxDebugSessions), 1)+'] ulMaxDebugSessions = ' + IntToStr(ulMaxDebugSessions^)); - end; - if bInitialized <> nil then begin - bInitialized^ := INIReadDWord(INI, 'SLInit', 'bInitialized', 1); - WriteLog('SLInit [0x'+IntToHex(DWORD(bInitialized), 1)+'] bInitialized = ' + IntToStr(bInitialized^)); - end; - Result := S_OK; - WriteLog('<<< CSLQuery::Initialize'); -end; - -procedure HookFunctions; -var - ConfigFile, Sect, FuncName: String; - V: DWORD; - TS_Handle, SLC_Handle: THandle; - TermSrvSize: DWORD; - SignPtr: Pointer; - I: Integer; - PatchList: SList; - Patch: Array of TBytes; - Jump: far_jmp; - MovJump: mov_far_jmp; -begin - { hook function ^^ - (called once) } - IsHooked := True; - TSMain := nil; - TSGlobals := nil; - SLGetWindowsInformationDWORD := nil; - - WriteLog('Loading configuration...'); - ConfigFile := ExtractFilePath(GetBinaryPath) + 'rdpwrap.ini'; - WriteLog('Configuration file: ' + ConfigFile); - INILoad(INI, ConfigFile); - if Length(INI) = 0 then begin - WriteLog('Error: Failed to load configuration'); - Exit; - end; - - LogFile := INIReadString(INI, 'Main', 'LogFile', ExtractFilePath(GetBinaryPath) + 'rdpwrap.txt'); - WriteLog('Initializing RDP Wrapper...'); - - // load termsrv.dll and get functions - TS_Handle := LoadLibrary('termsrv.dll'); - if TS_Handle = 0 then begin - WriteLog('Error: Failed to load Terminal Services library'); - Exit; - end; - TSMain := GetProcAddress(TS_Handle, 'ServiceMain'); - TSGlobals := GetProcAddress(TS_Handle, 'SvchostPushServiceGlobals'); - WriteLog( - 'Base addr: 0x' + IntToHex(TS_Handle, 8) + #13#10 + - 'SvcMain: termsrv.dll+0x' + IntToHex(Cardinal(@TSMain) - TS_Handle, 1) + #13#10 + - 'SvcGlobals: termsrv.dll+0x' + IntToHex(Cardinal(@TSGlobals) - TS_Handle, 1) - ); - - V := 0; - // check termsrv version - if GetModuleVersion('termsrv.dll', FV) then - V := Byte(FV.Version.w.Minor) or (Byte(FV.Version.w.Major) shl 8) - else begin - // check NT version - // V := GetVersion; // deprecated - // V := ((V and $FF) shl 8) or ((V and $FF00) shr 8); - end; - if V = 0 then begin - WriteLog('Error: Failed to detect Terminal Services version'); - Exit; - end; - - WriteLog('Version: '+ - IntToStr(FV.Version.w.Major)+'.'+ - IntToStr(FV.Version.w.Minor)+'.'+ - IntToStr(FV.Release)+'.'+ - IntToStr(FV.Build)); - - // temporarily freeze threads - WriteLog('Freezing threads...'); - StopThreads(); - - WriteLog('Caching patch codes...'); - PatchList := INIReadSection(INI, 'PatchCodes'); - SetLength(Patch, Length(PatchList)); - for I := 0 to Length(Patch) - 1 do begin - Patch[I] := INIReadBytes(INI, 'PatchCodes', PatchList[I]); - if Length(Patch[I]) > 16 then // for security reasons - SetLength(Patch[I], 16); // not more than 16 bytes - end; - - if (V = $0600) and (INIReadBool(INI, 'Main', 'SLPolicyHookNT60', True)) then begin - // Windows Vista - // uses SL Policy API (slc.dll) - - // load slc.dll and hook function - SLC_Handle := LoadLibrary('slc.dll'); - SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD'); - - if @SLGetWindowsInformationDWORD <> nil then - begin - // rewrite original function to call our function (make hook) - - WriteLog('Hook SLGetWindowsInformationDWORD'); - Stub_SLGetWindowsInformationDWORD.PushOp := $68; - Stub_SLGetWindowsInformationDWORD.PushArg := @New_SLGetWindowsInformationDWORD; - Stub_SLGetWindowsInformationDWORD.RetOp := $C3; - ReadProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD, - @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw); - WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD, - @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw); - end; - end; - if (V = $0601) and (INIReadBool(INI, 'Main', 'SLPolicyHookNT61', True)) then begin - // Windows 7 - // uses SL Policy API (slc.dll) - - // load slc.dll and hook function - SLC_Handle := LoadLibrary('slc.dll'); - SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD'); - - if @SLGetWindowsInformationDWORD <> nil then - begin - // rewrite original function to call our function (make hook) - - WriteLog('Hook SLGetWindowsInformationDWORD'); - Stub_SLGetWindowsInformationDWORD.PushOp := $68; - Stub_SLGetWindowsInformationDWORD.PushArg := @New_SLGetWindowsInformationDWORD; - Stub_SLGetWindowsInformationDWORD.RetOp := $C3; - ReadProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD, - @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw); - WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD, - @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw); - end; - end; - if V = $0602 then begin - // Windows 8 - // uses SL Policy internal unexported function - - // load slc.dll and get function - // (will be used on intercepting undefined values) - SLC_Handle := LoadLibrary('slc.dll'); - SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD'); - end; - if V = $0603 then begin - // Windows 8.1 - // uses SL Policy internal inline code - end; - if V = $0604 then begin - // Windows 10 - // uses SL Policy internal inline code - end; - - Sect := IntToStr(FV.Version.w.Major)+'.'+IntToStr(FV.Version.w.Minor)+'.'+ - IntToStr(FV.Release)+'.'+IntToStr(FV.Build); - - if INISectionExists(INI, Sect) then - if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin - if INIReadBool(INI, Sect, 'LocalOnlyPatch.x86', False) then begin - WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense'); - SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'LocalOnlyOffset.x86', 0)); - I := SListFind(PatchList, INIReadString(INI, Sect, 'LocalOnlyCode.x86', '')); - if I >= 0 then - WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw); - end; - if INIReadBool(INI, Sect, 'SingleUserPatch.x86', False) then begin - WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled'); - SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SingleUserOffset.x86', 0)); - I := SListFind(PatchList, INIReadString(INI, Sect, 'SingleUserCode.x86', '')); - if I >= 0 then - WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw); - end; - if INIReadBool(INI, Sect, 'DefPolicyPatch.x86', False) then begin - WriteLog('Patch CDefPolicy::Query'); - SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'DefPolicyOffset.x86', 0)); - I := SListFind(PatchList, INIReadString(INI, Sect, 'DefPolicyCode.x86', '')); - if I >= 0 then - WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw); - end; - if INIReadBool(INI, Sect, 'SLPolicyInternal.x86', False) then begin - WriteLog('Hook SLGetWindowsInformationDWORDWrapper'); - SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SLPolicyOffset.x86', 0)); - MovJump.MovOp := $89; // mov eax, ecx - MovJump.MovArg := $C8; // __msfastcall compatibility - MovJump.PushOp := $68; - MovJump.PushArg := @New_Win8SL; - MovJump.RetOp := $C3; - FuncName := INIReadString(INI, Sect, 'SLPolicyFunc.x86', 'New_Win8SL'); - if FuncName = 'New_Win8SL' then - MovJump.PushArg := @New_Win8SL; - if FuncName = 'New_Win8SL_CP' then - MovJump.PushArg := @New_Win8SL_CP; - WriteProcessMemory(GetCurrentProcess, SignPtr, - @MovJump, SizeOf(mov_far_jmp), bw); - end; - if INIReadBool(INI, Sect, 'SLInitHook.x86', False) then begin - WriteLog('Hook CSLQuery::Initialize'); - SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SLInitOffset.x86', 0)); - Jump.PushOp := $68; - Jump.PushArg := @New_CSLQuery_Initialize; - Jump.RetOp := $C3; - FuncName := INIReadString(INI, Sect, 'SLInitFunc.x86', 'New_CSLQuery_Initialize'); - if FuncName = 'New_CSLQuery_Initialize' then - Jump.PushArg := @New_CSLQuery_Initialize; - WriteProcessMemory(GetCurrentProcess, SignPtr, - @Jump, SizeOf(far_jmp), bw); - end; - end; - - // unfreeze threads - WriteLog('Resumimg threads...'); - RunThreads(); -end; - -function TermServiceMain(dwArgc: DWORD; lpszArgv: PWideChar): DWORD; stdcall; -begin - // wrap ServiceMain function - WriteLog('>>> ServiceMain'); - if not IsHooked then - HookFunctions; - Result := 0; - if @TSMain <> nil then - Result := TSMain(dwArgc, lpszArgv); - WriteLog('<<< ServiceMain'); -end; - -function TermServiceGlobals(lpGlobalData: Pointer): DWORD; stdcall; -begin - // wrap SvchostPushServiceGlobals function - WriteLog('>>> SvchostPushServiceGlobals'); - if not IsHooked then - HookFunctions; - Result := 0; - if @TSGlobals <> nil then - Result := TSGlobals(lpGlobalData); - WriteLog('<<< SvchostPushServiceGlobals'); -end; - -// export section - -exports - TermServiceMain index 1 name 'ServiceMain', - TermServiceGlobals index 2 name 'SvchostPushServiceGlobals'; - -begin - // DllMain procedure is not used -end. \ No newline at end of file diff --git a/src-x86-binarymaster/rdpwrap.dproj b/src-x86-binarymaster/rdpwrap.dproj deleted file mode 100644 index 2b81a43..0000000 --- a/src-x86-binarymaster/rdpwrap.dproj +++ /dev/null @@ -1,105 +0,0 @@ - - - {D6811241-D595-4809-B3B8-13BECEA56E11} - rdpwrap.dpr - Release - DCC32 - 12.0 - - - true - - - true - Base - true - - - true - Base - true - - - rdpwrap.dll - WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) - true - 00400000 - x86 - - - false - RELEASE;$(DCC_Define) - 0 - false - - - DEBUG;$(DCC_Define) - - - - MainSource - - - Base - - - Cfg_1 - Base - - - Cfg_2 - Base - - - - - Delphi.Personality.12 - VCLApplication - - - - rdpwrap.dpr - - - False - True - False - - - False - False - 1 - 0 - 0 - 0 - False - False - False - False - False - 1049 - 1251 - - - - - 1.0.0.0 - - - - - - 1.0.0.0 - - - - Embarcadero C++Builder Office 2000 Servers Package - Embarcadero C++Builder Office XP Servers Package - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - - - - 12 - - diff --git a/src-x86-binarymaster/rdpwrap.res b/src-x86-binarymaster/rdpwrap.res deleted file mode 100644 index 853a58e..0000000 Binary files a/src-x86-binarymaster/rdpwrap.res and /dev/null differ diff --git a/src-x86-x64-Fusix/RDPWrap.vcxproj b/src-x86-x64-Fusix/RDPWrap.vcxproj index ebc2664..0f10868 100644 --- a/src-x86-x64-Fusix/RDPWrap.vcxproj +++ b/src-x86-x64-Fusix/RDPWrap.vcxproj @@ -1,4 +1,4 @@ - + @@ -17,6 +17,10 @@ Release x64 + + Release + ARM64 + {29E4E73B-EBA6-495B-A76C-FBB462196C64} @@ -49,8 +53,13 @@ v120 true Unicode - - + + DynamicLibrary + false + v143 + true + Unicode + @@ -65,6 +74,9 @@ + + + true @@ -74,16 +86,25 @@ false + $(ProjectDir)Release\x86\ + $(ProjectDir)obj\Release\x86\ false + $(ProjectDir)Release\x64\ + $(ProjectDir)obj\Release\x64\ + + + false + $(ProjectDir)Release\arm64\ + $(ProjectDir)obj\Release\arm64\ Use Level3 Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;WINDOWS_IGNORE_PACKING_MISMATCH;%(PreprocessorDefinitions) true @@ -97,7 +118,7 @@ Use Level3 Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;WINDOWS_IGNORE_PACKING_MISMATCH;%(PreprocessorDefinitions) true @@ -112,7 +133,7 @@ MaxSpeed true true - WIN32;NDEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;WINDOWS_IGNORE_PACKING_MISMATCH;%(PreprocessorDefinitions) true true Level3 @@ -137,7 +158,7 @@ MaxSpeed true true - WIN32;NDEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;WINDOWS_IGNORE_PACKING_MISMATCH;%(PreprocessorDefinitions) true true Level3 @@ -156,6 +177,27 @@ true + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;WINDOWS_IGNORE_PACKING_MISMATCH;%(PreprocessorDefinitions) + true + true + Level3 + 1Byte + MultiThreaded + + + Windows + false + true + true + Export.def + + @@ -178,6 +220,9 @@ + false + + @@ -186,6 +231,7 @@ Create Create Create + Create @@ -194,4 +240,4 @@ - \ No newline at end of file + diff --git a/technical.txt b/technical.txt deleted file mode 100644 index eec609f..0000000 --- a/technical.txt +++ /dev/null @@ -1,561 +0,0 @@ -RDP Wrapper Library project by Stas'M - -Terminal Services supported versions -6.0.X.X (Windows Vista, any) [policy hook only] -6.0.6000.16386 (Windows Vista) [policy hook + extended patch] -6.0.6000.20723 (Windows Vista with KB944917) [todo] -6.0.6001.18000 (Windows Vista SP1) [policy hook + extended patch] -6.0.6001.22286 (Windows Vista SP1 with KB958612) [todo] -6.0.6001.22357 (Windows Vista SP1 with KB958612 v2) [todo] -6.0.6001.22323 (Windows Vista SP1 with KB960742) [todo] -6.0.6001.22392 (Windows Vista SP1 with KB968680) [todo] -6.0.6001.22565 (Windows Vista SP1 with KB977541) [todo] -6.0.6001.22635 (Windows Vista SP1 with KB970911) [todo] -6.0.6001.22801 (Windows Vista SP1 with KB2381675) [todo] -6.0.6002.18005 (Windows Vista SP2) [policy hook + extended patch] -6.0.6002.22269 (Windows Vista SP2 with KB977541) [todo] -6.0.6002.22340 (Windows Vista SP2 with KB970911) [todo] -6.0.6002.22515 (Windows Vista SP2 with KB2381675) [todo] -6.0.6002.22641 (Windows Vista SP2 with KB2523307) [todo] -6.0.6002.22790 (Windows Vista SP2 with KB2672601) [todo] -6.0.6002.19214 (Windows Vista SP2 with KB3003743 GDR) [policy hook + extended patch] -6.0.6002.23521 (Windows Vista SP2 with KB3003743 LDR) [policy hook + extended patch] -6.1.X.X (Windows 7, any) [policy hook only] -6.1.7100.0 (Windows 7 Release Candidate) [todo] -6.1.7600.16385 (Windows 7) [policy hook + extended patch] -6.1.7600.20661 (Windows 7 with KB951422) [todo] -6.1.7600.21085 (Windows 7 with KB951422 v2) [todo] -6.1.7600.20621 (Windows 7 with KB979470) [todo] -6.1.7600.20890 (Windows 7 with KB2479710) [policy hook + extended patch] -6.1.7600.21316 (Windows 7 with KB2750090) [policy hook + extended patch] -6.1.7600.21420 (Windows 7 with KB2800789) [todo] -6.1.7601.17514 (Windows 7 SP1) [policy hook + extended patch] -6.1.7601.21855 (Windows 7 SP1 with KB951422 v2) [todo] -6.1.7601.21650 (Windows 7 SP1 with KB2479710) [policy hook + extended patch] -6.1.7601.21866 (Windows 7 SP1 with KB2647409) [policy hook + extended patch] -6.1.7601.22104 (Windows 7 SP1 with KB2750090) [policy hook + extended patch] -6.1.7601.22213 (Windows 7 SP1 with KB2800789) [todo] -6.1.7601.22476 (Windows 7 SP1 with KB2870165) [todo] -6.1.7601.22435 (Windows 7 SP1 with KB2878424) [todo] -6.1.7601.22477 (Windows 7 SP1 with KB2896256) [todo] -6.1.7601.18540 (Windows 7 SP1 with KB2984972 GDR) [policy hook + extended patch] -6.1.7601.22750 (Windows 7 SP1 with KB2984972 LDR) [policy hook + extended patch] -6.1.7601.18637 (Windows 7 SP1 with KB3003743 GDR) [policy hook + extended patch] -6.1.7601.22843 (Windows 7 SP1 with KB3003743 LDR) [policy hook + extended patch] -6.1.7601.23403 (Windows 7 SP1 with KB3125574) [policy hook + extended patch] -6.1.7601.24234 (Windows 7 SP1 with KB4462923) [policy hook + extended patch] -6.2.8102.0 (Windows 8 Developer Preview) [policy hook + extended patch] -6.2.8250.0 (Windows 8 Consumer Preview) [policy hook + extended patch] -6.2.8400.0 (Windows 8 Release Preview) [policy hook + extended patch] -6.2.9200.16384 (Windows 8) [policy hook + extended patch] -6.2.9200.17048 (Windows 8 with KB2973501 GDR) [policy hook + extended patch] -6.2.9200.21166 (Windows 8 with KB2973501 LDR) [policy hook + extended patch] -6.3.9431.0 (Windows 8.1 Preview) [init hook + extended patch] -6.3.9600.16384 (Windows 8.1) [init hook + extended patch] -6.3.9600.17095 (Windows 8.1 with KB2959626) [init hook + extended patch] -6.3.9600.17415 (Windows 8.1 with KB3000850) [init hook + extended patch] -6.3.9600.18692 (Windows 8.1 with KB4022720) [init hook + extended patch] -6.3.9600.18708 (Windows 8.1 with KB4025335) [init hook + extended patch] -6.3.9600.18928 (Windows 8.1 with KB4088876) [init hook + extended patch] -6.3.9600.19093 (Windows 8.1 with KB4343891) [init hook + extended patch] -6.4.9841.0 (Windows 10 Technical Preview) [init hook + extended patch] -6.4.9860.0 (Windows 10 Technical Preview UP1) [init hook + extended patch] -6.4.9879.0 (Windows 10 Technical Preview UP2) [init hook + extended patch] -10.0.9926.0 (Windows 10 Pro Technical Preview) [init hook + extended patch] -10.0.10041.0 (Windows 10 Pro Technical Preview UP1) [init hook + extended patch] -10.0.10049.0 (Windows 10 Pro Technical Preview UP2) [todo] -10.0.10061.0 (Windows 10 Pro Technical Preview UP3) [todo] -10.0.10240.16384 (Windows 10 RTM) [init hook + extended patch] -10.0.10525.0 (Windows 10 th2_release.150812-1658) [todo] -10.0.10532.0 (Windows 10 th2_release.150822-1406) [todo] -10.0.10547.0 (Windows 10 th2_release.150913-1511) [todo] -10.0.10586.0 (Windows 10 th2_release.151029-1700) [init hook + extended patch] -10.0.10586.589 (Windows 10 th2_release.160906-1759) [init hook + extended patch] -10.0.11082.1000 (Windows 10 rs1_release.151210-2021) [init hook + extended patch] -10.0.11102.1000 (Windows 10 rs1_release.160113-1800) [init hook + extended patch] -10.0.14251.1000 (Windows 10 rs1_release.160124-1059) [init hook + extended patch] -10.0.14271.1000 (Windows 10 rs1_release.160218-2310) [init hook + extended patch] -10.0.14279.1000 (Windows 10 rs1_release.160229-1700) [init hook + extended patch] -10.0.14295.1000 (Windows 10 rs1_release.160318-1628) [init hook + extended patch] -10.0.14300.1000 (Windows Server 2016 Technical Preview 5) [init hook + extended patch] -10.0.14316.1000 (Windows 10 rs1_release.160402-2227) [init hook + extended patch] -10.0.14328.1000 (Windows 10 rs1_release.160418-1609) [init hook + extended patch] -10.0.14332.1001 (Windows 10 rs1_release.160422-1940) [init hook + extended patch] -10.0.14342.1000 (Windows 10 rs1_release.160506-1708) [init hook + extended patch] -10.0.14352.1002 (Windows 10 rs1_release.160522-1930) [init hook + extended patch] -10.0.14366.0 (Windows 10 rs1_release.160610-1700) [init hook + extended patch] -10.0.14367.0 (Windows 10 rs1_release.160613-1700) [init hook + extended patch] -10.0.14372.0 (Windows 10 rs1_release.160620-2342) [init hook + extended patch] -10.0.14379.0 (Windows 10 rs1_release.160627-1607) [init hook + extended patch] -10.0.14383.0 (Windows 10 rs1_release.160701-1839) [init hook + extended patch] -10.0.14385.0 (Windows 10 rs1_release.160706-1700) [init hook + extended patch] -10.0.14388.0 (Windows 10 rs1_release.160709-1635) [init hook + extended patch] -10.0.14393.0 (Windows 10 rs1_release.160715-1616) [init hook + extended patch] -10.0.14393.1198 (Windows 10 rs1_release_sec.170427-1353) [init hook + extended patch] -10.0.14393.1737 (Windows 10 rs1_release_inmarket.170914-1249) [init hook + extended patch] -10.0.14393.2457 (Windows 10 rs1_release_inmarket.180822-1743) [init hook + extended patch] -10.0.14901.1000 (Windows 10 rs_prerelease.160805-1700) [init hook + extended patch] -10.0.14905.1000 (Windows 10 rs_prerelease.160811-1739) [init hook + extended patch] -10.0.14915.1000 (Windows 10 rs_prerelease.160826-1902) [init hook + extended patch] -10.0.14926.1000 (Windows 10 rs_prerelease.160910-1529) [init hook + extended patch] -10.0.14931.1000 (Windows 10 rs_prerelease.160916-1700) [init hook + extended patch] -10.0.14936.1000 (Windows 10 rs_prerelease.160923-1700) [init hook + extended patch] -10.0.14942.1000 (Windows 10 rs_prerelease.161003-1929) [init hook + extended patch] -10.0.14946.1000 (Windows 10 rs_prerelease.161007-1700) [init hook + extended patch] -10.0.14951.1000 (Windows 10 rs_prerelease.161014-1700) [init hook + extended patch] -10.0.14955.1000 (Windows 10 rs_prerelease.161020-1700) [init hook + extended patch] -10.0.14959.1000 (Windows 10 rs_prerelease.161026-1700) [init hook + extended patch] -10.0.14965.1001 (Windows 10 rs_prerelease.161104-1700) [init hook + extended patch] -10.0.14971.1000 (Windows 10 rs_prerelease.161111-1700) [init hook + extended patch] -10.0.14986.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.14997.1001 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15002.1001 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15007.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15014.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15019.1000 (Windows 10 rs_prerelease.170121-1513) [init hook + extended patch] -10.0.15025.1000 (Windows 10 rs_prerelease.170127-1750) [init hook + extended patch] -10.0.15031.0 (Windows 10 rs2_release.170204-1546) [init hook + extended patch] -10.0.15042.0 (Windows 10 rs2_release.170219-2329) [init hook + extended patch] -10.0.15046.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15048.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15055.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15058.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15061.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15063.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15063.296 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15063.994 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.15063.1155 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16179.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16184.1001 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16199.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16215.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16232.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16237.1001 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16241.1001 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16251.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16251.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16257.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16257.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16273.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16275.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16278.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16281.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16288.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16291.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16294.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16296.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16299.0 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16299.15 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16353.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.16362.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17004.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17017.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17025.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17035.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17040.1000 (Windows 10 WinBuild.160101.0800) [todo] -10.0.17046.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17063.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17074.1002 (Windows 10 WinBuild.160101.0800) [todo] -10.0.17083.1000 (Windows 10 WinBuild.160101.0800) [todo] -10.0.17115.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17128.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17133.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17134.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17723.1000 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] -10.0.17763.1 (Windows 10 WinBuild.160101.0800) [init hook + extended patch] - -Source code changelog (rdpwrap library): - -2018.10.10 : -- added support for termsrv.dll 6.1.7601.24234 x86 - -2018.10.04 : -- added support for termsrv.dll 10.0.14393.2457 x86 - -2018.10.03 : -- added support for termsrv.dll 6.1.7601.24234 x64 -- added support for termsrv.dll 10.0.15063.994 x64 -- added support for termsrv.dll 10.0.17723.1000 x64 -- added support for termsrv.dll 10.0.17763.1 - -2018.09.10 : -- added support for termsrv.dll 6.1.7600.20890 -- added support for termsrv.dll 6.1.7600.21316 -- added support for termsrv.dll 6.1.7601.21650 -- added support for termsrv.dll 6.1.7601.21866 -- added support for termsrv.dll 6.1.7601.22104 -- added support for termsrv.dll 6.3.9600.19093 -- added support for termsrv.dll 10.0.14393.2457 x64 -- added support for termsrv.dll 10.0.15063.1155 x64 - -2018.05.16 : -- added support for termsrv.dll 10.0.17115.1 -- added support for termsrv.dll 10.0.17128.1 -- added support for termsrv.dll 10.0.17133.1 -- added support for termsrv.dll 10.0.17134.1 - -2018.03.26 : -- added support for termsrv.dll 6.3.9600.18928 by 1nd1g0 - -2017.12.27 : -- added support for termsrv.dll 10.0.17017.1000 -- added support for termsrv.dll 10.0.17025.1000 -- added support for termsrv.dll 10.0.17035.1000 -- added support for termsrv.dll 10.0.17046.1000 -- added support for termsrv.dll 10.0.17063.1000 - -2017.10.13 : -- added support for termsrv.dll 10.0.14393.1737 -- added support for termsrv.dll 10.0.16299.0 -- added support for termsrv.dll 10.0.16299.15 -- added support for termsrv.dll 10.0.17004.1000 - -2017.09.24 : -- added support for termsrv.dll 10.0.16291.0 -- added support for termsrv.dll 10.0.16294.1 -- added support for termsrv.dll 10.0.16296.0 -- added support for termsrv.dll 10.0.16362.1000 - -2017.09.15 : -- added support for termsrv.dll 10.0.16288.1 - -2017.09.06 : -- added support for termsrv.dll 10.0.16273.1000 -- added support for termsrv.dll 10.0.16275.1000 -- added support for termsrv.dll 10.0.16278.1000 -- added support for termsrv.dll 10.0.16281.1000 -- added support for termsrv.dll 10.0.16353.1000 - -2017.08.04 : -- added support for termsrv.dll 10.0.16257.1 -- added support for termsrv.dll 10.0.16257.1000 - -2017.07.30 : -- added support for termsrv.dll 6.3.9600.18708 -- added support for termsrv.dll 10.0.16232.1000 -- added support for termsrv.dll 10.0.16237.1001 -- added support for termsrv.dll 10.0.16241.1001 -- added support for termsrv.dll 10.0.16251.0 -- added support for termsrv.dll 10.0.16251.1000 - -2017.06.29 : -- added support for termsrv.dll 6.3.9600.18692 - -2017.06.10 : -- added support for termsrv.dll 10.0.15063.296 -- added support for termsrv.dll 10.0.16215.1000 - -2017.05.29 : -- added support for termsrv.dll 10.0.16199.1000 - -2017.05.17 : -- added support for termsrv.dll 10.0.14997.1001 x64 - -2017.05.12 : -- added support for termsrv.dll 10.0.14393.1198 x86 - -2017.05.03 : -- added support for termsrv.dll 10.0.16179.1000 -- added support for termsrv.dll 10.0.16184.1001 - -2017.03.22 : -- added support for termsrv.dll 10.0.15063.0 - -2017.03.21 : -- added support for termsrv.dll 10.0.15061.0 - -2017.03.16 : -- added support for termsrv.dll 10.0.15058.0 - -2017.03.14 : -- added support for termsrv.dll 10.0.15055.0 - -2017.03.05 : -- added support for termsrv.dll 10.0.15048.0 - -2017.03.02 : -- added support for termsrv.dll 10.0.15046.0 - -2017.03.01 : -- added support for termsrv.dll 10.0.15031.0 -- added support for termsrv.dll 10.0.15042.0 - -2017.02.03 : -- added support for termsrv.dll 10.0.15025.1000 x64 - -2017.01.28 : -- added support for termsrv.dll 10.0.15019.1000 - -2017.01.21 : -- added support for termsrv.dll 10.0.15014.1000 - -2017.01.15 : -- added support for termsrv.dll 10.0.15007.1000 - -2017.01.12 : -- added support for termsrv.dll 10.0.15002.1001 - -2016.12.23 : -- added support for termsrv.dll 10.0.14986.1000 - -2016.11.19 : -- added support for termsrv.dll 10.0.14959.1000 -- added support for termsrv.dll 10.0.14965.1001 -- added support for termsrv.dll 10.0.14971.1000 - -2016.10.28 : -- added support for termsrv.dll 10.0.14955.1000 - -2016.10.21 : -- added support for termsrv.dll 10.0.14951.1000 - -2016.10.19 : -- added support for termsrv.dll 10.0.14946.1000 - -2016.10.08 : -- added support for termsrv.dll 10.0.14942.1000 - -2016.09.30 : -- added support for termsrv.dll 10.0.14936.1000 - -2016.09.27 : -- added support for termsrv.dll 10.0.14931.1000 - -2016.09.15 : -- added support for termsrv.dll 10.0.14926.1000 - -2016.09.14 : -- added support for termsrv.dll 10.0.10586.589 - -2016.09.03 : -- added support for termsrv.dll 10.0.14915.1000 - -2016.08.28 : -- added support for termsrv.dll 6.1.7601.23403 -- added support for termsrv.dll 10.0.14901.1000 -- added support for termsrv.dll 10.0.14905.1000 - -2016.08.12 : -- added support for termsrv.dll 10.0.14385.0 - -2016.08.01 : -- preparing the release - -2016.07.23 : -- added online install mode to installer -- added feature to keep settings on uninstall -- fixed update firewall rule on port change in config tool -- added feature to hide users on logon - -2016.07.22 : -- added support for termsrv.dll 10.0.14393.0 - -2016.07.15 : -- added support for termsrv.dll 10.0.14383.0 -- added support for termsrv.dll 10.0.14388.0 - -2016.07.06 : -- added support for termsrv.dll 10.0.14379.0 - -2016.06.27 : -- added support for termsrv.dll 10.0.14372.0 x86 - -2016.06.26 : -- added support for termsrv.dll 10.0.14372.0 x64 by kbmorris - -2016.06.17 : -- fixed issue with termsrv.dll 10.0.14352.1002 -- added support for termsrv.dll 10.0.14366.0 -- added support for termsrv.dll 10.0.14367.0 - -2016.05.30 : -- added support for termsrv.dll 10.0.14352.1002 - -2016.05.14 : -- added support for termsrv.dll 10.0.14342.1000 - -2016.05.08 : -- added support for termsrv.dll 10.0.14300.1000 x64 -- added support for termsrv.dll 10.0.14328.1000 - -2016.04.29 : -- added support for termsrv.dll 10.0.14332.1001 by maxpiva - -2016.04.14 : -- added support for termsrv.dll 10.0.14316.1000 - -2016.04.06 : -- added support for termsrv.dll 10.0.14295.1000 - -2016.03.07 : -- added experimental codes for ARMv7 architecture (see rdpwrap-arm-kb.ini) -- Windows RT / termsrv.dll 6.2.9200.16384 -- Windows RT 8.1 / termsrv.dll 6.3.9600.16384 -- Windows RT 8.1 / termsrv.dll 6.3.9600.17095 - -2016.03.06 : -- added support for termsrv.dll 10.0.14279.1000 - -2016.02.29 : -- added support for termsrv.dll 10.0.14271.1000 - -2016.01.28 : -- added support for termsrv.dll 10.0.14251.1000 - -2016.01.26 : -- added support for termsrv.dll 10.0.11102.1000 - -2016.01.15 : -- updated messages in the installer -- added support for termsrv.dll 10.0.11082.1000 - -2015.11.14 : -- added support for termsrv.dll 10.0.10586.0 - -2015.08.11 : -- embed new rdpclip versions in the installer (for NT 6.0 and 6.1) -- preparing the release - -2015.08.07 : -- added INI update feature to installer - -2015.07.30 : -- fixed issue with Windows 10 Home x86 (wrong LocalOnly offset was specified in INI file) - -2015.07.17 : -- added support for termsrv.dll 10.0.10240.16384 -- added HOW TO hints to KB (so other reverse engineers can do this hard work more easier) - -2015.07.16 : -- moved all comments from INI file to Knowledge Base text file -- now INI file have smaller size -- updated RDP checker: changed IP Address to 127.0.0.2 (sometimes client doesn't want to connect .1), updated text message -- updated RDP config: list all possible shadowing modes, also write group policy -- updated installer: added workaround for 1056 error -- updated copyright years in source code -- obtained files from build 10.0.10240.16384 -- researching Windows 10 RTM - -2015.03.23 : -- researching Windows 10 Pro Technical Preview UP1 -- added support for termsrv.dll 10.0.10041.0 - -2015.03.20 : -- new build 10.0.10041.0 was released, obtaining files... - -2015.01.26 : -- researching Windows 10 Pro Technical Preview (10.0.9926.0 x86) -- added support for termsrv.dll 10.0.9926.0 (x86) - -2015.01.22 : -- v-yadli contributed offsets for version 10.0.9926.0 (x64) - -2014.12.13 : -- added more policy values to INI file - -2014.12.10 : -- C++ version seems to work well now! -- added support for termsrv.dll 6.4.9879.0 -- preparing the new release - -2014.12.09 : -- many bug fixes in C++ version, you can track it in the git history :) -- it can be compiled now :D -- we are getting closer to the finish line! - -2014.12.03 : -- added INI reader by Fusix for C++ version -- asulwer also helped with the development - -2014.11.25 : -- corrected some typos in INI file -- added EasyPrint policy value - -2014.11.24 : -- added support for termsrv.dll 6.3.9600.17415 - -2014.11.21 : -- new LiteINI module to read INI files -- added support to store patch settings in INI file -- version support can be extended without recompilation -- C++ version needs to be updated - -2014.11.20 : -- improved comments -- researching KB3000850 -- found required files -- improving RDPWrap... -- placing signatures, offsets, values, etc in separate config file -- working with code - -2014.11.13 : -- researching KB3003743 -- added support for version 6.0.6002.19214 -- added support for version 6.0.6002.23521 -- added support for version 6.1.7601.18637 -- added support for version 6.1.7601.22843 - -2014.11.02 : -- researching termsrv.dll 6.4.9860.0 -- done - -2014.10.19 : -- added support for version 6.0.6000.16386 (x64) -- added support for version 6.0.6001.18000 (x64) -- added support for version 6.1.7600.16385 - -2014.10.18 : -- corrected some typos in source -- simplified signature constants -- added support for version 6.0.6000.16386 (x86) -- added support for version 6.0.6001.18000 (x86) -- added support for version 6.0.6002.18005 -- added support for version 6.1.7601.17514 -- added support for version 6.1.7601.18540 -- added support for version 6.1.7601.22750 -- added support for version 6.2.9200.17048 -- added support for version 6.2.9200.21166 - -2014.10.17 : -- collecting information about all versions of Terminal Services beginning from Vista -- added [todo] to the versions list - -2014.10.16 : -- got new updates: KB2984972 for Win 7 (still works with 2 concurrent users) and KB2973501 for Win 8 (doesn't work) - -2014.10.02 : -- researching Windows 10 TP Remote Desktop -- done! even without debugging symbols ^^) - -2014.07.20 : -- added support for Windows 8 Release Preview -- added support for Windows 8 Consumer Preview -- added support for Windows 8 Developer Preview - -2014.07.19 : -- improved patching of Windows 8 -- added policy patches -- will patch CDefPolicy::Query -- will patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled - -2014.07.18 : -- researched patched files from MDL forum -- CSLQuery::GetMaxSessions requires no patching -- it's better to change the default policy, so... -- will patch CDefPolicy::Query -- will patch CEnforcementCore::GetInstanceOfTSLicense -- will patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled -- the function CSLQuery::Initialize is hooked correctly - -2014.07.17 : -- will hook only CSLQuery::Initialize function -- CSLQuery::GetMaxSessions will be patched -- added x86 signatures for 6.3.9431.0 (Windows 8.1 Preview) - -2014.07.16 : -- changing asm opcodes is bad, will hook CSL functions - -2014.07.15 : -- added x86 signatures for 6.3.9600.16384 (Windows 8.1) -2014.07.15 : -- added x86 signatures for 6.3.9600.17095 (Windows 8.1 with KB2959626) diff --git a/tools/build-local.ps1 b/tools/build-local.ps1 new file mode 100644 index 0000000..bbe1c1e --- /dev/null +++ b/tools/build-local.ps1 @@ -0,0 +1,259 @@ +#!/usr/bin/env pwsh +# tools/build-local.ps1 +# Full local build: C++ DLLs + C# tools → ./build/ +# +# Usage (run from repo root): +# .\tools\build-local.ps1 # full build +# .\tools\build-local.ps1 -SkipCpp # skip C++ DLL (faster for C# iteration) +# .\tools\build-local.ps1 -SkipMsi # skip MSI build (no WiX needed) +# +# See docs/BUILDING.md for prerequisites and troubleshooting. + +#Requires -Version 5 + +param( + [switch]$SkipCpp, + [switch]$SkipIcons, + [switch]$SkipMsi +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +$REPO = $PSScriptRoot | Split-Path -Parent +$BUILD = Join-Path $REPO "build" + +# ─── Helpers ────────────────────────────────────────────────────────────────── + +function Step([string]$msg) { + Write-Host "`n==> $msg" -ForegroundColor Cyan +} + +function Fail([string]$msg) { + Write-Host "[FAIL] $msg" -ForegroundColor Red + exit 1 +} + +# ─── Locate MSBuild ─────────────────────────────────────────────────────────── + +function Find-MSBuild { + $candidates = @( + # VS 2022 Build Tools / Community + "${env:ProgramFiles}\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.exe", + "${env:ProgramFiles}\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\MSBuild.exe", + "${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\MSBuild.exe", + # VS 2019 Build Tools / Community + "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.exe", + "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\amd64\MSBuild.exe", + "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\MSBuild.exe" + ) + foreach ($p in $candidates) { + if (Test-Path $p) { return $p } + } + # Fall back to PATH + $found = Get-Command msbuild -ErrorAction SilentlyContinue + if ($found) { return $found.Source } + return $null +} + +# ─── 0. Stamp INI date ──────────────────────────────────────────────────────── + +Step "Stamping rdpwrap.ini with today's date" +$today = Get-Date -Format "yyyy-MM-dd" +$iniFile = "$REPO\msi\rdpwrap.ini" +(Get-Content $iniFile) -replace '^Updated=.*', "Updated=$today" | Set-Content $iniFile +Write-Host " Updated= $today" + +# Stage INI into RDPWInst embedded resources so it gets compiled in +$iniDest = "$REPO\src-csharp\RDPWInst\Resources\rdpwrap.ini" +New-Item -Force -ItemType Directory (Split-Path $iniDest) | Out-Null +Copy-Item $iniFile $iniDest -Force +Write-Host " Staged: src-csharp/RDPWInst/Resources/rdpwrap.ini" + +# ─── 1. Icons ───────────────────────────────────────────────────────────────── + +if (-not $SkipIcons) { + Step "Generating application icons" + & "$REPO\tools\make-icons.ps1" +} + +# ─── 2. C++ DLLs ────────────────────────────────────────────────────────────── + +if (-not $SkipCpp) { + Step "Building C++ DLLs (x64 + Win32)" + + $msbuild = Find-MSBuild + if (-not $msbuild) { + Fail "MSBuild not found. Install Visual Studio 2019 or 2022 Build Tools with 'Desktop development with C++'." + } + Write-Host " Using MSBuild: $msbuild" + + $msbuildArgs = @( + "$REPO\src-x86-x64-Fusix\RDPWrap.sln", + "/p:Configuration=Release", + "/p:PlatformToolset=v143", + "/p:WindowsTargetPlatformVersion=10.0", + "/m", "/v:m" + ) + + foreach ($platform in @("x64", "Win32", "ARM64")) { + Write-Host " Building $platform..." + & $msbuild @msbuildArgs "/p:Platform=$platform" + if ($LASTEXITCODE -ne 0) { Fail "MSBuild failed for $platform" } + } +} else { + Write-Host "[skip] C++ DLL build (-SkipCpp)" -ForegroundColor Yellow +} + +# ─── 3. C# tools ────────────────────────────────────────────────────────────── + +Step "Publishing C# tools" + +# Verify dotnet +$dotnetVer = (dotnet --version 2>&1) +Write-Host " .NET SDK: $dotnetVer" + +$tools = @("RDPConf", "RDPCheck", "RDPWInst") +$rids = @("win-x64", "win-x86", "win-arm64") + +foreach ($tool in $tools) { + foreach ($rid in $rids) { + $arch = $rid -replace "win-", "" + $staging = Join-Path $BUILD "staging\$tool\$rid" + Write-Host " $tool / $rid → $staging" + + dotnet publish "$REPO\src-csharp\$tool\$tool.csproj" ` + -c Release -r $rid ` + --self-contained true ` + -p:PublishSingleFile=true ` + -p:IncludeNativeLibrariesForSelfExtract=true ` + -p:PublishTrimmed=false ` + -p:Version=1.0.0 ` + -o $staging ` + --nologo -v quiet + + if ($LASTEXITCODE -ne 0) { Fail "dotnet publish failed for $tool/$rid" } + } +} + +# ─── 4. Assemble build/ ─────────────────────────────────────────────────────── + +Step "Assembling ./build/" + +New-Item -Force -ItemType Directory $BUILD | Out-Null + +# C++ DLLs +if (-not $SkipCpp) { + $dllMap = @{ + "rdpwrap_x64.dll" = "$REPO\src-x86-x64-Fusix\Release\x64\RDPWrap.dll" + "rdpwrap_x86.dll" = "$REPO\src-x86-x64-Fusix\Release\x86\RDPWrap.dll" + "rdpwrap_arm64.dll" = "$REPO\src-x86-x64-Fusix\Release\arm64\RDPWrap.dll" + } + foreach ($dest in $dllMap.Keys) { + $src = $dllMap[$dest] + if (Test-Path $src) { + Copy-Item $src "$BUILD\$dest" -Force + Write-Host " Copied: $dest" + } else { + Write-Warning " Not found (DLL build skipped?): $src" + } + } +} + +# C# executables +foreach ($tool in $tools) { + foreach ($rid in $rids) { + $arch = $rid -replace "win-", "" + $src = "$BUILD\staging\$tool\$rid\$tool.exe" + $dest = "$BUILD\${tool}_${arch}.exe" + if (Test-Path $src) { + Copy-Item $src $dest -Force + Write-Host " Copied: ${tool}_${arch}.exe" + } else { + Write-Warning " Not found: $src" + } + } +} + +# INI file (side-by-side with installer, and for reference) +Copy-Item $iniFile "$BUILD\rdpwrap.ini" -Force +Write-Host " Copied: rdpwrap.ini" + +# Remove staging area +Remove-Item -Recurse -Force "$BUILD\staging" -ErrorAction SilentlyContinue + +# ─── 5. MSI ─────────────────────────────────────────────────────────────────── + +if (-not $SkipMsi) { + Step "Building MSI (WiX v5)" + + $wixProj = "$REPO\msi\RDPWInst.wixproj" + $pkgVer = Get-Date -Format "yy.M.d" # MSI version: major<=255, e.g. 26.4.1 + + foreach ($arch in @('x64', 'x86', 'arm64')) { + # Verify this arch's inputs exist in build/ + $required = @( + "$BUILD\RDPWInst_$arch.exe", + "$BUILD\RDPConf_$arch.exe", + "$BUILD\RDPCheck_$arch.exe", + "$BUILD\rdpwrap_$arch.dll", + "$BUILD\rdpwrap.ini" + ) + $missing = $required | Where-Object { -not (Test-Path $_) } + if ($missing) { + Write-Warning " Skipping $arch MSI -- missing inputs:`n $($missing -join "`n ")" + continue + } + + # Stage inputs next to the .wixproj (WiX resolves Source= relative to the project) + foreach ($inputFile in $required) { + Copy-Item $inputFile "$REPO\msi\" -Force -ErrorAction Continue + } + + # Explicit OutputPath per-arch avoids WiX placing all builds in the same bin/x86 dir. + # Explicit OutputName overrides the $(Platform) token which WiX doesn't expand in OutputName. + $outDir = Join-Path $REPO "msi_out\$arch" + $wixOut = Join-Path $outDir "RDPWrapper-$arch.msi" + New-Item -Force -ItemType Directory $outDir | Out-Null + + # Use Continue so a non-zero exit from dotnet/WiX does NOT throw under ErrorActionPreference=Stop + $buildArgs = @('build', $wixProj, '-c', 'Release', + "/p:Platform=$arch", + "/p:OutputName=RDPWrapper-$arch", + "/p:OutputPath=$outDir", + "/p:PackageVersion=$pkgVer", + '--nologo') + & dotnet @buildArgs + $wixExit = $LASTEXITCODE + if ($wixExit -ne 0) { + Write-Warning " MSI build failed for $arch (exit $wixExit) -- continuing." + continue + } + + $msiSrc = if (Test-Path $wixOut) { + Get-Item $wixOut + } else { + # Fallback: WiX may insert a locale subdir (e.g. msi_out/x64/en-US/…) + Get-ChildItem $outDir -Recurse -Filter "RDPWrapper-$arch.msi" -ErrorAction SilentlyContinue | + Sort-Object LastWriteTime -Descending | Select-Object -First 1 + } + if ($msiSrc) { + $dest = Join-Path $BUILD "RDPWrapper-$pkgVer-$arch.msi" + Copy-Item $msiSrc.FullName $dest -Force + Write-Host (" Produced: RDPWrapper-$pkgVer-$arch.msi ({0:N1} MB)" -f ($msiSrc.Length / 1MB)) + } else { + Write-Warning " MSI output not found after $arch build." + } + } +} else { + Write-Host "[skip] MSI build (-SkipMsi)" -ForegroundColor Yellow +} + +# ─── 6. Summary ─────────────────────────────────────────────────────────────── + +Step "Build complete" +Get-ChildItem $BUILD | Sort-Object Name | ForEach-Object { + $kb = [math]::Round($_.Length / 1KB, 0) + Write-Host (" {0,-28} {1,6} KB" -f $_.Name, $kb) +} +Write-Host "" diff --git a/tools/make-icons.ps1 b/tools/make-icons.ps1 new file mode 100644 index 0000000..c8c13b6 --- /dev/null +++ b/tools/make-icons.ps1 @@ -0,0 +1,109 @@ +#!/usr/bin/env pwsh +# tools/make-icons.ps1 +# Generates 32×32 ICO files for RDPConf and RDPCheck. +# Requires .NET (Windows / .NET 4.5+). Run from repo root: +# .\tools\make-icons.ps1 +# Output: +# src-csharp/RDPConf/app.ico +# src-csharp/RDPCheck/app.ico + +#Requires -Version 5 + +Add-Type -AssemblyName System.Drawing + +$REPO = Split-Path -Parent $PSScriptRoot + +function New-AppIcon { + param( + [string]$OutPath, + [System.Drawing.Color]$BackColor, + [string]$Letter, + [System.Drawing.Color]$ForeColor = [System.Drawing.Color]::White + ) + + $sz = 32 + $bmp = New-Object System.Drawing.Bitmap($sz, $sz, + [System.Drawing.Imaging.PixelFormat]::Format32bppArgb) + + $g = [System.Drawing.Graphics]::FromImage($bmp) + $g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias + $g.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::ClearTypeGridFit + $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic + + # Rounded-rectangle background + $bg = New-Object System.Drawing.SolidBrush($BackColor) + $r = 5 # corner radius + $path = New-Object System.Drawing.Drawing2D.GraphicsPath + $path.AddArc(0, 0, $r*2, $r*2, 180, 90) + $path.AddArc($sz - $r*2, 0, $r*2, $r*2, 270, 90) + $path.AddArc($sz - $r*2, $sz - $r*2, $r*2, $r*2, 0, 90) + $path.AddArc(0, $sz - $r*2, $r*2, $r*2, 90, 90) + $path.CloseFigure() + $g.FillPath($bg, $path) + + # Centered letter + $font = New-Object System.Drawing.Font( + "Segoe UI", 18, [System.Drawing.FontStyle]::Bold, + [System.Drawing.GraphicsUnit]::Pixel) + $fg = New-Object System.Drawing.SolidBrush($ForeColor) + $sf = New-Object System.Drawing.StringFormat + $sf.Alignment = [System.Drawing.StringAlignment]::Center + $sf.LineAlignment = [System.Drawing.StringAlignment]::Center + $rect = New-Object System.Drawing.RectangleF(0, 0, $sz, $sz) + $g.DrawString($Letter, $font, $fg, $rect, $sf) + + $g.Dispose() + + # --- Encode as PNG then wrap in ICO on-disk --- + $ms = New-Object System.IO.MemoryStream + $bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png) + $png = $ms.ToArray() + $ms.Dispose() + $bmp.Dispose() + + # ICO file format: + # ICONDIR 6 bytes : reserved(2) type=1(2) count=1(2) + # ICONDIRENTRY 16 bytes : w(1),h(1),colors(1),resv(1),planes(2),bits(2),size(4),offset(4) + # PNG data + $null = New-Item -Force -ItemType File $OutPath + $stream = [System.IO.File]::Open($OutPath, + [System.IO.FileMode]::Create, + [System.IO.FileAccess]::Write) + $w = New-Object System.IO.BinaryWriter($stream, + [System.Text.Encoding]::ASCII, $false) + + # ICONDIR + $w.Write([uint16]0) # reserved + $w.Write([uint16]1) # type = ICON + $w.Write([uint16]1) # image count + + # ICONDIRENTRY + $w.Write([byte]$sz) # width (0 = 256) + $w.Write([byte]$sz) # height + $w.Write([byte]0) # color count (0 = true-color) + $w.Write([byte]0) # reserved + $w.Write([uint16]1) # color planes + $w.Write([uint16]32) # bits per pixel + $w.Write([uint32]$png.Length) # image data size + $w.Write([uint32]22) # offset to image data (6 + 16 = 22) + + # PNG bytes + $w.Write($png) + + $w.Close() + $stream.Close() + + Write-Host " Created: $OutPath" +} + +Write-Host "Generating application icons..." + +New-AppIcon -OutPath "$REPO\src-csharp\RDPConf\app.ico" ` + -BackColor ([System.Drawing.Color]::FromArgb(0, 84, 166)) ` + -Letter "C" + +New-AppIcon -OutPath "$REPO\src-csharp\RDPCheck\app.ico" ` + -BackColor ([System.Drawing.Color]::FromArgb(16, 124, 16)) ` + -Letter "K" + +Write-Host "Done." diff --git a/tools/sergiye-hashes.json b/tools/sergiye-hashes.json new file mode 100644 index 0000000..6279410 --- /dev/null +++ b/tools/sergiye-hashes.json @@ -0,0 +1,18 @@ +{ + "_comment": [ + "This file pins the expected SHA-256 hashes of the rdpWrapper binaries downloaded", + "from https://github.com/sergiye/rdpWrapper/releases during the build-and-release.yml CI run.", + "", + "How to update after a new sergiye release:", + " 1. Download rdpWrapper_x64.exe and rdpWrapper_x86.exe from the release page.", + " 2. Run: Get-FileHash rdpWrapper_x64.exe -Algorithm SHA256", + " 3. Update the hashes and 'release' field below, then open a PR.", + "", + "If this file contains an empty 'release' string the verification step is SKIPPED", + "(bootstrap / first-run scenario). Set a real release tag once the first verified", + "download has been confirmed." + ], + "release": "2.10", + "rdpWrapper_x64.exe": "EAEE55CA7813E728177295770C52FBE6287DF7A49999426E0C71D916B3DF841F", + "rdpWrapper_x86.exe": "F59FE1DA29965F2FB001655C9F856BE5FD903BBCB7D92E807268C4D7B40D5AF8" +} diff --git a/tools/update-sergiye-hashes.ps1 b/tools/update-sergiye-hashes.ps1 new file mode 100644 index 0000000..73e2d51 --- /dev/null +++ b/tools/update-sergiye-hashes.ps1 @@ -0,0 +1,106 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS + Fetches the latest sergiye/rdpWrapper release, downloads the x64 and x86 GUI + executables, computes their SHA-256 hashes, and writes them to + tools/sergiye-hashes.json — ready to commit. + +.DESCRIPTION + Run this script locally (or in CI) immediately after a new sergiye/rdpWrapper + release is published, then commit the updated JSON file. Once the file contains + a non-empty 'release' key, build-and-release.yml will enforce the hashes on every + subsequent release run and fail the workflow if the downloaded files differ. + +.PARAMETER OutFile + Path to the JSON hash file to update. Defaults to tools/sergiye-hashes.json + relative to the script's parent directory. + +.PARAMETER GithubToken + Optional GitHub personal access token (or value of GITHUB_TOKEN env var) to + avoid API rate-limiting during repeated local runs. + +.EXAMPLE + # Run from the repo root: + pwsh tools/update-sergiye-hashes.ps1 + +.EXAMPLE + # Override output path: + pwsh tools/update-sergiye-hashes.ps1 -OutFile ./my-hashes.json +#> +[CmdletBinding()] +param( + [string] $OutFile = $null, + [string] $GithubToken = $env:GITHUB_TOKEN +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +# ── Resolve paths ───────────────────────────────────────────────────────────── +$repoRoot = Split-Path $PSScriptRoot -Parent +if (-not $OutFile) { + $OutFile = Join-Path $repoRoot 'tools\sergiye-hashes.json' +} + +# ── Fetch latest release metadata from GitHub API ───────────────────────────── +$apiUrl = 'https://api.github.com/repos/sergiye/rdpWrapper/releases/latest' +$headers = @{ Accept = 'application/vnd.github+json'; 'X-GitHub-Api-Version' = '2022-11-28' } +if ($GithubToken) { $headers['Authorization'] = "Bearer $GithubToken" } + +Write-Host "Querying GitHub API: $apiUrl" +$release = Invoke-RestMethod -Uri $apiUrl -Headers $headers -UseBasicParsing +$tag = $release.tag_name +Write-Host "Latest sergiye release: $tag" + +# ── Locate the two assets we pin ────────────────────────────────────────────── +$needed = @('rdpWrapper_x64.exe', 'rdpWrapper_x86.exe') +$assets = @{} +foreach ($name in $needed) { + $asset = $release.assets | Where-Object { $_.name -eq $name } + if (-not $asset) { + throw "Asset '$name' not found in release $tag. Available: $($release.assets.name -join ', ')" + } + $assets[$name] = $asset.browser_download_url + Write-Host " Found $name → $($asset.browser_download_url)" +} + +# ── Download to a temp directory and hash ───────────────────────────────────── +$tmp = Join-Path ([IO.Path]::GetTempPath()) "sergiye-hash-$([guid]::NewGuid().ToString('N'))" +$null = New-Item -ItemType Directory -Path $tmp -Force +$hashes = @{} + +try { + foreach ($name in $needed) { + $dest = Join-Path $tmp $name + Write-Host "Downloading $name …" + Invoke-WebRequest -Uri $assets[$name] -OutFile $dest -UseBasicParsing + $hash = (Get-FileHash $dest -Algorithm SHA256).Hash + $hashes[$name] = $hash + Write-Host " SHA-256: $hash" + } +} finally { + Remove-Item $tmp -Recurse -Force -ErrorAction SilentlyContinue +} + +# ── Build and write the JSON file ───────────────────────────────────────────── +$existing = @{ '_comment' = @() } +if (Test-Path $OutFile) { + $existing = Get-Content $OutFile -Raw | ConvertFrom-Json -AsHashtable +} + +$output = [ordered]@{ + '_comment' = $existing['_comment'] # preserve explanatory comment + 'release' = $tag + 'rdpWrapper_x64.exe' = $hashes['rdpWrapper_x64.exe'] + 'rdpWrapper_x86.exe' = $hashes['rdpWrapper_x86.exe'] +} + +$json = $output | ConvertTo-Json -Depth 5 +Set-Content -Path $OutFile -Value $json -Encoding UTF8 +Write-Host "" +Write-Host "Written: $OutFile" +Write-Host "" +Write-Host "Next steps:" +Write-Host " 1. Review the diff: git diff tools/sergiye-hashes.json" +Write-Host " 2. Commit: git add tools/sergiye-hashes.json && git commit -m 'chore: pin sergiye hashes to $tag'" +Write-Host " 3. Push: git push"