' TODO: consider incorporating a json writer of some sort instead of adhoc solution like the following ' e.g: http://demon.tw/my-work/vbs-json.html const HKEY_CLASSES_ROOT = &H80000000 const HKEY_CURRENT_USER = &H80000001 const HKEY_LOCAL_MACHINE = &H80000002 const HKEY_USERS = &H80000003 const HKEY_CURRENT_CONFIG = &H80000005 Sub LoadRegistryImplementationByOSArchitecture() If IsNull(OSArchitecture) Then WriteLineErr "missing OSArchitecture global. did not call util.DetermineOSArchitecture? or Forgot to load util.vbs?" WScript.Quit 25125 End If If OSArchitecture = "A" Then Include "ArchitectureAgnosticRegistry.vbs" Else Include "ArchitectureSpecificRegistry.vbs" End If End Sub Function PutValue(constHive, strSubKey, strValueName, strValue, strType) Select Case UCase(strType) Case "REG_SZ" PutValue = SetStringValue(constHive, strSubKey, strValueName, strValue) Case "REG_EXPAND_SZ" PutValue = SetExpandedStringValue(constHive, strSubKey, strValueName, strValue) Case "REG_BINARY" PutValue = SetBinaryValue(constHive, strSubKey, strValueName, ToBinaryValue(strValue)) Case "REG_NONE" PutValue = SetBinaryValue(constHive, strSubKey, strValueName, ToBinaryValue(strValue)) ' TODO: need to check that indeed int is the right type here Case "REG_DWORD" PutValue = SetDWORDValue(constHive, strSubKey, strValueName, CDbl(strValue)) Case "REG_MULTI_SZ" PutValue = SetMultiStringValue(constHive, strSubKey, strValueName, Split(strValue, ",")) Case "REG_QWORD" PutValue = SetQWORDValue(constHive, strSubKey, strValueName, strValue) Case "REG_DEFAULT" PutValue = SetStringValue(constHive, strSubKey, "", strValue) Case Else PutValue = SetStringValue(constHive, strSubKey, strValueName, strValue) End Select End Function ' render the child of a sub path strSubKey in hive constHive ' as json. Sub ListChildrenAsJson(constHive, strSubKey) ' start outputting json to stdout Write "{" Dim e1: e1 = EnumKey (constHive, strSubKey, arrKeyNames) If e1 <> 0 Then Write """exists"": false," Dim arrValueNames: arrValueNames = null Else Write """exists"": true," Dim e2: e2 = EnumValues (constHive, strSubKey, arrValueNames, arrValueTypes) If e2 <> 0 Then WScript.Quit e2 End If End If Write """keys"": [" If Not IsNull(arrKeyNames) Then For x = 0 To UBound(arrKeyNames) If (x > 0) Then Write "," End If Write """" & JsonSafe(arrKeyNames(x)) & """" Next End If Write "]," ' TODO: some duplicity of code between the two paths of this condition, this needs to be address at some point Write """values"":{" If Not IsNull(arrValueNames) Then For y = 0 To UBound(arrValueNames) If y > 0 Then Write "," End If strValueName = arrValueNames(y) intValueType = arrValueTypes(y) ' assign the value to varValue GetValueByType constHive, strSubKey, strValueName, intValueType, varValue WriteValue strValueName, intValueType, varValue Next Else ' fix for keys with only default values in them ' see http://stackoverflow.com/questions/8840343/how-to-read-the-default-value-from-registry-in-vbscript GetStringValue constHive, strSubKey, "", strDefaultValue If IsNull(strDefaultValue) = false and strDefaultValue <> "" Then ' write the default value with REG_SZ WriteValue "", 1, strDefaultValue End If End If Write "}}" End Sub Sub WriteValue (strValueName, intValueType, varValue) Write """" Write JsonSafe(strValueName) Write """:{" Write """type"": """ Write RenderType(intValueType) Write """," Write """value"":" Write RenderValueByType(intValueType, varValue) Write "}" End Sub ' give a raw HKLM\something\somewhere ' output the hive constant and the subkey, in this case: ' HKEY_LOCAL_MACHINE will be assigned to outConstHive ' and something\somewhere will be assigned to outStrSubKey Sub ParseHiveAndSubKey(strRawKey, outConstHive, outStrSubKey) ' split into two parts to deduce the hive and the sub key arrSplitted = Split(strRawKey, "\", 2, 1) If UBound(arrSplitted) > 0 Then strHive = arrSplitted(0) outStrSubKey = arrSplitted(1) Else strHive = strRawKey outStrSubKey = "" End If outConstHive = StringToHiveConst(UCase(strHive)) End Sub Function ArrayRemoveAt(arr, pos) Dim i If IsArray(arr) Then If pos >= 0 And pos <= UBound(arr) Then For i = pos To UBound(arr) - 1 arr(i) = arr(i + 1) Next ReDim Preserve arr(UBound(arr) - 1) End If End If End Function Sub ParseHiveAndSubKeyAndValue(strRawKey, outConstHive, outStrSubKey, outStrValue) ' split into two parts to deduce the hive and the sub key arrSplitted = Split(strRawKey, "\", -1, 1) If UBound(arrSplitted) > 0 Then strHive = arrSplitted(0) outStrValue = arrSplitted(UBound(arrSplitted)) test = ArrayRemoveAt(arrSplitted, UBound(arrSplitted)) test = ArrayRemoveAt(arrSplitted, 0) outStrSubKey = Join(arrSplitted, "\") Else strHive = strRawKey outStrSubKey = "" End If outConstHive = StringToHiveConst(UCase(strHive)) End Sub Function StringToHiveConst(strHive) Select Case strHive Case "HKCR" StringToHiveConst = HKEY_CLASSES_ROOT Case "HKCU" StringToHiveConst = HKEY_CURRENT_USER Case "HKLM" StringToHiveConst = HKEY_LOCAL_MACHINE Case "HKU" StringToHiveConst = HKEY_USERS Case "HKCC" StringToHiveConst = HKEY_CURRENT_CONFIG Case Else StringToHiveConst = Null End Select End Function ' TODO: this entire "by type" should be transformed into OOP style ' where each type will have a class with render(), getValue() etc... ' convert a value type number into a string label Function RenderType(intType) RenderType = "REG_UNKNOWN" Select Case intType Case 0 RenderType = "REG_NONE" Case 1 RenderType = "REG_SZ" Case 2 RenderType = "REG_EXPAND_SZ" Case 3 RenderType = "REG_BINARY" Case 4 RenderType = "REG_DWORD" Case 7 RenderType = "REG_MULTI_SZ" Case 11 RenderType = "REG_QWORD" Case Else ' TODO: should report / throw an error here WriteErr("invalid Registry Value Type " & intType) End Select End Function ' render by value type: ' string will return as a string with double quotes, e.g "value" ' multi string values which return as an array ot strings "["1", "2"]" (double quotes included ofc) ' numeric values like DWORD and QWORD just return as the number e.g. 1 ' byte arrays such as reg_binary return as an array of ints, e.g [1,2,3] Function RenderValueByType(intType, varValue) Select Case intType ' REG_NONE Case 0 RenderValueByType = "0" ' REG_SZ Case 1 RenderValueByType = """" & JsonSafe(varValue) & """" ' REG_EXPAND_SZ Case 2 RenderValueByType = """" & JsonSafe(varValue) & """" ' REG_BINARY Case 3 RenderValueByType = RenderByteArray(varValue) ' REG_DWORD Case 4 RenderValueByType= varValue ' REG_MULYI_SZ' Case 7 RenderValueByType = RenderStringArray(varValue) ' REG_QWORD Case 11 RenderValueByType = varValue Case Else ' TODO: should report / throw an error here WriteErr("invalid Registry Value Type " & intType) End Select End Function ' get the value of a registry based on its value type and assign it to out parameter outVarValue Sub GetValueByType(constHive, strKey, strValueName, intType, outVarValue) Select Case intType ' REG_NONE Case 0 GetStringValue constHive, strKey, strValueName, "0" Exit Sub ' REG_SZ Case 1 GetStringValue constHive, strKey, strValueName, outVarValue Exit Sub ' REG_EXPAND_SZ Case 2 GetExpandedStringValue constHive, strKey, strValueName, outVarValue Exit Sub ' REG_BINARY Case 3 GetBinaryValue constHive, strKey, strValueName, outVarValue Exit Sub ' REG_DWORD Case 4 GetDWORDValue constHive, strKey, strValueName, outVarValue ' #21 - VBS does not support UInt32. This is the workaround If outVarValue < 0 Then outVarValue = 4294967296 + outVarValue Exit Sub ' REG_MULYI_SZ' Case 7 GetMultiStringValue constHive, strKey, strValueName, outVarValue Exit Sub ' REG_QWORD Case 11 GetQWORDValue constHive, strKey, strValueName, outVarValue Exit Sub Case Else ' TODO: should report / throw an error here WriteErr("invalid Registry Value Type " & intType) End Select End Sub ' render a byte array as a json array of numbers Function RenderByteArray(arr) RenderByteArray = "[]" If Not IsNull(arr) Then RenderByteArray = "[" & Join(arr, ",") & "]" End If End Function ' render a string array as json string array Function RenderStringArray(arr) Result = "[" If Not IsNull(arr) Then For t = 0 To UBound(arr) If (t > 0) Then Result = Result & "," End If Result = Result & """" & JsonSafe(arr(t)) & """" Next End If Result = Result & "]" RenderStringArray = Result End Function Function ToBinaryValue(strValue) arrValue = Split(strValue, ",") If IsNull(arrValue) Then ToBinaryValue = Array() Exit Function End If For i = 0 To UBound(arrValue) arrValue(i) = CInt(arrValue(i)) Next ToBinaryValue = arrValue End Function