I am using the code example from dedndave to enumerate the registry for installed apps. It works fine listing one app at a time, whose name or GUID I then save to a buffer sequentially.
invoke RegOpenKeyEx, HKEY_LOCAL_MACHINE, offset sz_SubKey, NULL, KEY_ALL_ACCESS, offset hKeyKey
or eax,eax
jnz Exit_RegOpen ; exit if error on open
INVOKE RegQueryInfoKey,hKeyKey,eax,eax,eax,offset dw_Count,offset dw_BufSize,eax,eax,eax,eax,eax,eax
cmp dw_BufSize,sizeof sz_Buffer-1
ja Exit_RegEnum ;exit if our buffer is too small
mov ecx,dw_Count ; number of entries
xor edx,edx
Next_Entry:
push ecx
mov dw_BufSize, sizeof sz_Buffer-1
push edx
xor ecx,ecx
invoke RegEnumKeyEx,hKeyKey,edx,offset sz_Buffer,offset dw_BufSize,ecx,ecx,ecx,ecx
pop edx
pop ecx
inc edx
dec ecx
CALL Save_Entry ; dump single entry to buffer
cmp ecx,0
jnz Next_Entry
Exit_RegOpen:
invoke RegCloseKey, hKeyKey
Exit_RegEnum:
Now I wish to enumerate the subkeys in each entry usin RegEnumValue. When I place the call after CALL Save_Entry, according to OLLY the call succeeds, but no data is being dumped to the assigned buffers.
invoke RegEnumValue, hKeyKey, edx, offset lp_RegDataName, offset lp_RegDataNameLen, NULL, offset lp_RegDataType, offset lp_RegData, offset lp_RegDataLen
Does the RegEnumValue call replace the RegEnumKeyEx call. edx uses the same counter as the RegEnumKeyEX call. I've been reading the microsoft data sheets for 2 days and it looks like I've got it right but it doesn't work.
you may attach the full source that fails?
for each subkey that is enumerated by RegEnumKeyEx,
you must open a handle to the subkey
you can then enumerate the subkeys and/or values under that
then, you want to close that subkey handle
what you may want to do is to make a PROC out of it
then, use LOCALS for the handles, subkeys, and values
that way, you can call the routine, recursively
with each level of recursion, prepend 2 spaces to the keys and values
that will make it a little easier to read :P
Quote from: qWord on January 09, 2013, 07:10:03 AM
you may attach the full source that fails?
It is Top Secret LOL
@ Don57
gunner made such an example already :biggrin:
Download:
http://www.dreamincode.net/forums/index.php?app=core&module=attach§ion=attach&attach_id=29746&s=34a925358ed7c821f7d2db53161e6a70
(http://www.dreamincode.net/forums/uploads/monthly_06_2012/post-495049-13392980200285.png)
I hope I am not stepping on any toes posting this :(
Sorry If I am Gunner
Not top secret, I just enjoy writting the code myself. I try to understand the paradigm, then work the code out from there. Thanks for the help.
You are welcome, Gunners help really
Part of the charm of this place is that people take their time to help one another , if you noticed most topics have a solution ....we come up on searches for years to come. So lets suppose 5 years from now some has the same question and Google it (or even members using the search) , when they get to see this thread it is nice to have a working solution!
I make it a habit to post a source with my posts .... You can always post a little window with just the part that you need help with .... Like a bare bones example. That way you can still enjoy working on your own code, and other can reference this topic ..... Can you imagine no masm sources on the net ? And only snippets that you know the answers too?
If I look at the code from post #1 I think you're enumerating just the first value of the Subkey.
That value is almost the "Default" key which is empty. Could that be the case ? ;o)
Quote from: hfheatherfox07 on January 09, 2013, 08:07:04 PM
I hope I am not stepping on any toes posting this :(
Sorry If I am Gunner
Not at all! It was written to help all!
Still having trouble reading the subkey. Everything works fine except the Read_SubKey Proc.
right off, i see this problem...
QuoteRead_SubKey PROC
CALL ParsePath ; path for sub key enumeration
invoke MessageBox,0,offset sz_Buffer2,0,0
INVOKE RegOpenKeyEx, HKEY_LOCAL_MACHINE, offset sz_Buffer2, NULL, KEY_ALL_ACCESS, offset hSubKey
push eax
invoke GetLastError
invoke MessageBox,0,uhex$(eax),0,0
pop eax
or eax,eax
jnz Exit_RegSubOpen ; exit if error on open
xor edx,edx ; zero index
Next_SubEntry:
push edx
xor ecx,ecx
INVOKE RegEnumKeyEx,hSubKey,edx,offset lp_BufferEntry,offset dw_BufSize,ecx,ecx,ecx,ecx
pop edx
inc edx
cmp eax,ERROR_NO_MORE_ITEMS
jne Next_SubEntry
Exit_RegSubEnum:
INVOKE RegCloseKey, hKeyKey
Exit_RegSubOpen:
ret
Read_SubKey ENDP
oops :biggrin:
that may not be the only issue.....
Thanks. Too much copy and paste.
one thing you can do.....
when you open the key "HKLM\level1\level2", you can pass that handle to the next OpenKey call...
and use "level3" as the key string to open "HKLM\level1\level2\level3"
you use push/pop to save (counter/index-) registers across calls - it is maybe more efficient and readable to use local variables instead.
ok
when you make the "original" RegEnumKeyEx call....
mov dw_BufSize, sizeof sz_Buffer-1
push edx
xor ecx,ecx
INVOKE RegEnumKeyEx,hKeyKey,edx,offset sz_Buffer,offset dw_BufSize,ecx,ecx,ecx,ecx
you initialize the buffer size variable to the size of the buffer
when the function returns, it fills that variable with the length of the returned string (if successful)
now, when you call Read_SubKey, it thinks the buffer is that big :P
the normal practice would be to re-initialize that variable each time you call RegEnumKeyEx
that way, the function uses the buffer size, not the size of the last returned string
so - you want to add a line of code in the Read_SubKey proc just before each call to RegEnumKeyEx
Next_SubEntry:
push edx
xor ecx,ecx
mov dw_BufSize, sizeof sz_Buffer-1
INVOKE RegEnumKeyEx,hSubKey,edx,offset lp_BufferEntry,offset dw_BufSize,ecx,ecx,ecx,ecx
pop edx
inc edx
cmp eax,ERROR_NO_MORE_ITEMS
jne Next_SubEntry
another thing to mention....
Next_SubEntry:
push edx
xor ecx,ecx
mov dw_BufSize, sizeof sz_Buffer-1
INVOKE RegEnumKeyEx,hSubKey,edx,offset lp_BufferEntry,offset dw_BufSize,ecx,ecx,ecx,ecx
pop edx
inc edx
cmp eax,ERROR_NO_MORE_ITEMS
jne Next_SubEntry
notice that the function may fail for reasons other than ERROR_NO_MORE_ITEMS
it's ok - your loop will continue to run until the last item
but other errors may be returned that you should handle, like the buffer is too small
if EAX is anything other than 0, you may not want to not try to delete the key or something :biggrin:
and, finally.....
Next_Entry:
push ecx
mov dw_BufSize, sizeof sz_Buffer-1
push edx
xor ecx,ecx
INVOKE RegEnumKeyEx,hKeyKey,edx,offset sz_Buffer,offset dw_BufSize,ecx,ecx,ecx,ecx
pop edx
pop ecx
inc edx
dec ecx
push edx
push ecx
CALL Read_SubKey ; read entries for subkeys
pop ecx
pop edx
cmp ecx,0
jnz Next_Entry
the call to Read_SubKey destroys the contents of EAX, ECX, and EDX :P
better, yet....
Next_Entry:
push ecx
mov dw_BufSize, sizeof sz_Buffer-1
push edx
xor ecx,ecx
INVOKE RegEnumKeyEx,hKeyKey,edx,offset sz_Buffer,offset dw_BufSize,ecx,ecx,ecx,ecx
CALL Read_SubKey ; read entries for subkeys
pop edx
pop ecx
inc edx
dec ecx
jnz Next_Entry
see if this flies...
Thanks I'll give it a try. :t
Still banging around trying to get RegEnumValue going. The in Read_SubKey PROC return only 2 of 5 pieces of data. lp_RegDataType (lpType) and lp_RegDataLen (lpcbData)., but the other three buffers are empty. I realize that buffer are static, I will dynamically allocate them and add further error checking when I get the call working.
added 1 line :P
Read_SubKey PROC
CALL ParsePath ; path for sub key enumeration
INVOKE RegOpenKeyEx, HKEY_LOCAL_MACHINE, offset sz_Buffer2, NULL, KEY_ALL_ACCESS, offset hSubKey
or eax,eax
jnz Exit_RegSubOpen ; exit if error on open
xor edx,edx ; zero index
Next_SubEntry:
push edx
mov lp_RegValueNameLen,sizeof lp_RegValueName-1
INVOKE RegEnumValue........
no need to parse a new path name and open another handle, though
you can pass the handle from the RegOpenKeyEx to this proc
then - just use the subkey name :t
Thanks. Be lost in the woods, with these API withhout your help. :greenclp:
the registry is a little tricky :biggrin:
Quote from: dedndave on January 16, 2013, 06:12:42 PM
the registry is a little tricky :biggrin:
There is a very nice example in MASM32 examples :biggrin:
In masm32 v9 it is example in "\masm32\examples\example06\regdemo" folder.
In masm32 v10 it is example in "\masm32\examples\example06\regdemo" folder.
In masm32 v11 it is example in "\masm32\examples\example04\regdemo" folder. <<<---
I think the 3rd entry should be example 06.
I found it to be a good example of using an ini file in addition to commonly used reg functions.
Thanks everybody. The microsoft data sheets are confusing at times.
sometimes, it's what they don't tell you that's confusing :P
or - they tell you, but it's not in the document you'd expect - it's in some other document
Still working on this project. Added debugging routine to dump registry data to a file, got tired of reading the heap. It appears that the data that I am reading is valid, but I am only returning about 40% of installed programs. Program creates Reg Data.txt file. I think the problem is the access keys in the EnumerateKeys PROC, but not sure.
KEY_ALL
try KEY_ALL_ACCESS :biggrin:
and.....
02/03/2013 03:57 PM 663,702 toolbar.bmp
ouch !
maybe that could be a 16 color image
better yet, create a bitmap and generate the image with code or something :t
when i use a toolbar image, it usually has just icon type images
256 colors is plenty, regardless of what the other guys say - lol
Tried that but I'm on a 64 bit system, still doesn't get it.
ok - i take it you are using win7 ?
there may well be security permission issues
you may have to add some UAC access stuff to the manifest
and - there is also the WOW32 issue
because when you access a 64-bit registry in 32-bit code, you are viewing a virtualized 32-bit version of it
this is an area where i have very little experience :P
maybe the best approach is to write 64-bit code
Sorry long day. :dazzled: Reset KEY_ALL_ACCESS still missing some data in lp_RegData occasionally but nothing i need.