Code only works on ANSI-32, narrowed down where the issue is but still stuck.

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Gully
Posts: 18
Joined: 14 Nov 2019, 11:07

Code only works on ANSI-32, narrowed down where the issue is but still stuck.

17 Nov 2019, 02:37

Hey, I'm tyring to use the BRA Standard Lib from tic that can be found here.

However it doesn't appear to be working on Unicode versions of AHK, in ANSI this works fine

Code: Select all

BRA_AddFiles(BRA, "Test.png")
MsgBox, % BRA_ListFiles(BRA, "", 1)
and successfully shows the file name in the message box.

If I've done any half decent job debugging this it appears the issue is either with the RtlMoveMemory DLL calls or it's with this line Pos := RegExMatch(BRAFromMemIn, "mi`n)^(\d+)\|(" NameMatch ")\|\d+\|\d+$", FileInfo, Pos+StrLen(FileInfo)) I tend to think it's actually the 2nd one, reason being that with MsgBox, Pos: %Pos% File info: %FileInfo% after it, I get a proper result in ANSI but not Unicode.

Any help would be appreciated :D I'm not too familiar with the differences between different AHK versions so I'm having trouble spotting the problem.
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Code only works on ANSI-32, narrowed down where the issue is but still stuck.

17 Nov 2019, 08:01

Both VarSetCapacity() and RtlMoveMemory expect a size given in bytes. If you call StrLen() in AHK Unicode it returns the length as the number of WCHars /WORDS which contain two bytes each.
Gully
Posts: 18
Joined: 14 Nov 2019, 11:07

Re: Code only works on ANSI-32, narrowed down where the issue is but still stuck.

17 Nov 2019, 13:03

just me wrote:
17 Nov 2019, 08:01
Both VarSetCapacity() and RtlMoveMemory expect a size given in bytes. If you call StrLen() in AHK Unicode it returns the length as the number of WCHars /WORDS which contain two bytes each.
Thanks! I guess that would be as simple as just multiplying the length by 2 everywhere. Do you know if I need to change the "UInt"'s in the DLLCalls to "Ptr"? I thought that was something I had to do as well but switching them alone wasn't fixing the issue. Will report back soon after updating the rest.

EDIT: I got the packing working on Unicode however the Gdip_BitmapFromBRA function still only works on ANSI, I suspect the issue is with the DllCall's again although not entirely sure what I have to change.. I thought FileInfo2 might need to be multiplied by 2 but that didn't work.

Also wondering if anyone knows of another lib like this that also allows you to read more than just images from memory? Ideally I'd like to be able to pack more than just images in the archive, like .ahk or .exe, read the archive into memory and then work with the files from there, as far as I know BRA can only do that with images, to do other files you would need to extract to drive first.

Code: Select all

Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate=0)
{
	Static FName = "ObjRelease"
	
	if !BRAFromMemIn
		return -1
	Loop, Parse, BRAFromMemIn, `n
	{
		if (A_Index = 1)
		{
			StringSplit, Header, A_LoopField, |
			if (Header0 != 4 || Header2 != "BRA!")
				return -2
		}
		else if (A_Index = 2)
		{
			StringSplit, Info, A_LoopField, |
			if (Info0 != 3)
				return -3
		}
		else
			break
	}
	if !Alternate
		StringReplace, File, File, \, \\, All
	RegExMatch(BRAFromMemIn, "mi`n)^" (Alternate ? File "\|.+?\|(\d+)\|(\d+)" : "\d+\|" File "\|(\d+)\|(\d+)") "$", FileInfo)
	if !FileInfo
		return -4
	
	hData := DllCall("GlobalAlloc", "uint", 2, Ptr, FileInfo2, Ptr)
	pData := DllCall("GlobalLock", Ptr, hData, Ptr)
	DllCall("RtlMoveMemory", Ptr, pData, Ptr, &BRAFromMemIn+Info2+FileInfo1, Ptr, FileInfo2)
	DllCall("GlobalUnlock", Ptr, hData)
	DllCall("ole32\CreateStreamOnHGlobal", Ptr, hData, "int", 1, A_PtrSize ? "UPtr*" : "UInt*", pStream)
	DllCall("gdiplus\GdipCreateBitmapFromStream", Ptr, pStream, A_PtrSize ? "UPtr*" : "UInt*", pBitmap)
	If (A_PtrSize)
		%FName%(pStream)
	Else
		DllCall(NumGet(NumGet(1*pStream)+8), "uint", pStream)
	return pBitmap
}
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Code only works on ANSI-32, narrowed down where the issue is but still stuck.

20 Nov 2019, 21:32

See more up-to-date versions of Gdip_All.ahk, where some of these problems are fixed. E.g.:
https://raw.githubusercontent.com/mmikeww/AHKv2-Gdip/master/Gdip_All.ahk
The data is ANSI, so you need to use StrGet with CP0. This has been done in the updated function.

For reference, here the DllCall types are fixed for the BRA.ahk link you posted:

Code: Select all

;https://github.com/tariqporter/Gdip/blob/master/BRA.ahk

;e.g. RtlMoveMemory:
;before:
		DllCall("RtlMoveMemory", "UInt", &BRAFromMemIn, "UInt", &NewHeader, "UInt", StrLen(NewHeader))
;after:
		DllCall("RtlMoveMemory", "Ptr", &BRAFromMemIn, "Ptr", &NewHeader, "UPtr", StrLen(NewHeader))

;the other 6 DllCall lines:
;before:
			h := DllCall("CreateFile", "Str", OutputFolder FileInfo1, "UInt", 0x40000000, "UInt", 0, "UInt", 0, "UInt", 4, "UInt", 0, "UInt", 0)
			result := DllCall("WriteFile", "UInt", h, "UInt", &BRAFromMemIn+Info2+FileInfo2, "UInt", FileInfo3, "UInt*", Written, "UInt", 0)
			h := DllCall("CloseHandle", "UInt", h)
	h := DllCall("CreateFile", "Str", Output, "UInt", 0x40000000, "UInt", 0, "UInt", 0, "UInt", 4, "UInt", 0, "UInt", 0)
	result := DllCall("WriteFile", "UInt", h, "UInt", &BRAFromMemIn, "UInt", Round(Info2)+Round(Info3), "UInt*", Written, "UInt", 0)
	h := DllCall("CloseHandle", "UInt", h)
;after:
			h := DllCall("CreateFile", "Str", OutputFolder FileInfo1, "UInt", 0x40000000, "UInt", 0, "Ptr", 0, "UInt", 4, "UInt", 0, "Ptr", 0, "Ptr")
			result := DllCall("WriteFile", "Ptr", h, "Ptr", &BRAFromMemIn+Info2+FileInfo2, "UInt", FileInfo3, "UInt*", Written, "Ptr", 0)
			h := DllCall("CloseHandle", "Ptr", h)
	h := DllCall("CreateFile", "Str", Output, "UInt", 0x40000000, "UInt", 0, "Ptr", 0, "UInt", 4, "UInt", 0, "Ptr", 0, "Ptr")
	result := DllCall("WriteFile", "Ptr", h, "Ptr", &BRAFromMemIn, "UInt", Round(Info2)+Round(Info3), "UInt*", Written, "Ptr", 0)
	h := DllCall("CloseHandle", "Ptr", h)
Cheers.
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: Bing [Bot], Google [Bot] and 319 guests