help executing a classMemory function?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Asdam

help executing a classMemory function?

15 Aug 2017, 23:45

Hello, I'm having problems figuring out how to properly execute the "readRaw" function from the classMemory library made by RHCP (https://github.com/Kalamity/classMemory ... Memory.ahk)

I've made a test script designed to find a string in notepad (based off an example by RHCP)

It's supposed to find a string, then read part of that string into a temporary variable. The "finding a string" part is coded by RHCP (it has proven to work as expected since I include a file with his plugin in it) and the part I'm investigating is the readRaw part, which seems to return "0" or "1" instead of actual data.

Code: Select all

SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#Include ReadMemory.ahk

LoadData() {
	notepad := new _ClassMemory("ahk_exe Notepad.exe", "", hProcessCopy) 

	if !isObject(notepad) 
	{
		if (hProcessCopy = 0)
			msgbox The program isn't running (not found) or you passed an incorrect program identifier parameter. 
		else if (hProcessCopy = "")
			msgbox OpenProcess failed. If the target process has admin rights, then the script also needs to be ran as admin. Consult A_LastError for more information.
	}

	text := "this is a test"
	pattern := notepad.stringToPattern(text, "UTF-16")
	
	patternAddress := notepad.processPatternScan(,, pattern*) 
	 
	if patternAddress > 0
	{
		patternAddressString := "0x" ConvertBase(10, 16, patternAddress)
		msgbox % patternAddressString
		
		;tempvar := 0
		notepad.readRaw(patternAddress, ByRef tempvar, 2*)
		msgbox % tempvar
	}
	else
	{
		msgbox Not Found!`nReturn Value: %stringPattern%
	}
}

ConvertBase(InputBase, OutputBase, number)
{
	static u := A_IsUnicode ? "_wcstoui64" : "_strtoui64"
	static v := A_IsUnicode ? "_i64tow"    : "_i64toa"
	VarSetCapacity(s, 65, 0)
	value := DllCall("msvcrt.dll\" u, "Str", number, "UInt", 0, "UInt", InputBase, "CDECL Int64")
	DllCall("msvcrt.dll\" v, "Int64", value, "Str", s, "UInt", OutputBase, "CDECL")
	return s
}

^!F3::
	LoadData()
return
As you can see, I'm quite unsure how to properly execute the readRaw function, despite the EXPLICIT documentation in the classMemory script and of AHK's variadiac function execution...
I don't know
-which arguments are actually required to obtain the contents of the addresses (I thought the address and the program would be enough??)
-why some of the arguments are "optional", and whether that means I'm required to put in the non-optional arguments, especially because of the *
-whether this function should be initialized to a variable's value (i.e. tempvar := 0 or tempvar := notepad.readRaw etc...) or if that's unneccesary because of the usage of ByRef
-whether ByRef needs to be stated in the function call, or only in the function itself
-where the * goes to imply not all arguments are present, or if it's necessary at all in this case or any, since it's in the function declaration in the first place...

I've been messing around with this ******* code for days and I can't figure out what's supposed to make it WORK. Any help or direction would be highly appreciated. Am I just a scrub who doesn't know how to ******* write code or am I missing something HUGE here?!
Asdam
Posts: 3
Joined: 15 Aug 2017, 23:54

Re: help executing a classMemory function?

16 Aug 2017, 02:06

*ahem* so uh, I've calmed down a bit and un-scrubbed myself (and made an account)... AND figured out my problem! So aside from apologies for getting severely (overly?) PO'd, I'm gonna post the solution so this can... be marked as closed? I don't know how to remove a post I made as a guest (nice one again, me) so in case anyone else is curious about syntax, the working code appears to be this:

Code: Select all

notepad.readRaw(patternAddress, tempvar, bytes := 22 ;22 is just a number I picked to get an arbitrary 11 characters (2 bytes-per-character)
and I could use "test :=" etc to use a different variable (e.g. "test") to store whether it worked or not...

Thanks, me...

Edit: Well, now I have a new problem pertaining to the writeRaw function... It gives me error code 299 (ERROR_PARTIAL_COPY) whenever I try to use it... If anyone knows any reason this would be happening or how to fix it that'd be great.

Code: Select all

tempvar := [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
test := notepad.writeRaw(patternAddress, tempvar, sizeBytes := 22*)
msgbox % A_LastError
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: help executing a classMemory function?

16 Aug 2017, 07:18

Code: Select all

    ; Method:   writeRaw(address, pBuffer, sizeBytes, aOffsets*)
    ;           Writes a buffer to the process.
    ; Parameters:
    ;   address -       The memory address to which the contents of the buffer will be written 
    ;                   or if using the offset parameter, the base address of the pointer.    
    ;   pBuffer -       A pointer to the buffer which is to be written.
    ;                   This does not necessarily have to be the beginning of the buffer itself e.g. pBuffer := &buffer + offset
    ;   sizeBytes -     The number of bytes which are to be written from the buffer.
    ;   aOffsets* -     A variadic list of offsets. When using offsets the address parameter should equal the base address of the pointer.
    ;                   The address (base address) and offsets should point to the memory address which is to be written to.
    ; Return Values:
    ;       Non Zero -  Indicates success.
    ;       Zero     -  Indicates failure. Check errorLevel and A_LastError for more information
The function doesn't accept an array, but rather the address of the buffer that is to be written.
It gives me error code 299 (ERROR_PARTIAL_COPY) whenever I try to use it
You need to be a little careful when looking at A_lastError. A_LastError is not reset between function calls, therefore it's possible that a function higher up generated the 0x299 error.... in fact calling new _ClassMemory() will result in the 0x299 due to the way that one of the functions has to be written...although I could reset it. You can always manually reset the error using:

Code: Select all

DllCall("SetLastError", "UInt", 0)

Code: Select all

        array := [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
        ; create a variable called myBuffer and set its size to the number of bytes that are in array.
        ; the last parameter of VarSetCapacity() is used to initialise each byte to the specified value, in this case 0. 
        ; array.maxIndex() will return the value 23
        VarSetCapacity(myBuffer, array.maxIndex(), 0)
        ; Fill the buffer with values.
        for k, byteValue in array
        {
            NumPut(byteValue, myBuffer, A_Index - 1, "UChar")
        }

        ; the '&' in &myBuffer returns the pointer/address of myBuffer
        notepad.writeRaw(patternAddress, &myBuffer, array.maxIndex())
        msgbox % notepad.numberOfBytesWritten() " of " array.maxIndex() " bytes were written"
Asdam
Posts: 3
Joined: 15 Aug 2017, 23:54

Re: help executing a classMemory function?

16 Aug 2017, 21:38

Wow, thank you RHCP! I appreciate the education on your wrapper and Windows DLL-calls. I have one question though, if the VarSetCapacity function initializes the values with the last argument, why do they need to be copied with the loop?
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: help executing a classMemory function?

17 Aug 2017, 00:16

You're right, in the above case it's redundant as your array only contains the values 0. I included it in case can you wanted to write from an array that contained non zero values.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: ht55cd3 and 278 guests