Page 1 of 1

weird script crash if LoadLibrary isnt used

Posted: 13 Feb 2019, 05:27
by swagfag

Code: Select all

#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

Faulting application name: AutoHotkeyU64.exe, version: 1.1.30.1
Faulting module name: Gdiplus.dll_unloaded, version: 10.0.17763.292
Exception code: 0xc0000005
Fault offset: 0x00000000000034f7
Faulting process id: 0x1ea0
Faulting application path: C:\Program Files\AutoHotkey\AutoHotkeyU64.exe
Faulting module path: Gdiplus.dll

Re: weird script crash if LoadLibrary isnt used  Topic is solved

Posted: 13 Feb 2019, 05:43
by Helgef
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 :thumbup:

Cheers.

Re: weird script crash if LoadLibrary isnt used

Posted: 13 Feb 2019, 06:04
by just me
Longer story:

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.

Re: weird script crash if LoadLibrary isnt used

Posted: 13 Feb 2019, 07:28
by swagfag
im not entirely convinced thats whats happening. consider these scripts:
#1 - emulated dllcall loadlibrary behavior
#2 - mix: emulated+native dllcall loadlib behavior
#3 - native dllcall loadlib behavior
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:

Code: Select all

#NoEnv
SetBatchLines -1

DllCall("LoadLibrary", "Str", "Gdiplus.dll", "Ptr")

Loop 100000000
	DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", A_Index)

MsgBox survived

Re: weird script crash if LoadLibrary isnt used

Posted: 13 Feb 2019, 07:49
by Helgef
helgef wrote:it is undefined behaviour, which might or might not cause a crash, or something else or nothing.
Btw, #2 doesn't crash for me on 32 build, but errorlevel shows 0xc0000005, that is, access violation, which is in line with just me's points.

Cheers

Re: weird script crash if LoadLibrary isnt used

Posted: 13 Feb 2019, 07:57
by swagfag
anyways, i guess undefined behavior's gonna do what undefined behavior's gonna do

ill just go ahead and file this under my dllcall gotchas:
  • if its not User32.dll, Kernel32.dll, ComCtl32.dll, Gdi32.dll -> LoadLibrary()

Re: weird script crash if LoadLibrary isnt used

Posted: 13 Feb 2019, 08:20
by Helgef
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.

Re: weird script crash if LoadLibrary isnt used

Posted: 12 May 2019, 10:52
by swagfag
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

is that right?

Re: weird script crash if LoadLibrary isnt used

Posted: 12 May 2019, 11:03
by Helgef
swagfag wrote: is that right?
Yes.
Helgef wrote:
13 Feb 2019, 08:20
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.

Cheers.

Re: weird script crash if LoadLibrary isnt used

Posted: 13 May 2019, 04:31
by swagfag
great, thanks
id green u twice if i could