@echo off

rem ##############################################################################
rem #
rem # Copyright (c) 2013 VMware, Inc. All rights reserved.
rem # -- VMware Confidential
rem #
rem ##############################################################################

set _VUM_ROLLBACK=0

set _VUM_RUNDLL32_EXE=%windir%\system32\rundll32.exe
set _VUM_REG_EXE=%windir%\system32\reg.exe
set _VUM_SC_EXE=%windir%\system32\sc.exe
set _VUM_PING_EXE=%windir%\system32\ping.exe
set _VUM_FC_EXE=%windir%\system32\fc.exe
set _VUM_XCOPY_EXE=%windir%\system32\xcopy.exe
set "_VUM_OPENSSL_FULL_PATH=%~dp0openssl\openssl.exe"

set _VUM_VC_REG_PATH="HKLM\SOFTWARE\VMware, Inc.\VMware Update Manager"
set _VUM_VC_REG_WOW_PATH="HKLM\SOFTWARE\Wow6432Node\VMware, Inc.\VMware Update Manager"

call "%~dp0common" Verifying that required tools are installed

if NOT EXIST "%_VUM_REG_EXE%" (
	set last_error=reg.exe is not present in the system32 directory.
	goto endError
)

if NOT EXIST "%_VUM_SC_EXE%" (
	set last_error=sc.exe is not present in the system32 directory.
	goto endError
)

if NOT EXIST "%_VUM_XCOPY_EXE%" (
	set last_error=xcopy.exe is not present in the system32 directory.
	goto endError
)

if NOT EXIST "%_VUM_RUNDLL32_EXE%" (
	set last_error=rundll32.exe is not present in the system32 directory.
	goto endError
)

if NOT EXIST "%_VUM_OPENSSL_FULL_PATH%" (
	set last_error="%_VUM_OPENSSL_FULL_PATH%" is not present.
	goto endError
)

call "%~dp0common" Validating input parameters

if "%ROLLBACK_BACKUP_FOLDER%"=="" (
	set last_error=Backup folder was not specified
	goto endError
)

if "%vc_username%"=="" (
	set last_error=vCenter Sever account name was not specified
	goto endError
)

if "%vc_password%"=="" (
	set last_error=vCenter Sever account password was not specified
	goto endError
)

if NOT "%1"=="-rollback" (

	if "%vum_cert_chain%"=="" (
		set last_error=vSphere Update Manager certificate chain was not specified
		goto endError
	)
	
	if "%vum_private_key%"=="" (
		set last_error=vSphere Update Manager private key was not specified
		goto endError
	)

	IF NOT EXIST "%vum_cert_chain%" (
		set last_error=Cannot find the certificate file "%vum_cert_chain%"
		goto endError
	)
	IF NOT EXIST "%vum_private_key%" (
		set last_error=Cannot find the private key file "%vum_private_key%"
		goto endError
	)
)

call "%~dp0common" Checking the product install directory

set _VUM_INSTALL_PATH=
call :GetVUMInstallDir %_VUM_VC_REG_PATH% > nul 2>&1
if "%_VUM_INSTALL_PATH%"=="" call :GetVUMInstallDir %_VUM_VC_REG_WOW_PATH% > nul 2>&1
if "%_VUM_INSTALL_PATH%"=="" (
	call "%~dp0common" Failed to load path from the registry. vSphere Update Manager might not be installed.
	call :ClearInfo
	exit /B 2
)
rem chop off the last backslash if one is present
if "%_VUM_INSTALL_PATH:~-1%" == "\" set "_VUM_INSTALL_PATH=%_VUM_INSTALL_PATH:~0,-1%"
call "%~dp0common" Detected that vSphere Update Manager is installed at "%_VUM_INSTALL_PATH%"

set _VUM_VC_ADDR=
call :GetVCServerName %_VUM_VC_REG_PATH% > nul 2>&1
if "%_VUM_VC_ADDR%"=="" call :GetVCServerName %_VUM_VC_REG_WOW_PATH% > nul 2>&1
if "%_VUM_VC_ADDR%"=="" (
	set last_error=Failed to load vCenter Server Server Name from the registry.
	goto endError
)

set _VUM_VC_PORT=
call :GetVCServerPort %_VUM_VC_REG_PATH% > nul 2>&1
if "%_VUM_VC_PORT%"=="" call :GetVCServerPort %_VUM_VC_REG_WOW_PATH% > nul 2>&1
if "%_VUM_VC_PORT%"=="" (
	set last_error=Failed to load vCenter Server Port from the registry.
	goto endError
)
call "%~dp0common" Using vCenter Server at "%_VUM_VC_ADDR%" on port "%_VUM_VC_PORT%"

set "_VUM_SSL_PATH=%_VUM_INSTALL_PATH%\SSL"

rem tool doesn't like trailing slash on config path
set "_VUM_CONFIG_PATH=%_VUM_INSTALL_PATH%"

set "_VUM_ROLLBACK_PATH=%ROLLBACK_BACKUP_FOLDER%"
rem Remove trailing slash
if "%_VUM_ROLLBACK_PATH:~-1%" == "\" set "_VUM_ROLLBACK_PATH=%_VUM_ROLLBACK_PATH:~0,-1%"
call "%~dp0common" Rollback path is "%_VUM_ROLLBACK_PATH%"

if NOT EXIST "%_VUM_ROLLBACK_PATH%" (
	mkdir "%_VUM_ROLLBACK_PATH%"
	if NOT EXIST "%_VUM_ROLLBACK_PATH%" (
		set last_error=Specified rollback directory "%_VUM_ROLLBACK_PATH%" does not exist.
		goto endError
	)
)

set "_VUM_ROLLBACK_PATH=%_VUM_ROLLBACK_PATH%\VUM"
if NOT EXIST "%_VUM_ROLLBACK_PATH%" (
	mkdir "%_VUM_ROLLBACK_PATH%"
)
call "%~dp0common" Rollback path is "%_VUM_ROLLBACK_PATH%"
if NOT EXIST "%_VUM_ROLLBACK_PATH%" (
	set last_error=vSphere Update Manager rollback directory "%_VUM_ROLLBACK_PATH%" does not exist.
	goto endError
)

rem tool doesn't like trailing slash on log path
set "_VUM_LOG_PATH=%LOGS_FOLDER%"
if "%_VUM_LOG_PATH:~-1%" == "\" set "_VUM_LOG_PATH=%_VUM_LOG_PATH:~0,-1%"
call "%~dp0common" Log path is "%_VUM_LOG_PATH%"

set "_VUM_TOOL_PATH=%_VUM_ROLLBACK_PATH%"
set _VUM_TOOL_NAME=vciInstallUtils.exe
set "_VUM_TOOL_FULL_PATH=%_VUM_TOOL_PATH%\%_VUM_TOOL_NAME%"
set _VUM_TOOL_CERT_ARGS=-C "%_VUM_CONFIG_PATH%" -L "%_VUM_LOG_PATH%"
set _VUM_TOOL_TRUST_ARGS=-v %_VUM_VC_ADDR% -p %_VUM_VC_PORT% -U "%vc_username%" -P "%vc_password%" -C "%_VUM_CONFIG_PATH%" -L "%_VUM_LOG_PATH%"

set "_VUM_PATCH_PATH=%~dp0vumutils"
set _VUM_PATCH_CANARY_NAME=vmwareUpdateManagerUtility.patch.exe
set _VUM_PATCH_INF_NAME=vumtoolupdate.inf

call "%~dp0common" Copying in files for patching

for %%i in ("vciInstallUtils.exe" "vmwareUpdateManagerUtility.exe" "libeay32.dll" "log4cpp.dll" "ssleay32.dll" "sysimgbase.dll" "ufa-common.dll" "ufa-types.dll" "vim-types.dll" "vmacore.dll" "vmomi.dll") do (
	"%_VUM_XCOPY_EXE%" /y "%_VUM_INSTALL_PATH%\%%~i" "%_VUM_TOOL_PATH%\"
	if ERRORLEVEL 1 (
		set last_error=Cannot copy "%_VUM_INSTALL_PATH%\%%~i" to "%_VUM_TOOL_PATH%\": %ERRORLEVEL%
		goto endError
	)
)

call "%~dp0common" Copied the necessary product files

rem copy in patched versioned file
"%_VUM_XCOPY_EXE%" /y "%_VUM_PATCH_PATH%\%_VUM_PATCH_CANARY_NAME%" "%_VUM_TOOL_PATH%\"
if ERRORLEVEL 1 (
	set last_error=Cannot copy "%_VUM_PATCH_PATH%\%_VUM_PATCH_CANARY_NAME%" to "%_VUM_TOOL_PATH%\": %ERRORLEVEL%
	goto endError
)

rem copy over inf file to do conditional copy
"%_VUM_XCOPY_EXE%" /y "%_VUM_PATCH_PATH%\%_VUM_PATCH_INF_NAME%" "%_VUM_TOOL_PATH%\"
if ERRORLEVEL 1 (
	set last_error=Cannot copy "%_VUM_PATCH_PATH%\%_VUM_PATCH_INF_NAME%" to "%_VUM_TOOL_PATH%\": %ERRORLEVEL%
	goto endError
)

call "%~dp0common" Copied patched files, running a conditional update

pushd "%_VUM_TOOL_PATH%"

rem let Windows figure out whether source.exe is newer and overwrite
rem need to use a .\ prefix and no quotes, otherwise things fail
"%_VUM_RUNDLL32_EXE%" setupapi.dll,InstallHinfSection DefaultInstall 128 .\%_VUM_PATCH_INF_NAME%
call "%~dp0common" result of rundll32 is %ERRORLEVEL%

popd

rem fc has errorlevel 1 if files are different, otherwise 0
"%_VUM_FC_EXE%" /b "%_VUM_TOOL_PATH%\vmwareUpdateManagerUtility.exe" "%_VUM_TOOL_PATH%\%_VUM_PATCH_CANARY_NAME%" > nul
if ERRORLEVEL 1 (
	call "%~dp0common" Patched and final files are different, using the product files
) else (
	call "%~dp0common" Patched and final files are the same, patching other unversioned file
	"%_VUM_XCOPY_EXE%" /y "%_VUM_PATCH_PATH%\%_VUM_TOOL_NAME%" "%_VUM_TOOL_PATH%\"
	if ERRORLEVEL 1 (
		set last_error=Cannot copy "%_VUM_PATCH_PATH%\%_VUM_TOOL_NAME%" to "%_VUM_TOOL_PATH%\": %ERRORLEVEL%
		goto endError
	)
)

if NOT EXIST "%_VUM_TOOL_FULL_PATH%" (
	set last_error=%_VUM_TOOL_NAME% is not present in the "%_VUM_TOOL_PATH%" directory.
	goto endError
)

call "%~dp0common" Testing vCenter Server credentials...
"%_VUM_TOOL_FULL_PATH%" %_VUM_TOOL_TRUST_ARGS% -O vccred > "%_VUM_LOG_PATH%\vum.vccred.log"
rem returns 0 for success and 102 for bad login
if ERRORLEVEL 1 (
	set last_error=Cannot login to vCenter Server using specified credentials: %ERRORLEVEL%. More details may be present in "%_VUM_LOG_PATH%\vum.vccred.log"
	goto endError
)
call "%~dp0common" Successful login to vCenter Server using the specified credentials

if "%1"=="-rollback" (
	call "%~dp0common" Rolling back previous changes from "%_VUM_ROLLBACK_PATH%"
	IF NOT EXIST "%_VUM_ROLLBACK_PATH%\rui.crt" (
		set last_error=Cannot proceed with rollback, the backup file "%_VUM_ROLLBACK_PATH%\rui.crt" does not exist.
		goto endError
	)
	IF NOT EXIST "%_VUM_ROLLBACK_PATH%\rui.key" (
		set last_error=Cannot proceed with rollback, the backup file "%_VUM_ROLLBACK_PATH%\rui.key" does not exist
		goto endError
	)
	IF NOT EXIST "%_VUM_ROLLBACK_PATH%\rui.pfx" (
		set last_error=Cannot proceed with rollback, the backup file "%_VUM_ROLLBACK_PATH%\rui.pfx" does not exist
		goto endError
	)
	set _VUM_ROLLBACK=1
	goto revertFiles
)

call "%~dp0common" Removing rollback files

IF EXIST "%_VUM_ROLLBACK_PATH%\rui.crt" (
	del "%_VUM_ROLLBACK_PATH%\rui.crt"
	if ERRORLEVEL 1 (
		set last_error=Cannot delete backup file "%_VUM_ROLLBACK_PATH%\rui.crt": %ERRORLEVEL%
		goto endError
	)
)

IF EXIST "%_VUM_ROLLBACK_PATH%\rui.key" (
	del "%_VUM_ROLLBACK_PATH%\rui.key"
	if ERRORLEVEL 1 (
		set last_error=Cannot delete backup file "%_VUM_ROLLBACK_PATH%\rui.key": %ERRORLEVEL%
		goto endError
	)
)

IF EXIST "%_VUM_ROLLBACK_PATH%\rui.pfx" (
	del "%_VUM_ROLLBACK_PATH%\rui.pfx"
	if ERRORLEVEL 1 (
		set last_error=Cannot delete backup file "%_VUM_ROLLBACK_PATH%\rui.pfx": %ERRORLEVEL%
		goto endError
	)
)

call "%~dp0common" Backing up files to "%_VUM_ROLLBACK_PATH%"

"%_VUM_XCOPY_EXE%" "%_VUM_SSL_PATH%\rui.crt" "%_VUM_ROLLBACK_PATH%\"
if ERRORLEVEL 1 (
	set last_error=Cannot copy "%_VUM_SSL_PATH%\rui.crt" to "%_VUM_ROLLBACK_PATH%": %ERRORLEVEL%
	goto endError
)

"%_VUM_XCOPY_EXE%" "%_VUM_SSL_PATH%\rui.key" "%_VUM_ROLLBACK_PATH%\"
if ERRORLEVEL 1 (
	set last_error=Cannot copy "%_VUM_SSL_PATH%\rui.key" to "%_VUM_ROLLBACK_PATH%": %ERRORLEVEL%
	del "%_VUM_ROLLBACK_PATH%\rui.crt"
	goto endError
)

"%_VUM_XCOPY_EXE%" "%_VUM_SSL_PATH%\rui.pfx" "%_VUM_ROLLBACK_PATH%\"
if ERRORLEVEL 1 (
	set last_error=Cannot copy "%_VUM_SSL_PATH%\rui.pfx" to "%_VUM_ROLLBACK_PATH%": %ERRORLEVEL%
	del "%_VUM_ROLLBACK_PATH%\rui.key"
	del "%_VUM_ROLLBACK_PATH%\rui.crt"
	goto endError
)

call "%~dp0common" Copying in new certificate files

"%_VUM_XCOPY_EXE%" /y "%vum_cert_chain%" "%_VUM_INSTALL_PATH%\SSL\rui.crt"
if ERRORLEVEL 1 (
	set last_error=Cannot copy rui.crt: %ERRORLEVEL%
	goto endErrorUndoCopy
)

"%_VUM_XCOPY_EXE%" /y "%vum_private_key%" "%_VUM_INSTALL_PATH%\SSL\rui.key"
if ERRORLEVEL 1 (
	set last_error=Cannot copy rui.key: %ERRORLEVEL%
	goto endErrorUndoCopy
)

call "%~dp0common" Creating pfx file

IF EXIST "%_VUM_INSTALL_PATH%\SSL\rui.pfx" del "%_VUM_INSTALL_PATH%\SSL\rui.pfx"
"%_VUM_OPENSSL_FULL_PATH%" pkcs12 -export -out "%_VUM_INSTALL_PATH%\SSL\rui.pfx" -in "%_VUM_INSTALL_PATH%\SSL\rui.crt" -inkey "%_VUM_INSTALL_PATH%\SSL\rui.key" -name rui -passout pass:testpassword 2>&1
if ERRORLEVEL 1 (
	set last_error=openssl.exe Cannot generate rui.pfx: %ERRORLEVEL%
	goto endErrorUndoCopy
)

call "%~dp0common" Updated files

:stopServices

call "%~dp0common" Stopping services

"%_VUM_SC_EXE%" stop vmware-ufad-vci > nul
"%_VUM_SC_EXE%" stop vmware-ufad-vci > nul
if ERRORLEVEL 1063 (
	call "%~dp0common" Failed to stop vSphere Update Manager: %ERRORLEVEL%
	goto stopUfa
)
if ERRORLEVEL 1062 (
	call "%~dp0common" vSphere Update Manager has not been started
	goto stopUfa
)
if ERRORLEVEL 1061 (
	call "%~dp0common" Waiting to stop vSphere Update Manager
	"%_VUM_PING_EXE%" localhost > nul
	goto stopServices
)
if ERRORLEVEL 1 (
	call "%~dp0common" Failed to stop vSphere Update Manager: %ERRORLEVEL%
	goto stopUfa
)

:stopUfa
"%_VUM_SC_EXE%" stop vmware-vum-ufa > nul
"%_VUM_SC_EXE%" stop vmware-vum-ufa > nul
if ERRORLEVEL 1063 (
	call "%~dp0common" Failed to stop vSphere Update Manager UFA: %ERRORLEVEL%
	goto updateServices
)
if ERRORLEVEL 1062 (
	call "%~dp0common" vSphere Update Manager UFA has not been started
	goto updateServices
)
if ERRORLEVEL 1061 (
	call "%~dp0common" Need to wait to stop vSphere Update Manager UFA
	"%_VUM_PING_EXE%" localhost > nul
	goto stopUfa
)
if ERRORLEVEL 1 (
	call "%~dp0common" Failed to stop vSphere Update Manager UFA: %ERRORLEVEL%
	goto updateServices
)

:updateServices

call "%~dp0common" Updating services

"%_VUM_TOOL_FULL_PATH%" %_VUM_TOOL_CERT_ARGS% -I "%_VUM_CONFIG_PATH%" -O install-keystore > "%_VUM_LOG_PATH%\vum.install-keystore.log"
rem returns 0 for success but seems to log -storepass and -keypass
if ERRORLEVEL 1 (
	set last_error=Cannot update the keystore: %ERRORLEVEL%. More details may be present in "%_VUM_LOG_PATH%\vum.install-keystore.log"
	goto endErrorUndoCopyAndRestart
)

call "%~dp0common" Keystore was updated, now updating vCenter Server trust

"%_VUM_TOOL_FULL_PATH%" %_VUM_TOOL_TRUST_ARGS% -S "%_VUM_CONFIG_PATH%\extension.xml" -I "%_VUM_CONFIG_PATH%" -O extupdate > "%_VUM_LOG_PATH%\vum.extupdate.log"
rem returns 0 for success
if ERRORLEVEL 1 (
	set last_error=Cannot update the vCenter Server Server extension: %ERRORLEVEL%. More details may be present in "%_VUM_LOG_PATH%\vum.extupdate.log"
	goto endErrorUndoCopyAndRestart
)

call "%~dp0common" vCenter Server trust was updated, Restarting the Update service

"%_VUM_SC_EXE%" start vmware-ufad-vci > nul
if ERRORLEVEL 1 (
	call "%~dp0common" Failed to start vSphere Update Manager: %ERRORLEVEL%
)

call "%~dp0common" vSphere Update Manager start requested, script execution is complete

goto end

:ClearInfo

rem clear username and password info
set _VUM_TOOL_TRUST_ARGS=
exit /B 0

:GetVUMInstallDir
call "%~dp0common" GetVUMInstallDir called with "%1"
set _VUM_INSTALL_PATH=
for /F "tokens=1,2*" %%i in ('%_VUM_REG_EXE% query %1 /v "InstallPath"') DO (
	if "%%i"=="InstallPath" (
		SET "_VUM_INSTALL_PATH=%%k"
	)
)
exit /B 0

:GetVCServerName
call "%~dp0common" GetVCServerName called with "%1"
set _VUM_VC_ADDR=
for /F "tokens=1,2*" %%i in ('%_VUM_REG_EXE% query %1 /v "VCServer"') DO (
	if "%%i"=="VCServer" (
		SET "_VUM_VC_ADDR=%%k"
	)
)
exit /B 0

:GetVCServerPort
call "%~dp0common" GetVCServerPort called with "%1"
set _VUM_VC_PORT=
for /F "tokens=1,2*" %%i in ('%_VUM_REG_EXE% query %1 /v "VCServerPort"') DO (
	if "%%i"=="VCServerPort" (
		SET "_VUM_VC_PORT=%%k"
	)
)
exit /B 0

:end
call :ClearInfo
exit /B 0

:endErrorUndoCopyAndRestart

call :endErrorUndoCopy

call "%~dp0common" Undo is re-running the keystore update

"%_VUM_TOOL_FULL_PATH%" %_VUM_TOOL_CERT_ARGS% -I "%_VUM_CONFIG_PATH%" -O install-keystore > "%_VUM_LOG_PATH%\vum.install-keystore.log"
if ERRORLEVEL 1 (
	call "%~dp0common" Cannot update the keystore: %ERRORLEVEL%. For more details, see "%_VUM_LOG_PATH%\vum.install-keystore.log"
)

call "%~dp0common" Undo is re-running the vCenter Server trust update

"%_VUM_TOOL_FULL_PATH%" %_VUM_TOOL_TRUST_ARGS% -S "%_VUM_CONFIG_PATH%\extension.xml" -I "%_VUM_CONFIG_PATH%" -O extupdate > "%_VUM_LOG_PATH%\vum.extupdate.log"
if ERRORLEVEL 1 (
	call "%~dp0common" Cannot update the vCenter Server Server extension: %ERRORLEVEL%. For more details, see "%_VUM_LOG_PATH%\vum.extupdate.log"
)

call "%~dp0common" Undo is starting the vSphere Update Manager service

"%_VUM_SC_EXE%" start vmware-ufad-vci > nul
if ERRORLEVEL 1 (
	call "%~dp0common" Failed to start vSphere Update Manager: %ERRORLEVEL%
	goto endError
)

goto endError

:endErrorUndoCopy
:revertFiles

call "%~dp0common" Undo is copying files from rollback path to original location

"%_VUM_XCOPY_EXE%" /y "%_VUM_ROLLBACK_PATH%\rui.crt" "%_VUM_SSL_PATH%\"
"%_VUM_XCOPY_EXE%" /y "%_VUM_ROLLBACK_PATH%\rui.key" "%_VUM_SSL_PATH%\"
"%_VUM_XCOPY_EXE%" /y "%_VUM_ROLLBACK_PATH%\rui.pfx" "%_VUM_SSL_PATH%\"

if "%_VUM_ROLLBACK%"=="1" (
	rem set rollback to 0 to prevent another goto on error paths
	call "%~dp0common" Files restored, now updating services
	set _VUM_ROLLBACK=0
	goto stopServices
)

:endError

call "%~dp0common" "%last_error%"

call :ClearInfo

exit /B 1

rem ---------------------------------------------

call "%~dp0common" Successfully updated the vSphere Update Manager SSL certificate

call :ClearInfo
