Jump to content

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

Crazy Scripting : Resource-Only DLL for Dummies - 36L / v0.7


  • Please log in to reply
71 replies to this topic
Obi-Wahn
  • Members
  • 77 posts
  • Last active: Oct 29 2012 05:55 PM
  • Joined: 20 Apr 2006
Thanks for this Function SKAN.

While I was coding another script, I was wondering if it'd be possible to Save the Settings from the Script (compiled) into the script.

E.G.: When I'm exiting my compiled Script, the Window-Position and Size is stored to a .ini-File.
Could it be possible to write into the original Script?

Well, of course, its not as easy as I thought, because a first try with your funktion to add resources to the running script failed due to the lockdown of the RUNNING script by windows.
There was a .tmp-File in the Scriptdir, which can be renamed to .exe (ResHacker opens it and shows all resources added by your script) but when starting the .exe, it says "Exe corrupt". But windows shows the scripticon which I added during the compilation.

(compiled w/o upx)

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

I was wondering if it'd be possible to Save the Settings from the Script (compiled) into the script.


It is not possible to modify a running executable, so you will have to heavily workaround, which will not be worth the effort.

Okuu
  • Members
  • 44 posts
  • Last active: Mar 11 2011 05:30 PM
  • Joined: 22 Mar 2010
Does DllRead have a limit to file size?

I am trying to save resource pictures in my .dll as hex text, much like your cat example that I think is in another thread. However, when I call the .txt with the hex, it always returns a blank value. If I do the same thing with FileRead and no .dll it works fine though.

Code used is below

DllRead(Var, "Resource.dll", "Files", "picture.txt")

File size is 251,664 bytes. Input would be welcomed, hope you can get back to this sometime.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005
Is your text file saved in ANSI but you are DllRead()-ing it with AHK_L ? If that is the case, you need the following tip:

Note: To convert ANSI text to UNICODE, use: Var := StrGet( &Var, "" )


Unlike FileRead ( which automatically converts all data into Unicode ), DllRead() does not try to recognize the content and treats any data as binary.

Another alternative is to open and save your text file as unicode ( maybe in Notepad), prior to packing a DLL. But be aware that this method will double your data size.

Wicked - Guest
  • Guests
  • Last active:
  • Joined: --
SKAN, I've never been good with GDI+, but is there a way to get this to preserve the transparency? I packed a PNG into the DLL, used your method above for a JPG, but the background goes black.

Sorry if the answer to this question is simple, but I've never been good at this sort of thing. :p.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

I packed a PNG into the DLL, used your method above for a JPG, but the background goes black.


Can you provide me an image please.. I have been trying with various transparent PNGs, but unable to reproduce the said effect.

I'm on XP SP3.

Wicked
  • Members
  • 504 posts
  • Last active: Nov 18 2018 02:17 AM
  • Joined: 07 Jun 2008
Apologies for my late reply, SKAN.

The image I was using was <!-- m -->http://i.imgur.com/jRsu7.png<!-- m -->

Posted Image

After I extract it from the DLL, the background goes black. =/. I am also on XP SP3.

Thank you for your help. :D.

patchie
  • Members
  • 31 posts
  • Last active: May 08 2014 01:51 PM
  • Joined: 22 Feb 2008


DllRead( Var, "AHK.DLL","Files","BANNER.JPG" )

Gui, Add, Picture,w600 h150, %Var% ;This does not work =(


Gui, Add, Picture will accept only a filename and there is no built-in command in AHK to process image resources. :(

DllRead() just loads the file as is into a memory variable.
You need to process it and obtain a gdi bitmap before it can be applied in a picture control.

Sean showed us 'how to?' using GDI+ :
How to convert Image data (JPEG/PNG/GIF) to hBITMAP ?

The above topic can a bit tough for a newbie.. but read it anyway and then try the following script:

SetWorkingDir, %A_ScriptDir%
IfNotExist,ahk.dll
 urldownloadtofile,https://ahknet.autohotkey.com/~Skan/Scripts/RoD/ahk.dll, ahk.dll

GdiPlus( "[color=red]Startup[/color]" )
[color=darkred]nSize[/color] := DllRead( [color=darkred]Banner[/color], "AHK.DLL","Files","BANNER.JPG" )
[color=red]hBitmap[/color] := GdiPlus_hBitmapFromBuffer( [color=darkred]Banner[/color], [color=darkred]nSize[/color] )
GdiPlus( "[color=red]Shutdown[/color]" )
 
Gui, Add, Picture,x0 y0 w600 h150 hwnd[color=red]hPic 0x20E[/color]
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), [color=red]hBitmap[/color],, ahk_id %[color=red]hPic[/color]%

Gui, Show, w600 h400, ahk.dll\banner.jpg\0
OnExit, QuitScript
Return                                                 ; // end of auto-execute section //

GuiClose:
QuitScript:
 Gdi_DeleteObject( [color=red]hBitmap[/color] )
 OnExit
 ExitApp
Return


DllRead( ByRef Var, Filename, Section, Key ) {          ; Functionality and Parameters are
 VarSetCapacity( Var,64 ), VarSetCapacity( Var,0 )      ; identical to IniRead command ;-)
 If hMod := DllCall( "LoadLibrary", Str,Filename )
  If hRes := DllCall( "FindResource", UInt,hMod, Str,Key, Str,Section )
   If hData := DllCall( "LoadResource", UInt,hMod, UInt,hRes )
    If pData := DllCall( "LockResource", UInt,hData )
 Return VarSetCapacity( Var,nSize := DllCall( "SizeofResource", UInt,hMod, UInt,hRes ),32)
     , DllCall( "RtlMoveMemory", UInt,&Var, UInt,pData, UInt,nSize )
     , DllCall( "FreeLibrary", UInt,hMod )
Return DllCall( "FreeLibrary", UInt,hMod ) >> 32
}

;-----------------------------------------------------------------------------------------
;                                                        GDI and GDIPLUS Wrapper Functions
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

GdiPlus( Comm="Startup" ) {
 Static pToken, hMod
  If ( Comm="Startup" ) {
    If ! DllCall( "GetModuleHandle", Str,"gdiplus.dll" )
         hMod := DllCall( "LoadLibrary", Str,"gdiplus.dll" )
    DllCall( "LoadLibrary", Str,"gdiplus.dll" ), VarSetCapacity( si,16,0 ), NumPut( 1,si )
    Res := DllCall( "gdiplus\GdiplusStartup", UIntP,pToken, UInt,&si, UInt,0 )
  } Else {
  Res := DllCall( "gdiplus\GdiplusShutdown", UInt,pToken )
  If hMod
     DllCall( "FreeLibrary", UInt,hMod ),DllCall( "FreeLibrary", UInt,hMod ), hMod := 0
  }
Return ! Res
}

GdiPlus_hBitmapFromBuffer( ByRef Buffer, nSize, ByRef W="", ByRef H="" ) {
; Original code by Sean www.autohotkey.com/forum/viewtopic.php?p=147029#147029
  hData := DllCall("GlobalAlloc", UInt,2, UInt, nSize )
  pData := DllCall("GlobalLock",  UInt,hData )
  DllCall( "RtlMoveMemory", UInt,pData, UInt,&Buffer, UInt,nSize )
  DllCall( "GlobalUnlock", UInt,hData )
  DllCall( "ole32\CreateStreamOnHGlobal", UInt,hData, Int,True, UIntP,pStream )
  DllCall( "gdiplus\GdipCreateBitmapFromStream", UInt,pStream, UIntP,pBitmap )
  DllCall( "gdiplus\GdipCreateHBITMAPFromBitmap", UInt,pBitmap, UIntP,hBitmap, UInt,8 )
  DllCall( "gdiplus\GdipGetImageWidth" , UInt, pBitmap, UIntP,W )
  DllCall( "gdiplus\GdipGetImageHeight", UInt, pBitmap, UIntP,H )
  DllCall( "gdiplus\GdipDisposeImage", UInt,pBitmap )
  DllCall( NumGet( NumGet(1*pStream)+8 ), UInt,pStream ) ; IStream::Release ?!
Return hBitmap
}

Gdi_DeleteObject( hObj ) {
 Return !! DllCall( "GDI32\DeleteObject", UInt,hObj )
}


I have a .bmp image inside the DLL i wanna show in a gui, but i dont understand it all.

can somone explain this more for me?

my code is a bit shorter, but it works:

GdiPlus( "Startup" )
nSize := DllRead( Banner, "grafikk.DLL","Files","USB-2.bmp" )
hBitmap := GdiPlus_hBitmapFromBuffer( Banner, nSize )
GdiPlus( "Shutdown" )
 
Gui, Add, Picture,x0 y0 w600 h150 hwndhPic 0x20E
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %hPic%

Gui, Show, w600 h400, jajaj

Return                                                 ; // end of auto-execute section //

GuiClose:
 ExitApp
Return


DllRead( ByRef Var, Filename, Section, Key ) {          ; Functionality and Parameters are
 VarSetCapacity( Var,64 ), VarSetCapacity( Var,0 )      ; identical to IniRead command ;-)
 If hMod := DllCall( "LoadLibrary", Str,Filename )
  If hRes := DllCall( "FindResource", UInt,hMod, Str,Key, Str,Section )
   If hData := DllCall( "LoadResource", UInt,hMod, UInt,hRes )
    If pData := DllCall( "LockResource", UInt,hData )
 Return VarSetCapacity( Var,nSize := DllCall( "SizeofResource", UInt,hMod, UInt,hRes ),32)
     , DllCall( "RtlMoveMemory", UInt,&Var, UInt,pData, UInt,nSize )
     , DllCall( "FreeLibrary", UInt,hMod )
Return DllCall( "FreeLibrary", UInt,hMod ) >> 32
}

;-----------------------------------------------------------------------------------------
;                                                        GDI and GDIPLUS Wrapper Functions
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

GdiPlus( Comm="Startup" ) {
 Static pToken, hMod
  If ( Comm="Startup" ) {
    If ! DllCall( "GetModuleHandle", Str,"gdiplus.dll" )
         hMod := DllCall( "LoadLibrary", Str,"gdiplus.dll" )
    DllCall( "LoadLibrary", Str,"gdiplus.dll" ), VarSetCapacity( si,16,0 ), NumPut( 1,si )
    Res := DllCall( "gdiplus\GdiplusStartup", UIntP,pToken, UInt,&si, UInt,0 )
  } Else {
  Res := DllCall( "gdiplus\GdiplusShutdown", UInt,pToken )
  If hMod
     DllCall( "FreeLibrary", UInt,hMod ),DllCall( "FreeLibrary", UInt,hMod ), hMod := 0
  }
Return ! Res
}

GdiPlus_hBitmapFromBuffer( ByRef Buffer, nSize, ByRef W="", ByRef H="" ) {
; Original code by Sean www.autohotkey.com/forum/viewtopic.php?p=147029#147029
  hData := DllCall("GlobalAlloc", UInt,2, UInt, nSize )
  pData := DllCall("GlobalLock",  UInt,hData )
  DllCall( "RtlMoveMemory", UInt,pData, UInt,&Buffer, UInt,nSize )
  DllCall( "GlobalUnlock", UInt,hData )
  DllCall( "ole32\CreateStreamOnHGlobal", UInt,hData, Int,True, UIntP,pStream )
  DllCall( "gdiplus\GdipCreateBitmapFromStream", UInt,pStream, UIntP,pBitmap )
  DllCall( "gdiplus\GdipCreateHBITMAPFromBitmap", UInt,pBitmap, UIntP,hBitmap, UInt,8 )
  DllCall( "gdiplus\GdipGetImageWidth" , UInt, pBitmap, UIntP,W )
  DllCall( "gdiplus\GdipGetImageHeight", UInt, pBitmap, UIntP,H )
  DllCall( "gdiplus\GdipDisposeImage", UInt,pBitmap )
  DllCall( NumGet( NumGet(1*pStream)+8 ), UInt,pStream ) ; IStream::Release ?!
Return hBitmap
}

Gdi_DeleteObject( hObj ) {
 Return !! DllCall( "GDI32\DeleteObject", UInt,hObj )
}

Do i need all this code at the top? Can somone explain how i can have for example 2 images from the same dll file?

Thanks in advance :)
..:: Patchie ::..

Wicked
  • Members
  • 504 posts
  • Last active: Nov 18 2018 02:17 AM
  • Joined: 07 Jun 2008
SKAN (Or anyone else knowledgeable in this area), I'm using AHK_L and am having troubles. I can create an empty DLL, but I can not pack files into it (Not sure about reading yet, as I've not been able to pack them yet :p).

The resource files it is adding are all simple GIF images. I'm sure you'll point me to:

Var := StrGet( &Var, "" )

But I'm not sure where abouts to place that in the functions.

My apologies for taking your time.

3nL8f.png


SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

I'm using AHK_L and am having troubles. I can create an empty DLL, but I can not pack files into it


That is not enough info. What OS? Win 7 64bit?.

I tried the following in AHK_L 1.0.96.0 32b unicode

DllPackFiles( "C:\Program Files\AutoHotkey",        "variousfiles.dll", "Files" )
DllPackFiles( "F:\FDrive\Smiley Central Emoticons", "variousfiles.dll", "GIF"   )
and both folders get packed correctly (in the same dll).

Do you see any tmp files in the root folder?

If you are calling the function from a different script, then you should show me how you are calling it.
A mild file-lock on target 'resource dll' is enough for EndUpdateResource() to fail because EndUpdateResource() deletes the target file before it can write the updated content. If it cannot delete the target file, it writes a tmp file at the root of target folder.

For example:
I created a dll as C:\skan\res.dll and update some files in it.
I open it in PEINFO to view the structure
I call DllPackFiles() to pack an another folder.
Now - Since res.dll is open in PEINFO, EndUpdateResource() cannot delete it, so instead,
it will create the new copy of dll like c:\1234.tmp
AFAIK, there is no way to ascertain whether a target file is deletable, without actually deleting it.

Wicked
  • Members
  • 504 posts
  • Last active: Nov 18 2018 02:17 AM
  • Joined: 07 Jun 2008
I am running Windows XP SP3 -32b. AHK_L 1.1.00.00 32b Unicode.

I've put the following at the top of a script which only contains your functions:

DllPackFiles(A_MyDocuments "\Images", "Resource.dll")


Even if I use:

DllPackFiles(A_MyDocuments "\Images", "Resource.dll", "GIF")

Only an empty DLL is created.

A_MyDocuments "\Images" is full of 64 GIF images, no other type of files.

I don't have the DLL open in any other editing software.

I do not see any temp files, but the function is returning with the correct number of files (64).

Sry if I'm simply overlooking something. :(.

3nL8f.png


Wicked
  • Members
  • 504 posts
  • Last active: Nov 18 2018 02:17 AM
  • Joined: 07 Jun 2008
Got it to work!

I took out all but 10 GIF images, and it packed them properly. So I then took those 10 out, placed the next 10 in, and packed them into the same DLL. Repeated. It wouldn't do all 64 images at once, but did them 10 at a time. :).

Edit: Now when I try to read the DLL, it returns 0, and the ByRef parameter is just blank... >.<

nSize:=DllRead(PIMG, "Resource.dll", "FILES", "BLUE CORNER.GIF")
MsgBox, % nSize " - " PIMG

PIMG is blank, nSize is 0...
Posted Image

Could it possibly be due to just too many files, like the problem I had with the packing?

Thank you for your time, SKAN

3nL8f.png


SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

Could it possibly be due to just too many files, like the problem I had with the packing?


Definitely not.

DllPackFiles( "C:\Program Files\AutoHotkey",        "variousfiles.dll", "Files" )
DllPackFiles( "F:\FDrive\Smiley Central Emoticons", "variousfiles.dll", "GIF"   )

In above case, F:\FDrive\Smiley Central Emoticons\ has 645 animated gif files. Here is the Output file.

I simply do not understand where the glitch is, as I am not able to reproduce it.

Wicked
  • Members
  • 504 posts
  • Last active: Nov 18 2018 02:17 AM
  • Joined: 07 Jun 2008
I would happily allow you to TeamViewer or remote desktop my machine to see it for yourself, rather then trying to go by my uneducated explanations. :p. I'm terrible in the area of DLLCalls and such. >.< But at least through TV, you could see/edit the code and possibly work out why it's not working.

The file mine has created is here:
<!-- m -->https://ahknet.autoh...ed/Resource.dll<!-- m -->
See if you can read anything from it.

If you are interested, just let me know when.

3nL8f.png


SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

The file mine has created is here:
<!-- m -->https://ahknet.autoh...ed/Resource.dll<!-- m -->
See if you can read anything from it.


Rather, I would like exact copies of the source GIFs, that is, if you do not mind.
I should be able to reproduce the error.