# encoding: ascii
# api: powershell
# title: Get-WindowsProduct
# description: Version which correctly works with Windows 8.
# version: 0.1
# type: function
# author: Skourlatov
# license: CC0
# function: Get-WindowsProduct
# x-poshcode-id: 5106
# x-archived: 2014-04-26T17:38:18
# x-published: 2014-04-22T17:27:00
#
# It’s fast because WMI classes are not used.
# Works local.
#
Function Get-WindowsProduct
{
	function DecodeDigitalPID($digitalProductId)
	{
		New-Variable -Name base24 -Value 'BCDFGHJKMPQRTVWXY2346789' -Option Constant
		New-Variable -Name cryptedStringLength -Value 24 -Option Constant
		New-Variable -Name decryptionLength -Value 14 -Option Constant
		New-Variable -Name decryptedKey -Value ([System.String]::Empty)

		$containsN = ($digitalProductId[$decryptionLength] -shr 3) -bAnd 1
		$digitalProductId[$decryptionLength] = [System.Byte]($digitalProductId[$decryptionLength] -bAnd 0xF7) ## 247

		for ($i = $cryptedStringLength; $i -ge 0; $i--)
		{
			$digitMapIndex = 0
			for ($j = $decryptionLength; $j -ge 0; $j--)
			{
				$digitMapIndex = [System.UInt16]($digitMapIndex -shl 8 -bXor $digitalProductId[$j])
				$digitalProductId[$j] = [System.Byte][System.Math]::Floor($digitMapIndex / $base24.Length)
				$digitMapIndex = [System.UInt16]($digitMapIndex % $base24.Length)
			}
			$decryptedKey = $decryptedKey.Insert(0, $base24[$digitMapIndex])
		}

		if ([System.Boolean]$containsN)
		{
			$firstCharIndex = 0
			for ($index = 0; $index -lt $cryptedStringLength; $index++)
			{
				if ($decryptedKey[0] -ne $base24[$index]) {continue}
				$firstCharIndex = $index
				break
			}
			$keyWithN = $decryptedKey
			$keyWithN = $keyWithN.Remove(0, 1)
			$keyWithN = $keyWithN.Substring(0, $firstCharIndex) + 'N' + $keyWithN.Remove(0, $firstCharIndex)
			$decryptedKey = $keyWithN;
		}

		$returnValue = $decryptedKey
		for ($t = 20; $t -ge 5; $t -= 5)
		{
			$returnValue = $returnValue.Insert($t, '-')
		}

		return $returnValue
	} ## end DecodeDigitalPID

	$regPath = 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion'
	$binArray = $(Get-ItemProperty -Path $regPath).DigitalProductId[52..66]
	$preObject = @{
		ProductKey = DecodeDigitalPID($binArray)
		ProductID  = $(Get-ItemProperty -Path $regPath).ProductId;
		Edition    = $(Get-ItemProperty -Path $regPath).EditionID;
		Type       = 'x86';
		Version    = [System.Environment]::OSVersion.VersionString;
	}
	if ([System.Environment]::Is64BitOperatingSystem) {$preObject.Type += '-64'}
	$object = New-Object -TypeName System.Management.Automation.PSObject -Property $preObject
	Write-Output $object | Select-Object Version, Edition, Type, ProductID, ProductKey
} ## End Get-WindowsProduct
