System macro not working on AutoHotkey v1.1+ x64 Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jballi
Posts: 724
Joined: 29 Sep 2013, 17:34

System macro not working on AutoHotkey v1.1+ x64

18 Aug 2019, 17:07

This system macro works (for the most part) on AutoHotkey Basic, AutoHotkey v1.1+ ANSI and Unicode but does work on AutoHotkey v1.1+ x64.

Here is an example.

Code: Select all

#NoEnv
SetFormat Integer,Hex
x:=0x00007FFF6B133B1B
x:=DllCall("ntdll\RtlUlonglongByteSwap","UInt64",x,"CDecl UInt64")
outputdebug ErrorLevel: %ErrorLevel%, A_LastError: %A_LastError%
MsgBox % "Does you see a number?: " . x . "`nErrorLevel: " . ErrorLevel
return
Any help would be appreciated.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: System macro not working on AutoHotkey v1.1+ x64  Topic is solved

18 Aug 2019, 17:41

only the 32-bit ntdll exports a RtlUlonglongByteSwap. when u run the 64-bit ahk, 64-bit dlls will get loaded in.
use MsgBox % Format("0x{:X}", DllCall("ucrtbase\_byteswap_uint64", "UInt64", 0x00007FFF6B133B1B, "UInt64"))
User avatar
jballi
Posts: 724
Joined: 29 Sep 2013, 17:34

Re: System macro not working on AutoHotkey v1.1+ x64

18 Aug 2019, 17:49

I'm testing it now. It looks like the right solution. Thanks for the help. :)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: System macro not working on AutoHotkey v1.1+ x64

20 Aug 2019, 18:46

See:
LoadPicture() from variable - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=39002&p=181321#p181321

And here:
best utilities + best AutoHotkey scripts (+ useful tips) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=28149

[ list all of the functions in a dll file][ list dll functions]
[function: DllListExports (old version: PE_FunctionExports)]
DllListExports() - List of Function exports of a DLL - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=4563
AHK Functions :: InCache() - Cache List of Recent Items - Page 9 - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/7984-ahk-functions-incache-cache-list-of-recent-items/page-9
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jballi
Posts: 724
Joined: 29 Sep 2013, 17:34

Re: System macro not working on AutoHotkey v1.1+ x64

20 Aug 2019, 20:38

@jeeswg, Lots of good info. Thanks!

In this case, I was looking for system function to swap the bytes of a UInt64. I wrote my own function based on the RtlUlonglongByteSwap macro but it keeps clipping the high bit. [Stuff about AutoHotkey limitations] The _byteswap_uint64 system function appears to be in the 32-bit and 64-bit libraries and it does the job. I'm not planning to publish anything that uses it but it should work on all versions of AutoHotkey.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: System macro not working on AutoHotkey v1.1+ x64

20 Aug 2019, 21:55

Hmm. :think:
Reversing the bytes in a UInt64 / Int64.
I knew that Format can do Int64 to UInt64.
But it seems it cannot do UInt64 to Int64. So NumPut/NumGet is needed.

If you do bitshift-right on a negative number, it fills in all the initial bits with 1s. And so if you read that number as a positive number, it will be much bigger than it should be. But if you use & with a mask, you can ignore those initial bits.

Anyhow, a magic number is needed at one point: -72057594037927936, the Int64 dec equivalent of UInt64 hex 0xFF00000000000000.
One way of calculating this number, that I didn't use in the script, is, instead of:
UInt64: 0xFFFFFFFFFFFFFFFF - 0x00FFFFFFFFFFFFFF = 0xFF00000000000000
we do:
Int64: -1 - 0x00FFFFFFFFFFFFFF = -0x0100000000000000 = -72057594037927936
[EDIT:] You can omit the magic number. See 'with magic number' and 'without magic number' below.

Code: Select all

;==================================================

q:: ;Int64 to UInt64, and, UInt64 to Int64

;Int64 to UInt64:
MsgBox, % Format("{:i}", -1) ;-1
MsgBox, % Format("{:u}", -1) ;18446744073709551615
MsgBox, % Format("0x{:X}", -1) ;0xFFFFFFFFFFFFFFFF

;UInt64 to Int64 (fail):
;MsgBox, % Format("{:i}", "0xFFFFFFFFFFFFFFFF") ;incorrect: 9223372036854775807
;MsgBox, % Format("{:u}", "0xFFFFFFFFFFFFFFFF") ;incorrect: 9223372036854775807
;MsgBox, % Format("0x{:X}", "0xFFFFFFFFFFFFFFFF") ;incorrect: 0x7FFFFFFFFFFFFFFF

;UInt64 to Int64:
vNum := (0xFFFFFFFF<<32) | 0xFFFFFFFF
MsgBox, % vNum ;-1
MsgBox, % Format("{:i}", vNum) ;-1
MsgBox, % Format("{:u}", vNum) ;18446744073709551615
MsgBox, % Format("0x{:X}", vNum) ;0xFFFFFFFFFFFFFFFF

;UInt64 to Int64:
VarSetCapacity(vData, 8, 0)
NumPut("0xFFFFFFFFFFFFFFFF", &vData, 0, "UInt64")
vNum := NumGet(&vData, 0, "Int64")
MsgBox, % Format("{:i}", vNum) ;-1
MsgBox, % Format("{:u}", vNum) ;18446744073709551615
MsgBox, % Format("0x{:X}", vNum) ;0xFFFFFFFFFFFFFFFF
return

;==================================================

w:: ;convert UInt64 to Int64 via NumGet (recommended)
vHex := "0xFF00000000000000"
;vHex := "0xFFEEDDCCBBAA9988"
VarSetCapacity(vData, 8, 0)
NumPut(vHex, &vData, 0, "UInt64")
vNum := NumGet(&vData, 0, "Int64")
MsgBox, % vNum ;-72057594037927936
MsgBox, % Format("0x{:016X}", vNum) ;0xFF00000000000000
return

e:: ;convert UInt64 to Int64 via RegExReplace and bit-or (split number in two)
vHex := "0xFF00000000000000"
;vHex := "0xFFEEDDCCBBAA9988"
vTemp := RegExReplace(vHex, "i)(0x)?([0-9A-Z]{8})([0-9A-Z]{8})", "0x$2 0x$3")
MsgBox, % vTemp
oTemp := StrSplit(vTemp, " ")
;vNum := (0xFF000000<<32) | 0x00000000
vNum := (oTemp.1<<32) | oTemp.2
MsgBox, % vNum ;-72057594037927936
MsgBox, % Format("0x{:016X}", vNum) ;0xFF00000000000000
return

;==================================================

r:: ;reverse bytes in UInt64
vHex := "0xFFEEDDCCBBAA9988"
;vHex := "0xFFEEDDCCBBAA99FF"
Loop 4
{
	;UInt64 (hex) to Int64 (dec):
	VarSetCapacity(vData, 8, 0)
	NumPut(vHex, &vData, 0, "UInt64")
	vNum := NumGet(&vData, 0, "Int64")

	;MsgBox, % vNum ;-4822678189205112
	;MsgBox, % Format("0x{:016X}", vNum) ;0xFFEEDDCCBBAA9988
	;MsgBox, % Format("0x{:016X}", -72057594037927936&vNum) ;0xFF00000000000000
	;MsgBox, % Format("0x{:016X}", ((-72057594037927936&vNum)>>56)&0xFF) ;0x00000000000000FF

	;Int64 reverse bytes (with magic number):
	;vNum := ((-72057594037927936&vNum)>>56)&0xFF | (0xFF000000000000&vNum)>>40 | (0xFF0000000000&vNum)>>24 | (0xFF00000000&vNum)>>8 | (0xFF000000&vNum)<<8 | (0xFF0000&vNum)<<24 | (0xFF00&vNum)<<40 | (0xFF&vNum)<<56

	;Int64 reverse bytes (without magic number):
	vNum := (vNum>>56)&0xFF | (0xFF000000000000&vNum)>>40 | (0xFF0000000000&vNum)>>24 | (0xFF00000000&vNum)>>8 | (0xFF000000&vNum)<<8 | (0xFF0000&vNum)<<24 | (0xFF00&vNum)<<40 | (0xFF&vNum)<<56

	;Int64 (dec) to UInt64 (hex):
	vHex := Format("0x{:016X}", vNum)
	MsgBox, % vHex
}
return
Thanks for the DllCall version:
MsgBox, % Format("0x{:16X}", DllCall("ucrtbase\_byteswap_uint64", "UInt64","0xFFEEDDCCBBAA9988", "UInt64"))
Last edited by jeeswg on 22 Aug 2019, 03:07, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jballi
Posts: 724
Joined: 29 Sep 2013, 17:34

Re: System macro not working on AutoHotkey v1.1+ x64

20 Aug 2019, 23:06

jeeswg wrote:
20 Aug 2019, 21:55
Anyhow, a magic number is needed at one point: -72057594037927936, the Int64 dec equivalent of UInt64 hex 0xFF00000000000000.
Ahh. There's always a magic number. ;)

Thanks for the feedback and the alternate solutions. I appreciate it.
just me
Posts: 9482
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: System macro not working on AutoHotkey v1.1+ x64

21 Aug 2019, 03:57

jeeswg wrote:
20 Aug 2019, 21:55
...
Anyhow, a magic number is needed at one point: -72057594037927936, the Int64 dec equivalent of UInt64 hex 0xFF00000000000000.
...
Why?
User avatar
jballi
Posts: 724
Joined: 29 Sep 2013, 17:34

Re: System macro not working on AutoHotkey v1.1+ x64

21 Aug 2019, 07:41

just me wrote:
21 Aug 2019, 03:57
jeeswg wrote:
20 Aug 2019, 21:55
...
Anyhow, a magic number is needed at one point: -72057594037927936, the Int64 dec equivalent of UInt64 hex 0xFF00000000000000.
...
Why?
OK, I'll take a shot at it.

AutHotkey supports signed 64-bit numbers (Int64). It does not support unsigned 64-bit numbers (UInt64). If a number is too large to fit into Int64, it will be truncated or otherwise modified. The largest number you can fit into Int64 is 9,223,372,036,854,775,807. The smallest value is -9,223,372,036,854,775,808.

The mask jeeswg is working with in this case is 0xFF00000000000000. The decimal equivalent of 0xFF00000000000000 is 18,374,686,479,671,623,680. As you can see, this number is larger than can fit into Int64 so if we use it, it won't give us the correct results.

What we need is the Int64 equivalent of 0xFF00000000000000. -72,057,594,037,927,936 is that magic number. Since we are performing a Bitwise-and (&) operation, 0xFF00000000000000 and -72,057,594,037,927,936 are the exact same value from a bit value perspective. Don't believe me? Open the Microsoft Calculator and change the view to Programmer. With the mouse, click on the high 8 bits so that they change from 0 to 1. You should see -72,057,594,037,927,936 in the display. OK, click on the Hex radio button to change the view to Hex. You should now see FF00 0000 0000 0000. Magic!

I hope this was helpful.
just me
Posts: 9482
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: System macro not working on AutoHotkey v1.1+ x64

21 Aug 2019, 16:38

Code: Select all

#NoENv ; reverse bytes in UInt64
vHex := "0xFFEEDDCCBBAA9988"
; UInt64 (hex) to Int64 (dec):
VarSetCapacity(vData, 8, 0)
NumPut(vHex, &vData, 0, "UInt64")
vNum := NumGet(&vData, 0, "Int64")
; Int64 reverse bytes:
; jeeswg with 'Magic Number'
vNum1 := ((-72057594037927936&vNum)>>56)&0xFF | (0xFF000000000000&vNum)>>40 | (0xFF0000000000&vNum)>>24 | (0xFF00000000&vNum)>>8
       | (0xFF000000&vNum)<<8 | (0xFF0000&vNum)<<24 | (0xFF00&vNum)<<40 | (0xFF&vNum)<<56
; jeeswg w/o 'Magic Number'
vNum2 := (vNum>>56)&0xFF | (0xFF000000000000&vNum)>>40 | (0xFF0000000000&vNum)>>24 | (0xFF00000000&vNum)>>8
       | (0xFF000000&vNum)<<8 | (0xFF0000&vNum)<<24 | (0xFF00&vNum)<<40 | (0xFF&vNum)<<56
; Another option
vNum3 := ((vNum >> 56) & 255) | (((vNum >> 48) & 255) << 8) | (((vNum >> 40) & 255) << 16) | (((vNum >> 32) & 255) << 24)
       | (((vNum >> 24) & 255) << 32) | (((vNum >> 16) & 255) << 40) | (((vNum >> 8) & 255) << 48) | ((vNum & 255) << 56)
MsgBox, %vNum1%`n%vNum2%`n%vNum3%
/*
---------------------------
F8565391.ahk
---------------------------
-8603657889541918977
-8603657889541918977
-8603657889541918977
---------------------------
OK   
---------------------------
*/
ExitApp
User avatar
jballi
Posts: 724
Joined: 29 Sep 2013, 17:34

Re: System macro not working on AutoHotkey v1.1+ x64

21 Aug 2019, 20:31

These are excellent examples of how to work-around the lack of support for UInt64. Thanks!

My pet peeve is that this is just one of many dozens of AutoHotkey limitations. Every time I look at my code (or anybody's AutoHotkey scripts) and I see some fancy bit manipulation or an odd way of coding things and I wonder, "Why did I code it that way?" The answer is often because I needed to work around a AutoHotkey limitation. Yes, I'm grateful that AutoHotkey is flexible enough to provide alternatives but I have lot of code that was written to work-around stuff. For this problem, my solution is just to call the built-in, ready-to-go, no-questions-asked library function. It's gonna be just as fast (or close enough) than a AutoHotkey function and it works on all versions of AutoHotkey. The bonus is that when you see the code, there is no confusion as to what it is supposed to do.

Them be my thoughts.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: System macro not working on AutoHotkey v1.1+ x64

22 Aug 2019, 03:30

- @jballi: I agree with what you're saying about quirky things in AutoHotkey.
- Anything quirky is a good candidate for comments / a separate function.
- Although, in this case, this kind of bitshift and bitwise-and/bitwise-or algorithm, is what you often see in other programming languages.

Code: Select all

;LoadPicture() from variable - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=39002&p=181462#p181462

q:: ;swap bytes (UInt)
vNum := 0x11223344
vNum := (0xFF000000&vNum)>>24 | (0xFF0000&vNum)>>8 | (0xFF00&vNum)<<8 | (0xFF&vNum)<<24
MsgBox, % Format("0x{:X}", vNum)
return
- @just me: Thanks. I wanted to recreate the logic of the script above. Hence the magic number. But indeed the following are equivalent, and I've updated my earlier post:
((0xFF000000&vNum)>>24)&0xFF
(vNum>>24)&0xFF
As as are these:
((-72057594037927936&vNum)>>56)&0xFF
(vNum>>56)&0xFF

- Btw in AHK v2, 0xFF00000000000000 wraps around to -72057594037927936.

Code: Select all

;AHK v1
vNum := 0xFF00000000000000
MsgBox, % vNum+0 ;incorrect: 9223372036854775807
MsgBox, % 0xFF00000000000000 ;0xFF00000000000000

;AHK v2
vNum := 0xFF00000000000000
MsgBox(vNum+0) ;-72057594037927936
MsgBox(0xFF00000000000000) ;-72057594037927936
- Here's another approach for UInt64 (hex) to Int64 (dec):

Code: Select all

q:: ;UInt64 (hex) to Int64 (dec) - remove last hex character
;vHex := "0x7FFFFFFFFFFFFFFF" ;9223372036854775807
;vHex := "0x8000000000000000" ;-9223372036854775808
;vHex := "0xFF00000000000000" ;-72057594037927936
vHex := "0xFFEEDDCCBBAA9988" ;-4822678189205112
;vHex := "0xFFFFFFFFFFFFFFFF" ;-1

vIsV1 := !!SubStr(1, 0)
vNum := (SubStr(vHex, 1, -1) << 4) + Format("0x{}", SubStr(vHex, vIsV1-1))
Clipboard := vNum
MsgBox, % vNum "`r`n" Format("0x{:016X}", vNum)
return
- I'm still curious if other clever techniques are available for:
- UInt64 (hex) to Int64 (dec). I.e. how to handle numbers in the range 0x8000000000000000 to 0xFFFFFFFFFFFFFFFF.
- UInt64 reverse bytes.

- There is this for example, for UInt64 (dec) to Int64 (dec):
UInt64 <--> Int64: Using large unsigned hex/decimals - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/16888-uint64-int64-using-large-unsigned-hexdecimals/
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: System macro not working on AutoHotkey v1.1+ x64

25 Aug 2019, 15:53

In the past, I'd collected lists of dlls and their functions.
(See the 'LoadPicture() from variable' link above.)
The following dlls contained functions with 'byteswap' in their names:
msvcr100.dll
msvcr110.dll
msvcr110_clr0400.dll
msvcr120.dll
msvcr120_clr0400.dll
msvcr120d.dll
ntdll.dll (32-bit version only)

All of the msvcrXXX.dll files contained these 3 functions:
_byteswap_uint64
_byteswap_ulong
_byteswap_ushort

@swagfag: Where did you come across ucrtbase?

Code: Select all

q:: ;reverse bytes UShort/UInt/UInt64

;these 3 functions are only in the 32-bit version of ntdll.dll
;MsgBox, % Format("0x{:04X}", DllCall("ntdll\RtlUshortByteSwap", "UShort","0xFFEE", "Cdecl UShort"))
;MsgBox, % Format("0x{:08X}", DllCall("ntdll\RtlUlongByteSwap", "UInt","0xFFEEDDCC", "Cdecl UInt"))
;MsgBox, % Format("0x{:016X}", DllCall("ntdll\RtlUlonglongByteSwap", "UInt64","0xFFEEDDCCBBAA9988", "Cdecl UInt64"))

MsgBox, % Format("0x{:04X}", DllCall("msvcr100\_byteswap_ushort", "UShort","0xFFEE", "Cdecl UShort"))
MsgBox, % Format("0x{:08X}", DllCall("msvcr100\_byteswap_ulong", "UInt","0xFFEEDDCC", "Cdecl UInt"))
MsgBox, % Format("0x{:016X}", DllCall("msvcr100\_byteswap_uint64", "UInt64","0xFFEEDDCCBBAA9988", "Cdecl UInt64"))

MsgBox, % Format("0x{:04X}", DllCall("ucrtbase\_byteswap_ushort", "UShort","0xFFEE", "Cdecl UShort"))
MsgBox, % Format("0x{:08X}", DllCall("ucrtbase\_byteswap_ulong", "UInt","0xFFEEDDCC", "Cdecl UInt"))
MsgBox, % Format("0x{:016X}", DllCall("ucrtbase\_byteswap_uint64", "UInt64","0xFFEEDDCCBBAA9988", "Cdecl UInt64"))
return
Last edited by jeeswg on 24 Sep 2019, 14:27, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot] and 258 guests