1 #!powershell
2 
3 # Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
4 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5 
6 #AnsibleRequires -CSharpUtil Ansible.Basic
7 
8 # This modules does not accept any options
9 $spec = @{
10     supports_check_mode = $true
11 }
12 
13 $module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
14 
15 # First try to find the product key from ACPI
16 try {
17     $product_key = (Get-CimInstance -Class SoftwareLicensingService).OA3xOriginalProductKey
18 } catch {
19     $product_key = $null
20 }
21 
22 if (-not $product_key) {
23     # Else try to get it from the registry instead
24     try {
25         $data = Get-ItemPropertyValue -LiteralPath "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" -Name DigitalProductId
26     } catch {
27         $data = $null
28     }
29 
30     # And for Windows 2008 R2
31     if (-not $data) {
32         try {
33             $data = Get-ItemPropertyValue -LiteralPath "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" -Name DigitalProductId4
34         } catch {
35             $data = $null
36         }
37     }
38 
39     if ($data) {
40         $product_key = $null
41         $isWin8 = [int]($data[66]/6) -band 1
42         $HF7 = 0xF7
43         $data[66] = ($data[66] -band $HF7) -bOr (($isWin8 -band 2) * 4)
44         $hexdata = $data[52..66]
45         $chardata = "B","C","D","F","G","H","J","K","M","P","Q","R","T","V","W","X","Y","2","3","4","6","7","8","9"
46 
47         # Decode base24 binary data
48         for ($i = 24; $i -ge 0; $i--) {
49             $k = 0
50             for ($j = 14; $j -ge 0; $j--) {
51                 $k = $k * 256 -bxor $hexdata[$j]
52                 $hexdata[$j] = [math]::truncate($k / 24)
53                 $k = $k % 24
54             }
55             $product_key_output = $chardata[$k] + $product_key_output
56             $last = $k
57         }
58 
59         $product_key_tmp1 = $product_key_output.SubString(1,$last)
60         $product_key_tmp2 = $product_key_output.SubString(1,$product_key_output.Length - 1)
61         if ($last -eq 0) {
62             $product_key_output = "N" + $product_key_tmp2
63         } else {
64             $product_key_output = $product_key_tmp2.Insert($product_key_tmp2.IndexOf($product_key_tmp1) + $product_key_tmp1.Length, "N")
65         }
66         $num = 0
67         $product_key_split = @()
68         for ($i = 0; $i -le 4; $i++) {
69             $product_key_split += $product_key_output.SubString($num,5)
70             $num += 5
71         }
72         $product_key = $product_key_split -join "-"
73     }
74 }
75 
76 # Retrieve license information
77 $license_info = Get-CimInstance SoftwareLicensingProduct | Where-Object PartialProductKey
78 
79 $winlicense_status = switch ($license_info.LicenseStatus) {
80     0 { "Unlicensed" }
81     1 { "Licensed" }
82     2 { "OOBGrace" }
83     3 { "OOTGrace" }
84     4 { "NonGenuineGrace" }
85     5 { "Notification" }
86     6 { "ExtendedGrace" }
87     default { $null }
88 }
89 
90 $winlicense_edition = $license_info.Name
91 $winlicense_channel = $license_info.ProductKeyChannel
92 
93 $module.Result.ansible_facts = @{
94     ansible_os_product_id = (Get-CimInstance Win32_OperatingSystem).SerialNumber
95     ansible_os_product_key = $product_key
96     ansible_os_license_edition = $winlicense_edition
97     ansible_os_license_channel = $winlicense_channel
98     ansible_os_license_status = $winlicense_status
99 }
100 
101 $module.ExitJson()
102