You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rdpwrap/bin/autoupdate.bat

1328 lines
51 KiB

<!-- : Begin of batch script
@echo off
setLocal EnableExtensions
setlocal EnableDelayedExpansion
:: _ _
:: _ | | _ | | _
:: ____ _ _| |_ ___ _ _ ____ _ | | ____| |_ ____ | | _ ____| |_
:: / _ | | | | _)/ _ \| | | | _ \ / || |/ _ | _)/ _ ) | || \ / _ | _)
:: ( ( | | |_| | |_| |_| | |_| | | | ( (_| ( ( | | |_( (/ / _| |_) ( ( | | |__
:: \_||_|\____|\___\___/ \____| ||_/ \____|\_||_|\___\____(_|____/ \_||_|\___)
:: |_|
::
:: Automatic RDP Wrapper installer and updater v.1.4 asmtron (2025-10-23)
:: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:: Options:
:: -log = redirect display output to the file autoupdate.log
:: -taskadd = add autorun of autoupdate.bat on startup in schedule task
:: -taskremove = remove autorun of autoupdate.bat on startup in schedule task
::
:: Info:
:: The autoupdater first use and check the local rdpwrap.ini file.
:: If a new termsrv.dll is not supported in the local rdpwrap.ini file,
:: autoupdate uses the online rdpwrap.ini files from the community.
::
:: Autogeneration: v.1.4 or newer supports autogeneration of rdpwrap.ini entries
::
:: { Special thanks to binarymaster, sebaxakerhtc and all other contributors }
::
::
:: -----------------------------------------
:: Location of new/updated rdpwrap.ini files
:: -----------------------------------------
set rdpwrap_ini_update_github_1="https://raw.githubusercontent.com/asmtron/rdpwrap/master/res/rdpwrap.ini"
set rdpwrap_ini_update_github_2="https://raw.githubusercontent.com/sebaxakerhtc/rdpwrap.ini/master/rdpwrap.ini"
set rdpwrap_ini_update_github_3="https://raw.githubusercontent.com/affinityv/INI-RDPWRAP/master/rdpwrap.ini"
::set rdpwrap_ini_update_github_4="https://raw.githubusercontent.com/....Extra.4...."
::set rdpwrap_ini_update_github_5="https://raw.githubusercontent.com/....Extra.5...."
::
set autoupdate_version=1.4
set autoupdate_url="https://raw.githubusercontent.com/asmtron/rdpwrap/master/bin/autoupdate.bat"
set autoupdate_ver_url="https://raw.githubusercontent.com/asmtron/rdpwrap/master/bin/autoupdate.ver"
set autoupdate_bat="%~dp0autoupdate.bat"
set autoupdate_new_bat="%~dp0autoupdate_new.bat"
set autoupdate_log="%~dp0autoupdate.log"
set autoupdate_ver="%~dp0autoupdate.ver"
set RDPWInst_exe="%~dp0RDPWInst.exe"
set rdpwrap_dll="%~dp0rdpwrap.dll"
set rdpwrap_ini="%~dp0rdpwrap.ini"
set rdpwrap_ini_check=%rdpwrap_ini%
set rdpwrap_new_ini="%~dp0rdpwrap_new.ini"
set rdpwrap_ini_url=%rdpwrap_ini_update_github_1%
set github_location=1
set retry_network_check=0
set rdpwrap_installed=0
set version_check=0
set updated=0
::
set cvdump_url="https://raw.githubusercontent.com/asmtron/rdpwrap/master/bin/helper/cvdump.zip"
set cvdump_zip="%~dp0helper\cvdump.zip"
set cvdump_exe="%~dp0helper\cvdump.exe"
set pdblister_url="https://raw.githubusercontent.com/asmtron/rdpwrap/master/bin/helper/pdblister.zip"
set pdblister_zip="%~dp0helper\pdblister.zip"
set pdblister_exe="%~dp0helper\pdblister.exe"
set helper_path="%~dp0helper\"
set termsrv_dll="%systemroot%\system32\termsrv.dll"
set termsrv_pdb_dump="%~dp0helper\termsrv.pdb.dump"
set autogen=0
set autogen_ready=0
::
set arg_log=0
set arg_taskadd=0
set arg_taskremove=0
set arg_updated=0
set arg_nowaitnet=0
set arg_help=0
set arg_unknown=0
set args_count=0
set args=
::
:: --------------------------------
:: 1) check if admin
:: --------------------------------
fsutil dirty query %systemdrive% >nul
if not %errorlevel% == 0 (
call :not_admin
goto :eof
)
::
:: --------------------------------
:: 2) check arguments
:: --------------------------------
for %%i in (%*) do (
set /a args_count=!args_count!+1
set unknown=1
if /i "%%i"=="-log" set arg_log=1 & set unknown=0 & set "args=!args! %%i"
if /i "%%i"=="-taskadd" set arg_taskadd=1 & set unknown=0 & set "args=!args! %%i"
if /i "%%i"=="-taskremove" set arg_taskremove=1 & set unknown=0 & set "args=!args! %%i"
if /i "%%i"=="-updated" set arg_updated=1 & set unknown=0 & set "args=!args! %%i"
if /i "%%i"=="-nowaitnet" set arg_nowaitnet=1 & set unknown=0 & set "args=!args! %%i"
if /i "%%i"=="-help" set arg_help=1 & set unknown=0 & set "args=!args! %%i"
if /i "%%i"=="-?" set arg_help=1 & set unknown=0 & set "args=!args! %%i"
if /i "%%i"=="/?" set arg_help=1 & set unknown=0 & set "args=!args! %%i"
if !unknown!==1 (
set arg_unknown=%%i
)
)
if not %arg_unknown%==0 (
call :header
call :missing_arg
goto :eof
)
if %arg_help%==1 (
call :header
call :usage_arg
goto :eof
)
if %arg_taskadd%==1 (
call :header
echo [+] add autorun of %autoupdate_bat% on startup in the schedule task.
schtasks /create /f /sc ONSTART /tn "RDP Wrapper Autoupdate" /tr "cmd.exe /C \"%~dp0autoupdate.bat\" -log" /ru SYSTEM /delay 0000:10
powershell "$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries; Set-ScheduledTask -TaskName 'RDP Wrapper Autoupdate' -Settings $settings"
goto :eof
)
if %arg_taskremove%==1 (
call :header
echo [-] remove autorun of %autoupdate_bat% on startup in the schedule task^^!
schtasks /delete /f /tn "RDP Wrapper Autoupdate"
goto :eof
)
if %arg_updated%==1 (
set updated=1
copy /y %autoupdate_new_bat% %autoupdate_bat%
) else (
if exist %autoupdate_new_bat% del %autoupdate_new_bat%
)
if %arg_log%==1 (
echo %autoupdate_bat% output from %date% at %time% > %autoupdate_log%
if %args_count% == 1 (
call %autoupdate_bat% >> %autoupdate_log%
) else (
call %autoupdate_bat% %args:-log=% >> %autoupdate_log%
)
goto :eof
)
call :header
if %arg_nowaitnet%==1 (
echo [+] Set option: do not wait up to 5 minutes for a valid internet connection
set /a retry_network_check=29
)
::
:: --------------------------------
:: 3) check if "RDPWInst.exe" exist
:: --------------------------------
if not exist %RDPWInst_exe% (
call :error_install
goto :eof
)
:: ----------------------------------
:: 4) check if TermService is running
:: ----------------------------------
sc queryex "TermService"|find "STATE"|find /v "RUNNING" >nul&&(
echo [-] TermService NOT running^^!
call :install
)||(
echo [+] TermService running.
)
:: ------------------------------------------
:: 5) check if listener session rdp-tcp exist
:: ------------------------------------------
set rdp_tcp_session=""
set rdp_tcp_session_id=0
if exist %systemroot%\system32\query.exe (
for /f "tokens=1-2* usebackq" %%a in (
`query session rdp-tcp`
) do (
set rdp_tcp_session=%%a
set /a rdp_tcp_session_id=%%b 2>nul
)
) else (
for /f "tokens=2* usebackq" %%a in (
`reg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v "fDenyTSConnections" 2^>nul`
) do (
if "%%a"=="REG_DWORD" (
set rdp_tcp_session=AllowTSConnection
if "%%b"=="0x0" (set rdp_tcp_session_id=1)
)
)
)
if %rdp_tcp_session_id%==0 (
echo [-] Listener session rdp-tcp NOT found^^!
call :install
) else (
echo [+] Found listener session: %rdp_tcp_session% ^(ID: %rdp_tcp_session_id%^).
)
:: -----------------------------------------
:: 6) check if rdpwrap.dll exist in registry
:: -----------------------------------------
reg query "HKLM\SYSTEM\CurrentControlSet\Services\TermService\Parameters" /f "rdpwrap.dll" >nul&&(
echo [+] Found windows registry entry for "rdpwrap.dll".
)||(
echo [-] NOT found windows registry entry for "rdpwrap.dll"^^!
if %rdpwrap_installed%==0 (
call :install
)
)
:: -----------------------------------
:: 7) check if rdpwrap.dll file exists
:: -----------------------------------
if exist %rdpwrap_dll% (
echo [+] Found file: %rdpwrap_dll%
) else (
echo [-] File NOT found: %rdpwrap_dll%^^!
if %rdpwrap_installed%==0 (
call :install
)
)
:: ------------------------------
:: 8) check if rdpwrap.ini exists
:: ------------------------------
if exist %rdpwrap_ini% (
echo [+] Found file: %rdpwrap_ini%.
) else (
echo [-] File NOT found: %rdpwrap_ini%^^!
if %rdpwrap_installed%==0 (
call :install
)
)
:: ----------------------------------------------------
:: 9) get file version of %windir%\System32\termsrv.dll
:: ----------------------------------------------------
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:getFileVersion %termsrv_dll%`
) do (
set termsrv_dll_ver=%%a
)
if "%termsrv_dll_ver%"=="" (
echo [x] Error on getting the file version of %termsrv_dll%^^!
goto :eof
) else (
echo [+] Installed "termsrv.dll" version: %termsrv_dll_ver%.
)
:: -------------------------------------------------------------------------------------------
:: 10) check if installed file version is different to the last saved file version in registry
:: -------------------------------------------------------------------------------------------
echo [*] Read last "termsrv.dll" version from the windows registry...
for /f "tokens=2* usebackq" %%a in (
`reg query "HKEY_LOCAL_MACHINE\SOFTWARE\RDP-Wrapper\Autoupdate" /v "termsrv.dll" 2^>nul`
) do (
set last_termsrv_dll_ver=%%b
)
if "%last_termsrv_dll_ver%"=="%termsrv_dll_ver%" (
echo [+] Current "termsrv.dll v.%termsrv_dll_ver%" same as last "termsrv.dll v.%last_termsrv_dll_ver%".
) else (
echo [-] Current "termsrv.dll v.%termsrv_dll_ver%" different from last "termsrv.dll v.%last_termsrv_dll_ver%"^^!
echo [*] Update current "termsrv.dll" version to the windows registry...
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\RDP-Wrapper\Autoupdate" /v "termsrv.dll" /t REG_SZ /d "%termsrv_dll_ver%" /f
if %rdpwrap_installed%==0 (
call :install
)
)
:: ----------------------------------------------------------------
:: 11) check if installed termsrv.dll version exists in rdpwrap.ini
:: ----------------------------------------------------------------
call :check_dll_version
::
::
:: F I N I S H
::
echo.
goto :eof
::
:: ----------------------------------------------
:: Search termsrv.dll version in file rdpwrap.ini
:: ----------------------------------------------
:check_dll_version
if exist %rdpwrap_ini_check% (
echo [*] Start searching [%termsrv_dll_ver%] version entry in file %rdpwrap_ini_check%...
findstr /c:"[%termsrv_dll_ver%]" %rdpwrap_ini_check% >nul&&(
echo [+] Found "termsrv.dll" version entry [%termsrv_dll_ver%] in file %rdpwrap_ini_check%.
echo [.] ..............................................
echo [*] RDP Wrapper seems to be up-to-date and working...
)||(
echo [-] NOT found "termsrv.dll" version entry [%termsrv_dll_ver%] in file %rdpwrap_ini_check%^^!
if not "!rdpwrap_ini_update_github_%github_location%!" == "" (
set rdpwrap_ini_url=!rdpwrap_ini_update_github_%github_location%!
call :update
call :check_dll_version
) else (
if %autogen%==0 (
set autogen=1
set /a github_location=1
set rdpwrap_ini_url=%rdpwrap_ini_update_github_1%
echo [.] ......................................................................................................
echo [~] Start the process of automatically generating entries for "termsrv.dll" with version [%termsrv_dll_ver%]
call :update
call :check_dll_version
) else (
echo [*] NOT found "termsrv.dll" version entry [%termsrv_dll_ver%] in file %rdpwrap_ini_check%^^!
echo [-] Give up - "termsrv.dll" version [%termsrv_dll_ver%] is not yet supported at the moment^^!
echo [~] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo [X] RDP Wrapper will probably not work correctly ...
)
)
)
) else (
echo [-] File NOT found: %rdpwrap_ini_check%.
echo [*] Give up - Please check if Antivirus/Firewall blocks the file %rdpwrap_ini_check%^^!
)
goto :eof
::
:: -----------------------------------------------------
:: Install RDP Wrapper (exactly uninstall and reinstall)
:: -----------------------------------------------------
:install
echo.
echo [*] Uninstall and reinstall RDP Wrapper...
echo.
if exist %rdpwrap_dll% set rdpwrap_force_uninstall=1
if exist %rdpwrap_ini% set rdpwrap_force_uninstall=1
if "%rdpwrap_force_uninstall%"=="1" (
echo [*] Set windows registry entry for "rdpwrap.dll" to force uninstall...
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\TermService\Parameters" /f /v ServiceDll /t REG_EXPAND_SZ /d %rdpwrap_dll%
)
call :update
set rdpwrap_installed=1
::call :setNLA
goto :eof
::
:: -------------------
:: Restart RDP Wrapper
:: -------------------
:restart
echo.
echo [*] Restart RDP Wrapper with new ini (uninstall and reinstall)...
echo.
%RDPWInst_exe% -u
if exist %rdpwrap_new_ini% (
echo.
echo [*] Use latest downloaded rdpwrap.ini from GitHub...
echo -^> %rdpwrap_ini_url%
echo -^> %rdpwrap_new_ini%
echo -^> %rdpwrap_ini%
echo [+] copy %rdpwrap_new_ini% to %rdpwrap_ini%...
copy %rdpwrap_new_ini% %rdpwrap_ini%
echo.
) else (
echo [x] ERROR - File %rdpwrap_new_ini% is missing ^^!
)
%RDPWInst_exe% -i
::call :setNLA
goto :eof
::
:: -----------------------------------
:: check if online access is available
:: -----------------------------------
:update
echo [*] check network connectivity...
call :netcheck
call :checkversion
goto :eof
::
:: -----------------------------------
:: check if online access is available
:: -----------------------------------
:netcheck
ping -n 1 google.com>nul
if errorlevel 1 (
echo [.] Wait for network connection is available...
ping 127.0.0.1 -n 11>nul
set /a retry_network_check=retry_network_check+1
:: wait for a maximum of 5 minutes
if %retry_network_check% LSS 30 call netcheck
)
goto :eof
::
:: ---------------------------------------------------
:: check if new version of autoupdate.bat is available
:: ---------------------------------------------------
:checkversion
if %version_check%==1 (
call :download
goto :eof
)
set version_check=1
echo.
echo [*] get version info of autoupdate.bat from GitHub...
echo -^> %autoupdate_ver_url%
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:saveWebBinary %autoupdate_ver_url% %autoupdate_ver%`
) do (
set "download_status=%%a"
)
if not "%download_status%"=="-1" (
echo [-] FAILED to get version info of autoupdate.bat from GitHub...
echo [*] Please check you internet connection/firewall and try again^^!
call :download
goto :eof
)
for /f "usebackq tokens=*" %%a in (%autoupdate_ver%) do (set "autoupdate_online_version=%%a")
echo [+] Successfully get autoupdate 'v.%autoupdate_online_version%' info from GitHhub.
if %autoupdate_version% GEQ %autoupdate_online_version% (
echo [*] autoupdate 'v.%autoupdate_online_version%' is up to date
call :download
goto :eof
)
echo [+] New version 'v.%autoupdate_online_version%' of autoupdate.bat available^^!
echo [*] Download new version of autoupdate.bat from GitHub...
echo -^> %autoupdate_url%
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:saveWebBinary %autoupdate_url% %autoupdate_new_bat%`
) do (
set "download_status=%%a"
)
if "%download_status%"=="-1" (
echo [+] Restart with the new autoupdate 'v.%autoupdate_online_version%' ...
if %updated%==1 (
call :download
)
if "%args%" == "" (
cmd /c %autoupdate_new_bat% -updated
) else (
cmd /c %autoupdate_new_bat% -updated %args%
)
exit
) else (
echo [-] FAILED to download from GitHub latest version to %autoupdate_bat%^^!
echo [*] Please check you internet connection/firewall and try again^^!
call :download
goto :eof
)
::
:: ---------------------------------------------------------------
:: Download an newer up-to-date version of rdpwrap.ini from GitHub
:: ---------------------------------------------------------------
:download
echo.
if %autogen%==1 (
echo _____________________________
echo [~] Autogeneration attempt: %github_location%
) else (
echo ______________
echo [~] Attempt: %github_location%
)
echo [*] Download latest version of rdpwrap.ini from GitHub...
echo -^> %rdpwrap_ini_url%
set /a github_location=github_location+1
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:saveWebBinary %rdpwrap_ini_url% %rdpwrap_new_ini%`
) do (
set "download_status=%%a"
)
if "%download_status%"=="-1" (
echo [+] Successfully downloaded from GitHhub latest version to %rdpwrap_new_ini%.
set rdpwrap_ini_check=%rdpwrap_new_ini%
if %autogen%==1 (
echo [~] Try to autogenerate new "termsrv.dll" [%termsrv_dll_ver%] entries for %rdpwrap_new_ini%
call :setup_autogen
)
call :restart
) else (
echo [-] FAILED to download from GitHub latest version to %rdpwrap_new_ini%^^!
echo [*] Please check you internet connection/firewall and try again^^!
)
goto :eof
::
:: -----------------------------------------------------
:: Setup autogen (download debug symbols of termsrv.dll)
:: -----------------------------------------------------
:setup_autogen
if %autogen_ready%==1 (
call :start_autogen
) else (
echo [*] Setup autogenerator...
if not exist %pdblister_exe% (
call :download_pdblister
)
if not exist %cvdump_exe% (
call :download_cvdump
)
if exist %pdblister_exe% (
if exist %cvdump_exe% (
call :generate_symbol
if exist %termsrv_pdb_dump% (
call :start_autogen
)
)
)
)
goto :eof
::
:: ------------------
:: Download pdblister
:: ------------------
:download_pdblister
echo [+] Download the "Symbol Checker tool pdblister v0.0.4" from Github...
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:saveWebBinary %pdblister_url% %pdblister_zip%`
) do (
set "pdblister_status=%%a"
)
if "%pdblister_status%"=="-1" (
echo [+] Successfully downloaded the "Symbol Checker tool" file:
echo -^> %pdblister_zip%
) else (
echo [-] FAILED to download the "Symbol Checker tool" file %pdblister_zip%
echo [*] Please check you internet connection/firewall and try again^^!
goto :eof
)
echo [+] Extract pdblister.exe from zip file: %pdblister_zip%
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:unzip %pdblister_zip% %helper_path%`
) do (
set "unzip_pdblister=%%a"
)
if "%unzip_pdblister%"=="-1" (
echo [+] Successfully extracted the "Symbol Checker tool" file: %pdblister_exe%
) else (
echo [-] FAILED to extract the Symbol Checker tool" file: %pdblister_exe%
)
goto :eof
::
:: ---------------
:: Download cvdump
:: ---------------
:download_cvdump
echo [+] Download "Microsoft Debugging Information Dumper Version 14.00.23611" from Github...
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:saveWebBinary %cvdump_url% %cvdump_zip%`
) do (
set "cvdump_status=%%a"
)
if "%cvdump_status%"=="-1" (
echo [+] Successfully downloaded the "Microsoft Debugging Information Dumper" file:
echo -^> %cvdump_zip%
) else (
echo [-] FAILED to download the "Microsoft Debugging Information Dumper" file %cvdump_zip%
echo [*] Please check you internet connection/firewall and try again^^!
goto :eof
)
echo [+] Extract cvdum.exe from zip file: %cvdump_zip%
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:unzip %cvdump_zip% %helper_path%`
) do (
set "unzip_vdump=%%a"
)
if "%unzip_vdump%"=="-1" (
echo [+] Successfully extracted the "Microsoft Debugging Information Dumper" file: %cvdump_exe%
) else (
echo [-] FAILED to extract the "Microsoft Debugging Information Dumper" file: %cvdump_exe%
)
goto :eof
::
:: -----------------------------------
:: Download and generate debug symbols
:: -----------------------------------
:generate_symbol
echo [+] Download and generate debug symbols dump for "termsrv.dll" version [%termsrv_dll_ver%]
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:pdbDownload %termsrv_dll%`
) do (
set "download_pdb=%%a"
)
if "%download_pdb%"=="-1" (
echo [+] Successfully downloaded and generated the debug symbol file:
echo -^> %termsrv_pdb_dump%
set autogen_ready=1
) else (
echo [-] FAILED to download and generate the the debug symbol file: %termsrv_pdb_dump%
echo [*] Please check you internet connection/firewall and try again^^!
)
goto :eof
::
:: ------------------------------------------------
:: Autogenerate termsrv.dll entries for rdpwrap.ini
:: ------------------------------------------------
:start_autogen
echo [+] Start generating new entries for "termsrv.dll" version [%termsrv_dll_ver%]
echo [.] ........................................................................
for /f "tokens=* usebackq" %%a in (
`cscript //nologo "%~f0?.wsf" //job:GenerateTermsrvINIEntries %termsrv_dll_ver% %rdpwrap_new_ini% %termsrv_dll% %termsrv_pdb_dump%`
) do (
set "autogen_status=%%a"
)
if "%autogen_status%"=="-1" (
echo [+] Successfully generated new entries for "termsrv.dll" with version [%termsrv_dll_ver%] in the file: %rdpwrap_new_ini%
echo -^> "termsrv.dll" [%termsrv_dll_ver%]
echo -^> %termsrv_pdb_dump%
echo -^> %rdpwrap_new_ini%
) else (
echo [-] FAILED to generate new entries for "termsrv.dll" version [%termsrv_dll_ver%] in the file: %rdpwrap_new_ini%
echo [*] Reasons for the failure:
echo - missing ".autogen" templates in %rdpwrap_new_ini%
echo - wrong ".autogen" templates in %rdpwrap_new_ini%
echo - incompatible ".autogen" templates in %rdpwrap_new_ini%
)
goto :eof
::
:: --------------------------------
:: Set Network Level Authentication
:: --------------------------------
:setNLA
echo [*] Set Network Level Authentication in the windows registry...
reg.exe add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v SecurityLayer /t reg_dword /d 0x2 /f
reg.exe add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v MinEncryptionLevel /t reg_dword /d 0x2 /f
reg.exe add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v UserAuthentication /t reg_dword /d 0x1 /f
goto :eof
::
:: ---------------
:: No admin rights
:: ---------------
:not_admin
color 0e
echo ___________________________________
echo [x] ERROR - No Administrator Rights
echo [*] This script must be run as administrator to work properly^^!
echo ^<Please use 'right click' on this batch file and select "Run As Administrator"^>
echo.
timeout 60
goto :eof
::
:: ----------------
:: Error on Install
:: ----------------
:error_install
echo [-] RDP Wrapper installer executable (RDPWInst.exe) not found^^!
echo Please extract all files from the downloaded RDP Wrapper package or check your Antivirus.
echo.
goto :eof
::
:: ---------
:: Arguments
:: ---------
:header
echo _________________________________________________
echo Automatic RDP Wrapper installer and updater v.%autoupdate_version%
echo.
echo ^<check if the RDP Wrapper is up-to-date and working^>
echo.
goto :eof
:usage_arg
echo [*] Supported argments are:
echo -log = redirect display output to the file autoupdate.log
echo -taskadd = add autorun of autoupdate.bat on startup in the schedule task
echo -taskremove = remove autorun of autoupdate.bat on startup in the schedule task
echo -nowaitnet = do not wait up to 5 minutes for a valid internet connection
echo.
echo -help = shows this help
goto :eof
:missing_arg
echo [x] Unknown argument specified: "%arg_unknown%"
call :usage_arg
goto :eof
::
:: -------
:: E X I T
:: -------
exit /b
::
--- : Begin of wsf script code --- saveWebBinary, getFileVersion, unzip, pdbDownload, AUTOGEN.GenerateTermsrvINIEntries --->
<package>
<job id="saveWebBinary"><script language="VBScript">
Set args = WScript.Arguments
WScript.Echo SaveWebBinary(args(0), args(1))
Wscript.Quit
Function SaveWebBinary(strUrl, strFile)
On Error Resume Next
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Const ForWriting = 2
Dim result, web, varByteArray, strData, strBuffer, lngCounter, ado
result = false
'Download the file with any available object
Err.Clear
Set web = Nothing
Set web = CreateObject("WinHttp.WinHttpRequest.5.1")
If web Is Nothing Then Set web = CreateObject("WinHttp.WinHttpRequest")
If web Is Nothing Then Set web = CreateObject("MSXML2.ServerXMLHTTP")
If web Is Nothing Then Set web = CreateObject("Microsoft.XMLHTTP")
web.Open "GET", strURL, False
web.Send
If Err.Number = 0 And web.Status = "200" Then
varByteArray = web.ResponseBody
'Now save the file with any available method
Set ado = Nothing
Set ado = CreateObject("ADODB.Stream")
If ado Is Nothing Then
Dim fs, ts, max
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile(strFile, ForWriting, True)
strData = ""
strBuffer = ""
max = UBound(varByteArray)
For lngCounter = 0 To max
ts.Write Chr(255 And Ascb(Midb(varByteArray,lngCounter + 1, 1)))
Next
ts.Close
Else
ado.Type = adTypeBinary
ado.Open
ado.Write varByteArray
ado.SaveToFile strFile, adSaveCreateOverWrite
ado.Close
End If
result = True
End If
Set web = Nothing
SaveWebBinary = result
End Function
</script></job>
<job id="getFileVersion"><script language="VBScript">
Set args = WScript.Arguments
Set fso = CreateObject("Scripting.FileSystemObject")
WScript.Echo fso.GetFileVersion(args(0))
Wscript.Quit
</script></job>
<job id="unzip"><script language="VBScript">
Set args = WScript.Arguments
WScript.Echo unzip(args(0), args(1))
Wscript.Quit
Function unzip(ZipFile, ExtractTo)
On Error Resume Next
Dim fso, objShell, FilesInZip, item, result
result = False
Set fso = CreateObject("Scripting.FileSystemObject")
If FSO.FolderExists(ExtractTo) = False Then
'If the extraction location does not exist create it.
fso.CreateFolder(ExtractTo)
End If
If fso.FileExists(ZipFile) = True Then
'Extract the files from zip archive
set objShell = CreateObject("Shell.Application")
set FilesInZip=objShell.NameSpace(ZipFile).Items
objShell.NameSpace(ExtractTo).CopyHere(FilesInZip)
For Each item in FilesInZip
If fso.FileExists(fso.BuildPath(ExtractTo, item)) = True Then
result = True
End If
Next
End If
Set fso = Nothing
Set objShell = Nothing
unzip = result
End Function
</script></job>
<job id="pdbDownload"><script language="VBScript">
Set args = WScript.Arguments
WScript.Echo pdbDownload(args(0))
Wscript.Quit
Function pdbDownload(file)
On Error Resume Next
Dim result, pdb, symbol, WshShell, pdblister
result = false
pdb = ""
Set WshShell = CreateObject("WScript.Shell")
WshShell.CurrentDirectory = ".\helper"
Set pdblister = WshShell.Exec("pdblister.exe download-single SRV*.\Symbols*https://msdl.microsoft.com/download/symbols " + file + " json")
If IsObject (pdblister) Then
Do While pdblister.Status = 0
WScript.Sleep 100
Loop
Dim aStdOut: aStdOut = Split(pdblister.StdOut.ReadAll, ",", -1, 1)
If UBound(aStdOut) = 2 Then
If InStr(LCase(aStdOut(2)),"success") Then
Dim aSymbol: aSymbol = Split(aStdOut(1), chr(34), -1, 1)
If (UBound(aSymbol) = 4) Then
If InStr(LCase(aSymbol(1)),"path") Then
pdb = Replace(aSymbol(3), "\\", "\")
End If
End if
End If
End If
End If
If pdb <> "" Then
Dim dump, fso
dump = Right(pdb, Len(pdb) - InStrRev(pdb, "\")) + ".dump"
WshShell.Run "cmd /c cvdump.exe " + pdb + " > " + dump, 1, True
Set fso = CreateObject("Scripting.FileSystemObject")
If (fso.FileExists(dump)) Then
result = true
End If
Set fso = Nothing
End If
Set pdblister = Nothing
Set WshShell = Nothing
pdbDownload = result
End Function
</script></job>
<job id="GenerateTermsrvINIEntries"><script language="VBScript">
Dim args: Set args = WScript.Arguments
Dim oAuogen: Set oAutoGen = New AUTOGEN
WScript.Echo oAutoGen.GenerateTermsrvINIEntries(args(0), args(1), args(2), args(3))
Set oAutoGen = Nothing
Wscript.Quit
Class AUTOGEN
Public Function GenerateTermsrvINIEntries(fileVersion, iniPath, termsrvPath, symbolFile)
'On Error Resume Next
Dim architecture: architecture = 0
Dim result: result = False
Dim aVer: aVer = Split(fileVersion, ".", -1, 1)
If UBound(aVer) = 3 Then
Dim pdbdump: Set pdbdump = (New TXTFile)(symbolFile)
If pdbdump.isValid Then
If (pdbdump.searchTextLine("amd64\termsrv.exp") <> "") Then
architecture = 64
ElseIf (pdbdump.searchTextLine("i386\termsrv.exp") <> "") Then
architecture = 32
End If
If architecture <> 0 Then
Dim rdpwrapini: Set rdpwrapini = (New INIFile)(iniPath)
If rdpwrapini.isValid Then
result = generateINIEntriesTermsrv(fileVersion, getSections_autogen(aVer, ".autogen"), pdbdump, architecture, rdpwrapini, termsrvPath)
If result = True Then
result = generateINIEntriesTermsrvSLInit(fileVersion + "-SLInit", getSections_autogen(aVer, ".autogen-SLInit"), pdbdump, architecture, rdpwrapini)
rdpwrapini.Save
End If
End If
Set rdpwrapini = Nothing
End If
End If
Set pdbdump = Nothing
End If
GenerateTermsrvINIEntries = result
End Function
Private Function generateINIEntriesTermsrv(fileSection, aSection, pdbdump, architecture, rdpwrapini, termsrvPath)
Dim result: result = False
Dim termsrvdll: termsrvdll = False
Dim aKeyPatch, aKeyOffset, aKeyCode, keyPatch, KeyOffset, KeyCode
If architecture = 64 Then
aKeyPatch = Array("LocalOnlyPatch.x64", "SingleUserPatch.x64", "DefPolicyPatch.x64", "SLInitHook.x64")
aKeyOffset = Array("LocalOnlyOffset.x64", "SingleUserOffset.x64", "DefPolicyOffset.x64", "SLInitOffset.x64")
aKeyCode = Array("LocalOnlyCode.x64", "SingleUserCode.x64", "DefPolicyCode.x64", "SLInitFunc.x64")
ElseIf architecture = 32 then
aKeyPatch = Array("LocalOnlyPatch.x86", "SingleUserPatch.x86", "DefPolicyPatch.x86", "SLInitHook.x86")
aKeyOffset = Array("LocalOnlyOffset.x86", "SingleUserOffset.x86", "DefPolicyOffset.x86", "SLInitOffset.x86")
aKeyCode = Array("LocalOnlyCode.x86", "SingleUserCode.x86", "DefPolicyCode.x86", "SLInitFunc.x86")
Else
generateINIEntriesTermsrv = False
Exit Function
End If
Dim funcAddress, patchAddress, offsetType, offset, pos, posMax, sec, secMax
pos = 0
posMax = UBound(aKeyPatch)
sec = 0
secMax = UBound(aSection)
For pos = 0 To posMax
For sec = 0 To secMax
keyPatch = rdpwrapini.GetValue(aSection(sec), aKeyPatch(pos))
KeyOffset = rdpwrapini.GetValue(aSection(sec), aKeyOffset(pos))
KeyCode = rdpwrapini.GetValue(aSection(sec), aKeyCode(pos))
If (keyPatch <> "") And (KeyOffset <> "") And (KeyCode <> "") Then
funcAddress = getFunctionAddress(pdbdump, keyPatch)
If funcAddress <> 0 Then
offsetType = Mid(KeyOffset, 1, 1)
If offsetType = "*" Then
If Not IsObject(termsrvdll) then
Set termsrvdll = (New BINFile)(termsrvPath)
If termsrvdll.isValid = False Then
generateINIEntriesTermsrv = False
Exit function
End If
End If
patchAddress = searchBinaryDataLocation(funcAddress, termsrvdll, Mid(KeyOffset, 2, Len(KeyOffset)-1))
ElseIf offsetType = "+" Then
On Error Resume Next
offset = CLng("&H" + Mid(KeyOffset, 2, Len(KeyOffset)-1))
On Error GoTo 0
patchAddress = funcAddress + offset
ElseIf offsetType = "-" Then
On Error Resume Next
offset = CLng("&H" + Mid(KeyOffset, 2, Len(KeyOffset)-1))
On Error GoTo 0
patchAddress = funcAddress - offset
Else
On Error Resume Next
offset = CLng("&H" + KeyOffset)
On Error GoTo 0
patchAddress = funcAddress + offset
End If
If patchAddress <> 0 Then
rdpwrapini.SetValue fileSection, aKeyPatch(pos), "1"
rdpwrapini.SetValue fileSection, aKeyOffset(pos), Hex(patchAddress)
rdpwrapini.SetValue fileSection, aKeyCode(pos), KeyCode
result = True
End If
End If
End If
Next
Next
Set termsrvdll = Nothing
generateINIEntriesTermsrv = result
End Function
Private Function generateINIEntriesTermsrvSLInit(fileSection, aSection, pdbdump, architecture, rdpwrapini)
Dim result: result = False
Dim aKey
If architecture = 64 Then
aKey = Array("bInitialized.x64", "bServerSku.x64", "lMaxUserSessions.x64", "bAppServerAllowed.x64", "bRemoteConnAllowed.x64", "bMultimonAllowed.x64", "ulMaxDebugSessions.x64", "bFUSEnabled.x64")
ElseIf architecture = 32 then
aKey = Array("bInitialized.x86", "bServerSku.x86", "lMaxUserSessions.x86", "bAppServerAllowed.x86", "bRemoteConnAllowed.x86", "bMultimonAllowed.x86", "ulMaxDebugSessions.x86", "bFUSEnabled.x86")
Else
generateINIEntriesTermsrvSLInit = False
Exit Function
End If
Dim func, funcAddress, pos, posMax, sec, secMax
pos = 0
posMax = UBound(aKey)
sec = 0
secMax = UBound(aSection)
For pos = 0 To posMax
For sec = 0 To secMax
func = rdpwrapini.GetValue(aSection(sec), aKey(pos))
If func <> "" Then
funcAddress = getFunctionAddress(pdbdump, func)
If funcAddress <> 0 Then
rdpwrapini.SetValue fileSection, aKey(pos), Hex(funcAddress)
result = True
End If
End If
Next
Next
generateINIEntriesTermsrvSLInit = result
End Function
Private Function getSections_autogen(aVer, addition)
Dim sVer2, sArray2, sArraySize2, max2, sVer3, sArray3, sArraySize3, max3, aSections, pos, size, i , jj, str
sVer2 = aVer(2)
sArraySize2 = Len(sVer2) - 1
ReDim sArray2(sArraySize2)
For i = 0 to sArraySize2
sArray2(i) = Mid(sVer2, i + 1, 1)
Next
sVer3 = aVer(3)
sArraySize3 = Len(sVer3) - 1
ReDim sArray3(sArraySize3)
For i = 0 to sArraySize3
sArray3(i) = Mid(sVer3, i + 1, 1)
Next
max2 = len(aVer(2))
max3 = len(aVer(3))
ReDim aSections(max2 + max3)
size = UBound(sArray2)
pos = 0
For i=0 To max2
str = ""
For jj=size To 0 Step -1
If jj >= pos Then
str = "*" + str
Else
str = sArray2(jj) + str
End If
Next
aSections(pos) = aVer(0) + "." + aVer(1) + "." + str + addition
pos = pos + 1
Next
size = UBound(sArray3)
pos = max2
For i=0 To max3
str = ""
For jj=size To 0 Step -1
If jj >= (pos-max2) Then
str = "*" + str
Else
str = sArray3(jj) + str
End If
Next
aSections(pos) = aVer(0) + "." + aVer(1) + "." + aVer(2) + "." + str + addition
pos = pos + 1
Next
getSections_autogen = aSections
End Function
Private Function searchBinaryDataLocation(funcAddress, termsrvdll, dataString)
Dim address, size, byteArray, byteArrayMax, arrData, pos, max, i, jj, b
address = 0
size = Len(dataString) / 2
pos = 1
max = size-1
redim arrData(max)
On Error Resume Next
For i = 0 to max
arrData(i) = CInt("&H" + Mid(dataString, pos, 2))
pos = pos + 2
Next
On Error GoTo 0
byteArray = termsrvdll.GetBytes()
byteArrayMax = UBound(byteArray) - 1
pos = 0
For i = funcAddress To byteArrayMax
b = AscB(MidB(byteArray, i + 1, 1))
If b = arrData(0) Then
For jj = 1 To max
b = AscB(MidB(byteArray, i + 1 + jj, 1))
If b = arrData(jj) Then
If jj = max Then
address = i + jj
Exit For
End If
Else
Exit For
End If
Next
End If
If address <> 0 Then Exit For
Next
searchBinaryDataLocation = address
End Function
Private Function getFunctionAddress(pdbdump, func)
Dim S_PUB32, aS_PUB32, addressOffset, addressSection, virtualAddressText, aVirtualAddress, virtualAddress
virtualAddress = 0
S_PUB32 = pdbdump.searchTextLine(func)
aS_PUB32 = SplitMultiDelimiters(S_PUB32, Array(":","[","]"), -1, 1, "|")
If (UBound(aS_PUB32) > 3 And aS_PUB32(0) = "S_PUB32") Then
On Error Resume Next
addressOffset = CInt("&H" + aS_PUB32(2))
addressSection = CLng("&H" + aS_PUB32(3))
virtualAddressText = pdbdump.SearchTextBlockLastLine(Array("SECTION HEADER #" + Hex(addressOffset), "virtual address"))
virtualAddressText = Trim(virtualAddressText)
aVirtualAddress = Split(virtualAddressText, " ", -1, 1)
virtualAddress = CLng("&H" + aVirtualAddress(0))
On Error GoTo 0
End If
getFunctionAddress = virtualAddress + addressSection
End function
Private Function SplitMultiDelimiters(text, aDelimiters, count, compare, placeholder)
If IsArray(aDelimiters) Then
Dim size, i
size = UBound(aDelimiters)
For i = 0 To size
text = Replace(text, aDelimiters(i), placeholder)
Next
End If
SplitMultiDelimiters = Split(text, placeholder, count, compare)
End Function
End Class
Const TypeBinary = 1, ForReading = 1, ForWriting = 2, ForAppending = 8
Class BINFile
Private FSO, inStream, FileName, FileBytes, Valid
Private Function GetFileContents()
If Not FileExists() Then
GetFileContents = false
Valid = false
Else
inStream.LoadFromFile(FileName)
GetFileContents = inStream.Read()
Valid = true
End If
End Function
Private Sub WriteFileContents(ByVal MyContents)
binaryStream.Write MyContents
'Save binary data to disk
binaryStream.SaveToFile FileName, ForWriting
End Sub
Public Default Function Init(MyFileName)
Valid = False
Set FSO = CreateObject("Scripting.FileSystemObject")
set inStream = WScript.CreateObject("ADODB.Stream")
inStream.Open
inStream.type= TypeBinary
FileName = MyFileName
Load
Set Init = Me
End Function
Public Sub Load
FileBytes = GetFileContents
End Sub
Public Sub Save
WriteFileContents(FileBytes)
End Sub
Public Function isValid()
isValid = Valid
End Function
Public Function GetFileName()
GetFileName = Right(FileName, Len(FileName) - InStrRev(FileName, "\"))
End Function
Public Function GetFilePath()
GetFilePath = Left(FileName, InStrRev(FileName, "\"))
End Function
Public Function FileExists()
FileExists = FSO.FileExists(FileName)
End Function
Public Function GetBytes()
GetBytes = FileBytes
End Function
Public Sub SetBytes(byteArray)
FileBytes = byteArray
End sub
End Class
Class TXTFile
Private FSO, FileName, FileContents, Valid
Private Function GetFileContents()
If Not FileExists() Then
GetFileContents = vbNullString
Valid = false
ElseIf FileIsEmpty() Then
GetFileContents = vbNullString
Valid = False
Else
GetFileContents = FSO.OpenTextFile(FileName, ForReading).ReadAll
Valid = true
End If
End Function
Private Sub WriteFileContents(ByVal MyContents)
Dim FileStream: Set FileStream = FSO.OpenTextFile(FileName, ForWriting, True)
FileStream.Write MyContents
FileStream.Close()
End Sub
Public Default Function Init(MyFileName)
Valid = false
Set FSO = CreateObject("Scripting.FileSystemObject")
FileName = MyFileName
Load
Set Init = Me
End Function
Public Sub Load
FileContents = GetFileContents
End Sub
Public Sub Save
WriteFileContents(FileContents)
End Sub
Public Function isValid()
isValid = Valid
End Function
Public Function GetFileName()
GetFileName = Right(FileName, Len(FileName) - InStrRev(FileName, "\"))
End Function
Public Function GetFilePath()
GetFilePath = Left(FileName, InStrRev(FileName, "\"))
End Function
Public Function FileExists()
FileExists = FSO.FileExists(FileName)
End Function
Public Function FileIsEmpty()
FileIsEmpty = FSO.OpenTextFile(FileName).AtEndOfStream
End Function
Public Function SearchTextLine(searchText)
Dim result: result = ""
Dim pos: pos = InStr(1, FileContents, searchText, vbTextCompare)
If pos > 0 Then
Dim lineStart: lineStart = InStrRev(FileContents, vbCrLf, pos, vbTextCompare) + 2
Dim lineEnd: lineEnd = InStr(pos, FileContents, vbCrLf, vbTextCompare)
result = Mid(FileContents, lineStart, lineEnd - lineStart)
End If
searchTextLine = result
End Function
Function SearchTextBlockLastLine(aSearchText)
Dim result: result = ""
If IsArray(aSearchText) Then
Dim ln: ln = 0
Dim max: max = UBound(aSearchText)
Dim pos: pos = InStr(1, FileContents, aSearchText(ln), vbTextCompare)
Do While pos > 0
If ln = max Then
Dim lineStart: lineStart = InStrRev(FileContents, vbCrLf, pos, vbTextCompare) + 2
Dim lineEnd: lineEnd = InStr(pos, FileContents, vbCrLf, vbTextCompare)
result = Mid(FileContents, lineStart, lineEnd - lineStart)
Exit Do ' Abort loop when text is found
Else
ln = ln + 1
pos = InStr(pos, FileContents, aSearchText(ln), vbTextCompare)
End if
Loop
End if
SearchTextBlockLastLine = result
End Function
End Class
Class INIFile
Private FSO, FileName, FileContents, Valid
Private Function GetFileContents()
If Not FileExists() Then
GetFileContents = vbNullString
Valid = False
ElseIf FileIsEmpty() Then
GetFileContents = vbNullString
Valid = False
Else
GetFileContents = FSO.OpenTextFile(FileName, ForReading).ReadAll
Valid = true
End If
End Function
Private Function GetSectionContents(MySection, PosSection, PosEndSection)
Dim SectionContents: SectionContents = vbNullString
PosSection = InStr(1, FileContents, "[" & MySection & "]", vbTextCompare)
If PosSection > 0 Then
PosEndSection = InStr(PosSection, FileContents, vbCrLf & "[")
If PosEndSection = 0 Then PosEndSection = Len(FileContents) + 1
SectionContents = Mid(FileContents, PosSection, PosEndSection - PosSection)
End If
GetSectionContents = SectionContents
End Function
Private Sub WriteFileContents(ByVal MyContents)
Dim FileStream: Set FileStream = FSO.OpenTextFile(FileName, ForWriting, True)
FileStream.Write MyContents
FileStream.Close()
End Sub
Private Function ExtractValue(ByVal MyFrom, ByVal MyStart, ByVal MyEnd)
Dim PosS: PosS = InStr(1, MyFrom, MyStart, 1)
If PosS > 0 Then
PosS = PosS + Len(MyStart)
Dim PosE: PosE = InStr(PosS, MyFrom, MyEnd, 1)
If PosE = 0 Then PosE = InStr(PosS, MyFrom, vbCrLf, 1)
If PosE = 0 Then PosE = Len(MyFrom) + 1
ExtractValue = Mid(MyFrom, PosS, PosE - PosS)
Else
ExtractValue = vbNullString
End If
End Function
Public Default Function Init(MyFileName)
Valid = False
Set FSO = CreateObject("Scripting.FileSystemObject")
FileName = MyFileName
Load
Set Init = Me
End Function
Public Sub Load
FileContents = GetFileContents
End Sub
Public Sub Save
WriteFileContents(FileContents)
End Sub
Public Function isValid()
isValid = Valid
End Function
Public Function GetFileName()
GetFileName = Right(FileName, Len(FileName) - InStrRev(FileName, "\"))
End Function
Public Function GetFilePath()
GetFilePath = Left(FileName, InStrRev(FileName, "\"))
End Function
Public Function FileExists()
FileExists = FSO.FileExists(FileName)
End Function
Public Function FileIsEmpty()
FileIsEmpty = FSO.OpenTextFile(FileName).AtEndOfStream
End Function
Public Function GetSections()
Dim SectionsRegExp: Set SectionsRegExp = New RegExp
' Matches a [Section] on its own line. Could be at the very beginning of the file,
' in the middle of the file, or at the very end of the file (an empty [Section]).
SectionsRegExp.Pattern = "([\r\n]\[|^\[)([^\]]*)(\][\r\n]|\]$)"
SectionsRegExp.Global = True ' Matches all occurrences, not just the first one.
Dim SectionMatches: Set SectionMatches = SectionsRegExp.Execute(FileContents)
Dim Sections: Sections = Array()
Dim Index
If SectionMatches.Count > 0 Then
For Index = 0 To SectionMatches.Count - 1
ReDim Preserve Sections(Index)
Sections(Index) = SectionMatches.Item(Index).SubMatches(1)
Next
End If
GetSections = Sections
End Function
Public Function GetKeys(MySection)
Dim PosSection: PosSection = 0
Dim PosEndSection: PosEndSection = 0
Dim SectionContents: SectionContents = GetSectionContents(MySection, PosSection, PosEndSection)
Dim KeysRegExp: Set KeysRegExp = New RegExp
' Matches a key= on its own line; captures the name of the key.
KeysRegExp.Pattern = "[\r\n]{1,2}([^=]*)="
KeysRegExp.Global = True
Dim KeyMatches: Set KeyMatches = KeysRegExp.Execute(SectionContents)
Dim Keys: Keys = Array()
Dim Index
If KeyMatches.Count > 0 Then
For Index = 0 To KeyMatches.Count - 1
ReDim Preserve Keys(Index)
Keys(Index) = KeyMatches.Item(Index).SubMatches(0)
Next
End If
GetKeys = Keys
End Function
Public Function GetValue(MySection, MyKeyName)
Dim Value
Dim PosSection: PosSection = 0
Dim PosEndSection: PosEndSection = 0
Dim SectionContents: SectionContents = GetSectionContents(MySection, PosSection, PosEndSection)
Dim re : Set re = New RegExp
re.Global = True
re.Pattern = " +" 'remove one or more spaces
SectionContents = re.Replace(SectionContents, "")
Set re = Nothing
If InStr(1, SectionContents, vbCrLf & MyKeyName & "=", vbTextCompare) > 0 Then
Value = ExtractValue(SectionContents, vbCrLf & MyKeyName & "=", vbCrLf)
End If
GetValue = Value
End Function
Public Sub SetValue(MySection, MyKeyName, MyValue)
Dim PosSection: PosSection = 0
Dim PosEndSection: PosEndSection = 0
Dim OldSectionContents: OldSectionContents = GetSectionContents(MySection, PosSection, PosEndSection)
If OldSectionContents <> vbNullString Then
Dim KeyName, Line, Found, NewSectionContents
Dim re : Set re = New RegExp
re.Global = True
re.Pattern = " +" 'remove one or more spaces
OldSectionContents = re.Replace(OldSectionContents, "")
Set re = Nothing
OldSectionContents = Split(OldSectionContents, vbCrLf)
KeyName = LCase(MyKeyName & "=") ' Temp variable to find a key.
' Copy each line over; if the key matches, change its value first.
For Each Line In OldSectionContents
If LCase(Left(Line, Len(KeyName))) = KeyName Then
Line = MyKeyName & "=" & MyValue
Found = True
End If
If Line <> "" Then
NewSectionContents = NewSectionContents & Line & vbCrLf
End If
Next
If IsEmpty(Found) Then ' Key not found.
' Append it to the [Section].
NewSectionContents = NewSectionContents & MyKeyName & "=" & MyValue & vbCrLf
End If
' Combine pre-section, new section, and post-section data.
FileContents = Left(FileContents, PosSection-1) & NewSectionContents & Mid(FileContents, PosEndSection)
Else
' Section doesn't exist.
' If the file doesn't already end in a new line, and if the file isn't empty...
If Right(FileContents, 2) <> vbCrLf And Len(FileContents) > 0 Then
' Add a new line to the end of the file
FileContents = FileContents & vbCrLf
End If
' Add section data at the end of file contents.
FileContents = FileContents & vbCrLf & "[" & MySection & "]" & vbCrLf & MyKeyName & "=" & MyValue
End If
End Sub
End Class
</script></job>
</package>