2962 lines
86 KiB
PowerShell
2962 lines
86 KiB
PowerShell
#
|
|
# Copyright 2018-2024 HP Development Company, L.P.
|
|
# All Rights Reserved.
|
|
#
|
|
# NOTICE: All information contained herein is, and remains the property of HP Development Company, L.P.
|
|
#
|
|
# The intellectual and technical concepts contained herein are proprietary to HP Development Company, L.P
|
|
# and may be covered by U.S. and Foreign Patents, patents in process, and are protected by
|
|
# trade secret or copyright law. Dissemination of this information or reproduction of this material
|
|
# is strictly forbidden unless prior written permission is obtained from HP Development Company, L.P.
|
|
|
|
using namespace HP.CMSLHelper
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version 3.0
|
|
|
|
# CMSL is normally installed in C:\Program Files\WindowsPowerShell\Modules
|
|
# but if installed via PSGallery and via PS7, it is installed in a different location
|
|
if(Test-Path "$PSScriptRoot\..\HP.Private\HP.CMSLHelper.dll") {
|
|
Add-Type -Path "$PSScriptRoot\..\HP.Private\HP.CMSLHelper.dll"
|
|
}
|
|
else {
|
|
Add-Type -Path "$PSScriptRoot\HP.CMSLHelper.dll"
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateReadINI {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $True)] $file,
|
|
[Parameter(Mandatory = $False)] [int]$maxRetries = 0
|
|
)
|
|
|
|
Write-Verbose "Reading INI style file '$file'"
|
|
[System.IO.StreamReader]$streamReader = $null
|
|
$CommentCount = 0
|
|
$name = $null
|
|
|
|
# only allow https or file paths with or without file:// URL prefix
|
|
if ($file -and -not ($file.StartsWith("https://",$true,$null) -or [System.IO.File]::Exists($file) -or $file.StartsWith("file://",$true,$null))) {
|
|
throw [System.ArgumentException]"Only HTTPS or valid existing file paths are supported."
|
|
}
|
|
|
|
|
|
# if file starts with file:// or file:/// or file:////, remove the file URL prefix to just use the actual file path
|
|
if ($file.StartsWith("file://",$true,$null)) {
|
|
$file = $file.Substring(7)
|
|
}
|
|
|
|
# remove any leading forward slashes
|
|
$file = $file.TrimStart("/")
|
|
|
|
try {
|
|
if ($file.StartsWith("https://",$true,$null)) {
|
|
Write-Verbose ("Reading network file: $file")
|
|
|
|
[int]$retries = $maxRetries
|
|
do {
|
|
try {
|
|
Write-Verbose "Downloading CVA file $file, try $($maxRetries-$retries) / $maxRetries"
|
|
[System.Net.ServicePointManager]::SecurityProtocol = Get-HPPrivateAllowedHttpsProtocols
|
|
$userAgent = Get-HPPrivateUserAgent
|
|
$data = Invoke-WebRequest -Uri $file -UserAgent $userAgent -UseBasicParsing -ErrorAction Stop
|
|
$retries = 0
|
|
}
|
|
catch {
|
|
$retries = $retries - 1
|
|
Write-Verbose ("Download failed: $($_.Exception)")
|
|
if ($retries -le 0) { throw $_ }
|
|
Start-Sleep 5
|
|
|
|
}
|
|
} while ($retries -gt 0)
|
|
|
|
$streamReader = New-Object System.IO.StreamReader ($data.RawContentStream)
|
|
}
|
|
else {
|
|
Write-Verbose ("Reading filesystem file: $file")
|
|
$streamReader = New-Object -TypeName System.IO.StreamReader -ArgumentList $file
|
|
}
|
|
|
|
$ini = @{}
|
|
while (($line = $streamReader.ReadLine()) -ne $null) {
|
|
switch -regex ($line) {
|
|
"^\[(.+)\]$" {
|
|
# Section
|
|
$section = $matches[1]
|
|
$ini[$section] = @{}
|
|
$CommentCount = 0
|
|
}
|
|
"^(;.*)$" {
|
|
# Comment
|
|
if (!(Test-Path variable:\section)) {
|
|
$section = "No-Section"
|
|
$ini[$section] = @{}
|
|
}
|
|
$value = $matches[1]
|
|
$CommentCount = $CommentCount + 1
|
|
$name = "Comment" + $CommentCount
|
|
$ini[$section][$name] = $value
|
|
}
|
|
"(.+?)\s*=\s*(.*)" {
|
|
# Key
|
|
if (!($section)) {
|
|
$section = "No-Section"
|
|
$ini[$section] = @{}
|
|
}
|
|
$name,$value = $matches[1..2]
|
|
if ($ini[$section][$name]) {
|
|
if ($ini[$section][$name] -is [string]) {
|
|
$ini[$section][$name] = @($ini[$section][$name])
|
|
}
|
|
$ini[$section][$name] += $value
|
|
}
|
|
else {
|
|
$ini[$section][$name] = $value
|
|
}
|
|
continue
|
|
}
|
|
"^(?!(.*[=])).*" {
|
|
# section text block
|
|
if (!($section)) {
|
|
$section = "No-Section"
|
|
$ini[$section] = @{}
|
|
}
|
|
|
|
if ($ini[$section]["_body"] -eq $null) {
|
|
$ini[$section]["_body"] = @()
|
|
}
|
|
|
|
$ini[$section]["_body"] += ($matches.Values | Where-Object { $_.StartsWith("[") -eq $false })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
if ($streamReader) {
|
|
$streamReader.Close()
|
|
$streamReader.Dispose()
|
|
$streamReader = $null
|
|
}
|
|
}
|
|
return $ini
|
|
}
|
|
|
|
|
|
|
|
|
|
# this is what the downloaded filename will be
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateTemporaryFileName ($filename,[System.IO.DirectoryInfo]$cacheDir = [System.IO.Path]::GetTempPath() + "hp") {
|
|
$cacheDir = Join-Path -Path $cacheDir -ChildPath $filename
|
|
$cacheDir.FullName
|
|
}
|
|
|
|
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function GetLockedStreamForWrite {
|
|
[CmdletBinding()]
|
|
param([string]$target,[int]$maxRetries = 10)
|
|
|
|
Write-Verbose "Opening exclusive access to file $target with maximum retries of $maxRetries"
|
|
$lock_wait = $false
|
|
|
|
do {
|
|
try {
|
|
$lock_wait = $false
|
|
$result = New-Object -TypeName System.IO.FileStream -ArgumentList $target,Create,Write,None
|
|
}
|
|
catch {
|
|
Write-Verbose ("******* $($_ | fl)")
|
|
$lock_wait = $true
|
|
if ($maxRetries -gt 0) {
|
|
Start-Sleep -Seconds 30
|
|
$maxRetries = $maxRetries - 1
|
|
}
|
|
else {
|
|
throw "Could not obtain exclusive access to file '$target' and all retries were exhausted."
|
|
}
|
|
|
|
}
|
|
}
|
|
while ($lock_wait -eq $true)
|
|
$result
|
|
}
|
|
|
|
# check for collision with other processes
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function GetSharedFileInformation {
|
|
[CmdletBinding()]
|
|
param($file,[string]$mode,[switch]$wait,[int]$maxRetries,[switch]$progress,[switch]$skipSignatureCheck)
|
|
|
|
$return = $true
|
|
$length = 0
|
|
$sig = $false
|
|
|
|
Write-Verbose ("Getting file information for file $file with access rights=$mode, wait = $wait, maxRetries=$maxRetries, skipAuthenticode=$($skipSignatureCheck.IsPresent)")
|
|
if (-not $wait.IsPresent) {
|
|
Write-Verbose ("This operation will not be retried.")
|
|
$maxRetries = 0
|
|
}
|
|
|
|
do {
|
|
# file length
|
|
try {
|
|
$length = (Get-ChildItem -File $file -ErrorAction Stop).Length
|
|
}
|
|
catch {
|
|
Write-Verbose "Caught exception: $_.Message"
|
|
return (-1,$true,$skipSignatureCheck.IsPresent)
|
|
}
|
|
|
|
Write-Verbose ("Target file length on disk is $length bytes")
|
|
try {
|
|
$fs = [System.IO.File]::Open($file,"Open",$mode)
|
|
$return = $true
|
|
$fs.Close()
|
|
$fs.Dispose()
|
|
Write-Verbose "Able to read from file '$file', it doesn't seem locked."
|
|
|
|
|
|
if ($skipSignatureCheck.IsPresent) {
|
|
Write-Verbose "Not checking Authenticode signature for file $file"
|
|
$sig = $true
|
|
}
|
|
else {
|
|
$sig = Get-HPPrivateCheckSignature -File $file -Progress:$progress
|
|
}
|
|
break
|
|
}
|
|
catch [System.IO.FileNotFoundException]{
|
|
Write-Verbose "File not found: $_.Message"
|
|
return (-1,$true,$skipSignatureCheck.IsPresent)
|
|
}
|
|
catch {
|
|
Write-Verbose "Internal error: $_.Message"
|
|
$return = $false
|
|
if ($maxRetries -gt 0) {
|
|
if ($progress) {
|
|
Write-Progress -Activity "Blocked by another process, will retry for ($maxRetries) tries"
|
|
}
|
|
|
|
Write-Verbose ("Sleeping for 30 seconds since someone else has '$file' locked")
|
|
Start-Sleep -Seconds 30
|
|
Write-Verbose ("Woke up")
|
|
}
|
|
$maxRetries = $maxRetries - 1
|
|
}
|
|
} while ($maxRetries -gt 0)
|
|
($length,$return,$sig)
|
|
}
|
|
|
|
|
|
# download a file
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-HPPrivateDownloadFile {
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[string]$url,
|
|
[string]$target,
|
|
[bool]$progress,
|
|
[string]$noclobber,
|
|
[switch]$panic,
|
|
[int]$maxRetries = 0,
|
|
[switch]$skipSignatureCheck
|
|
)
|
|
|
|
Write-Verbose ("Requesting to download $url to $target with progress: $progress and signatureCheckSkip: $skipSignatureCheck")
|
|
[System.Net.ServicePointManager]::SecurityProtocol = Get-HPPrivateAllowedHttpsProtocols
|
|
$userAgent = Get-HPPrivateUserAgent
|
|
$targetStream = $null
|
|
$responseStream = $null
|
|
$response = $null
|
|
|
|
try {
|
|
if (Test-Path $target -PathType Leaf) {
|
|
# target file exists
|
|
switch ($noclobber) {
|
|
"no" {
|
|
if ($panic.IsPresent) { throw "File $target already exists, will not overwrite." }
|
|
|
|
if ($progress) { Write-Host -ForegroundColor Magenta "File $target already exists, will not overwrite." }
|
|
return
|
|
}
|
|
"yes" {
|
|
if ($progress -eq $true) { Write-Verbose "Overwriting existing file $target" }
|
|
}
|
|
"skip" {}
|
|
}
|
|
|
|
}
|
|
else {
|
|
#create lead directory if needed
|
|
$lead = Split-Path $target
|
|
if (!(Test-Path $lead)) {
|
|
Write-Verbose "Creating directory '$lead'"
|
|
$leaf = Split-Path $lead -leaf
|
|
New-Item -ItemType Directory -Force -Path $lead.TrimEnd($leaf) -Name $leaf | Out-Null
|
|
}
|
|
}
|
|
|
|
$uri = New-Object "System.Uri" "$url"
|
|
$retries = $maxRetries
|
|
|
|
do {
|
|
$request = [System.Net.HttpWebRequest]::Create($uri)
|
|
$request.set_Timeout(60000)
|
|
|
|
if (-not $request -is [System.Net.FtpWebRequest]) {
|
|
$request.set_UserAgent($userAgent)
|
|
}
|
|
try {
|
|
Write-Verbose "Executing query on $uri, try $($maxRetries-$retries) / $maxRetries"
|
|
$response = $request.GetResponse()
|
|
$retries = 0
|
|
}
|
|
catch {
|
|
$retries = $retries - 1
|
|
|
|
if ($retries -le 0) {
|
|
throw "Query failed: $($_.Exception)"
|
|
}
|
|
else{
|
|
Write-Verbose ("Query failed: $($_.Exception). Trying again.")
|
|
}
|
|
Start-Sleep 5
|
|
}
|
|
|
|
} while ($retries -gt 0)
|
|
|
|
$responseContentLength = $response.get_ContentLength()
|
|
if ($responseContentLength -ge 1024) {
|
|
$totalLength = [System.Math]::Floor($responseContentLength / 1024)
|
|
}
|
|
else {
|
|
$totalLength = 1
|
|
}
|
|
|
|
# Someone else may be downloading this file at this time, so we'll wait until they release the
|
|
# lock and then we check the size
|
|
Write-Verbose ("Target file is $target")
|
|
|
|
# get file information if it exists to see if it contains the contents we want
|
|
# and if file does not exist, continue on with the download as usual
|
|
if(Test-Path -Path $target -PathType leaf){
|
|
$r = GetSharedFileInformation -File $target -Mode "Read" -Wait -maxRetries $maxRetries -Progress:$progress -skipSignatureCheck:$skipSignatureCheck
|
|
if ($noclobber -eq "skip") {
|
|
if (($r[0] -eq $response.get_ContentLength()) -and ($r[2] -eq $true)) {
|
|
Write-Verbose "File already exists or another process has finished downloading this file for us."
|
|
return
|
|
}
|
|
else {
|
|
# overwrite=skip means skip overwriting existing files without error so will not proceed with download
|
|
Write-Verbose ("Existing file $target doesn't seem correct (size=$($r[0]) vs expected $($response.get_ContentLength()), signature_check=$($r[2]). Skipping (will not overwrite). ")
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
$responseStream = $response.GetResponseStream()
|
|
$targetStream = GetLockedStreamForWrite -maxRetries $maxRetries -Target $target
|
|
|
|
$buffer = New-Object byte[] 10KB
|
|
$count = $responseStream.Read($buffer,0,$buffer.Length)
|
|
$downloadedBytes = $count
|
|
|
|
#being too verbose with Write-Progress slows down the process
|
|
$maxChunks = 20
|
|
$chunkSize = $totalLength / $maxChunks
|
|
while ($chunkSize -gt 1024) {
|
|
$maxChunks = $maxChunks * 2
|
|
$chunkSize = $totalLength / $maxChunks
|
|
}
|
|
|
|
if ($chunkSize -lt 16384) {
|
|
$chunkSize = 16384
|
|
$maxChunks = 1
|
|
}
|
|
|
|
$lastChunk = 0
|
|
while ($count -gt 0) {
|
|
$targetStream.Write($buffer,0,$count)
|
|
$count = $responseStream.Read($buffer,0,$buffer.Length)
|
|
$downloadedBytes = $downloadedBytes + $count
|
|
$thisChunk = [System.Math]::Floor(($downloadedBytes / 100) / $totalLength)
|
|
|
|
# warning: do not update progress every iteration because it slows down the download significantly
|
|
# i.e. SoftPaq 144724 will take 14-17 mins instead of 30-40 seconds to download
|
|
if (($progress -eq $true) -and ($thisChunk -gt $lastChunk)) {
|
|
$lastChunk = $thisChunk
|
|
Write-Progress -Activity "Downloading file '$($url.split('/') | Select -Last 1)'" -Status "Downloaded ($([System.Math]::Floor($downloadedBytes/1024))K of $($totalLength)K): " -PercentComplete ((([System.Math]::Floor($downloadedBytes / 1024)) / $totalLength) * 100)
|
|
}
|
|
}
|
|
|
|
if ($progress -eq $true) {
|
|
Write-Verbose ("Finished downloading '$($url.split('/') | Select-Object -Last 1)'")
|
|
Write-Progress -Activity "Finished downloading file '$($url.split('/') | Select-Object -Last 1)'" -Completed
|
|
}
|
|
}
|
|
catch{
|
|
throw ("Failed to download due to $($_.Exception)")
|
|
}
|
|
finally {
|
|
if ($targetStream) {
|
|
$targetStream.Flush()
|
|
$targetStream.Close()
|
|
$targetStream.Dispose()
|
|
}
|
|
|
|
if ($responseStream) {
|
|
$responseStream.Close()
|
|
$responseStream.Dispose()
|
|
}
|
|
|
|
if ($response) {
|
|
$response.Close()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateCurrentOs {
|
|
switch ([string][System.Environment]::OSVersion.Version.Major + "." + [string][System.Environment]::OSVersion.Version.Minor) {
|
|
"10.0" { $os = "win10" }
|
|
"6.3" { $os = "win81" }
|
|
"6.2" { $os = "win8" }
|
|
"6.1" { $os = "win7" }
|
|
}
|
|
if ([string][System.Environment]::OSVersion.Version.Build -ge 22000) {
|
|
$os = "win11"
|
|
}
|
|
return $os
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Send-HPPrivateKMSRequest
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$KMSUri,
|
|
[string]$JsonPayload,
|
|
[string]$AccessToken,
|
|
[string]$Method = "POST"
|
|
)
|
|
|
|
Write-Verbose "HTTPS Request $KMSUri : $Method => $jsonPayload"
|
|
$userAgent = Get-HPPrivateUserAgent
|
|
$request = [System.Net.HttpWebRequest]::Create($KMSUri)
|
|
$request.set_UserAgent($userAgent)
|
|
$request.Method = $Method
|
|
$request.Timeout = -1
|
|
$request.KeepAlive = $true
|
|
$request.ReadWriteTimeout = -1
|
|
$request.Headers.Add("Authorization","Bearer $AccessToken")
|
|
if ($JsonPayload) {
|
|
$content = [System.Text.Encoding]::UTF8.GetBytes($JsonPayload)
|
|
$request.ContentType = "application/json"
|
|
$request.ContentLength = $content.Length
|
|
$stream = $request.GetRequestStream()
|
|
$stream.Write($content,0,$content.Length)
|
|
$stream.Flush()
|
|
$stream.Close()
|
|
}
|
|
|
|
try {
|
|
[System.Net.WebResponse]$response = $request.GetResponse()
|
|
}
|
|
catch [System.Net.WebException]{
|
|
Write-Verbose $_.Exception.Message
|
|
$response = $_.Exception.Response
|
|
}
|
|
|
|
if ($response.PSObject.Properties.Name -match 'StatusDescription') {
|
|
$statusDescription = $response.StatusDescription
|
|
$receiveStream = $response.GetResponseStream()
|
|
$streamReader = New-Object System.IO.StreamReader $receiveStream
|
|
$responseContent = $streamReader.ReadToEnd()
|
|
$streamReader.Close()
|
|
$streamReader.Dispose()
|
|
Write-Verbose $responseContent
|
|
}
|
|
|
|
$response.Close()
|
|
return $statusDescription,$responseContent
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-HPPrivateKMSErrorHandle {
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$ApiResponseContent,
|
|
[string]$Status
|
|
)
|
|
|
|
if ($Status -eq 'Not Found') {
|
|
throw "URL not found"
|
|
}
|
|
|
|
try {
|
|
$response = $ApiResponseContent | ConvertFrom-Json
|
|
}
|
|
catch {
|
|
Write-Verbose $ApiResponseContent
|
|
throw 'Error code malformed'
|
|
}
|
|
|
|
if ($response -and $response.PSObject.Properties.Name -contains 'errorCode') {
|
|
switch ($response.errorCode) {
|
|
# Internal errors codes are suppressed
|
|
401 { throw "Error code ($_): Unauthorized" }
|
|
402 { throw "Error code ($_): Key does not exist" }
|
|
403 { throw "Error code ($_): Key does not exist" }
|
|
404 { throw "Error code ($_): Error while adding key to vault" }
|
|
405 { throw "Error code ($_): Unauthorized" }
|
|
406 { throw "Error code ($_): Invalid Azure tenant" }
|
|
407 { throw "Error code ($_): User does not belong to any group" }
|
|
408 { throw "Error code ($_): User does not belong to any group the key is assigned to" }
|
|
409 { throw "Error code ($_): Invalid access token" }
|
|
410 { throw "Error code ($_): Invalid access token" }
|
|
411 { throw "Error code ($_): Invalid access token" }
|
|
412 { throw "Error code ($_): Invalid access token" }
|
|
413 { throw "Error code ($_): Invalid key id" }
|
|
414 { throw "Error code ($_): Unauthorized" }
|
|
415 { throw "Error code ($_): Failed to recover secret" }
|
|
416 { throw "Error code ($_): Invalid request" }
|
|
417 { throw "Error code ($_): Unauthorized" }
|
|
418 { throw "Error code ($_): Invalid request" }
|
|
419 { throw "Error code ($_): Invalid request" }
|
|
420 { throw "Error code ($_): Key not concurrent" }
|
|
440 { throw "Error code ($_): Permission table functionality not supported" }
|
|
430 { throw "Error code ($_): Unauthorized" }
|
|
431 { throw "Error code ($_): Key mapping already exists" }
|
|
432 { throw "Error code ($_): Unauthorized" }
|
|
433 { throw "Error code ($_): Invalid key mapping" }
|
|
434 { throw "Error code ($_): Unauthorized" }
|
|
435 { throw "Error code ($_): Invalid key mapping" }
|
|
436 { throw "Error code ($_): Unauthorized" }
|
|
437 { throw "Error code ($_): Invalid key mapping" }
|
|
438 { throw "Error code ($_): Incorrect content-type" }
|
|
439 { throw "Error code ($_): Multiple changes for the same device id is not supported" }
|
|
501 { throw "Error code ($_): Key already exists" }
|
|
502 { throw "Error code ($_): Invalid key id" }
|
|
503 { throw "Error code ($_): Invalid key id" }
|
|
504 { throw "Error code ($_): Invalid key id" }
|
|
601 { throw "Error code ($_): Invalid request" }
|
|
602 { throw "Error code ($_): Invalid key id" }
|
|
603 { throw "Error code ($_): Unauthorized" }
|
|
604 { throw "Error code ($_): Malformed key" }
|
|
606 { throw "Error code ($_): Same EK and SK is not allowed" }
|
|
default { throw "Error code ($_)" }
|
|
}
|
|
}
|
|
|
|
Write-Verbose $ApiResponseContent
|
|
throw "Wrong URL or error code malformed"
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only.
|
|
Determine if running in WinPE.
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only.
|
|
Returns $true if running in Win PE, $false otherwise.
|
|
|
|
.EXAMPLE
|
|
Test-WinPE
|
|
#>
|
|
function Test-WinPE
|
|
{
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
$r = Test-Path -Path Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Control\MiniNT
|
|
Write-Verbose ("Running in Windows PE: $r")
|
|
$r
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateCurrentOsBitness {
|
|
if ([environment]::Is64BitOperatingSystem -eq $true) {
|
|
$output = systeminfo | findstr /C:"System Type"
|
|
|
|
if($output -match "ARM64-based PC") { # ARM64-based PC means ARM64
|
|
return "arm64"
|
|
}
|
|
else { # x64-based PC means x64
|
|
return 64
|
|
}
|
|
}
|
|
else {
|
|
return 32
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateUnicodePath {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path
|
|
)
|
|
|
|
return "\\?\$Path"
|
|
}
|
|
|
|
# perform an action after a SoftPaq download completed
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-PostDownloadSoftpaqAction
|
|
{
|
|
[CmdletBinding()]
|
|
param([string]$downloadedFile,[string]$action,[string]$number,$info,[string]$Destination)
|
|
|
|
Write-Verbose 'Processing post-download action'
|
|
$PostDownloadCmd = $null
|
|
|
|
switch ($action) {
|
|
"extract" {
|
|
if (!$Destination) {
|
|
$Destination = (Get-Item $downloadedFile).DirectoryName
|
|
$Destination = Join-Path -Path $Destination -ChildPath (Get-Item $downloadedFile).BaseName
|
|
}
|
|
|
|
Write-Verbose -Message "Extracting $downloadedFile to: $Destination"
|
|
$output = Start-Process -Wait -PassThru "$downloadedFile" -ArgumentList "-e -f `"$Destination`"","-s"
|
|
$result = $?
|
|
Write-Verbose -Message "Extraction result: $result"
|
|
}
|
|
"install" {
|
|
#$PostDownloadCmd = descendNodesAndGet $info -field "install"
|
|
if($Destination){
|
|
# the /f switch for SoftPaq executables = the runtime switch that
|
|
# overrides the default target path specified in build time
|
|
$output = Start-Process -Wait -PassThru "$downloadedFile" -ArgumentList "/f `"$Destination`""
|
|
}
|
|
else{
|
|
# default destination folder is C:\SWSetup\SP<$number>
|
|
$output = Start-Process -Wait -PassThru "$downloadedFile"
|
|
}
|
|
|
|
$result = $?
|
|
Write-Verbose -Message "Installation result: $result"
|
|
}
|
|
"silentinstall" {
|
|
# Get the silent install command from the metadata
|
|
if (!$info) { $info = Get-SoftpaqMetadata $number }
|
|
|
|
$PostDownloadCmd = $info | Out-SoftpaqField -Field "silentinstall"
|
|
if($Destination){
|
|
# the /f switch for SoftPaq executables = the runtime switch that
|
|
# overrides the default target path specified in build time
|
|
$output = Start-Process -Wait -PassThru "$downloadedFile" -ArgumentList "-s","-e cmd.exe","/f `"$Destination`"","-a","/c $PostDownloadCmd"
|
|
}
|
|
else{
|
|
# default destination folder is C:\SWSetup\SP<$number>
|
|
$output = Start-Process -Wait -PassThru "$downloadedFile" -ArgumentList "-s","-e cmd.exe","-a","/c $PostDownloadCmd"
|
|
}
|
|
$result = $?
|
|
Write-Verbose -Message "Silent installation result: $result"
|
|
}
|
|
}
|
|
|
|
# -PassThru switch for Start-Process allows us to get the process object output. Then, we can check the exit code of the
|
|
# SoftPaq executable to get the specific error code. This is more useful for debugging than just getting a boolean result.
|
|
Write-Verbose -Message "The $action process exited with return code: $($output.ExitCode)"
|
|
|
|
Write-Verbose 'Post-download action processing complete'
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateAllowedHttpsProtocols {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
$c = [System.Net.SecurityProtocolType]([System.Net.SecurityProtocolType].GetEnumNames() | Where-Object { $_ -ne "Ssl3" -and $_ -ne "Tls" -and $_ -ne "Tls11" })
|
|
Write-Verbose "Removing obsolete protocols SSL 3.0, TLS 1.0, and TLS 1.1; now supporting: $c"
|
|
$c
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateCacheDirPath {
|
|
|
|
[CmdletBinding()]
|
|
param([System.IO.DirectoryInfo]$seed)
|
|
|
|
if (-not $seed) {
|
|
$seed = [System.IO.Path]::GetTempPath() + "hp"
|
|
}
|
|
Join-Path -Path $seed -ChildPath "cache"
|
|
Write-Verbose "Local caching path is: $seed"
|
|
}
|
|
|
|
# check authenticode signature
|
|
# check CVA and SoftPaq hash to determine download of the SoftPaq
|
|
#
|
|
# tests (remove these comments once we are happy with the function)
|
|
#
|
|
# PASS: Get-HPPrivateCheckSignature -file C:\windows\System32\notepad.exe -signedBy "Microsoft Windows" -Verbose
|
|
# PASS: Get-HPPrivateCheckSignature -file C:\windows\System32\notepad.exe -Verbose
|
|
# PASS: Get-HPPrivateCheckSignature -file .\sp99062.exe -CVAfile .\sp99062.cva -Verbose
|
|
# PASS: Get-HPPrivateCheckSignature -file .\sp99062.exe -CVAfile .\sp99062.cva -Verbose -signedBy "HP Inc."
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateCheckSignature {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Position = 0,Mandatory = $true)]
|
|
[string]$file,
|
|
|
|
[Parameter(Mandatory = $false,Position = 1)]
|
|
[string]$CVAfile = $null,
|
|
|
|
[Parameter(Mandatory = $false,Position = 2)]
|
|
[string]$signedBy = $null,
|
|
|
|
[Parameter(Mandatory = $false,Position = 3)]
|
|
[switch]$Progress
|
|
|
|
)
|
|
|
|
if ($Progress.IsPresent) {
|
|
Write-Progress -Activity "Checking integrity of $file"
|
|
}
|
|
|
|
try {
|
|
|
|
if ($file.StartsWith('\\?\')) {
|
|
$c = Get-AuthenticodeSignature -LiteralPath $file
|
|
}
|
|
else {
|
|
$c = Get-AuthenticodeSignature -FilePath $file
|
|
}
|
|
|
|
if ($c.Status -ne "Valid") {
|
|
Write-Verbose ("$file is not signed or certificate is invalid.")
|
|
return $false
|
|
}
|
|
if ($signedBy) {
|
|
$signer = $c.SignerCertificate.Subject.Split(",")[0].trim().Split("=")[1]
|
|
|
|
if ($signer -ne $signedBy) {
|
|
Write-Verbose ("$file is not signed by $signedBy; it is signed by $signer, failing.")
|
|
return $false
|
|
}
|
|
else {
|
|
Write-Verbose ("$file is signed by $signedBy.")
|
|
# return $true
|
|
}
|
|
}
|
|
|
|
if ($CVAfile) {
|
|
Write-Verbose "Verifying '$file' using '$CVAFile'"
|
|
|
|
$targetFile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($file)
|
|
$targetCVA = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($CVAFile)
|
|
|
|
# Getting hash value of CVA
|
|
$read_file = Get-HPPrivateReadINI -File $targetCVA
|
|
$CVA_SHA256 = $read_file | Out-SoftpaqField -Field SoftPaqSHA256
|
|
|
|
Write-Verbose "CVA has SHA-256 hash '$CVA_SHA256'"
|
|
if ($CVA_SHA256 -and $CVA_SHA256.Length -eq 64) {
|
|
Write-Verbose 'Checking EXE SHA-256 hash'
|
|
$EXE_SHA256 = (Get-FileHash -Path $targetFile -Algorithm SHA256).Hash
|
|
Write-Verbose "EXE has SHA256 hash: $EXE_SHA256"
|
|
|
|
$sha256match = $CVA_SHA256 -eq $EXE_SHA256
|
|
Write-Verbose "SHA-256 matched: $sha256match"
|
|
return $sha256match
|
|
}
|
|
else {
|
|
Write-Verbose 'This CVA file has no checksum value'
|
|
return $false
|
|
}
|
|
}
|
|
|
|
# When only file is passed and it has valid signature
|
|
return $true
|
|
}
|
|
catch {
|
|
Write-Verbose "Had exception $($_.Exception.Message) during signature check"
|
|
return $false
|
|
}
|
|
finally {
|
|
if ($Progress.IsPresent) {
|
|
Write-Progress -Activity "Finished checking integrity of $file" -Completed
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-HPPrivateDeleteCachedItem {
|
|
[CmdletBinding()]
|
|
param([Parameter(Mandatory = $true)] $cab)
|
|
|
|
Invoke-HPPrivateSafeRemove -Path $cab
|
|
Invoke-HPPrivateSafeRemove -Path "$cab.dir" -Recurse
|
|
}
|
|
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-HPPrivateSafeRemove {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true,ValueFromPipelineByPropertyName = $true)] [string[]]$path,
|
|
[Parameter(Mandatory = $false)] [switch]$recurse
|
|
)
|
|
foreach ($p in $path) {
|
|
if (Test-Path $p) {
|
|
Write-Verbose "Removing $p"
|
|
Remove-Item $p -Recurse:$recurse
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-HPPrivateExpandCAB {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)] $cab,
|
|
[Parameter(Mandatory = $false)] $expectedFile # check for file inside expanded CAB
|
|
)
|
|
Write-Verbose "Expanding CAB $cab to $cab.dir"
|
|
|
|
$target = "$cab.dir"
|
|
Invoke-HPPrivateSafeRemove -Path $target -Recurse -Verbose:$VerbosePreference
|
|
Write-Verbose "Expanding $cab to $target"
|
|
$result = New-Item -Force $target -ItemType Directory
|
|
Write-Verbose "Created folder $result"
|
|
|
|
$shell = New-Object -ComObject "Shell.Application"
|
|
$exception = $null
|
|
try {
|
|
if (!$?) { $(throw "unable to create $comObject object") }
|
|
$sourceCab = $shell.Namespace($cab).items()
|
|
$DestinationFolder = $shell.Namespace($target)
|
|
$DestinationFolder.CopyHere($sourceCab)
|
|
}
|
|
catch {
|
|
$exception = $_.Exception
|
|
}
|
|
finally {
|
|
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$shell) | Out-Null
|
|
[System.GC]::Collect()
|
|
[System.GC]::WaitForPendingFinalizers()
|
|
}
|
|
|
|
if ($exception) {
|
|
throw "Failed to decompress $cab. $($exception.Message)."
|
|
}
|
|
|
|
if ($expectedFile){
|
|
|
|
$downloadedOk = Test-Path $expectedFile
|
|
if ($downloadedOk -eq $false) {
|
|
throw "Invalid cab file, did not find $expectedFile in contents"
|
|
}
|
|
|
|
return $expectedFile
|
|
}
|
|
|
|
}
|
|
|
|
|
|
# check if a download is needed, based on file existence and the remote last-modified time
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Test-HPPrivateIsDownloadNeeded {
|
|
[CmdletBinding()]
|
|
param([Parameter(Mandatory = $true)] $url,[Parameter(Mandatory = $true)] $file)
|
|
|
|
Write-Verbose "Checking if we need a new copy of $file"
|
|
|
|
# $c = [System.Net.ServicePointManager]::SecurityProtocol
|
|
# Write-Verbose ("Allowed HTTPS protocols: $c")
|
|
[System.Net.ServicePointManager]::SecurityProtocol = Get-HPPrivateAllowedHttpsProtocols
|
|
$userAgent = Get-HPPrivateUserAgent
|
|
|
|
# need to validate if $header can be generated, in other words if $url is legitimate
|
|
try {
|
|
$headers = (Invoke-WebRequest -Uri $url -UserAgent $userAgent -Method HEAD -UseBasicParsing).Headers
|
|
[datetime]$offered = [string]$headers["Last-Modified"]
|
|
Write-Verbose "File on server has timestamp $offered"
|
|
}
|
|
catch {
|
|
Write-Verbose "HTTPS request to $url failed: $($_.Exception.Message)"
|
|
throw
|
|
}
|
|
|
|
$exists = Test-Path -Path $file -PathType leaf
|
|
if ($exists -eq $false) {
|
|
Write-Verbose "Cached file $file does not exist. Need to download new file."
|
|
$offered
|
|
$true
|
|
}
|
|
else {
|
|
[datetime]$have = (Get-Item $file).CreationTime
|
|
$r = ($have -lt $offered)
|
|
Write-Verbose "Cached file exists and has timestamp $have. Need to download: $r"
|
|
|
|
$offered
|
|
$r
|
|
}
|
|
}
|
|
|
|
# check if script is running on ISE
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Test-HPPrivateIsRunningOnISE {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
return $null -ne $(Get-Variable -Name psISE -ErrorAction Ignore)
|
|
}
|
|
|
|
# check if long-path registry key is set
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Test-HPPrivateIsLongPathSupported {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
try {
|
|
return $(Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem\' -Name LongPathsEnabled).LongPathsEnabled -eq 1
|
|
}
|
|
catch {
|
|
Write-Verbose "Error accessing registry entry LongPathsEnabled: $($_.Exception.Message)"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
# check if the downloaded xml file is corrupted.
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Test-HPPrivateIsValidXmlFile {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)] $file
|
|
)
|
|
|
|
if (-not (Test-Path -Path $file)) {
|
|
Write-Verbose "File $file does not exist."
|
|
return $false
|
|
}
|
|
|
|
# Check for Load or Parse errors when loading the XML file.
|
|
$xml = New-Object System.Xml.XmlDocument
|
|
try {
|
|
$xml.Load($file)
|
|
return $true
|
|
}
|
|
catch [System.Xml.XmlException]{
|
|
Write-Verbose "Invalid XML file $file"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
# get temporary file name
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateTempFileName {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
$tempFileName = [System.IO.Path]::GetTempFileName()
|
|
$tempFileName = $tempFileName.TrimEnd('.tmp')
|
|
$tempFileName = $($tempFileName -Split '\\')[-1]
|
|
return $tempFileName
|
|
}
|
|
|
|
# get hp temporary file path
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateTempPath {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
$tempPath = [System.IO.Path]::GetTempPath()
|
|
$tempPath = Join-Path -Path $tempPath -ChildPath 'hp'
|
|
return [System.IO.DirectoryInfo]$tempPath
|
|
}
|
|
|
|
# get temporary file path
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateTempFilePath {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
[System.IO.DirectoryInfo]$tempPath = Join-Path -Path $([System.IO.Path]::GetTempPath()) -ChildPath 'hp'
|
|
$tempFileName = Get-HPPrivateTempFileName
|
|
return Join-Path -Path $tempPath.FullName -ChildPath $tempFileName
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateUserAgent () {
|
|
"CMSL $($MyInvocation.MyCommand.Module.Version)"
|
|
}
|
|
|
|
# calculates CurrentOSVer
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function GetCurrentOSVer {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
try {
|
|
$result = [string](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name DisplayVersion | Select-Object DisplayVersion).DisplayVersion
|
|
|
|
if ($result -match '[0-9]{2}[hH][0-9]') {
|
|
$bits = $result.substring(0,2)
|
|
if ($bits -ge 21) {
|
|
# for DisplayVersion >= 21XX, use the DisplayVersion as OSVer
|
|
# convert OSVer to lower since the reference files have "21h1" in file name
|
|
return $result.ToLower()
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Write-Verbose "Display Version not found. Fallback to ReleaseId."
|
|
}
|
|
|
|
# If DisplayVersion isn't found or DisplayVersion < 21XX, use ReleaseId instead
|
|
$result = [string](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name ReleaseID | Select-Object ReleaseID).ReleaseId
|
|
return $result
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateCurrentDisplayOSVer {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
if ([string][System.Environment]::OSVersion.Version.Build -gt 19041) {
|
|
$result = [string](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name DisplayVersion | Select-Object DisplayVersion).DisplayVersion
|
|
}
|
|
else {
|
|
$result = [string](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name ReleaseID | Select-Object ReleaseID).ReleaseId
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function validateWmiResult {
|
|
[CmdletBinding()]
|
|
param([int]$code,[int]$category = 0xff)
|
|
|
|
Write-Verbose "Validating error code $code for facility $category"
|
|
switch ($code) {
|
|
0 {}
|
|
0xea {}
|
|
6 { throw [NotSupportedException]"Operation could not be completed. Please ensure this is a supported HP system." }
|
|
5 { throw [ArgumentException]"Method called with invalid parameters." }
|
|
4 { throw [UnauthorizedAccessException]"The caller does not have permissions to perform this operation." }
|
|
0x1000 { throw [SystemException]"HP Secure Platform Management is not provisioned." }
|
|
0x1c { throw [SystemException]"The request was not accepted by the BIOS." }
|
|
default { validateWmiResultInCategory -Category $category -code $code }
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function validateWmiResultInCategory {
|
|
[CmdletBinding()]
|
|
param([int]$category,[int]$code)
|
|
|
|
switch ($category) {
|
|
1 {
|
|
switch ($code) {
|
|
0x40 { throw [NotSupportedException]"This system does not support firmware logs." }
|
|
0x41 { throw [System.TimeoutException]"Call has timed out." }
|
|
default { throw [SystemException]"An unknown error $code has occured." }
|
|
}
|
|
}
|
|
2 {
|
|
switch ($code) {
|
|
0x0b { throw [UnauthorizedAccessException]"The caller does not have permissions to perform this operation." }
|
|
0x0e { throw [UnauthorizedAccessException]"The operation could not be completed, possibly due to a bios password mismatch?" }
|
|
0x0010 { throw [SystemException]"Invalid flash offset." }
|
|
0x0012 { throw [SystemException]"Invalid flash checksum" }
|
|
0x0013 { throw [InvalidOperationException]"Flash-in-progress error" }
|
|
0x0014 { throw [InvalidOperationException]"Flash-in-progress not set" }
|
|
default { throw [SystemException]"An unknown error $code has occured." }
|
|
}
|
|
}
|
|
3 {
|
|
switch ($code) {
|
|
# this facility doesn't define specific codes
|
|
default { throw [SystemException]"An unknown error $code has occured." }
|
|
}
|
|
}
|
|
4 {
|
|
switch ($code) {
|
|
0x0b { throw [UnauthorizedAccessException]"The caller does not have permissions to perform this operation." }
|
|
0x03 { throw [NotSupportedException]"This system does not support HP Secure Platform Management or a hardware option is missing." }
|
|
0x1001 { throw [SystemException]"HP Secure Platform Management is already provisioned." }
|
|
0x1002 { throw [SystemException]"HP Secure Platform Management is in use. Deprovision all features that use the HP Secure Platform Management first." }
|
|
default { throw [SystemException]"An unknown error $code has occured." }
|
|
}
|
|
}
|
|
5 {
|
|
switch ($code) {
|
|
0x03 { throw [NotSupportedException]"This system does not support HP Sure Recover or there is a configuration issue." }
|
|
default { throw [SystemException]"An unknown error $code has occured." }
|
|
}
|
|
}
|
|
default {
|
|
throw [SystemException]"An unknown error $code has occured."
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Test-HPPrivateCustomResult {
|
|
[CmdletBinding()]
|
|
param([int]$result,[int]$mi_result,[int]$category)
|
|
Write-Verbose ("Checking result={0:x8}, mi_result={1:x8}, category={2:x4}" -f $result,$mi_result,$category)
|
|
switch ($result) {
|
|
0 { Write-Verbose ("Operation succeeded.") }
|
|
0x80000711 { validateWmiResult -code $mi_result -Category $category } # E_DFM_FAILED_WITH_EXTENDED_ERROR
|
|
0x80000710 { throw [NotSupportedException]"Current platform does not support this operation." } # E_DFM_FEATURE_NOT_SUPPORTED
|
|
0x8000070b { throw [System.IO.IOException]"Firmware file could not be read." } # E_DFM_FILE_ACCESS_FAILURE
|
|
0x8000070e { throw [InvalidOperationException]"Firmware file is too long for expected flash type." } # E_DFM_FLASH_BUR_INPUT_DATA_TOO_LARGE
|
|
0x80000712 { throw [InvalidOperationException]"The firmware does not mach the target platform." } # E_DFM_WRONG_FLASH_FILE
|
|
0x80000714 { throw [OutOfMemoryException]"A memory allocation failed. The system may be out of memory." } # E_DFM_ALLOC_FAILED
|
|
0x80000715 { throw [InvalidOperationException]"Password length is not valid." } # E_DFM_PASSWORD_SIZE_INVALID
|
|
0x8000071a { throw [System.ArgumentException]"Invalid parameter for HP Sure View API" }
|
|
1392 { throw [System.IO.IOException]"Could not copy the file to the system partition." } # ERROR_FILE_CORRUPT
|
|
234 { Write-Verbose ("Operation succeeded.") } # MORE_DATA
|
|
default { throw [ComponentModel.Win32Exception]$result }
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Convert-HPPrivateObjectToBytes {
|
|
[CmdletBinding()]
|
|
param($obj)
|
|
|
|
$mem = $null
|
|
$length = 0
|
|
$bytes = $()
|
|
|
|
|
|
Write-Verbose "Converting object of type $($obj.Gettype()) to byte array"
|
|
try {
|
|
$length = [System.Runtime.InteropServices.Marshal]::SizeOf($obj)
|
|
$bytes = New-Object byte[] $length
|
|
Write-Verbose "Converting object of type $($obj.Gettype()) is $length bytes"
|
|
$mem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($length)
|
|
|
|
[System.Runtime.InteropServices.Marshal]::StructureToPtr($obj,$mem,$true)
|
|
[System.Runtime.InteropServices.Marshal]::Copy($mem,$bytes,0,$length)
|
|
($bytes,$length)
|
|
}
|
|
finally {
|
|
# Free the memory we allocated for the struct value
|
|
if ($mem) {
|
|
Write-Verbose "Freeing allocated memory"
|
|
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($mem)
|
|
}
|
|
}
|
|
Write-Verbose "Conversion complete."
|
|
|
|
}
|
|
|
|
|
|
#region Cryptography
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivatePublicKeyCoalesce {
|
|
[CmdletBinding()]
|
|
param(
|
|
[System.IO.FileInfo]$file,
|
|
[psobject]$key
|
|
)
|
|
|
|
if ($file) {
|
|
$efile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($file)
|
|
Write-Verbose "Coalescing to FILE PEM $efile"
|
|
$modulus = New-Object arr4k_t
|
|
$modulus_size = 4096
|
|
$exponent = 0
|
|
$mi_result = 0
|
|
|
|
$c = '[X509Utilities]::get_public_key_from_pem' + (Test-OSBitness) + '($efile,[ref]$modulus, [ref]$modulus_size, [ref]$exponent);'
|
|
$result = Invoke-Expression -Command $c
|
|
Test-HPPrivateCustomResult -result $result -mi_result $mi_result -Category 0x04
|
|
New-Object -TypeName PSObject -Property @{
|
|
Modulus = $modulus.raw[0..($modulus_size - 1)]
|
|
Exponent = $exponent
|
|
}
|
|
|
|
}
|
|
else {
|
|
Write-Verbose "Coalescing to binary PEM"
|
|
$key
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateX509CertCoalesce {
|
|
[CmdletBinding()]
|
|
param(
|
|
[System.IO.FileInfo]$file,
|
|
[System.Security.Cryptography.X509Certificates.X509Certificate2]$cert,
|
|
[string]$password
|
|
)
|
|
$param = @{}
|
|
if ($password) {
|
|
$param.Add("Password",(ConvertTo-SecureString -AsPlainText -Force $password))
|
|
}
|
|
if ($file) {
|
|
$efile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($file)
|
|
Write-Verbose "Coalescing to FILE certificate $efile"
|
|
$param.Add("FileName",$efile)
|
|
Get-HPPrivatePublicKeyCertificateFromPFX @param -Verbose:$VerbosePreference
|
|
}
|
|
else {
|
|
Write-Verbose "Coalescing to binary certificate"
|
|
$key = $cert.PublicKey.key
|
|
$parameters = $key.ExportParameters($false);
|
|
$mod_reversed = $parameters.Modulus
|
|
[array]::Reverse($mod_reversed)
|
|
New-Object -TypeName PSObject -Property @{
|
|
Full = $Cert
|
|
Certificate = $cert.Export('Cert')
|
|
Modulus = $mod_reversed
|
|
Exponent = $parameters.Exponent
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
# get the PK from a PFX file
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivatePublicKeyCertificateFromPFX {
|
|
[CmdletBinding(DefaultParameterSetName = "FF")]
|
|
param(
|
|
[Parameter(Mandatory = $true,Position = 0)]
|
|
[string]$FileName,
|
|
|
|
[Parameter(Mandatory = $false,Position = 1)]
|
|
[securestring]$Password
|
|
)
|
|
|
|
$certfile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($FileName)
|
|
if (-not (Test-Path -PathType leaf -Path $certfile)) {
|
|
throw [System.IO.FileNotFoundException]"Certificate file '$certfile' could not be found"
|
|
}
|
|
Write-Verbose "Extracting public key from '$certfile'."
|
|
|
|
try {
|
|
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList ($certfile,$Password,'Exportable')
|
|
$key = $cert.PublicKey.Key
|
|
$parameters = $key.ExportParameters($false);
|
|
|
|
$mod_reversed = $parameters.Modulus
|
|
[array]::Reverse($mod_reversed)
|
|
New-Object -TypeName PSObject -Property @{
|
|
Full = $cert
|
|
Certificate = $cert.Export('Cert')
|
|
Modulus = $mod_reversed
|
|
Exponent = $parameters.Exponent
|
|
}
|
|
}
|
|
finally {
|
|
#$cert.Dispose();
|
|
#$cert = $null
|
|
}
|
|
|
|
}
|
|
|
|
# sign a byte array with a certificate provided in $Filename
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-HPPrivateSignData {
|
|
[CmdletBinding()]
|
|
param(
|
|
[System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate,
|
|
[byte[]]$Data
|
|
)
|
|
$privKey = $Certificate.PrivateKey
|
|
if ($null -eq $privKey) {
|
|
Write-Error "Please provide an exportable key in the PFX file"
|
|
}
|
|
$params = $privKey.ExportParameters($true)
|
|
$cspParams = New-Object System.Security.Cryptography.CspParameters (24,"Microsoft Enhanced RSA and AES Cryptographic Provider")
|
|
$enhancedSignCsp = New-Object System.Security.Cryptography.RSACryptoServiceProvider ($cspParams)
|
|
$enhancedSignCsp.ImportParameters($params)
|
|
|
|
$result = $enhancedSignCsp.SignData($Data,[System.Security.Cryptography.HashAlgorithmName]::SHA256,[System.Security.Cryptography.RSASignaturePadding]::Pkcs1)
|
|
[array]::Reverse($result)
|
|
return $result
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateHash {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true,Position = 0)] [byte[]]$data,
|
|
[Parameter(Mandatory = $false,Position = 1)] [string]$algo = "SHA256"
|
|
)
|
|
$cp = [System.Security.Cryptography.HashAlgorithm]::Create($algo)
|
|
try {
|
|
$result = $cp.ComputeHash($data)
|
|
}
|
|
finally {
|
|
$cp.Dispose()
|
|
}
|
|
$result
|
|
|
|
}
|
|
#endregion
|
|
|
|
# Downloads files for when OfflineCacheMode is Enable
|
|
# If -platform is present : Downloads Advisory Data Files (XXXX_cds.cab) where XXXX is platform ID.
|
|
# also downloads the platform List
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateOfflineCacheFiles {
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$url,
|
|
[string]$filename,
|
|
[System.IO.DirectoryInfo]$cacheDirOffline = [System.IO.Path]::GetTempPath() + "hp",
|
|
[switch]$expand
|
|
)
|
|
|
|
$file = Get-HPPrivateTemporaryFileName -FileName $filename -cacheDir $cacheDirOffline
|
|
$filename = $filename.Replace("cab","xml")
|
|
$downloadedFile = "$file.dir\$filename"
|
|
|
|
Write-Verbose "Checking if $url is available locally."
|
|
try {
|
|
$result = Test-HPPrivateIsDownloadNeeded -url $url -File $file -Verbose:$VerbosePreference
|
|
}
|
|
catch {
|
|
throw [System.Net.WebException]"Could not find data file $url"
|
|
}
|
|
|
|
if ($result[1] -eq $true) {
|
|
Write-Verbose "$url is not local or is out of date, will download."
|
|
Write-Verbose "Cleaning cached data and downloading the data file."
|
|
Invoke-HPPrivateDeleteCachedItem -cab $file
|
|
Invoke-HPPrivateDownloadFile -url $url -Target $file -Verbose:$VerbosePreference
|
|
(Get-Item $file).CreationTime = ($result[0])
|
|
(Get-Item $file).LastWriteTime = ($result[0])
|
|
}
|
|
|
|
if ($expand.IsPresent) {
|
|
# Need to make sure that the expanded data file exists and is not corrupted.
|
|
# Otherwise, expand the cab file.
|
|
if (-not (Test-Path $downloadedFile) -or (-not (Test-HPPrivateIsValidXmlFile -File $downloadedFile))) {
|
|
Write-Verbose "Extracting the data file and looking for $downloadedFile."
|
|
$file = Invoke-HPPrivateExpandCAB -cab $file -expectedFile $downloadedFile
|
|
}
|
|
}
|
|
return $downloadedFile
|
|
}
|
|
|
|
# build URL for a remote item
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateItemUrl (
|
|
[CmdletBinding()]
|
|
[int]$Number,
|
|
[string]$Ext,
|
|
[string]$Url) {
|
|
if ($url) {
|
|
return "$url/sp$number.$ext"
|
|
}
|
|
|
|
[string]$baseNumber = $number.ToString()
|
|
[int]$last3Value = [int]($baseNumber.substring($baseNumber.Length - 3))
|
|
[int]$blockStart = [int]($baseNumber.substring(0,$baseNumber.Length - 3))
|
|
|
|
[string]$block = ""
|
|
[int]$blockEnd = $blockStart
|
|
|
|
if ($last3Value -gt 500) {
|
|
$blockEnd += 1
|
|
$block = "$($blockStart)501-$($blockEnd)000"
|
|
}
|
|
else {
|
|
if ($last3Value -eq 0) {
|
|
$blockStart -= 1
|
|
$block = "$($blockStart)501-$($blockEnd)000"
|
|
}
|
|
else {
|
|
$block = "$($blockStart)001-$($blockStart)500"
|
|
}
|
|
}
|
|
|
|
return "https://ftp.hp.com/pub/softpaq/sp$block/sp$number.$ext"
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function biosErrorCodesToString ($code) {
|
|
switch ($code) {
|
|
0 { return "OK" }
|
|
1 { return "Not Supported" }
|
|
2 { return "Unspecified error" }
|
|
3 { return "Operation timed out" }
|
|
4 { return "Operation failed or setting name is invalid" }
|
|
5 { return "Invalid parameter" }
|
|
6 { return "Access denied or incorrect password" }
|
|
7 { return "Bios user already exists" }
|
|
8 { return "Bios user not present" }
|
|
9 { return "Bios user name too long" }
|
|
10 { return "Password policy not met" }
|
|
11 { return "Invalid keyboard layout" }
|
|
12 { return "Too many users" }
|
|
32768 { return "Security or password policy not met" }
|
|
default { return "Unknown error: $code" }
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function getBiosSettingInterface {
|
|
[CmdletBinding(DefaultParameterSetName = 'nNwSession')]
|
|
param(
|
|
[Parameter(ParameterSetName = 'NewSession',Position = 0,Mandatory = $false)]
|
|
[string]$Target = ".",
|
|
[Parameter(ParameterSetName = 'ReuseSession',Position = 1,Mandatory = $true)]
|
|
[CimSession]$CimSession
|
|
)
|
|
$defaultAction = $ErrorActionPreference
|
|
$ns = getNamespace
|
|
$ErrorActionPreference = "Stop";
|
|
|
|
try {
|
|
Write-Verbose "Getting BIOS interface from '$target' for namespace '$ns'"
|
|
$params = @{
|
|
Namespace = $ns
|
|
Class = "HPBIOS_BIOSSettingInterface"
|
|
}
|
|
|
|
if ($CimSession) {
|
|
$params.Add("CimSession",$CimSession)
|
|
}
|
|
|
|
if ($Target -and ($target -ne ".") -and -not $CimSession) {
|
|
$params.Add("ComputerName",$Target)
|
|
}
|
|
|
|
|
|
$result = Get-CimInstance @params -ErrorAction stop
|
|
if (-not $result) { throw [System.EntryPointNotFoundException]"Setting interface not found" }
|
|
}
|
|
catch {
|
|
Write-Error "Method failed: $($_.Exception.Message)" -ErrorAction stop
|
|
}
|
|
finally {
|
|
$ErrorActionPreference = $defaultAction
|
|
}
|
|
$result
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function getNamespace {
|
|
[CmdletBinding()]
|
|
param()
|
|
[string]$c = [environment]::GetEnvironmentVariable("HP_BIOS_NAMESPACE","User")
|
|
if (-not $c) {
|
|
return "root\HP\InstrumentedBIOS"
|
|
}
|
|
Write-Verbose ("Default BIOS namespace is overwritten via HP_BIOS_NAMESPACE Variable, to $c. This should only happen during development.")
|
|
return $c
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSecurePlatformIsProvisioned
|
|
{
|
|
[boolean]$status = $false
|
|
|
|
try {
|
|
$result = Invoke-Expression -Command 'Get-HPSecurePlatformState'
|
|
|
|
if ($result.State -eq "Provisioned") {
|
|
$status = $true
|
|
}
|
|
}
|
|
catch {}
|
|
|
|
return $status
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateFileContent {
|
|
[CmdletBinding()]
|
|
param([System.IO.FileInfo]$File)
|
|
|
|
$f = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($File)
|
|
|
|
# Default encoding for PS5.1 is Default meaning the encoding that correpsonds to the system's active code page
|
|
# Default encoding for PS7.3 is utf8NoBOM
|
|
[string]$content = Get-Content -Encoding UTF8 -Raw -Path $f -ErrorAction Stop
|
|
|
|
return $content
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromPayload {
|
|
[CmdletBinding()]
|
|
param([string]$Content)
|
|
$payload = $Content | ConvertFrom-Json
|
|
|
|
if ($payload.purpose -ne "hp:sureadmin:biossettingslist") {
|
|
throw "The payload should be generated by New-HPSureAdminBIOSSettingValuePayload function"
|
|
}
|
|
|
|
$data = [System.Text.Encoding]::UTF8.GetString($payload.Data)
|
|
$settingsList = (Get-HPPrivateSettingsFromJson $data)
|
|
|
|
return $settingsList
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromPayloadFile {
|
|
[CmdletBinding()]
|
|
param([System.IO.FileInfo]$File)
|
|
$content = Get-HPPrivateFileContent $File
|
|
return Get-HPPrivateSettingsFromPayload $content
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromJsonFile {
|
|
[CmdletBinding()]
|
|
param([System.IO.FileInfo]$File)
|
|
[string]$content = Get-HPPrivateFileContent $File
|
|
return (Get-HPPrivateSettingsFromJson $content)
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromJson {
|
|
[CmdletBinding()]
|
|
param([string]$Content)
|
|
$list = $Content | ConvertFrom-Json
|
|
|
|
$settingsList = New-Object System.Collections.Generic.List[SureAdminSetting]
|
|
foreach ($item in $list) {
|
|
$setting = New-Object -TypeName SureAdminSetting
|
|
$setting.Name = $item.Name
|
|
$setting.Value = $item.Value
|
|
if ("AuthString" -in $item.PSObject.Properties.Name) {
|
|
$setting.AuthString = $item.AuthString
|
|
}
|
|
$settingsList.Add($setting)
|
|
}
|
|
|
|
return $settingsList
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromBcuFile {
|
|
[CmdletBinding()]
|
|
param([System.IO.FileInfo]$File)
|
|
$list = [ordered]@{}
|
|
$auth = @{}
|
|
$currset = ""
|
|
|
|
Write-Verbose "Reading from file: $File"
|
|
switch -regex -File $File {
|
|
|
|
'^;Signature=<BEAM/>.*' {
|
|
# keeping compatibility with BCU tool
|
|
$c = $matches[0].trim()
|
|
$auth[$currset] = $c.substring(11)
|
|
}
|
|
|
|
'^;AuthString=<BEAM/>.*' {
|
|
$c = $matches[0].trim()
|
|
$auth[$currset] = $c.substring(12)
|
|
}
|
|
|
|
'^\S.*$' {
|
|
$currset = $matches[0].trim()
|
|
if ($currset -ne "BIOSConfig 1.0" -and -not $currset.StartsWith(";")) {
|
|
$list[$currset] = New-Object System.Collections.Generic.List[System.String]
|
|
}
|
|
}
|
|
|
|
'^\s.*$' {
|
|
# value (indented)
|
|
$c = $matches[0].trim()
|
|
$list[$currset].Add($c)
|
|
}
|
|
}
|
|
|
|
$settingsList = New-Object System.Collections.Generic.List[SureAdminSetting]
|
|
foreach ($s in $list.keys) {
|
|
$setting = New-Object -TypeName SureAdminSetting
|
|
$setting.Name = $s
|
|
$setting.Value = Get-HPPrivateDesiredValue -Value $list[$s]
|
|
if ($auth.ContainsKey($s)) {
|
|
$setting.AuthString = $auth[$s]
|
|
}
|
|
$settingsList.Add($setting)
|
|
}
|
|
|
|
return $settingsList
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateDesiredValue {
|
|
[CmdletBinding()]
|
|
param($Value)
|
|
|
|
$desired = $null
|
|
|
|
$list = $Value -split ','
|
|
foreach ($v in $list) {
|
|
|
|
if ($v.StartsWith("*")) {
|
|
# enum
|
|
$desired = $v.substring(1)
|
|
break
|
|
}
|
|
}
|
|
|
|
if (-not $desired) {
|
|
# not an enum
|
|
if ($list.Count -eq 1) {
|
|
$desired = $list # a string or int
|
|
}
|
|
else {
|
|
$desired = $list -join ',' # an ordered list
|
|
}
|
|
}
|
|
|
|
return $desired
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromCsvFile {
|
|
[CmdletBinding()]
|
|
param([System.IO.FileInfo]$File)
|
|
Write-Verbose "Reading CSV"
|
|
$content = Get-HPPrivateFileContent $File
|
|
$items = $content | ConvertFrom-Csv
|
|
|
|
$settingsList = New-Object System.Collections.Generic.List[SureAdminSetting]
|
|
|
|
foreach ($item in $items) {
|
|
$setting = New-Object -TypeName SureAdminSetting
|
|
$setting.Name = $item.Name
|
|
$setting.Value = (Get-HPPrivateDesiredValue $item.CURRENT_VALUE)
|
|
if ("AUTHSTRING" -in $item.PSObject.Properties.Name) {
|
|
$setting.AuthString = $item.AuthString
|
|
}
|
|
$settingsList.Add($setting)
|
|
}
|
|
|
|
return $settingsList
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromXmlFile {
|
|
[CmdletBinding()]
|
|
param([System.IO.FileInfo]$File)
|
|
Write-Verbose "Reading XML"
|
|
$content = Get-HPPrivateFileContent $File
|
|
|
|
try {
|
|
$entries = ([xml]$content).ImagePal.BIOSSettings.BIOSSetting
|
|
$settingsList = New-Object System.Collections.Generic.List[SureAdminSetting]
|
|
|
|
foreach ($item in $entries) {
|
|
$setting = New-Object -TypeName SureAdminSetting
|
|
$setting.Name = $item.Name
|
|
$setting.Value = $item.Value
|
|
if ("AuthString" -in $item.PSObject.Properties.Name) {
|
|
# The XML parser adds an unwanted space in the tag BEAM
|
|
$setting.AuthString = $item.AuthString.InnerXml -replace "<BEAM />","<BEAM/>"
|
|
}
|
|
$settingsList.Add($setting)
|
|
}
|
|
}
|
|
catch [System.Management.Automation.PropertyNotFoundException]{
|
|
throw [System.FormatException]'Invalid XML file.'
|
|
}
|
|
|
|
return $settingsList
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateSettingsFromFile {
|
|
[CmdletBinding()]
|
|
param(
|
|
[System.IO.FileInfo]$FileName,
|
|
[string]$Format
|
|
)
|
|
[System.Collections.Generic.List[SureAdminSetting]]$settingsList = $null
|
|
|
|
switch ($Format) {
|
|
{ $_ -eq 'CSV' } { $settingsList = Get-HPPrivateSettingsFromCsvFile $FileName }
|
|
{ $_ -eq 'XML' } { $settingsList = Get-HPPrivateSettingsFromXmlFile $FileName }
|
|
{ $_ -eq 'JSON' } { $settingsList = Get-HPPrivateSettingsFromJsonFile $FileName }
|
|
{ $_ -eq 'BCU' } { $settingsList = Get-HPPrivateSettingsFromBcuFile $FileName }
|
|
{ $_ -eq 'payload' } { $settingsList = Get-HPPrivateSettingsFromPayloadFile $FileName }
|
|
default { throw [System.FormatException]"Format specifier not provided, and could not determine format from file extension" }
|
|
}
|
|
|
|
return $settingsList
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Invoke-HPPrivateSetSetting {
|
|
[CmdletBinding(DefaultParameterSetName = 'NewSession')]
|
|
param(
|
|
[Parameter(ParameterSetName = 'NewSession',Position = 0,Mandatory = $true)]
|
|
[Parameter(ParameterSetName = 'ReuseSession',Position = 0,Mandatory = $true)]
|
|
[SureAdminSetting]$Setting,
|
|
[Parameter(ParameterSetName = 'NewSession',Position = 1,Mandatory = $false)]
|
|
[Parameter(ParameterSetName = 'ReuseSession',Position = 1,Mandatory = $false)]
|
|
[string]$Password,
|
|
[Parameter(ParameterSetName = 'NewSession',Position = 2,Mandatory = $false)]
|
|
[Parameter(ParameterSetName = 'ReuseSession',Position = 2,Mandatory = $false)]
|
|
$ErrorHandling = 0,
|
|
[Parameter(ParameterSetName = 'NewSession',Position = 3,Mandatory = $false)]
|
|
[Parameter(ParameterSetName = 'ReuseSession',Position = 3,Mandatory = $false)]
|
|
[Alias('Target')]
|
|
[string]$ComputerName = ".",
|
|
[Parameter(ParameterSetName = 'ReuseSession',Position = 4,Mandatory = $true)]
|
|
[CimSession]$CimSession,
|
|
[Parameter(ParameterSetName = 'NewSession',Position = 5,Mandatory = $false)]
|
|
[Parameter(ParameterSetName = 'ReuseSession',Position = 5,Mandatory = $false)]
|
|
[ref]$SingleSettingFailCounter
|
|
)
|
|
$readOnly = 0
|
|
$notFound = 0
|
|
$alreadySet = 0
|
|
$localCounter = 0
|
|
|
|
$s = $null
|
|
if (-not $CimSession) { $CimSession = newCimSession -Target $ComputerName }
|
|
|
|
try {
|
|
$s = Get-HPBIOSSetting -Name $Setting.Name -CimSession $CimSession -ErrorAction stop
|
|
}
|
|
catch {
|
|
$notFound = 1
|
|
$SingleSettingFailCounter.Value = 0 #matching BCU, even if setting not found exit with 0
|
|
$err = $PSItem.ToString()
|
|
|
|
Write-Verbose "'$Setting.Name': $err"
|
|
switch ($ErrorHandling) {
|
|
0 { throw $err }
|
|
1 { Write-Warning -Message "$err" }
|
|
2 { Write-Verbose "Setting '$Setting.Name' could not be set, but ErrorHandling was set to 2 so error is quietly ignored" }
|
|
}
|
|
return $readOnly,$notFound,$alreadySet,$SingleSettingFailCounter.Value
|
|
}
|
|
|
|
if ($s) {
|
|
switch ($s.CimClass.CimClassName) {
|
|
"HPBIOS_BIOSEnumeration" {
|
|
if ($s.CurrentValue -eq $Setting.Value) {
|
|
$alreadySet = 1
|
|
Write-Host "Setting $($Setting.Name) is already set to $($Setting.Value)"
|
|
}
|
|
}
|
|
default {
|
|
if ($s.Value -eq $Setting.Value) {
|
|
$alreadySet = 1
|
|
Write-Host "Setting $($Setting.Name) is already set to $($Setting.Value)"
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($alreadySet -eq $false) {
|
|
if ($s.IsReadOnly -eq 1) { $readOnly = 1 }
|
|
else {
|
|
if ($ErrorHandling -ne 1) {
|
|
Set-HPPrivateBIOSSetting -Setting $setting -password $Password -CimSession $CimSession -SkipPrecheck $true -ErrorHandling $ErrorHandling -actualSetFailCounter ([ref]$localCounter) -Verbose:$VerbosePreference
|
|
$SingleSettingFailCounter.Value = $localCounter
|
|
}
|
|
else {
|
|
try {
|
|
Set-HPPrivateBIOSSetting -Setting $setting -password $Password -CimSession $CimSession -SkipPrecheck $true -ErrorHandling $ErrorHandling -actualSetFailCounter ([ref]$localCounter) -Verbose:$VerbosePreference
|
|
}
|
|
catch {
|
|
$SingleSettingFailCounter.Value = $localCounter
|
|
$err = $PSItem.ToString()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $readOnly,$notFound,$alreadySet,$SingleSettingFailCounter.Value
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateUseAuthString {
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$SettingName
|
|
)
|
|
|
|
if ((Get-HPPrivateIsSureAdminEnabled) -eq $true -or $SettingName -eq "Enhanced BIOS Authentication Mode") {
|
|
return $true
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Set-HPPrivateBIOSSetting {
|
|
[CmdletBinding()]
|
|
param(
|
|
$Setting,
|
|
[string]$ComputerName = ".",
|
|
[CimSession]$CimSession,
|
|
[switch]$SkipPrecheck,
|
|
[AllowEmptyString()]
|
|
[string]$Password,
|
|
$ErrorHandling,
|
|
[Parameter(Mandatory = $false)]
|
|
[ref]$actualSetFailCounter
|
|
)
|
|
|
|
$localCounterForSet = 0
|
|
|
|
if ($CimSession -eq $null) {
|
|
$CimSession = newCimSession -Target $ComputerName
|
|
}
|
|
|
|
$Name = $Setting.Name
|
|
$Value = $Setting.Value
|
|
if ($Setting.AuthString -and (Get-HPPrivateUseAuthString -SettingName $Name) -eq $true) {
|
|
$authorization = $Setting.AuthString
|
|
Write-Verbose "Using authorization string"
|
|
}
|
|
else {
|
|
$authorization = "<utf-16/>" + $Password
|
|
Write-Verbose "Using BIOS Setup password"
|
|
}
|
|
|
|
if ($SkipPrecheck.IsPresent) {
|
|
Write-Verbose "Skipping pre-check"
|
|
|
|
if ($Name -eq "Setup Password" -or $Name -eq "Power-On Password") {
|
|
$type = 'HPBIOS_BIOSPassword'
|
|
}
|
|
else {
|
|
$type = 'HPBIOS_Setting'
|
|
}
|
|
}
|
|
else {
|
|
$obj = Get-HPBIOSSetting -Name $name -CimSession $CimSession -ErrorAction stop
|
|
$type = $obj.CimClass.CimClassName
|
|
}
|
|
|
|
$c = getBiosSettingInterface -CimSession $CimSession
|
|
switch ($type) {
|
|
{ $_ -eq 'HPBIOS_BIOSPassword' } {
|
|
Write-Verbose "Setting Password setting '$Name' on '$ComputerName'"
|
|
$Arguments = @{
|
|
Name = $Name
|
|
Value = "<utf-16/>" + [string]$Value
|
|
Password = $authorization
|
|
}
|
|
$r = Invoke-CimMethod -InputObject $c -MethodName SetBiosSetting -Arguments $Arguments
|
|
}
|
|
|
|
default {
|
|
Write-Verbose "Setting HP BIOS Setting '$Name' to value '$Value' on '$ComputerName'"
|
|
$Arguments = @{
|
|
Name = $Name
|
|
Value = [string]$Value
|
|
Password = $authorization;
|
|
}
|
|
$r = Invoke-CimMethod -InputObject $c -MethodName SetBiosSetting -Arguments $Arguments
|
|
}
|
|
}
|
|
|
|
if ($r.Return -eq 0) {
|
|
$message = "HP BIOS Setting $Name successfully set"
|
|
if ($Name -ne "Setup Password" -and $Name -ne "Power-On Password") {
|
|
$message += " to $Value"
|
|
}
|
|
Write-Host -ForegroundColor Green $message
|
|
}
|
|
if ($r.Return -ne 0) {
|
|
|
|
$localCounterForSet++
|
|
|
|
if ($r.Return -eq 5) {
|
|
Write-Host -ForegroundColor Magenta "Operation failed. Please make sure that you are passing a valid value."
|
|
Write-Host -ForegroundColor Magenta "Some variable names or values may be case sensitive."
|
|
}
|
|
$Err = "$(biosErrorCodesToString($r.Return))"
|
|
if ($ErrorHandling -eq 1) {
|
|
Write-Host -ForegroundColor Red "$($setting.Name) failed to set due to $Err"
|
|
$actualSetFailCounter.Value = $localCounterForSet
|
|
}
|
|
throw $Err
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateIsSureAdminEnabled {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
[boolean]$status = $false
|
|
|
|
if ((Get-HPPrivateIsSureAdminSupported) -eq $true) {
|
|
try {
|
|
$mode = (Get-HPBIOSSettingValue -Name "Enhanced BIOS Authentication Mode")
|
|
if ($mode -eq "Enable") {
|
|
$status = $true
|
|
}
|
|
}
|
|
catch {}
|
|
}
|
|
|
|
return $status
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Get-HPPrivateIsSureAdminSupported {
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
[boolean]$status = $false
|
|
try {
|
|
$mode = (Get-HPBIOSSettingValue -Name "Enhanced BIOS Authentication Mode")
|
|
$status = $true
|
|
}
|
|
catch {}
|
|
|
|
return $status
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function newCimSession () {
|
|
[CmdletBinding()]
|
|
param
|
|
(
|
|
[Parameter(Position = 0)] $SkipTestConnection = $true,
|
|
[Parameter(Position = 1)] $Protocol = 'DCOM',
|
|
[Parameter(Position = 2)] $target = '.',
|
|
[Parameter(Position = 3)] $SessionName = 'CMSLCimSession'
|
|
)
|
|
|
|
Write-Verbose "Creating new CimSession (Protocol= $Protocol, Computer=$Target)"
|
|
$opts = New-CimSessionOption -Protocol $Protocol
|
|
|
|
$params = @{
|
|
Name = $SessionName
|
|
SkipTestConnection = $SkipTestConnection
|
|
SessionOption = $opts
|
|
}
|
|
if ($Target -and ($Target -ne ".")) {
|
|
$params.Add("ComputerName",$target)
|
|
}
|
|
New-CimSession @params
|
|
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Set-HPPrivateBIOSSettingsList {
|
|
[CmdletBinding()]
|
|
param(
|
|
[System.Collections.Generic.List[SureAdminSetting]]$settingsList,
|
|
[string]$Password,
|
|
[string]$ComputerName = ".",
|
|
$ErrorHandling = 2,
|
|
[CimSession]$CimSession,
|
|
[switch]$NoSummary
|
|
)
|
|
|
|
$failedToSet = 0
|
|
|
|
if (-not $CimSession) {
|
|
$CimSession = newCimSession -Target $ComputerName
|
|
}
|
|
|
|
$counter = @(0,0,0,0,0)
|
|
foreach ($setting in $SettingsList) {
|
|
$counter[0]++
|
|
$refParameter = 0
|
|
|
|
$params = @{
|
|
Setting = $setting
|
|
ErrorHandling = $ErrorHandling
|
|
CimSession = $CimSession
|
|
Password = $Password
|
|
SingleSettingFailCounter = [ref]$refParameter
|
|
}
|
|
|
|
$c = Invoke-HPPrivateSetSetting @params -Verbose:$VerbosePreference
|
|
$failedToSet += $refParameter
|
|
|
|
$counter[1] += $c[0]
|
|
$counter[2] += $c[1]
|
|
$counter[3] += $c[2]
|
|
}
|
|
|
|
|
|
if ($counter -and (-not $NoSummary.IsPresent)) {
|
|
$summary = "Total: $($counter[0]), not found: $($counter[2]), different but read-only: $($counter[1]), already set: $($counter[3])"
|
|
Write-Output $summary
|
|
}
|
|
|
|
if ($ErrorHandling -eq 1) {
|
|
if ($failedToSet -eq 0) {
|
|
return 0
|
|
}
|
|
else {
|
|
return 13
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
This is a private command for internal use only
|
|
|
|
.DESCRIPTION
|
|
This is a private command for internal use only
|
|
|
|
.EXAMPLE
|
|
|
|
.NOTES
|
|
- This is a private command for internal use only
|
|
#>
|
|
function Set-HPPrivateBIOSSettingsListPayload {
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(ParameterSetName = 'Payload',Position = 0,Mandatory = $true,ValueFromPipeline = $true)]
|
|
[string]$Payload,
|
|
$ErrorHandling = 2
|
|
)
|
|
|
|
[System.Collections.Generic.List[SureAdminSetting]]$settingsList = Get-HPPrivateSettingsFromPayload -Content $Payload
|
|
|
|
$params = @{
|
|
SettingsList = $settingsList
|
|
ErrorHandling = $ErrorHandling
|
|
}
|
|
Set-HPPrivateBIOSSettingsList @params -Verbose:$VerbosePreference
|
|
}
|
|
|
|
|
|
|
|
# SIG # Begin signature block
|
|
# MIIoHQYJKoZIhvcNAQcCoIIoDjCCKAoCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
|
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
|
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCvkeuMuMg4zBEx
|
|
# e734Z2uOMS3JxJEXoo8iBGyL88Q046CCDYowggawMIIEmKADAgECAhAIrUCyYNKc
|
|
# TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
|
|
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
|
|
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z
|
|
# NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
|
|
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
|
|
# UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
|
|
# ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0
|
|
# JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr
|
|
# Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF
|
|
# LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F
|
|
# LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh
|
|
# 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ
|
|
# wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay
|
|
# g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI
|
|
# YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp
|
|
# QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro
|
|
# OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB
|
|
# WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+
|
|
# YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P
|
|
# AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk
|
|
# BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC
|
|
# hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v
|
|
# dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j
|
|
# b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED
|
|
# MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql
|
|
# +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF
|
|
# UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h
|
|
# mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw
|
|
# YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld
|
|
# AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw
|
|
# 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP
|
|
# LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE
|
|
# QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn
|
|
# KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji
|
|
# WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq
|
|
# yK+p/pQd52MbOoZWeE4wggbSMIIEuqADAgECAhAJvPMqSNxAYhV5FFpsbzOhMA0G
|
|
# CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
|
|
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
|
|
# UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjQwMjE1MDAwMDAwWhcNMjUwMjE4
|
|
# MjM1OTU5WjBaMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAG
|
|
# A1UEBxMJUGFsbyBBbHRvMRAwDgYDVQQKEwdIUCBJbmMuMRAwDgYDVQQDEwdIUCBJ
|
|
# bmMuMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEApbF6fMFy6zhGVra3
|
|
# SZN418Cp2O8kjihQCU9tqPO9tkzbMyTsgveLJVnXPJNG9kQPMGUNp+wEHcoUzlRc
|
|
# YJMEL9fhfzpWPeSIIezGLPCdrkMmS3fdRUwFqEs7z/C6Ui2ZqMaKhKjBJTIWnipe
|
|
# rRfzGB7RoLepQcgqeF5s0DBy4oG83dqcRHo3IJRTBg39tHe3mD5uoGHn5n366abX
|
|
# vC+k53BVyD8w8XLppFVH5XuNlXMq/Ohf613i7DRb/+u92ZiAPVPXXnlxUE26cuDb
|
|
# OfJKN/bXPmvnWcNW3YHVp9ztPTQZhX4yWYXHrAI2Cv6HxUpO6NzhFoRoBTkcYNbA
|
|
# 91pf1Vagh/MNcA2BfQYT975/Vlvj9cfEZ/NwZthZuHa3rdrvCKhhjw7YU2QUeaTJ
|
|
# 0uaX4g6B9PFNqAASYLach3CDJiLmYEfus/utPh57mk0q27yL25fXo/PaMDXiDNIi
|
|
# 7Wuz7A+sPsbtdiY8zvEIRQ+XJXtKAlD4tqG9YzlTO6ZoQX/rAgMBAAGjggIDMIIB
|
|
# /zAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNVHQ4EFgQURH4F
|
|
# u5yEAuElYWUbyGRYkNLLrA8wPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEF
|
|
# BQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIH
|
|
# gDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRw
|
|
# Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmlu
|
|
# Z1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGln
|
|
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hB
|
|
# Mzg0MjAyMUNBMS5jcmwwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUFBzABhhho
|
|
# dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6Ly9jYWNl
|
|
# cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNB
|
|
# NDA5NlNIQTM4NDIwMjFDQTEuY3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQAD
|
|
# ggIBAFiCyuI6qmaQodDyMNpp0l7eIXFgJ4JI59o59PleFj4rcyd/+F4iI7u5if8G
|
|
# rV5Kn3s3tK9vfJO8SpqtEh7lL4e69z6v3ohcy4uy2hsjKQ/fFcDo9pQYDGmDVjCa
|
|
# D5qSVEIBlJHBe5NKEJAgUE0kaMjLzbi2+8DKJlNtvZ+hatuPl9fMnmU+VbQh7JhZ
|
|
# yJdz8Ay0tcQ9lC8HAX5Ah/pU+Vtv+c8gMSxjS1aWXoGCa1869IVi2O6qx7MuX12U
|
|
# 1eIpB9XxYr7HSebvg2G7Gz6nCh7u+4k7m3hJu9EStUIN2JII5260+E60uDWoHEhx
|
|
# tHbdueFQxJrTKnhplOSaaPFCVBDkWG83ZzN9N3z/45w1pBUNBiPJdRQJ58MhBYQe
|
|
# Zl90heMBL8QNQk2i0E5gHNT9pJiCR9+mvJkRxEVgUn+16ZpVnI6kzhThV9qBaWVF
|
|
# h83X4UWc/nwHKIuu+4x4fmkYc79A3MrsHflZIO8jOy0GC/xBnZTQ8s5b9Tb2UkHk
|
|
# w692Ypl7War3W7M37JCAPC/A7M4CwQYjdjG43zs5m36auYVaTvRLKtZVLzcj8oZX
|
|
# 4vqhlZ8+jCPXFiuDfoBXiTckTLpv/eHQ6q7Aoda+qARWPPE1U2v5r/lpKVqIx7B4
|
|
# PdFZAUf5MtG/Bj7LVXvXjW8ABIJv7L4cI2akn6Es0dmvd6PsMYIZ6TCCGeUCAQEw
|
|
# fTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNV
|
|
# BAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hB
|
|
# Mzg0IDIwMjEgQ0ExAhAJvPMqSNxAYhV5FFpsbzOhMA0GCWCGSAFlAwQCAQUAoHww
|
|
# EAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYK
|
|
# KwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIILMzgp9
|
|
# qvv95sDUAyV1zk8mqFadtmPlOBGBFpdxKHPDMA0GCSqGSIb3DQEBAQUABIIBgDR+
|
|
# cxIjFBQApN7X+fdbsZM1UqOWVlf3N6taDknkStl/qhuWS/PUOiCfYJrMQqUtMF3V
|
|
# Ep+Ur9MlJLmCQpUFa5IsU2c5gd9luTfL6fbNdXfYdaCT7+ZdgGKWN0w9k3/OEP4m
|
|
# uEY0Gr1NVEMq6WfnW/EJAlNBe7Mg/UDSQnm27hv+1/t5ALvly5UtYuxpP6ad9X7l
|
|
# ++X1pUGBaiZEXLqukN2hlCa6UiWSRuoojVaKgzR6PHRwXJpZlxGGtsn5UalyJ/97
|
|
# SUcOdwMZqpeAvsKJBZc+RP2vwWpwYTinFzt1DgmUzILoVaeH5bryBmOysKZB9xTp
|
|
# ALmpT3mzBQqFllugIFrpsI2JwT0r4y7tR8pT+Rgt8nTEjdXEs4yD+fHmzE5K30xE
|
|
# wFJQJPfSWL9eyqucOQzBUxRMjeUGzvbnRHB/zrhT0MnSAE/i9FqPSxRYysSnqi2r
|
|
# MXw9qtgSIW1M5cNxAg3id0sAIJxqKXDualErWjCfr+/nl1bmBOCSUF38vwQjlKGC
|
|
# Fz8wghc7BgorBgEEAYI3AwMBMYIXKzCCFycGCSqGSIb3DQEHAqCCFxgwghcUAgED
|
|
# MQ8wDQYJYIZIAWUDBAIBBQAwdwYLKoZIhvcNAQkQAQSgaARmMGQCAQEGCWCGSAGG
|
|
# /WwHATAxMA0GCWCGSAFlAwQCAQUABCDUV0vUjebUzqrF/zInTXfZPEjifWeWv4v8
|
|
# lWHRdfduPQIQVbs3H5YVmm3sMWFb5JZoLRgPMjAyNDA4MjcxNjU1NDhaoIITCTCC
|
|
# BsIwggSqoAMCAQICEAVEr/OUnQg5pr/bP1/lYRYwDQYJKoZIhvcNAQELBQAwYzEL
|
|
# MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE
|
|
# aWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBD
|
|
# QTAeFw0yMzA3MTQwMDAwMDBaFw0zNDEwMTMyMzU5NTlaMEgxCzAJBgNVBAYTAlVT
|
|
# MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UEAxMXRGlnaUNlcnQgVGlt
|
|
# ZXN0YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCjU0WH
|
|
# HYOOW6w+VLMj4M+f1+XS512hDgncL0ijl3o7Kpxn3GIVWMGpkxGnzaqyat0QKYoe
|
|
# YmNp01icNXG/OpfrlFCPHCDqx5o7L5Zm42nnaf5bw9YrIBzBl5S0pVCB8s/LB6Yw
|
|
# aMqDQtr8fwkklKSCGtpqutg7yl3eGRiF+0XqDWFsnf5xXsQGmjzwxS55DxtmUuPI
|
|
# 1j5f2kPThPXQx/ZILV5FdZZ1/t0QoRuDwbjmUpW1R9d4KTlr4HhZl+NEK0rVlc7v
|
|
# CBfqgmRN/yPjyobutKQhZHDr1eWg2mOzLukF7qr2JPUdvJscsrdf3/Dudn0xmWVH
|
|
# VZ1KJC+sK5e+n+T9e3M+Mu5SNPvUu+vUoCw0m+PebmQZBzcBkQ8ctVHNqkxmg4ho
|
|
# Yru8QRt4GW3k2Q/gWEH72LEs4VGvtK0VBhTqYggT02kefGRNnQ/fztFejKqrUBXJ
|
|
# s8q818Q7aESjpTtC/XN97t0K/3k0EH6mXApYTAA+hWl1x4Nk1nXNjxJ2VqUk+tfE
|
|
# ayG66B80mC866msBsPf7Kobse1I4qZgJoXGybHGvPrhvltXhEBP+YUcKjP7wtsfV
|
|
# x95sJPC/QoLKoHE9nJKTBLRpcCcNT7e1NtHJXwikcKPsCvERLmTgyyIryvEoEyFJ
|
|
# UX4GZtM7vvrrkTjYUQfKlLfiUKHzOtOKg8tAewIDAQABo4IBizCCAYcwDgYDVR0P
|
|
# AQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgw
|
|
# IAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMB8GA1UdIwQYMBaAFLoW
|
|
# 2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSltu8T5+/N0GSh1VapZTGj3tXj
|
|
# STBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGln
|
|
# aUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3JsMIGQ
|
|
# BggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
|
|
# cnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
|
|
# RGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3J0
|
|
# MA0GCSqGSIb3DQEBCwUAA4ICAQCBGtbeoKm1mBe8cI1PijxonNgl/8ss5M3qXSKS
|
|
# 7IwiAqm4z4Co2efjxe0mgopxLxjdTrbebNfhYJwr7e09SI64a7p8Xb3CYTdoSXej
|
|
# 65CqEtcnhfOOHpLawkA4n13IoC4leCWdKgV6hCmYtld5j9smViuw86e9NwzYmHZP
|
|
# VrlSwradOKmB521BXIxp0bkrxMZ7z5z6eOKTGnaiaXXTUOREEr4gDZ6pRND45Ul3
|
|
# CFohxbTPmJUaVLq5vMFpGbrPFvKDNzRusEEm3d5al08zjdSNd311RaGlWCZqA0Xe
|
|
# 2VC1UIyvVr1MxeFGxSjTredDAHDezJieGYkD6tSRN+9NUvPJYCHEVkft2hFLjDLD
|
|
# iOZY4rbbPvlfsELWj+MXkdGqwFXjhr+sJyxB0JozSqg21Llyln6XeThIX8rC3D0y
|
|
# 33XWNmdaifj2p8flTzU8AL2+nCpseQHc2kTmOt44OwdeOVj0fHMxVaCAEcsUDH6u
|
|
# vP6k63llqmjWIso765qCNVcoFstp8jKastLYOrixRoZruhf9xHdsFWyuq69zOuhJ
|
|
# RrfVf8y2OMDY7Bz1tqG4QyzfTkx9HmhwwHcK1ALgXGC7KP845VJa1qwXIiNO9OzT
|
|
# F/tQa/8Hdx9xl0RBybhG02wyfFgvZ0dl5Rtztpn5aywGRu9BHvDwX+Db2a2QgESv
|
|
# gBBBijCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQEL
|
|
# BQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UE
|
|
# CxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBS
|
|
# b290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UE
|
|
# BhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2Vy
|
|
# dCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIw
|
|
# DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTep
|
|
# l1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt
|
|
# +FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r
|
|
# 07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dh
|
|
# gxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfA
|
|
# csW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpH
|
|
# IEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJS
|
|
# lRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0
|
|
# z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y
|
|
# 99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBID
|
|
# fV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXT
|
|
# drnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
|
|
# A1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFd
|
|
# ZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUH
|
|
# AwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
|
|
# Y2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
|
|
# bS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0
|
|
# dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3Js
|
|
# MCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsF
|
|
# AAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoN
|
|
# qilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8V
|
|
# c40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJods
|
|
# kr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6sk
|
|
# HibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82H
|
|
# hyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HN
|
|
# T7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8z
|
|
# OYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIX
|
|
# mVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZ
|
|
# E/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSF
|
|
# D/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwggWNMIIEdaAD
|
|
# AgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYT
|
|
# AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy
|
|
# dC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0y
|
|
# MjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYD
|
|
# VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAf
|
|
# BgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEB
|
|
# BQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4Smn
|
|
# PVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6f
|
|
# qVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O
|
|
# 7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZ
|
|
# Vu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4F
|
|
# fYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLm
|
|
# qaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMre
|
|
# Sx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/ch
|
|
# srIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+U
|
|
# DCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xM
|
|
# dT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUb
|
|
# AgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFd
|
|
# ZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAO
|
|
# BgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRw
|
|
# Oi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRz
|
|
# LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0f
|
|
# BD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNz
|
|
# dXJlZElEUm9vdENBLmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEM
|
|
# BQADggEBAHCgv0NcVec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLt
|
|
# pIh3bb0aFPQTSnovLbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouy
|
|
# XtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jS
|
|
# TEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAc
|
|
# AgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2
|
|
# h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2MIIDcgIBATB3MGMxCzAJBgNVBAYT
|
|
# AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQg
|
|
# VHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAVEr/OU
|
|
# nQg5pr/bP1/lYRYwDQYJYIZIAWUDBAIBBQCggdEwGgYJKoZIhvcNAQkDMQ0GCyqG
|
|
# SIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNDA4MjcxNjU1NDhaMCsGCyqGSIb3
|
|
# DQEJEAIMMRwwGjAYMBYEFGbwKzLCwskPgl3OqorJxk8ZnM9AMC8GCSqGSIb3DQEJ
|
|
# BDEiBCCyR2EllVtZnEP5wyD3EfPGe3y79W+Na0r5UjazHHUwFDA3BgsqhkiG9w0B
|
|
# CRACLzEoMCYwJDAiBCDS9uRt7XQizNHUQFdoQTZvgoraVZquMxavTRqa1Ax4KDAN
|
|
# BgkqhkiG9w0BAQEFAASCAgBwVHPSur7Jwaxf0zlyQci/GdRk2Zr496jVce/Y1zGV
|
|
# 0ZI5hEBaSYuvkjJI2ECNSXAsa5+FJaSNBablqgyjfeWyT4JOD6pM36RC6l/ZVAmS
|
|
# WQWfLbAQ3xolSIAwa/97W7SSF1v5Uu2P3tBSEAf7AoL2hIS/BW8R1+fgJXqps4Ep
|
|
# fyYgX13SuXv4E10yGovfDdlREB3BgJj/ugHMxR8ZNzS2vS59DkjZUkDVdaNoV5Y1
|
|
# c3gyACM8e3Otbfm+l6RMiIqcOmo20z0oZ2kL/v4BnshdeAQQEDzc3NvuAmmnkEHT
|
|
# THebloIG+1ghN4vRftPQRVXcwISXah713r+h+B5otnWruMm8oJCvXqKH96x6ezYw
|
|
# VV8ylbSqciopSf35tLPcFaQCz6/VnmTyv+XZRR4w662Ky5xsS8HSheK4OqJUlRtL
|
|
# SccOGvn7ora9ztEIpT5/GUDXLISJvWSMOMUw+ngrOGJF3X46CMG2FhgOpwKeb6jt
|
|
# 9L94IetOxMUaagAaMEfmXGBBEz5fn6TmCPOYqFXKkSkJTKIZJOcd5SxyOVqBqLIf
|
|
# I34dbbxEj/J7K9Uk1iA2+cFV9EaEsayOLBnbEh2fJJGXtqDsmlA3EUZzowuygO6O
|
|
# FmzgU5IVDoCtrE7YPJgEHJR2MvzmoNZaeGGhGqCcxEmXUhGs6luC6FB2iKnYc889
|
|
# Jw==
|
|
# SIG # End signature block
|