]> granicus.if.org Git - imagemagick/blob - MagickCore/module.c
The -preview option is an image operator
[imagemagick] / MagickCore / module.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                  M   M   OOO   DDDD   U   U  L      EEEEE                   %
7 %                  MM MM  O   O  D   D  U   U  L      E                       %
8 %                  M M M  O   O  D   D  U   U  L      EEE                     %
9 %                  M   M  O   O  D   D  U   U  L      E                       %
10 %                  M   M   OOO   DDDD    UUU   LLLLL  EEEEE                   %
11 %                                                                             %
12 %                                                                             %
13 %                          MagickCore Module Methods                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                              Bob Friesenhahn                                %
17 %                                March 2000                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://www.imagemagick.org/script/license.php                           %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39 \f
40 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/coder.h"
46 #include "MagickCore/client.h"
47 #include "MagickCore/configure.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/linked-list.h"
52 #include "MagickCore/magic.h"
53 #include "MagickCore/magick.h"
54 #include "MagickCore/memory_.h"
55 #include "MagickCore/module.h"
56 #include "MagickCore/module-private.h"
57 #include "MagickCore/nt-base-private.h"
58 #include "MagickCore/policy.h"
59 #include "MagickCore/semaphore.h"
60 #include "MagickCore/splay-tree.h"
61 #include "MagickCore/static.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/string-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
67 #if defined(MAGICKCORE_MODULES_SUPPORT)
68 #if defined(MAGICKCORE_LTDL_DELEGATE)
69 #include "ltdl.h"
70 typedef lt_dlhandle ModuleHandle;
71 #else
72 typedef void *ModuleHandle;
73 #endif
74 \f
75 /*
76   Define declarations.
77 */
78 #if defined(MAGICKCORE_LTDL_DELEGATE)
79 #  define ModuleGlobExpression "*.la"
80 #else
81 #  if defined(_DEBUG)
82 #    define ModuleGlobExpression "IM_MOD_DB_*.dll"
83 #  else
84 #    define ModuleGlobExpression "IM_MOD_RL_*.dll"
85 #  endif
86 #endif
87 \f
88 /*
89   Global declarations.
90 */
91 static SemaphoreInfo
92   *module_semaphore = (SemaphoreInfo *) NULL;
93
94 static SplayTreeInfo
95   *module_list = (SplayTreeInfo *) NULL;
96 \f
97 /*
98   Forward declarations.
99 */
100 static const ModuleInfo
101   *RegisterModule(const ModuleInfo *,ExceptionInfo *);
102
103 static MagickBooleanType
104   GetMagickModulePath(const char *,MagickModuleType,char *,ExceptionInfo *),
105   IsModuleTreeInstantiated(),
106   UnregisterModule(const ModuleInfo *,ExceptionInfo *);
107
108 static void
109   TagToCoderModuleName(const char *,char *),
110   TagToFilterModuleName(const char *,char *),
111   TagToModuleName(const char *,const char *,char *);
112 \f
113 /*
114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 %                                                                             %
116 %                                                                             %
117 %                                                                             %
118 %   A c q u i r e M o d u l e I n f o                                         %
119 %                                                                             %
120 %                                                                             %
121 %                                                                             %
122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123 %
124 %  AcquireModuleInfo() allocates the ModuleInfo structure.
125 %
126 %  The format of the AcquireModuleInfo method is:
127 %
128 %      ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
129 %
130 %  A description of each parameter follows:
131 %
132 %    o path: the path associated with the tag.
133 %
134 %    o tag: a character string that represents the image format we are
135 %      looking for.
136 %
137 */
138 MagickExport ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
139 {
140   ModuleInfo
141     *module_info;
142
143   module_info=(ModuleInfo *) AcquireMagickMemory(sizeof(*module_info));
144   if (module_info == (ModuleInfo *) NULL)
145     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
146   (void) ResetMagickMemory(module_info,0,sizeof(*module_info));
147   if (path != (const char *) NULL)
148     module_info->path=ConstantString(path);
149   if (tag != (const char *) NULL)
150     module_info->tag=ConstantString(tag);
151   module_info->timestamp=time(0);
152   module_info->signature=MagickCoreSignature;
153   return(module_info);
154 }
155 \f
156 /*
157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 %                                                                             %
159 %                                                                             %
160 %                                                                             %
161 %   D e s t r o y M o d u l e L i s t                                         %
162 %                                                                             %
163 %                                                                             %
164 %                                                                             %
165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 %
167 %  DestroyModuleList() unregisters any previously loaded modules and exits
168 %  the module loaded environment.
169 %
170 %  The format of the DestroyModuleList module is:
171 %
172 %      void DestroyModuleList(void)
173 %
174 */
175 MagickExport void DestroyModuleList(void)
176 {
177   /*
178     Destroy magick modules.
179   */
180   LockSemaphoreInfo(module_semaphore);
181 #if defined(MAGICKCORE_MODULES_SUPPORT)
182   if (module_list != (SplayTreeInfo *) NULL)
183     module_list=DestroySplayTree(module_list);
184 #endif
185   UnlockSemaphoreInfo(module_semaphore);
186 }
187 \f
188 /*
189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 %                                                                             %
191 %                                                                             %
192 %                                                                             %
193 %   G e t M o d u l e I n f o                                                 %
194 %                                                                             %
195 %                                                                             %
196 %                                                                             %
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 %
199 %  GetModuleInfo() returns a pointer to a ModuleInfo structure that matches the
200 %  specified tag.  If tag is NULL, the head of the module list is returned. If
201 %  no modules are loaded, or the requested module is not found, NULL is
202 %  returned.
203 %
204 %  The format of the GetModuleInfo module is:
205 %
206 %      ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
207 %
208 %  A description of each parameter follows:
209 %
210 %    o tag: a character string that represents the image format we are
211 %      looking for.
212 %
213 %    o exception: return any errors or warnings in this structure.
214 %
215 */
216 MagickExport ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
217 {
218   ModuleInfo
219     *module_info;
220
221   if (IsModuleTreeInstantiated() == MagickFalse)
222     return((ModuleInfo *) NULL);
223   LockSemaphoreInfo(module_semaphore);
224   ResetSplayTreeIterator(module_list);
225   if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0))
226     {
227 #if defined(MAGICKCORE_MODULES_SUPPORT)
228       if (LocaleCompare(tag,"*") == 0)
229         (void) OpenModules(exception);
230 #endif
231       module_info=(ModuleInfo *) GetNextValueInSplayTree(module_list);
232       UnlockSemaphoreInfo(module_semaphore);
233       return(module_info);
234     }
235   module_info=(ModuleInfo *) GetValueFromSplayTree(module_list,tag);
236   UnlockSemaphoreInfo(module_semaphore);
237   return(module_info);
238 }
239 \f
240 /*
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %   G e t M o d u l e I n f o L i s t                                         %
246 %                                                                             %
247 %                                                                             %
248 %                                                                             %
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 %
251 %  GetModuleInfoList() returns any modules that match the specified pattern.
252 %
253 %  The format of the GetModuleInfoList function is:
254 %
255 %      const ModuleInfo **GetModuleInfoList(const char *pattern,
256 %        size_t *number_modules,ExceptionInfo *exception)
257 %
258 %  A description of each parameter follows:
259 %
260 %    o pattern: Specifies a pointer to a text string containing a pattern.
261 %
262 %    o number_modules:  This integer returns the number of modules in the list.
263 %
264 %    o exception: return any errors or warnings in this structure.
265 %
266 */
267
268 #if defined(__cplusplus) || defined(c_plusplus)
269 extern "C" {
270 #endif
271
272 static int ModuleInfoCompare(const void *x,const void *y)
273 {
274   const ModuleInfo
275     **p,
276     **q;
277
278   p=(const ModuleInfo **) x,
279   q=(const ModuleInfo **) y;
280   if (LocaleCompare((*p)->path,(*q)->path) == 0)
281     return(LocaleCompare((*p)->tag,(*q)->tag));
282   return(LocaleCompare((*p)->path,(*q)->path));
283 }
284
285 #if defined(__cplusplus) || defined(c_plusplus)
286 }
287 #endif
288
289 MagickExport const ModuleInfo **GetModuleInfoList(const char *pattern,
290   size_t *number_modules,ExceptionInfo *exception)
291 {
292   const ModuleInfo
293     **modules;
294
295   register const ModuleInfo
296     *p;
297
298   register ssize_t
299     i;
300
301   /*
302     Allocate module list.
303   */
304   assert(pattern != (char *) NULL);
305   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
306   assert(number_modules != (size_t *) NULL);
307   *number_modules=0;
308   p=GetModuleInfo("*",exception);
309   if (p == (const ModuleInfo *) NULL)
310     return((const ModuleInfo **) NULL);
311   modules=(const ModuleInfo **) AcquireQuantumMemory((size_t)
312     GetNumberOfNodesInSplayTree(module_list)+1UL,sizeof(*modules));
313   if (modules == (const ModuleInfo **) NULL)
314     return((const ModuleInfo **) NULL);
315   /*
316     Generate module list.
317   */
318   LockSemaphoreInfo(module_semaphore);
319   ResetSplayTreeIterator(module_list);
320   p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
321   for (i=0; p != (const ModuleInfo *) NULL; )
322   {
323     if ((p->stealth == MagickFalse) &&
324         (GlobExpression(p->tag,pattern,MagickFalse) != MagickFalse))
325       modules[i++]=p;
326     p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
327   }
328   UnlockSemaphoreInfo(module_semaphore);
329   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleInfoCompare);
330   modules[i]=(ModuleInfo *) NULL;
331   *number_modules=(size_t) i;
332   return(modules);
333 }
334 \f
335 /*
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %                                                                             %
338 %                                                                             %
339 %                                                                             %
340 %   G e t M o d u l e L i s t                                                 %
341 %                                                                             %
342 %                                                                             %
343 %                                                                             %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 %
346 %  GetModuleList() returns any image format modules that match the specified
347 %  pattern.
348 %
349 %  The format of the GetModuleList function is:
350 %
351 %      char **GetModuleList(const char *pattern,const MagickModuleType type,
352 %        size_t *number_modules,ExceptionInfo *exception)
353 %
354 %  A description of each parameter follows:
355 %
356 %    o pattern: Specifies a pointer to a text string containing a pattern.
357 %
358 %    o type: choose from MagickImageCoderModule or MagickImageFilterModule.
359 %
360 %    o number_modules:  This integer returns the number of modules in the
361 %      list.
362 %
363 %    o exception: return any errors or warnings in this structure.
364 %
365 */
366
367 #if defined(__cplusplus) || defined(c_plusplus)
368 extern "C" {
369 #endif
370
371 static int ModuleCompare(const void *x,const void *y)
372 {
373   register const char
374     **p,
375     **q;
376
377    p=(const char **) x;
378   q=(const char **) y;
379   return(LocaleCompare(*p,*q));
380 }
381
382 #if defined(__cplusplus) || defined(c_plusplus)
383 }
384 #endif
385
386 MagickExport char **GetModuleList(const char *pattern,
387   const MagickModuleType type,size_t *number_modules,ExceptionInfo *exception)
388 {
389 #define MaxModules  511
390
391   char
392     **modules,
393     filename[MagickPathExtent],
394     module_path[MagickPathExtent],
395     path[MagickPathExtent];
396
397   DIR
398     *directory;
399
400   MagickBooleanType
401     status;
402
403   register ssize_t
404     i;
405
406   size_t
407     max_entries;
408
409   struct dirent
410     *buffer,
411     *entry;
412
413   /*
414     Locate all modules in the image coder or filter path.
415   */
416   switch (type)
417   {
418     case MagickImageCoderModule:
419     default:
420     {
421       TagToCoderModuleName("magick",filename);
422       status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
423         exception);
424       break;
425     }
426     case MagickImageFilterModule:
427     {
428       TagToFilterModuleName("analyze",filename);
429       status=GetMagickModulePath(filename,MagickImageFilterModule,module_path,
430         exception);
431       break;
432     }
433   }
434   if (status == MagickFalse)
435     return((char **) NULL);
436   GetPathComponent(module_path,HeadPath,path);
437   max_entries=MaxModules;
438   modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
439     sizeof(*modules));
440   if (modules == (char **) NULL)
441     return((char **) NULL);
442   *modules=(char *) NULL;
443   directory=opendir(path);
444   if (directory == (DIR *) NULL)
445     {
446       modules=(char **) RelinquishMagickMemory(modules);
447       return((char **) NULL);
448     }
449   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
450   if (buffer == (struct dirent *) NULL)
451     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
452   i=0;
453   while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
454          (entry != (struct dirent *) NULL))
455   {
456     status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
457     if (status == MagickFalse)
458       continue;
459     if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
460       continue;
461     if (i >= (ssize_t) max_entries)
462       {
463         modules=(char **) NULL;
464         if (~max_entries > max_entries)
465           modules=(char **) ResizeQuantumMemory(modules,(size_t)
466             (max_entries << 1),sizeof(*modules));
467         max_entries<<=1;
468         if (modules == (char **) NULL)
469           break;
470       }
471     /*
472       Add new module name to list.
473     */
474     modules[i]=AcquireString((char *) NULL);
475     GetPathComponent(entry->d_name,BasePath,modules[i]);
476     if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
477       {
478         (void) CopyMagickString(modules[i],modules[i]+10,MagickPathExtent);
479         modules[i][strlen(modules[i])-1]='\0';
480       }
481     i++;
482   }
483   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
484   (void) closedir(directory);
485   if (modules == (char **) NULL)
486     {
487       (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
488         "MemoryAllocationFailed","`%s'",pattern);
489       return((char **) NULL);
490     }
491   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
492   modules[i]=(char *) NULL;
493   *number_modules=(size_t) i;
494   return(modules);
495 }
496 \f
497 /*
498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
499 %                                                                             %
500 %                                                                             %
501 %                                                                             %
502 %  G e t M a g i c k M o d u l e P a t h                                      %
503 %                                                                             %
504 %                                                                             %
505 %                                                                             %
506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 %
508 %  GetMagickModulePath() finds a module with the specified module type and
509 %  filename.
510 %
511 %  The format of the GetMagickModulePath module is:
512 %
513 %      MagickBooleanType GetMagickModulePath(const char *filename,
514 %        MagickModuleType module_type,char *path,ExceptionInfo *exception)
515 %
516 %  A description of each parameter follows:
517 %
518 %    o filename: the module file name.
519 %
520 %    o module_type: the module type: MagickImageCoderModule or
521 %      MagickImageFilterModule.
522 %
523 %    o path: the path associated with the filename.
524 %
525 %    o exception: return any errors or warnings in this structure.
526 %
527 */
528 static MagickBooleanType GetMagickModulePath(const char *filename,
529   MagickModuleType module_type,char *path,ExceptionInfo *exception)
530 {
531   char
532     *module_path;
533
534   assert(filename != (const char *) NULL);
535   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
536   assert(path != (char *) NULL);
537   assert(exception != (ExceptionInfo *) NULL);
538   if (strchr(filename,'/') != (char *) NULL)
539     return(MagickFalse);
540   (void) CopyMagickString(path,filename,MagickPathExtent);
541   module_path=(char *) NULL;
542   switch (module_type)
543   {
544     case MagickImageCoderModule:
545     default:
546     {
547       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
548         "Searching for coder module file \"%s\" ...",filename);
549       module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
550 #if defined(MAGICKCORE_CODER_PATH)
551       if (module_path == (char *) NULL)
552         module_path=AcquireString(MAGICKCORE_CODER_PATH);
553 #endif
554       break;
555     }
556     case MagickImageFilterModule:
557     {
558       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
559         "Searching for filter module file \"%s\" ...",filename);
560       module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
561 #if defined(MAGICKCORE_FILTER_PATH)
562       if (module_path == (char *) NULL)
563         module_path=AcquireString(MAGICKCORE_FILTER_PATH);
564 #endif
565       break;
566     }
567   }
568   if (module_path != (char *) NULL)
569     {
570       register char
571         *p,
572         *q;
573
574       for (p=module_path-1; p != (char *) NULL; )
575       {
576         (void) CopyMagickString(path,p+1,MagickPathExtent);
577         q=strchr(path,DirectoryListSeparator);
578         if (q != (char *) NULL)
579           *q='\0';
580         q=path+strlen(path)-1;
581         if ((q >= path) && (*q != *DirectorySeparator))
582           (void) ConcatenateMagickString(path,DirectorySeparator,
583             MagickPathExtent);
584         (void) ConcatenateMagickString(path,filename,MagickPathExtent);
585         if (IsPathAccessible(path) != MagickFalse)
586           {
587             module_path=DestroyString(module_path);
588             return(MagickTrue);
589           }
590         p=strchr(p+1,DirectoryListSeparator);
591       }
592       module_path=DestroyString(module_path);
593     }
594 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
595   else
596 #if defined(MAGICKCORE_CODER_PATH)
597     {
598       const char
599         *directory;
600
601       /*
602         Search hard coded paths.
603       */
604       switch (module_type)
605       {
606         case MagickImageCoderModule:
607         default:
608         {
609           directory=MAGICKCORE_CODER_PATH;
610           break;
611         }
612         case MagickImageFilterModule:
613         {
614           directory=MAGICKCORE_FILTER_PATH;
615           break;
616         }
617       }
618       (void) FormatLocaleString(path,MagickPathExtent,"%s%s",directory,
619         filename);
620       if (IsPathAccessible(path) == MagickFalse)
621         {
622           ThrowFileException(exception,ConfigureWarning,
623             "UnableToOpenModuleFile",path);
624           return(MagickFalse);
625         }
626       return(MagickTrue);
627     }
628 #else
629 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
630     {
631       const char
632         *registery_key;
633
634       unsigned char
635         *key_value;
636
637       /*
638         Locate path via registry key.
639       */
640       switch (module_type)
641       {
642         case MagickImageCoderModule:
643         default:
644         {
645           registery_key="CoderModulesPath";
646           break;
647         }
648         case MagickImageFilterModule:
649         {
650           registery_key="FilterModulesPath";
651           break;
652         }
653       }
654       key_value=NTRegistryKeyLookup(registery_key);
655       if (key_value == (unsigned char *) NULL)
656         {
657           ThrowMagickException(exception,GetMagickModule(),ConfigureError,
658             "RegistryKeyLookupFailed","`%s'",registery_key);
659           return(MagickFalse);
660         }
661       (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",(char *)
662         key_value,DirectorySeparator,filename);
663       key_value=(unsigned char *) RelinquishMagickMemory(key_value);
664       if (IsPathAccessible(path) == MagickFalse)
665         {
666           ThrowFileException(exception,ConfigureWarning,
667             "UnableToOpenModuleFile",path);
668           return(MagickFalse);
669         }
670       return(MagickTrue);
671     }
672 #endif
673 #endif
674 #if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
675 # error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
676 #endif
677 #else
678   {
679     char
680       *home;
681
682     home=GetEnvironmentValue("MAGICK_HOME");
683     if (home != (char *) NULL)
684       {
685         /*
686           Search MAGICK_HOME.
687         */
688 #if !defined(MAGICKCORE_POSIX_SUPPORT)
689         (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",home,
690           DirectorySeparator,filename);
691 #else
692         const char
693           *directory;
694
695         switch (module_type)
696         {
697           case MagickImageCoderModule:
698           default:
699           {
700             directory=MAGICKCORE_CODER_RELATIVE_PATH;
701             break;
702           }
703           case MagickImageFilterModule:
704           {
705             directory=MAGICKCORE_FILTER_RELATIVE_PATH;
706             break;
707           }
708         }
709         (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s",home,
710           directory,filename);
711 #endif
712         home=DestroyString(home);
713         if (IsPathAccessible(path) != MagickFalse)
714           return(MagickTrue);
715       }
716   }
717   if (*GetClientPath() != '\0')
718     {
719       /*
720         Search based on executable directory.
721       */
722 #if !defined(MAGICKCORE_POSIX_SUPPORT)
723       (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",GetClientPath(),
724         DirectorySeparator,filename);
725 #else
726       char
727         prefix[MagickPathExtent];
728
729       const char
730         *directory;
731
732       switch (module_type)
733       {
734         case MagickImageCoderModule:
735         default:
736         {
737           directory="coders";
738           break;
739         }
740         case MagickImageFilterModule:
741         {
742           directory="filters";
743           break;
744         }
745       }
746       (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
747       ChopPathComponents(prefix,1);
748       (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s/%s",prefix,
749         MAGICKCORE_MODULES_RELATIVE_PATH,directory,filename);
750 #endif
751       if (IsPathAccessible(path) != MagickFalse)
752         return(MagickTrue);
753     }
754 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
755   {
756     /*
757       Search module path.
758     */
759     if ((NTGetModulePath("CORE_RL_MagickCore_.dll",path) != MagickFalse) ||
760         (NTGetModulePath("CORE_DB_MagickCore_.dll",path) != MagickFalse))
761       {
762         (void) ConcatenateMagickString(path,DirectorySeparator,
763           MagickPathExtent);
764         (void) ConcatenateMagickString(path,filename,MagickPathExtent);
765         if (IsPathAccessible(path) != MagickFalse)
766           return(MagickTrue);
767       }
768   }
769 #endif
770   {
771     char
772       *home;
773
774     home=GetEnvironmentValue("XDG_CONFIG_HOME");
775     if (home == (char *) NULL)
776       home=GetEnvironmentValue("LOCALAPPDATA");
777     if (home == (char *) NULL)
778       home=GetEnvironmentValue("APPDATA");
779     if (home == (char *) NULL)
780       home=GetEnvironmentValue("USERPROFILE");
781     if (home != (char *) NULL)
782       {
783         /*
784           Search $XDG_CONFIG_HOME/ImageMagick.
785         */
786         (void) FormatLocaleString(path,MagickPathExtent,"%s%sImageMagick%s%s",
787           home,DirectorySeparator,DirectorySeparator,filename);
788         home=DestroyString(home);
789         if (IsPathAccessible(path) != MagickFalse)
790           return(MagickTrue);
791       }
792     home=GetEnvironmentValue("HOME");
793     if (home != (char *) NULL)
794       {
795         /*
796           Search $HOME/.config/ImageMagick.
797         */
798         (void) FormatLocaleString(path,MagickPathExtent,
799           "%s%s.config%sImageMagick%s%s",home,DirectorySeparator,
800           DirectorySeparator,DirectorySeparator,filename);
801         home=DestroyString(home);
802         if (IsPathAccessible(path) != MagickFalse)
803           return(MagickTrue);
804       }
805   }
806   /*
807     Search current directory.
808   */
809   if (IsPathAccessible(path) != MagickFalse)
810     return(MagickTrue);
811   if (exception->severity < ConfigureError)
812     ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
813       path);
814 #endif
815   return(MagickFalse);
816 }
817 \f
818 /*
819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
820 %                                                                             %
821 %                                                                             %
822 %                                                                             %
823 %   I s M o d u l e T r e e I n s t a n t i a t e d                           %
824 %                                                                             %
825 %                                                                             %
826 %                                                                             %
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828 %
829 %  IsModuleTreeInstantiated() determines if the module tree is instantiated.
830 %  If not, it instantiates the tree and returns it.
831 %
832 %  The format of the IsModuleTreeInstantiated() method is:
833 %
834 %      IsModuleTreeInstantiated()
835 %
836 */
837
838 static void *DestroyModuleNode(void *module_info)
839 {
840   ExceptionInfo
841     *exception;
842
843   register ModuleInfo
844     *p;
845
846   exception=AcquireExceptionInfo();
847   p=(ModuleInfo *) module_info;
848   if (UnregisterModule(p,exception) == MagickFalse)
849     CatchException(exception);
850   if (p->tag != (char *) NULL)
851     p->tag=DestroyString(p->tag);
852   if (p->path != (char *) NULL)
853     p->path=DestroyString(p->path);
854   exception=DestroyExceptionInfo(exception);
855   return(RelinquishMagickMemory(p));
856 }
857
858 static MagickBooleanType IsModuleTreeInstantiated()
859 {
860   if (module_list == (SplayTreeInfo *) NULL)
861     {
862       if (module_semaphore == (SemaphoreInfo *) NULL)
863         ActivateSemaphoreInfo(&module_semaphore);
864       LockSemaphoreInfo(module_semaphore);
865       if (module_list == (SplayTreeInfo *) NULL)
866         {
867           MagickBooleanType
868             status;
869
870           ModuleInfo
871             *module_info;
872
873           module_list=NewSplayTree(CompareSplayTreeString,
874             (void *(*)(void *)) NULL,DestroyModuleNode);
875           if (module_list == (SplayTreeInfo *) NULL)
876             ThrowFatalException(ResourceLimitFatalError,
877               "MemoryAllocationFailed");
878           module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
879           module_info->stealth=MagickTrue;
880           status=AddValueToSplayTree(module_list,module_info->tag,module_info);
881           if (status == MagickFalse)
882             ThrowFatalException(ResourceLimitFatalError,
883               "MemoryAllocationFailed");
884           if (lt_dlinit() != 0)
885             ThrowFatalException(ModuleFatalError,
886               "UnableToInitializeModuleLoader");
887         }
888       UnlockSemaphoreInfo(module_semaphore);
889     }
890   return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
891 }
892 \f
893 /*
894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895 %                                                                             %
896 %                                                                             %
897 %                                                                             %
898 %   I n v o k e D y n a m i c I m a g e F i l t e r                           %
899 %                                                                             %
900 %                                                                             %
901 %                                                                             %
902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903 %
904 %  InvokeDynamicImageFilter() invokes a dynamic image filter.
905 %
906 %  The format of the InvokeDynamicImageFilter module is:
907 %
908 %      MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
909 %        const int argc,const char **argv,ExceptionInfo *exception)
910 %
911 %  A description of each parameter follows:
912 %
913 %    o tag: a character string that represents the name of the particular
914 %      module.
915 %
916 %    o image: the image.
917 %
918 %    o argc: a pointer to an integer describing the number of elements in the
919 %      argument vector.
920 %
921 %    o argv: a pointer to a text array containing the command line arguments.
922 %
923 %    o exception: return any errors or warnings in this structure.
924 %
925 */
926 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
927   Image **images,const int argc,const char **argv,ExceptionInfo *exception)
928 {
929   char
930     name[MagickPathExtent],
931     path[MagickPathExtent];
932
933   ImageFilterHandler
934     *image_filter;
935
936   MagickBooleanType
937     status;
938
939   ModuleHandle
940     handle;
941
942   PolicyRights
943     rights;
944
945   /*
946     Find the module.
947   */
948   assert(images != (Image **) NULL);
949   assert((*images)->signature == MagickCoreSignature);
950   if ((*images)->debug != MagickFalse)
951     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
952       (*images)->filename);
953 #if !defined(MAGICKCORE_BUILD_MODULES)
954   {
955     MagickBooleanType
956       status;
957
958     status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
959     if (status != MagickFalse)
960       return(status);
961   }
962 #endif
963   rights=ReadPolicyRights;
964   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
965     {
966       errno=EPERM;
967       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
968         "NotAuthorized","`%s'",tag);
969       return(MagickFalse);
970     }
971   TagToFilterModuleName(tag,name);
972   status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
973   if (status == MagickFalse)
974     {
975       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
976         "UnableToLoadModule","'%s': %s",name,path);
977       return(MagickFalse);
978     }
979   /*
980     Open the module.
981   */
982   handle=(ModuleHandle) lt_dlopen(path);
983   if (handle == (ModuleHandle) NULL)
984     {
985       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
986         "UnableToLoadModule","'%s': %s",name,lt_dlerror());
987       return(MagickFalse);
988     }
989   /*
990     Locate the module.
991   */
992 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
993   (void) FormatLocaleString(name,MagickPathExtent,"%sImage",tag);
994 #else
995   (void) FormatLocaleString(name,MagickPathExtent,"%s%sImage",
996     MAGICKCORE_NAMESPACE_PREFIX,tag);
997 #endif
998   /*
999     Execute the module.
1000   */
1001   ClearMagickException(exception);
1002   image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
1003   if (image_filter == (ImageFilterHandler *) NULL)
1004     (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1005       "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1006   else
1007     {
1008       size_t
1009         signature;
1010
1011       if ((*images)->debug != MagickFalse)
1012         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1013           "Invoking \"%s\" dynamic image filter",tag);
1014       signature=image_filter(images,argc,argv,exception);
1015       if ((*images)->debug != MagickFalse)
1016         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1017           tag);
1018       if (signature != MagickImageFilterSignature)
1019         (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1020           "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1021           (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
1022     }
1023   /*
1024     Close the module.
1025   */
1026   if (lt_dlclose(handle) != 0)
1027     (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1028       "UnableToCloseModule","'%s': %s",name,lt_dlerror());
1029   return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
1030 }
1031 \f
1032 /*
1033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 %                                                                             %
1035 %                                                                             %
1036 %                                                                             %
1037 %  L i s t M o d u l e I n f o                                                %
1038 %                                                                             %
1039 %                                                                             %
1040 %                                                                             %
1041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1042 %
1043 %  ListModuleInfo() lists the module info to a file.
1044 %
1045 %  The format of the ListModuleInfo module is:
1046 %
1047 %      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1048 %
1049 %  A description of each parameter follows.
1050 %
1051 %    o file:  An pointer to a FILE.
1052 %
1053 %    o exception: return any errors or warnings in this structure.
1054 %
1055 */
1056 MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1057   ExceptionInfo *exception)
1058 {
1059   char
1060     filename[MagickPathExtent],
1061     module_path[MagickPathExtent],
1062     **modules,
1063     path[MagickPathExtent];
1064
1065   register ssize_t
1066     i;
1067
1068   size_t
1069     number_modules;
1070
1071   if (file == (const FILE *) NULL)
1072     file=stdout;
1073   /*
1074     List image coders.
1075   */
1076   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1077   if (modules == (char **) NULL)
1078     return(MagickFalse);
1079   TagToCoderModuleName("magick",filename);
1080   (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
1081     exception);
1082   GetPathComponent(module_path,HeadPath,path);
1083   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1084   (void) FormatLocaleFile(file,"Image Coder\n");
1085   (void) FormatLocaleFile(file,
1086     "-------------------------------------------------"
1087     "------------------------------\n");
1088   for (i=0; i < (ssize_t) number_modules; i++)
1089   {
1090     (void) FormatLocaleFile(file,"%s",modules[i]);
1091     (void) FormatLocaleFile(file,"\n");
1092   }
1093   (void) fflush(file);
1094   /*
1095     Relinquish resources.
1096   */
1097   for (i=0; i < (ssize_t) number_modules; i++)
1098     modules[i]=DestroyString(modules[i]);
1099   modules=(char **) RelinquishMagickMemory(modules);
1100   /*
1101     List image filters.
1102   */
1103   modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
1104   if (modules == (char **) NULL)
1105     return(MagickFalse);
1106   TagToFilterModuleName("analyze",filename);
1107   (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
1108     exception);
1109   GetPathComponent(module_path,HeadPath,path);
1110   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1111   (void) FormatLocaleFile(file,"Image Filter\n");
1112   (void) FormatLocaleFile(file,
1113     "-------------------------------------------------"
1114     "------------------------------\n");
1115   for (i=0; i < (ssize_t) number_modules; i++)
1116   {
1117     (void) FormatLocaleFile(file,"%s",modules[i]);
1118     (void) FormatLocaleFile(file,"\n");
1119   }
1120   (void) fflush(file);
1121   /*
1122     Relinquish resources.
1123   */
1124   for (i=0; i < (ssize_t) number_modules; i++)
1125     modules[i]=DestroyString(modules[i]);
1126   modules=(char **) RelinquishMagickMemory(modules);
1127   return(MagickTrue);
1128 }
1129 \f
1130 /*
1131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132 %                                                                             %
1133 %                                                                             %
1134 %                                                                             %
1135 +   M o d u l e C o m p o n e n t G e n e s i s                               %
1136 %                                                                             %
1137 %                                                                             %
1138 %                                                                             %
1139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1140 %
1141 %  ModuleComponentGenesis() instantiates the module component.
1142 %
1143 %  The format of the ModuleComponentGenesis method is:
1144 %
1145 %      MagickBooleanType ModuleComponentGenesis(void)
1146 %
1147 */
1148 MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
1149 {
1150   MagickBooleanType
1151     status;
1152
1153   if (module_semaphore == (SemaphoreInfo *) NULL)
1154     module_semaphore=AcquireSemaphoreInfo();
1155   status=IsModuleTreeInstantiated();
1156   return(status);
1157 }
1158 \f
1159 /*
1160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1161 %                                                                             %
1162 %                                                                             %
1163 %                                                                             %
1164 +   M o d u l e C o m p o n e n t T e r m i n u s                             %
1165 %                                                                             %
1166 %                                                                             %
1167 %                                                                             %
1168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1169 %
1170 %  ModuleComponentTerminus() destroys the module component.
1171 %
1172 %  The format of the ModuleComponentTerminus method is:
1173 %
1174 %      ModuleComponentTerminus(void)
1175 %
1176 */
1177 MagickPrivate void ModuleComponentTerminus(void)
1178 {
1179   if (module_semaphore == (SemaphoreInfo *) NULL)
1180     ActivateSemaphoreInfo(&module_semaphore);
1181   DestroyModuleList();
1182   RelinquishSemaphoreInfo(&module_semaphore);
1183 }
1184 \f
1185 /*
1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187 %                                                                             %
1188 %                                                                             %
1189 %                                                                             %
1190 %   O p e n M o d u l e                                                       %
1191 %                                                                             %
1192 %                                                                             %
1193 %                                                                             %
1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195 %
1196 %  OpenModule() loads a module, and invokes its registration module.  It
1197 %  returns MagickTrue on success, and MagickFalse if there is an error.
1198 %
1199 %  The format of the OpenModule module is:
1200 %
1201 %      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1202 %
1203 %  A description of each parameter follows:
1204 %
1205 %    o module: a character string that indicates the module to load.
1206 %
1207 %    o exception: return any errors or warnings in this structure.
1208 %
1209 */
1210 MagickPrivate MagickBooleanType OpenModule(const char *module,
1211   ExceptionInfo *exception)
1212 {
1213   char
1214     filename[MagickPathExtent],
1215     module_name[MagickPathExtent],
1216     name[MagickPathExtent],
1217     path[MagickPathExtent];
1218
1219   MagickBooleanType
1220     status;
1221
1222   ModuleHandle
1223     handle;
1224
1225   ModuleInfo
1226     *module_info;
1227
1228   register const CoderInfo
1229     *p;
1230
1231   size_t
1232     signature;
1233
1234   /*
1235     Assign module name from alias.
1236   */
1237   assert(module != (const char *) NULL);
1238   module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1239   if (module_info != (ModuleInfo *) NULL)
1240     return(MagickTrue);
1241   (void) CopyMagickString(module_name,module,MagickPathExtent);
1242   p=GetCoderInfo(module,exception);
1243   if (p != (CoderInfo *) NULL)
1244     (void) CopyMagickString(module_name,p->name,MagickPathExtent);
1245   if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1246     return(MagickTrue);  /* module already opened, return */
1247   /*
1248     Locate module.
1249   */
1250   handle=(ModuleHandle) NULL;
1251   TagToCoderModuleName(module_name,filename);
1252   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1253     "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1254   *path='\0';
1255   status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1256   if (status == MagickFalse)
1257     return(MagickFalse);
1258   /*
1259     Load module
1260   */
1261   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1262     "Opening module at path \"%s\"",path);
1263   handle=(ModuleHandle) lt_dlopen(path);
1264   if (handle == (ModuleHandle) NULL)
1265     {
1266       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1267         "UnableToLoadModule","'%s': %s",path,lt_dlerror());
1268       return(MagickFalse);
1269     }
1270   /*
1271     Register module.
1272   */
1273   module_info=AcquireModuleInfo(path,module_name);
1274   module_info->handle=handle;
1275   if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1276     return(MagickFalse);
1277   /*
1278     Define RegisterFORMATImage method.
1279   */
1280   TagToModuleName(module_name,"Register%sImage",name);
1281   module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1282   if (module_info->register_module == (size_t (*)(void)) NULL)
1283     {
1284       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1285         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1286       return(MagickFalse);
1287     }
1288   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1289     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1290     (void *) module_info->register_module);
1291   /*
1292     Define UnregisterFORMATImage method.
1293   */
1294   TagToModuleName(module_name,"Unregister%sImage",name);
1295   module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1296   if (module_info->unregister_module == (void (*)(void)) NULL)
1297     {
1298       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1299         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1300       return(MagickFalse);
1301     }
1302   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1303     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1304     (void *) module_info->unregister_module);
1305   signature=module_info->register_module();
1306   if (signature != MagickImageCoderSignature)
1307     {
1308       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1309         "ImageCoderSignatureMismatch","'%s': %8lx != %8lx",module_name,
1310         (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
1311       return(MagickFalse);
1312     }
1313   return(MagickTrue);
1314 }
1315 \f
1316 /*
1317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1318 %                                                                             %
1319 %                                                                             %
1320 %                                                                             %
1321 %   O p e n M o d u l e s                                                     %
1322 %                                                                             %
1323 %                                                                             %
1324 %                                                                             %
1325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326 %
1327 %  OpenModules() loads all available modules.
1328 %
1329 %  The format of the OpenModules module is:
1330 %
1331 %      MagickBooleanType OpenModules(ExceptionInfo *exception)
1332 %
1333 %  A description of each parameter follows:
1334 %
1335 %    o exception: return any errors or warnings in this structure.
1336 %
1337 */
1338 MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
1339 {
1340   char
1341     **modules;
1342
1343   register ssize_t
1344     i;
1345
1346   size_t
1347     number_modules;
1348
1349   /*
1350     Load all modules.
1351   */
1352   (void) GetMagickInfo((char *) NULL,exception);
1353   number_modules=0;
1354   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1355   if ((modules == (char **) NULL) || (*modules == (char *) NULL))
1356     {
1357       if (modules != (char **) NULL)
1358         modules=(char **) RelinquishMagickMemory(modules);
1359       return(MagickFalse);
1360     }
1361   for (i=0; i < (ssize_t) number_modules; i++)
1362     (void) OpenModule(modules[i],exception);
1363   /*
1364     Relinquish resources.
1365   */
1366   for (i=0; i < (ssize_t) number_modules; i++)
1367     modules[i]=DestroyString(modules[i]);
1368   modules=(char **) RelinquishMagickMemory(modules);
1369   return(MagickTrue);
1370 }
1371 \f
1372 /*
1373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1374 %                                                                             %
1375 %                                                                             %
1376 %                                                                             %
1377 %   R e g i s t e r M o d u l e                                               %
1378 %                                                                             %
1379 %                                                                             %
1380 %                                                                             %
1381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1382 %
1383 %  RegisterModule() adds an entry to the module list.  It returns a pointer to
1384 %  the registered entry on success.
1385 %
1386 %  The format of the RegisterModule module is:
1387 %
1388 %      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1389 %        ExceptionInfo *exception)
1390 %
1391 %  A description of each parameter follows:
1392 %
1393 %    o info: a pointer to the registered entry is returned.
1394 %
1395 %    o module_info: a pointer to the ModuleInfo structure to register.
1396 %
1397 %    o exception: return any errors or warnings in this structure.
1398 %
1399 */
1400 static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1401   ExceptionInfo *exception)
1402 {
1403   MagickBooleanType
1404     status;
1405
1406   assert(module_info != (ModuleInfo *) NULL);
1407   assert(module_info->signature == MagickCoreSignature);
1408   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1409   if (module_list == (SplayTreeInfo *) NULL)
1410     return((const ModuleInfo *) NULL);
1411   status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1412   if (status == MagickFalse)
1413     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1414       "MemoryAllocationFailed","`%s'",module_info->tag);
1415   return(module_info);
1416 }
1417 \f
1418 /*
1419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1420 %                                                                             %
1421 %                                                                             %
1422 %                                                                             %
1423 %  T a g T o C o d e r M o d u l e N a m e                                    %
1424 %                                                                             %
1425 %                                                                             %
1426 %                                                                             %
1427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428 %
1429 %  TagToCoderModuleName() munges a module tag and obtains the filename of the
1430 %  corresponding module.
1431 %
1432 %  The format of the TagToCoderModuleName module is:
1433 %
1434 %      char *TagToCoderModuleName(const char *tag,char *name)
1435 %
1436 %  A description of each parameter follows:
1437 %
1438 %    o tag: a character string representing the module tag.
1439 %
1440 %    o name: return the module name here.
1441 %
1442 */
1443 static void TagToCoderModuleName(const char *tag,char *name)
1444 {
1445   assert(tag != (char *) NULL);
1446   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1447   assert(name != (char *) NULL);
1448 #if defined(MAGICKCORE_LTDL_DELEGATE)
1449   (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
1450   (void) LocaleLower(name);
1451 #else
1452 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1453   if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1454     (void) CopyMagickString(name,tag,MagickPathExtent);
1455   else
1456     {
1457 #if defined(_DEBUG)
1458       (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_DB_%s_.dll",tag);
1459 #else
1460       (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_RL_%s_.dll",tag);
1461 #endif
1462     }
1463 #endif
1464 #endif
1465 }
1466 \f
1467 /*
1468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469 %                                                                             %
1470 %                                                                             %
1471 %                                                                             %
1472 %  T a g T o F i l t e r M o d u l e N a m e                                  %
1473 %                                                                             %
1474 %                                                                             %
1475 %                                                                             %
1476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1477 %
1478 %  TagToFilterModuleName() munges a module tag and returns the filename of the
1479 %  corresponding filter module.
1480 %
1481 %  The format of the TagToFilterModuleName module is:
1482 %
1483 %      void TagToFilterModuleName(const char *tag,char name)
1484 %
1485 %  A description of each parameter follows:
1486 %
1487 %    o tag: a character string representing the module tag.
1488 %
1489 %    o name: return the filter name here.
1490 %
1491 */
1492 static void TagToFilterModuleName(const char *tag,char *name)
1493 {
1494   assert(tag != (char *) NULL);
1495   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1496   assert(name != (char *) NULL);
1497 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1498   (void) FormatLocaleString(name,MagickPathExtent,"FILTER_%s_.dll",tag);
1499 #elif !defined(MAGICKCORE_LTDL_DELEGATE)
1500   (void) FormatLocaleString(name,MagickPathExtent,"%s.dll",tag);
1501 #else
1502   (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
1503 #endif
1504 }
1505 \f
1506 /*
1507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1508 %                                                                             %
1509 %                                                                             %
1510 %                                                                             %
1511 %   T a g T o M o d u l e N a m e                                             %
1512 %                                                                             %
1513 %                                                                             %
1514 %                                                                             %
1515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1516 %
1517 %  TagToModuleName() munges the module tag name and returns an upper-case tag
1518 %  name as the input string, and a user-provided format.
1519 %
1520 %  The format of the TagToModuleName module is:
1521 %
1522 %      TagToModuleName(const char *tag,const char *format,char *module)
1523 %
1524 %  A description of each parameter follows:
1525 %
1526 %    o tag: the module tag.
1527 %
1528 %    o format: a sprintf-compatible format string containing %s where the
1529 %      upper-case tag name is to be inserted.
1530 %
1531 %    o module: pointer to a destination buffer for the formatted result.
1532 %
1533 */
1534 static void TagToModuleName(const char *tag,const char *format,char *module)
1535 {
1536   char
1537     name[MagickPathExtent];
1538
1539   assert(tag != (const char *) NULL);
1540   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1541   assert(format != (const char *) NULL);
1542   assert(module != (char *) NULL);
1543   (void) CopyMagickString(name,tag,MagickPathExtent);
1544   LocaleUpper(name);
1545 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1546   (void) FormatLocaleString(module,MagickPathExtent,format,name);
1547 #else
1548   {
1549     char
1550       prefix_format[MagickPathExtent];
1551
1552     (void) FormatLocaleString(prefix_format,MagickPathExtent,"%s%s",
1553       MAGICKCORE_NAMESPACE_PREFIX,format);
1554     (void) FormatLocaleString(module,MagickPathExtent,prefix_format,name);
1555   }
1556 #endif
1557 }
1558 \f
1559 /*
1560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1561 %                                                                             %
1562 %                                                                             %
1563 %                                                                             %
1564 %   U n r e g i s t e r M o d u l e                                           %
1565 %                                                                             %
1566 %                                                                             %
1567 %                                                                             %
1568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1569 %
1570 %  UnregisterModule() unloads a module, and invokes its de-registration module.
1571 %  Returns MagickTrue on success, and MagickFalse if there is an error.
1572 %
1573 %  The format of the UnregisterModule module is:
1574 %
1575 %      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1576 %        ExceptionInfo *exception)
1577 %
1578 %  A description of each parameter follows:
1579 %
1580 %    o module_info: the module info.
1581 %
1582 %    o exception: return any errors or warnings in this structure.
1583 %
1584 */
1585 static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1586   ExceptionInfo *exception)
1587 {
1588   /*
1589     Locate and execute UnregisterFORMATImage module.
1590   */
1591   assert(module_info != (const ModuleInfo *) NULL);
1592   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1593   assert(exception != (ExceptionInfo *) NULL);
1594   if (module_info->unregister_module == NULL)
1595     return(MagickTrue);
1596   module_info->unregister_module();
1597   if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1598     {
1599       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1600         "UnableToCloseModule","'%s': %s",module_info->tag,lt_dlerror());
1601       return(MagickFalse);
1602     }
1603   return(MagickTrue);
1604 }
1605 #else
1606
1607 #if !defined(MAGICKCORE_BUILD_MODULES)
1608 extern size_t
1609   analyzeImage(Image **,const int,const char **,ExceptionInfo *);
1610 #endif
1611
1612 MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1613   ExceptionInfo *magick_unused(exception))
1614 {
1615   return(MagickTrue);
1616 }
1617
1618 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1619   Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1620 {
1621   PolicyRights
1622     rights;
1623
1624   assert(image != (Image **) NULL);
1625   assert((*image)->signature == MagickCoreSignature);
1626   if ((*image)->debug != MagickFalse)
1627     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1628   rights=ReadPolicyRights;
1629   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
1630     {
1631       errno=EPERM;
1632       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1633         "NotAuthorized","`%s'",tag);
1634       return(MagickFalse);
1635     }
1636 #if defined(MAGICKCORE_BUILD_MODULES)
1637   (void) tag;
1638   (void) argc;
1639   (void) argv;
1640   (void) exception;
1641 #else
1642   {
1643     ImageFilterHandler
1644       *image_filter;
1645
1646     image_filter=(ImageFilterHandler *) NULL;
1647     if (LocaleCompare("analyze",tag) == 0)
1648       image_filter=(ImageFilterHandler *) analyzeImage;
1649     if (image_filter == (ImageFilterHandler *) NULL)
1650       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1651         "UnableToLoadModule","`%s'",tag);
1652     else
1653       {
1654         size_t
1655           signature;
1656
1657         if ((*image)->debug != MagickFalse)
1658           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1659             "Invoking \"%s\" static image filter",tag);
1660         signature=image_filter(image,argc,argv,exception);
1661         if ((*image)->debug != MagickFalse)
1662           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
1663             tag);
1664         if (signature != MagickImageFilterSignature)
1665           {
1666             (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1667               "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1668               (unsigned long) signature,(unsigned long)
1669               MagickImageFilterSignature);
1670             return(MagickFalse);
1671           }
1672       }
1673   }
1674 #endif
1675   return(MagickTrue);
1676 }
1677 #endif