 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
tomte
Joined: 12 Aug 2007 Posts: 12
|
Posted: Tue Jan 06, 2009 2:13 pm Post subject: RegRead64() and RegWrite64() - no redirect to Wow6432Node |
|
|
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 |
|
 |
afranco
Joined: 12 Oct 2009 Posts: 1 Location: San Francisco
|
Posted: Mon Oct 12, 2009 9:31 pm Post subject: |
|
|
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  |
|
| Back to top |
|
 |
twigdulla17
Joined: 18 Mar 2010 Posts: 1
|
Posted: Sun Apr 04, 2010 1:51 am Post subject: |
|
|
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 |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Thu May 20, 2010 10:47 am Post subject: |
|
|
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 |
|
 |
tomte
Joined: 12 Aug 2007 Posts: 12
|
Posted: Thu May 20, 2010 11:19 am Post subject: |
|
|
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) |
|
| Back to top |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Thu May 20, 2010 2:06 pm Post subject: |
|
|
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 |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Thu May 20, 2010 2:15 pm Post subject: |
|
|
| 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 |
|
 |
tomte
Joined: 12 Aug 2007 Posts: 12
|
Posted: Thu May 20, 2010 2:34 pm Post subject: |
|
|
| Ah - good find. Thanks for sharing the solution. |
|
| Back to top |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Thu May 20, 2010 2:54 pm Post subject: Fix for AHK_Lw (unicode build) |
|
|
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 |
|
 |
fincs
Joined: 05 May 2007 Posts: 1158 Location: Seville, Spain
|
Posted: Thu May 20, 2010 2:58 pm Post subject: Re: Fix for AHK_Lw (unicode build) |
|
|
| 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 |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Thu May 20, 2010 3:02 pm Post subject: Re: Fix for AHK_Lw (unicode build) |
|
|
| 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 |
|
 |
fincs
Joined: 05 May 2007 Posts: 1158 Location: Seville, Spain
|
|
| Back to top |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Thu May 20, 2010 3:13 pm Post subject: |
|
|
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 |
|
 |
fincs
Joined: 05 May 2007 Posts: 1158 Location: Seville, Spain
|
|
| Back to top |
|
 |
tomte
Joined: 12 Aug 2007 Posts: 12
|
Posted: Thu May 20, 2010 3:23 pm Post subject: |
|
|
| Correct - the function works fine on 32bit machines as well. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|