The MASM Forum

General => The Campus => Topic started by: Don57 on January 09, 2013, 06:29:38 AM

Title: RegEnumValue
Post by: Don57 on January 09, 2013, 06:29:38 AM
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.
Title: Re: RegEnumValue
Post by: qWord on January 09, 2013, 07:10:03 AM
you may attach the full source that fails?
Title: Re: RegEnumValue
Post by: dedndave on January 09, 2013, 08:36:00 AM
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
Title: Re: RegEnumValue
Post by: hfheatherfox07 on January 09, 2013, 08:07:04 PM
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&section=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
Title: Re: RegEnumValue
Post by: Don57 on January 10, 2013, 01:42:37 AM
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.
Title: Re: RegEnumValue
Post by: hfheatherfox07 on January 10, 2013, 04:07:20 AM
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?
Title: Re: RegEnumValue
Post by: Greenhorn on January 10, 2013, 08:59:40 AM
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)
Title: Re: RegEnumValue
Post by: Gunner on January 10, 2013, 10:57:38 AM
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!
Title: Re: RegEnumValue
Post by: Don57 on January 11, 2013, 03:04:20 AM
Still having trouble reading the subkey. Everything works fine except the Read_SubKey Proc.
Title: Re: RegEnumValue
Post by: dedndave on January 11, 2013, 03:35:06 AM
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.....
Title: Re: RegEnumValue
Post by: Don57 on January 11, 2013, 03:43:27 AM
Thanks. Too much copy and paste.
Title: Re: RegEnumValue
Post by: dedndave on January 11, 2013, 03:49:08 AM
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"
Title: Re: RegEnumValue
Post by: qWord on January 11, 2013, 03:50:47 AM
you use push/pop to save (counter/index-) registers across calls - it is maybe more efficient and readable to use local variables instead.
Title: Re: RegEnumValue
Post by: dedndave on January 11, 2013, 04:05:08 AM
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
Title: Re: RegEnumValue
Post by: dedndave on January 11, 2013, 04:20:57 AM
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:
Title: Re: RegEnumValue
Post by: dedndave on January 11, 2013, 04:31:13 AM
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
Title: Re: RegEnumValue
Post by: dedndave on January 11, 2013, 05:04:29 AM
see if this flies...
Title: Re: RegEnumValue
Post by: Don57 on January 11, 2013, 09:27:38 AM
Thanks I'll give it a try.  :t
Title: Re: RegEnumValue
Post by: Don57 on January 16, 2013, 07:46:45 AM
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.
Title: Re: RegEnumValue
Post by: dedndave on January 16, 2013, 08:29:09 AM
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
Title: Re: RegEnumValue
Post by: Don57 on January 16, 2013, 04:07:06 PM
Thanks. Be lost in the woods, with these API withhout your help.  :greenclp:
Title: Re: RegEnumValue
Post by: dedndave on January 16, 2013, 06:12:42 PM
the registry is a little tricky   :biggrin:
Title: Re: RegEnumValue
Post by: hfheatherfox07 on January 16, 2013, 06:56:34 PM
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.  <<<---

Title: Re: RegEnumValue
Post by: Magnum on January 17, 2013, 03:20:40 AM
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.
Title: Re: RegEnumValue
Post by: Don57 on January 17, 2013, 08:15:01 AM
Thanks everybody. The microsoft data sheets are confusing at times.
Title: Re: RegEnumValue
Post by: dedndave on January 17, 2013, 10:43:35 AM
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
Title: Re: RegEnumValue
Post by: Don57 on February 06, 2013, 05:20:37 AM
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.
Title: Re: RegEnumValue
Post by: dedndave on February 06, 2013, 05:33:58 AM
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
Title: Re: RegEnumValue
Post by: Don57 on February 06, 2013, 06:20:59 AM
Tried that but I'm on a 64 bit system, still doesn't get it.
Title: Re: RegEnumValue
Post by: dedndave on February 06, 2013, 06:24:43 AM
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
Title: Re: RegEnumValue
Post by: Don57 on February 06, 2013, 11:14:48 AM
Sorry long day.  :dazzled: Reset  KEY_ALL_ACCESS still missing some data in lp_RegData occasionally but nothing i need.