TraceProvider.psm1
function Trace-CmdletUpdateAksHci { <# .DESCRIPTION Emit's trace/logs by calling into the TraceProvider api .PARAMETER CmdletName CmdletName information to identify user invoked cmdlet e.g. "Install-AksHci" .PARAMETER ConfigDetails To capture DeploymentId, Audience, Catalog, AksHciVersion, ModuleName, Offer and ArmId information .PARAMETER AksHciInitialVersion To capture value of AksHciVersion at the start of Update .PARAMETER UpgradePath To capture the list of all the versions to be updated to .PARAMETER AksHciTargetVersion To capture the target/final AksHciVersion .PARAMETER AksHciCurrentVersion To capture the current AksHciVersion .PARAMETER IsSuccess Flag to detect pass/failure .PARAMETER ErrorMessage Details/ErrorMessage around the failure; probably error message or any other info useful for debugging .PARAMETER StartCmdletTime StartTime of the command in Ms (Millisecond) #> [CmdletBinding()] Param( [string] $ConfigDetails, [string] $CmdletName, [bool] $IsSuccess = $false, [Object] $ErrorMessage = @(), [DateTime] $StartCmdletTime, [string] $AksHciInitialVersion, [Object] $UpgradePath = @(), [string] $AksHciTargetVersion, [string] $AksHciCurrentVersion, [bool] $IsUpdateAksHciStarted = $false, #Flag for Start of Update [string] $UpdateAksHciCorrelationId, [bool] $IsStepUpdateAksHciStarted = $false, #Flag for Start of Step Update [string] $StepUpdateAksHciCorrelationId, [bool] $IsStepUpdateAksHciComplete = $false #Flag for End/Complete of Step Update ) $DurationMs ="" if($null -ne $StartCmdletTime) { $EndCmdletTime = Get-Date $DurationMs = [Math]::Round(($EndCmdletTime - $StartCmdletTime).TotalMilliseconds) } $encoding = [system.Text.Encoding]::UTF8 $callstack = Get-PSCallStack if($null -ne $callstack[1]) { $CmdletName = $callstack[1].Command $ScriptPath = $callstack[1].ScriptName } $ErrorWithStackTrace = "" if($null -ne $ErrorMessage) { if($null -ne $($ErrorMessage.ScriptStackTrace)) { $ErrorWithStackTrace = $($ErrorMessage.ScriptStackTrace) } } #Capture Exception and InnerException from ErrorMessage. $ExceptionMessage = "" $InnerErrorException = "" [bool] $IsUserErrorFlag = $false [bool] $IsInfraErrorFlag = $false [bool] $IsErrorFlag = $false if ($null -ne ($($ErrorMessage.Exception))) { $ExceptionMessage = $($ErrorMessage.Exception) if ($null -ne ($($ErrorMessage.Exception.InnerException))) { $InnerErrorException = $($ErrorMessage.Exception.InnerException.Message) } if ($null -ne ($($ErrorMessage.Exception.errorflag))) { $errorflagEnumValue = $ErrorMessage.Exception.errorflag $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag = CheckErrorType -errorflagEnumValue $errorflagEnumValue } } $AttemptedUpgradePath = "" if ($null -ne $UpgradePath) { #Convert it to string $AttemptedUpgradePath = "$UpgradePath" #Comma separated values $AttemptedUpgradePath = $AttemptedUpgradePath.Replace(" ", ", ") } $ConfigDetailsBytes = $encoding.GetBytes($ConfigDetails) $CmdletNameBytes = $encoding.GetBytes($CmdletName) $ErrorMessageBytes = $encoding.GetBytes($ErrorMessage) $ExceptionMessageBytes = $encoding.GetBytes($ExceptionMessage) $InnerErrorExceptionBytes = $encoding.GetBytes($InnerErrorException) $ErrorWithStackTraceBytes = $encoding.GetBytes($ErrorWithStackTrace) $ScriptPathBytes = $encoding.GetBytes($ScriptPath) $AksHciInitialVersionBytes = $encoding.GetBytes($AksHciInitialVersion) $AttemptedUpgradePathBytes = $encoding.GetBytes($AttemptedUpgradePath) $AksHciTargetVersionBytes = $encoding.GetBytes($AksHciTargetVersion) $AksHciCurrentVersionBytes = $encoding.GetBytes($AksHciCurrentVersion) $ParentCorrelationIdBytes = $encoding.GetBytes($UpdateAksHciCorrelationId) $CorrelationIdBytes = $encoding.GetBytes($StepUpdateAksHciCorrelationId) $DurationMsBytes = $encoding.GetBytes($DurationMs) [TraceCmdlet.API]::TraceCmdletForUpdate($ConfigDetailsBytes, $CmdletNameBytes, $ScriptPathBytes, $DurationMsBytes, $IsSuccess, $AksHciInitialVersionBytes, $AttemptedUpgradePathBytes, $AksHciTargetVersionBytes, $AksHciCurrentVersionBytes, $IsUpdateAksHciStarted, $ParentCorrelationIdBytes, $IsStepUpdateAksHciStarted, $CorrelationIdBytes, $IsStepUpdateAksHciComplete, $ErrorMessageBytes, $ExceptionMessageBytes, $InnerErrorExceptionBytes, $ErrorWithStackTraceBytes, $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag) # Temporary call, see notes in function description Repair-Console } function Trace-Cmdlet { <# .DESCRIPTION Emit's trace/logs by calling into the TraceProvider api .PARAMETER ConfigDetails To capture DeploymentId, Audience, Catalog, AksHciVersion, ModuleName, Offer and ArmId information .PARAMETER CmdletName CmdletName information to identify user invoked cmdlet e.g. "Install-AksHci" .PARAMETER CmdletParameters Get additional information i.e. relevant/useful parameter information from the cmdlet .PARAMETER ChildStageName To identify which part of the Cmdlet failed eg. for CmdletName "Uninstall-AksHci", child StageName is "RemoveCluster" .PARAMETER IsSuccess Flag to detect pass/failure .PARAMETER ErrorMessage Details/ErrorMessage around the failure; probably error message or any other info useful for debugging .PARAMETER StartCmdletTime StartTime of the command in Ms (Millisecond) #> [CmdletBinding()] Param( [string] $ConfigDetails, [string] $CmdletName, [Object] $CmdletParameters = @(), [string] $ChildStageName, [bool] $IsSuccess = $true, [Object] $ErrorMessage = @(), [DateTime] $StartCmdletTime, [string] $ScriptPath, [string] $AksHciTargetVersion ) $DurationMs ="" if($null -ne $StartCmdletTime) { $EndCmdletTime = Get-Date $DurationMs = [Math]::Round(($EndCmdletTime - $StartCmdletTime).TotalMilliseconds) } $encoding = [system.Text.Encoding]::UTF8 $callstack = Get-PSCallStack if($null -ne $callstack[1]) { $CmdletName = $callstack[1].Command $ScriptPath = $callstack[1].ScriptName } $CmdletParameters = $CmdletParameters |ConvertTo-Json # Need this check, when no CmdletParameters are passed if([String]::IsNullOrWhiteSpace($CmdletParameters)) { $CmdletParameters = "" } # For Success TraceCmdlet, Exception & StackTrace is empty $ExceptionMessage = "" $InnerErrorException = "" $ErrorWithStackTrace = "" [bool] $IsUserErrorFlag = $false [bool] $IsInfraErrorFlag = $false [bool] $IsErrorFlag = $false $ConfigDetailsBytes = $encoding.GetBytes($ConfigDetails) $CmdletNameBytes = $encoding.GetBytes($CmdletName) $CmdletParametersBytes = $encoding.GetBytes($CmdletParameters) $ChildStageNameBytes = $encoding.GetBytes($ChildStageName) $ErrorMessageBytes = $encoding.GetBytes($ErrorMessage) $ExceptionMessageBytes = $encoding.GetBytes($ExceptionMessage) $InnerErrorExceptionBytes = $encoding.GetBytes($InnerErrorException) $ErrorWithStackTraceBytes = $encoding.GetBytes($ErrorWithStackTrace) $DurationMsBytes = $encoding.GetBytes($DurationMs) $ScriptPathBytes = $encoding.GetBytes($ScriptPath) $AksHciTargetVersionBytes = $encoding.GetBytes($AksHciTargetVersion) [TraceCmdlet.API]::TraceCmdlet($ConfigDetailsBytes, $CmdletNameBytes, $CmdletParametersBytes, $ChildStageNameBytes, $IsSuccess, $ScriptPathBytes, $ErrorMessageBytes, $ExceptionMessageBytes, $InnerErrorExceptionBytes, $ErrorWithStackTraceBytes, $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag, $DurationMsBytes, $AksHciTargetVersionBytes) # Temporary call, see notes in function description Repair-Console } function Trace-CmdletError { <# .DESCRIPTION Emit's trace/logs by calling into the TraceProvider api .PARAMETER CmdletName CmdletName information to identify user invoked cmdlet e.g. "Install-AksHci" .PARAMETER ConfigDetails To capture DeploymentId, Audience, Catalog, AksHciVersion, ModuleName, Offer and ArmId information .PARAMETER ChildStageName To identify which part of the Cmdlet failed eg. for CmdletName "Uninstall-AksHci", child StageName is "RemoveCluster" .PARAMETER CmdletParameters Get additional information i.e. relevant/useful parameter information from the cmdlet .PARAMETER IsSuccess Flag to detect pass/failure .PARAMETER ErrorMessage Details/ErrorMessage around the failure; probably error message or any other info useful for debugging .PARAMETER StartCmdletTime StartTime of the command in Ms (Millisecond) #> [CmdletBinding()] Param( [string] $CmdletName, [string] $ScriptPath, [string] $ConfigDetails, [string] $ChildStageName, [Object] $CmdletParameters = @(), [bool] $IsSuccess = $false, [Object] $ErrorMessage = @(), [DateTime] $StartCmdletTime, [string] $AksHciTargetVersion ) $DurationMs ="" if($null -ne $StartCmdletTime) { $EndCmdletTime = Get-Date $DurationMs = [Math]::Round(($EndCmdletTime - $StartCmdletTime).TotalMilliseconds) } $encoding = [system.Text.Encoding]::UTF8 $callstack = Get-PSCallStack if($null -ne $callstack[1]) { $CmdletName = $callstack[1].Command $ScriptPath = $callstack[1].ScriptName } $ErrorWithStackTrace = "" if($null -ne $ErrorMessage) { $ErrorWithStackTrace = $($ErrorMessage.ScriptStackTrace) } #Capture Exception and InnerException from ErrorMessage. $ExceptionMessage = "" $InnerErrorException = "" [bool] $IsUserErrorFlag = $false [bool] $IsInfraErrorFlag = $false [bool] $IsErrorFlag = $false if ($null -ne ($($ErrorMessage.Exception))) { $ExceptionMessage = $($ErrorMessage.Exception) if ($null -ne ($($ErrorMessage.Exception.InnerException))) { $InnerErrorException = $($ErrorMessage.Exception.InnerException.Message) } if ($null -ne ($($ErrorMessage.Exception.errorflag))) { $errorflagEnumValue = $ErrorMessage.Exception.errorflag $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag = CheckErrorType -errorflagEnumValue $errorflagEnumValue } } $CmdletParameters = $CmdletParameters |ConvertTo-Json # Need this check, when no CmdletParameters are passed if([String]::IsNullOrWhiteSpace($CmdletParameters)) { $CmdletParameters = "" } $ConfigDetailsBytes = $encoding.GetBytes($ConfigDetails) $CmdletNameBytes = $encoding.GetBytes($CmdletName) $CmdletParametersBytes = $encoding.GetBytes($CmdletParameters) $ChildStageNameBytes = $encoding.GetBytes($ChildStageName) $ErrorMessageBytes = $encoding.GetBytes($ErrorMessage) $ExceptionMessageBytes = $encoding.GetBytes($ExceptionMessage) $InnerErrorExceptionBytes = $encoding.GetBytes($InnerErrorException) $ErrorWithStackTraceBytes = $encoding.GetBytes($ErrorWithStackTrace) $DurationMsBytes = $encoding.GetBytes($DurationMs) $ScriptPathBytes = $encoding.GetBytes($ScriptPath) $AksHciTargetVersionBytes = $encoding.GetBytes($AksHciTargetVersion) [TraceCmdlet.API]::TraceCmdlet($ConfigDetailsBytes, $CmdletNameBytes, $CmdletParametersBytes, $ChildStageNameBytes, $IsSuccess, $ScriptPathBytes, $ErrorMessageBytes, $ExceptionMessageBytes, $InnerErrorExceptionBytes, $ErrorWithStackTraceBytes, $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag, $DurationMsBytes, $AksHciTargetVersionBytes) # Temporary call, see notes in function description Repair-Console } function Initialize-TraceCmdlet { <# .DESCRIPTION Initialize the TraceCmdlet types (once per session). #> try { [TraceCmdlet.API] | Out-Null } catch { $path = $($MyInvocation.PSScriptRoot) -replace [RegEx]::Escape("\"), "\\" $signature = @" [DllImport("$path\\TraceProvider.dll")] public static extern void TraceCmdlet([In] byte[] ConfigDetails, [In] byte[] CmdletName, [In] byte[] CmdletParameters, [In] byte[] ChildStageName, [In] bool IsSuccess, [In] byte[] ScriptPath, [In] byte[] ErrorMessage, [In] byte[] Exception, [In] byte[] InnerErrorException, [In] byte[] ErrorStackTrace, [In] bool IsUserError, [In] bool IsInfraError, [In] bool IsError, [In] byte[] DurationMs, [In] byte[] AksHciTargetVersion); [DllImport("$path\\TraceProvider.dll")] public static extern void TraceCmdletForUpdate([In] byte[] ConfigDetailsBytes, [In] byte[] CmdletNameBytes, [In] byte[] ScriptPathBytes, [In] byte[] DurationMsBytes, [In] bool IsSuccess, [In] byte[] AksHciInitialVersionBytes, [In] byte[] AttemptedUpgradePathBytes, [In] byte[] AksHciTargetVersionBytes, [In] byte[] AksHciCurrentVersionBytes, [In] bool IsUpdateAksHciStarted, [In] byte[] UpdateAksHciCorrelationId, [In] bool IsStepUpdateAksHciStarted, [In] byte[] StepUpdateAksHciCorrelationId, [In] bool IsStepUpdateAksHciComplete, [In] byte[] ErrorMessageBytes, [In] byte[] ExceptionMessageBytes, [In] byte[] InnerErrorExceptionBytes, [In] byte[] ErrorWithStackTraceBytes, [In] bool IsUserError, [In] bool IsInfraError, [In] bool IsError); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool SetHandleInformation(IntPtr hObject, uint dwMask, uint dwFlags); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetStdHandle(int nStdHandle); "@ Add-Type -MemberDefinition $signature -Name API -Namespace TraceCmdlet } } function Repair-Console { <# .DESCRIPTION Repairs console stdin/stdout/stderr after a TraceCmdlet API call. This is a known golang c-shared bug which is being fixed in Go: https://github.com/golang/go/issues/44876 #> try { [TraceCmdlet.API]::SetHandleInformation([TraceCmdlet.API]::GetStdHandle(-10), 1, 1) | Out-Null [TraceCmdlet.API]::SetHandleInformation([TraceCmdlet.API]::GetStdHandle(-11), 1, 1) | Out-Null [TraceCmdlet.API]::SetHandleInformation([TraceCmdlet.API]::GetStdHandle(-12), 1, 1) | Out-Null } catch {} } function Convert-ParametersToString { <# .DESCRIPTION Takes a dictionary of parameters and converts them to a string representation. .PARAMETER argDictionary Dictionary of arguments (e.g. obtained from $PSBoundParameters). #> param ( [Object] $argDictionary ) $strArgs = "" foreach ($key in $argDictionary.Keys) { $seperator = " " $val = $argDictionary[$key] if (($val -eq $true) -or ($val -eq $false)) { $seperator = ":$" } $strArgs += " -$key$seperator$val" } return $strArgs } function CheckErrorType { <# .DESCRIPTION Function to check the error type e.g. IsUser, IsInfra, IsError #> param ( [int] $errorflagEnumValue ) [bool] $IsUserErrorFlag = $false [bool] $IsInfraErrorFlag = $false [bool] $IsErrorFlag = $false $telemetryFlagVal = $ErrorMessage.Exception.errorflag if ($telemetryFlagVal -eq "IsUserErrorFlag") { $IsUserErrorFlag = $true return $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag } if ($telemetryFlagVal -eq "IsInfraErrorFlag") { $IsInfraErrorFlag = $true return $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag } if ($telemetryFlagVal -eq "IsErrorFlag") { $IsErrorFlag = $true return $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag } return $IsUserErrorFlag, $IsInfraErrorFlag, $IsErrorFlag } Initialize-TraceCmdlet # SIG # Begin signature block # MIInnwYJKoZIhvcNAQcCoIInkDCCJ4wCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCOIiWAzeEduiG+ # 0cihARZuXbPzSE7Sx4vMCN+0qQsnSKCCDXYwggX0MIID3KADAgECAhMzAAACy7d1 # OfsCcUI2AAAAAALLMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NTU5WhcNMjMwNTExMjA0NTU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQC3sN0WcdGpGXPZIb5iNfFB0xZ8rnJvYnxD6Uf2BHXglpbTEfoe+mO//oLWkRxA # wppditsSVOD0oglKbtnh9Wp2DARLcxbGaW4YanOWSB1LyLRpHnnQ5POlh2U5trg4 # 3gQjvlNZlQB3lL+zrPtbNvMA7E0Wkmo+Z6YFnsf7aek+KGzaGboAeFO4uKZjQXY5 # RmMzE70Bwaz7hvA05jDURdRKH0i/1yK96TDuP7JyRFLOvA3UXNWz00R9w7ppMDcN # lXtrmbPigv3xE9FfpfmJRtiOZQKd73K72Wujmj6/Su3+DBTpOq7NgdntW2lJfX3X # a6oe4F9Pk9xRhkwHsk7Ju9E/AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUrg/nt/gj+BBLd1jZWYhok7v5/w4w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzQ3MDUyODAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJL5t6pVjIRlQ8j4dAFJ # ZnMke3rRHeQDOPFxswM47HRvgQa2E1jea2aYiMk1WmdqWnYw1bal4IzRlSVf4czf # zx2vjOIOiaGllW2ByHkfKApngOzJmAQ8F15xSHPRvNMmvpC3PFLvKMf3y5SyPJxh # 922TTq0q5epJv1SgZDWlUlHL/Ex1nX8kzBRhHvc6D6F5la+oAO4A3o/ZC05OOgm4 # EJxZP9MqUi5iid2dw4Jg/HvtDpCcLj1GLIhCDaebKegajCJlMhhxnDXrGFLJfX8j # 7k7LUvrZDsQniJZ3D66K+3SZTLhvwK7dMGVFuUUJUfDifrlCTjKG9mxsPDllfyck # 4zGnRZv8Jw9RgE1zAghnU14L0vVUNOzi/4bE7wIsiRyIcCcVoXRneBA3n/frLXvd # jDsbb2lpGu78+s1zbO5N0bhHWq4j5WMutrspBxEhqG2PSBjC5Ypi+jhtfu3+x76N # mBvsyKuxx9+Hm/ALnlzKxr4KyMR3/z4IRMzA1QyppNk65Ui+jB14g+w4vole33M1 # pVqVckrmSebUkmjnCshCiH12IFgHZF7gRwE4YZrJ7QjxZeoZqHaKsQLRMp653beB # fHfeva9zJPhBSdVcCW7x9q0c2HVPLJHX9YCUU714I+qtLpDGrdbZxD9mikPqL/To # /1lDZ0ch8FtePhME7houuoPcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCGX8wghl7AgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAALLt3U5+wJxQjYAAAAAAsswDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFCPuYF3jt6CFIZXzlAy1SH0 # dVkrShKVetUxRlQbsST4MEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAheUTPHIgTJk7uS1yXCbjtMr7f9m50TVyyM2FyLWpdRL40VHNemqkV0Tv # SBKoPZNj18B8eWZzFIqvMA4b0i+feHvAe4qRbws6CA70jRSGkWol/YTRzec5h0dd # 4krbDR/XfwIW2VbAXDoPq/G6XvpqfI4jcmfG92sLvTKeTclbVAbeqlA6NqFzpbUf # MGrUHIW1PLysvozgXDGu32EsTqMNRzSl9Ao+uxo2ADZMRT7srVwBYKl1/i6CtGIl # wDW2yO1ELxxdoGG/e0d2HSAQSu9Nb+xFEpEQPAN8BVudMNEJMDk4j8BucUAsK2zB # CogsT5WeFJCvN+kMCelIcq3eVMKFeaGCFwkwghcFBgorBgEEAYI3AwMBMYIW9TCC # FvEGCSqGSIb3DQEHAqCCFuIwghbeAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFVBgsq # hkiG9w0BCRABBKCCAUQEggFAMIIBPAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCA5cxZVSqeVsnEs3V7RdXhgthxWhNAsc036Z9+I9x83uAIGY8aLyAup # GBMyMDIzMDEyNjIyMzEwNS4zMzJaMASAAgH0oIHUpIHRMIHOMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3NvZnQgT3Bl # cmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046RjdB # Ni1FMjUxLTE1MEExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZp # Y2WgghFcMIIHEDCCBPigAwIBAgITMwAAAaUA3gjEQAdxTgABAAABpTANBgkqhkiG # 9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYw # JAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yMjAzMDIx # ODUxMTlaFw0yMzA1MTExODUxMTlaMIHOMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVy # dG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046RjdBNi1FMjUxLTE1MEEx # JTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqG # SIb3DQEBAQUAA4ICDwAwggIKAoICAQC6sYboIGpIvMLqDjDHe67BEJ5gIbVfIlNW # NIrbB6t9E3QlyQ5r2Y2mfMrzh2BVYU8g9W+SRibcGY1s9X4JQqrMeagcT9VsdQmZ # 7ENbYkbEVkHNdlZBE5pGPMeOjIB7BsgJoTz6bIEZ5JRmoux6kBQd9cf0I5Me62wJ # a+j25QeLTpmkdZysZeFSILLQ8H53imqBBMOIjf8U3c7WY8MhomOYTaem3nrZHIs4 # CRTt/8kR2IdILZPm0RIa5iIG2q664G8+zLJwO7ZSrxnDvYh3OvtrMpqwFctws0OC # DDTxXE08fME2fpKb+pRbNXhvMZX7LtjQ1irIazJSh9iaWM1gFtXwjg+Yq17BOCzr # 4sWUL253kBOvohnyEMGm4/n0XaLgFNgIhPomjbCA2qXSmm/Fi8c+lT0WxC/jOjBZ # HLKIrihx6LIQqeyYZmfYjNMqxMdl3mzoWv10N+NirERrNodNoKV+sAcsk/Hg9zCV # SMUkZuDCyIpb1nKXfTd66KGsGy1OoHZO4KClkuvfsNo7aLlwhGLeiD32avJXYtC/ # wsGG7b+5mx5iGfTnNCRCXOm/YHFQ36D4npjCnM9eQS3qcse56UNjIgyiLHDqioV7 # mSPj2XqzTh4Yv77MtvxY/ZQepCazGEn1dBdn67wUgVzAe8Y7/KYKl+UF1HvJ08W+ # FHydHAwLwQIDAQABo4IBNjCCATIwHQYDVR0OBBYEFF+mjwMAl66urXDu+9xZF0to # qRrfMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYw # VKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jv # c29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcB # AQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv # cHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSku # Y3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZIhvcN # AQELBQADggIBAJabCxflMDCihEdqdFiZ6OBuhhhp34N6ow3Wh3Obr12LRuiph66g # H/2Kh5JjaLUq+mRBJ5RgiWEe1t7ifuW6b49N8Bahnn70LCiEdvquk686M7z+DbKH # Vk0+UlafwukxAxriwvZjkCgOLci+NB01u7cW9HAHX4J8hxaCPwbGaPxWl3s0PITu # MVI4Q6cjTXielmL1+TQvh7/Z5k8s46shIPy9nFwDpsRFr3zwENZX8b67VMBu+Yxn # lGnsJIcLc2pwpz95emI8CRSgep+/017a34pNcWNZIHr9ScEOWlHT8cEnQ5hhOF0z # drOqTzovCDtffTn+gBL4eNXg8Uc/tdVVHKbhp+7SVHkk1Eh7L80PBAjo+cO+zL+e # fxfIVrtO3oJxvEq1o+fkxcTTwqcfwBTb88/qHU0U2XeC1rqJnDB1JixYlBjgHXrR # ekqHxxuRHBZ9A0w9WqQWcwj/MbBkHGYMFaqO6L9t/7iCZTAiwMk2GVfSEwj9PXIl # CWygVQkDaxhJ0P1yxTvZsrMsg0a7x4VObhj3V8+Cbdv2TeyUGEblTUrgqTcKCtCa # 9bOnIg7xxHi8onM8aCHvRh90sn2x8er/6YSPohNw1qNUwiu+RC+qbepOYt+v5J9r # klV3Ux+OGVZId/4oVd7xMLO/Lhpb7IjHKygYKaNx3XIwx4h6FrFH+BiMMIIHcTCC # BVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWlj # cm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMw # MTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg # MjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3mi # y9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+ # Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3 # oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+ # tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0 # hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLN # ueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZ # nkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n # 6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC # 4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vc # G9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtF # tvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEE # BQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNV # HQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3 # TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br # aW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkG # CSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8E # BTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRP # ME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1 # Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEww # SgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMv # TWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCd # VX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQ # dTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnu # e99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYo # VSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlC # GVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZ # lvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ # ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtq # RRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+ # y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgk # NWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqK # Oghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAs8wggI4AgEBMIH8oYHU # pIHRMIHOMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYD # VQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMd # VGhhbGVzIFRTUyBFU046RjdBNi1FMjUxLTE1MEExJTAjBgNVBAMTHE1pY3Jvc29m # dCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVALPJcNtFs5sQyojd # S4Ye5mVl7rSooIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw # DQYJKoZIhvcNAQEFBQACBQDnfOeaMCIYDzIwMjMwMTI2MTU1MDUwWhgPMjAyMzAx # MjcxNTUwNTBaMHQwOgYKKwYBBAGEWQoEATEsMCowCgIFAOd855oCAQAwBwIBAAIC # Iu0wBwIBAAICEZgwCgIFAOd+ORoCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYB # BAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOB # gQA2Nlc7NY75Ev2KSx4rIbTQOLMoUS442HzWSR/w7sK0tOGHIEbLwvGRVbIb9RxB # BY+lHHcUdD4cDJxuYwT6vGb7nTRked0zSyGl03qwFWRlYAvfyjabOg2CbAPjWkhl # 4ncGxXPLj4yyYzFIGczjvYzITZAyj0BR7FrQYn4xAaa4CTGCBA0wggQJAgEBMIGT # MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT # HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABpQDeCMRAB3FOAAEA # AAGlMA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQ # AQQwLwYJKoZIhvcNAQkEMSIEIMnMZVG/yf/OXUz6nMm9X+iLXV3N1YcoWSpPZG4V # +iaTMIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQguAo4cX5mBLGgrdgFPNyo # YfuiR5cpNwe9L3zBzJQS3FwwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ # Q0EgMjAxMAITMwAAAaUA3gjEQAdxTgABAAABpTAiBCBUMbv6476sN5x7jffCyIeT # JwwdpPackOKyaRtZjfvbnDANBgkqhkiG9w0BAQsFAASCAgByebly0vUV1C8XXamI # xMYdpEgzg+F5ayXmSF+gbiw8CGdHm4AUl4B+8sfG+2MRd3DlQtiGKpnOxQXhUQMO # rfdqSLFUa44ezbd1qd2t5gQKCxRUbWk8/Hil95HuJGFrDkSgl3yf3di7Ci2g/w4t # rzaErjVE4T0bfb+1+caCiTUmSVJqbXlWYlUjGA19rPPPdPZHPHV508zJX3xpD9PT # td3kpv/l3fayOw8dwue/mObw7DlLhEofbqOmR4ny1XkGgnqtWywc17dHZL1YE8uV # ROGN7xERc07zXeirLYXCquUBev9EBFbTeCzEqkuH6dGH0pGDPyOIsYmTXFECra8D # 09Hjoo/0qKMVnVmoJ/Jc0RRM/iiXpqW7QuVZQgAO+O1lWJeVCszdRZbMtJO6P8lJ # of1INQGniqLaHBfF+k9sGvJyTH8YNsr1QjYBE/HtxFc6aF1B61uhKJ0rHB88rx/p # R2XAImtx9eowX77FkoldT9lFGEuuXRY2FMQskcsfSlOV7v+ifgC9JNRN4XKFSm3a # pPoDWeyR/SBsdFI5jMypBnAvqpnKwG+A/qTGAtU6KFSUDROPk/X0k5hwIOhaQ9vJ # 8Qo5A5NhhR2Fex/Q+CtuttYXXSXG7S4vd1hSBh+ApahE/ziUs9GRGO9Oqkv7yKWg # G3V04h56/lx5a8MQtOdMUg45Cw== # SIG # End signature block |