Integrom.Library.psHelper.psm1

New-Variable -name Version -value '1.50' -option ReadOnly, Private -Force


$dynamicEnumBlock = @"
   public enum %%ENUM_NAME%% {
      %%ENUM_DATA%%
   }
"@


Add-Type -Name WinApi -Namespace igmPShelper -MemberDefinition @'
[DllImport("Kernel32.dll")]
public static extern uint GetCurrentThreadId();
'@


Add-Type -Path "$($PSScriptRoot)\System.IO.Hashing.dll"

function testForISE() {return ($host.name -like '*ise*')}

function getPressedKeyCode([bool]$iseMode = $false) {
    if ($iseMode) {
        $pInfo = New-Object System.Diagnostics.ProcessStartInfo
        $pInfo.FileName = "powershell.exe" #pwsh (7.x+) unlikely to be used in the ISE but may need to include for this
        $pInfo.RedirectStandardError = $true
        $pInfo.RedirectStandardOutput = $true
        $pInfo.UseShellExecute = $false
        $pInfo.Arguments = {([System.Console]::ReadKey($true)).Key}
        $tmpProcess = New-Object System.Diagnostics.Process
        $tmpProcess.StartInfo = $pInfo
        $tmpProcess.Start() | Out-Null
        $tmpProcess.WaitForExit()
        $key = [byte]$tmpProcess.StandardOutput.ReadToEnd()[0]
    } else {$key = ($Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')).VirtualKeyCode}
    return $key
}

function convertObjectToHashtable ($varInput, [hashtable]$refDestinationHashtable) {
    if ($null -eq $varInput) {return -1}
    foreach ($property in $varInput.PSObject.Properties) {
        switch ("[" + $property.value.getType() + "]") {
            "[System.Management.Automation.PSCustomObject]" {
                $refDestinationHashtable.add($property.name, @{})
                convertObjectToHashtable $property.value $refDestinationHashtable[$property.name]
            }
            "[System.Object[]]" {
                $refDestinationHashtable.add($property.name, [string[]]@())
                foreach ($object in $property.value) {[string[]]$refDestinationHashtable[$property.name] += [string]$object}
            }
            default {
                if ($property.value -eq 'true' -or $property.value -eq 'false') {
                    $refDestinationHashtable.add($property.Name, [bool]$property.value)
                } elseif ($property.value -eq 'null') {
                    $refDestinationHashtable.add($property.Name, $null)
                } else {    
                    $refDestinationHashtable.add($property.Name, $property.value)
                }
            } 
        }
    }
    return 0
}       

function displayJSONData ($variantInput, [int]$indentLevel = 0) {
    [string]$indent = ''
    $indentLevel += 5
    foreach ($object in $variantInput.Psobject.properties) {
        if ($object.typeNameOfValue -eq "System.Management.Automation.PSCustomObject") {
            write-host "$($indent.PadLeft($indentLevel))$($object.Name)"
            displayJSONData $object.value $keyToFind $indentLevel
        } else {
            write-host "$($indent.PadLeft($indentLevel))$($object.Name): $($object.Value)"
        }
    }
}

function displayHashTable ($variantHashInput, [int]$indentLevel = 0) {
    [string]$indent = ''
    $indentLevel += 5
    foreach ($key in $variantHashInput.Keys) {
        if ($variantHashInput[$key] -is [System.Collections.Hashtable]) {
            write-host "$($indent.PadLeft($indentLevel))$key"
            displayHashTable $variantHashInput[$key] $indentLevel
        } else {
            write-host "$($indent.PadLeft($indentLevel))$key`: $($variantHashInput[$key])"
        }
    }
}

function setFileAttribute ([string]$fileName, [System.IO.FileAttributes]$attribute) {
    try {$fileInfo = (Get-ChildItem $fileName -force -ErrorAction Stop)} catch {return -1}
    try {$fileInfo.Attributes = $fileInfo.Attributes -bor ($attribute).value__} catch {return -2}
    return 0
}

function isFileReadOnly ([string]$fileName) {
    try {$fileInfo = (Get-ChildItem $fileName -ErrorAction Stop)} catch {return -1}
    return ($fileInfo.Attributes -band ([system.io.fileattributes]::ReadOnly).value__ -eq 1)
}

function getChassisSerialNumber() {
    try {
        return ([string](Get-CimInstance -ErrorAction Stop -class win32_bios).serialNumber -replace '[\x00-\x20\x7f-\xff]+', $null).ToUpper()
    } catch {
        return $null
    }   
}

function getChassisModelID() {
    try {
        $modelString = ([string](Get-CimInstance -class CIM_ComputerSystem -ErrorAction Stop).model -replace "[\x00-\x20\x7f-\xff]+", $null).ToUpper()
        return [string]::Format("{0:X2}{1:X2}{2:X2}{3:X2}", $([System.IO.Hashing.Crc32]::Hash($modelString.ToCharArray())))
    } catch {
        return $null
    }
}

function getPossibleLibPaths{param([string]$libName, [string]$baseLibPath)
   [string[]]$pathSuffixes = '', '_lib\', "$($env:ProgramFiles)\Integrom\Libraries"
   [string[]]$result = @()

   if (-not ($baseLibPath -match '\\$')) {$baseLibPath = "$($baseLibPath)\"}
   $regexResult = [regex]::Match("$($baseLibPath)$($libName)", '(?<root>^[a-z]:|\.\.|\.)?(?<path>.*\\)?(?<libName>.+$)', [Text.RegularExpressions.RegexOptions]::IgnoreCase)
   $expRoot = $regexResult[0].Groups['root'].value
   $path = $regexResult[0].Groups['path'].value
   $modName = $regexResult[0].Groups['libName'].value
   if ([string]::IsNullOrEmpty($expRoot)) {$rootsToTest = '.', '..'} else {$rootsToTest = $expRoot}
   if (-not ($path -match '^\\')) {$path = "\$($path)"}
   $pathSuffixes += "$($modName)\"
   foreach ($root in $rootsToTest) {
      foreach ($pathSuffix in $pathSuffixes) {
         $result += "$($root)$($path)$($pathSuffix)$($libName).ps1"
      }
   }
   return $result
}

function loadLibraries {[CmdletBinding()]param([string[]]$libraryNames, [string]$libPath)
   [int]$statusCode = 0
   
   if ($libraryNames.Count -lt 1) {return -5}
   foreach ($libraryName in $libraryNames) {
      Write-Host "INFO: Loading library $($libraryName)...."
      foreach ($fqLibPath in (getPossibleLibPaths -libName $libraryName -baseLibPath $libPath)) {
         try {
            $ExecutionContext.SessionState.InvokeCommand.InvokeScript($PSCmdlet.SessionState, {param($libName); . $libName}.Ast.GetScriptBlock(), $fqLibPath)
            $libLoaded = $true
         } catch {
            $libLoaded = $false
            continue
         }
         if ($libLoaded) {break}
      }
      if (-not $libLoaded) {
         $statusCode = -20
         Write-host "WARNING: Failed to load library $($libraryName) from all known location(s)."
      }
   }
   return $statusCode
}

function getLibraryVersion([string]$libraryName, [string]$libPath) {
   foreach ($fqLibPath in (getPossibleLibPaths -libName $libraryName -baseLibPath $libPath)) {
      try {
         $null = Invoke-Command {$fqLibPath} -NoNewScope
         return $Version
      } catch {
         continue
      }
   }
   return -1
}

function injectEnumFromJSON{[CmdletBinding()]param([string]$jsonFile, [string]$jsonKey, [string]$enumDef = $dynamicEnumBlock)
   [int]$v = 4001
   [scriptblock]$unboundCode = {param([string]$enumdef); Add-Type -TypeDefinition $enumdef}.Ast.GetScriptBlock()
   [PSCustomObject]$jsonFileData = Get-Content $jsonfile | ConvertFrom-Json
   if (($jsonFileData.$jsonKey).count -lt 1) {return -5}
   foreach ($item in $jsonFileData.$jsonKey) {$enumItems += "@$($item) = $($v),`n"; $v ++}
   $enumDef = $enumDef`
      -replace '%%ENUM_NAME%%', $jsonKey`
      -replace '%%ENUM_DATA%%', $enumItems
   try {
      $ExecutionContext.SessionState.InvokeCommand.InvokeScript($PSCmdlet.SessionState, $unboundCode, $enumDef)
      return 0
   } catch {
      return -17
   }
}