'==========================================================================
'
' NAME: Install-LAPS-6.2.0.0-M-R1.vbs
'
' AUTHOR:  Max Erenburg 
' DATE  : 4/06/2018
'
' COMMENT: This script will verify that LAPS is installed properly
' on client and servers respectively; not on DC's though. 
' *** X64 bit package only ***
'==========================================================================

Option Explicit

Dim vDate, vTime, altTime, altDate, vDateTime
vDateTime = Now

Dim oShell, oFSO, oProcessEnv, sScript, PUBLICPROPERTY, iErrCode, sMsg
Dim sDebugBlat, sMSIDebugQA, sSuccess, sPilot
Dim sMailbox1, sMailbox2, sRelayHost, sCN, sFQDN, sTry
Dim sSrcRoot, sSystem32, sLogDir, sScriptsDir, sEmailDir, sDebugLog
Dim sDomFQDN, sLib, sBlat, sEngKey
Dim sCoreBlat, sCoreBlat2, sCoreWMI, sCoreInfo, sCoreInfo2, sCoreInfo3, DebugLog
Dim oWMI, sWMIFailed, sWMIMsgBody2
Dim ProductName, IsServer, CSDver, s64Bit, DC
Dim iMSIVal, oMSIinstaller, AppName, MSIver, GUID, sAlreadyInst, sFound

Set oShell = CreateObject("WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oProcessEnv = oShell.Environment("PROCESS")

' Packager's defined variable's for MSI based installations
Const PRODUCTCODE = "{EA8CB806-C109-4700-96B4-F1F268E5036C}" ' x64 package
Const DEPLOYNAME = "LAPS-x64-6.2.0.0"
Const SIDE = "-M"
Const RELEASE = "-R1"
Const VERSION = "6.2.0.0"
sScript = "Install-" & DEPLOYNAME & SIDE & RELEASE
PUBLICPROPERTY = ""

sDebugBlat = "False" ' Email if blat found missing and copied down local.
sMSIDebugQA = "False" ' QA Mode for MSI '(used to speed up large package testing by running "Notepad" instead of actual MSI/EXE to test pre/post functions
sSuccess = "False" ' Set to False if you dont want success emails. ' For enterprise deployment set to false, for one of installations leave as True
sPilot = "False" ' Set to False if you dont want attachment of debug file to success emails. ' Use for QA/UAT, once ready for Production deployments set to False

sMailbox1 = "merenburg@theorchard.com" : sMailbox2 = ""
sRelayHost = "smtp-relay.gmail.com"
sCN = oProcessEnv("COMPUTERNAME")
sFQDN = "@TheOrchard.com"
sTry = "2"

sSrcRoot = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
sSystem32 = oProcessEnv("SYSTEMROOT") & "\system32\"
sLogDir = oProcessEnv("SYSTEMROOT") & "\EngLogs"
sScriptsDir = sLogDir & "\Scripts"
sEmailDir = sLogDir & "\Email"
sDebugLog = sScriptsDir & "\" & sScript & ".log"

sBlat = sSystem32 & "blat.exe"
sEngKey = "HKLM\SOFTWARE\ORCDENG\"

' Get Domain Name we are working with so we dont have to have additional copies of same script per AD Forest/Domain.
Call GetDomainName
sLib = "\\" & sDomFQDN & "\netlogon\lib\"

' Ensure email alerts are available
Call CopyBlat

' Initialize WMI connection to cimv2
On Error Resume Next 
Set oWMI = GetObject("winmgmts:\\.\root\cimv2")
If Err.Number <> 0 Then
	iErrCode = Err.Number
	sWMIFailed = "Failed"
	sWMIMsgBody2 = Now & "__ Script was unable to successfully connect to cimv2, Error code: " & iErrCode & ", installations are dependent on WMI being healthy, cannot proceed."
End If
On Error GoTo 0

sMsg = sMsg & "|ScriptPath: " & WScript.ScriptFullName

' Create directory(s) for local centralized logging
Call CreateLogDirs

' Create debug log or append to log if this script has been run before
Call CreateDebugLog("FirstCheck")

If sWMIFailed = "Failed" Then 'fail with hard error as we need WMI up and running (health to perform installs, etc..)
	If Not IsObject(DebugLog) Then Call CreateDebugLog("WriteLog")
	WSHLog "CriticalFailure", sWMIMsgBody2
End If

Dim SRVACCT, CLTACCT : SRVACCT = "mhightower" :  CLTACCT = "etackleberry"

' Get what OS, CSD version are we working with
Call GetOSInfo

' Check if product is already Installed
Call ChkPkgAlreadyInstalled

If sAlreadyInst = "No" Then
	If Not IsObject(DebugLog) Then Call CreateDebugLog("WriteLog") : sPilot = "True"
	DebugLog.WriteLine(Now & "__ Product: " & PRODUCTCODE & " was not found installed.")

	' Pre-MSI Install
	Call MSIPreInst

	' Install MSI package
	If IsServer = "True" Then
		Call MSIPkgInstall("/qb!")
	Else
		Call MSIPkgInstall("/qn")
		Call GPUpdate
	End If
Else ' sAlreadyInst = "Yes" and you wish to run a health check on installation
	Call AppHealthCheck
End If

If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Wrapper execution complete, total execution time: " & DateDiffToWords(vDateTime,Now))
WSHLog "Information", "Wrapper execution complete, total execution time: " & DateDiffToWords(vDateTime,Now)

' Log/email exit code, cleanup and exit
If Not(IsNull(iMSIVal) Or IsEmpty(iMSIVal)) Then
	If Not IsObject(DebugLog) Then Call CreateDebugLog("WriteLog")
	DebugLog.WriteLine(Now & "__ Exiting... Wrapper exit code: " & iMSIVal)
	If (sSuccess = "True") And (sPilot = "False") And (sCoreBlat = "") Then Email sScript & "  Status", WScript.ScriptFullName & ", wrapper exit code: " & iMSIVal & " " & sMsg
	Call Cleanup(sScript & "  Status", WScript.ScriptFullName & ", wrapper exit code: " & iMSIVal & " " & sMsg)
	WScript.Quit(iMSIVal)
ElseIf Not (IsNull(iErrCode) Or IsEmpty(iErrCode)) Then
	If Not IsObject(DebugLog) Then Call CreateDebugLog("WriteLog")
	DebugLog.WriteLine(Now & "__ Exiting... Wrapper exit code : " & iErrCode)
	If (sSuccess = "True") And (sPilot = "False") And (sCoreBlat = "") Then Email sScript & "  Status", WScript.ScriptFullName & ", wrapper exit code : " & iErrCode & " " & sMsg
	Call Cleanup(sScript & "  Status", WScript.ScriptFullName & ", wrapper exit code : " & iErrCode & " " & sMsg)
	WScript.Quit(iErrCode)
Else
	If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Exiting... Wrapper exit code  : " & Err.Number)
	If (sSuccess = "True") And (sPilot = "False") And (sCoreBlat = "") Then Email sScript & "  Status", WScript.ScriptFullName & ", wrapper exit code  : " & Err.Number & " " & sMsg
	Call Cleanup(sScript & "  Status", WScript.ScriptFullName & ", wrapper exit code  : " & Err.Number & " " & sMsg)
	WScript.Quit
End If

' ------   Packager's defined Functions/Subs section    -------

' Application/Installation Health Check Function
Function AppHealthCheck
	Dim sUser, oUser
	If IsServer = "True" Then
		sUser = SRVACCT
	Else
		sUser = CLTACCT
	End If
	On Error Resume Next
	Set oUser = GetObject("WinNT://./" & sUser & ",user")
	If Err.Number <> 0 Then
		If Not IsObject(DebugLog) Then Call CreateDebugLog("WriteLog")
		DebugLog.WriteLine(Now & "__ Product: " & PRODUCTCODE & " was found installed, but user account " & sUser & " does not exit. Have to uninstall and reinstall LAPS.")
		sPilot = "True"
		If IsServer = "True" Then 
			Call MSIUninstall("/qb!")
		Else
			Call MSIUninstall("/qn")
		End If
		Call MSIPreInst
		If IsServer = "True" Then 
			Call MSIPkgInstall("/qb!")
		Else
			Call MSIPkgInstall("/qn")
			Call GPUpdate
		End If
	Else
		If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ User account " & sUser & " found exists.")
		Set oUser = Nothing
	End If
	On Error GoTo 0
End Function

' MSI package Installation Function
Function MSIPkgInstall(sDisplayOptions)
	Dim sMSIFile, sMSTFile, MSICMDLINE, sMsiLog, iInstVal
	sMSIFile = sSrcRoot & DEPLOYNAME & SIDE & RELEASE & ".msi"
	If NOT oFSO.FileExists(sMSIFile) Then
		iErrCode = "53"
		DebugLog.WriteLine(Now & "__ MSI specified to be installed in wrapper does not exist in source: " & sMSIFile)
		WSHLog "CriticalFailure", "MSI specified to be installed in wrapper does not exist in source: " & sMSIFile
	End If
	
	If oFSO.FileExists(sSrcRoot & DEPLOYNAME & SIDE & RELEASE & ".mst") Then
		sMSTFile = sSrcRoot & DEPLOYNAME & SIDE & RELEASE & ".mst"
	Else
		sMSTFile = Null
	End If
	
	Call Stamp
	If Not IsNull(sMSTFile) Then
		sMsiLog = Chr(34) & sScriptsDir & "\" & sScript & "-MSI_MST-" & altDate & "-" & altTime & ".log" & Chr(34)
		If PUBLICPROPERTY <> "" Then
			MSICMDLINE = "msiexec.exe REBOOT=ReallySuppress " & PUBLICPROPERTY & " TRANSFORMS=" & Chr(34) & sMSTFile & Chr(34) & " /i " & chr(34) & sMSIFile & chr(34) & " " & sDisplayOptions & " /L*v " & sMsiLog
		Else
			MSICMDLINE = "msiexec.exe REBOOT=ReallySuppress TRANSFORMS=" & Chr(34) & sMSTFile & Chr(34) & " /i " & chr(34) & sMSIFile & chr(34) & " " & sDisplayOptions & " /L*v " & sMsiLog
		End If
	Else
		sMsiLog = Chr(34) & sScriptsDir & "\" & sScript & "-MSI-" & altDate & "-" & altTime & ".log" & Chr(34)
		If PUBLICPROPERTY <> "" Then
			MSICMDLINE = "msiexec.exe REBOOT=ReallySuppress " & PUBLICPROPERTY & " /i " & chr(34) & sMSIFile & chr(34) & " " & sDisplayOptions & " /L*v " & sMsiLog
		Else
			MSICMDLINE = "msiexec.exe REBOOT=ReallySuppress /i " & chr(34) & sMSIFile & chr(34) & " " & sDisplayOptions & " /L*v " & sMsiLog
		End If
	End If

	DebugLog.WriteLine(Now & "__ Issuing installation commandline: " & MSICMDLINE)
	If sMSIDebugQA = "False" Then
		oProcessEnv("SEE_MASK_NOZONECHECKS") = 1
		iInstVal = oShell.Run(MSICMDLINE, 1, True)
		iMSIVal = iInstVal
		If iMSIVal = 0 Or iMSIVal = 3010 Then
			DebugLog.WriteLine(Now & "__ MSI installation completed, result code: " & iMSIVal)
		Else
			DebugLog.WriteLine(Now & "__ MSI installation FAILED, result code: " & iMSIVal)
			oProcessEnv.Remove("SEE_MASK_NOZONECHECKS")
			WSHLog "CriticalFailure", "MSI installation FAILED, result code: " & iMSIVal
		End If
	ElseIf sMSIDebugQA = "True" Then
		Dim sDebugTest
		sDebugTest = "NOTEPAD.EXE"
		iInstVal = oShell.Run(sDebugTest, 1, True)
	End If
End Function

' gpupdate function
Function GPUpdate
	On Error Resume Next
	Dim sCMD, vCT, iStat, iErrDesc
	sCMD = "gpupdate.exe /force"
	If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Executing " & sCMD)
	vCT = Now
	iStat = oShell.Run(sSystem32 & sCMD, 0, True)
	If iStat = 0 Then
		If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Execution completed, exit code: " & iStat & ", total execution time: " & DateDiffToWords(vCT,Now))
	Else
		iErrCode = iStat
		iErrDesc = CStr(iStat) & " " & Err.Description & "."
		If Not IsObject(DebugLog) Then Call CreateDebugLog("WriteLog")
		DebugLog.WriteLine(Now & "__ Execution of " & sCMD & ", FAILED. Result code: " & iErrDesc)
		WSHLog "Warning", "Execution of " & sCMD & ", FAILED. Result code: " & iErrDesc
	End If
	iStat = Null
	On Error GoTo 0
End Function

' Setup pre msi installation function
Function MSIPreInst
	If DC = "True" Then WSHLog "CriticalFailure", "This script should not have been executed on a DC."
	 	
	If IsServer = "True" Then
		PUBLICPROPERTY = "CUSTOMADMINNAME=" & SRVACCT
	Else
		PUBLICPROPERTY = "CUSTOMADMINNAME=" & CLTACCT
	End If
End Function

' Get what OS, CSD version are we working with
Function GetOSInfo
	' Get what OS, CSD version are we working with
	On Error Resume Next
	Dim sPN, sCSDVer
	sPN = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName"
	ProductName = GetRegData(sPN, "{default}")
	If ProductName = "{default}" Then
		iErrCode = "53"
		DebugLog.WriteLine(Now & "__ GetOSInfo function failed to read reg Key: " & sPN)
		WSHLog "CriticalFailure", "GetOSInfo function failed to read reg Key: " & sPN
	ElseIf ProductName = "" Then
		iErrCode = "53"
		DebugLog.WriteLine(Now & "__ GetOSInfo- function found a Null value in reg Value: " & sPN)
		WSHLog "CriticalFailure", "GetOSInfo- function found a Null value in reg Value: " & sPN
	End If
	If InStr(UCase(ProductName), "SERVER") Then
		IsServer = "True"	
	End If
	sCSDVer = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CSDVersion"
	CSDver = GetRegData(sCSDVer, "{default}")
	If CSDver = "{default}" Then CSDver = "RTM"
	s64Bit = "0"
	If oFSO.FileExists(oProcessEnv("SYSTEMROOT") & "\SysWOW64\wscript.exe") Then
		s64Bit = "1"
	End If
	If s64Bit = "1" Then
		ProductName = ProductName & " x64"
	End If
	sMsg = " | |Scriptname: " & WScript.ScriptName & " |Hostname: " & sCN & "|OS: " & ProductName & ", " & CSDver & "." ' Do not remove this last & "." otherwise it wraps
	If s64Bit = "0" Then WSHLog "CriticalFailure", "This script does not support 32 bit OS."

	Dim DeviceInfo, oDomain
	Set DeviceInfo = oWMI.ExecQuery("SELECT DomainRole FROM Win32_ComputerSystem")
	If Err.Number = 0 Then
		For Each oDomain In DeviceInfo 
			If oDomain.DomainRole = 4 Or oDomain.DomainRole = 5 Then DC = "True"
		Next
	Else
		WSHLog "CriticalFailure", "Critical issue, could not connect to WMI, cimv2:Win32_ComputerSystem to obtain DomainRole information."
	End If
	Set DeviceInfo = Nothing
	On Error GoTo 0
End Function

' Check if msi package already installed
Function ChkPkgAlreadyInstalled
	Call GetMSIInfo("GUID", PRODUCTCODE, Null, Null)
	If Not(IsNull(GUID) Or IsEmpty(GUID)) Then
		sFound = Now & "__ Found " & AppName & " v" & MSIver & " already installed."
		sAlreadyInst = "Yes"
	Else
		sAlreadyInst = "No"
	End If
End Function

' Uninstall MSI function, cProp is for when you need to have a custom condition in MSIUnistall Function to do something custom :) otherwise it doesnt matter what is passed.
Function MSIUninstall(sDisplayOptions)
	Dim sScriptUninst, MSICMDLINE, sMsiLog, iUnstVal
	sScriptUninst = "Uninstall-" & AppName & "-v" & MSIver
	Call Stamp
	sMsiLog = Chr(34) & sScriptsDir & "\" & sScriptUninst & "-MSI-" & altDate & "-" & altTime & ".log" & Chr(34)
	MSICMDLINE = "msiexec.exe REBOOT=ReallySuppress /x " & chr(34) & GUID & chr(34) & " " & sDisplayOptions & " /L*v " & sMsiLog
	DebugLog.WriteLine(Now & "__ Issuing uninstall commandline: " & MSICMDLINE)
	If sMSIDebugQA = "False" Then
		iUnstVal = oShell.Run(MSICMDLINE, 1, True)
		iMSIVal = iUnstVal
		If iMSIVal = 0 Or iMSIVal = 3010 Then
			DebugLog.WriteLine(Now & "__ MSI uninstallation completed, result code: " & iMSIVal)
		Else
			DebugLog.WriteLine(Now & "__ MSI uninstallation FAILED, result code: " & iMSIVal)
			WSHLog "CriticalFailure", "MSI uninstallation FAILED, result code: " & iMSIVal
		End If
	ElseIf sMSIDebugQA = "True" Then
		Dim sDebugTest
		sDebugTest = "NOTEPAD.EXE"
		iUnstVal = oShell.Run(sDebugTest, 1, True)
	End If
End Function


' ------   Wrapper 3.0.5 Functions/Subs section    -------

' Using WindowsInstaller engine get MSI ProductCode status Function
Function GetMSIInfo(sCond, sProperty1, sProperty2, sMatch) ' Condition = 'Name' or 'GUID' we will be providing / The name or GUID itself ' If name the type of match
	Call ResetMSIvalues
	On Error Resume Next
	Dim product, products, GetAppName
	Set oMSIinstaller = CreateObject("WindowsInstaller.Installer") : CheckError
	If oMSIinstaller Is Nothing Then
		iErrCode = "429"
		WSHLog "CriticalFailure", "Could not connect to WindowsInstaller.Installer" & Chr(13) & "Windows Installer Engine." & sMsg
	Else
		Set products = oMSIinstaller.Products : CheckError
		For Each product In products
			If UCASE(sCond) = "NAME" Then
				GetAppName = oMSIinstaller.ProductInfo(product, "ProductName")
				If UCASE(sMatch) = "EXACT" Then
					If UCASE(GetAppName) = UCASE(sProperty1) Then
						AppName = GetAppName
						GUID = product
						MSIver = oMSIinstaller.ProductInfo(product, "VersionString") : CheckError ' Installed
					End If
				Else
					If Not UCASE(sMatch) = "INSTR" Then
						If InStr(UCASE(GetAppName), UCASE(sProperty1)) And Not InStr(UCASE(GetAppName), UCASE(sMatch)) >0 Then
							AppName = GetAppName
							GUID = product
							MSIver = oMSIinstaller.ProductInfo(product, "VersionString") : CheckError ' Installed
						End If
					Else
						If InStr(UCASE(GetAppName), UCASE(sProperty1)) Then
							If InStr(UCASE(GetAppName), UCASE(sProperty2)) Then
								AppName = GetAppName
								GUID = product
								MSIver = oMSIinstaller.ProductInfo(product, "VersionString") : CheckError ' Installed
							End If
						End If
					End If
				End If
			ElseIf UCASE(sCond) = "GUID" Then
				If UCASE(product) = UCASE(sProperty1) Then
					AppName = oMSIinstaller.ProductInfo(product, "ProductName")
					GUID = product
					MSIver = oMSIinstaller.ProductInfo(product, "VersionString") : CheckError ' Installed
				End If
			End If
		Next
	End If
	Set oMSIinstaller = Nothing
	On Error GoTo 0
End Function

' Checks MSI Installer object errors Sub
Sub CheckError
	Dim message, errRec
	If Err = 0 Then Exit Sub
	message = Err.Source & " " & Hex(Err) & ": " & Err.Description
	If Not oMSIinstaller Is Nothing Then
		Set errRec = oMSIinstaller.LastErrorRecord
		If Not errRec Is Nothing Then message = message & ": " & errRec.FormatText
	End If
	iErrCode = Err.Number
	WSHLog "CriticalFailure", message  & ". " & sMsg
End Sub

' Reset MSI Values Sub
Sub ResetMSIvalues
	AppName = Null
	GUID = Null
	MSIver = Null
End Sub

' Check state of process(es), or Kill Process(es) Function
Function CheckProcess(pCond, pName, pMatch, action, sleeptime) ' Begins, Like, or Exact / %ProcessName / commandline match / Kill or Check
	On Error Resume Next
	Dim Process, oProcess, iCount
	If pCond = "Begins" Then
		Set Process = oWMI.ExecQuery("SELECT Name FROM Win32_Process WHERE Name LIKE '" & pName & "%'")
	ElseIf pCond = "Like" Then
		Set Process = oWMI.ExecQuery("SELECT Name FROM Win32_Process WHERE Name LIKE '%" & pName & "%'")
	ElseIf pCond = "Exact" Then
		Set Process = oWMI.ExecQuery("SELECT Name FROM Win32_Process WHERE Name ='" & pName & "'")
	End If
	If Process.Count = 0 Then
		CheckProcess = "notrunning" '"stopped"
	Else
		CheckProcess = "started"
		iCount = 1
		If action = "Kill" Then
			For Each oProcess In Process
				If Not IsNull(pMatch) Then
					If InStr(UCase(oProcess.CommandLine), UCase(pMatch)) Then
						oProcess.Terminate()
						If iCount < 2 Then
							DebugLog.WriteLine(Now & "__ Terminated: " & oProcess.Name & " process, ID: " & oProcess.ProcessId & " , CMDLine: " & oProcess.CommandLine)
						ElseIf iCount => 2 Then
							DebugLog.WriteLine(Now & "__ Terminated: " & oProcess.Name & " process, #" & iCount & ", ID: " & oProcess.ProcessId & " , CMDLine: " & oProcess.CommandLine)
						End If
					End If
				Else
					oProcess.Terminate()
					If iCount < 2 Then
						DebugLog.WriteLine(Now & "__ Terminated: " & oProcess.Name & " process, ID: " & oProcess.ProcessId & " , CMDLine: " & oProcess.CommandLine)
					ElseIf iCount => 2 Then
						DebugLog.WriteLine(Now & "__ Terminated: " & oProcess.Name & " process, #" & iCount & ", ID: " & oProcess.ProcessId & " , CMDLine: " & oProcess.CommandLine)
					End If
					iCount = iCount + 1
				End If
			Next
			WScript.Sleep sleeptime ' sleep to release files to be deleted. 5000 equals 5 seconds.
		Else
			' Process Audit mode
			For Each oProcess In Process
				If iCount < 2 Then
					DebugLog.WriteLine(Now & "__ Process found running: " & oProcess.Name & " process, ID: " & oProcess.ProcessId & " , CMDLine: " & oProcess.CommandLine)
				ElseIf iCount => 2 Then
					DebugLog.WriteLine(Now & "__ Process found running: " & oProcess.Name & " process, #" & iCount & ", ID: " & oProcess.ProcessId & " , CMDLine: " & oProcess.CommandLine)
				End If
			Next                                     
		End If
	End If
	On Error GoTo 0
End Function

' Check state of Service and manipulate it Function
Function CheckService(Name, Startup, Startup2, Status, DelayedAutoStart, Required)
	On Error Resume Next
	Dim oWin32Service, iErrDesc
	Set oWin32Service = GetObject("winmgmts:\\.\root\cimv2:Win32_Service")
	If Err.Number <> 0 Then
		iErrCode = Err.Number
		iErrDesc = CStr(Err.Number) & " " & Err.Description & "."
		DebugLog.WriteLine(Now & "__ Unable to connect to WMI namespace \root\cimv2:Win32_Service. ")
		WSHLog "CriticalFailure", "Unable to connect to WMI namespace \root\cimv2:Win32_Service. Error code: " & iErrDesc
	End If
	Dim oSvc, sStartMode, sState, iMode, sStartMode2, iState, sState2, sExitCode, sSVCKey, SVCKey
	Dim sleepDur, SleepTime, iSleepDur
	SleepTime = "1000"
	iSleepDur = "3"
	Set oSvc = Getobject("winmgmts:root\cimv2:Win32_Service.Name='" & Name & "'")
	If Err.Number <> 0 Then
		If UCASE(Required) = "REQUIRED" Then
			DebugLog.WriteLine(Now & "__ Service: " & Name & ", does not exist on this system and is a mandatory service.")
			WSHLog "CriticalFailure", "Service: " & Name & ", does not exist on this system and is a mandatory service."
		Else
			DebugLog.WriteLine(Now & "__ Service: " & Name & ", does not exist on this system")
			Exit Function
		End If
	Else
		sStartMode = oSvc.StartMode
		sState = oSvc.State
		If Not UCase(Startup) = "NULL" Then
			If sStartMode <> Startup Then
				iMode = oSvc.ChangeStartMode(Startup2)
				sExitCode = ResolveSVCcode(iMode)
				Set oSvc = Getobject("winmgmts:root\cimv2:Win32_Service.Name='" & Name & "'")
				sStartMode2 = oSvc.StartMode
				sState = oSvc.State
				If sStartMode2 <> Startup Then
					DebugLog.WriteLine(Now & "__ Failed to change Service: " & Name & ", from " & sStartMode & " to " & Startup2 & " (" & sExitCode & ")")
					WSHLog "Warning", "Failed to change Service: " & Name & ", from " & sStartMode & " to " & Startup2 & " (" & sExitCode & ")"
				Else
					DebugLog.WriteLine(Now & "__ Service: " & Name & ", was successfully changed from " & sStartMode & " to " & Startup2)
				End If
			Else
				DebugLog.WriteLine(Now & "__ Service: " & Name & ", found startup type already set to: " & sStartMode)
			End If
		End If
		sleepDur = 0
		If Not Status = "NoCheck" Then
			If Status = "Stopped" Then
				If sState <> Status Then                                                               
					iState = oSvc.StopService()
					sExitCode = ResolveSVCcode(iState)
					Do Until sState2 = "Stopped" Or sState2 = "Exceeded Wait Time"
						Wscript.Sleep SleepTime
						Set oSvc = Getobject("winmgmts:root\cimv2:Win32_Service.Name='" & Name & "'")
						sState2 = oSvc.State
						sleepDur = sleepDur + 1
						If sleepDur = iSleepDur Then
							sState2 = "Exceeded Wait Time" ' to get out of loop
						End If
					Loop
					If sleepDur = iSleepDur Then
						DebugLog.WriteLine(Now & "__ Service: " & Name & ", was found " & sState & "; attempt to stop the service failed OR Wait Time expired! (" & sExitCode & ")")
						WSHLog "Warning", "Service: " & Name & ", was found " & sState & "; attempt to stop the service failed OR Wait Time expired! (" & sExitCode & ")"
					Else
						DebugLog.WriteLine(Now & "__ Service: " & Name & ", was found " & sState & "; attempt to stop the service Succeeded.")
					End If
				End If
			ElseIf Status = "Running" Then
				If sState <> Status Then
					iState = oSvc.StartService()
					sExitCode = ResolveSVCcode(iState)
					Do Until sState2 = "Running" Or sState2 = "Exceeded Wait Time"
						WScript.Sleep SleepTime
						Set oSvc = Getobject("winmgmts:root\cimv2:Win32_Service.Name='" & Name & "'")
						sState2 = oSvc.State
						sleepDur = sleepDur + 1
						If sleepDur = iSleepDur Then
							sState2 = "Exceeded Wait Time" ' to get out of loop
						End If
					Loop
					If sleepDur = iSleepDur Then
						DebugLog.WriteLine(Now & "__ Service: " & Name & ", was found " & sState & "; attempt to start the service failed OR Wait Time expired! (" & sExitCode & ")")
						WSHLog "Warning", "Service: " & Name & ", was found " & sState & "; attempt to start the service failed OR Wait Time expired! (" & sExitCode & ")"
					Else
						DebugLog.WriteLine(Now & "__ Service: " & Name & ", was found " & sState & "; attempt to start the service Succeeded.")
					End If
				End If
			End If
		End If
		If DelayedAutoStart = "Delayed" Then
			sSVCKey = "HKLM\SYSTEM\CurrentControlSet\Services\" & Name & "\DelayedAutoStart"
			SVCKey = GetRegData(sSVCKey, "{default}")
			If SVCKey = "{default}" Then
				oShell.RegWrite sSVCKey, "1", "REG_DWORD"
				If Err.number <> 0 Then
					DebugLog.WriteLine(Now & "__ Found " & sSVCKey & " missing, could not create reg Key with a value of 1 (Delayed Start).")
					WSHLog "Warning", "Found " & sSVCKey & " missing, could not create reg Key with a value of 1 (Delayed Start)."
				Else
					DebugLog.WriteLine(Now & "__ Successfully created " & sSVCKey & ", with value of 1 (Delayed Start).")
				End If
			ElseIf Not SVCKey = "1" Then
				oShell.RegWrite sSVCKey, "1", "REG_DWORD"
				If Err.number <> 0 Then
					iErrCode = Err.Number
					iErrDesc = CStr(Err.Number) & " " & Err.Description & "."
					DebugLog.WriteLine(Now & "__ Found " & sSVCKey & " set to " & SVCKey & ", was not able to change it to a value of 1 (Delayed Start). Error code: " & iErrDesc)
					WSHLog "Warning", "Found " & sSVCKey & " set to " & SVCKey & ", was not able to change it to a value of 1 (Delayed Start). Error code: " & iErrDesc
				Else
					DebugLog.WriteLine(Now & "__ Successfully changed " & sSVCKey & ", with value of 1 (Delayed Start).")
				End If
			End If
		End If
	End If
	On Error GoTo 0
End Function

' Resolve Exit Code to WMI Service Change
Function ResolveSVCcode(svccode)
	Select Case svccode
		Case 0 : ResolveSVCcode = "Success"
		Case 1 : ResolveSVCcode = "Not Supported"
		Case 2 : ResolveSVCcode = "Access Denied"
		Case 3 : ResolveSVCcode = "Dependent Services Running"
		Case 4 : ResolveSVCcode = "Invalid Service Control"
		Case 5 : ResolveSVCcode = "Service Cannot Accept Control"
		Case 6 : ResolveSVCcode = "Service Not Active"
		Case 7 : ResolveSVCcode = "Service Request Timeout"
		Case 8 : ResolveSVCcode = "Unknown Failure"
		Case 9 : ResolveSVCcode = "Path Not Found"
		Case 10 : ResolveSVCcode = "Service Already Running"
		Case 11 : ResolveSVCcode = "Service Database Locked"
		Case 12 : ResolveSVCcode = "Service Dependency Deleted"
		Case 13 : ResolveSVCcode = "Service Dependency Failure"
		Case 14 : ResolveSVCcode = "Service Disabled"
		Case 15 : ResolveSVCcode = "Service Logon Failed"
		Case 16 : ResolveSVCcode = "Service Marked For Deletion"
		Case 17 : ResolveSVCcode = "Service No Thread"
		Case 18 : ResolveSVCcode = "Status Circular Dependency"
		Case 19 : ResolveSVCcode = "Status Duplicate Name"
		Case 20 : ResolveSVCcode = "Status Invalid Name"
		Case 21 : ResolveSVCcode = "Status Invalid Parameter"
		Case 22 : ResolveSVCcode = "Status Invalid Service Account"
		Case 23 : ResolveSVCcode = "Status Service Exists"
		Case 24 : ResolveSVCcode = "Service Already Paused"
		Case Else : ResolveSVCcode = svccode
	End Select
End Function

' Read Registry Key/Values Function
Function GetRegData(sRegKey, vDefault)
	On Error Resume Next
	Dim vReturn
	vReturn = oShell.RegRead(sRegKey)
	If Err.Number <> 0 Then
		GetRegData = vDefault
		Err.Clear
	Else
		GetRegData = vReturn
	End If
	On Error GoTo 0
End Function

' Will delete any regkey and it subkeys Sub
Sub DeleteRegKeys(HIVE, sHive, sKeyPath)
	On Error Resume Next
	Const HKEY_CLASSES_ROOT = &H80000000: Const HKEY_CURRENT_USER = &H80000001
	Const HKEY_LOCAL_MACHINE = &H80000002: Const HKEY_USERS = &H80000003
	Const HKEY_CURRENT_CONFIG = &H80000005: Const HKEY_DYN_DATA = &H80000006
	Dim oReg, aSubkeys, sSubkey, iReturn
	Select Case sHive
		Case "HKCR": sHive = &H80000000
		Case "HKCU": sHive = &H80000001
		Case "HKLM": sHive = &H80000002
		Case "HKU": sHive = &H80000003
		Case "HKCC": sHive = &H80000004
		Case "HKDD": sHive = &H80000005
	End Select
	If sHive = "" Then sHive = HKEY_LOCAL_MACHINE
	Set oReg = GetObject("winmgmts:\\.\root\default:StdRegProv")
	oReg.EnumKey sHive, sKeyPath, aSubkeys
	If IsArray(aSubkeys) Then
		For Each sSubkey In aSubkeys
			DeleteRegKeys HIVE, sHive, sKeyPath & "\" & sSubkey
		Next
	End If
	iReturn = oReg.DeleteKey(sHive, sKeyPath)
	If iReturn = 0 Then
		DebugLog.WriteLine(Now & "__ Succeeded deleting: " & HIVE & "\" & sKeyPath)
	Else
		DebugLog.WriteLine(Now & "__ Failed deleting: " & HIVE & "\" & sKeyPath)
		WSHLog "Warning", "Failed deleting: " & HIVE & "\" & sKeyPath
	End If
	On Error GoTo 0
End Sub

Sub RegKeyCheck(sRegKey, Hive, HiveDupe)
	Dim sHive
	Select Case Hive
		Case "HKCR": sHive = "HKEY_CLASSES_ROOT"
		Case "HKCU": sHive = "HKEY_CURRENT_USER"
		Case "HKLM": sHive = "HKEY_LOCAL_MACHINE"
		Case "HKU": sHive = "HKEY_USERS"
		Case "HKCC": sHive = "HKEY_CURRENT_CONFIG"
		Case "HKDD": sHive = "HKEY_DYN_DATA"
	End Select
	On Error Resume Next
	Dim sCheck
	sCheck = oShell.RegRead(sHive & "\" & sRegKey & "\")
	If Err.Number = 0 Then
		DebugLog.WriteLine(Now & "__ Found " & sHive & "\" & sRegKey)
		Call DeleteRegKeys(Hive, HiveDupe, sRegKey)
	End If
	On Error GoTo 0
End Sub

' Get ID of who is running the script, as well as who is logged on (if anyone) Function
Function GetWhoIsRunningScript
	On Error Resume Next
	If sWMIFailed = "Failed" Then
		sMsg = sMsg & "|Script was executed utilizing account: (WMI not available) "
		sMsg = sMsg & "|Following account(s) are logged on during execution of script: (WMI not available) "
	Else
		Dim cProcessList, oProcess, cProperties, sNameOfUser, sUserDomain
		Set cProcessList = oWMI.ExecQuery("SELECT CommandLine,Name FROM Win32_Process WHERE " & "Name = 'cscript.exe' or Name = 'wscript.exe'")
		For Each oProcess in cProcessList
			If InStr(oProcess.CommandLine, Wscript.ScriptFullName) Then
				cProperties = oProcess.GetOwner(sNameOfUser,sUserDomain)
			End If
		Next
		If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Script was executed utilizing account: " & sUserDomain & "\" & sNameOfUser)
		sMsg = sMsg & "|Script was executed utilizing account: " & sUserDomain & "\" & sNameOfUser & "."	
	
		Dim cCS, oCS, LoggedInUser
		Set cCS = oWMI.ExecQuery("SELECT UserName FROM Win32_ComputerSystem")
		LoggedInUser = "NOONE"
		For Each oCS in cCS
			LoggedInUser = oCS.UserName
		Next
		If IsNull(LoggedInUser) Then
			If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Script detected the following account(s) are logged on during start of installation: No Logon detected")
			sMsg = sMsg & "|Following account(s) are logged on during execution of script: No Logon detected"
		Else
			If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Script detected the following account(s) are logged on during start of installation: " & LoggedInUser)
			sMsg = sMsg & "|Following account(s) are logged on during execution of script: " & LoggedInUser
		End If
	End If
	On Error GoTo 0
End Function

' Creates Corporate Engineering debug log (or append to existing log if run before) Function
Function CreateDebugLog(sCondition)
	If sCondition = "WriteLog" Then
		Call CreateDebugLogNow
	Else
		If (sCoreBlat <> "" Or sCoreBlat2 <> "" Or sCoreWMI <> "" Or sCoreInfo <> "" Or sCoreInfo2 <> "" Or sCoreInfo3 <> "") Then
			Call CreateDebugLogNow
		End If
	End If
End Function

Sub CreateDebugLogNow
	On Error Resume Next
	Const ForReading = 1 : Const ForWriting = 2 : Const ForAppending = 8
	Dim iErrDesc
	If NOT oFSO.FileExists(sDebugLog) Then
		Set DebugLog = oFSO.OpenTextFile(sDebugLog, ForWriting, True)
		If Err.Number <> 0 Then
			iErrCode = Err.Number
			iErrDesc = CStr(Err.Number) & " " & Err.Description & "."
			Call GetWhoIsRunningScript
			WSHLog "CriticalFailure", "Attempt to create Debuglog: " &  sDebugLog & ", failed. Error code: " & iErrDesc
		End If
	Else ' Append to existing log
		Set DebugLog = oFSO.OpenTextFile(sDebugLog, ForAppending, True)
		If Err.Number <> 0 Then
			iErrCode = Err.Number
			iErrDesc = CStr(Err.Number) & " " & Err.Description & "."
			Call GetWhoIsRunningScript
			WSHLog "CriticalFailure", "Attempt to append to Debuglog: " &  sDebugLog & ", failed. Error code: " & iErrDesc
		Else
			DebugLog.WriteLine(" ")
		End If
	End If
	WSHLog "Information", "Commencing installation of " & DEPLOYNAME & SIDE & RELEASE
	DebugLog.WriteLine(Now & "__ Commencing installation of " & DEPLOYNAME & SIDE & RELEASE & " on " & oProcessEnv("COMPUTERNAME"))
	DebugLog.WriteLine(Now & "__ Script/Path utilized: " & Wscript.ScriptFullName)
	If sCoreBlat <> "" Then	DebugLog.WriteLine(sCoreBlat)
	If sCoreBlat2 <> "" Then DebugLog.WriteLine(sCoreBlat2)
	If sCoreWMI <> "" Then DebugLog.WriteLine(sCoreWMI)
	If sCoreInfo <> "" Then DebugLog.WriteLine(sCoreInfo)
	If sCoreInfo2 <> "" Then DebugLog.WriteLine(sCoreInfo2)
	If sCoreInfo3 <> "" Then DebugLog.WriteLine(sCoreInfo3)
	Call GetWhoIsRunningScript
	On Error GoTo 0
End Sub

' Creates Corporate Engineering Logs directory(s) for script, package installation, and custom logging if they do not exist
Function CreateLogDirs
	If Not oFSO.FolderExists(sLogDir) Then Call CreateLogDir(sLogDir)
	If Not oFSO.FolderExists(sScriptsDir) Then Call CreateLogDir(sScriptsDir)
	If Not oFSO.FolderExists(sEmailDir) Then Call CreateLogDir(sEmailDir)
End Function

' Create Log directory's requested 
Sub CreateLogDir(sDir)
	On Error Resume Next
	Dim iErrDesc
	oFSO.CreateFolder(sDir)
	If Err.Number = 0 Then
		WSHLog "Success", sDir & " directory Created."
		If sDir = sLogDir Then sCoreInfo = Now & "__ " & sLogDir & " directory Created."
		If sDir = sScriptsDir Then sCoreInfo2 = Now & "__ " & sScriptsDir & " directory Created."
		If sDir = sEmailDir Then sCoreInfo3 = Now & "__ " & sEmailDir & " directory Created."
	Else
		iErrCode = Err.Number
		iErrDesc = CStr(Err.Number) & " " & Err.Description & "."
		Call GetWhoIsRunningScript
		oProcessEnv("SEE_MASK_NOZONECHECKS") = 1
		WSHLog "CriticalFailure", "Could not create " & sDir & " directory, Error # " & iErrDesc
	End If
	On Error GoTo 0
End Sub

' Copy blat file to system to ensure email alerts are available
Function CopyBlat
	On Error Resume Next
	Dim fn, vTimeThis, sLenghtTM, iErrDesc : fn = "blat.exe"
	If Not oFSO.FileExists(sBlat) Then
		If oFSO.FileExists(sLib & fn) Then
			vTimeThis = Now
			oFSO.CopyFile sLib & fn, sSystem32 & fn, True
			If Err.Number = 0 Then
				sLenghtTM = DateDiffToWords(vTimeThis,Now)
				WSHLog "Success", "Copied " & fn & " successfully. Took: " & sLenghtTM & "."
				sCoreBlat2 = Now & "__ Copied " & fn & " successfully. Took: " & sLenghtTM & "."
				If sDebugBlat = "True" Then Email "Copied " & fn & " successfully", "Copied " & fn & " successfully. Took: " & sLenghtTM & "."
			Else
				iErrCode = Err.Number
				iErrDesc = CStr(Err.Number) & " " & Err.Description & "."
				sBlat = sLib & "blat.exe"
				oProcessEnv("SEE_MASK_NOZONECHECKS") = 1
				WSHLog "Failure", "Could not copy " & fn & " from " & sLib & " to: " & sSystem32 & ", Error # " & iErrDesc & ". Will continue with network copy..."
				oProcessEnv.Remove("SEE_MASK_NOZONECHECKS")
			End If
		Else
			sCoreBlat = Now & "__ Blat not found, not in: " & sSystem32 & ", nor in: " & sLib & " no email status will be available."
			WSHLog "Failure", "Blat not found, not in: " & sSystem32 & ", nor in: " & sLib & " no email status will be available."
		End If
	End If
	On Error GoTo 0
End Function

' Get AD domain Name
Function GetDomainName
	On Error Resume Next
	Dim Info
	Set Info = CreateObject("AdSystemInfo")
	If Err.Number <> 0 Then
		iErrCode = Err.Number	
		Call CreateLogDirs
		If Not IsObject(DebugLog) Then Call CreateDebugLog("WriteLog")
		WSHLog "CriticalFailure", "Failed to create object AdSystemInfo, error: " & iErrCode
	Else
		sDomFQDN = Info.DomainDNSName
	End If
	On Error GoTo 0
End Function

' WSH Application Event Log, logging Function
Function WSHLog(EventType, Desc)
	On Error Resume Next
	If EventType = "Information" Then oShell.LogEvent 4, sScript & Chr(13) & "------------------------------------------------------" & Chr(13) & Desc
	If EventType = "Success" Then oShell.LogEvent 0, sScript & Chr(13) & "------------------------------------------------------" & Chr(13) & Desc
	If EventType = "Warning" Then
		oShell.LogEvent 2, sScript & Chr(13) & "------------------------------------------------------" & Chr(13) & Desc
		WScript.Sleep 500
		If sCoreBlat = "" Then Email EventType, Desc & " " & sMsg
	End If
	If EventType = "Failure" Then
		oShell.LogEvent 1, sScript & Chr(13) & "------------------------------------------------------" & Chr(13) & Desc
		WScript.Sleep 500
		If sCoreBlat = "" Then Email EventType, Desc & " " & sMsg
	End If
	If EventType = "CriticalFailure" Then
		oShell.LogEvent 1, sScript & Chr(13) &    "------------------------------------------------------" & Chr(13) & Desc & " Script exiting..."
		WScript.Sleep 500
		If Not((IsNull(iMSIVal) Or IsEmpty(iMSIVal)) Or iMSIVal = 0 Or iMSIVal = 1030) Then
			If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Critical failure, exiting... Wrapper exit code: " & iMSIVal)
			sPilot = "True" ' Force attachment of debuglog since we have a critical failure
			Call Cleanup(sScript & " - " & EventType, Desc & " " & sMsg)
			WScript.Quit(iMSIVal)
		ElseIf Not(IsNull(iErrCode) Or IsEmpty(iErrCode)) Then
			If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Critical failure, exiting... Wrapper exit code : " & iErrCode)
			sPilot = "True" ' Force attachment of debuglog since we have a critical failure
			Call Cleanup(sScript & " - " & EventType, Desc & " " & sMsg)
			WScript.Quit(iErrCode)
		Else
			If IsObject(DebugLog) Then DebugLog.WriteLine(Now & "__ Critical failure exiting... Wrapper exit code  : " & Err.Number)
			sPilot = "True" ' Force attachment of debuglog since we have a critical failure
			Call Cleanup(sScript & " - " & EventType, Desc & " " & sMsg)
			WScript.Quit
		End If
	End If
	On Error GoTo 0
End Function

' EMail Results Function
Function Email(Subject, Body)
	On Error Resume Next
	Dim sTmpFile, sP1, sP2, iMail
	If Not(IsNull(sMailbox2) Or IsEmpty(sMailbox2)) Then
		sP1 = sMailbox1 & "," & sMailbox2
	Else
		sP1 = sMailbox1
	End If
	sTmpFile = sEmailDir & "\" & oFSO.GetTempName
	oFSO.CreateTextFile sTmpFile
	If Err.Number <> 0 Then
		sP2 = "-log " & Chr(34) & oProcessEnv("TEMP") & "\"
	Else
		oFSO.DeleteFile sTmpFile
		sP2 = "-log " & Chr(34) & sEmailDir & "\"
	End If

	Call Stamp
	If (sPilot = "True") And (IsObject(DebugLog)) Then
		iMail = oShell.Run(sBlat & " -body " & Chr(34) &_
		Body & Chr(34) & " -to " & sP1 & " -subject " & Chr(34) & Subject &_
		Chr(34) & " -server " & sRelayHost & " -f " & sCN & sFQDN & " -attacht " & Chr(34) & sDebugLog & Chr(34) & " -debug " & sP2 & sScript & "_" & altDate & "-" & altTime & ".log" & Chr(34) & " -try " & sTry, 2, True)
	Else
		iMail = oShell.Run(sBlat & " -body " & Chr(34) &_
		Body & Chr(34) & " -to " & sP1 & " -subject " & Chr(34) & Subject &_
		Chr(34) & " -server " & sRelayHost & " -f " & sCN & sFQDN & " -debug " & sP2 & sScript & "_" & altDate & "-" & altTime & ".log" & Chr(34) & " -try " & sTry, 2, True)
	End If
	On Error Goto 0
End Function

' Date/Time Stamping Function
Function Stamp
	On Error Resume Next
	Dim oSplit
	vDate = FormatDateTime(Now(), vbShortDate)
	altDate = Replace(Date, "/", "_")
	vTime = FormatDateTime(Now(), vbLongTime)
	altTime = Replace(Time, ":", ".")
	oSplit = Split(altTime)
	altTime = oSplit(0) & "." & oSplit(1)
	On Error GoTo 0
End Function

' Time into words Function
Function DateDiffToWords(d1, d2)
	Dim report, seconds
	report = ""
	seconds = abs(datediff("S", d1, d2))
	If seconds <= 0 Then
		report = "0 seconds"
	Else
		seconds = seconds mod (24*60*60)
		'divide by 3600 to get hours
		If seconds >= 3600 Then
			report = report & seconds\(3600) & " hour(s), "
		End If
		'use mod to get remaining seconds and divide to get minutes
		seconds = seconds mod (60*60)
		If seconds >= 60 Then
			report = report & seconds\(60) & " minute(s), "
		End If
		'use mod to get remaining seconds
		seconds = seconds Mod (60)
		report = report & seconds & " second(s)"
	End If
	DateDiffToWords = report
End Function

' Close up logs, objects, etc...
Function Cleanup(Subject, Body)
	' Close log(s)
	If IsObject(DebugLog) Then DebugLog.Close
	If (sPilot = "True") And (sCoreBlat = "") Then Email Subject, Body
	If oProcessEnv("SEE_MASK_NOZONECHECKS") = "1" Then oProcessEnv.Remove("SEE_MASK_NOZONECHECKS")
	
	'Clean Up
	Set oWMI = Nothing
	Set oProcessEnv = Nothing
	Set oFSO = Nothing
	Set oShell = Nothing
End Function

'' SIG '' Begin signature block
'' SIG '' MIITbgYJKoZIhvcNAQcCoIITXzCCE1sCAQExCzAJBgUr
'' SIG '' DgMCGgUAMGcGCisGAQQBgjcCAQSgWTBXMDIGCisGAQQB
'' SIG '' gjcCAR4wJAIBAQQQTvApFpkntU2P5azhDxfrqwIBAAIB
'' SIG '' AAIBAAIBAAIBADAhMAkGBSsOAwIaBQAEFPt/X8g/in/2
'' SIG '' RMDr3vEXQhbMb9sAoIIODDCCBBQwggL8oAMCAQICCwQA
'' SIG '' AAAAAS9O4VLXMA0GCSqGSIb3DQEBBQUAMFcxCzAJBgNV
'' SIG '' BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNh
'' SIG '' MRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9i
'' SIG '' YWxTaWduIFJvb3QgQ0EwHhcNMTEwNDEzMTAwMDAwWhcN
'' SIG '' MjgwMTI4MTIwMDAwWjBSMQswCQYDVQQGEwJCRTEZMBcG
'' SIG '' A1UEChMQR2xvYmFsU2lnbiBudi1zYTEoMCYGA1UEAxMf
'' SIG '' R2xvYmFsU2lnbiBUaW1lc3RhbXBpbmcgQ0EgLSBHMjCC
'' SIG '' ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJTv
'' SIG '' Zfi1V5+gUw00BusJH7dHGGrL8Fvk/yelNNH3iRq/nrHN
'' SIG '' EkFuZtSBoIWLZFpGL5mgjXex4rxc3SLXamfQu+jKdN6L
'' SIG '' Tw2wUuWQW+tHDvHnn5wLkGU+F5YwRXJtOaEXNsq5oIwb
'' SIG '' TwgZ9oExrWEWpGLmtECew/z7lfb7tS6VgZjg78Xr2AJZ
'' SIG '' eHf3quNSa1CRKcX8982TZdJgYSLyBvsy3RZR+g79ijDw
'' SIG '' Fwmnu/MErquQ52zfeqn078RiJ19vmW04dKoRi9rfxxRM
'' SIG '' 6YWy7MJ9SiaP51a6puDPklOAdPQD7GiyYLyEIACDG6Hu
'' SIG '' tHQFwSmOYtBHsfrwU8wY+S47+XB+tCUCAwEAAaOB5TCB
'' SIG '' 4jAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB
'' SIG '' /wIBADAdBgNVHQ4EFgQURtg+/9zjvv+D5vSFm7DdatYU
'' SIG '' qcEwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUH
'' SIG '' AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3Jl
'' SIG '' cG9zaXRvcnkvMDMGA1UdHwQsMCowKKAmoCSGImh0dHA6
'' SIG '' Ly9jcmwuZ2xvYmFsc2lnbi5uZXQvcm9vdC5jcmwwHwYD
'' SIG '' VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJ
'' SIG '' KoZIhvcNAQEFBQADggEBAE5eVpAeRrTZSTHzuxc5KBvC
'' SIG '' Ft39QdwJBQSbb7KimtaZLkCZAFW16j+lIHbThjTUF8xV
'' SIG '' OseC7u+ourzYBp8VUN/NFntSOgLXGRr9r/B4XOBLxRjf
'' SIG '' OiQe2qy4qVgEAgcw27ASXv4xvvAESPTwcPg6XlaDzz37
'' SIG '' Dbz0xe2XnbnU26UnhOM4m4unNYZEIKQ7baRqC6GD/Sjr
'' SIG '' 2u8o9syIXfsKOwCr4CHr4i81bA+ONEWX66L3mTM1fsua
'' SIG '' irtFTec/n8LZivplsm7HfmX/6JLhLDGi97AnNkiPJm87
'' SIG '' 7k12H3nD5X+WNbwtDswBsI5//1GAgKeS1LNERmSMh08W
'' SIG '' YwcxS2Ow3/MwggSfMIIDh6ADAgECAhIRIdaZp2SXPvH4
'' SIG '' Qn7pGcxTQRQwDQYJKoZIhvcNAQEFBQAwUjELMAkGA1UE
'' SIG '' BhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
'' SIG '' KDAmBgNVBAMTH0dsb2JhbFNpZ24gVGltZXN0YW1waW5n
'' SIG '' IENBIC0gRzIwHhcNMTYwNTI0MDAwMDAwWhcNMjcwNjI0
'' SIG '' MDAwMDAwWjBgMQswCQYDVQQGEwJTRzEfMB0GA1UEChMW
'' SIG '' R01PIEdsb2JhbFNpZ24gUHRlIEx0ZDEwMC4GA1UEAxMn
'' SIG '' R2xvYmFsU2lnbiBUU0EgZm9yIE1TIEF1dGhlbnRpY29k
'' SIG '' ZSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
'' SIG '' CgKCAQEAsBeuotO2BDBWHlgPse1VpNZUy9j2czrsXV6r
'' SIG '' Jf02pfqEw2FAxUa1WVI7QqIuXxNiEKlb5nPWkiWxfSPj
'' SIG '' BrOHOg5D8NcAiVOiETFSKG5dQHI88gl3p0mSl9RskKB2
'' SIG '' p/243LOd8gdgLE9YmABr0xVU4Prd/4AsXximmP/Uq+yh
'' SIG '' RVmyLm9iXeDZGayLV5yoJivZF6UQ0kcIGnAsM4t/aIAq
'' SIG '' taFda92NAgIpA6p8N7u7KU49U5OzpvqP0liTFUy5LauA
'' SIG '' o6Ml+6/3CGSwekQPXBDXX2E3qk5r09JTJZ2Cc/os+XKw
'' SIG '' qRk5KlD6qdA8OsroW+/1X1H0+QrZlzXeaoXmIwRCrwID
'' SIG '' AQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgeAMEwGA1Ud
'' SIG '' IARFMEMwQQYJKwYBBAGgMgEeMDQwMgYIKwYBBQUHAgEW
'' SIG '' Jmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9z
'' SIG '' aXRvcnkvMAkGA1UdEwQCMAAwFgYDVR0lAQH/BAwwCgYI
'' SIG '' KwYBBQUHAwgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov
'' SIG '' L2NybC5nbG9iYWxzaWduLmNvbS9ncy9nc3RpbWVzdGFt
'' SIG '' cGluZ2cyLmNybDBUBggrBgEFBQcBAQRIMEYwRAYIKwYB
'' SIG '' BQUHMAKGOGh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5j
'' SIG '' b20vY2FjZXJ0L2dzdGltZXN0YW1waW5nZzIuY3J0MB0G
'' SIG '' A1UdDgQWBBTUooRKOFoYf7pPMFC9ndV6h9YJ9zAfBgNV
'' SIG '' HSMEGDAWgBRG2D7/3OO+/4Pm9IWbsN1q1hSpwTANBgkq
'' SIG '' hkiG9w0BAQUFAAOCAQEAj6kakW0EpjcgDoOW3iPTa24f
'' SIG '' bt1kPWghIrX4RzZpjuGlRcckoiK3KQnMVFquxrzNY46z
'' SIG '' PVBI5bTMrs2SjZ4oixNKEaq9o+/Tsjb8tKFyv22XY3mM
'' SIG '' RLxwL37zvN2CU6sa9uv6HJe8tjecpBwwvKu8LUc235Ig
'' SIG '' A+hxxlj2dQWaNPALWVqCRDSqgOQvhPZHXZbJtsrKnbem
'' SIG '' uuRQ09Q3uLogDtDTkipbxFm7oW3bPM5EncE4Kq3jjb3N
'' SIG '' CXcaEL5nCgI2ZIi5sxsm7ueeYMRGqLxhM2zPTrmcuWrw
'' SIG '' nzf+tT1PmtNN/94gjk6Xpv2fCbxNyhh2ybBNhVDygNId
'' SIG '' BvVYBAexGDCCBU0wggQ1oAMCAQICEAPq4x/DNeCiI9mC
'' SIG '' 5DlK/ZUwDQYJKoZIhvcNAQELBQAwcjELMAkGA1UEBhMC
'' SIG '' VVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UE
'' SIG '' CxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGln
'' SIG '' aUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmlu
'' SIG '' ZyBDQTAeFw0xODAzMjIwMDAwMDBaFw0yMTAzMjUxMjAw
'' SIG '' MDBaMIGJMQswCQYDVQQGEwJVUzERMA8GA1UECBMITmV3
'' SIG '' IFlvcmsxETAPBgNVBAcTCE5ldyBZb3JrMSkwJwYDVQQK
'' SIG '' EyBUaGUgT3JjaGFyZCBFbnRlcnByaXNlcyBOWSwgSW5j
'' SIG '' LjEpMCcGA1UEAxMgVGhlIE9yY2hhcmQgRW50ZXJwcmlz
'' SIG '' ZXMgTlksIEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IB
'' SIG '' DwAwggEKAoIBAQC+uBrLcB6HSH12Fw3iQk0wnrBMR/Xm
'' SIG '' yH+oInoXTnQhhGhTle6PWioUUp4b7K6v1o5t/7oqqeU1
'' SIG '' TlZhFrXw20wGa0X5B2U07eeRyB9jWMyeDalbWPazUlfo
'' SIG '' gmtiGnHUTbj1+MtjtnIb2eVv7umcNoi7qhPzJvVMDIyC
'' SIG '' J4OYi6pIfV+nVjuGizGK3Ep43fj8eM1rpvpF4qxsPt/8
'' SIG '' mGgcbZVKVPERkezu8PhnqsQq6BKp6ncq+BbKaolzwRcV
'' SIG '' i7ZZzmpsnRFKU6jE06s0ptBmUCl/7WY69qMdO0Tu4RNY
'' SIG '' ItuihrFaWL2WLdjPANvTFG2xL2DgIz4LEWgSUVOu4aSw
'' SIG '' g39XAgMBAAGjggHFMIIBwTAfBgNVHSMEGDAWgBRaxLl7
'' SIG '' KgqjpepxA8Bg+S32ZXUOWDAdBgNVHQ4EFgQUFWb1jhPM
'' SIG '' z9PmvFrOw3FSTHHXyswwDgYDVR0PAQH/BAQDAgeAMBMG
'' SIG '' A1UdJQQMMAoGCCsGAQUFBwMDMHcGA1UdHwRwMG4wNaAz
'' SIG '' oDGGL2h0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEy
'' SIG '' LWFzc3VyZWQtY3MtZzEuY3JsMDWgM6Axhi9odHRwOi8v
'' SIG '' Y3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNz
'' SIG '' LWcxLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwDATAq
'' SIG '' MCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2Vy
'' SIG '' dC5jb20vQ1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEE
'' SIG '' eDB2MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
'' SIG '' Y2VydC5jb20wTgYIKwYBBQUHMAKGQmh0dHA6Ly9jYWNl
'' SIG '' cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1
'' SIG '' cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNVHRMBAf8E
'' SIG '' AjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAgdQ4jSO4z+O79
'' SIG '' 4AlCpzGIOmn8XT2WTDPXg5b5lPg3Z22YMQ5JHmRzWXax
'' SIG '' mxFAhD8kCSPGhL+MfIJMZt9hTbdM8WUinqKLNvbVDiIK
'' SIG '' O1H9Vnwz5VJ03qGRExixZOiULeeNDmj6kh4KcqFtzio0
'' SIG '' M/4GARMYiwyBg1CNlD59Jvz3RzFZugm3K+yXU1JlznMJ
'' SIG '' 8QoY0MWHsiHV/nJssNnMWCpvR7S0wC5pSn3DXeS7XVma
'' SIG '' SAc3xavwCg5sJG3LS2LKwx12ksbj+mfz+t2RqQIE5iFz
'' SIG '' 81EVhK7qbF8cbRKhgtcqbCjqr3dsj4lfMpe/+OcXR7DI
'' SIG '' wWGGyquVUv0vqiaTph2zMYIEzjCCBMoCAQEwgYYwcjEL
'' SIG '' MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu
'' SIG '' YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8G
'' SIG '' A1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENv
'' SIG '' ZGUgU2lnbmluZyBDQQIQA+rjH8M14KIj2YLkOUr9lTAJ
'' SIG '' BgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAA
'' SIG '' oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAc
'' SIG '' BgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkq
'' SIG '' hkiG9w0BCQQxFgQUdqkPcrlFPMB2BTnO26UI+fqsUqIw
'' SIG '' DQYJKoZIhvcNAQEBBQAEggEAXloLkzNkyBV3oNu1Fe7l
'' SIG '' IfFFGYQxuVMlii+dze6rCDXvnzvB0Np7czATPSklJ7RJ
'' SIG '' LTJtAimO55cvpjngbWqvlWi2wzF0SZouE0lBhN/AbKhv
'' SIG '' qJby1aiW/WcrQx47ToU+yeKgd0D9v/X/LOL8iEV+HbN0
'' SIG '' 5VnkfffTlHGvLd/L667J7fnNy0wzGnGCBRrxqQIxLBt/
'' SIG '' RN7turMUj1J0JwniOP2CkBGgnWBiK8+PWBxiujaBz2D7
'' SIG '' XDIRM3utlheyT15Vw+i/blf7goGTtpUYgRfYNLszCyjp
'' SIG '' D8MUb/RbMgACoDSnT8joJT00vaSE2UgjJ8n7hOWae36W
'' SIG '' 9qNPdwWKLKmcGKGCAqIwggKeBgkqhkiG9w0BCQYxggKP
'' SIG '' MIICiwIBATBoMFIxCzAJBgNVBAYTAkJFMRkwFwYDVQQK
'' SIG '' ExBHbG9iYWxTaWduIG52LXNhMSgwJgYDVQQDEx9HbG9i
'' SIG '' YWxTaWduIFRpbWVzdGFtcGluZyBDQSAtIEcyAhIRIdaZ
'' SIG '' p2SXPvH4Qn7pGcxTQRQwCQYFKw4DAhoFAKCB/TAYBgkq
'' SIG '' hkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJ
'' SIG '' BTEPFw0xODA0MjUwMDMyMjhaMCMGCSqGSIb3DQEJBDEW
'' SIG '' BBTcRfdz+5u1JHD4guOlicIW2AQY6TCBnQYLKoZIhvcN
'' SIG '' AQkQAgwxgY0wgYowgYcwgYQEFGO4L6th9YOQlpUFCwAk
'' SIG '' nFApM+x5MGwwVqRUMFIxCzAJBgNVBAYTAkJFMRkwFwYD
'' SIG '' VQQKExBHbG9iYWxTaWduIG52LXNhMSgwJgYDVQQDEx9H
'' SIG '' bG9iYWxTaWduIFRpbWVzdGFtcGluZyBDQSAtIEcyAhIR
'' SIG '' IdaZp2SXPvH4Qn7pGcxTQRQwDQYJKoZIhvcNAQEBBQAE
'' SIG '' ggEApF+hjG7BfjFkcAJQ+mD1ZkzJEqZc332WT2CcluD6
'' SIG '' OK/9Yjozyz35sqbL5hMqy+gzv8XICj5bIePdFI+ht45U
'' SIG '' Sgs1WxqIl4AjNbGfvU1z+GQlFykPzPIZqFlO2ICWBUW0
'' SIG '' bgl9O5AS/2g90lRgdiZLVm9DunWH+uJAI+TIcaEVQsTM
'' SIG '' yJJJ1mNNbdfjY8ZY67CVO0RkGONE7t3DAnyfoR5O6tj1
'' SIG '' eXmq0CrBgEmhTSV8w0hZuhdsrNJ0lzKsS6zuzBdQwfM0
'' SIG '' 3JKxl6uvdHSW6IKO7kiMZMYVXdZHXDsOqsM8dWVBlGmU
'' SIG '' AdId6lGDkD42Ek1b5f1p9aVPmSserQvp9GvCOg==
'' SIG '' End signature block
