diff --git a/Sophia/LTSC/Sophia.ps1 b/Sophia/LTSC/Sophia.ps1 index f1d470be..4d55f70f 100644 --- a/Sophia/LTSC/Sophia.ps1 +++ b/Sophia/LTSC/Sophia.ps1 @@ -2,8 +2,8 @@ .SYNOPSIS Default preset file for "Windows 10 Sophia Script" (LTSC version) - Version: v5.0.4 - Date: 20.02.2021 + Version: v5.0.5 + Date: 02.03.2021 Copyright (c) 2021 farag & oZ-Zo https://github.com/farag2 @@ -57,7 +57,7 @@ param Clear-Host -$Host.UI.RawUI.WindowTitle = "Windows 10 Sophia Script for LTSC v5.0.4 | $([char]0x00A9) farag & oz-zo, 2015–2021" +$Host.UI.RawUI.WindowTitle = "Windows 10 Sophia Script for LTSC v5.0.5 | $([char]0x00A9) farag & oz-zo, 2015–2021" Remove-Module -Name Sophia -Force -ErrorAction Ignore Import-Module -Name $PSScriptRoot\Sophia.psd1 -PassThru -Force @@ -459,8 +459,8 @@ StorageSenseRecycleBin -Enable # StorageSenseRecycleBin -Disable #endregion StorageSense -# Disable hibernation if the device is not a laptop -# Отключить режим гибернации, если устройство не является ноутбуком +# Disable hibernation +# Отключить режим гибернации Hibernate -Disable # Enable hibernate (default value) @@ -581,8 +581,8 @@ LatestInstalled.NET -Enable # Не использовать последнюю установленную версию .NET для всех приложений (значение по умолчанию) # LatestInstalled.NET -Disable -# Do not allow the computer (if device is not a laptop) to turn off the network adapters to save power -# Запретить отключение всех сетевых адаптеров для экономии энергии (если устройство не является ноутбуком) +# Do not allow the computer to turn off the network adapters to save power +# Запретить отключение всех сетевых адаптеров для экономии энергии PCTurnOffDevice -Disable # Allow the computer to turn off the network adapters to save power (default value) @@ -703,6 +703,22 @@ SmartActiveHours -Enable # Do not automatically adjust active hours for me based on daily usage (default value) # Не изменять автоматически период активности для этого устройства на основе действий (значение по умолчанию) # SmartActiveHours -Disable +<# + Register app, calculate hash, and set as default for specific extension without the "How do you want to open this?" pop-up + Зарегистрировать приложение, вычислить хэш и установить как приложение по умолчанию для конкретного расширения без всплывающего окошка "Каким образом вы хотите открыть этот файл?" + + Examples: + Примеры: + Set-Association -ProgramPath "C:\SumatraPDF.exe" -Extension .pdf -Icon "shell32.dll,100" + Set-Association -ProgramPath "C:\Program Files\Notepad++\notepad++.exe" -Extension .psm1 -Icon "C:\Program Files\Notepad++\notepad++.exe,0" + + The app must be installed + Приложение должно быть установлено + + Do not use relative paths like "%Program Files%" + Не используйте относительные пути вида "%Program Files%" +#> +# Set-Association -ProgramPath "C:\Program Files\Notepad++\notepad++.exe" -Extension .psm1 -Icon "C:\Program Files\Notepad++\notepad++.exe,0" #endregion System #region Start menu @@ -855,7 +871,7 @@ PUAppsDetection -Enable There is a bug in KVM with QEMU: enabling this function causes VM to freeze up during the loading phase of Windows Включить песочницу для Microsoft Defender - В KVM с QEMU присутсвует баг: включение этой функции приводит ВМ к зависанию во время загрузки Windows + В KVM с QEMU присутствует баг: включение этой функции приводит ВМ к зависанию во время загрузки Windows #> DefenderSandbox -Enable diff --git a/Sophia/LTSC/Sophia.psd1 b/Sophia/LTSC/Sophia.psd1 index 2d1ac390..92d99648 100644 Binary files a/Sophia/LTSC/Sophia.psd1 and b/Sophia/LTSC/Sophia.psd1 differ diff --git a/Sophia/LTSC/Sophia.psm1 b/Sophia/LTSC/Sophia.psm1 index 952d1db3..934f925b 100644 --- a/Sophia/LTSC/Sophia.psm1 +++ b/Sophia/LTSC/Sophia.psm1 @@ -463,9 +463,9 @@ function ScheduledTasks "XblGameSaveTask" ) - # If device is not a laptop disable FODCleanupTask too - # Если устройство не является ноутбуком, отключить также и FODCleanupTask - if ((Get-CimInstance -ClassName Win32_ComputerSystem).PCSystemType -ne 2) + # Check if device has a camera + $DeviceHasCamera = Get-CimInstance -ClassName Win32_PnPEntity | Where-Object -FilterScript {($_.PNPClass -eq "Camera") -or ($_.PNPClass -eq "Image")} + if (-not $DeviceHasCamera) { # Windows Hello $CheckedScheduledTasks += "FODCleanupTask" @@ -545,7 +545,7 @@ function ScheduledTasks { [void]$SelectedTasks.Remove($Task) } - + if ($SelectedTasks.Count -gt 0) { $Button.IsEnabled = $true @@ -1182,7 +1182,6 @@ function OpenFileExplorerTo <# .SYNOPSIS Hide Task View button on the taskbar - Скрыть кнопку Просмотра задач .PARAMETER Hide Show Task View button on the taskbar @@ -1835,7 +1834,7 @@ function TaskbarSearch <# .SYNOPSIS - Always show/hide all icons in the notification area + Configure icons in the notification area .PARAMETER Show Always show all icons in the notification area @@ -2753,7 +2752,7 @@ function StorageSenseRecycleBin Configure hibernation .PARAMETER Disable - Disable hibernation (if the device is not a laptop) + Disable hibernation .PARAMETER Enable Enable hibernation @@ -2765,6 +2764,7 @@ function StorageSenseRecycleBin Hibernate -Disable .NOTES + Do not recommend turning it off on laptops Current user #> function Hibernate @@ -2794,10 +2794,7 @@ function Hibernate } "Disable" { - if ((Get-CimInstance -ClassName Win32_ComputerSystem).PCSystemType -ne 2) - { - POWERCFG /HIBERNATE OFF - } + POWERCFG /HIBERNATE OFF } } } @@ -3375,21 +3372,12 @@ function WindowsFeatures # Initialize an array list to store the selected Windows features $SelectedFeatures = New-Object -TypeName System.Collections.ArrayList($null) - # The following FODv2 items will have their checkboxes checked + # The following Windows features will have their checkboxes checked [string[]]$CheckedFeatures = @( # Legacy Components # Компоненты прежних версий "LegacyComponents", - <# - Media Features - Компоненты работы с мультимедиа - - If you want to leave "Multimedia settings" in the advanced settings of Power Options do not disable this feature - Если вы хотите оставить параметр "Параметры мультимедиа" в дополнительных параметрах электропитания, не отключайте этот компонент - #> - "MediaPlayback", - # PowerShell 2.0 "MicrosoftWindowsPowerShellV2", "MicrosoftWindowsPowershellV2Root", @@ -3402,6 +3390,18 @@ function WindowsFeatures # Клиент рабочих папок "WorkFolders-Client" ) + + # The following Windows features will have their checkboxes unchecked + [string[]]$UncheckedFeatures = @( + <# + Media Features + Компоненты работы с мультимедиа + + If you want to leave "Multimedia settings" in the advanced settings of Power Options do not disable this feature + Если вы хотите оставить параметр "Параметры мультимедиа" в дополнительных параметрах электропитания, не отключайте этот компонент + #> + "MediaPlayback" + ) #endregion Variables #region XAML Markup @@ -3538,10 +3538,15 @@ function WindowsFeatures $CheckBox.IsChecked = $true # If feature checked add to the array list - if ($CheckBox.IsChecked) + if ($UnCheckedFeatures | Where-Object -FilterScript {$Feature.FeatureName -like $_}) { - [void]$SelectedFeatures.Add($Feature) + $CheckBox.IsChecked = $false + # Exit function if item is not checked + return } + + # If feature checked add to the array list + [void]$SelectedFeatures.Add($Feature) } } #endregion Functions @@ -3568,7 +3573,7 @@ function WindowsFeatures # Getting list of all optional features according to the conditions $OFS = "|" $Features = Get-WindowsOptionalFeature -Online | Where-Object -FilterScript { - ($_.State -in $State) -and ($_.FeatureName -cmatch $CheckedFeatures) + ($_.State -in $State) -and (($_.FeatureName -cmatch $UncheckedFeatures) -or ($_.FeatureName -cmatch $CheckedFeatures)) } | ForEach-Object -Process {Get-WindowsOptionalFeature -FeatureName $_.FeatureName -Online} $OFS = " " @@ -3630,18 +3635,17 @@ function WindowsCapabilities Add-Type -AssemblyName PresentationCore, PresentationFramework #region Variables - # Initialize an array list to store the selected FODv2 items + # Initialize an array list to store the selected optional features $SelectedCapabilities = New-Object -TypeName System.Collections.ArrayList($null) - # The following FODv2 items will have their checkboxes checked + # The following optional features will have their checkboxes checked [string[]]$CheckedCapabilities = @( # Microsoft Quick Assist # Быстрая поддержка (Майкрософт) "App.Support.QuickAssist*" ) - # The following FODv2 items will have their checkboxes unchecked - # Следующие дополнительные компоненты будут иметь чекбоксы неотмеченными + # The following optional features will have their checkboxes unchecked [string[]]$UncheckedCapabilities = @( # Internet Explorer 11 "Browser.InternetExplorer*", @@ -3664,7 +3668,7 @@ function WindowsCapabilities "OpenSSH.Client*" ) - # The following FODv2 items will be excluded from the display + # The following optional features will be excluded from the display [string[]]$ExcludedCapabilities = @( # The DirectX Database to configure and optimize apps when multiple Graphics Adapters are present # База данных DirectX для настройки и оптимизации приложений при наличии нескольких графических адаптеров @@ -3939,7 +3943,7 @@ function UpdateMicrosoftProducts { "Disable" { - if ((New-Object -ComObject Microsoft.Update.ServiceManager).Services | Where-Object {$_.ServiceID -eq "7971f918-a847-4430-9279-4a52d1efe18d"} ) + if ((New-Object -ComObject Microsoft.Update.ServiceManager).Services | Where-Object {$_.ServiceID -eq "7971f918-a847-4430-9279-4a52d1efe18d"}) { (New-Object -ComObject Microsoft.Update.ServiceManager).RemoveService("7971f918-a847-4430-9279-4a52d1efe18d") } @@ -3956,7 +3960,7 @@ function UpdateMicrosoftProducts Configure the power management scheme .PARAMETER High - Set the power management scheme on "High performance" if device is a desktop + Set the power management scheme on "High performance" .PARAMETER Balanced Set the power management scheme on "Balanced" @@ -3968,6 +3972,7 @@ function UpdateMicrosoftProducts PowerManagementScheme -Balanced .NOTES + Do not recommend turning "High performance" scheme on on laptops Current user #> function PowerManagementScheme @@ -3993,10 +3998,7 @@ function PowerManagementScheme { "High" { - if ((Get-CimInstance -ClassName Win32_ComputerSystem).PCSystemType -eq 1) - { - POWERCFG /SETACTIVE SCHEME_MIN - } + POWERCFG /SETACTIVE SCHEME_MIN } "Balanced" { @@ -4060,7 +4062,7 @@ function LatestInstalled.NET <# .SYNOPSIS - Configure all network adapters to be disabled to save power + Configure network adapters to save power .PARAMETER Disable Do not allow the computer to turn off the network adapters to save power @@ -4075,7 +4077,7 @@ function LatestInstalled.NET PCTurnOffDevice -Enable .NOTES - If device is not a laptop + Do not recommend turning it on on laptops .NOTES Current user @@ -4105,24 +4107,18 @@ function PCTurnOffDevice { "Disable" { - if ((Get-CimInstance -ClassName Win32_ComputerSystem).PCSystemType -ne 2) + foreach ($Adapter in $Adapters) { - foreach ($Adapter in $Adapters) - { - $Adapter.AllowComputerToTurnOffDevice = "Disabled" - $Adapter | Set-NetAdapterPowerManagement - } + $Adapter.AllowComputerToTurnOffDevice = "Disabled" + $Adapter | Set-NetAdapterPowerManagement } } "Enable" { - if ((Get-CimInstance -ClassName Win32_ComputerSystem).PCSystemType -ne 2) + foreach ($Adapter in $Adapters) { - foreach ($Adapter in $Adapters) - { - $Adapter.AllowComputerToTurnOffDevice = "Enabled" - $Adapter | Set-NetAdapterPowerManagement - } + $Adapter.AllowComputerToTurnOffDevice = "Enabled" + $Adapter | Set-NetAdapterPowerManagement } } } @@ -4242,10 +4238,11 @@ function SetUserShellFolderLocation .EXAMPLE UserShellFolder -UserFolder Desktop -FolderPath "$env:SystemDrive:\Desktop" -RemoveDesktopINI + .LINK + https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath + .NOTES User files or folders won't me moved to a new location - - https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath #> function UserShellFolder { @@ -4408,8 +4405,8 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int .EXAMPLE ShowMenu -Menu $ListOfItems -Default $DefaultChoice - .NOTES - https://qna.habr.com/user/MaxKozlov + .LINK + https://qna.habr.com/answer?answer_id=1522379 #> function ShowMenu { @@ -5556,6 +5553,433 @@ function SmartActiveHours } } } +<# + .SYNOPSIS + Register app, calculate hash, and set as default for specific extension without the "How do you want to open this" pop-up + + .PARAMETER ProgramPath + Set path to the .exe + + .PARAMETER Extension + Set extension type + + .PARAMETER Icon + Set path to the icon + + .EXAMPLE + Set-Association -ProgramPath "C:\SumatraPDF.exe" -Extension .pdf -Icon "shell32.dll,100" + + .EXAMPLE + Set-Association -ProgramPath "C:\Program Files\Notepad++\notepad++.exe" -Extension .psm1 -Icon "C:\Program Files\Notepad++\notepad++.exe,0" + + .LINK + https://github.com/DanysysTeam/PS-SFTA + + .NOTES + The app must be installed + Do not use relative paths like "%Program Files%" + Current user +#> +function Set-Association +{ + [CmdletBinding()] + param + ( + [Parameter( + Position = 0, + Mandatory = $true + )] + [ValidateScript({Test-Path -Path $_})] + [String] + $ProgramPath, + + [Parameter( + Position = 1, + Mandatory = $true + )] + [String] + $Extension, + + [Parameter( + Position = 3, + Mandatory = $false + )] + [String] + $Icon + ) + + $ProgId = "Applications\" + (Get-Item -Path $ProgramPath).BaseName + $Extension + + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids")) + { + New-Item -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids" -Force + } + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids" -Name $ProgId -PropertyType None -Value ([byte[]]@()) -Force + + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command")) + { + New-Item -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command" -Force + } + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command" -Name "(Default)" -PropertyType String -Value "`"$ProgramPath`" `"%1`"" -Force + + function Set-FTA + { + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [String] + $ProgId, + + [Parameter(Mandatory = $true)] + [String] + $Extension, + + [String] + $Icon + ) + + function local:Set-Icon + { + param + ( + [Parameter( + Position = 0, + Mandatory = $true + )] + [String] + $ProgId, + + [Parameter( + Position = 1, + Mandatory = $true + )] + [String] + $Icon + ) + + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon")) + { + New-Item -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon" -Force + } + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon" -Name "(Default)" -PropertyType String -Value $Icon -Force + } + + 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 + ) + + $Signature = @{ + Namespace = "Registry" + Name = "Utils" + Language = "CSharp" + MemberDefinition = @" +[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); +} +"@ + } + + if (-not ("Registry.Utils" -as [type])) + { + Add-Type @Signature + } + + [Registry.Utils]::DeleteKey($Key) + } + + Remove-UserChoiceKey -Key "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" + + if (-not (Test-Path -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice")) + { + New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Force + } + New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Name Hash -PropertyType String -Value $ProgHash -Force + New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Name ProgId -PropertyType String -Value $ProgId -Force + } + + 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() + + return $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) + { + return (($iValue -shr $iCount) -bxor 0xFFFF0000) + } + else + { + return ($iValue -shr $iCount) + } + } + + function local:Get-Long + { + [CmdletBinding()] + param + ( + [Parameter( + Position = 0, + Mandatory = $true + )] + [byte[]] + $Bytes, + + [Parameter(Position = 1)] + [int] + $Index = 0 + ) + + return ([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 -iValue $lengthBase -iCount 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 -Bytes $bytesMD5) -bor 1) + 0x69FB0000L) + $Map.MD52 = ((Get-Long -Bytes $bytesMD5 -Index 4) -bor 1) + 0x13DB0000L + $Map.INDEX = Get-ShiftRight -iValue ($length - 2) -iCount 1 + $Map.COUNTER = $Map.INDEX + 1 + + while ($Map.COUNTER) + { + $Map.R0 = Convert-Int32 -Value ((Get-Long -Bytes $bytesBaseInfo -Index $Map.PDATA) + [long]$Map.OUTHASH1) + $Map.R1[0] = Convert-Int32 -Value (Get-Long -Bytes $bytesBaseInfo -Index ($Map.PDATA + 4)) + $Map.PDATA = $Map.PDATA + 8 + $Map.R2[0] = Convert-Int32 -Value (($Map.R0 * ([long]$Map.MD51)) - (0x10FA9605L * ((Get-ShiftRight -iValue $Map.R0 -iCount 16)))) + $Map.R2[1] = Convert-Int32 -Value ((0x79F8A395L * ([long]$Map.R2[0])) + (0x689B6B9FL * (Get-ShiftRight -iValue $Map.R2[0] -iCount 16))) + $Map.R3 = Convert-Int32 -Value ((0xEA970001L * $Map.R2[1]) - (0x3C101569L * (Get-ShiftRight -iValue $Map.R2[1] -iCount 16) )) + $Map.R4[0] = Convert-Int32 -Value ($Map.R3 + $Map.R1[0]) + $Map.R5[0] = Convert-Int32 -Value ($Map.CACHE + $Map.R3) + $Map.R6[0] = Convert-Int32 -Value (($Map.R4[0] * [long]$Map.MD52) - (0x3CE8EC25L * (Get-ShiftRight -iValue $Map.R4[0] -iCount 16))) + $Map.R6[1] = Convert-Int32 -Value ((0x59C3AF2DL * $Map.R6[0]) - (0x2232E0F1L * (Get-ShiftRight -iValue $Map.R6[0] -iCount 16))) + $Map.OUTHASH1 = Convert-Int32 -Value ((0x1EC90001L * $Map.R6[1]) + (0x35BD1EC9L * (Get-ShiftRight -iValue $Map.R6[1] -iCount 16))) + $Map.OUTHASH2 = Convert-Int32 -Value ([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 -Bytes $bytesMD5) -bor 1) + $Map.MD52 = ((Get-Long -Bytes $bytesMD5 4) -bor 1) + $Map.INDEX = Get-ShiftRight -iValue ($length - 2) -iCount 1 + $Map.COUNTER = $Map.INDEX + 1 + + while ($Map.COUNTER) + { + $Map.R0 = Convert-Int32 -Value ((Get-Long -Bytes $bytesBaseInfo -Index $Map.PDATA) + ([long]$Map.OUTHASH1)) + $Map.PDATA = $Map.PDATA + 8 + $Map.R1[0] = Convert-Int32 -Value ($Map.R0 * [long]$Map.MD51) + $Map.R1[1] = Convert-Int32 -Value ((0xB1110000L * $Map.R1[0]) - (0x30674EEFL * (Get-ShiftRight -iValue $Map.R1[0] -iCount 16))) + $Map.R2[0] = Convert-Int32 -Value ((0x5B9F0000L * $Map.R1[1]) - (0x78F7A461L * (Get-ShiftRight -iValue $Map.R1[1] -iCount 16))) + $Map.R2[1] = Convert-Int32 -Value ((0x12CEB96DL * (Get-ShiftRight -iValue $Map.R2[0] 16)) - (0x46930000L * $Map.R2[0])) + $Map.R3 = Convert-Int32 -Value ((0x1D830000L * $Map.R2[1]) + (0x257E1D83L * (Get-ShiftRight -iValue $Map.R2[1] -iCount 16))) + $Map.R4[0] = Convert-Int32 -Value ([long]$Map.MD52 * ([long]$Map.R3 + (Get-Long -Bytes $bytesBaseInfo -Index ($Map.PDATA - 4)))) + $Map.R4[1] = Convert-Int32 -Value ((0x16F50000L * $Map.R4[0]) - (0x5D8BE90BL * (Get-ShiftRight -iValue $Map.R4[0] -iCount 16))) + $Map.R5[0] = Convert-Int32 -Value ((0x96FF0000L * $Map.R4[1]) - (0x2C7C6901L * (Get-ShiftRight -iValue $Map.R4[1] -iCount 16))) + $Map.R5[1] = Convert-Int32 -Value ((0x2B890000L * $Map.R5[0]) + (0x7C932B89L * (Get-ShiftRight -iValue $Map.R5[0] -iCount 16))) + $Map.OUTHASH1 = Convert-Int32 -Value ((0x9F690000L * $Map.R5[1]) - (0x405B6097L * (Get-ShiftRight -iValue ($Map.R5[1]) -iCount 16))) + $Map.OUTHASH2 = Convert-Int32 -Value ([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 -Bytes $outHash -Index 8) -bxor (Get-Long -Bytes $outHash)) + $hashValue2 = ((Get-Long -Bytes $outHash 12) -bxor (Get-Long -Bytes $outHash -Index 4)) + + $buffer = [BitConverter]::GetBytes($hashValue1) + $buffer.CopyTo($outHashBase, 0) + $buffer = [BitConverter]::GetBytes($hashValue2) + $buffer.CopyTo($outHashBase, 4) + $base64Hash = [Convert]::ToBase64String($outHashBase) + } + + return $base64Hash + } + + # Get current user SID + $userSid = (Get-CimInstance -ClassName Win32_UserAccount | Where-Object -FilterScript {$_.Name -eq $env:USERNAME}).SID + # Secret static string stored in %SystemRoot%\SysWOW64\shell32.dll + $userExperience = "User Choice set via Windows User Experience {D18B6DD5-6124-4341-9318-804003BAFA0B}" + $userDateTime = Get-HexDateTime + $baseInfo = "$Extension$userSid$ProgId$userDateTime$userExperience".ToLower() + $ProgHash = Get-Hash -BaseInfo $baseInfo + + # Handle Extension + Write-ExtensionKeys -ProgId $ProgId -Extension $Extension -ProgHash $ProgHash + + if ($Icon) + { + Set-Icon -ProgId $ProgId -Icon $Icon + } + } + + Set-FTA -ProgId $ProgId -Extension $Extension -Icon $Icon +} #endregion System #region Start menu