AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

RegRead64() and RegWrite64() - no redirect to Wow6432Node
Goto page 1, 2  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
tomte



Joined: 12 Aug 2007
Posts: 12

PostPosted: Tue Jan 06, 2009 2:13 pm    Post subject: RegRead64() and RegWrite64() - no redirect to Wow6432Node Reply with quote

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
Back to top
View user's profile Send private message
afranco



Joined: 12 Oct 2009
Posts: 1
Location: San Francisco

PostPosted: Mon Oct 12, 2009 9:31 pm    Post subject: Reply with quote

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 Very Happy
Back to top
View user's profile Send private message
twigdulla17



Joined: 18 Mar 2010
Posts: 1

PostPosted: Sun Apr 04, 2010 1:51 am    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 20, 2010 10:47 am    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
tomte



Joined: 12 Aug 2007
Posts: 12

PostPosted: Thu May 20, 2010 11:19 am    Post subject: Reply with quote

I haven't had a chance to test on Win7 but I'd take a guess that... Wink

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)
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 20, 2010 2:06 pm    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 20, 2010 2:15 pm    Post subject: Reply with quote

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 Thu May 20, 2010 2:53 pm; edited 2 times in total
Back to top
View user's profile Send private message
tomte



Joined: 12 Aug 2007
Posts: 12

PostPosted: Thu May 20, 2010 2:34 pm    Post subject: Reply with quote

Ah - good find. Thanks for sharing the solution.
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 20, 2010 2:54 pm    Post subject: Fix for AHK_Lw (unicode build) Reply with quote

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 Thu May 20, 2010 2:58 pm; edited 1 time in total
Back to top
View user's profile Send private message
fincs



Joined: 05 May 2007
Posts: 1158
Location: Seville, Spain

PostPosted: Thu May 20, 2010 2:58 pm    Post subject: Re: Fix for AHK_Lw (unicode build) Reply with quote

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
Get SciTE4AutoHotkey v3.0.00 (Release Candidate)
[My project list]
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 20, 2010 3:02 pm    Post subject: Re: Fix for AHK_Lw (unicode build) Reply with quote

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 Thu May 20, 2010 3:11 pm; edited 2 times in total
Back to top
View user's profile Send private message
fincs



Joined: 05 May 2007
Posts: 1158
Location: Seville, Spain

PostPosted: Thu May 20, 2010 3:10 pm    Post subject: Reply with quote

It does append the correct extension.
_________________
fincs
Get SciTE4AutoHotkey v3.0.00 (Release Candidate)
[My project list]
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 20, 2010 3:13 pm    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
fincs



Joined: 05 May 2007
Posts: 1158
Location: Seville, Spain

PostPosted: Thu May 20, 2010 3:14 pm    Post subject: Reply with quote

I think the flag is indeed ignored.
_________________
fincs
Get SciTE4AutoHotkey v3.0.00 (Release Candidate)
[My project list]
Back to top
View user's profile Send private message
tomte



Joined: 12 Aug 2007
Posts: 12

PostPosted: Thu May 20, 2010 3:23 pm    Post subject: Reply with quote

Correct - the function works fine on 32bit machines as well.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group