AutoHotkey Community

It is currently May 27th, 2012, 3:19 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: January 6th, 2009, 3:13 pm 
Offline

Joined: August 12th, 2007, 3:49 am
Posts: 12
This script provides RegRead64() and RegWrite64() functions that do not redirect to Wow6432Node on 64-bit machines.

Registry calls from 32 bit applications running on 64 bit machines are normally intercepted by the system and redirected from HKLM\SOFTWARE to HKLM\SOFTWARE\Wow6432Node. Using these functions you can read the "true" registry on 64 bit machines from AutoHotkey.

Code:
; _reg64.ahk ver 0.1 by tomte
; Script for AutoHotkey   ( http://www.autohotkey.com/ )
;
; Provides RegRead64() and RegWrite64() functions that do not redirect to Wow6432Node on 64-bit machines
; RegRead64() and RegWrite64() takes the same parameters as regular AHK RegRead and RegWrite commands, plus one optional DataMaxSize param for RegRead64()
;
; RegRead64() can handle the same types of values as AHK RegRead:
; REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_DWORD, and REG_BINARY
; (values are returned in same fashion as with RegRead - REG_BINARY as hex string, REG_MULTI_SZ split with linefeed etc.)
;
; RegWrite64() can handle REG_SZ, REG_EXPAND_SZ and REG_DWORD only
;
; Usage:
; myvalue := RegRead64("HKEY_LOCAL_MACHINE", "SOFTWARE\SomeCompany\Product\Subkey", "valuename")
; RegWrite64("REG_SZ", "HKEY_LOCAL_MACHINE", "SOFTWARE\SomeCompany\Product\Subkey", "valuename", "mystring")
; If the value name is blank/omitted the subkey's default value is used, if the value is omitted with RegWrite64() a blank/zero value is written
;

RegRead64(sRootKey, sKeyName, sValueName = "", DataMaxSize=1024) {
   HKEY_CLASSES_ROOT   := 0x80000000   ; http://msdn.microsoft.com/en-us/library/aa393286.aspx
   HKEY_CURRENT_USER   := 0x80000001
   HKEY_LOCAL_MACHINE   := 0x80000002
   HKEY_USERS         := 0x80000003
   HKEY_CURRENT_CONFIG   := 0x80000005
   HKEY_DYN_DATA      := 0x80000006
   HKCR := HKEY_CLASSES_ROOT
   HKCU := HKEY_CURRENT_USER
   HKLM := HKEY_LOCAL_MACHINE
   HKU    := HKEY_USERS
   HKCC := HKEY_CURRENT_CONFIG
   
   REG_NONE             := 0   ; http://msdn.microsoft.com/en-us/library/ms724884.aspx
   REG_SZ                := 1
   REG_EXPAND_SZ         := 2
   REG_BINARY            := 3
   REG_DWORD            := 4
   REG_DWORD_BIG_ENDIAN   := 5
   REG_LINK            := 6
   REG_MULTI_SZ         := 7
   REG_RESOURCE_LIST      := 8

   KEY_QUERY_VALUE := 0x0001   ; http://msdn.microsoft.com/en-us/library/ms724878.aspx
   KEY_WOW64_64KEY := 0x0100   ; http://msdn.microsoft.com/en-gb/library/aa384129.aspx (do not redirect to Wow6432Node on 64-bit machines)
   KEY_SET_VALUE   := 0x0002
   KEY_WRITE      := 0x20006

   myhKey := %sRootKey%      ; pick out value (0x8000000x) from list of HKEY_xx vars
   IfEqual,myhKey,, {      ; Error - Invalid root key
      ErrorLevel := 3
      return ""
   }
   
   RegAccessRight := KEY_QUERY_VALUE + KEY_WOW64_64KEY
   
   DllCall("Advapi32.dll\RegOpenKeyExA", "uint", myhKey, "str", sKeyName, "uint", 0, "uint", RegAccessRight, "uint*", hKey)   ; open key
   DllCall("Advapi32.dll\RegQueryValueExA", "uint", hKey, "str", sValueName, "uint", 0, "uint*", sValueType, "uint", 0, "uint", 0)      ; get value type
   If (sValueType == REG_SZ or sValueType == REG_EXPAND_SZ) {
      VarSetCapacity(sValue, vValueSize:=DataMaxSize)
      DllCall("Advapi32.dll\RegQueryValueExA", "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "str", sValue, "uint*", vValueSize)   ; get string or string-exp
   } Else If (sValueType == REG_DWORD) {
      VarSetCapacity(sValue, vValueSize:=4)
      DllCall("Advapi32.dll\RegQueryValueExA", "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "uint*", sValue, "uint*", vValueSize)   ; get dword
   } Else If (sValueType == REG_MULTI_SZ) {
      VarSetCapacity(sTmp, vValueSize:=DataMaxSize)
      DllCall("Advapi32.dll\RegQueryValueExA", "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "str", sTmp, "uint*", vValueSize)   ; get string-mult
      sValue := ExtractData(&sTmp) "`n"
      Loop {
         If (errorLevel+2 >= &sTmp + vValueSize)
            Break
         sValue := sValue ExtractData( errorLevel+1 ) "`n"
      }
   } Else If (sValueType == REG_BINARY) {
      VarSetCapacity(sTmp, vValueSize:=DataMaxSize)
      DllCall("Advapi32.dll\RegQueryValueExA", "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "str", sTmp, "uint*", vValueSize)   ; get binary
      sValue := ""
      SetFormat, integer, h
      Loop %vValueSize% {
         hex := SubStr(Asc(SubStr(sTmp,A_Index,1)),3)
         StringUpper, hex, hex
         sValue := sValue hex
      }
      SetFormat, integer, d
   } Else {            ; value does not exist or unsupported value type
      DllCall("Advapi32.dll\RegCloseKey", "uint", hKey)
      ErrorLevel := 1
      return ""
   }
   DllCall("Advapi32.dll\RegCloseKey", "uint", hKey)
   return sValue
}

RegWrite64(sValueType, sRootKey, sKeyName, sValueName = "", sValue = "") {
   HKEY_CLASSES_ROOT   := 0x80000000   ; http://msdn.microsoft.com/en-us/library/aa393286.aspx
   HKEY_CURRENT_USER   := 0x80000001
   HKEY_LOCAL_MACHINE   := 0x80000002
   HKEY_USERS         := 0x80000003
   HKEY_CURRENT_CONFIG   := 0x80000005
   HKEY_DYN_DATA      := 0x80000006
   HKCR := HKEY_CLASSES_ROOT
   HKCU := HKEY_CURRENT_USER
   HKLM := HKEY_LOCAL_MACHINE
   HKU    := HKEY_USERS
   HKCC := HKEY_CURRENT_CONFIG
   
   REG_NONE             := 0   ; http://msdn.microsoft.com/en-us/library/ms724884.aspx
   REG_SZ                := 1
   REG_EXPAND_SZ         := 2
   REG_BINARY            := 3
   REG_DWORD            := 4
   REG_DWORD_BIG_ENDIAN   := 5
   REG_LINK            := 6
   REG_MULTI_SZ         := 7
   REG_RESOURCE_LIST      := 8

   KEY_QUERY_VALUE := 0x0001   ; http://msdn.microsoft.com/en-us/library/ms724878.aspx
   KEY_WOW64_64KEY := 0x0100   ; http://msdn.microsoft.com/en-gb/library/aa384129.aspx (do not redirect to Wow6432Node on 64-bit machines)
   KEY_SET_VALUE   := 0x0002
   KEY_WRITE      := 0x20006
   
   myhKey := %sRootKey%         ; pick out value (0x8000000x) from list of HKEY_xx vars
   myValueType := %sValueType%      ; pick out value (0-8) from list of REG_SZ,REG_DWORD etc. types
   IfEqual,myhKey,, {      ; Error - Invalid root key
      ErrorLevel := 3
      return ErrorLevel
   }
   IfEqual,myValueType,, {   ; Error - Invalid value type
      ErrorLevel := 2
      return ErrorLevel
   }
   
   RegAccessRight := KEY_QUERY_VALUE + KEY_WOW64_64KEY + KEY_WRITE
   
   DllCall("Advapi32.dll\RegCreateKeyExA", "uint", myhKey, "str", sKeyName, "uint", 0, "uint", 0, "uint", 0, "uint", RegAccessRight, "uint", 0, "uint*", hKey)   ; open/create key
   If (myValueType == REG_SZ or myValueType == REG_EXPAND_SZ) {
      vValueSize := StrLen(sValue) + 1
      DllCall("Advapi32.dll\RegSetValueExA", "uint", hKey, "str", sValueName, "uint", 0, "uint", myValueType, "str", sValue, "uint", vValueSize)   ; write string
   } Else If (myValueType == REG_DWORD) {
      vValueSize := 4
      DllCall("Advapi32.dll\RegSetValueExA", "uint", hKey, "str", sValueName, "uint", 0, "uint", myValueType, "uint*", sValue, "uint", vValueSize)   ; write dword
   } Else {      ; REG_MULTI_SZ, REG_BINARY, or other unsupported value type
      ErrorLevel := 2
   }
   DllCall("Advapi32.dll\RegCloseKey", "uint", hKey)
   return ErrorLevel
}

ExtractData(pointer) {  ; http://www.autohotkey.com/forum/viewtopic.php?p=91578#91578 SKAN
   Loop {
         errorLevel := ( pointer+(A_Index-1) )
         Asc := *( errorLevel )
         IfEqual, Asc, 0, Break ; Break if NULL Character
         String := String . Chr(Asc)
      }
   Return String
}

; Thanks Chris, Lexikos and SKAN
; http://www.autohotkey.com/forum/topic37710-15.html
; http://www.autohotkey.com/forum/viewtopic.php?p=235522


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 12th, 2009, 10:31 pm 
Offline

Joined: October 12th, 2009, 10:18 pm
Posts: 1
Location: San Francisco
That is wonderful, it solve 1/2 of my needs.
I am also looking for a loop (registry) supporting the 64 bit registry. Anybody? thanks :D


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 4th, 2010, 2:51 am 
Offline

Joined: March 18th, 2010, 6:45 am
Posts: 1
Here is a small example of the registry redirector:
If you access the key HKEY_LOCAL_MACHINE\SOFTWARE\MyApp\Settings from a 64-bit app, you really opening this node. If you open this node from a 32-bit app, you are transparently redirected to HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MyApp\Setting.
Collapse

#include <windows.h>

#include <stdio.h>

#include <tchar.h>

#pragma comment(lib, "Advapi32.lib")
int _tmain()
{
LONG lRet;
HKEY hKey;
// Open the key in the default-view

lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE,

_T("SOFTWARE\\MyApp\\MySettings"),
0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
if(lRet == ERROR_SUCCESS)
{
#if _M_IX86
TCHAR szValue[] = _T("x86");
RegSetValueEx(hKey, _T("AppType"), 0, REG_SZ,
(const BYTE*) szValue,
(DWORD) (_tcslen(szValue)+sizeof(TCHAR))*sizeof(TCHAR));
#else
TCHAR szValue[] = _T("x64 / IA64");
RegSetValueEx(hKey, _T("AppType"), 0, REG_SZ,
(const BYTE*) szValue,
(DWORD) (_tcslen(szValue)+sizeof(TCHAR))*sizeof(TCHAR));
#endif
RegCloseKey(hKey);
}
return 0;
}

After executing this example as 32-bit 'and' 64-bit application, you have created two separate registry keys. One containing the "x86" value and the other containing the "x64 / IA64" value.
indianapolis web design


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 11:47 am 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
I need RegRead64(), but I can't get it to work on my Win7 x64.

This call fails ALWAYS! hKey is always 0 after the call.
Code:
DllCall("Advapi32.dll\RegOpenKeyExA", "uint", myhKey, "str", sKeyName, "uint", 0, "uint", RegAccessRight, "uint*", hKey)   ; open key

(BTW, it might be a good idea to check it, and return an ErrorLevel of 4 when it fails.)

I've tried everything, including reading keys in non-protected area of the registry, running the script as Administrator, modifying the code, but to no avail.

Can you confirm that that function is supposed to work under Win7, or is it specific to Vista or XP?

Here is an example of what I've used to check the function:
Code:
root  = HKEY_CURRENT_USER
key   = Console
value = ColorTable01
RegRead, key, %root%, %key%, %value%
key64 := RegRead64(root, key, value)
msgbox key = %key%`nkey64 = %key64%

the MsgBox shows the key retrieved by the standard AHK RegRead command, but of course nothing for RegRead64().

Someone can help?


P.S.: I second afranco's request. It would be nice to have also a function to browse the registry tree in x64 mode.

_________________
r0lZ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 12:19 pm 
Offline

Joined: August 12th, 2007, 3:49 am
Posts: 12
I haven't had a chance to test on Win7 but I'd take a guess that... ;-)

This works:
Code:
root  = HKEY_CURRENT_USER
rkey   = Console
value = ColorTable01
RegRead, key, %root%, %rkey%, %value%
key64 := RegRead64(root, rkey, value)
msgbox key = %key%`nkey64 = %key64%


And this doesn't:
Code:
root  = HKEY_CURRENT_USER
key   = Console
value = ColorTable01
RegRead, key, %root%, %key%, %value%
key64 := RegRead64(root, key, value)
msgbox key = %key%`nkey64 = %key64%


(the RegRead line is overwriting your key variable so RegRead64() is fed the wrong key)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 3:06 pm 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
Oops, that's right! But that code snipped is only something I've written to quickly test the function. In my real program, I haven't made the same error. And anyway, even after having fixed the bug or using your code, the problem persists.

Trust me, there is really something that doesn't work in RegRead64().
(I haven't checked RegWrite64() because I don't need it, but I'm almost sure it has a similar problem.)

BTW, I forgot to say that I use AutoHotkey_Lw v1.0.48.05.L51, if that makes any difference.

_________________
r0lZ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 3:15 pm 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
r0lZ wrote:
BTW, I forgot to say that I use AutoHotkey_Lw v1.0.48.05.L51, if that makes any difference.

Yeah! That's the problem!

The function works fine under the regular AutoHotkey, but fails under AHK_L. Pity, as I need AHK_L for the unicode support and the Objects.

[EDIT]
OK, the solution is simple! I should have read the AHK_L doc before posting here.

Under AHK_Lw (unicode build), simply replace "str" by "AStr" in all DLL calls. I still have to check if the returned value is correct when it's a string (as my example retrieves an integer), but I guess it will be OK.

[EDIT2]
No, that doesn't work. See my next post for the correct solution.

_________________
r0lZ


Last edited by r0lZ on May 20th, 2010, 3:53 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 3:34 pm 
Offline

Joined: August 12th, 2007, 3:49 am
Posts: 12
Ah - good find. Thanks for sharing the solution.


Report this post
Top
 Profile  
Reply with quote  
PostPosted: May 20th, 2010, 3:54 pm 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
Hum, the fix in my previous post doesn't work when a string is retrieved (such as a REG_SZ value type).

The correct fix for AHK_Lw (unicode build) is this one:

Do not change the "str" arguments as explained in my previous post. It's not necessary.

Replace ExA by ExW at the end of all function names in all DLLcalls. (Only RegCloseKey doesn't need to be modified.)

You might also want to increase the default value of the DataMaxSize argument in RegRead64() from 1024 to 2048, to take the "double size" of unicode strings into account.

_________________
r0lZ


Last edited by r0lZ on May 20th, 2010, 3:58 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
PostPosted: May 20th, 2010, 3:58 pm 
Offline
User avatar

Joined: May 5th, 2007, 7:24 pm
Posts: 1240
Location: Seville, Spain
r0lZ wrote:
Replace ExA by ExW at the end of all function names in the calls. (Only RegCloseKey doesn't need to be modified.)


Better yet, replace ExA by just Ex to make it work on both AutoHotkey_L builds.

_________________
fincs
Highly recommended: AutoHotkey_L (see why) (all my code snippets require it)
Formal request to polyethene - I support the unity of the AutoHotkey community
Get SciTE4AutoHotkey v3.0.00 (Release Candidate)
[My project list]


Report this post
Top
 Profile  
Reply with quote  
PostPosted: May 20th, 2010, 4:02 pm 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
fincs wrote:
Better yet, replace ExA by just Ex to make it work on both AutoHotkey_L builds.
Oh, yes, thanks for the tip.
But it I've understood correctly, when the A or W extension is not present, AHK_L tries both functions. Is it right? In that case, it might take longer to execute it. Right?
Or does it simply append the correct extension before calling the right function?

_________________
r0lZ


Last edited by r0lZ on May 20th, 2010, 4:11 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 4:10 pm 
Offline
User avatar

Joined: May 5th, 2007, 7:24 pm
Posts: 1240
Location: Seville, Spain
It does append the correct extension.

_________________
fincs
Highly recommended: AutoHotkey_L (see why) (all my code snippets require it)
Formal request to polyethene - I support the unity of the AutoHotkey community
Get SciTE4AutoHotkey v3.0.00 (Release Candidate)
[My project list]


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 4:13 pm 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
Thanks.

I have another question. Can I use these RegRead64() and RegWrite64() functions under an x86 version of Windows? I suppose that the same DLL exist, and that the KEY_WOW64_64KEY flag is simply ignored on non-64bit systems. Am I right? (Unfortunately, I don't have x86 OSses here to test.)

_________________
r0lZ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 4:14 pm 
Offline
User avatar

Joined: May 5th, 2007, 7:24 pm
Posts: 1240
Location: Seville, Spain
I think the flag is indeed ignored.

_________________
fincs
Highly recommended: AutoHotkey_L (see why) (all my code snippets require it)
Formal request to polyethene - I support the unity of the AutoHotkey community
Get SciTE4AutoHotkey v3.0.00 (Release Candidate)
[My project list]


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 20th, 2010, 4:23 pm 
Offline

Joined: August 12th, 2007, 3:49 am
Posts: 12
Correct - the function works fine on 32bit machines as well.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Stigg, tidbit and 10 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group