From f53ea780e7622d92ffca81058812612e8c1b6914 Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Sun, 29 Mar 2026 13:24:29 +0100 Subject: [PATCH] Adding in new CI methods, to build and publish --- .github/workflows/build-cpp.yml | 89 ++++++++++++++++++ .github/workflows/publish-ini.yml | 137 +++++++++++++++++++++++++++ README.md | 57 +++++++++--- src-installer/RDPWInst.dpr | 150 +++++++++++++++++++++++++++++- 4 files changed, 417 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/build-cpp.yml create mode 100644 .github/workflows/publish-ini.yml diff --git a/.github/workflows/build-cpp.yml b/.github/workflows/build-cpp.yml new file mode 100644 index 0000000..a0ec763 --- /dev/null +++ b/.github/workflows/build-cpp.yml @@ -0,0 +1,89 @@ +name: Build C++ DLL + +# Trigger on version tags (e.g. v1.7.0) or manually +on: + push: + tags: + - 'v*' + workflow_dispatch: + +permissions: + contents: write + +jobs: + # ── Build x64 and Win32 release DLLs ───────────────────────────────────────── + build: + runs-on: windows-2022 + strategy: + matrix: + platform: [x64, Win32] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + # 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.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/${{ matrix.platform }}/Release/rdpwrap.dll + if-no-files-found: error + + # ── Assemble a GitHub Release from both DLL artifacts ──────────────────────── + release: + needs: build + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + + steps: + - name: Download x64 artifact + uses: actions/download-artifact@v4 + with: + name: rdpwrap-dll-x64 + path: ./dist/x64 + + - name: Download Win32 artifact + uses: actions/download-artifact@v4 + with: + name: rdpwrap-dll-Win32 + path: ./dist/x86 + + - name: Rename DLLs for release + run: | + mv dist/x64/rdpwrap.dll dist/rdpwrap_x64.dll + mv dist/x86/rdpwrap.dll dist/rdpwrap_x86.dll + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + make_latest: false + body: | + ## RDP Wrapper DLL – ${{ github.ref_name }} + + Built from `src-x86-x64-Fusix/` with MSVC v143 (VS 2022). + + | File | Architecture | + |---|---| + | `rdpwrap_x64.dll` | x86-64 (64-bit Windows) | + | `rdpwrap_x86.dll` | x86 (32-bit Windows) | + + > Place the appropriate DLL in `C:\Program Files\RDP Wrapper\rdpwrap.dll` + > and run `RDPWInst.exe -i` to install. + files: | + dist/rdpwrap_x64.dll + dist/rdpwrap_x86.dll diff --git a/.github/workflows/publish-ini.yml b/.github/workflows/publish-ini.yml new file mode 100644 index 0000000..7363bb2 --- /dev/null +++ b/.github/workflows/publish-ini.yml @@ -0,0 +1,137 @@ +name: Publish INI and Offset Finder Tools + +on: + push: + branches: [main, master] + paths: + - 'res/rdpwrap.ini' + - '.github/workflows/publish-ini.yml' + workflow_dispatch: + +permissions: + contents: write + +jobs: + publish: + runs-on: windows-2022 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # ── 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 res/rdpwrap.ini -Raw + $iniDate = if ($iniContent -match 'Updated=([^\r\n]+)') { $Matches[1] } else { 'unknown' } + + echo "date=$date" >> $env:GITHUB_OUTPUT + echo "stamp=$stamp" >> $env:GITHUB_OUTPUT + echo "inidate=$iniDate" >> $env:GITHUB_OUTPUT + + # ── Download the latest RDPWrapOffsetFinder release zip from llccd ────── + - name: Download RDPWrapOffsetFinder + id: finder + shell: pwsh + run: | + $zip = "RDPWrapOffsetFinder.zip" + + # Resolve the real latest-release download URL via the GitHub API + $apiUrl = "https://api.github.com/repos/llccd/RDPWrapOffsetFinder/releases/latest" + $release = Invoke-RestMethod -Uri $apiUrl -Headers @{ "User-Agent" = "rdpwrap-ci" } + $asset = $release.assets | Where-Object { $_.name -like "*.zip" } | Select-Object -First 1 + if (-not $asset) { throw "No zip asset found in latest RDPWrapOffsetFinder release" } + + Write-Host "Downloading $($asset.browser_download_url)" + Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $zip + + # Expand the archive + Expand-Archive -Path $zip -DestinationPath .\finder -Force + + # Diagnostic: show what we got + Write-Host "Zip contents:" + Get-ChildItem -Recurse .\finder | Select-Object FullName + + # Helper: find a file by name pattern, preferring arch-specific subdirs + function Find-Binary($pattern, $archHint) { + $hits = Get-ChildItem -Recurse -Filter $pattern .\finder + # prefer paths that contain the arch hint + $match = $hits | Where-Object { $_.FullName -match $archHint } | Select-Object -First 1 + if (-not $match) { $match = $hits | Select-Object -First 1 } + return $match + } + + $x64exe = Find-Binary "RDPWrapOffsetFinder*.exe" "x64" + $x86exe = Find-Binary "RDPWrapOffsetFinder*.exe" "x86|Win32|32" + $x64dll = Find-Binary "Zydis*.dll" "x64" + $x86dll = Find-Binary "Zydis*.dll" "x86|Win32|32" + + # If only one exe/dll variant exists, use it for both architectures + if (-not $x86exe) { $x86exe = $x64exe } + if (-not $x86dll) { $x86dll = $x64dll } + if (-not $x64exe) { throw "Could not locate RDPWrapOffsetFinder exe in zip" } + if (-not $x64dll) { throw "Could not locate Zydis dll in zip" } + + Copy-Item $x64exe.FullName .\RDPWrapOffsetFinder_x64.exe + Copy-Item $x86exe.FullName .\RDPWrapOffsetFinder_x86.exe + Copy-Item $x64dll.FullName .\Zydis_x64.dll + Copy-Item $x86dll.FullName .\Zydis_x86.dll + + Write-Host "Staged binaries:" + Get-ChildItem .\RDPWrapOffsetFinder_*.exe, .\Zydis_*.dll | + Format-Table Name, Length + + echo "finder_ver=$($release.tag_name)" >> $env:GITHUB_OUTPUT + + # ── Validate the INI has required sections ─────────────────────────────── + - name: Validate INI + shell: pwsh + run: | + $ini = Get-Content res/rdpwrap.ini -Raw + foreach ($section in @('[Main]', '[SLPolicy]', '[PatchCodes]')) { + if ($ini -notmatch [regex]::Escape($section)) { + throw "INI validation failed: missing required section $section" + } + } + $sectionCount = ([regex]::Matches($ini, '^\[[\d\.]+\]', 'Multiline')).Count + Write-Host "INI is valid. Windows-version sections: $sectionCount" + + # ── Create/update a versioned GitHub Release with all assets ───────────── + - name: Publish release + uses: softprops/action-gh-release@v2 + with: + tag_name: "ini-${{ steps.meta.outputs.date }}" + name: "INI Update ${{ steps.meta.outputs.date }}" + make_latest: true + body: | + ## RDP Wrapper — Automated INI Release + + | Field | Value | + |---|---| + | INI `Updated` date | `${{ steps.meta.outputs.inidate }}` | + | Published | ${{ steps.meta.outputs.stamp }} | + | RDPWrapOffsetFinder | ${{ steps.finder.outputs.finder_ver }} | + + ### Assets + | File | Purpose | + |---|---| + | `rdpwrap.ini` | Latest offset database for all known termsrv.dll versions | + | `RDPWrapOffsetFinder_x64.exe` | Auto-generates offsets for unknown x64 Windows builds | + | `RDPWrapOffsetFinder_x86.exe` | Auto-generates offsets for unknown x86 Windows builds | + | `Zydis_x64.dll` / `Zydis_x86.dll` | Required runtime for the offset finder | + + The installer fetches `rdpwrap.ini` from this release automatically. + If your termsrv.dll version is not in the INI, the installer downloads the + offset finder tools and generates the missing section on-the-fly. + files: | + res/rdpwrap.ini + RDPWrapOffsetFinder_x64.exe + RDPWrapOffsetFinder_x86.exe + Zydis_x64.dll + Zydis_x86.dll diff --git a/README.md b/README.md index 837e679..d38bafe 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ -# RDP Wrapper Library by Stas'M +# RDP Wrapper Library + +> **Maintained fork** by [@sjackson0109](https://github.com/sjackson0109) — based on the original work by [Stas'M / binarymaster](https://github.com/stascorp/rdpwrap). [![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) +![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) +[![INI publish](https://github.com/sjackson0109/rdpwrap/actions/workflows/publish-ini.yml/badge.svg)](https://github.com/sjackson0109/rdpwrap/actions/workflows/publish-ini.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) +![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. @@ -64,21 +68,30 @@ 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* :) ### 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* +- **x86 Delphi version** (installer, config tool, checker) — requires *Embarcadero RAD Studio 2010* or later; no automated CI yet +- **x86/x64 C++ version** (`rdpwrap.dll`) — can be built locally with *Visual Studio 2013+*, or automatically via the [Build C++ DLL](.github/workflows/build-cpp.yml) GitHub Actions workflow (uses MSVC v143 / VS 2022) by pushing a `v*` tag + +### CI/CD Pipelines: + +| Workflow | Trigger | Output | +|---|---|---| +| [publish-ini.yml](.github/workflows/publish-ini.yml) | Push to `main`/`master` touching `res/rdpwrap.ini`, or manual | GitHub Release with `rdpwrap.ini`, `RDPWrapOffsetFinder_x64/x86.exe`, `Zydis_x64/x86.dll` | +| [build-cpp.yml](.github/workflows/build-cpp.yml) | Version tag push (`v*`) | GitHub Release with `rdpwrap_x64.dll` and `rdpwrap_x86.dll` | [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 +100,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: @@ -119,7 +138,7 @@ It's recommended to have original termsrv.dll file with the RDP Wrapper installa > 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? @@ -131,7 +150,7 @@ Yes, it works in online mode by default. You may disable it by removing `-o` fla > 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 `res/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 +162,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 `update.bat`. 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 +187,14 @@ Visit [issues](https://github.com/stascorp/rdpwrap/issues) section, and check wh ### Change log: +#### 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** — [`publish-ini.yml`](.github/workflows/publish-ini.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 diff --git a/src-installer/RDPWInst.dpr b/src-installer/RDPWInst.dpr index 6c95f3f..f419d82 100644 --- a/src-installer/RDPWInst.dpr +++ b/src-installer/RDPWInst.dpr @@ -93,6 +93,7 @@ var TermServicePID: DWORD; ShareSvc: Array of String; sShareSvc: String; + TermSrvVerTxt: String; // e.g. '10.0.26100.7623' — set by CheckTermsrvVersion function SupportedArchitecture: Boolean; var @@ -617,7 +618,9 @@ end; function GitINIFile(var Content: String): Boolean; const - URL = 'https://raw.githubusercontent.com/stascorp/rdpwrap/master/res/rdpwrap.ini'; + // Points to the latest release artifact in the sjackson0109 fork. + // The publish-ini CI/CD workflow keeps this asset up to date automatically. + URL = 'https://github.com/sjackson0109/rdpwrap/releases/latest/download/rdpwrap.ini'; var NetHandle: HINTERNET; UrlHandle: HINTERNET; @@ -843,6 +846,138 @@ begin Result := True; end; +{ ────────────────────────────────────────────────────────────────────────────── + DownloadFileToDisk + Downloads the HTTP/HTTPS resource at URL and saves it to DestPath on disk. + Returns True only when the destination file exists and is non-empty. +────────────────────────────────────────────────────────────────────────────── } +function DownloadFileToDisk(const URL, DestPath: String): Boolean; +var + NetHandle: HINTERNET; + UrlHandle: HINTERNET; + FileHandle: THandle; + Buf: Array[0..4095] of Byte; + BytesRead, BytesWritten: DWORD; +begin + Result := False; + NetHandle := InternetOpen('RDP Wrapper', 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; + FileHandle := CreateFile(PChar(DestPath), GENERIC_WRITE, 0, nil, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if FileHandle = INVALID_HANDLE_VALUE then + begin + InternetCloseHandle(UrlHandle); + InternetCloseHandle(NetHandle); + Exit; + end; + repeat + InternetReadFile(UrlHandle, @Buf[0], SizeOf(Buf), BytesRead); + if BytesRead > 0 then + WriteFile(FileHandle, Buf[0], BytesRead, BytesWritten, nil); + until BytesRead = 0; + CloseHandle(FileHandle); + InternetCloseHandle(UrlHandle); + InternetCloseHandle(NetHandle); + Result := FileExists(DestPath); +end; + +{ ────────────────────────────────────────────────────────────────────────────── + INIHasSection + Returns True when the INI file at INIPath contains [Section]. +────────────────────────────────────────────────────────────────────────────── } +function INIHasSection(const INIPath, Section: String): Boolean; +var + F: TStringList; +begin + Result := False; + if not FileExists(INIPath) then Exit; + F := TStringList.Create; + try + F.LoadFromFile(INIPath); + Result := Pos('[' + Section + ']', F.Text) > 0; + finally + F.Free; + end; +end; + +{ ────────────────────────────────────────────────────────────────────────────── + TryAutoGenerateOffsets + If the current termsrv.dll version (TermSrvVerTxt) is absent from the on-disk + rdpwrap.ini, download RDPWrapOffsetFinder + Zydis from the sjackson0109 release + assets and run the finder to append the generated section to the INI. + This mirrors the approach used by sergiye/rdpWrapper (Wrapper.cs GenerateIniFile). +────────────────────────────────────────────────────────────────────────────── } +procedure TryAutoGenerateOffsets; +const + BASE_URL = 'https://github.com/sjackson0109/rdpwrap/releases/latest/download/'; +var + TempDir, ExePath, DllPath, INIPath, ArchSuffix, SysCmd: String; +begin + if TermSrvVerTxt = '' then Exit; + + INIPath := ExtractFilePath(ExpandPath(WrapPath)) + 'rdpwrap.ini'; + + if INIHasSection(INIPath, TermSrvVerTxt) then + begin + Writeln('[+] Version ', TermSrvVerTxt, ' is covered in INI.'); + Exit; + end; + + Writeln('[!] Version ', TermSrvVerTxt, ' not found in INI.'); + Writeln('[*] Attempting automatic offset generation via RDPWrapOffsetFinder...'); + + if Arch = 64 then ArchSuffix := '_x64' else ArchSuffix := '_x86'; + + TempDir := ExpandPath('%TEMP%') + '\rdpwrapoffset'; + if not ForceDirectories(TempDir) and not DirectoryExists(TempDir) then + begin + Writeln('[-] Could not create temp directory. Skipping auto-generation.'); + Exit; + end; + + ExePath := TempDir + '\RDPWrapOffsetFinder.exe'; + DllPath := TempDir + '\Zydis.dll'; + + Writeln('[*] Downloading RDPWrapOffsetFinder', ArchSuffix, '.exe ...'); + if not DownloadFileToDisk(BASE_URL + 'RDPWrapOffsetFinder' + ArchSuffix + '.exe', ExePath) then + begin + Writeln('[-] Download failed. The release asset may not yet be published.'); + Writeln('[!] Run the publish-ini workflow on the sjackson0109/rdpwrap repository,'); + Writeln('[!] then re-run this installer to enable auto-generation.'); + Exit; + end; + + Writeln('[*] Downloading Zydis', ArchSuffix, '.dll ...'); + if not DownloadFileToDisk(BASE_URL + 'Zydis' + ArchSuffix + '.dll', DllPath) then + begin + Writeln('[-] Zydis download failed. Skipping auto-generation.'); + DeleteFile(ExePath); + Exit; + end; + + Writeln('[*] Running offset finder for termsrv.dll ', TermSrvVerTxt, ' ...'); + { Run via cmd.exe so >> redirect to the INI file works correctly. } + SysCmd := ExpandPath('%SystemRoot%') + '\System32\cmd.exe'; + ExecWait('"' + SysCmd + '" /c ""' + ExePath + '" >> "' + INIPath + '""'); + + if INIHasSection(INIPath, TermSrvVerTxt) then + Writeln('[+] Offsets generated successfully for version ', TermSrvVerTxt) + else + Writeln('[!] Offset finder ran but [', TermSrvVerTxt, '] was not added.', + ' Session may be limited or unstable for this build.'); + + { Clean up temporary tool files } + DeleteFile(ExePath); + DeleteFile(DllPath); + RemoveDirectory(PChar(TempDir)); +end; + procedure CheckTermsrvVersion; var SuppLvl: Byte; @@ -857,6 +992,7 @@ begin GetFileVersion(ExpandPath(TermServicePath), FV); VerTxt := Format('%d.%d.%d.%d', [FV.Version.w.Major, FV.Version.w.Minor, FV.Release, FV.Build]); + TermSrvVerTxt := VerTxt; // expose globally for TryAutoGenerateOffsets Writeln('[*] Terminal Services version: ', VerTxt); if (FV.Version.w.Major = 5) and (FV.Version.w.Minor = 1) then @@ -1119,6 +1255,15 @@ begin end; Str.Free; + { After writing updated INI, fill any missing section for the running + termsrv.dll. FV/TermSrvVerTxt may not be set in the -w path, so + compute the version here before calling TryAutoGenerateOffsets. } + GetFileVersion(ExpandPath(TermServicePath), FV); + TermSrvVerTxt := Format('%d.%d.%d.%d', + [FV.Version.w.Major, FV.Version.w.Minor, FV.Release, FV.Build]); + Writeln('[*] Checking INI coverage for installed termsrv.dll version...'); + TryAutoGenerateOffsets; + SvcStart(TermService); Writeln('[+] Update completed.'); @@ -1208,6 +1353,9 @@ begin Online := (ParamStr(2) = '-o') or (ParamStr(3) = '-o'); ExtractFiles; + Writeln('[*] Checking INI coverage for installed termsrv.dll version...'); + TryAutoGenerateOffsets; + Writeln('[*] Configuring service library...'); SetWrapperDll;