diff --git a/.github/workflows/native-package.yml b/.github/workflows/native-package.yml
deleted file mode 100644
index 5dfbf9f..0000000
--- a/.github/workflows/native-package.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: native package
-on: workflow_dispatch
-jobs:
- build-native:
- name: native build
- runs-on: windows-2022
- strategy:
- fail-fast: false
- matrix:
- arch: [ x86, x64, arm64 ]
-
- steps:
- - name: Configure runner
- run: |
- Install-Module -Name VsDevShell -Force
-
- - name: Check out ${{ github.repository }}
- uses: actions/checkout@v3
-
- - name: Build Detours (${{matrix.arch}})
- shell: pwsh
- run: |
- Enter-VsDevShell ${{matrix.arch}}
- .\detours.ps1
-
- - name: Build MsRdpEx (${{matrix.arch}})
- shell: pwsh
- run: |
- $ArchDir = "${{matrix.arch}}"
- $BuildDir = "build-$ArchDir"
- $MsvcArch = @{"x86"="Win32";"x64"="x64";"arm64"="ARM64"}["${{matrix.arch}}"]
- cmake -G "Visual Studio 17 2022" -A $MsvcArch -DWITH_DOTNET=OFF -B $BuildDir
- cmake --build $BuildDir --config Release
- New-Item -ItemType Directory -Path "dependencies/MsRdpEx/$ArchDir" | Out-Null
- Copy-Item "$BuildDir/Release/MsRdpEx.dll" "dependencies/MsRdpEx/$ArchDir/MsRdpEx.dll"
- Copy-Item "$BuildDir/Release/MsRdpEx_Exe.exe" "dependencies/MsRdpEx/$ArchDir/MsRdpEx.exe"
-
- - name: Upload MsRdpEx (${{matrix.arch}})
- uses: actions/upload-artifact@v3
- with:
- name: MsRdpEx-${{matrix.arch}}
- path: dependencies/MsRdpEx/${{matrix.arch}}
diff --git a/.github/workflows/nuget-package.yml b/.github/workflows/nuget-package.yml
index 99e9948..4692714 100644
--- a/.github/workflows/nuget-package.yml
+++ b/.github/workflows/nuget-package.yml
@@ -3,8 +3,21 @@ name: nuget package
on:
workflow_dispatch:
inputs:
+ version:
+ description: 'release version'
+ default: "latest"
+ required: true
+ detours-git-commit:
+ description: 'Detours git commit'
+ default: '4b8c659'
+ required: true
+ skip-publish:
+ description: 'Skip publishing'
+ required: true
+ type: boolean
+ default: false
dry-run:
- description: 'Dry run'
+ description: Dry run (simulate)
required: true
type: boolean
default: true
@@ -14,28 +27,53 @@ on:
jobs:
preflight:
name: Preflight
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
outputs:
- dry-run: ${{ steps.get-dry-run.outputs.dry-run }}
+ package-env: ${{ steps.info.outputs.package-env }}
+ package-version: ${{ steps.info.outputs.package-version }}
+ dry-run: ${{ steps.info.outputs.dry-run }}
steps:
- - name: Get dry run
- id: get-dry-run
+ - name: Package information
+ id: info
shell: pwsh
run: |
- Set-PSDebug -Trace 1
-
- $IsDryRun = '${{ github.event.inputs.dry-run }}' -Eq 'true' -Or '${{ github.event_name }}' -Eq 'schedule'
+ $IsMasterBranch = ('${{ github.ref_name }}' -eq 'master')
+ $DryRun = [System.Boolean]::Parse('${{ inputs.dry-run }}')
- if ($IsDryRun) {
- echo "dry-run=true" >> $Env:GITHUB_OUTPUT
+ $PackageEnv = if ($IsMasterBranch) {
+ "publish-prod"
} else {
- echo "dry-run=false" >> $Env:GITHUB_OUTPUT
+ "publish-test"
+ }
+
+ if (-Not $IsMasterBranch) {
+ $DryRun = $true # force dry run when not on master branch
+ }
+ if ('${{ github.event_name }}' -Eq 'schedule') {
+ $DryRun = $true # force dry run for scheduled runs
+ }
+
+ $PackageVersion = '${{ github.event.inputs.version }}'
+ if ($PackageVersion -eq 'latest') {
+ $PackageVersion = (Get-Date -Format "yyyy.MM.dd") + ".0"
+ }
+
+ if ($PackageVersion -NotMatch '^\d+\.\d+\.\d+\.\d+$') {
+ throw "invalid version format: $PackageVersion, expected: 1.2.3.4"
}
+ echo "package-env=$PackageEnv" >> $Env:GITHUB_OUTPUT
+ echo "package-version=$PackageVersion" >> $Env:GITHUB_OUTPUT
+ echo "dry-run=$($DryRun.ToString().ToLower())" >> $Env:GITHUB_OUTPUT
+
+ echo "::notice::Version: $PackageVersion"
+ echo "::notice::DryRun: $DryRun"
+
build-native:
name: Build native library
runs-on: windows-2022
+ needs: [preflight]
strategy:
fail-fast: false
matrix:
@@ -43,25 +81,47 @@ jobs:
steps:
- name: Configure runner
+ shell: pwsh
run: |
Install-Module -Name VsDevShell -Force
- name: Check out ${{ github.repository }}
uses: actions/checkout@v3
- - name: Build Detours (${{matrix.arch}})
+ - name: Set package version
shell: pwsh
run: |
- Set-PSDebug -Trace 1
+ $PackageVersion = '${{ needs.preflight.outputs.package-version }}'
+ $csprojPath = "dotnet\Devolutions.MsRdpEx\Devolutions.MsRdpEx.csproj"
+ $csprojContent = Get-Content $csprojPath -Raw
+ $csprojContent = $csprojContent -Replace '().*?()', "$PackageVersion"
+ Set-Content -Path $csprojPath -Value $csprojContent -Encoding UTF8
+
+ - name: Restore Detours Cache (${{matrix.arch}})
+ id: cache-detours
+ uses: actions/cache/restore@v3
+ with:
+ path: dependencies/detours
+ key: detours-${{ matrix.arch }}-${{ inputs.detours-git-commit }}
+ - name: Build Detours (${{matrix.arch}})
+ if: steps.cache-detours.outputs.cache-hit != 'true'
+ shell: pwsh
+ run: |
Enter-VsDevShell ${{matrix.arch}}
- .\detours.ps1
+ $GitCommit = '${{ inputs.detours-git-commit }}'
+ .\detours.ps1 -GitCommit $GitCommit
+
+ - name: Save Detours Cache (${{matrix.arch}})
+ if: steps.cache-detours.outputs.cache-hit != 'true'
+ uses: actions/cache/save@v3
+ with:
+ path: dependencies/detours
+ key: detours-${{ matrix.arch }}-${{ inputs.detours-git-commit }}
- name: Build MsRdpEx.dll (${{matrix.arch}})
shell: pwsh
run: |
- Set-PSDebug -Trace 1
-
$ArchDir = "${{matrix.arch}}"
$BuildDir = "build-$ArchDir"
$MsvcArch = @{"x86"="Win32";"x64"="x64";"arm64"="ARM64"}["${{matrix.arch}}"]
@@ -69,6 +129,8 @@ jobs:
cmake --build $BuildDir --config Release
New-Item -ItemType Directory -Path "dependencies/MsRdpEx/$ArchDir" | Out-Null
Copy-Item "$BuildDir/Release/MsRdpEx.dll" "dependencies/MsRdpEx/$ArchDir"
+ Copy-Item "$BuildDir/Release/MsRdpEx.pdb" "dependencies/MsRdpEx/$ArchDir"
+ Copy-Item "$BuildDir/Release/MsRdpEx_Exe.exe" "dependencies/MsRdpEx/$ArchDir/MsRdpEx.exe"
- name: Upload native components
uses: actions/upload-artifact@v3
@@ -79,12 +141,21 @@ jobs:
build-managed:
name: Build and package managed library
runs-on: windows-2022
- needs: build-native
+ needs: [preflight, build-native]
steps:
- name: Check out ${{ github.repository }}
uses: actions/checkout@v3
+ - name: Set package version
+ shell: pwsh
+ run: |
+ $PackageVersion = '${{ needs.preflight.outputs.package-version }}'
+ $csprojPath = "dotnet\Devolutions.MsRdpEx\Devolutions.MsRdpEx.csproj"
+ $csprojContent = Get-Content $csprojPath -Raw
+ $csprojContent = $csprojContent -Replace '().*?()', "$PackageVersion"
+ Set-Content -Path $csprojPath -Value $csprojContent -Encoding UTF8
+
- name: Prepare dependencies
shell: pwsh
run: |
@@ -99,7 +170,6 @@ jobs:
shell: pwsh
run: |
Set-PSDebug -Trace 1
-
Set-Location "dependencies/MsRdpEx"
$(Get-Item ".\MsRdpEx-*") | ForEach-Object { ($p1,$p2) = $_.Name -Split '-'; Rename-Item $_ $p2 }
Get-ChildItem * -Recurse
@@ -108,7 +178,6 @@ jobs:
shell: pwsh
run: |
Set-PSDebug -Trace 1
-
$BuildDir = "build-dotnet"
cmake -G "Visual Studio 17 2022" -A x64 -DWITH_DOTNET=ON -DWITH_NATIVE=OFF -B $BuildDir
cmake --build $BuildDir --config Release
@@ -121,13 +190,11 @@ jobs:
path: package/*.nupkg
publish:
- name: Publish NuGet package
- runs-on: ubuntu-20.04
- environment: nuget-publish
- if: needs.preflight.outputs.dry-run == 'false'
- needs:
- - preflight
- - build-managed
+ name: Publish packages
+ runs-on: ubuntu-22.04
+ needs: [preflight, build-native, build-managed]
+ environment: ${{ needs.preflight.outputs.package-env }}
+ if: ${{ fromJSON(inputs.skip-publish) == false }}
steps:
- name: Download NuGet package artifact
@@ -139,24 +206,45 @@ jobs:
- name: Publish to nuget.org
shell: pwsh
run: |
- Set-PSDebug -Trace 1
+ $DryRun = [System.Boolean]::Parse('${{ needs.preflight.outputs.dry-run }}')
+ $NugetPackage = (Get-Item ./package/*.nupkg) | Resolve-Path -Relative
+
+ $PushArgs = @(
+ 'nuget', 'push', "$NugetPackage",
+ '--api-key', '${{ secrets.NUGET_API_KEY }}',
+ '--source', 'https://api.nuget.org/v3/index.json',
+ '--skip-duplicate', '--no-symbols'
+ )
+ Write-Host "dotnet $($PushArgs -Join ' ')"
+ if ($DryRun) {
+ Write-Host "Dry Run: skipping nuget.org publishing!"
+ } else {
+ & 'dotnet' $PushArgs
+ }
+
+ - name: Create GitHub release
+ shell: pwsh
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ working-directory: package
+ run: |
+ $PackageVersion = '${{ needs.preflight.outputs.package-version }}'
+ $DryRun = [System.Boolean]::Parse('${{ needs.preflight.outputs.dry-run }}')
- $Files = Get-ChildItem -Recurse package/*.nupkg
-
- foreach ($File in $Files) {
- $PushCmd = @(
- 'dotnet',
- 'nuget',
- 'push',
- "$File",
- '--api-key',
- '${{ secrets.NUGET_API_KEY }}',
- '--source',
- 'https://api.nuget.org/v3/index.json',
- '--skip-duplicate'
- )
-
- Write-Host "Publishing $($File.Name)..."
- $PushCmd = $PushCmd -Join ' '
- Invoke-Expression $PushCmd
+ $HashPath = 'checksums'
+ $Files = Get-Item * | % { Get-FileHash -Algorithm SHA256 $_.FullName }
+ $Files | % { "$($_.Hash) $(Split-Path $_.Path -Leaf)" } | Out-File -FilePath $HashPath -Append -Encoding ASCII
+
+ echo "::group::checksums"
+ Get-Content $HashPath
+ echo "::endgroup::"
+
+ $ReleaseTag = "v$Version"
+ $ReleaseTitle = "MsRdpEx v${Version}"
+ $Repository = $Env:GITHUB_REPOSITORY
+
+ if ($DryRun) {
+ Write-Host "Dry Run: skipping GitHub release!"
+ } else {
+ & gh release create $ReleaseTag --repo $Repository --title $ReleaseTitle ./*
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 824e691..8709768 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,7 +29,7 @@ message(STATUS "VERSION: ${MSRDPEX_VERSION}")
set(MSRDPEX_NAME "MsRdpEx")
set(MSRDPEX_VENDOR "Devolutions Inc.")
-set(MSRDPEX_COPYRIGHT "Copyright 2021-2022 ${MSRDPEX_VENDOR}")
+set(MSRDPEX_COPYRIGHT "Copyright 2021-2023 ${MSRDPEX_VENDOR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
@@ -44,24 +44,36 @@ if(NOT DEFINED WITH_DOTNET)
endif()
if(MSVC)
- include(MSVCRuntime)
+ include(MSVCRuntime)
- if(NOT DEFINED MSVC_RUNTIME)
- set(MSVC_RUNTIME "static")
- endif()
+ if(NOT DEFINED MSVC_RUNTIME)
+ set(MSVC_RUNTIME "static")
+ endif()
- configure_msvc_runtime()
+ configure_msvc_runtime()
endif()
if(WIN32)
- set(C_FLAGS "")
- set(C_FLAGS "${C_FLAGS} -D_UNICODE")
- set(C_FLAGS "${C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
- set(C_FLAGS "${C_FLAGS} -DWIN32_LEAN_AND_MEAN")
- set(C_FLAGS "${C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS")
- set(C_FLAGS "${C_FLAGS} -DWINVER=0x0602 -D_WIN32_WINNT=0x0602")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS}")
+ set(C_FLAGS "")
+ set(C_FLAGS "${C_FLAGS} -D_UNICODE")
+ set(C_FLAGS "${C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
+ set(C_FLAGS "${C_FLAGS} -DWIN32_LEAN_AND_MEAN")
+ set(C_FLAGS "${C_FLAGS} -D_WINSOCK_DEPRECATED_NO_WARNINGS")
+ set(C_FLAGS "${C_FLAGS} -DWINVER=0x0602 -D_WIN32_WINNT=0x0602")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS}")
+
+ set(C_FLAGS_RELEASE "/Zi /GF") # produce debug symbols in release builds
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${C_FLAGS_RELEASE}")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${C_FLAGS_RELEASE}")
+
+ # http://devcenter.wintellect.com/jrobbins/correctly-creating-native-c-release-build-pdbs
+ set(LINKER_FLAGS_RELEASE "/DEBUG")
+ set(LINKER_FLAGS_RELEASE "${LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF")
+ set(LINKER_FLAGS_RELEASE "${LINKER_FLAGS_RELEASE} /MAP /MAPINFO:EXPORTS")
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}" CACHE STRING "" FORCE)
+ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}" CACHE STRING "" FORCE)
+ set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}" CACHE STRING "" FORCE)
endif()
set(DEPENDENCIES_DIR "${CMAKE_SOURCE_DIR}/dependencies")
diff --git a/detours.ps1 b/detours.ps1
index 1c2ccbe..7182b6a 100644
--- a/detours.ps1
+++ b/detours.ps1
@@ -1,3 +1,7 @@
+param(
+ [string] $GitRepo = 'https://github.com/microsoft/Detours',
+ [string] $GitCommit = '4b8c659' # July 24, 2023
+)
$RepoRoot = $PSScriptRoot
@@ -8,12 +12,12 @@ Push-Location
Set-Location $SourcesDir
if (-Not (Test-Path -Path "detours")) {
- & 'git' 'clone' 'https://github.com/microsoft/Detours' 'detours'
+ & 'git' 'clone' $GitRepo 'detours'
}
Set-Location "detours/src"
-& 'git' 'checkout' '45a76a3' # August 17, 2021
+& 'git' 'checkout' $GitCommit
if (-Not (Test-Path Env:VSCMD_ARG_TGT_ARCH)) {
throw "VSCMD_ARG_TGT_ARCH is not set, use a Visual Studio developer shell"
diff --git a/dll/ApiHooks.cpp b/dll/ApiHooks.cpp
index fa9d5d6..081b834 100644
--- a/dll/ApiHooks.cpp
+++ b/dll/ApiHooks.cpp
@@ -976,6 +976,12 @@ bool MsRdpEx_IsAddressInModule(PVOID pAddress, LPCTSTR pszModule)
return result;
}
+bool MsRdpEx_IsAddressInRdpAxModule(PVOID pAddress)
+{
+ return MsRdpEx_IsAddressInModule(pAddress, L"mstscax.dll") ||
+ MsRdpEx_IsAddressInModule(pAddress, L"rdclientax.dll");
+}
+
void MsRdpEx_GlobalInit()
{
MsRdpEx_NameResolver_Get();
diff --git a/dll/MsRdpEx.h b/dll/MsRdpEx.h
index 8e6fab6..fc2b71c 100644
--- a/dll/MsRdpEx.h
+++ b/dll/MsRdpEx.h
@@ -205,6 +205,7 @@ LONG MsRdpEx_AttachHooks();
LONG MsRdpEx_DetachHooks();
bool MsRdpEx_IsAddressInModule(PVOID pAddress, LPCTSTR pszModule);
+bool MsRdpEx_IsAddressInRdpAxModule(PVOID pAddress);
LONG MsRdpEx_GetRectWidth(LPRECT rect);
LONG MsRdpEx_GetRectHeight(LPRECT rect);
diff --git a/dll/RdpSettings.cpp b/dll/RdpSettings.cpp
index 8537721..2e38733 100644
--- a/dll/RdpSettings.cpp
+++ b/dll/RdpSettings.cpp
@@ -55,7 +55,7 @@ static HRESULT Hook_ITSPropertySet_SetBoolProperty(ITSPropertySet* This, const c
return hr;
}
-static int g_UiShowConnectionInformation = 0;
+static int g_InitializeKDCProxyClient = 0;
static HRESULT Hook_ITSPropertySet_GetBoolProperty(ITSPropertySet* This, const char* propName, int* propValue)
{
@@ -68,25 +68,25 @@ static HRESULT Hook_ITSPropertySet_GetBoolProperty(ITSPropertySet* This, const c
// CTsConnectionInfoDlg::GetExpandedInfoString crashes if we set TSGTransportIsUsed true when it's not
// CTscSslFilter::OnConnected checks IgnoreAuthenticationLevel, NegotiateSecurityLayer right before calling
// CTscSslFilter::InitializeKDCProxyClient, so use this to our advantage to filter out undesired call sites.
- // We use a basic g_UiShowConnectionInformation state machine, checking for caller DLLs, and hope for the best.
- if (MsRdpEx_IsAddressInModule(_ReturnAddress(), L"mstscax.dll") ||
- MsRdpEx_IsAddressInModule(_ReturnAddress(), L"rdclientax.dll")) {
- if (MsRdpEx_StringIEquals(propName, "IgnoreAuthenticationLevel")) {
- if (g_UiShowConnectionInformation == 0) {
- g_UiShowConnectionInformation = 1;
- }
+ // We use a basic g_InitializeKDCProxyClient state machine, checking for caller DLLs, and hope for the best.
+ if (MsRdpEx_StringIEquals(propName, "IgnoreAuthenticationLevel") &&
+ MsRdpEx_IsAddressInRdpAxModule(_ReturnAddress())) {
+ if (g_InitializeKDCProxyClient == 0) {
+ g_InitializeKDCProxyClient = 1;
}
- else if (MsRdpEx_StringIEquals(propName, "NegotiateSecurityLayer")) {
- if (g_UiShowConnectionInformation == 1) { //
- g_UiShowConnectionInformation = 2;
- }
+ }
+ else if (MsRdpEx_StringIEquals(propName, "NegotiateSecurityLayer") &&
+ MsRdpEx_IsAddressInRdpAxModule(_ReturnAddress())) {
+ if (g_InitializeKDCProxyClient == 1) {
+ g_InitializeKDCProxyClient = 2;
}
- else if (MsRdpEx_StringIEquals(propName, "TSGTransportIsUsed")) {
- if (g_UiShowConnectionInformation == 2) {
- g_UiShowConnectionInformation = 0;
- *propValue = 1; // bypass if (TSGTransportIsUsed) { /* break Kerberos */ }
- MsRdpEx_LogPrint(TRACE, "TSGTransportIsUsed is a lie!");
- }
+ }
+ else if (MsRdpEx_StringIEquals(propName, "TSGTransportIsUsed") &&
+ MsRdpEx_IsAddressInRdpAxModule(_ReturnAddress())) {
+ if (g_InitializeKDCProxyClient == 2) {
+ g_InitializeKDCProxyClient = 0;
+ *propValue = 1; // bypass if (TSGTransportIsUsed) { /* break Kerberos */ }
+ MsRdpEx_LogPrint(TRACE, "TSGTransportIsUsed is a lie!");
}
}
diff --git a/dotnet/Devolutions.MsRdpEx/Devolutions.MsRdpEx.csproj b/dotnet/Devolutions.MsRdpEx/Devolutions.MsRdpEx.csproj
index b652876..05b66fa 100644
--- a/dotnet/Devolutions.MsRdpEx/Devolutions.MsRdpEx.csproj
+++ b/dotnet/Devolutions.MsRdpEx/Devolutions.MsRdpEx.csproj
@@ -3,7 +3,7 @@
Devolutions.MsRdpEx
Devolutions.MsRdpEx
- 2023.9.28.0
+ 1.0.0.0
mamoreau@devolutions.net
Devolutions
Microsoft RDP Extensions