StrLen does not work for binary buffers, either (only tell where the first NULL is), so these functions need an extra parameter, the actual length of the buffers (which can be smaller than the allocated memory). Setting the length to 0 makes the functions use all the allocated space for the buffers.

Hex2Bin and Bin2Hex convert data between binary form and double-digit hex strings.

BufferCopy copies (part of) a binary buffer into another variable.

BufferCompare compares two binary variables. The result is 0 at equality, otherwise the first different bytes determine the sign of the returned value: negative if the first parameter is smaller, positive if it is larger than the second parameter.

First some calling examples are given, with listing all the variables. The actual functions follow.

hModule := DllCall("LoadLibrary","str","msvcrt.dll") ; Preloads C library Hex2Bin(b0,"000102030405060708090a0b0c0d0e0f00") Hex2Bin(b1,"000102030405060708090a0b0c0d0e0f01") BufferCopy(a,b0,0,17) BufferCopy(c,b0,2,15) Bin2Hex(g,a,17) Bin2Hex(h,c,15) x := BufferCompare(a, b0,17) y := BufferCompare(b1,b0,17) MsgBox %g%`n%h%`n%x%`n%y% GoSub $ ; ListVars for debug DllCall("FreeLibrary", "UInt", hModule) ExitApp BufferCompare(ByRef a, Byref b, n=0) ; compare buffers { ; a <,=,> b: Return <,=,> 0 u := VarSetCapacity(a) v := VarSetCapacity(b) IfLess n, 1, SetEnv n,0xffffffff ; n = 0: compare all allocated IfLess u,%n%, SetEnv n,%u% ; use at most the capacity of a IfLess v,%n%, SetEnv n,%v% ; use at most the capacity of b Return DllCall("msvcrt\memcmp", "UInt", &a, "UInt", &b, "UInt", n, "CDecl Int") } BufferCopy(ByRef a, Byref b, b0=0,n=0) ; copy buffer a <- b[b0 + 0..n-1] { m := VarSetCapacity(b)-b0 IfLess m,1, { ; nothing is left a = Return } IfLess n, 1, SetEnv n,0xffffffff ; n = 0: copy all allocated memory IfLess m,%n%, SetEnv n,%m% ; copy at most the capacity Granted := VarSetCapacity(a, n, 33) ; make sure a is large enough IfLess Granted,%n%, { ErrorLevel = Mem=%Granted% ; Error if not enough memory Return } StringLeft a, a, n ; trim to the right length DllCall("RtlMoveMemory", "UInt", &a, "UInt", &b + b0, "UInt", n) } Bin2Hex(ByRef h, ByRef b, n=0) ; n bytes binary data -> stream of 2-digit hex { ; n = 0: all (SetCapacity can be larger than used!) format = %A_FormatInteger% ; save original integer format SetFormat Integer, Hex ; for converting bytes to hex m := VarSetCapacity(b) If (n < 1 or n > m) n := m Address := &b h = Loop %n% { x := *Address ; get byte in hex StringTrimLeft x, x, 2 ; remove 0x x = 0%x% ; pad left StringRight x, x, 2 ; 2 hex digits h = %h%%x% Address++ } SetFormat Integer, %format% ; restore original format } Hex2Bin(ByRef b, h, n=0) ; n hex digit-pairs -> binary data { ; n = 0: all. (Only ByRef can handle binaries) m := Ceil(StrLen(h)/2) If (n < 1 or n > m) n := m Granted := VarSetCapacity(b, n, 33) IfLess Granted,%n%, { ErrorLevel = Mem=%Granted% Return } StringLeft b, b, n Address := &b Loop %n% { StringLeft x, h, 2 StringTrimLeft h, h, 2 x = 0x%x% DllCall("RtlFillMemory", "UInt", Address, "UInt", 1, "UChar", x) Address++ } } $: ShowVars: ; list vars, wait until closed (ESC, [x]) ListVars ; Subroutine shows function locals, too WinGet ID, ID, A ; note ListVars window ID Loop { Sleep 30 IfWinNotExist ahk_id %ID% break } Return