HEX
Server: Apache
System: Windows NT MAGNETO-ARM 10.0 build 22000 (Windows 10) AMD64
User: Michel (0)
PHP: 7.4.7
Disabled: NONE
Upload Files
File: C:/Windows/OEM/GuestAgent.wsf
<package>
    <?component error="true" debug="true" ?>
    <reference object="WbemScripting.SWbemLocator" />
    <comment>
      Configures the Guest Agent Service.
    </comment>
    <component id="GuestAgent">
        <registration
            progid="WaGuest.GuestAgent"
            description=""
            version="1.0.0.0"
            clsid="{cfd6b1a2-1f62-4a64-ad9d-6ceb9e183aab}"/>

        <public>
            <property name="WScript" />
            <method name="Initialize">
                <param name="gaPackageName" />
            </method>
            <method name="ConfigureGuestAgent">
                <param name="kvpPrefix" />
                <param name="offlineMode" />
            </method>
            <method name="ConfigureGuestAgentOfflined">
                <param name="kvpPrefix" />
                <param name="offlineMode" />
            </method>
            <method name="UninstallGuestAgent">
                <param name="uninstallMode" />
                <param name="kvpPrefix" />
            </method>
        </public>

        <object id="WshShell" progid="WScript.Shell" />

        <script language="VBScript" src="Utility.vbs" />

        <script language="VBScript">

            Const ERROR_GAPACKAGENOTFOUND =           1
            Const ERROR_AZUREKEYNOTCONFIGURED =       2
            Const ERROR_VMTYPENOTCONFIGURED=          3
            Const ERROR_GUESTAGENTKEYNOTCONFIGURED =  4
            Const ERROR_GAINCARNATIONNOTCONFIGURED =  5
            Const ERROR_GAPACKAGENAMENOTFOUND =       6
            Const ERROR_SERVICEINSTALLEDNOTVERIFIED = 7
            Const ERROR_ENABLESERVICEFAILED =         8
            Const ERROR_STARTSERVICE =                9

            Dim g_Trace
            Dim oTraceEvent
            Dim oGAPackageName
            Dim oGuestAgentBinaryLocation
            Dim oExtractedAgentLocation
            Dim oServiceAlreadyInstalled
            Dim oOldGuestAgentBinLocation

            Sub Initialize(gaPackageName)
                Set g_Trace = GetScriptObject(Me.WScript, "Tracing.wsf", "TraceSource")
                g_Trace.Name = "GuestAgent"

                if gaPackageName <> "." then
                            oGAPackageName = gaPackageName
                            else
                    oGAPackageName = ""
                end if
            End Sub

            ' This function configures the Guest Agent on the machine and returns true if the machine should be restarted after provisioning
            ' to complete this configuration. If no restart is required this function returns false.
            ' kvpPrefix: The KVP prefix to use when logging new procedures
            ' offlineMode: Boolean indicating if the guest agent is being configured 
            '              as disabled (offlineMode=true) or enabled (offlineMode=false)
            Function ConfigureGuestAgent(kvpPrefix, offlineMode)
                On Error Resume Next
                Dim dotNetExists
                dotNetExists = False
                ConfigureGuestAgent = False
                oGuestAgentBinaryLocation = ""
                oExtractedAgentLocation = ""
                oServiceAlreadyInstalled = False
                oOldGuestAgentBinLocation = ""
                oWindowsAzureGuestAgentInstalled = False
                oTelemetryServiceAlreadyInstalled = False

                If InstrumentProcedure("VerifyOsRequirements", "", True, False, kvpPrefix & "0_VerifyOsRequirements", g_Trace) = True Then

                    oServiceAlreadyInstalled = InstrumentProcedure("CheckServiceInstalled", """RdAgent""", True, False, kvpPrefix & "1_CheckServiceInstalled", g_Trace)
                    If oServiceAlreadyInstalled = True Then
                        oOldGuestAgentBinLocation = InstrumentProcedure("GetServiceInstallLocation", """RdAgent""", True, False, kvpPrefix & "2_GetServiceInstallLocation", g_Trace)
                    End If

                    oWindowsAzureGuestAgentInstalled = InstrumentProcedure("CheckServiceInstalled", """WindowsAzureGuestAgent""", True, False, kvpPrefix & "3_CheckServiceInstalledForWindosAzureGuestAgent", g_Trace)
                    oTelemetryServiceAlreadyInstalled = InstrumentProcedure("CheckServiceInstalled", """WindowsAzureTelemetryService""", True, False, kvpPrefix & "4_CheckServiceInstalledAzureTelemetryService", g_Trace)

                    ' Stop any running or already configured Guest agent services. This will happen
                    ' when captured roles are provisioned. If service is not running or not installed then
                    ' its a no-op
                    if oServiceAlreadyInstalled = True  Then
                        Call InstrumentProcedure("StopServiceWait", """RdAgent"", ""WaAppAgent.exe""", False, False, kvpPrefix & "5_StopServiceWait-RdAgent", g_Trace)
                        If TraceError(g_Trace, "Stopping RdAgent service failed.") <> 0 Then
                            Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopRdAgentService"))
                                .setAttribute "StopServiceErrorCode", errReturnCode
                            End With
                        g_Trace.TraceEvent oTraceEvent
                        End If
                    End If

                    if oWindowsAzureGuestAgentInstalled = True Then
                        Call InstrumentProcedure("StopServiceWait", """WindowsAzureGuestAgent"", ""WindowsAzureGuestAgent.exe""", False, False, kvpPrefix & "6_StopServiceWait-WindowsAzureGuestAgent", g_Trace)
                        If TraceError(g_Trace, "Stopping WindowsAzureGuestAgent service failed.") <> 0 Then
                            Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                            With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopGuestAgentService"))
                                .setAttribute "StopServiceErrorCode", errReturnCode
                            End With
                            g_Trace.TraceEvent oTraceEvent
                        End If
                    End If

                    If oTelemetryServiceAlreadyInstalled = True Then
                        Call InstrumentProcedure("StopServiceWait", """WindowsAzureTelemetryService"", ""WindowsAzureTelemetryService.exe""", False, False, kvpPrefix & "7_StopServiceWait-WindowsAzureTelemetryService", g_Trace)
                        If TraceError(g_Trace, "Stopping WindowsAzureTelemetryService service failed.") <> 0 Then
                            Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                            With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopTelemetryService"))
                                .setAttribute "StopServiceErrorCode", errReturnCode
                            End With
                            g_Trace.TraceEvent oTraceEvent
                        End If
                    End If

                    Call InstrumentProcedure("StopEventTrace", "", False, False, kvpPrefix & "8_StopEventTrace", g_Trace)
                    TraceError g_Trace, "Stopping trace for guestagent logs failed."

                    Call InstrumentProcedure("DeleteEventTrace", "", False, False, kvpPrefix & "9_DeleteEventTrace", g_Trace)
                    TraceError g_Trace, "Deleting trace for guestagent logs failed."

                    Call InstrumentProcedure("UnzipGuestAgentPackage", "", False, False, kvpPrefix & "10_UnzipGuestAgentPackage", g_Trace)
                    If TraceError(g_Trace, "Unzipping the Guest Agent Package to " & oExtractedAgentLocation & " failed.") <> 0 Then
                        Exit Function
                    End If

                    ' Inform ConfigureRdAgentSerivce whether to enable RdAgent service when creating the services
                    Call InstrumentProcedure("ConfigureRdAgentService", BoolToString(offlineMode), False, False, kvpPrefix & "11_ConfigureRdAgentService", g_Trace)
                    If TraceError(g_Trace, "Installing the RdAgent service failed.") <> 0 Then
                        Exit Function
                    End If

                    Call InstrumentProcedure("SetVmTypeInRegistry", "", False, False, kvpPrefix & "12_SetVmTypeInRegistry", g_Trace)
                    If TraceError(g_Trace, "Setting the VMType in registry failed.") <> 0 Then
                        Exit Function
                    End If

                    ' VM is not being provisioned if we are in offline mode
                    ' inform SetGAParamsInRegistry about our mode to prevent logging provision time
                    Call InstrumentProcedure("SetGAParamsInRegistry", BoolToString(offlineMode), False, False, kvpPrefix & "13_SetGAParamsInRegistry", g_Trace)
                    If TraceError(g_Trace, "Setting the GA Settings in registry failed.") <> 0 Then
                        Exit Function
                    End If

                    dotNetExists = InstrumentProcedure("ValidDotNetVersionExists", "", True, False, kvpPrefix & "14_ValidDotNetVersionExists", g_Trace)
                    If TraceError(g_Trace, "Checking for the DotNetVersion failed.") <> 0 Then
                        Exit Function
                    End If

                    If dotNetExists = True Then
                        ' Nested condition: If we are in offlineMode, we don't want to enable the services
                        ' But we also don't want to reboot strictly because of the guest agent requirements
                        If offlineMode = False Then
                            ' Enables service if not enabled. This is needed for the service disabled during sysprep process.
                            Call InstrumentProcedure("EnableService", """RdAgent"", ""Automatic""", False, False, kvpPrefix & "15_EnableService-RdAgent", g_Trace)
                            If TraceError(g_Trace, "Enabling RdAgent service failed.") <> 0 Then
                                Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("EnableRdAgentService"))
                                    .setAttribute "EnableServiceErrorCode", errReturnCode
                                End With
                                g_Trace.TraceEvent oTraceEvent
                            End If

                            Call InstrumentProcedure("EnableService", """WindowsAzureGuestAgent"", ""Automatic""", False, False, kvpPrefix & "16_EnableService-WindowsAzureGuestAgent", g_Trace)
                            If TraceError(g_Trace, "Enabling WindowsAzureGuestAgent service failed.") <> 0 Then
                                Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("EnableWindowsAzureGuestAgentService"))
                                    .setAttribute "EnableServiceErrorCode", errReturnCode
                                End With
                                g_Trace.TraceEvent oTraceEvent
                            End If

                            Call InstrumentProcedure("EnableService", """WindowsAzureTelemetryService"", ""Automatic""", False, False, kvpPrefix & "17_EnableService-WindowsAzureTelemetryService", g_Trace)
                            If TraceError(g_Trace, "Enabling WindowsAzureTelemetryService service failed.") <> 0 Then
                                Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("EnableWindowsAzureTelemetryServiceService"))
                                    .setAttribute "EnableServiceErrorCode", errReturnCode
                                End With
                                g_Trace.TraceEvent oTraceEvent
                            End If

                            Call InstrumentProcedure("StartRdAgentService", "", False, False, kvpPrefix & "18_StartRdAgentService", g_Trace)
                            If TraceError(g_Trace, "Starting the RdAgent service failed") <> 0 Then
                                Exit Function
                            End If
                        End If
                    Else
                        ConfigureGuestAgent = True
                    End If

                    If oServiceAlreadyInstalled = True and oOldGuestAgentBinLocation <> "" Then
                        'Remove Old folder - best effort

                        Set oTraceEvent = g_Trace.CreateEvent("INFO")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("DeleteOldPackagesFolder"))
                            .setAttribute "OldFolder", oOldGuestAgentBinLocation
                        End With
                        g_Trace.TraceEvent oTraceEvent

                        Call InstrumentProcedure("DeleteFolder", """" & oOldGuestAgentBinLocation & """", False, False, kvpPrefix & "19_DeleteFolder", g_Trace)
                        TraceError g_Trace, "Deleting old packages folder '" & oOldGuestAgentBinLocation & "' failed."
                    End If
                Else
                    Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ConfigureGuestAgent"))
                            .setAttribute "VerifyOsRequirements", CStr(False)
                    End With
                    g_Trace.TraceEvent oTraceEvent
                End If
            End Function

            ' This function configures the Guest Agent on the machine that has been offlined/preprovisioned
            Function ConfigureGuestAgentOfflined(kvpPrefix, offlineMode)
                On Error Resume Next

                Dim dotNetExists

                If offlineMode = True Then
                    ' This scenario means that we are configuring the guest agent
                    ' in a preprovision state (offlineMode) but the guest agent
                    ' has already been configured (on the VHD itself)
                    ' This is a no-op as we have to wait for reprovision before enabling the services
                    Exit Function
                End If

                ConfigureGuestAgentOfflined = False
                oGuestAgentBinaryLocation = ""
                oExtractedAgentLocation = ""
                oServiceAlreadyInstalled = True
                oOldGuestAgentBinLocation = ""

                Call InstrumentProcedure("SetGAParamsInRegistryOfflined", "", False, False, kvpPrefix & "0_SetGAParamsInRegistryOfflined", g_Trace)
                If TraceError(g_Trace, "Setting the GA Settings in registry failed.") <> 0 Then
                    Exit Function
                End If

                dotNetExists = InstrumentProcedure("ValidDotNetVersionExists", "", True, False, kvpPrefix & "1_ValidDotNetVersionExists", g_Trace)
                If TraceError(g_Trace, "Checking for the DotNetVersion failed.") <> 0 Then
                    Exit Function
                End If

                ' Enable RDAgent even when restart is required. 
                ' This ensures that RdAgent launches on restart and installs .NET Framework if needed
                ' This is already done in non-offline mode when we create the service
                Call InstrumentProcedure("EnableService", QuoteString("RdAgent") & ", " & QuoteString("Automatic"), False, False, kvpPrefix & "2_EnableServiceOfflined-RdAgent", g_Trace)
                If TraceError(g_Trace, "Enabling RdAgent service failed.") <> 0 Then
                    Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("EnableRdAgentServiceOfflined"))
                        .setAttribute "EnableServiceErrorCode", errReturnCode
                    End With
                    g_Trace.TraceEvent oTraceEvent
                End If

                If dotNetExists = True Then
                    ' Enables service if not enabled. This is needed because we disabled the service when configuring in offline mode

                    Call InstrumentProcedure("EnableService", QuoteString("WindowsAzureGuestAgent") & ", " & QuoteString("Automatic"), False, False, kvpPrefix & "3_EnableServiceOfflined-WindowsAzureGuestAgent", g_Trace)
                    If TraceError(g_Trace, "Enabling WindowsAzureGuestAgent service failed.") <> 0 Then
                        Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("EnableWindowsAzureGuestAgentServiceOfflined"))
                            .setAttribute "EnableServiceErrorCode", errReturnCode
                        End With
                        g_Trace.TraceEvent oTraceEvent
                    End If

                    Call InstrumentProcedure("EnableService", QuoteString("WindowsAzureTelemetryService") & ", " & QuoteString("Automatic"), False, False, kvpPrefix & "4_EnableServiceOfflined-WindowsAzureTelemetryService", g_Trace)
                    If TraceError(g_Trace, "Enabling WindowsAzureTelemetryService service failed.") <> 0 Then
                        Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("EnableWindowsAzureTelemetryServiceServiceOfflined"))
                            .setAttribute "EnableServiceErrorCode", errReturnCode
                        End With
                        g_Trace.TraceEvent oTraceEvent
                    End If

                    Call InstrumentProcedure("StartRdAgentService", "", False, False, kvpPrefix & "5_StartRdAgentServiceOfflined", g_Trace)
                    If TraceError(g_Trace, "Starting the RdAgent service failed") <> 0 Then
                        Exit Function
                    End If
                Else
                    ConfigureGuestAgentOfflined = True
                End If
            End Function

            ' This function returns True if a valid version of DotNet is present for the GA to run. If not it returns false
            Function ValidDotNetVersionExists
                On Error Resume Next

                Const KeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"
                Const ValueName = "Install"

                Dim dotNetVersionExists, dwValue, eventType

                dotNetVersionExists = False
                dwValue = GetRegistryValue(g_Trace, KeyPath, ValueName, "REG_DWORD", False)


                If Not IsNull(dwValue) Then
                    Set oTraceEvent = g_Trace.CreateEvent("INFO")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ValidDotNetVersionExists"))
                        .setAttribute "dwValueReturned", dwValue
                    End With
                    g_Trace.TraceEvent oTraceEvent
                    dotNetVersionExists = True
                End If
                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ValidDotNetVersionExists"))
                    .setAttribute "ValidDotNetVersionExists", CStr(dotNetVersionExists)
                End With
                g_Trace.TraceEvent oTraceEvent
                ValidDotNetVersionExists = dotNetVersionExists
            End Function

            'This function Uninstalls the GuestAgent - Pass "ServiceOnly" if folders are to be preserved
            Sub UninstallGuestAgent(uninstallMode, kvpPrefix)
                On Error Resume Next

                Call InstrumentProcedure("UnregisterService", """RdAgent"", ""WaAppAgent.exe""", False, False, kvpPrefix & "0_UnregisterService-RdAgent", g_Trace)
                TraceError g_Trace, "Unregistering RdAgent service failed."

                Call InstrumentProcedure("UnregisterService", """WindowsAzureGuestAgent"", ""WindowsAzureGuestAgent.exe""", False, False, kvpPrefix & "1_UnregisterService-WindowsAzureGuestAgent", g_Trace)
                TraceError g_Trace, "Unregistering WindowsAzureGuestAgent service failed."

                Call InstrumentProcedure("UnregisterService", """WindowsAzureTelemetryService"", ""WindowsAzureTelemetryService.exe""", False, False, kvpPrefix & "2_UnregisterService-WindowsAzureTelemetryService", g_Trace)
                TraceError g_Trace, "Unregistering WindowsAzureTelemetryService service failed."

                Call InstrumentProcedure("StopEventTrace", "", False, False, kvpPrefix & "3_StopEventTrace", g_Trace)
                TraceError g_Trace, "Stopping trace for guestagent logs failed."

                Call InstrumentProcedure("DeleteEventTrace", "", False, False, kvpPrefix & "4_DeleteEventTrace", g_Trace)
                TraceError g_Trace, "Deleting trace for guestagent logs failed."

                If uninstallMode <> "ServiceOnly" Then

                    Call InstrumentProcedure("DeleteAzureFolders", "", False, False, kvpPrefix & "5_DeleteAzureFolders", g_Trace)
                    TraceError g_Trace, "Deleting azure folders failed."

                    Call InstrumentProcedure("DeleteAzureRegistryKeys", "", False, False, kvpPrefix & "6_DeleteAzureRegistryKeys", g_Trace)
                    TraceError g_Trace, "Deleting azure registry keys failed."

                End If
            End Sub

            ' This function Enables the service if disabled and changes its start mode as requested.
            Sub EnableService(serviceName, startMode)
                Dim configureServiceCommand, oResults

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("EnableService"))
                        .setAttribute "ServiceName", serviceName
                End With
                g_Trace.TraceEvent oTraceEvent

                configureServiceCommand = "%SystemRoot%\OEM\WaGuest.exe /configureservicestartmode " & QuoteString(serviceName) & " " & QuoteString(startMode) & " 1"
                Set oResults = ExecuteAndTraceWithResults(configureServiceCommand, g_Trace)
                If oResults.ExitCode <> 0 Then
                    Err.Raise vbObjectError + ERROR_ENABLESERVICEFAILED, "GuestAgent.wsf", "Failed to configure service start mode"
                    Exit Sub
                End If

            End Sub

            Sub StopProcessWait(processName)
                Dim stopProcessCommand, oResults

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopProcessWait"))
                        .setAttribute "ProcessName", processName
                End With
                g_Trace.TraceEvent oTraceEvent

                stopProcessCommand = "%SystemRoot%\OEM\WaGuest.exe /terminateprocess " & QuoteString(processName)
                Set oResults = ExecuteAndTraceWithResults(stopProcessCommand, g_Trace)

                If oResults.ExitCode <> 0 Then
                    Err.Raise vbObjectError + ERROR_ENABLESERVICEFAILED, "GuestAgent.wsf", "Failed to kill process"
                    Exit Sub
                End If
            End Sub

            ' This function checks if the service is installed.
             Function CheckServiceInstalled(serviceName)
                On Error Resume Next

                Dim verifyServiceInstalledCommand, serviceInstalledResult, verifyServiceInstalled
                verifyServiceInstalled = False

                verifyServiceInstalledCommand = "%SystemRoot%\OEM\WaGuest.exe /isserviceinstalled " & QuoteString(serviceName)
                Set oResults = ExecuteAndTraceWithResults(verifyServiceInstalledCommand, g_Trace)
                If oResults.ExitCode <> 0 Then
                    Err.Raise vbObjectError + ERROR_SERVICEINSTALLEDNOTVERIFIED, "GuestAgent.wsf", "Failed to verify if the service is installed"
                    Exit Function
                End If

                serviceInstalledResult = Trim(Replace(oResults.StdOut, vbCrLf, ""))
                If serviceInstalledResult = "true" Then
                    verifyServiceInstalled = True
                Else
                    verifyServiceInstalled = False
                End If
                CheckServiceInstalled = verifyServiceInstalled
            End Function

            ' This function Stops and wait for the service to stop. If the service is stopped or not there then its a no-op
            Sub StopServiceWait(serviceName, processName)
                Dim stopServiceCommand
                stopServiceCommand = "%SystemRoot%\OEM\WaGuest.exe /stopservice " & QuoteString(serviceName)
                Set oResults = ExecuteAndTraceWithResults(stopServiceCommand, g_Trace)
                call StopProcessWait(processName)
                TraceError g_Trace, "Stopping process: " + processName + " failed."
            End Sub

            ' This function unregisters a service.
            Sub UnregisterService(serviceName, processName)
                On Error Resume Next

                Dim unregisterServiceCommand
                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("UnregisterService"))
                    .setAttribute "ServiceName", serviceName
                End With
                g_Trace.TraceEvent oTraceEvent

                unregisterServiceCommand = "%SystemRoot%\OEM\WaGuest.exe /unregisterservice " & QuoteString(serviceName)
                Set oResults = ExecuteAndTraceWithResults(unregisterServiceCommand, g_Trace)
                If oResults.ExitCode <> 0 Then
                    Err.Raise vbObjectError + ERROR_SERVICEINSTALLEDNOTVERIFIED, "GuestAgent.wsf", "Failed to unregister the service"
                    Exit Sub
                End If

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("UnregisterService"))
                g_Trace.TraceEvent oTraceEvent

            End Sub

            ' This function stops traces for GA logging
            Sub StopEventTrace
                On Error Resume Next

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopEventTrace"))
                    .setAttribute "StopGAEvents", "True"
                End With
                g_Trace.TraceEvent oTraceEvent
                ExecuteAndTraceWithResults "%SystemRoot%\System32\logman.exe stop GAEvents", g_trace

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopEventTrace"))
                    .setAttribute "StopRTEvents", "True"
                End With
                g_Trace.TraceEvent oTraceEvent
                ExecuteAndTraceWithResults "%SystemRoot%\System32\logman.exe stop RTEvents", g_trace

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopEventTrace"))
                    .setAttribute "StopMetricEvents", "True"
                End With
                g_Trace.TraceEvent oTraceEvent
                ExecuteAndTraceWithResults "%SystemRoot%\System32\logman.exe -ets stop WindowsAzure-GuestAgent-Metrics", g_trace

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("StopEventTrace"))
                    .setAttribute "StopDiagnosticsEvents", "True"
                End With
                g_Trace.TraceEvent oTraceEvent
                ExecuteAndTraceWithResults "%SystemRoot%\System32\logman.exe -ets stop WindowsAzure-GuestAgent-Diagnostic", g_trace

            End Sub

            ' This function deletes traces for GA logging
            Sub DeleteEventTrace
                On Error Resume Next

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("DeleteEventTrace"))
                    .setAttribute "DeleteGAEvents", "True"
                End With
                g_Trace.TraceEvent oTraceEvent
                ExecuteAndTraceWithResults "%SystemRoot%\System32\logman.exe delete GAEvents", g_trace

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("DeleteEventTrace"))
                    .setAttribute "DeleteRTEvents", "True"
                End With
                g_Trace.TraceEvent oTraceEvent
                ExecuteAndTraceWithResults "%SystemRoot%\System32\logman.exe delete RTEvents", g_trace
            End Sub

            ' This function deletes all the Azure specific folders on the filesystem.
            Sub DeleteAzureFolders
                On Error Resume Next

                Dim gaPath, pluginsPath
                Dim fso
                Set fso = CreateObject("Scripting.FileSystemObject")
                gaPath = fso.BuildPath(WshShell.ExpandEnvironmentStrings("%SYSTEMDRIVE%"), "\WindowsAzure")
                pluginsPath = fso.BuildPath(WshShell.ExpandEnvironmentStrings("%SYSTEMDRIVE%"), "\Packages")
                call DeleteFolder(gaPath)
                call DeleteFolder(pluginsPath)
            End Sub

            ' This function deletes the folder specified in the path parameter.
            Sub DeleteFolder(path)
                On Error Resume Next

                Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")

                fso.DeleteFolder path, True
                If Err.number <> 0 And Err.number <> 76 Then
                    ' 76 - Path not found is not an issue when deleting
                    Set oTraceEvent = g_Trace.CreateEvent("WARNING")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("DeleteFolder"))
                        .setAttribute "Path", gaPath
                        .setAttribute "Error", Err.number
                        .setAttribute "Description", Err.Description
                    End With
                    g_Trace.TraceEvent oTraceEvent
                Else
                    Err.number = 0
                End If
            End Sub

            Sub DeleteAzureRegistryKeys
                On Error Resume Next

                const HKEY_LOCAL_MACHINE = &H80000002
                const strComputer = "."
                const strAzureKeyPath = "SOFTWARE\Microsoft\Windows Azure"
                const strGAKeyPath = "SOFTWARE\Microsoft\GuestAgent"

                Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")

                errReturnCode = objReg.DeleteKey(HKEY_LOCAL_MACHINE, strAzureKeyPath)
                If errReturnCode = 0 And Err.Number = 0 Then
                    eventType = "INFO"
                Else
                    eventType = "ERROR"
                End If

                Set oTraceEvent = g_Trace.CreateEvent(eventType)
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("DeleteAzureRegistryKeys"))
                    .setAttribute "AzureKeyPath", strAzureKeyPath
                    .setAttribute "DeleteKey", errReturnCode
                End With
                g_Trace.TraceEvent oTraceEvent

                errReturnCode = objReg.DeleteKey(HKEY_LOCAL_MACHINE, strGAKeyPath)
                If errReturnCode = 0 And Err.Number = 0 Then
                    eventType = "INFO"
                Else
                    eventType = "ERROR"
                End If

                Set oTraceEvent = g_Trace.CreateEvent(eventType)
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("DeleteAzureRegistryKeys"))
                    .setAttribute "GAKeyPath", strGAKeyPath
                    .setAttribute "DeleteKey", errReturnCode
                End With
                g_Trace.TraceEvent oTraceEvent

            End Sub

            ' This function verifies the OS requirements for installing GuestAgent.
             Function VerifyOsRequirements
                On Error Resume Next

                Dim majorVersion : majorVersion = GetOSCurrentMajorVersionNumber
                Dim minorVersion : minorVersion = GetOSCurrentMinorVersionNumber
                If TraceError(g_Trace, "VerifyOsRequirements: Failed to read the major and minor versions - will inject GuestAgent anyway") <> 0 Then
                    VerifyOsRequirements = True
                    Exit Function
                End If

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("VerifyOsRequirements"))
                    .setAttribute "OsMajorVersion", majorVersion
                    .setAttribute "OsMinorVersion", minorVersion
                End With
                g_Trace.TraceEvent oTraceEvent
                
                VerifyOsRequirements = ((majorVersion > 6) Or (majorVersion = 6 And minorVersion > 0)) 
            End Function

            ' This function returns the w.x.y.z version components of the parameterized version string as a four-element array
            ' raising an error if the parameterized version string cannot be parsed into its version components.
            ' If the parameterized version string has fewer than four components, 0 will be returned for the missing components' values
            Private Function GetVersionComponents(versionStr)
                Const ERROR_EMPTY_VERSION_STRING = 13

                Dim components
                Dim w, x, y, z
                w = 0
                x = 0
                y = 0
                z = 0

                components = Split(versionStr, ".") ' Split raises an error if versionString is Null, returns empty array if versionStr is ""

                If UBound(components) < 0 Then
                    Err.Raise vbObjectError + ERROR_EMPTY_VERSION_STRING, "GuestAgent.wsf", "GetVersionComponents: The parameterized version string is empty"
                End If
                If UBound(components) >= 0 Then
                    w = CLng(components(0))
                End If
                If UBound(components) >= 1 Then
                    x = CLng(components(1))
                End If
                If UBound(components) >= 2 Then
                    y = CLng(components(2))
                End If
                If UBound(components) >= 3 Then
                    z = CLng(components(3))
                End If

                GetVersionComponents = Array(w, x, y, z)
            End Function

            ' Unzips the GuestAgent package and returns the path to the directory in which it was extracted to
            Sub UnzipGuestAgentPackage
                On Error Resume Next
                Dim objGAZipLocation
                Dim extractToPath, zipPath, scriptDir
                Dim fso
                Dim appendDirName

                Const FOF_SILENT = &H4&
                Const FOF_NOCONFIRMATION = &H10&
                Const FOF_NOERRORUI = &H400&

                Set fso = CreateObject("Scripting.FileSystemObject")
                scriptDir = fso.GetParentFolderName(Me.WScript.ScriptFullName)
                zipPath = fso.BuildPath(scriptDir, "GuestAgent\")
                zipPath = fso.BuildPath(zipPath, oGAPackageName)
                appendDirName = ""

                extractToPath = fso.BuildPath(WshShell.ExpandEnvironmentStrings("%SYSTEMDRIVE%"), "\WindowsAzure\")

                'If the WindowsAzure folder does not exist create it.
                If Not fso.FolderExists(extractToPath) Then
                    fso.CreateFolder(extractToPath)
                    If Err.number <> 0 Then
                        Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("UnzipGuestAgentPackage"))
                            .setAttribute "WindowsAzureCreateFolderFailed", Err.number
                            .setAttribute "Description", Err.Description
                        End With
                        g_Trace.TraceEvent oTraceEvent
                        Exit Sub
                    End If
                Else
                    Set oTraceEvent = g_Trace.CreateEvent("WARN")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("UnzipGuestAgentPackage"))
                        .setAttribute "WindowsAzureFolderExists", CStr(True)
                    End With
                    g_Trace.TraceEvent oTraceEvent
                End If

                If oServiceAlreadyInstalled = True Then
                    ' If service already there then create a new unique folder with date stamp
                    Dim myTime
                    myTime = Now
                    appendDirName = "_" & Year(myTime) & Month(myTime) & Day(myTime) & "_" & Hour(myTime) & Minute(myTime) & Second(myTime)
                End If

                extractToPath = fso.BuildPath(extractToPath, "Packages" & appendDirName & "\")
                oExtractedAgentLocation = extractToPath

                'If the Packages folder does not exist create it.
                If Not fso.FolderExists(extractToPath) Then
                    fso.CreateFolder(extractToPath)
                    If Err.number <> 0 Then
                        Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("UnzipGuestAgentPackage"))
                            .setAttribute "WindowsAzurePackagesCreateFolderFailed", Err.number
                            .setAttribute "Description", Err.Description
                        End With
                        g_Trace.TraceEvent oTraceEvent
                        Exit Sub
                    End If
                Else
                    Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("UnzipGuestAgentPackage"))
                        .setAttribute "WindowsAzurePackagesFolderExists", CStr(True)
                    End With
                    g_Trace.TraceEvent oTraceEvent
                End If

                Dim extractorExePath, extractorExeCmdString
                extractorExePath = fso.BuildPath(scriptDir, "VmAgentPackageExtractor\")
                extractorExeCmdString = extractorExePath & "PackageExtractor.exe """ & zipPath & " "" """ & extractToPath & " """
                ExecuteAndTraceWithResults extractorExeCmdString, g_Trace

                If TraceError(g_Trace, "UnzipGuestAgentPackage: Failed to unzip VMAgent package") = 0 Then
                    Set oTraceEvent = g_Trace.CreateEvent("INFO")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("UnzipGuestAgentPackage"))
                        .setAttribute "ZipLocation", zipPath
                        .setAttribute "ExtractionLocation", extractToPath
                    End With
                    g_Trace.TraceEvent oTraceEvent
                End If
            End Sub

            ' This procedure registers the transparent installer service (RdAgent / WaAppAgent.exe)
            Sub ConfigureRdAgentService(offlineMode)
                On Error Resume Next
                Dim objWMIService, objService, servicePath, startMode
                Dim errReturnCode   ' only used (logged) when RdAgent service doesn't exist and must be created
                Dim fso

                Const OWN_PROCESS = 16
                Const NOT_INTERACTIVE = False
                Const NORMAL_ERROR_CONTROL = 1

                Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
                Set objService = objWMIService.Get("Win32_BaseService")
                Set fso = CreateObject("Scripting.FileSystemObject")
                servicePath = fso.BuildPath(oExtractedAgentLocation, "\WaAppAgent.exe")

                If CBool(offlineMode) = True Then
                    ' In offline mode, we don't want the service starting on next boot
                    ' We set its start mode to disabled with the expectation that a
                    ' subsequent provisioning pass will enable the service
                    startMode = "Disabled"
                Else
                    startMode = "Automatic"
                End If

                If oServiceAlreadyInstalled = False Then
                    ' if the service is not installed, then the correct version to use is the HOST's version
                    oGuestAgentBinaryLocation = oExtractedAgentLocation
                    ' Create service
                    errReturnCode = objService.Create("RdAgent", "RdAgent", servicePath, OWN_PROCESS, NORMAL_ERROR_CONTROL, startMode, _
                                                       NOT_INTERACTIVE, NULL, NULL )
                    Set oTraceEvent = g_Trace.CreateEvent("INFO")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ConfigureRdAgentService"))
                            .setAttribute "CreateService", errReturnCode
                            .setAttribute "StartMode", startmode
                    End With
                    g_Trace.TraceEvent oTraceEvent
                Else
                    ' if the version to install is not newer than the existing version, leave the existing version installed but re-configure it just-in-case something has been changed
                    Dim existingServicePath, existingServiceVersionStr, serviceVersionStr, existingServiceVersionComponents, serviceVersionComponents

                    existingServicePath = fso.BuildPath(oOldGuestAgentBinLocation, "\WaAppAgent.exe")
                    existingServiceVersionStr = fso.GetFileVersion(existingServicePath)
                    serviceVersionStr = fso.GetFileVersion(servicePath)
                    existingServiceVersionComponents = GetVersionComponents(existingServiceVersionStr)
                    serviceVersionComponents = GetVersionComponents(serviceVersionStr)

                    ' the y component is the branch ID and can be safely ignored
                    ' serviceVersionComponents(2)   <= existingServiceVersionComponents(2) And _

                    If (serviceVersionComponents(0) <= existingServiceVersionComponents(0) And _
                        serviceVersionComponents(1) <= existingServiceVersionComponents(1) And _
                        serviceVersionComponents(3) <= existingServiceVersionComponents(3)) Then    ' z increases with every new version where x (minor) remains the same

                        oGuestAgentBinaryLocation = fso.GetParentFolderName(existingServicePath)
                        oOldGuestAgentBinLocation = fso.GetFolder(oExtractedAgentLocation).Path     ' set to extracted location for clean-up, post-configuration
                    Else
                        oGuestAgentBinaryLocation = fso.GetParentFolderName(servicePath)
                    End If

                    ' Change service settings with resolved path
                    servicePath = fso.BuildPath(oGuestAgentBinaryLocation, "\WaAppAgent.exe")
                    call SetServicePathInRegistry("RdAgent", servicePath)
                    If TraceError(g_Trace, "Setting the RdAgent service path in registry failed.") <> 0 Then
                        Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ConfigureRdAgentService"))
                            .setAttribute "Failed to update RdAgent path", Err.number
                        End With
                        g_Trace.TraceEvent oTraceEvent

                        Exit Sub
                    End If

                    servicePath = fso.BuildPath(oGuestAgentBinaryLocation, "\Telemetry\WindowsAzureTelemetryService.exe")
                    call SetServicePathInRegistry("WindowsAzureTelemetryService", servicePath)
                    If TraceError(g_Trace, "Setting the WindowsAzureTelemetryService service path in registry failed.") <> 0 Then
                        Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ConfigureRdAgentService"))
                            .setAttribute "Failed to update WindowsAzureTelemetryService path", Err.number
                        End With
                        g_Trace.TraceEvent oTraceEvent

                        Exit Sub
                    End If

                    servicePath = fso.BuildPath(oGuestAgentBinaryLocation, "\GuestAgent\WindowsAzureGuestAgent.exe")
                    ' There are two versions of GuestAgent. The newer version removes the GuestAgent folder and thus we need to double check here
                    ' TODO: We should evaluate the possibility to remove the setting as now the newer version RdAgent does set the path and they 
                    ' have the best knowledge where the GuestAgent should be.
                    If Not fso.FileExists(servicePath) Then
                        servicePath = fso.BuildPath(oGuestAgentBinaryLocation, "\WindowsAzureGuestAgent.exe")
                    End If
                    call SetServicePathInRegistry("WindowsAzureGuestAgent", servicePath)
                    If TraceError(g_Trace, "Setting the WindowsAzureGuestAgent service path in registry failed.") <> 0 Then
                        Set oTraceEvent = g_Trace.CreateEvent("ERROR")
                        With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ConfigureRdAgentService"))
                            .setAttribute "Failed to update WindowsAzureGuestAgent path", Err.number
                        End With
                        g_Trace.TraceEvent oTraceEvent

                        Exit Sub
                    End If

                    Set oTraceEvent = g_Trace.CreateEvent("INFO")
                    With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("ConfigureRdAgentService"))
                            .setAttribute "GuestAgentBinariesLocation", oGuestAgentBinaryLocation
                    End With
                    g_Trace.TraceEvent oTraceEvent
                End If
            End Sub

            ' Start the installer service
            Sub StartRdAgentService
                On Error Resume Next
                Dim startServiceCommand
                startServiceCommand = "%SystemRoot%\OEM\WaGuest.exe /startservice RdAgent"
                Set oResults = ExecuteAndTraceWithResults(startServiceCommand, g_Trace)
                If oResults.ExitCode <> 0 Then
                    Err.Raise vbObjectError + ERROR_STARTSERVICE, "GuestAgent.wsf", "Failed to start service"
                    Exit Sub
                End If
            End Sub

            ' Set VMType information in registry for GA to use at runtime
            Sub SetVmTypeInRegistry
                On Error Resume Next

                const HKEY_LOCAL_MACHINE = &H80000002
                const strComputer = "."
                const strKeyPath = "SOFTWARE\Microsoft\Windows Azure"
                Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
                objReg.CreateKey HKEY_LOCAL_MACHINE, strKeyPath

                strValueName = "VMType"
                strTypeValue = "IAAS"
                objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strTypeValue

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("SetVmTypeInRegistry"))
                    .setAttribute strValueName, strTypeValue
                End With
                g_Trace.TraceEvent oTraceEvent

            End Sub

            ' Set the service registry path
            Sub SetServicePathInRegistry (serviceName, servicePath)
                On Error Resume Next

                Dim strKeyPath

                const HKEY_LOCAL_MACHINE = &H80000002
                const strComputer = "."
                strKeyPath = "SYSTEM\CurrentControlSet\Services\" & serviceName
                Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
                objReg.CreateKey HKEY_LOCAL_MACHINE, strKeyPath
                objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, "ImagePath", servicePath

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("SetRdAgentServicePathInRegistry"))
                    .setAttribute "ServiceName", serviceName
                    .setAttribute "ServiceImagePath", servicePath
                End With
                g_Trace.TraceEvent oTraceEvent
            End Sub

            ' Set the incarnation in registry for GA to use at runtime
            Sub SetGAParamsInRegistry(offlineMode)
                On Error Resume Next

                Dim servicePath, strFileVer, strProvisioningTime

                Set objFSO = CreateObject("Scripting.FileSystemObject")
                servicePath = objFSO.BuildPath(oGuestAgentBinaryLocation, "\TransparentInstaller.dll")
                strFileVer = objFSO.GetFileVersion(servicePath)

                strProvisioningTime = FormatDateTime(Now)

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("SetGAParamsInRegistry"))
                    .setAttribute "BasePath", oGuestAgentBinaryLocation
                    .setAttribute "ServicePath", servicePath
                    .setAttribute "FileVersion", strFileVer
                End With
                g_Trace.TraceEvent oTraceEvent

                const HKEY_LOCAL_MACHINE = &H80000002
                const strComputer = "."
                const strKeyPath = "SOFTWARE\Microsoft\GuestAgent"
                Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
                objReg.CreateKey HKEY_LOCAL_MACHINE, strKeyPath
                objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, "Incarnation", strFileVer
                If offlineMode = False Then
                    objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, "VmProvisionedAt", strProvisioningTime
                End If
                objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, "ManifestTimeStamp", ""

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("SetGAParamsInRegistry"))
                    .setAttribute "Incarnation", strFileVer
                    If offlineMode = False Then
                        .setAttribute "VmProvisionedAt", strProvisioningTime
                    End If
                    .setAttribute "ManifestTimeStamp", ""
                End With
                g_Trace.TraceEvent oTraceEvent
            End Sub

            ' Set the provisioning time in registry for GA to use at runtime
            Sub SetGAParamsInRegistryOfflined
                On Error Resume Next

                Dim strProvisioningTime : strProvisioningTime = FormatDateTime(Now)

                const HKEY_LOCAL_MACHINE = &H80000002
                const strComputer = "."
                const strKeyPath = "SOFTWARE\Microsoft\GuestAgent"
                Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
                objReg.CreateKey HKEY_LOCAL_MACHINE, strKeyPath
                objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, "VmProvisionedAt", strProvisioningTime

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("SetGAParamsInRegistryOfflined"))
                    .setAttribute "VmProvisionedAt", strProvisioningTime
                End With
                g_Trace.TraceEvent oTraceEvent
            End Sub

            ' Get service install location the incarnation in registry for GA to use at runtime
            Function GetServiceInstallLocation(serviceName)
                On Error Resume Next

                Dim strKeyPath, servicePath

                const HKEY_LOCAL_MACHINE = &H80000002
                const strComputer = "."
                strKeyPath = "SYSTEM\CurrentControlSet\Services\" & serviceName
                Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")

                objReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath, "ImagePath", servicePath

                Set oTraceEvent = g_Trace.CreateEvent("INFO")
                With oTraceEvent.appendChild(oTraceEvent.ownerDocument.createElement("GetServiceInstallLocation"))
                    .setAttribute "ServiceName", serviceName
                    .setAttribute "ServiceImagePath", servicePath
                End With
                g_Trace.TraceEvent oTraceEvent

                Set fso = CreateObject("Scripting.FileSystemObject")

                GetServiceInstallLocation = fso.GetParentFolderName(servicePath)

            End Function

        </script>
    </component>
</package>