Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

RegRead64() and RegWrite64() - no redirect to Wow6432Node


  • Please log in to reply
31 replies to this topic
r0lZ
  • Members
  • 192 posts
  • Last active: Feb 11 2012 11:19 PM
  • Joined: 21 Apr 2007
Thanks to you, tomte and fincs. You are doing a wonderful job in maintaining AutoHotkey alive and helping the newbies like me!

BTW, tomte, any chance to have a function to parse the x64 registry? ;-)
r0lZ

fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007
I've recently released (2 days ago) a native 64-bit build of AutoHotkey_L and registry loops might even work, the catch is that DllCall and RegisterCallback are not implemented at the moment.

r0lZ
  • Members
  • 192 posts
  • Last active: Feb 11 2012 11:19 PM
  • Joined: 21 Apr 2007
I've noticed that. Great job! But I need to parse the registry for x64 AND x86 apps, so even if, with your AHK_L64, I can remove the two x64 function needed by the 32bit versions of AutoHotkey, I will need equivalent functions to read the registry in 32bit mode. So, currently, there is no solution, until your new version will support DLLcall.

But I've found the M$ doc of RegEnumKey(), and I'll try to implement it. With the numerous examples of DLLcalls in this forum and what's I've learned today, that should be possible.

Thanks again!
r0lZ

r0lZ
  • Members
  • 192 posts
  • Last active: Feb 11 2012 11:19 PM
  • Joined: 21 Apr 2007
I've somewhat expanded the RegRead64() function to (partially) implement the REG_QWORD registry data type.

You have to add this line at the end of the data types list:
REG_QWORD            := 11

and this, in the cases list later in the original code:
} Else If (sValueType == REG_QWORD) {
        VarSetCapacity(sValue, vValueSize:=8)
        DllCall("Advapi32.dll\RegQueryValueEx", "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "uint64*", sValue, "uint*", vValueSize)
Note the "uint64*" instead of the usual "uint*".

This code is for AHK_L. If you use the mainstream AHK, replace RegQueryValueEx by RegQueryValueExA.

That works well, but due to a AHK limitation (at least in non-64bit versions), the unsigned 64bit integers have to be treated as signed, so you have to take care if the returned value is negative.
r0lZ

jonib
  • Members
  • 75 posts
  • Last active: Feb 18 2017 04:44 PM
  • Joined: 09 May 2006

But I've found the M$ doc of RegEnumKey(), and I'll try to implement it. With the numerous examples of DLLcalls in this forum and what's I've learned today, that should be possible.

I've been meaning to post my RegEnumKey64(), It works for me but not a full replacement for the Reg loop.

Example code:
  Loop
  {
    If Not GDFGamePath := RegEnumKey64("HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\GameUX" . RegPath, (A_Index - 1))
      Break
    GDFGamePath%GameNr% := RegRead64("HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\GameUX" . RegPath . "" . GDFGamePath, GamePath)
  }
Hopefully this is useful, I'll add more info if needed, don't have time right now.
RegEnumKey64(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
   KEY_ENUMERATE_SUB_KEYS := 0x0008
  ERROR_MORE_DATA := 234
  ERROR_NO_MORE_ITEMS := 259
  ERROR_SUCCESS := 0

   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 + KEY_ENUMERATE_SUB_KEYS

   DllCall("Advapi32.dll\RegOpenKeyExA", "uint", myhKey, "str", sKeyName, "uint", 0, "uint", RegAccessRight, "uint*", hKey)   ; open key

  VarSetCapacity(sValue, vValueSize := 64000)
  If DllCall("Advapi32.dll\RegEnumKeyExA", "uint", hKey, "uint", sValueName, "str", sValue, "uint*", vValueSize, "uint", 0, "uint", 0, "uint", 0, "uint", 0)      ; get value type
    sValue := ""
   DllCall("Advapi32.dll\RegCloseKey", "uint", hKey)
   return sValue
}

jonib

r0lZ
  • Members
  • 192 posts
  • Last active: Feb 11 2012 11:19 PM
  • Joined: 21 Apr 2007
I've written something very similar, but I use the AHK_L Object() to return more information in an array. Also, I've written another function to return the value names (and again more info in an array), using RegEnumValue().

With these two functions, it is easy to parse a whole branch of the registry, although it's not so easy than with the native AHK loop method.

Maybe I'll post my code here later, but it is not finished yet.

Thanks anyway for your help!
r0lZ

captainspacedog
  • Members
  • 27 posts
  • Last active: Nov 03 2011 03:25 PM
  • Joined: 21 Jul 2009
I am trying to write registry entries on a remote 64bit computer.
We are using this to add notices to users via the regkeys below.

Any ideas?

HKEY_LOCAL_MACHINE, Software\Microsoft\Windows NT\CurrentVersion\Winlogon, LegalNoticeCaption
and
HKEY_LOCAL_MACHINE, Software\Microsoft\Windows NT\CurrentVersion\Winlogon, LegalNoticeText

Nozavi
  • Members
  • 111 posts
  • Last active: Aug 19 2011 11:34 AM
  • Joined: 20 Feb 2008

How about deleting a key?

Shouldn't it look like this?

DllCall("Advapi32.dll\RegOpenKeyExA", "uint", myhKey, "str", sKeyName, "uint", 0, "uint", RegAccessRight, "uint*", hKey) 
DllCall("Advapi32.dll\RegDeleteKeyExA", "uint", hKey, "str", sKeyName, "uint", RegAccessRight , "uint", 0)


UP

BGM
  • Members
  • 199 posts
  • Last active: Jun 05 2015 06:26 PM
  • Joined: 12 Jan 2011
Hi, y'all! I have a problem here.
I want to write this key (onto 64bit windows 7)(I have AutoHotkey_L), but it writes to the WOW key anyway.

regwrite, REG_SZ, HKEY_LOCAL_MACHINE, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\Namespace\{21EC2020-3AEA-1069-A2DD-08002B30309D} ;Add Control Panel to My Computer (no keys)

So I tried regwrite64, but it didn't write to the right key either.

regwrite64("REG_SZ", "HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\Namespace\{21EC2020-3AEA-1069-A2DD-08002B30309D}")

Am I missing something?

r0lZ
  • Members
  • 192 posts
  • Last active: Feb 11 2012 11:19 PM
  • Joined: 21 Apr 2007
I think you must use regwrite64 and AHK_L X64 and have administrator rights to write to the right key!
r0lZ

BGM
  • Members
  • 199 posts
  • Last active: Jun 05 2015 06:26 PM
  • Joined: 12 Jan 2011
AHK_L X64? I didn't know there was a 64bit version. That might help...

BGM
  • Members
  • 199 posts
  • Last active: Jun 05 2015 06:26 PM
  • Joined: 12 Jan 2011
I am using a 32bit system, but am provisioning a 64bit system, and don't want to install 64bit AHK. Is there a location where I can download just the 64bit AutoHotkey binary without any installer?

r0lZ
  • Members
  • 192 posts
  • Last active: Feb 11 2012 11:19 PM
  • Joined: 21 Apr 2007
I don't know, but installers are mainly ZIP archives with an executable program. You should be able to extract the binaries with a good archiver program such as 7-zip, without installing the package.

There are 3 versions of AHK_L: ANSI 32 bit, unicode 32 bit and unicode 64 bit.

Personally, I install the 3 AHK_L versions in the same folder, but I rename the binaries before installing the next version, to keep them all. Only Autohotkey.exe and AutoHotkeySC.bin are different in the different packages.

Of course, you cannot run the 64 bit version on a 32 bit computer, but you can compile a 64 bit version of your script, and test it on another computer.
r0lZ

BGM
  • Members
  • 199 posts
  • Last active: Jun 05 2015 06:26 PM
  • Joined: 12 Jan 2011
Yes, I know I can't run the 64bit version on my 32bit computer, but I can copy the 64bit one to the b4bit computer and use it there until I am finished with it.

It never occurred to me to unzip the installer! Now, I see 3 AutoHotkey.exe 's in there! I assume the 64bit version is the larger-sized one without any icon.

After I did that, hey, it works! Now, if only that reg64 script would work for binary values!

Thanks for your advice.

random11
  • Members
  • 102 posts
  • Last active: May 27 2014 02:48 PM
  • Joined: 10 Dec 2008

I dont know what im doing wrong. I copied the code exactly and even when I try a  registry that is in both 64 and 32 bit sections I still get an error. Here is the 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

5::
out := RegRead64("HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\Audio", "EnableCaptureMonitor")
MsgBox %out% err:%ErrorLevel%
return

4:: 
send ^s
Reload
return

Can someone help me