Get product keys of Windows and Office products PB 5.20
Posted: Thu May 28, 2009 1:33 pm
Updated for 5.20+
View Windows and every single Office Product Key separately (as long as separate installation is done for each product).
The code has been updated for PB 5.20 and supports up to Office 2013 with multiple Office product support (in case we have lost the keys).
View Windows and every single Office Product Key separately (as long as separate installation is done for each product).
The code has been updated for PB 5.20 and supports up to Office 2013 with multiple Office product support (in case we have lost the keys).
Code: Select all
Import ""
GetNativeSystemInfo(*info)
EndImport
Global REG_BINARY.i=3
Procedure.s GetString(hKey.l, strPath.s, strValue.s, RegType.l=2)
;this procedure is reading the registry values when we know
;exactly what we want to read and where to read
;OnErrorResume()
KeyHand.l:datatype.l:lResult.l
Dim strBuf.b(1):lDataBufSize.l
intZeroPos.l:tempV.l:mm.l
RegOpenKeyEx_(hKey, strPath, 0, $101, @KeyHand)
lResult = RegQueryValueEx_(KeyHand, strValue, 0, @lValueType, 0, @lDataBufSize)
If lDataBufSize > 0
ReDim strBuf.b(lDataBufSize-1)
EndIf
lResult = RegQueryValueEx_(KeyHand, @strValue, 0, @RegType, @strBuf(), @lDataBufSize)
If lResult = #ERROR_SUCCESS
If lValueType = 4
tempV.l = 0
For i = 0 To lDataBufSize-1
tempV = tempV + (strBuf(i) & $FF) * Pow(16,(2 * i))
Next
ProcedureReturn StrU(tempV,#PB_Long)
EndIf
tmp.s
If RegType = #REG_MULTI_SZ
For i=0 To lDataBufSize-1
If strBuf(i)=0
tmp + " , "
Else
tmp+ Chr(strBuf(i))
EndIf
Next
For i=lDataBufSize-1 To 0 Step -1
If Right(tmp,3)=" , ":tmp = Left(tmp,Len(tmp)-3):EndIf
Next
ProcedureReturn tmp + "."
EndIf
For i=0 To lDataBufSize-1
tmp+ Chr(strBuf(i))
Next
ProcedureReturn tmp
EndIf
EndProcedure
Procedure.s ReadReg(ReadKey.l, SubKey.s, ReadValue.s, ValueType.l, LookInSubFolders.l, HelpValue.s, HelpValueRead.s, Array ArrayToRecieveData.b(1), HelpFolder.s="", ReturnPath.l=0)
;this procedure is reading the registry values when we DO NOT know
;exactly what we want to read and where to read
;OnErrorResume()
RequesySubKey.s: TempStr.s: RLen.l: Result.l
STime.FILETIME: MaxValLen.l: azz.l:tmp.s
MaxValNameLen.l: MaxSubKeyLen.l: MaxSubKeyLen2.l
SubKeys.l: Values.l: hKey.i: i.l
hKey1.l: hKey2.l:SKey.s:SKey2.s
Result = RegOpenKeyEx_(ReadKey, SubKey, 0, #KEY_ALL_ACCESS, @hKey)
If Result <> 0
RegOpenKeyEx_(ReadKey, SubKey, 0, #KEY_ALL_ACCESS |$100, @hKey)
EndIf
Result = RegQueryInfoKey_(hKey, 0, 0, 0, @SubKeys, @MaxSubKeyLen, 0, @Values, @MaxValNameLen, @MaxValLen, 0, STime)
keynum = SubKeys
For i = 0 To keynum - 1
TempStr = Space(255)
RLen = 255
Result = RegEnumKey_(hKey, i, @TempStr, @RLen)
SKey = SubKey + "\" + TempStr
If LookInSubFolders > 0
For ii=1 To LookInSubFolders
Result = RegOpenKeyEx_(ReadKey, SKey, 0, $101, @hKey1)
Result = RegQueryInfoKey_(hKey1, 0, 0, 0, @SubKeys, @MaxSubKeyLen, 0, @Values, @MaxValNameLen, @MaxValLen, 0, STime)
For iii=0 To SubKeys-1
TempStr = Space(255): RLen = 255
Result = RegEnumKey_(hKey1, iii, @TempStr, @RLen)
SKey2 = SKey + "\" + TempStr
If RegOpenKeyEx_(ReadKey, SKey2 + "\" + HelpFolder, 0, $101, @hKey2) = #ERROR_SUCCESS
azz = 1
RegCloseKey_(hKey2)
Break
EndIf
Next
If azz = 1
RegCloseKey_(hKey1)
RegCloseKey_(hKey)
ProcedureReturn GetString(ReadKey,SKey2,ReadValue,ValueType)
EndIf
Next
EndIf
If HelpValue <> ""
tmpp.s=GetString(ReadKey,SKey,HelpValue,#REG_SZ)
If FindString(tmpp,HelpValueRead,1) = 0
Goto ReadNext
EndIf
EndIf
tmp = GetString(ReadKey, SKey, ReadValue,ValueType)
If tmp<> ""
datalen.l;=164
RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, sKey, 0, $101, @hKey2)
RegQueryValueEx_(hKey2, "DigitalProductID", 0, @lValueType, 0, @datalen)
If datalen > 0
ReDim ArrayToRecieveData.b(datalen-1)
EndIf
RegQueryValueEx_(hKey2, @"DigitalProductID", 0, @REG_BINARY, @ArrayToRecieveData(), @datalen)
Result = RegCloseKey_(hKey2)
Result = RegCloseKey_(hKey)
If ReturnPath>0
ProcedureReturn SKey
Else
ProcedureReturn tmp
EndIf
EndIf
ReadNext:
Next
EndProcedure
Procedure.s IsWin64()
Protected Info.SYSTEM_INFO
GetNativeSystemInfo(Info)
If info\wProcessorArchitecture
ProcedureReturn "Wow6432Node\"
EndIf
EndProcedure
Procedure.s DecodeKey(Array KeyData.b(1), DecodeOffset.l)
;The reading Offset is 808 for Office 2010 and 52 for Windows and older Office versions.
Dim bProductKey.a(14)
For ilByte = DecodeOffset To DecodeOffset + 14
bProductKey(ilByte - DecodeOffset) = KeyData(ilByte)
Next
For i=0 To 14
Debug Hex(bProductKey(i))
Next
Dim bKeyChars.b(24)
;Now we are going To 'base24' decode the Product Key
;Possible characters in the CD Key:
bKeyChars(0) = Asc("B")
bKeyChars(1) = Asc("C")
bKeyChars(2) = Asc("D")
bKeyChars(3) = Asc("F")
bKeyChars(4) = Asc("G")
bKeyChars(5) = Asc("H")
bKeyChars(6) = Asc("J")
bKeyChars(7) = Asc("K")
bKeyChars(8) = Asc("M")
bKeyChars(9) = Asc("P")
bKeyChars(10) = Asc("Q")
bKeyChars(11) = Asc("R")
bKeyChars(12) = Asc("T")
bKeyChars(13) = Asc("V")
bKeyChars(14) = Asc("W")
bKeyChars(15) = Asc("X")
bKeyChars(16) = Asc("Y")
bKeyChars(17) = Asc("2")
bKeyChars(18) = Asc("3")
bKeyChars(19) = Asc("4")
bKeyChars(20) = Asc("6")
bKeyChars(21) = Asc("7")
bKeyChars(22) = Asc("8")
bKeyChars(23) = Asc("9")
nCur.i: sCDKey.s
ilKeyByte.i: ilBit.i
For ilByte = 24 To 0 Step -1
;Step through each character in the CD key
nCur = 0
For ilKeyByte = 14 To 0 Step -1
;Step through each byte in the Product Key
nCur = (nCur * 256) ! bProductKey(ilKeyByte)
bProductKey(ilKeyByte) = Int(nCur / 24)
nCur = nCur % 24
Next
sCDKey = Chr(bKeyChars(nCur)) + sCDKey
If (ilByte % 5) = 0 And ilByte <> 0 : sCDKey = "-" + sCDKey:EndIf
Next
ProcedureReturn sCDKey
EndProcedure
Procedure.s WindowsKeys(KeyType.l, KeyFix.s, Array DataArray.s(1))
ilByte.l: lDataLen.l = 1270: hKey.l: keyval.s: Dim TempStr.s(66)
Dim bDigitalProductID.b(lDataLen)
;The keytype tell us which key do we need.
;Each office product can be installed separately from the CD (in some cases)
;with its own key so we will take them all, if they exist.
ArrayCount.l=-1
Select KeyType
Case 0 ;office key
For i.l = 15 To 14 Step -1
keyval = "SOFTWARE\" + IsWin64() + "Microsoft\Office\" + Str(i) + ".0\Registration"
value.s=ReadReg(#HKEY_LOCAL_MACHINE,keyval,"DigitalProductId",@REG_BINARY,0,"ProductNameNonQualified","Microsoft Office",bDigitalProductID(),"",0)
If value <>""
ArrayCount + 1
If ArraySize(DataArray()) < ArrayCount: ReDim DataArray.s(ArrayCount): EndIf
DataArray(ArrayCount) = RSet(Str(i),2,"0") + DecodeKey(bDigitalProductID(),52)
EndIf
Next
For i.l = 12 To 1 Step -1
keyval = "SOFTWARE\" + IsWin64() + "Microsoft\Office\" + Str(i) + ".0\Registration"
value.s=ReadReg(#HKEY_LOCAL_MACHINE,keyval,"DigitalProductId",@REG_BINARY,0,"SuiteName","Microsoft Office",bDigitalProductID(),"",0)
If value <>""
;Debug value
ArrayCount + 1
If ArraySize(DataArray()) < ArrayCount: ReDim DataArray.s(ArrayCount): EndIf
DataArray(ArrayCount) = RSet(Str(i),2,"0") + DecodeKey(bDigitalProductID(),52)
EndIf
Next
Case 1 To 13 ;Products
For i.l = 15 To 14 Step -1
keyval = "SOFTWARE\" + IsWin64() + "Microsoft\Office\" + Str(i) + ".0\Registration"
value.s=ReadReg(#HKEY_LOCAL_MACHINE,keyval,"DigitalProductId",@REG_BINARY,0,"ProductNameNonQualified","Microsoft Office" + KeyFix,bDigitalProductID(),"",0)
If value <>""
;Debug value
ArrayCount + 1
If ArraySize(DataArray()) < ArrayCount: ReDim DataArray.s(ArrayCount): EndIf
DataArray(ArrayCount) = RSet(Str(i),2,"0") + DecodeKey(bDigitalProductID(),52)
EndIf
Next
For i.l = 1 To 12
keyval = "SOFTWARE\" + IsWin64() + "Microsoft\Office\" + Str(i) + ".0\Registration"
;"ProductName" is needed to take the key for the correct product
keyval=ReadReg(#HKEY_LOCAL_MACHINE,keyval,"DigitalProductId",@REG_BINARY,0,"ProductName","Microsoft Office " + KeyFix,bDigitalProductID(),"",1)
If keyval <>""
ArrayCount + 1
If ArraySize(DataArray()) < ArrayCount: ReDim DataArray.s(ArrayCount): EndIf
DataArray(ArrayCount) = RSet(Str(i),2,"0") + DecodeKey(bDigitalProductID(),52)
EndIf
Next
FreeArray(bDigitalProductID())
If ArrayCount = -1: DataArray(0) = " Not Available": EndIf
EndSelect
EndProcedure
Procedure.s DecodeVersion(dta.l)
Select dta
Case 15
ProcedureReturn "2013"
Case 14
ProcedureReturn "2010"
Case 12
ProcedureReturn "2007"
Case 11
ProcedureReturn "2003"
Case 10
ProcedureReturn "XP"
Case 9
ProcedureReturn"2000"
Case 8
ProcedureReturn"97"
Case 7
ProcedureReturn "95"
Case 0
ProcedureReturn ""
Default
ProcedureReturn Str(dta)
EndSelect
EndProcedure
;show me results
If OpenWindow(0, 100, 200, 470, 360, "Product Keys", #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
ListIconGadget(0,10,10,450,340,"Product",120,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
AddGadgetColumn(0,1,"Version",80)
AddGadgetColumn(0,2,"Key",220)
;get the keys
Dim DatArr.s(1)
Dim Product.s(14)
Product(0) = "Office"
Product(1) = "Access"
Product(2) = "Excel"
Product(3) = "Outlook"
Product(4) = "PowerPoint"
Product(5) = "Word"
Product(6) = "FrontPage"
Product(7) = "InfoPath"
Product(8) = "Publisher"
Product(9) = "Visio"
Product(10) = "OneNote"
Product(11) = "Project"
Product(12) = "SharePoint Designer"
Product(13) = "SharePoint Workspace"
;windows
Dim bDigitalProductID.b(164):lDataLen.l = 164
Select OSVersion()
Case #PB_OS_Windows_95, #PB_OS_Windows_98, #PB_OS_Windows_ME
keyval.s = "SOFTWARE\Microsoft\Windows\CurrentVersion"
Default
keyval = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
EndSelect
RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, keyval,0, $101, @hKey.i)
RegQueryValueEx_(hKey, "DigitalProductID", 0, @REG_BINARY, @bDigitalProductID(), @lDataLen)
Result = RegCloseKey_(hKey)
DatArr(0) = DecodeKey(bDigitalProductID(),52)
AddGadgetItem(0,-1,"Windows"+Chr(10)+ReplaceString(GetString(#HKEY_LOCAL_MACHINE,keyval,"ProductName"),"Windows ","")+Chr(10)+DatArr(0))
;office
For ii=0 To 13
FreeArray(DatArr())
Dim DatArr.s(1)
WindowsKeys(ii,Product(ii), DatArr())
For i=0 To ArraySize(DatArr())
If DatArr(i) <> ""
;Debug Val(Left(DatArr(i),2))
AddGadgetItem(0,-1,Product(ii)+Chr(10)+DecodeVersion(Val(Left(DatArr(i),2)))+Chr(10)+Right(DatArr(i),Len(DatArr(i))-2))
EndIf
Next
FreeArray(DatArr())
Next
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_CloseWindow
Quit = 1
EndIf
Until Quit = 1
EndIf