When using Remote Desktop Services to connect to non-Windows-Server edition, at most one remote user can be connected to the remote Windows computer. However, it is possible to lift this restriction by patching (replacing some bytes in) termsrv.dll
which the below PowerShell script does.
Obviously this is definitely educational, and you should stick to Microsoft’s ridiculous TOS/licensing/rules!!
Read through it before you run it because you will need to change things.
#
# Get status of the two services UmRdpService and TermService...
#
$svc_UmRdpService_status = (Get-Service UmRdpService).status
$svc_TermService_status = (Get-Service TermService ).status
#
# Display them ...
#
Write-Host "Status of service UmRdpService: $svc_TermService_status"
Write-Host "Status of service TermService: $svc_TermService_status"
#
# Before stopping them ...
Stop-Service UmRdpService
Stop-Service TermService
#
# Save ACL and owner of termsrv.dll:
#
$termsrv_dll_acl = Get-Acl C:\Windows\System32\termsrv.dll
$termsrv_dll_owner = $termsrv_dll_acl.owner
Write-Host "Owner of termsrv.dll: $termsrv_dll_owner"
#
# Create backup of termsrv.dll, just in case:
#
Copy-Item C:\Windows\System32\termsrv.dll C:\Windows\System32\termsrv.dll.copy
#
# Take ownership of the DLL...
#
takeown /f C:\Windows\System32\termsrv.dll
$new_termsrv_dll_owner = (Get-Acl C:\Windows\System32\termsrv.dll).owner
#
# and grant (/G) full control (:F) to myself:
#
# cacls C:\Windows\System32\termsrv.dll /G $new_termsrv_dll_owner:F
cacls C:\Windows\System32\termsrv.dll /G rene:F
#
# Read DLL as byte-array in order to modify the bytes.
#
# See https://stackoverflow.com/a/57342311/180275 for some details.
#
# $dll_as_bytes = get-content C:\Windows\System32\termsrv.dll -raw -asByteStream # PowerShell Core version
$dll_as_bytes = Get-Content C:\Windows\System32\termsrv.dll -raw -encoding byte # PowerShell traditional version
#
# Convert the byte array to a string that represents each byte's value
# as hexadecimal value, separated by spaces:
#
$dll_as_text = $dll_as_bytes.forEach('ToString', 'X2') -join ' '
#
# Search for byte array (which is dependent on the Windows edition) and replace them.
# See
# http://woshub.com/how-to-allow-multiple-rdp-sessions-in-windows-10/
# for details.
#
# $dll_as_text_replaced = $dll_as_text -replace '39 81 3C 06 00 00 0F 84 5D 61 01 00', 'B8 00 01 00 00 89 81 38 06 00 00 90' # Windows 1909
$dll_as_text_replaced = $dll_as_text -replace '39 81 3C 06 00 00 0F 84 5D 61 01 00', 'B8 00 01 00 00 89 81 38 06 00 00 90' # Windows 1903
# $dll_as_text_replaced = $dll_as_text -replace '39 81 3C 06 00 00 0F 84 3B 2B 01 00', 'B8 00 01 00 00 89 81 38 06 00 00 90' # Windows 1809
# $dll_as_text_replaced = $dll_as_text -replace '8B 99 3C 06 00 00 8B B9 38 06 00 00', 'B8 00 01 00 00 89 81 38 06 00 00 90' # Windows 1803
# $dll_as_text_replaced = $dll_as_text -replace '8B 99 3C 06 00 00 8B B9 38 06 00 00', 'B8 00 01 00 00 89 81 38 06 00 00 90' # Windows 1803
#
# Use the replaced string to create a byte array again
#
# [byte[]] $dll_as_bytes_replaced = -split $dll_as_text_replaced -replace '^', '0x' # PowerShell Core version
[byte[]] $dll_as_bytes_replaced = -split $dll_as_text_replaced -replace '^', '0x' # PoserShell traditional version
#
# Create termsrv.dll.patched from byte array:
#
Set-Content C:\Windows\System32\termsrv.dll.patched -encoding byte -Value $dll_as_bytes_replaced
#
# Compare patched and original DLL (/b: binary comparison)
#
fc.exe /b C:\Windows\System32\termsrv.dll.patched C:\Windows\System32\termsrv.dll
#
# Expected output something like:
#
# 0001F215: B8 39
# 0001F216: 00 81
# 0001F217: 01 3C
# 0001F218: 00 06
# 0001F21A: 89 00
# 0001F21B: 81 0F
# 0001F21C: 38 84
# 0001F21D: 06 5D
# 0001F21E: 00 61
# 0001F21F: 00 01
# 0001F220: 90 00
#
#
# Overwrite original DLL with patched version:
#
Copy-Item C:\Windows\System32\termsrv.dll.patched C:\Windows\System32\termsrv.dll
#
# Restore original ACL:
#
Set-Acl C:\Windows\System32\termsrv.dll $termsrv_dll_acl
#
# Start services again:
#
# start-service UmRdpService
# start-service TermService
sc start TermService
sc start UmRdpService
The Windows Service TermService.
RDP Wrapper Library is a project on github whose goal is to enable Remote Desktop Host support and concurrent RDP sessions on reduced functionality systems for home usage. How to Allow Multiple RDP Sessions in Windows 10? was helpful to develop this script. Multiple RDP (Remote Desktop) sessions in Windows 10