#NoEnv
; DllCall("LoadLibrary", "Str", "Gdiplus.dll") ; crash on exit if this is commented out
VarSetCapacity(GdiplusStartupInput, 12 + A_PtrSize, 0)
NumPut(1, GdiplusStartupInput, 0, "UInt")
DllCall("Gdiplus.dll\GdiplusStartup", "UPtr*", token, "Ptr", &GdiplusStartupInput, "Ptr", 0)
Esc::
DllCall("Gdiplus.dll\GdiplusShutdown", "UPtr", token) ; crash if loadlibrary wasnt used
ExitApp
why is it that calling GdiplusShutdown() without an explicit prior LoadLibrary() crashes my script? the dllcall should be managing loadlibrary/freelibrary internally, so why does it make a difference
As you say, dllcall calls FreeLibrary before returning. so your token is invalid. Using it is undefined behaviour, which might or might not cause a crash, or something else or nothing.
just me wrote:Longer story:
well put
Cheers.
Last edited by Helgef on 13 Feb 2019, 06:06, edited 1 time in total.
Some DLLs initialize memory and/or other resources for the calling process/thread when loaded or initialized by functions like GdiplusStartup(). The resources are used by subsequent function calls and stay valid until the DLL is freed/unloaded or 'uninitialized' (e.g. GdiplusShutdown()). If such a DLL is unloaded prematurely, your script may crash if you call other DLL functions afterwards.
so if i can manually load/unload gdiplus.dll however many times i want and GdiplusShutdown() succeeds provided the dll is loaded at the time of calling it, why is is then that the 2 naked Startup/Shutdown dllcalls back-to-back fail. #1 should be functionally equivalent to #3
furthermore, i dont think its an issue with feeding GdiplusShutdown() bogus tokens. Startup gives me tokens in the range 16850796 atm, and the following script ran without crashing:
if its not User32.dll, Kernel32.dll, ComCtl32.dll, Gdi32.dll -> LoadLibrary()
That is not entirely correct. You need to specify the path/name of the dll when it is not one of those, however, the dll might still be loaded. You can check if a dll needs to be loaded by calling GetModuleHandle.
Cheers.
As a side note, I have implemented a #LoadLibrary directive, to load dlls at load time, although I might redesign the implemenation, I didn't decide if I will make PR or not. Edit: I changed it and made a PR: #136.
Last edited by Helgef on 13 May 2019, 04:35, edited 1 time in total.
meaning, if u have User32.dll, for example, whose dependencies include, among others, powrprof.dll, that AHK will automatically load powrprof.dll by default, however if u wanted to use the functions from powrprof.dll, DllCall("powrprof.dll\whatever", ...) would still be required
You can check if a dll needs to be loaded by calling GetModuleHandle.
Even if a particular dll was loaded, you do not have any general guarantees that something, i.e., the program or some script lib you use, will not unload it, so you should probably load any dlls which you are unsure about.