Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RegistryKeyLookupFailed `CoderModulesPath' @ error/module.c/GetMagickModulePath/665 #4222

Closed
Zeus64 opened this issue Sep 14, 2021 · 9 comments

Comments

@Zeus64
Copy link

Zeus64 commented Sep 14, 2021

ImageMagick version

7.1.0-Q16

Operating system

Windows

Operating system, version and so on

10

Description

I updated ImageMagick-7.0.7-23 to 7.1.0-Q16 by replacing all binaries with the new one, but now when I launch my program I have: Project w3wp.exe raised exception class Exception with message 'RegistryKeyLookupFailed `CoderModulesPath' @ error/module.c/GetMagickModulePath/665'

Note:
*) I don't have any registry, at the launch of my app I do: setEnvironmentVariable(PChar('MAGICK_CODER_MODULE_PATH'), pChar(aImageMagickHome + '\modules\coders'))
*) I load CORE_RL_MagickWand_.dll in my app and I do not call any exe, I work only with wand api
*) Everything work perfectly with ImageMagick-7.0.7-23 binaries
*) Adding the registry keys fix the problem, but I can't use registry key for many reasons

What can explain such regression? when I compare the code of module.c (7.0.7-23 vs 7.1.0-Q16) their in no difference in it that can explain the problem as far as I can understand :( so where the problem can be?

Note: I wrote a wrapper of imagemagick wand api for all Delphi users: https://github.com/Zeus64/alcinoe and it's during the update of this wrapper that I faced the problem

Steps to Reproduce

on windows 10 :

1/ at the launch of the app do: setEnvironmentVariable('MAGICK_CODER_MODULE_PATH', xxx)
2/ load CORE_RL_MagickWand_.dll in the app, work only with wand api
3/ call MagickReadImage and receive the error RegistryKeyLookupFailed `CoderModulesPath' @ error/module.c/GetMagickModulePath/665

Images

No response

@snibgo
Copy link

snibgo commented Sep 14, 2021

Windows installations are usually done by downloading one of the *.exe installation programs from https://imagemagick.org/script/download.php#windows , and running it. The "portable" versions don't use the Windows registry.

If your old version was "portable", I expect you can replace it by simply deleting all the files and replacing them with the new ones.

If the new version is not "portable" then it will use the registry for its searches, and if you haven't done a proper installation, the registry entries will not be there.

@Zeus64
Copy link
Author

Zeus64 commented Sep 15, 2021

Portable version (windows) do not expose the CORE_RL_MagickWand_.dll that I use to access the wand API from my delphi App. I always use the windows version and I set at the startup of the app the environment variables via the windows api setEnvironmentVariable:

  • MAGICK_HOME
  • MAGICK_CONFIGURE_PATH
  • MAGICK_CODER_FILTER_PATH
  • MAGICK_CODER_MODULE_PATH

those environment variable overload the registry keys like you can see in the module.c :

static MagickBooleanType GetMagickModulePath(const char *filename,
  MagickModuleType module_type,char *path,ExceptionInfo *exception)
{
  char
    *module_path;

  assert(filename != (const char *) NULL);
  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
  assert(path != (char *) NULL);
  assert(exception != (ExceptionInfo *) NULL);
  if (strchr(filename,'/') != (char *) NULL)
    return(MagickFalse);
  (void) CopyMagickString(path,filename,MagickPathExtent);
  module_path=(char *) NULL;
  switch (module_type)
  {
    case MagickImageCoderModule:
    default:
    {
      (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
        "Searching for coder module file \"%s\" ...",filename);
      module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
#if defined(MAGICKCORE_CODER_PATH)
      if (module_path == (char *) NULL)
        module_path=AcquireString(MAGICKCORE_CODER_PATH);
#endif
      break;
    }
    case MagickImageFilterModule:
    {
      (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
        "Searching for filter module file \"%s\" ...",filename);
      module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
#if defined(MAGICKCORE_FILTER_PATH)
      if (module_path == (char *) NULL)
        module_path=AcquireString(MAGICKCORE_FILTER_PATH);
#endif
      break;
    }
  }
  if (module_path != (char *) NULL)
    {
      char
        *p,
        *q;

      for (p=module_path-1; p != (char *) NULL; )
      {
        (void) CopyMagickString(path,p+1,MagickPathExtent);
        q=strchr(path,DirectoryListSeparator);
        if (q != (char *) NULL)
          *q='\0';
        q=path+strlen(path)-1;
        if ((q >= path) && (*q != *DirectorySeparator))
          (void) ConcatenateMagickString(path,DirectorySeparator,
            MagickPathExtent);
        (void) ConcatenateMagickString(path,filename,MagickPathExtent);
#if defined(MAGICKCORE_HAVE_REALPATH)
        {
          char
            resolved_path[PATH_MAX+1];

          if (realpath(path,resolved_path) != (char *) NULL)
            (void) CopyMagickString(path,resolved_path,MagickPathExtent);
        }
#endif
        if (IsPathAccessible(path) != MagickFalse)
          {
            module_path=DestroyString(module_path);
            return(MagickTrue);
          }
        p=strchr(p+1,DirectoryListSeparator);
      }
      module_path=DestroyString(module_path);
    }
#if defined(MAGICKCORE_INSTALLED_SUPPORT)
  else
#if defined(MAGICKCORE_CODER_PATH)
    {
      const char
        *directory;

      /*
        Search hard coded paths.
      */
      switch (module_type)
      {
        case MagickImageCoderModule:
        default:
        {
          directory=MAGICKCORE_CODER_PATH;
          break;
        }
        case MagickImageFilterModule:
        {
          directory=MAGICKCORE_FILTER_PATH;
          break;
        }
      }
      (void) FormatLocaleString(path,MagickPathExtent,"%s%s",directory,
        filename);
      if (IsPathAccessible(path) == MagickFalse)
        {
          ThrowFileException(exception,ConfigureWarning,
            "UnableToOpenModuleFile",path);
          return(MagickFalse);
        }
      return(MagickTrue);
    }
#else
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
    {
      const char
        *registery_key;

      unsigned char
        *key_value;

      /*
        Locate path via registry key.
      */
      switch (module_type)
      {
        case MagickImageCoderModule:
        default:
        {
          registery_key="CoderModulesPath";
          break;
        }
        case MagickImageFilterModule:
        {
          registery_key="FilterModulesPath";
          break;
        }
      }
      key_value=NTRegistryKeyLookup(registery_key);
      if (key_value == (unsigned char *) NULL)
        {
          ThrowMagickException(exception,GetMagickModule(),ConfigureError,
            "RegistryKeyLookupFailed","'%s'",registery_key);
          return(MagickFalse);
        }
      (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",(char *)
        key_value,DirectorySeparator,filename);
      key_value=(unsigned char *) RelinquishMagickMemory(key_value);
      if (IsPathAccessible(path) == MagickFalse)
        {
          ThrowFileException(exception,ConfigureWarning,
            "UnableToOpenModuleFile",path);
          return(MagickFalse);
        }
      return(MagickTrue);
    }
#endif
#endif
#if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
# error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
#endif
#else
  {
    char
      *home;

    home=GetEnvironmentValue("MAGICK_HOME");
    if (home != (char *) NULL)
      {
        /*
          Search MAGICK_HOME.
        */
#if !defined(MAGICKCORE_POSIX_SUPPORT)
        (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",home,
          DirectorySeparator,filename);
#else
        const char
          *directory;

        switch (module_type)
        {
          case MagickImageCoderModule:
          default:
          {
            directory=MAGICKCORE_CODER_RELATIVE_PATH;
            break;
          }
          case MagickImageFilterModule:
          {
            directory=MAGICKCORE_FILTER_RELATIVE_PATH;
            break;
          }
        }
        (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s",home,
          directory,filename);
#endif
        home=DestroyString(home);
        if (IsPathAccessible(path) != MagickFalse)
          return(MagickTrue);
      }
  }
  if (*GetClientPath() != '\0')
    {
      /*
        Search based on executable directory.
      */
#if !defined(MAGICKCORE_POSIX_SUPPORT)
      (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",GetClientPath(),
        DirectorySeparator,filename);
#else
      char
        prefix[MagickPathExtent];

      const char
        *directory;

      switch (module_type)
      {
        case MagickImageCoderModule:
        default:
        {
          directory="coders";
          break;
        }
        case MagickImageFilterModule:
        {
          directory="filters";
          break;
        }
      }
      (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
      ChopPathComponents(prefix,1);
      (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s/%s",prefix,
        MAGICKCORE_MODULES_RELATIVE_PATH,directory,filename);
#endif
      if (IsPathAccessible(path) != MagickFalse)
        return(MagickTrue);
    }
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
  {
    /*
      Search module path.
    */
    if ((NTGetModulePath("CORE_RL_MagickCore_.dll",path) != MagickFalse) ||
        (NTGetModulePath("CORE_DB_MagickCore_.dll",path) != MagickFalse))
      {
        (void) ConcatenateMagickString(path,DirectorySeparator,
          MagickPathExtent);
        (void) ConcatenateMagickString(path,filename,MagickPathExtent);
        if (IsPathAccessible(path) != MagickFalse)
          return(MagickTrue);
      }
  }
#endif
  {
    char
      *home;

    home=GetEnvironmentValue("XDG_CONFIG_HOME");
    if (home == (char *) NULL)
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
      home=GetEnvironmentValue("LOCALAPPDATA");
    if (home == (char *) NULL)
      home=GetEnvironmentValue("APPDATA");
    if (home == (char *) NULL)
      home=GetEnvironmentValue("USERPROFILE");
#endif
    if (home != (char *) NULL)
      {
        /*
          Search $XDG_CONFIG_HOME/ImageMagick.
        */
        (void) FormatLocaleString(path,MagickPathExtent,"%s%sImageMagick%s%s",
          home,DirectorySeparator,DirectorySeparator,filename);
        home=DestroyString(home);
        if (IsPathAccessible(path) != MagickFalse)
          return(MagickTrue);
      }
    home=GetEnvironmentValue("HOME");
    if (home != (char *) NULL)
      {
        /*
          Search $HOME/.config/ImageMagick.
        */
        (void) FormatLocaleString(path,MagickPathExtent,
          "%s%s.config%sImageMagick%s%s",home,DirectorySeparator,
          DirectorySeparator,DirectorySeparator,filename);
        home=DestroyString(home);
        if (IsPathAccessible(path) != MagickFalse)
          return(MagickTrue);
      }
  }
  /*
    Search current directory.
  */
  if (IsPathAccessible(path) != MagickFalse)
    return(MagickTrue);
  if (exception->severity < ConfigureError)
    ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
      path);
#endif
  return(MagickFalse);
}

It's was working very well in previous version of imagemagick (at least in 7.0.7-23) but I don't understand why in 7.1.0 this not work anymore so their is clearly a regression somewhere

@Zeus64
Copy link
Author

Zeus64 commented Sep 15, 2021

I activated the log and i can see :

  <event>2021-09-15T10:16:58+00:00 0:05.233 0.094u 7.1.0 Module w3wp.exe[9564]: module.c/OpenModule/1273/Module
  Searching for module "JPEG" using filename "IM_MOD_RL_JPEG_.dll"</event>
  <event>2021-09-15T10:16:58+00:00 0:05.233 0.094u 7.1.0 Module w3wp.exe[9564]: module.c/GetMagickModulePath/546/Module
  Searching for coder module file "IM_MOD_RL_JPEG_.dll" ...</event>

that correspond to this line :

(void) LogMagickEvent(ModuleEvent,GetMagickModule(),
        "Searching for coder module file \"%s\" ...",filename);
      module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");

So i don't understand why GetEnvironmentValue("MAGICK_CODER_MODULE_PATH"); do no work anymore in 7.1.0

@Zeus64
Copy link
Author

Zeus64 commented Sep 15, 2021

Is their a place where I can get the install exe (ie: ImageMagick-7.0.8-22-Q16-x64-dll.zip) to know exactly at with version the regression appear ? I don't have visual studio so I can't compile the source code

As far as I understand, it's look like that now module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH") is not working anymore but I can't understand why :(

@snibgo
Copy link

snibgo commented Sep 15, 2021

Everything work perfectly with ImageMagick-7.0.7-23 binaries

Sorry, I don't know what has changed that might prevent "GetEnvironmentValue("MAGICK_CODER_MODULE_PATH")" from working.

I know nothing about Delphi.

@Zeus64
Copy link
Author

Zeus64 commented Sep 15, 2021

I work on it all the day, I confirm that now in 7.1.0 doing from the calling process

setEnvironmentVariable('MAGICK_CODER_MODULE_PATH', 'xxx')
following by a
Loadlibrary('CORE_RL_MagickWand_.dll')

is not working anymore because imagemagick, via the getEnv function, don't see the change made by setEnvironmentVariable('MAGICK_CODER_MODULE_PATH', 'xxx') :(
it's was working perfectly in 7.0.8-22

As getEnv is a quite generic function, I think the cause is maybe due because of a change of the compiler (vsstudio 2019?)

this quite big problem because now their is no way to deliver the c++ dll within the app :(

@snibgo
Copy link

snibgo commented Sep 15, 2021

What defines the function setEnvironmentVariable()? That function isn't part of IM, nor is it part of the GNU C library.

I suggest you test your build environment with trivial programs such as:

#include <MagickWand/MagickWand.h>

int main()
{
  MagickWandGenesis();

  setenv ("MYPATH", "myvalue", 1);

  printf ("MYPATH is %s\n", GetEnvironmentValue("MYPATH"));

  MagickWandTerminus();

  return 0;
}

@Zeus64
Copy link
Author

Zeus64 commented Sep 15, 2021

@Zeus64
Copy link
Author

Zeus64 commented Sep 16, 2021

a blank delphi app (in fact doesn"t matter it's delphi or something else) is loading at starting the msvcrt.dll (don't know why but it's like this) with take a cache of the environment variables, so when later I call setEnvironementVariable and later load a dll with use also msvcrt.dll and try to call getenv from this dll, then it's use the cache of msvcrt.dll and don't see the change I made just before via setEnvironementVariable, that a shame :( I I will try now to import from msvcrt.dll the _putenv and use it instead of setEnvironementVariable. don't understand why such ugly getenv exist :(

@Zeus64 Zeus64 closed this as completed Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants