PSHelperTools.psm1
function New-TestEnvironment(){ Set-Location $env:temp $Folder = -join ((65..90) + (97..122) | Get-Random -Count 20 | % {[char]$_}) New-Item $Folder -ItemType Directory Set-Location $Folder } function Test-Symlink(){ [Cmdletbinding()] param($Path) if(Test-Path $Path){ ((Get-Item $Path).Attributes.ToString() -match "ReparsePoint") } else{ $False } } function Get-SymlinkTarget(){ [Cmdletbinding()] param($Path) if(Test-Symlink $Path){ try{ ((Get-Item $Path | Select-Object -ExpandProperty Target) -replace "^UNC\\", "\\") } catch{ "" } } else{ "" } } function Join-StringCustom{ param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [String[]] $Strings, [String] $Separator ) Begin{ $Array = [System.Collections.ArrayList]@() } Process{ $Array.Add($Strings[0]) | Out-Null } End{ $Return = "" for($i = 0; $i -lt $Array.Count - 1; $i = $i + 1){ $Return = -join($Return, $Array[$i], $Separator) } $Return = -join($Return, $Array[$Array.Count - 1]) $Return } } #Which Verb? Format? Optimize? Convert? Resolve? Unify is unapproved but fitting function Format-Path(){ [Cmdletbinding()] param($Path) Write-Verbose "Format-Path: $Path" if($Path.StartsWith(".")){ #Get Absolute path if path starts with "." $Path = Resolve-Path -Path $Path Write-Verbose "Resolved Path: $Path" } if($Path -match "^.*::(.*)"){ $Path = $Path -replace "^.*::(.*)", '$1' Write-Verbose "Replaced Powershell providers: $Path" } $Path = $Path -replace "/" , "\" ` -replace "^\\\\\.\\" , "" ` -replace "^\\\\\?\\" , "" ` -replace "^UNC\\" , "\\" Write-Verbose "Replaced UNC conventions: $Path" if($Path -match "^\\\\([A-Za-z]+)(@SSL)?"){ $Path = $Path -replace "^\\\\([A-Za-z]+)(@SSL)?", "\\$((Resolve-DnsName $matches[1] -Type "A").IPAddress)" Write-Verbose "Resolve name into IP: $Path" } return $Path.TrimEnd("\") } function Resolve-Symlink(){ [Cmdletbinding()] param($Path) Write-Verbose "Resolve-Symlink: $Path" $Path = Format-Path $Path Write-Verbose "Formatted: $Path" $Current = $Path while($Current){ Write-Verbose "Current step: $Current" if(Test-Symlink $Current){ $Target = Get-SymlinkTarget $Current Write-Verbose "Step is Symlink, replacing with target: $Target" $Path = $Path -replace "^$([System.Text.RegularExpressions.Regex]::Escape($Current))", "$Target" $Current = $Target } else{ $Current = Split-Path -Path $Current -Parent -ErrorAction Stop } } Write-Verbose "Resolved Symlink: $Path" return Format-Path $Path } function Compare-Paths(){ [Cmdletbinding()] param([String]$First, [String]$Second) Write-Verbose "Comparing-Paths: '$First' to '$Second'" return (Resolve-Symlink $First -ErrorAction Stop) -eq (Resolve-Symlink $Second -ErrorAction Stop) } <# .SYNOPSIS Set File Type Association Windows 8/10/11 .DESCRIPTION Set File/Protocol Type Association Default Application Windows 8/10/11 .NOTES Version : 1.2.0 Author(s) : Danyfirex & Dany3j Credits : https://bbs.pediy.com/thread-213954.htm LMongrain - Hash Algorithm PureBasic Version License : MIT License Copyright : 2022 Danysys. <danysys.com> .EXAMPLE Get-FTA Show All Application Program Id .EXAMPLE Get-FTA .pdf Show Default Application Program Id for an Extension .EXAMPLE Set-FTA AcroExch.Document.DC .pdf Set Acrobat Reader DC as Default .pdf reader .EXAMPLE Set-FTA Applications\SumatraPDF.exe .pdf Set Sumatra PDF as Default .pdf reader .EXAMPLE Set-PTA ChromeHTML http Set Google Chrome as Default for http Protocol .EXAMPLE Register-FTA "C:\SumatraPDF.exe" .pdf -Icon "shell32.dll,100" Register Application and Set as Default for .pdf reader .LINK https://github.com/DanysysTeam/PS-SFTA #> function Get-FTA { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [String] $Extension ) if ($Extension) { Write-Verbose "Get File Type Association for $Extension" $assocFile = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -ErrorAction SilentlyContinue).ProgId Write-Output $assocFile } else { Write-Verbose "Get File Type Association List" $assocList = Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\* | ForEach-Object { $progId = (Get-ItemProperty "$($_.PSParentPath)\$($_.PSChildName)\UserChoice" -ErrorAction SilentlyContinue).ProgId if ($progId) { "$($_.PSChildName), $progId" } } Write-Output $assocList } } function Get-PTA { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [String] $Protocol ) if ($Protocol) { Write-Verbose "Get Protocol Type Association for $Protocol" $assocFile = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$Protocol\UserChoice" -ErrorAction SilentlyContinue).ProgId Write-Output $assocFile } else { Write-Verbose "Get Protocol Type Association List" $assocList = Get-ChildItem HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\* | ForEach-Object { $progId = (Get-ItemProperty "$($_.PSParentPath)\$($_.PSChildName)\UserChoice" -ErrorAction SilentlyContinue).ProgId if ($progId) { "$($_.PSChildName), $progId" } } Write-Output $assocList } } function Register-FTA { [CmdletBinding()] param ( [Parameter( Position = 0, Mandatory = $true)] [ValidateScript( { Test-Path $_ })] [String] $ProgramPath, [Parameter( Position = 1, Mandatory = $true)] [Alias("Protocol")] [String] $Extension, [Parameter( Position = 2, Mandatory = $false)] [String] $ProgId, [Parameter( Position = 3, Mandatory = $false)] [String] $Icon ) Write-Verbose "Register Application + Set Association" Write-Verbose "Application Path: $ProgramPath" if ($Extension.Contains(".")) { Write-Verbose "Extension: $Extension" } else { Write-Verbose "Protocol: $Extension" } if (!$ProgId) { $ProgId = "SFTA." + [System.IO.Path]::GetFileNameWithoutExtension($ProgramPath).replace(" ", "") + $Extension } $progCommand = """$ProgramPath"" ""%1""" Write-Verbose "ApplicationId: $ProgId" Write-Verbose "ApplicationCommand: $progCommand" try { $keyPath = "HKEY_CURRENT_USER\SOFTWARE\Classes\$Extension\OpenWithProgids" [Microsoft.Win32.Registry]::SetValue( $keyPath, $ProgId, ([byte[]]@()), [Microsoft.Win32.RegistryValueKind]::None) $keyPath = "HKEY_CURRENT_USER\SOFTWARE\Classes\$ProgId\shell\open\command" [Microsoft.Win32.Registry]::SetValue($keyPath, "", $progCommand) Write-Verbose "Register ProgId and ProgId Command OK" } catch { throw "Register ProgId and ProgId Command FAILED" } Set-FTA -ProgId $ProgId -Extension $Extension -Icon $Icon } function Remove-FTA { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [Alias("ProgId")] [String] $ProgramPath, [Parameter(Mandatory = $true)] [String] $Extension ) function local:Remove-UserChoiceKey { param ( [Parameter( Position = 0, Mandatory = $True )] [String] $Key ) $code = @' using System; using System.Runtime.InteropServices; using Microsoft.Win32; namespace Registry { public class Utils { [DllImport("advapi32.dll", SetLastError = true)] private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult); [DllImport("advapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)] private static extern uint RegDeleteKey(UIntPtr hKey, string subKey); public static void DeleteKey(string key) { UIntPtr hKey = UIntPtr.Zero; RegOpenKeyEx((UIntPtr)0x80000001u, key, 0, 0x20019, out hKey); RegDeleteKey((UIntPtr)0x80000001u, key); } } } '@ try { Add-Type -TypeDefinition $code } catch {} try { [Registry.Utils]::DeleteKey($Key) } catch {} } function local:Update-Registry { $code = @' [System.Runtime.InteropServices.DllImport("Shell32.dll")] private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); public static void Refresh() { SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero); } '@ try { Add-Type -MemberDefinition $code -Namespace SHChange -Name Notify } catch {} try { [SHChange.Notify]::Refresh() } catch {} } if (Test-Path -Path $ProgramPath) { $ProgId = "SFTA." + [System.IO.Path]::GetFileNameWithoutExtension($ProgramPath).replace(" ", "") + $Extension } else { $ProgId = $ProgramPath } try { $keyPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" Write-Verbose "Remove User UserChoice Key If Exist: $keyPath" Remove-UserChoiceKey $keyPath $keyPath = "HKCU:\SOFTWARE\Classes\$ProgId" Write-Verbose "Remove Key If Exist: $keyPath" Remove-Item -Path $keyPath -Recurse -ErrorAction Stop | Out-Null } catch { Write-Verbose "Key No Exist: $keyPath" } try { $keyPath = "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids" Write-Verbose "Remove Property If Exist: $keyPath Property $ProgId" Remove-ItemProperty -Path $keyPath -Name $ProgId -ErrorAction Stop | Out-Null } catch { Write-Verbose "Property No Exist: $keyPath Property: $ProgId" } Update-Registry Write-Output "Removed: $ProgId" } function Set-FTA { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $ProgId, [Parameter(Mandatory = $true)] [Alias("Protocol")] [String] $Extension, [String] $Icon, [switch] $DomainSID ) if (Test-Path -Path $ProgId) { $ProgId = "SFTA." + [System.IO.Path]::GetFileNameWithoutExtension($ProgId).replace(" ", "") + $Extension } Write-Verbose "ProgId: $ProgId" Write-Verbose "Extension/Protocol: $Extension" #Write required Application Ids to ApplicationAssociationToasts #When more than one application associated with an Extension/Protocol is installed ApplicationAssociationToasts need to be updated function local:Write-RequiredApplicationAssociationToasts { param ( [Parameter( Position = 0, Mandatory = $True )] [String] $ProgId, [Parameter( Position = 1, Mandatory = $True )] [String] $Extension ) try { $keyPath = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts" [Microsoft.Win32.Registry]::SetValue($keyPath, $ProgId + "_" + $Extension, 0x0) Write-Verbose ("Write Reg ApplicationAssociationToasts OK: " + $ProgId + "_" + $Extension) } catch { Write-Verbose ("Write Reg ApplicationAssociationToasts FAILED: " + $ProgId + "_" + $Extension) } $allApplicationAssociationToasts = Get-ChildItem -Path HKLM:\SOFTWARE\Classes\$Extension\OpenWithList\* -ErrorAction SilentlyContinue | ForEach-Object { "Applications\$($_.PSChildName)" } $allApplicationAssociationToasts += @( ForEach ($item in (Get-ItemProperty -Path HKLM:\SOFTWARE\Classes\$Extension\OpenWithProgids -ErrorAction SilentlyContinue).PSObject.Properties ) { if ([string]::IsNullOrEmpty($item.Value) -and $item -ne "(default)") { $item.Name } }) $allApplicationAssociationToasts += Get-ChildItem -Path HKLM:SOFTWARE\Clients\StartMenuInternet\* , HKCU:SOFTWARE\Clients\StartMenuInternet\* -ErrorAction SilentlyContinue | ForEach-Object { (Get-ItemProperty ("$($_.PSPath)\Capabilities\" + (@("URLAssociations", "FileAssociations") | Select-Object -Index $Extension.Contains("."))) -ErrorAction SilentlyContinue).$Extension } $allApplicationAssociationToasts | ForEach-Object { if ($_) { if (Set-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts $_"_"$Extension -Value 0 -Type DWord -ErrorAction SilentlyContinue -PassThru) { Write-Verbose ("Write Reg ApplicationAssociationToastsList OK: " + $_ + "_" + $Extension) } else { Write-Verbose ("Write Reg ApplicationAssociationToastsList FAILED: " + $_ + "_" + $Extension) } } } } function local:Update-RegistryChanges { $code = @' [System.Runtime.InteropServices.DllImport("Shell32.dll")] private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); public static void Refresh() { SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero); } '@ try { Add-Type -MemberDefinition $code -Namespace SHChange -Name Notify } catch {} try { [SHChange.Notify]::Refresh() } catch {} } function local:Set-Icon { param ( [Parameter( Position = 0, Mandatory = $True )] [String] $ProgId, [Parameter( Position = 1, Mandatory = $True )] [String] $Icon ) try { $keyPath = "HKEY_CURRENT_USER\SOFTWARE\Classes\$ProgId\DefaultIcon" [Microsoft.Win32.Registry]::SetValue($keyPath, "", $Icon) Write-Verbose "Write Reg Icon OK" Write-Verbose "Reg Icon: $keyPath" } catch { Write-Verbose "Write Reg Icon FAILED" } } function local:Write-ExtensionKeys { param ( [Parameter( Position = 0, Mandatory = $True )] [String] $ProgId, [Parameter( Position = 1, Mandatory = $True )] [String] $Extension, [Parameter( Position = 2, Mandatory = $True )] [String] $ProgHash ) function local:Remove-UserChoiceKey { param ( [Parameter( Position = 0, Mandatory = $True )] [String] $Key ) $code = @' using System; using System.Runtime.InteropServices; using Microsoft.Win32; namespace Registry { public class Utils { [DllImport("advapi32.dll", SetLastError = true)] private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult); [DllImport("advapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)] private static extern uint RegDeleteKey(UIntPtr hKey, string subKey); public static void DeleteKey(string key) { UIntPtr hKey = UIntPtr.Zero; RegOpenKeyEx((UIntPtr)0x80000001u, key, 0, 0x20019, out hKey); RegDeleteKey((UIntPtr)0x80000001u, key); } } } '@ try { Add-Type -TypeDefinition $code } catch {} try { [Registry.Utils]::DeleteKey($Key) } catch {} } try { $keyPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" Write-Verbose "Remove Extension UserChoice Key If Exist: $keyPath" Remove-UserChoiceKey $keyPath } catch { Write-Verbose "Extension UserChoice Key No Exist: $keyPath" } try { $keyPath = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" [Microsoft.Win32.Registry]::SetValue($keyPath, "Hash", $ProgHash) [Microsoft.Win32.Registry]::SetValue($keyPath, "ProgId", $ProgId) Write-Verbose "Write Reg Extension UserChoice OK" } catch { throw "Write Reg Extension UserChoice FAILED" } } function local:Write-ProtocolKeys { param ( [Parameter( Position = 0, Mandatory = $True )] [String] $ProgId, [Parameter( Position = 1, Mandatory = $True )] [String] $Protocol, [Parameter( Position = 2, Mandatory = $True )] [String] $ProgHash ) try { $keyPath = "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$Protocol\UserChoice" Write-Verbose "Remove Protocol UserChoice Key If Exist: $keyPath" Remove-Item -Path $keyPath -Recurse -ErrorAction Stop | Out-Null } catch { Write-Verbose "Protocol UserChoice Key No Exist: $keyPath" } try { $keyPath = "HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$Protocol\UserChoice" [Microsoft.Win32.Registry]::SetValue( $keyPath, "Hash", $ProgHash) [Microsoft.Win32.Registry]::SetValue($keyPath, "ProgId", $ProgId) Write-Verbose "Write Reg Protocol UserChoice OK" } catch { throw "Write Reg Protocol UserChoice FAILED" } } function local:Get-UserExperience { [OutputType([string])] $userExperienceSearch = "User Choice set via Windows User Experience" $user32Path = [Environment]::GetFolderPath([Environment+SpecialFolder]::SystemX86) + "\Shell32.dll" $fileStream = [System.IO.File]::Open($user32Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) $binaryReader = New-Object System.IO.BinaryReader($fileStream) [Byte[]] $bytesData = $binaryReader.ReadBytes(5mb) $fileStream.Close() $dataString = [Text.Encoding]::Unicode.GetString($bytesData) $position1 = $dataString.IndexOf($userExperienceSearch) $position2 = $dataString.IndexOf("}", $position1) Write-Output $dataString.Substring($position1, $position2 - $position1 + 1) } function local:Get-UserSid { [OutputType([string])] $userSid = ((New-Object System.Security.Principal.NTAccount([Environment]::UserName)).Translate([System.Security.Principal.SecurityIdentifier]).value).ToLower() Write-Output $userSid } #use in this special case #https://github.com/DanysysTeam/PS-SFTA/pull/7 function local:Get-UserSidDomain { if (-not ("System.DirectoryServices.AccountManagement" -as [type])) { Add-Type -AssemblyName System.DirectoryServices.AccountManagement } [OutputType([string])] $userSid = ([System.DirectoryServices.AccountManagement.UserPrincipal]::Current).SID.Value.ToLower() Write-Output $userSid } function local:Get-HexDateTime { [OutputType([string])] $now = [DateTime]::Now $dateTime = [DateTime]::New($now.Year, $now.Month, $now.Day, $now.Hour, $now.Minute, 0) $fileTime = $dateTime.ToFileTime() $hi = ($fileTime -shr 32) $low = ($fileTime -band 0xFFFFFFFFL) $dateTimeHex = ($hi.ToString("X8") + $low.ToString("X8")).ToLower() Write-Output $dateTimeHex } function Get-Hash { [CmdletBinding()] param ( [Parameter( Position = 0, Mandatory = $True )] [string] $BaseInfo ) function local:Get-ShiftRight { [CmdletBinding()] param ( [Parameter( Position = 0, Mandatory = $true)] [long] $iValue, [Parameter( Position = 1, Mandatory = $true)] [int] $iCount ) if ($iValue -band 0x80000000) { Write-Output (( $iValue -shr $iCount) -bxor 0xFFFF0000) } else { Write-Output ($iValue -shr $iCount) } } function local:Get-Long { [CmdletBinding()] param ( [Parameter( Position = 0, Mandatory = $true)] [byte[]] $Bytes, [Parameter( Position = 1)] [int] $Index = 0 ) Write-Output ([BitConverter]::ToInt32($Bytes, $Index)) } function local:Convert-Int32 { param ( [Parameter( Position = 0, Mandatory = $true)] $Value ) [byte[]] $bytes = [BitConverter]::GetBytes($Value) return [BitConverter]::ToInt32( $bytes, 0) } [Byte[]] $bytesBaseInfo = [System.Text.Encoding]::Unicode.GetBytes($baseInfo) $bytesBaseInfo += 0x00, 0x00 $MD5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider [Byte[]] $bytesMD5 = $MD5.ComputeHash($bytesBaseInfo) $lengthBase = ($baseInfo.Length * 2) + 2 $length = (($lengthBase -band 4) -le 1) + (Get-ShiftRight $lengthBase 2) - 1 $base64Hash = "" if ($length -gt 1) { $map = @{PDATA = 0; CACHE = 0; COUNTER = 0 ; INDEX = 0; MD51 = 0; MD52 = 0; OUTHASH1 = 0; OUTHASH2 = 0; R0 = 0; R1 = @(0, 0); R2 = @(0, 0); R3 = 0; R4 = @(0, 0); R5 = @(0, 0); R6 = @(0, 0); R7 = @(0, 0) } $map.CACHE = 0 $map.OUTHASH1 = 0 $map.PDATA = 0 $map.MD51 = (((Get-Long $bytesMD5) -bor 1) + 0x69FB0000L) $map.MD52 = ((Get-Long $bytesMD5 4) -bor 1) + 0x13DB0000L $map.INDEX = Get-ShiftRight ($length - 2) 1 $map.COUNTER = $map.INDEX + 1 while ($map.COUNTER) { $map.R0 = Convert-Int32 ((Get-Long $bytesBaseInfo $map.PDATA) + [long]$map.OUTHASH1) $map.R1[0] = Convert-Int32 (Get-Long $bytesBaseInfo ($map.PDATA + 4)) $map.PDATA = $map.PDATA + 8 $map.R2[0] = Convert-Int32 (($map.R0 * ([long]$map.MD51)) - (0x10FA9605L * ((Get-ShiftRight $map.R0 16)))) $map.R2[1] = Convert-Int32 ((0x79F8A395L * ([long]$map.R2[0])) + (0x689B6B9FL * (Get-ShiftRight $map.R2[0] 16))) $map.R3 = Convert-Int32 ((0xEA970001L * $map.R2[1]) - (0x3C101569L * (Get-ShiftRight $map.R2[1] 16) )) $map.R4[0] = Convert-Int32 ($map.R3 + $map.R1[0]) $map.R5[0] = Convert-Int32 ($map.CACHE + $map.R3) $map.R6[0] = Convert-Int32 (($map.R4[0] * [long]$map.MD52) - (0x3CE8EC25L * (Get-ShiftRight $map.R4[0] 16))) $map.R6[1] = Convert-Int32 ((0x59C3AF2DL * $map.R6[0]) - (0x2232E0F1L * (Get-ShiftRight $map.R6[0] 16))) $map.OUTHASH1 = Convert-Int32 ((0x1EC90001L * $map.R6[1]) + (0x35BD1EC9L * (Get-ShiftRight $map.R6[1] 16))) $map.OUTHASH2 = Convert-Int32 ([long]$map.R5[0] + [long]$map.OUTHASH1) $map.CACHE = ([long]$map.OUTHASH2) $map.COUNTER = $map.COUNTER - 1 } [Byte[]] $outHash = @(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) [byte[]] $buffer = [BitConverter]::GetBytes($map.OUTHASH1) $buffer.CopyTo($outHash, 0) $buffer = [BitConverter]::GetBytes($map.OUTHASH2) $buffer.CopyTo($outHash, 4) $map = @{PDATA = 0; CACHE = 0; COUNTER = 0 ; INDEX = 0; MD51 = 0; MD52 = 0; OUTHASH1 = 0; OUTHASH2 = 0; R0 = 0; R1 = @(0, 0); R2 = @(0, 0); R3 = 0; R4 = @(0, 0); R5 = @(0, 0); R6 = @(0, 0); R7 = @(0, 0) } $map.CACHE = 0 $map.OUTHASH1 = 0 $map.PDATA = 0 $map.MD51 = ((Get-Long $bytesMD5) -bor 1) $map.MD52 = ((Get-Long $bytesMD5 4) -bor 1) $map.INDEX = Get-ShiftRight ($length - 2) 1 $map.COUNTER = $map.INDEX + 1 while ($map.COUNTER) { $map.R0 = Convert-Int32 ((Get-Long $bytesBaseInfo $map.PDATA) + ([long]$map.OUTHASH1)) $map.PDATA = $map.PDATA + 8 $map.R1[0] = Convert-Int32 ($map.R0 * [long]$map.MD51) $map.R1[1] = Convert-Int32 ((0xB1110000L * $map.R1[0]) - (0x30674EEFL * (Get-ShiftRight $map.R1[0] 16))) $map.R2[0] = Convert-Int32 ((0x5B9F0000L * $map.R1[1]) - (0x78F7A461L * (Get-ShiftRight $map.R1[1] 16))) $map.R2[1] = Convert-Int32 ((0x12CEB96DL * (Get-ShiftRight $map.R2[0] 16)) - (0x46930000L * $map.R2[0])) $map.R3 = Convert-Int32 ((0x1D830000L * $map.R2[1]) + (0x257E1D83L * (Get-ShiftRight $map.R2[1] 16))) $map.R4[0] = Convert-Int32 ([long]$map.MD52 * ([long]$map.R3 + (Get-Long $bytesBaseInfo ($map.PDATA - 4)))) $map.R4[1] = Convert-Int32 ((0x16F50000L * $map.R4[0]) - (0x5D8BE90BL * (Get-ShiftRight $map.R4[0] 16))) $map.R5[0] = Convert-Int32 ((0x96FF0000L * $map.R4[1]) - (0x2C7C6901L * (Get-ShiftRight $map.R4[1] 16))) $map.R5[1] = Convert-Int32 ((0x2B890000L * $map.R5[0]) + (0x7C932B89L * (Get-ShiftRight $map.R5[0] 16))) $map.OUTHASH1 = Convert-Int32 ((0x9F690000L * $map.R5[1]) - (0x405B6097L * (Get-ShiftRight ($map.R5[1]) 16))) $map.OUTHASH2 = Convert-Int32 ([long]$map.OUTHASH1 + $map.CACHE + $map.R3) $map.CACHE = ([long]$map.OUTHASH2) $map.COUNTER = $map.COUNTER - 1 } $buffer = [BitConverter]::GetBytes($map.OUTHASH1) $buffer.CopyTo($outHash, 8) $buffer = [BitConverter]::GetBytes($map.OUTHASH2) $buffer.CopyTo($outHash, 12) [Byte[]] $outHashBase = @(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) $hashValue1 = ((Get-Long $outHash 8) -bxor (Get-Long $outHash)) $hashValue2 = ((Get-Long $outHash 12) -bxor (Get-Long $outHash 4)) $buffer = [BitConverter]::GetBytes($hashValue1) $buffer.CopyTo($outHashBase, 0) $buffer = [BitConverter]::GetBytes($hashValue2) $buffer.CopyTo($outHashBase, 4) $base64Hash = [Convert]::ToBase64String($outHashBase) } Write-Output $base64Hash } Write-Verbose "Getting Hash For $ProgId $Extension" If ($DomainSID.IsPresent) { Write-Verbose "Use Get-UserSidDomain" } Else { Write-Verbose "Use Get-UserSid" } $userSid = If ($DomainSID.IsPresent) { Get-UserSidDomain } Else { Get-UserSid } $userExperience = Get-UserExperience $userDateTime = Get-HexDateTime Write-Debug "UserDateTime: $userDateTime" Write-Debug "UserSid: $userSid" Write-Debug "UserExperience: $userExperience" $baseInfo = "$Extension$userSid$ProgId$userDateTime$userExperience".ToLower() Write-Verbose "baseInfo: $baseInfo" $progHash = Get-Hash $baseInfo Write-Verbose "Hash: $progHash" #Write AssociationToasts List Write-RequiredApplicationAssociationToasts $ProgId $Extension #Handle Extension Or Protocol if ($Extension.Contains(".")) { Write-Verbose "Write Registry Extension: $Extension" Write-ExtensionKeys $ProgId $Extension $progHash } else { Write-Verbose "Write Registry Protocol: $Extension" Write-ProtocolKeys $ProgId $Extension $progHash } if ($Icon) { Write-Verbose "Set Icon: $Icon" Set-Icon $ProgId $Icon } Update-RegistryChanges } function Set-PTA { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $ProgId, [Parameter(Mandatory = $true)] [String] $Protocol, [String] $Icon ) Set-FTA -ProgId $ProgId -Protocol $Protocol -Icon $Icon } |