name: Publish INI and Offset Finder Tools on: push: branches: [main, master] paths: - 'res/rdpwrap.ini' - '.github/workflows/publish-ini.yml' workflow_dispatch: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true permissions: contents: write jobs: publish: runs-on: windows-2022 steps: - name: Checkout repository uses: actions/checkout@v6 # ── Build rdpwrap.dll for both x64 and Win32 ──────────────────────────── - name: Setup MSBuild uses: microsoft/setup-msbuild@v3 - name: Build rdpwrap.dll (x64 and Win32) shell: pwsh run: | foreach ($platform in @('x64', 'Win32')) { 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/x64/Release/rdpwrap.dll .\rdpwrap_x64.dll Copy-Item src-x86-x64-Fusix/Win32/Release/rdpwrap.dll .\rdpwrap_x86.dll Write-Host "Built DLLs:" Get-Item .\rdpwrap_x64.dll, .\rdpwrap_x86.dll | 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 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 echo "finder_ver=$($release.tag_name)" >> $env:GITHUB_OUTPUT # ── Download the latest rdpWrapper GUI app from sergiye ───────────────── - 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 # ── 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" # ── Assemble the two user-facing distribution bundles ──────────────────── - name: Create distribution bundles shell: pwsh run: | # RDPWrapper.zip - complete install package. # Contains both arch DLLs, both arch wrapper exes, latest INI, and scripts. $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 .\rdpWrapper_x64.exe "$d\rdpWrapper_x64.exe" Copy-Item .\rdpWrapper_x86.exe "$d\rdpWrapper_x86.exe" Copy-Item res\rdpwrap.ini "$d\rdpwrap.ini" Copy-Item bin\install.bat "$d\install.bat" Copy-Item bin\uninstall.bat "$d\uninstall.bat" Copy-Item bin\update.bat "$d\update.bat" Compress-Archive -Path "$d\*" -DestinationPath ".\RDPWrapper.zip" -Force Remove-Item $d -Recurse -Force # RDPWrapOffsetFinder.zip - offset finder with per-arch subfolders. # Extract x64\ or x86\ folder and run RDPWrapOffsetFinder.exe directly. $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, .\RDPWrapOffsetFinder.zip | Format-Table Name, Length # ── 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 }}" 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) | ${{ steps.wrapper.outputs.wrapper_ver }} | | RDPWrapOffsetFinder (llccd) | ${{ steps.finder.outputs.finder_ver }} | ### Downloads | File | Contents | Use | |---|---|---| | `RDPWrapper.zip` | rdpwrap_x64.dll, rdpwrap_x86.dll, rdpWrapper_x64.exe, rdpWrapper_x86.exe, rdpwrap.ini, install/uninstall/update.bat | Main install package - extract and run `rdpWrapper_x64.exe` | | `RDPWrapOffsetFinder.zip` | x64\RDPWrapOffsetFinder.exe + Zydis.dll, x86\RDPWrapOffsetFinder.exe + Zydis.dll | Generate offsets for an unknown termsrv.dll version manually | ### Individual 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 RDPWrapOffsetFinder.zip res/rdpwrap.ini rdpwrap_x64.dll rdpwrap_x86.dll RDPWrapOffsetFinder_x64.exe RDPWrapOffsetFinder_x86.exe Zydis_x64.dll Zydis_x86.dll