This is very specific, but maybe will be useful for some registry guy :)
In short:
if you need to build a ton of nested loops for:
just say, you have a task to enumerate:
1) several keys
2) in the same location of HKLM / HKCU / HKU + every SID
3) separately consider WOW6432Node (read value with KEY_WOW64_64KEY flag and without) + exclude one of 'shared' keys (keys that point to the same phisical location in both 64/32-bit modes).
you can fit all in 1 single cycle with this 'Hives Enumerator' class.
Example:
Here is your old code:
Here is how it looks now with my class:
Or you can enum hives without keys. Just don't use HE.AddKeys.
Required:
Some enums to Global module: just to support quick IntelliSense tips.
Dependencies:
modRegVirtualType.bas (included)
Good luck :)
-----------------
Live example (attached as demo):
Result:
---------
Hive handle: -2147483646
Hive name: HKLM
Hive + key: HKLM\Software\Classes\AppID
Key: Software\Classes\AppID
Redirected: False
Array index: 0
User name: All users
---------
Hive handle: -2147483646
Hive name: HKLM
Hive + key: HKLM\Software\Classes\CLSID
Key: Software\Classes\CLSID
Redirected: True
Array index: 1
User name: All users
---------
Hive handle: -2147483646
Hive name: HKLM
Hive + key: HKLM\Software\Classes\CLSID
Key: Software\Classes\CLSID
Redirected: False
Array index: 1
User name: All users
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\.DEFAULT\Software\Classes\CLSID
Key: .DEFAULT\Software\Classes\CLSID
Redirected: False
Array index: 1
User name: Default user
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-19\Software\Classes\CLSID
Key: S-1-5-19\Software\Classes\CLSID
Redirected: True
Array index: 1
User name: Local service
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-19\Software\Classes\CLSID
Key: S-1-5-19\Software\Classes\CLSID
Redirected: False
Array index: 1
User name: Local service
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-20\Software\Classes\CLSID
Key: S-1-5-20\Software\Classes\CLSID
Redirected: True
Array index: 1
User name: Network service
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-20\Software\Classes\CLSID
Key: S-1-5-20\Software\Classes\CLSID
Redirected: False
Array index: 1
User name: Network service
Above, we requested:
1) for HE_HIVE_HKLM + HE_HIVE_HKU hives.
2) aKey(0) have exception: list HKLM only (see prefix "HKLM\...")
3) HE_SID_ALL
4) WOW + no WOW
We got:
1) only 1 iteration of aKey(0) -> HKLM\Software\Classes\AppID, because it is 'Shared' key. WOW mode is point to the same phisical location, so WOW iteration is skipped.
2) 2 iteration of aKey(1) of HKLM. 1 - WOW, 2 - No WOW.
3) 5 iterations of aKey(1) of HKU. 1 - .Default SID, 2 - S-1-5-19, 3 - S-1-5-20, where:
- HKU\.Default\Software\Classes\CLSID is not 'redirected' key, that's why only 1 iteration
- S-1-5-19 and S-1-5-20 ARE 'redirected' keys, that's why +2 iterations for each (WOW, no WOW)
Note: that class doesn't check and skip keys that are not exist (it is responsibility of caller).
E.g. if I'll create:
- HKEY_USERS\S-1-5-19\Software\Classes\Wow6432Node\CLSID
and remove:
- HKEY_USERS\S-1-5-19\Software\Classes\CLSID
class will produce 2 iterations (with .Redirected = 'true', and with 'false').
-----------------------------------
Detailed description of the class:
Common scheme of the cycle:
Stages of using:
I. Required initialization:
Set global rule for iterator:
where every arg. is a sum of bits, available from Intellisense, e.g.:
[Hives]
What properties are affected:
- .Hive
- .HiveName
- .HiveNameAndSID
- .KeyAndHive
- .UserName
[SIDs]
What properties are affected:
- .HiveNameAndSID
- .KeyAndHive
- .UserName
- .IsSidSystem
- .IsSidUser
- .IsSidDefault properties.
[WOW_Modes]
What properties are affected:
- .Redirected
2. Optional. Supply key (keys).
a) Supply array of keys:
What properties are affected:
- .Key
- .KeyAndHive
- .SharedKey
- .KeyIndex
b) Supply single key (or keys one by one with several .AddKey calls)
What properties are affected:
- .Key
- .KeyAndHive
- .SharedKey
- special excludes for hives.
where:
[Key] is a key in any of 2 formats:
1) Key
2) Hive\Key
It's can be:
Software\Classes\CLSID
HKLM\Software\Classes\AppID
HKEY_LOCAL_MACHINE\Software\Classes\AppID
In case, you prepended concrete "Hive" to key it will be treated as an exclude from global rule (e.g., HE.Init HE_HIVE_ALL): for such key, enumerator will return only concrete hive (HKLM in example above).
[opt_PostPlaceholder] - optional. Any text. Enumerator will append it to the .Key. You can use it in your cycle e.g., to replace with a data that was not known to you at the time of class initialization (e.g. to replace manually "{CLSID}" by real CLSID in different parts of key for different keys).
II. Beginning of enumeration.
III. Using of properties.
HE.Hive - hive handle (constant)
HE.Key - string, representing the key only, e.g. 'Software\Microsoft'
HE.Redirection - boolean, representing WOW mode (false - native key, true - 32-bit key).
HE.KeyAndHive - string, "Hive\Key"
HE.HiveName - string, short name of hive, e.g. "HKLM"
HE.HiveNameAndSID - string, e.g. "HKU\S-1-5-19"
HE.UserName - string:
- for HKLM - "All users"
- for HKCU - current user's name
- for HKU\S-1-5-19 - "Local service"
- for HKU\S-1-5-20 - "Network service"
- for HKU\.Default - "Default user"
- for HKU\S-some another SID - user's name of that SID
HE.KeyIndex - index of array passed to the class used in current iteration, e.g. need, if you track several linked arrays by its index, like array of keys + array of these keys' description and want to get description by index for current iteration (see first example above - for sDes() array it will be sDes(HE.KeyIndex) ).
HE.SharedKey - boolean. To know if this key have a 'shared' type, e.g. need, if you know that this key1 linked to another key2, so if key1 is 'Shared' and key2 is not, now you know e.g. that you need to pay attention on both WOW modes of key2.
HE.IsSidService - boolean. TRUE, if current iteration is on 'HKU\S-1-5-19' or, 'HKU\S-1-5-20'
HE.IsSidUser - boolean. TRUE, if current iteration is on 'HKU\S-Some custom logged user'
HE.IsSidDefault - boolean. TRUE, if current iteration is on 'HKU\.Default'
Methods:
PrintAll - test reason. To show in debug. window all properties of all iterations. Try play with it :)
IV. Optional steps.
Repeat enum.
If you need repeat enumeration again with the same settings:
Erase / fresh enum:
Just use .Init again with the same or new settings.
It will erase all data supplied before. No need to terminate the class.
In short:
if you need to build a ton of nested loops for:
just say, you have a task to enumerate:
1) several keys
2) in the same location of HKLM / HKCU / HKU + every SID
3) separately consider WOW6432Node (read value with KEY_WOW64_64KEY flag and without) + exclude one of 'shared' keys (keys that point to the same phisical location in both 64/32-bit modes).
you can fit all in 1 single cycle with this 'Hives Enumerator' class.
Example:
Here is your old code:
Code:
sRegRuns(1) = "Software\Microsoft\Windows\CurrentVersion\Run"
sDes(1) = "Run"
sRegRuns(2) = "Software\Microsoft\Windows\CurrentVersion\RunServices"
sDes(2) = "RunServices"
'...
For i = 0 To UBound(aHives) 'HKLM, HKCU, HKU()
For Each UseWow In Array(False, True)
If (bIsWin32 And UseWow) _
Or bIsWin64 And UseWow And _
(sHive = "HKCU" _
Or StrBeginWith(sHive, "HKU\")) Then Exit For
For K = LBound(sRegRuns) To UBound(sRegRuns)
Code:
Dim HE as clsHiveEnum
Set HE = New clsHiveEnum
'...
sRegRuns(1) = "Software\Microsoft\Windows\CurrentVersion\Run"
sDes(1) = "Run"
sRegRuns(2) = "Software\Microsoft\Windows\CurrentVersion\RunServices"
sDes(2) = "RunServices"
'...
HE.Init HE_HIVE_ALL, HE_SID_ALL, HE_REDIR_BOTH
HE.AddKeys sRegRuns
Do While HE.MoveNext
'that's all :) Just use HE.Hive, HE.Key, HE.Redirected and many more...
Loop
Required:
Some enums to Global module: just to support quick IntelliSense tips.
Dependencies:
modRegVirtualType.bas (included)
Good luck :)
-----------------
Live example (attached as demo):
Code:
Dim HE As clsHiveEnum
Set HE = New clsHiveEnum
Dim aKey(1) As String
aKey(0) = "HKLM\Software\Classes\AppID"
aKey(1) = "Software\Classes\CLSID"
HE.Init HE_HIVE_HKLM Or HE_HIVE_HKU, HE_SID_ALL, HE_REDIR_BOTH
HE.AddKeys aKey
Do While HE.MoveNext
Debug.Print " --------- "
Debug.Print "Hive handle: " & HE.Hive
Debug.Print "Hive name: " & HE.HiveName
Debug.Print "Hive + key: " & HE.KeyAndHive
Debug.Print "Key: " & HE.Key
Debug.Print "Redirected: " & HE.Redirected
Debug.Print "Array index: " & HE.KeyIndex
Debug.Print "User name: " & HE.UserName
Loop
Set HE = Nothing
Quote:
---------
Hive handle: -2147483646
Hive name: HKLM
Hive + key: HKLM\Software\Classes\AppID
Key: Software\Classes\AppID
Redirected: False
Array index: 0
User name: All users
---------
Hive handle: -2147483646
Hive name: HKLM
Hive + key: HKLM\Software\Classes\CLSID
Key: Software\Classes\CLSID
Redirected: True
Array index: 1
User name: All users
---------
Hive handle: -2147483646
Hive name: HKLM
Hive + key: HKLM\Software\Classes\CLSID
Key: Software\Classes\CLSID
Redirected: False
Array index: 1
User name: All users
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\.DEFAULT\Software\Classes\CLSID
Key: .DEFAULT\Software\Classes\CLSID
Redirected: False
Array index: 1
User name: Default user
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-19\Software\Classes\CLSID
Key: S-1-5-19\Software\Classes\CLSID
Redirected: True
Array index: 1
User name: Local service
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-19\Software\Classes\CLSID
Key: S-1-5-19\Software\Classes\CLSID
Redirected: False
Array index: 1
User name: Local service
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-20\Software\Classes\CLSID
Key: S-1-5-20\Software\Classes\CLSID
Redirected: True
Array index: 1
User name: Network service
---------
Hive handle: -2147483645
Hive name: HKU
Hive + key: HKU\S-1-5-20\Software\Classes\CLSID
Key: S-1-5-20\Software\Classes\CLSID
Redirected: False
Array index: 1
User name: Network service
1) for HE_HIVE_HKLM + HE_HIVE_HKU hives.
2) aKey(0) have exception: list HKLM only (see prefix "HKLM\...")
3) HE_SID_ALL
4) WOW + no WOW
We got:
1) only 1 iteration of aKey(0) -> HKLM\Software\Classes\AppID, because it is 'Shared' key. WOW mode is point to the same phisical location, so WOW iteration is skipped.
2) 2 iteration of aKey(1) of HKLM. 1 - WOW, 2 - No WOW.
3) 5 iterations of aKey(1) of HKU. 1 - .Default SID, 2 - S-1-5-19, 3 - S-1-5-20, where:
- HKU\.Default\Software\Classes\CLSID is not 'redirected' key, that's why only 1 iteration
- S-1-5-19 and S-1-5-20 ARE 'redirected' keys, that's why +2 iterations for each (WOW, no WOW)
Note: that class doesn't check and skip keys that are not exist (it is responsibility of caller).
E.g. if I'll create:
- HKEY_USERS\S-1-5-19\Software\Classes\Wow6432Node\CLSID
and remove:
- HKEY_USERS\S-1-5-19\Software\Classes\CLSID
class will produce 2 iterations (with .Redirected = 'true', and with 'false').
-----------------------------------
Detailed description of the class:
Common scheme of the cycle:
Code:
' {
' 1. Keys (if supplied)
' {
' 2. HKLM / HKCU / HKU + every SID...
' {
' 3. REDIR_WOW (redirected) / REDIR_NO_WOW
' }
' }
' }
I. Required initialization:
Set global rule for iterator:
Code:
HE.Init [Hives], [opt_SIDs], [opt_WOW_Modes]
Code:
HE.Init HE_HIVE_HKLM Or HE_HIVE_HKCU
Code:
HE_HIVE_ALL - all
HE_HIVE_HKLM - HKLM only
HE_HIVE_HKCU - HKCU only
HE_HIVE_HKU - HKU only
- .Hive
- .HiveName
- .HiveNameAndSID
- .KeyAndHive
- .UserName
[SIDs]
Code:
HE_SID_ALL - all
HE_SID_DEFAULT - HKU\.Default (target of HKU\S-1-5-18 symlink)
HE_SID_SERVICE - mean HKU\S-1-5-19 (Local service) and HKU\S-1-5-20 (Network service)
HE_SID_USER - mean other currently logged users, excepting current user (available as HKCU)
- .HiveNameAndSID
- .KeyAndHive
- .UserName
- .IsSidSystem
- .IsSidUser
- .IsSidDefault properties.
[WOW_Modes]
Code:
HE_REDIR_BOTH - to iterate both WOW modes (checking for 'Shared' keys will be activated for this flag only)
HE_REDIR_NO_WOW - NO_WOW only (64-bit keys)
HE_REDIR_WOW - WOW only (32-bit keys)
HE_REDIR_DONT_IGNORE_SHARED - ignore checking for 'Shared' type. Force iteratation of every WOW mode.
- .Redirected
2. Optional. Supply key (keys).
a) Supply array of keys:
Code:
HE.AddKeys string_array
- .Key
- .KeyAndHive
- .SharedKey
- .KeyIndex
b) Supply single key (or keys one by one with several .AddKey calls)
What properties are affected:
- .Key
- .KeyAndHive
- .SharedKey
- special excludes for hives.
Code:
HE.AddKey [Key], [opt_PostPlaceholder]
[Key] is a key in any of 2 formats:
1) Key
2) Hive\Key
It's can be:
Quote:
Software\Classes\CLSID
HKLM\Software\Classes\AppID
HKEY_LOCAL_MACHINE\Software\Classes\AppID
[opt_PostPlaceholder] - optional. Any text. Enumerator will append it to the .Key. You can use it in your cycle e.g., to replace with a data that was not known to you at the time of class initialization (e.g. to replace manually "{CLSID}" by real CLSID in different parts of key for different keys).
II. Beginning of enumeration.
Code:
Do while HE.MoveNext
'use any HE property
Loop
III. Using of properties.
HE.Hive - hive handle (constant)
HE.Key - string, representing the key only, e.g. 'Software\Microsoft'
HE.Redirection - boolean, representing WOW mode (false - native key, true - 32-bit key).
HE.KeyAndHive - string, "Hive\Key"
HE.HiveName - string, short name of hive, e.g. "HKLM"
HE.HiveNameAndSID - string, e.g. "HKU\S-1-5-19"
HE.UserName - string:
- for HKLM - "All users"
- for HKCU - current user's name
- for HKU\S-1-5-19 - "Local service"
- for HKU\S-1-5-20 - "Network service"
- for HKU\.Default - "Default user"
- for HKU\S-some another SID - user's name of that SID
HE.KeyIndex - index of array passed to the class used in current iteration, e.g. need, if you track several linked arrays by its index, like array of keys + array of these keys' description and want to get description by index for current iteration (see first example above - for sDes() array it will be sDes(HE.KeyIndex) ).
HE.SharedKey - boolean. To know if this key have a 'shared' type, e.g. need, if you know that this key1 linked to another key2, so if key1 is 'Shared' and key2 is not, now you know e.g. that you need to pay attention on both WOW modes of key2.
HE.IsSidService - boolean. TRUE, if current iteration is on 'HKU\S-1-5-19' or, 'HKU\S-1-5-20'
HE.IsSidUser - boolean. TRUE, if current iteration is on 'HKU\S-Some custom logged user'
HE.IsSidDefault - boolean. TRUE, if current iteration is on 'HKU\.Default'
Methods:
PrintAll - test reason. To show in debug. window all properties of all iterations. Try play with it :)
IV. Optional steps.
Repeat enum.
If you need repeat enumeration again with the same settings:
Code:
HE.Repeat
Do While HE.MoveNext
'...
Erase / fresh enum:
Just use .Init again with the same or new settings.
It will erase all data supplied before. No need to terminate the class.