Windows DllMain initialization broken (6.9.0-3)
Posted: 2015-01-13T16:54:32-07:00
If you use any of the ImageMagick dlls directly on windows (in my case through Magick++ but MagickWand will show the same issue) MagickCoreGenesis() will be called automatically in DllMain(). This is an issue for several reasons:
1. Since MagickCoreGenesis() is already called before any other code can run and subsequent calls are ignored there's no way to set the execution path.
2. The automatically supplied path in MagickCoreGenesis() is always INVALID. Combined with 1 this is a huge frustration if all you want to do is to distribute the ImageMagick dlls with an appliction.
The offending code is in nt-base.c, the marked part needs to be deleted. MagickCoreGenesis() actually needs a path with a filename, stripping the filename ensures the path will always be ignored.
In nt-base.c:
There is a second issue that also blocks the automatically supplied path from being valid. Absolute windows paths generally DO NOT start with a backslash. I assume someone tried to be clever and forgot that linux isn't the only OS on earth. Put the marked check in an ifdef so it's not checked on windows.
In magick.c:
These changes make ImageMagick usable in dll form on windows again. The DllMain() initialization on windows should probably be documented somewhere too.
1. Since MagickCoreGenesis() is already called before any other code can run and subsequent calls are ignored there's no way to set the execution path.
2. The automatically supplied path in MagickCoreGenesis() is always INVALID. Combined with 1 this is a huge frustration if all you want to do is to distribute the ImageMagick dlls with an appliction.
The offending code is in nt-base.c, the marked part needs to be deleted. MagickCoreGenesis() actually needs a path with a filename, stripping the filename ensures the path will always be ignored.
In nt-base.c:
Code: Select all
BOOL WINAPI DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved)
{
...
count=(ssize_t) GetModuleFileNameW(handle,wide_path,MaxTextExtent);
if (count != 0)
{
char
*path;
module_path=create_utf8_string(wide_path);
DELETE FROM HERE
for ( ; count > 0; count--)
if (module_path[count] == '\\')
{
module_path[count+1]='\0';
break;
}
DELETE TO HERE
MagickCoreGenesis(module_path,MagickFalse);
...
In magick.c:
Code: Select all
MagickExport void MagickCoreGenesis(const char *path,
const MagickBooleanType establish_signal_handlers)
{
...
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
NTWindowsGenesis();
#endif
/*
Set client name and execution path.
*/
(void) GetExecutionPath(execution_path,MaxTextExtent);
if ((path != (const char *) NULL) &&
ONLY USE IF NOT WINDOWS
(*path == *DirectorySeparator) &&
END ONLY USE IF NOT WINDOWS
(IsPathAccessible(path) != MagickFalse))
(void) CopyMagickString(execution_path,path,MaxTextExtent);
GetPathComponent(execution_path,TailPath,filename);
(void) SetClientName(filename);
GetPathComponent(execution_path,HeadPath,execution_path);
(void) SetClientPath(execution_path);
...