;; 
;;=====================================================================================----- 
;; 
;;FUNCTION       GetMSKeys() 
;; 
;;ACTION         Returns an array of Product;License_Key data for all installed MSft products 
;; 
;;AUTHOR         Allen Powell 
;;		 Adapted by Glenn Barnas 
;; 
;;VERSION        1.0 - 2014/01/11 
;; 
;;HISTORY        1.0 - 2014/01/11 - Initial Release 
;; 
;;SYNTAX         GetMSKeys() 
;; 
;;PARAMETERS     none - operates on local computer 
;; 
;;REMARKS         
;; 
;;RETURNS        Array in "product;License_Key" format 
;; 
;;DEPENDENCIES   Get_Product_Key() UDF included in this file 
;;		 SearchReg() and ArrayAdd() external UDFs 
;; 
;;TESTED WITH    WXP, W2K3, W2K8, W2K12, Win7, Win8 
;; 
;;EXAMPLES       $aMSProd = GetMSKeys() 
; 
Function GetMSKeys()
 
  Dim $_RegArray						; Results of SearchReg call 
  Dim $_RegView							; State of WOW64AlternateRegView 
  Dim $_Value							; Array enumerator 
  Dim $_Product							; Product name 
  Dim $_Key							; Reg Key String 
  Dim $_Array2							; secondary array 
  Dim $_Guid							; Product GUID string 
  Dim $_I							; Index 
  Dim $_aCollect[0]						; collection array 
 
  $GetMSKeys = $_aCollect					; Default return empty 
  $_I = -1							; init pointer to empty array  
 
  $_RegView = SetOption('WOW64AlternateRegView','On')
 
  ; Get array of keys (native) 
  $_RegArray = SearchReg('HKLM\Software\Microsoft','DigitalProductID',2)
 
  If @ONWOW64
    ; Get array of x64-mode keys and combine with results of native query 
    $_Array2 = SearchReg('HKLM\Software\WOW6432NODE\Microsoft', 'DigitalProductID', 2)
    $_RegArray = ArrayAdd($_RegArray, $_Array2)
  EndIf
 
  ; Exit if none found, otherwise build an array to return 
  If UBound($_RegArray) < 0
    Exit 2
  Else
    For Each $_Value In $_RegArray
      If $_Value
        $_Product = ReadValue(Join(Split($_Value, '<=>DigitalProductId'), ''), 'ProductName')
        If $_Product = ''
          $_Guid = '{' + Split(Split($_Value, '{')[1], '}')[0] + '}'
          If InStr($_Value, 'WOW6432Node')
            $_Product = ReadValue('HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' + $_Guid, 'DisplayName')
          Else
            $_Product = ReadValue('HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\' + $_Guid, 'DisplayName')
          Endif
        Endif
        If $_Product
          $_Key = Get_Product_Key(ReadValue(Join(Split($_Value, '<=>DigitalProductId'), ''), 'DigitalProductID'))
          $_I = $_I + 1
          ReDim Preserve $_aCollect[$_I]
          $_aCollect[$_I] = $_Product + ';' + $_Key
        EndIf
      EndIf
    Next
  EndIf
 
  $_RegView = SetOption('WOW64AlternateRegView', $_RegView)
 
  $GetMSKeys = $_aCollect
  Exit 0
 
EndFunction
 
 
; Return an extracted license key from the ProductID 
Function Get_Product_Key($_sProductID)
 
  Dim $_aiKeyChars[24]
  Dim $_ilByte
  Dim $_I
  Dim $_iLOffset, $_iUOffset
  Dim $_bProductKey[15]
  Dim $_C
  Dim $_nCur
  Dim $_sCDKey
 
  For Each $_C In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $_aiKeyChars[$_I] = Asc($_C)
    $_I = $_I + 1
  Next
 
  If Len($_sProductID) = 2544
    $_iLOffset = 809
    $_iUOffset = 823
  Else
    $_iLOffset = 53
    $_iUOffset = 67
  EndIf
 
  For $_I = $_iLOffset * 2 - 1 To $_iUOffset * 2 - 1 Step 2
    $_bProductKey[($_I - ($_iLOffset * 2 - 1)) / 2] = Execute( "Exit &" + SubStr($_sProductId, $_I, 2))
  Next
 
  For $_ilByte = 24 To 0 Step -1
    $_nCur = 0
    For $_I = 14 To 0 Step -1
      $_nCur = $_nCur * 256 ^ $_bProductKey[$_I]			; NOTE THE XOR!  
      $_bProductKey[$_I] = Int($_nCur / 24)
      $_nCur = $_nCur Mod 24
    Next
 
    $_sCDKey = Chr($_aiKeyChars[$_nCur]) + $_sCDKey
    If $_ilByte Mod 5 = 0 And $_ilByte <> 0
      $_sCDKey = "-" + $_sCDKey
    EndIf
 
  Next
 
  $Get_Product_Key = $_sCDKey
  Exit 0
 
EndFunction