]> granicus.if.org Git - imagemagick/blob - MagickCore/module.c
(no commit message)
[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-2014 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 %    http://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/hashmap.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(ExceptionInfo *),
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=MagickSignature;
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(exception) == 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 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
387   struct dirent **result)
388 {
389 #if defined(MAGICKCORE_HAVE_READDIR_R)
390   return(readdir_r(directory,entry,result));
391 #else
392   (void) entry;
393   errno=0;
394   *result=readdir(directory);
395   return(errno);
396 #endif
397 }
398
399 MagickExport char **GetModuleList(const char *pattern,
400   const MagickModuleType type,size_t *number_modules,ExceptionInfo *exception)
401 {
402   char
403     **modules,
404     filename[MaxTextExtent],
405     module_path[MaxTextExtent],
406     path[MaxTextExtent];
407
408   DIR
409     *directory;
410
411   MagickBooleanType
412     status;
413
414   register ssize_t
415     i;
416
417   size_t
418     max_entries;
419
420   struct dirent
421     *buffer,
422     *entry;
423
424   /*
425     Locate all modules in the image coder or filter path.
426   */
427   switch (type)
428   {
429     case MagickImageCoderModule:
430     default:
431     {
432       TagToCoderModuleName("magick",filename);
433       status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
434         exception);
435       break;
436     }
437     case MagickImageFilterModule:
438     {
439       TagToFilterModuleName("analyze",filename);
440       status=GetMagickModulePath(filename,MagickImageFilterModule,module_path,
441         exception);
442       break;
443     }
444   }
445   if (status == MagickFalse)
446     return((char **) NULL);
447   GetPathComponent(module_path,HeadPath,path);
448   max_entries=255;
449   modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
450     sizeof(*modules));
451   if (modules == (char **) NULL)
452     return((char **) NULL);
453   *modules=(char *) NULL;
454   directory=opendir(path);
455   if (directory == (DIR *) NULL)
456     {
457       modules=(char **) RelinquishMagickMemory(modules);
458       return((char **) NULL);
459     }
460   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
461   if (buffer == (struct dirent *) NULL)
462     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
463   i=0;
464   while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
465          (entry != (struct dirent *) NULL))
466   {
467     status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
468     if (status == MagickFalse)
469       continue;
470     if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
471       continue;
472     if (i >= (ssize_t) max_entries)
473       {
474         modules=(char **) NULL;
475         if (~max_entries > max_entries)
476           modules=(char **) ResizeQuantumMemory(modules,(size_t)
477             (max_entries << 1),sizeof(*modules));
478         max_entries<<=1;
479         if (modules == (char **) NULL)
480           break;
481       }
482     /*
483       Add new module name to list.
484     */
485     modules[i]=AcquireString((char *) NULL);
486     GetPathComponent(entry->d_name,BasePath,modules[i]);
487     if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
488       {
489         (void) CopyMagickString(modules[i],modules[i]+10,MaxTextExtent);
490         modules[i][strlen(modules[i])-1]='\0';
491       }
492     i++;
493   }
494   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
495   (void) closedir(directory);
496   if (modules == (char **) NULL)
497     {
498       (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
499         "MemoryAllocationFailed","`%s'",pattern);
500       return((char **) NULL);
501     }
502   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
503   modules[i]=(char *) NULL;
504   *number_modules=(size_t) i;
505   return(modules);
506 }
507 \f
508 /*
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 %                                                                             %
511 %                                                                             %
512 %                                                                             %
513 %  G e t M a g i c k M o d u l e P a t h                                      %
514 %                                                                             %
515 %                                                                             %
516 %                                                                             %
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518 %
519 %  GetMagickModulePath() finds a module with the specified module type and
520 %  filename.
521 %
522 %  The format of the GetMagickModulePath module is:
523 %
524 %      MagickBooleanType GetMagickModulePath(const char *filename,
525 %        MagickModuleType module_type,char *path,ExceptionInfo *exception)
526 %
527 %  A description of each parameter follows:
528 %
529 %    o filename: the module file name.
530 %
531 %    o module_type: the module type: MagickImageCoderModule or
532 %      MagickImageFilterModule.
533 %
534 %    o path: the path associated with the filename.
535 %
536 %    o exception: return any errors or warnings in this structure.
537 %
538 */
539 static MagickBooleanType GetMagickModulePath(const char *filename,
540   MagickModuleType module_type,char *path,ExceptionInfo *exception)
541 {
542   char
543     *module_path;
544
545   assert(filename != (const char *) NULL);
546   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
547   assert(path != (char *) NULL);
548   assert(exception != (ExceptionInfo *) NULL);
549   (void) CopyMagickString(path,filename,MaxTextExtent);
550   module_path=(char *) NULL;
551   switch (module_type)
552   {
553     case MagickImageCoderModule:
554     default:
555     {
556       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
557         "Searching for coder module file \"%s\" ...",filename);
558       module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
559 #if defined(MAGICKCORE_CODER_PATH)
560       if (module_path == (char *) NULL)
561         module_path=AcquireString(MAGICKCORE_CODER_PATH);
562 #endif
563       break;
564     }
565     case MagickImageFilterModule:
566     {
567       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
568         "Searching for filter module file \"%s\" ...",filename);
569       module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
570 #if defined(MAGICKCORE_FILTER_PATH)
571       if (module_path == (char *) NULL)
572         module_path=AcquireString(MAGICKCORE_FILTER_PATH);
573 #endif
574       break;
575     }
576   }
577   if (module_path != (char *) NULL)
578     {
579       register char
580         *p,
581         *q;
582
583       for (p=module_path-1; p != (char *) NULL; )
584       {
585         (void) CopyMagickString(path,p+1,MaxTextExtent);
586         q=strchr(path,DirectoryListSeparator);
587         if (q != (char *) NULL)
588           *q='\0';
589         q=path+strlen(path)-1;
590         if ((q >= path) && (*q != *DirectorySeparator))
591           (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
592         (void) ConcatenateMagickString(path,filename,MaxTextExtent);
593         if (IsPathAccessible(path) != MagickFalse)
594           {
595             module_path=DestroyString(module_path);
596             return(MagickTrue);
597           }
598         p=strchr(p+1,DirectoryListSeparator);
599       }
600       module_path=DestroyString(module_path);
601     }
602 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
603   else
604 #if defined(MAGICKCORE_CODER_PATH)
605     {
606       const char
607         *directory;
608
609       /*
610         Search hard coded paths.
611       */
612       switch (module_type)
613       {
614         case MagickImageCoderModule:
615         default:
616         {
617           directory=MAGICKCORE_CODER_PATH;
618           break;
619         }
620         case MagickImageFilterModule:
621         {
622           directory=MAGICKCORE_FILTER_PATH;
623           break;
624         }
625       }
626       (void) FormatLocaleString(path,MaxTextExtent,"%s%s",directory,filename);
627       if (IsPathAccessible(path) == MagickFalse)
628         {
629           ThrowFileException(exception,ConfigureWarning,
630             "UnableToOpenModuleFile",path);
631           return(MagickFalse);
632         }
633       return(MagickTrue);
634     }
635 #else
636 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
637     {
638       const char
639         *registery_key;
640
641       unsigned char
642         *key_value;
643
644       /*
645         Locate path via registry key.
646       */
647       switch (module_type)
648       {
649         case MagickImageCoderModule:
650         default:
651         {
652           registery_key="CoderModulesPath";
653           break;
654         }
655         case MagickImageFilterModule:
656         {
657           registery_key="FilterModulesPath";
658           break;
659         }
660       }
661       key_value=NTRegistryKeyLookup(registery_key);
662       if (key_value == (unsigned char *) NULL)
663         {
664           ThrowMagickException(exception,GetMagickModule(),ConfigureError,
665             "RegistryKeyLookupFailed","`%s'",registery_key);
666           return(MagickFalse);
667         }
668       (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",(char *) key_value,
669         DirectorySeparator,filename);
670       key_value=(unsigned char *) RelinquishMagickMemory(key_value);
671       if (IsPathAccessible(path) == MagickFalse)
672         {
673           ThrowFileException(exception,ConfigureWarning,
674             "UnableToOpenModuleFile",path);
675           return(MagickFalse);
676         }
677       return(MagickTrue);
678     }
679 #endif
680 #endif
681 #if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
682 # error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
683 #endif
684 #else
685   {
686     char
687       *home;
688
689     home=GetEnvironmentValue("MAGICK_HOME");
690     if (home != (char *) NULL)
691       {
692         /*
693           Search MAGICK_HOME.
694         */
695 #if !defined(MAGICKCORE_POSIX_SUPPORT)
696         (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",home,
697           DirectorySeparator,filename);
698 #else
699         const char
700           *directory;
701
702         switch (module_type)
703         {
704           case MagickImageCoderModule:
705           default:
706           {
707             directory=MAGICKCORE_CODER_RELATIVE_PATH;
708             break;
709           }
710           case MagickImageFilterModule:
711           {
712             directory=MAGICKCORE_FILTER_RELATIVE_PATH;
713             break;
714           }
715         }
716         (void) FormatLocaleString(path,MaxTextExtent,"%s/lib/%s/%s",home,
717           directory,filename);
718 #endif
719         home=DestroyString(home);
720         if (IsPathAccessible(path) != MagickFalse)
721           return(MagickTrue);
722       }
723   }
724   if (*GetClientPath() != '\0')
725     {
726       /*
727         Search based on executable directory.
728       */
729 #if !defined(MAGICKCORE_POSIX_SUPPORT)
730       (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
731         DirectorySeparator,filename);
732 #else
733       char
734         prefix[MaxTextExtent];
735
736       const char
737         *directory;
738
739       switch (module_type)
740       {
741         case MagickImageCoderModule:
742         default:
743         {
744           directory="coders";
745           break;
746         }
747         case MagickImageFilterModule:
748         {
749           directory="filters";
750           break;
751         }
752       }
753       (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
754       ChopPathComponents(prefix,1);
755       (void) FormatLocaleString(path,MaxTextExtent,"%s/lib/%s/%s/%s",prefix,
756         MAGICKCORE_MODULES_RELATIVE_PATH,directory,filename);
757 #endif
758       if (IsPathAccessible(path) != MagickFalse)
759         return(MagickTrue);
760     }
761 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
762   {
763     /*
764       Search module path.
765     */
766     if ((NTGetModulePath("CORE_RL_magick_.dll",path) != MagickFalse) ||
767         (NTGetModulePath("CORE_DB_magick_.dll",path) != MagickFalse) ||
768         (NTGetModulePath("Magick.dll",path) != MagickFalse))
769       {
770         (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
771         (void) ConcatenateMagickString(path,filename,MaxTextExtent);
772         if (IsPathAccessible(path) != MagickFalse)
773           return(MagickTrue);
774       }
775   }
776 #endif
777   {
778     char
779       *home;
780
781     home=GetEnvironmentValue("HOME");
782     if (home == (char *) NULL)
783       home=GetEnvironmentValue("USERPROFILE");
784     if (home != (char *) NULL)
785       {
786         /*
787           Search $HOME/.config/ImageMagick.
788         */
789         (void) FormatLocaleString(path,MaxTextExtent,
790           "%s%s.config%sImageMagick%s%s",home,DirectorySeparator,
791           DirectorySeparator,DirectorySeparator,filename);
792         home=DestroyString(home);
793         if (IsPathAccessible(path) != MagickFalse)
794           return(MagickTrue);
795       }
796   }
797   /*
798     Search current directory.
799   */
800   if (IsPathAccessible(path) != MagickFalse)
801     return(MagickTrue);
802   if (exception->severity < ConfigureError)
803     ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
804       path);
805 #endif
806   return(MagickFalse);
807 }
808 \f
809 /*
810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
811 %                                                                             %
812 %                                                                             %
813 %                                                                             %
814 %   I s M o d u l e T r e e I n s t a n t i a t e d                           %
815 %                                                                             %
816 %                                                                             %
817 %                                                                             %
818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819 %
820 %  IsModuleTreeInstantiated() determines if the module tree is instantiated.
821 %  If not, it instantiates the tree and returns it.
822 %
823 %  The format of the IsModuleTreeInstantiated() method is:
824 %
825 %      IsModuleTreeInstantiated(Exceptioninfo *exception)
826 %
827 %  A description of each parameter follows.
828 %
829 %    o exception: return any errors or warnings in this structure.
830 %
831 */
832
833 static void *DestroyModuleNode(void *module_info)
834 {
835   ExceptionInfo
836     *exception;
837
838   register ModuleInfo
839     *p;
840
841   exception=AcquireExceptionInfo();
842   p=(ModuleInfo *) module_info;
843   if (UnregisterModule(p,exception) == MagickFalse)
844     CatchException(exception);
845   if (p->tag != (char *) NULL)
846     p->tag=DestroyString(p->tag);
847   if (p->path != (char *) NULL)
848     p->path=DestroyString(p->path);
849   exception=DestroyExceptionInfo(exception);
850   return(RelinquishMagickMemory(p));
851 }
852
853 static MagickBooleanType IsModuleTreeInstantiated(
854   ExceptionInfo *magick_unused(exception))
855 {
856   if (module_list == (SplayTreeInfo *) NULL)
857     {
858       if (module_semaphore == (SemaphoreInfo *) NULL)
859         ActivateSemaphoreInfo(&module_semaphore);
860       LockSemaphoreInfo(module_semaphore);
861       if (module_list == (SplayTreeInfo *) NULL)
862         {
863           MagickBooleanType
864             status;
865
866           ModuleInfo
867             *module_info;
868
869           module_list=NewSplayTree(CompareSplayTreeString,
870             (void *(*)(void *)) NULL,DestroyModuleNode);
871           if (module_list == (SplayTreeInfo *) NULL)
872             ThrowFatalException(ResourceLimitFatalError,
873               "MemoryAllocationFailed");
874           module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
875           module_info->stealth=MagickTrue;
876           status=AddValueToSplayTree(module_list,module_info->tag,module_info);
877           if (status == MagickFalse)
878             ThrowFatalException(ResourceLimitFatalError,
879               "MemoryAllocationFailed");
880           if (lt_dlinit() != 0)
881             ThrowFatalException(ModuleFatalError,
882               "UnableToInitializeModuleLoader");
883         }
884       UnlockSemaphoreInfo(module_semaphore);
885     }
886   return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
887 }
888 \f
889 /*
890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 %                                                                             %
892 %                                                                             %
893 %                                                                             %
894 %   I n v o k e D y n a m i c I m a g e F i l t e r                           %
895 %                                                                             %
896 %                                                                             %
897 %                                                                             %
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899 %
900 %  InvokeDynamicImageFilter() invokes a dynamic image filter.
901 %
902 %  The format of the InvokeDynamicImageFilter module is:
903 %
904 %      MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
905 %        const int argc,const char **argv,ExceptionInfo *exception)
906 %
907 %  A description of each parameter follows:
908 %
909 %    o tag: a character string that represents the name of the particular
910 %      module.
911 %
912 %    o image: the image.
913 %
914 %    o argc: a pointer to an integer describing the number of elements in the
915 %      argument vector.
916 %
917 %    o argv: a pointer to a text array containing the command line arguments.
918 %
919 %    o exception: return any errors or warnings in this structure.
920 %
921 */
922 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
923   Image **images,const int argc,const char **argv,ExceptionInfo *exception)
924 {
925   char
926     name[MaxTextExtent],
927     path[MaxTextExtent];
928
929   ImageFilterHandler
930     *image_filter;
931
932   MagickBooleanType
933     status;
934
935   ModuleHandle
936     handle;
937
938   PolicyRights
939     rights;
940
941   /*
942     Find the module.
943   */
944   assert(images != (Image **) NULL);
945   assert((*images)->signature == MagickSignature);
946   if ((*images)->debug != MagickFalse)
947     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
948       (*images)->filename);
949 #if !defined(MAGICKCORE_BUILD_MODULES)
950   {
951     MagickBooleanType
952       status;
953
954     status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
955     if (status != MagickFalse)
956       return(status);
957   }
958 #endif
959   rights=ReadPolicyRights;
960   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
961     {
962       errno=EPERM;
963       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
964         "NotAuthorized","`%s'",tag);
965       return(MagickFalse);
966     }
967   TagToFilterModuleName(tag,name);
968   status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
969   if (status == MagickFalse)
970     {
971       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
972         "UnableToLoadModule","'%s': %s",name,path);
973       return(MagickFalse);
974     }
975   /*
976     Open the module.
977   */
978   handle=(ModuleHandle) lt_dlopen(path);
979   if (handle == (ModuleHandle) NULL)
980     {
981       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
982         "UnableToLoadModule","'%s': %s",name,lt_dlerror());
983       return(MagickFalse);
984     }
985   /*
986     Locate the module.
987   */
988 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
989   (void) FormatLocaleString(name,MaxTextExtent,"%sImage",tag);
990 #else
991   (void) FormatLocaleString(name,MaxTextExtent,"%s%sImage",
992     MAGICKCORE_NAMESPACE_PREFIX,tag);
993 #endif
994   /*
995     Execute the module.
996   */
997   ClearMagickException(exception);
998   image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
999   if (image_filter == (ImageFilterHandler *) NULL)
1000     (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1001       "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1002   else
1003     {
1004       size_t
1005         signature;
1006
1007       if ((*images)->debug != MagickFalse)
1008         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1009           "Invoking \"%s\" dynamic image filter",tag);
1010       signature=image_filter(images,argc,argv,exception);
1011       if ((*images)->debug != MagickFalse)
1012         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1013           tag);
1014       if (signature != MagickImageFilterSignature)
1015         (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1016           "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1017           (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
1018     }
1019   /*
1020     Close the module.
1021   */
1022   if (lt_dlclose(handle) != 0)
1023     (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1024       "UnableToCloseModule","'%s': %s",name,lt_dlerror());
1025   return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
1026 }
1027 \f
1028 /*
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %                                                                             %
1031 %                                                                             %
1032 %                                                                             %
1033 %  L i s t M o d u l e I n f o                                                %
1034 %                                                                             %
1035 %                                                                             %
1036 %                                                                             %
1037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 %
1039 %  ListModuleInfo() lists the module info to a file.
1040 %
1041 %  The format of the ListModuleInfo module is:
1042 %
1043 %      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1044 %
1045 %  A description of each parameter follows.
1046 %
1047 %    o file:  An pointer to a FILE.
1048 %
1049 %    o exception: return any errors or warnings in this structure.
1050 %
1051 */
1052 MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1053   ExceptionInfo *exception)
1054 {
1055   char
1056     filename[MaxTextExtent],
1057     module_path[MaxTextExtent],
1058     **modules,
1059     path[MaxTextExtent];
1060
1061   register ssize_t
1062     i;
1063
1064   size_t
1065     number_modules;
1066
1067   if (file == (const FILE *) NULL)
1068     file=stdout;
1069   /*
1070     List image coders.
1071   */
1072   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1073   if (modules == (char **) NULL)
1074     return(MagickFalse);
1075   TagToCoderModuleName("magick",filename);
1076   (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
1077     exception);
1078   GetPathComponent(module_path,HeadPath,path);
1079   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1080   (void) FormatLocaleFile(file,"Image Coder\n");
1081   (void) FormatLocaleFile(file,
1082     "-------------------------------------------------"
1083     "------------------------------\n");
1084   for (i=0; i < (ssize_t) number_modules; i++)
1085   {
1086     (void) FormatLocaleFile(file,"%s",modules[i]);
1087     (void) FormatLocaleFile(file,"\n");
1088   }
1089   (void) fflush(file);
1090   /*
1091     Relinquish resources.
1092   */
1093   for (i=0; i < (ssize_t) number_modules; i++)
1094     modules[i]=DestroyString(modules[i]);
1095   modules=(char **) RelinquishMagickMemory(modules);
1096   /*
1097     List image filters.
1098   */
1099   modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
1100   if (modules == (char **) NULL)
1101     return(MagickFalse);
1102   TagToFilterModuleName("analyze",filename);
1103   (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
1104     exception);
1105   GetPathComponent(module_path,HeadPath,path);
1106   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1107   (void) FormatLocaleFile(file,"Image Filter\n");
1108   (void) FormatLocaleFile(file,
1109     "-------------------------------------------------"
1110     "------------------------------\n");
1111   for (i=0; i < (ssize_t) number_modules; i++)
1112   {
1113     (void) FormatLocaleFile(file,"%s",modules[i]);
1114     (void) FormatLocaleFile(file,"\n");
1115   }
1116   (void) fflush(file);
1117   /*
1118     Relinquish resources.
1119   */
1120   for (i=0; i < (ssize_t) number_modules; i++)
1121     modules[i]=DestroyString(modules[i]);
1122   modules=(char **) RelinquishMagickMemory(modules);
1123   return(MagickTrue);
1124 }
1125 \f
1126 /*
1127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1128 %                                                                             %
1129 %                                                                             %
1130 %                                                                             %
1131 +   M o d u l e C o m p o n e n t G e n e s i s                               %
1132 %                                                                             %
1133 %                                                                             %
1134 %                                                                             %
1135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1136 %
1137 %  ModuleComponentGenesis() instantiates the module component.
1138 %
1139 %  The format of the ModuleComponentGenesis method is:
1140 %
1141 %      MagickBooleanType ModuleComponentGenesis(void)
1142 %
1143 */
1144 MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
1145 {
1146   ExceptionInfo
1147     *exception;
1148
1149   MagickBooleanType
1150     status;
1151
1152   if (module_semaphore == (SemaphoreInfo *) NULL)
1153     module_semaphore=AcquireSemaphoreInfo();
1154   exception=AcquireExceptionInfo();
1155   status=IsModuleTreeInstantiated(exception);
1156   exception=DestroyExceptionInfo(exception);
1157   return(status);
1158 }
1159 \f
1160 /*
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1162 %                                                                             %
1163 %                                                                             %
1164 %                                                                             %
1165 +   M o d u l e C o m p o n e n t T e r m i n u s                             %
1166 %                                                                             %
1167 %                                                                             %
1168 %                                                                             %
1169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1170 %
1171 %  ModuleComponentTerminus() destroys the module component.
1172 %
1173 %  The format of the ModuleComponentTerminus method is:
1174 %
1175 %      ModuleComponentTerminus(void)
1176 %
1177 */
1178 MagickPrivate void ModuleComponentTerminus(void)
1179 {
1180   if (module_semaphore == (SemaphoreInfo *) NULL)
1181     ActivateSemaphoreInfo(&module_semaphore);
1182   DestroyModuleList();
1183   RelinquishSemaphoreInfo(&module_semaphore);
1184 }
1185 \f
1186 /*
1187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188 %                                                                             %
1189 %                                                                             %
1190 %                                                                             %
1191 %   O p e n M o d u l e                                                       %
1192 %                                                                             %
1193 %                                                                             %
1194 %                                                                             %
1195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196 %
1197 %  OpenModule() loads a module, and invokes its registration module.  It
1198 %  returns MagickTrue on success, and MagickFalse if there is an error.
1199 %
1200 %  The format of the OpenModule module is:
1201 %
1202 %      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1203 %
1204 %  A description of each parameter follows:
1205 %
1206 %    o module: a character string that indicates the module to load.
1207 %
1208 %    o exception: return any errors or warnings in this structure.
1209 %
1210 */
1211 MagickPrivate MagickBooleanType OpenModule(const char *module,
1212   ExceptionInfo *exception)
1213 {
1214   char
1215     filename[MaxTextExtent],
1216     module_name[MaxTextExtent],
1217     name[MaxTextExtent],
1218     path[MaxTextExtent];
1219
1220   MagickBooleanType
1221     status;
1222
1223   ModuleHandle
1224     handle;
1225
1226   ModuleInfo
1227     *module_info;
1228
1229   register const CoderInfo
1230     *p;
1231
1232   size_t
1233     signature;
1234
1235   /*
1236     Assign module name from alias.
1237   */
1238   assert(module != (const char *) NULL);
1239   module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1240   if (module_info != (ModuleInfo *) NULL)
1241     return(MagickTrue);
1242   (void) CopyMagickString(module_name,module,MaxTextExtent);
1243   p=GetCoderInfo(module,exception);
1244   if (p != (CoderInfo *) NULL)
1245     (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1246   if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1247     return(MagickTrue);  /* module already opened, return */
1248   /*
1249     Locate module.
1250   */
1251   handle=(ModuleHandle) NULL;
1252   TagToCoderModuleName(module_name,filename);
1253   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1254     "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1255   *path='\0';
1256   status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1257   if (status == MagickFalse)
1258     return(MagickFalse);
1259   /*
1260     Load module
1261   */
1262   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1263     "Opening module at path \"%s\"",path);
1264   handle=(ModuleHandle) lt_dlopen(path);
1265   if (handle == (ModuleHandle) NULL)
1266     {
1267       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1268         "UnableToLoadModule","'%s': %s",path,lt_dlerror());
1269       return(MagickFalse);
1270     }
1271   /*
1272     Register module.
1273   */
1274   module_info=AcquireModuleInfo(path,module_name);
1275   module_info->handle=handle;
1276   if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1277     return(MagickFalse);
1278   /*
1279     Define RegisterFORMATImage method.
1280   */
1281   TagToModuleName(module_name,"Register%sImage",name);
1282   module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1283   if (module_info->register_module == (size_t (*)(void)) NULL)
1284     {
1285       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1286         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1287       return(MagickFalse);
1288     }
1289   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1290     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1291     (void *) module_info->register_module);
1292   /*
1293     Define UnregisterFORMATImage method.
1294   */
1295   TagToModuleName(module_name,"Unregister%sImage",name);
1296   module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1297   if (module_info->unregister_module == (void (*)(void)) NULL)
1298     {
1299       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1300         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1301       return(MagickFalse);
1302     }
1303   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1304     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1305     (void *) module_info->unregister_module);
1306   signature=module_info->register_module();
1307   if (signature != MagickImageCoderSignature)
1308     {
1309       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1310         "ImageCoderSignatureMismatch","'%s': %8lx != %8lx",module_name,
1311         (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
1312       return(MagickFalse);
1313     }
1314   return(MagickTrue);
1315 }
1316 \f
1317 /*
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319 %                                                                             %
1320 %                                                                             %
1321 %                                                                             %
1322 %   O p e n M o d u l e s                                                     %
1323 %                                                                             %
1324 %                                                                             %
1325 %                                                                             %
1326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327 %
1328 %  OpenModules() loads all available modules.
1329 %
1330 %  The format of the OpenModules module is:
1331 %
1332 %      MagickBooleanType OpenModules(ExceptionInfo *exception)
1333 %
1334 %  A description of each parameter follows:
1335 %
1336 %    o exception: return any errors or warnings in this structure.
1337 %
1338 */
1339 MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
1340 {
1341   char
1342     **modules;
1343
1344   register ssize_t
1345     i;
1346
1347   size_t
1348     number_modules;
1349
1350   /*
1351     Load all modules.
1352   */
1353   (void) GetMagickInfo((char *) NULL,exception);
1354   number_modules=0;
1355   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1356   if (modules == (char **) NULL)
1357     return(MagickFalse);
1358   for (i=0; i < (ssize_t) number_modules; i++)
1359     (void) OpenModule(modules[i],exception);
1360   /*
1361     Relinquish resources.
1362   */
1363   for (i=0; i < (ssize_t) number_modules; i++)
1364     modules[i]=DestroyString(modules[i]);
1365   modules=(char **) RelinquishMagickMemory(modules);
1366   return(MagickTrue);
1367 }
1368 \f
1369 /*
1370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1371 %                                                                             %
1372 %                                                                             %
1373 %                                                                             %
1374 %   R e g i s t e r M o d u l e                                               %
1375 %                                                                             %
1376 %                                                                             %
1377 %                                                                             %
1378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379 %
1380 %  RegisterModule() adds an entry to the module list.  It returns a pointer to
1381 %  the registered entry on success.
1382 %
1383 %  The format of the RegisterModule module is:
1384 %
1385 %      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1386 %        ExceptionInfo *exception)
1387 %
1388 %  A description of each parameter follows:
1389 %
1390 %    o info: a pointer to the registered entry is returned.
1391 %
1392 %    o module_info: a pointer to the ModuleInfo structure to register.
1393 %
1394 %    o exception: return any errors or warnings in this structure.
1395 %
1396 */
1397 static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1398   ExceptionInfo *exception)
1399 {
1400   MagickBooleanType
1401     status;
1402
1403   assert(module_info != (ModuleInfo *) NULL);
1404   assert(module_info->signature == MagickSignature);
1405   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1406   if (module_list == (SplayTreeInfo *) NULL)
1407     return((const ModuleInfo *) NULL);
1408   status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1409   if (status == MagickFalse)
1410     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1411       "MemoryAllocationFailed","`%s'",module_info->tag);
1412   return(module_info);
1413 }
1414 \f
1415 /*
1416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1417 %                                                                             %
1418 %                                                                             %
1419 %                                                                             %
1420 %  T a g T o C o d e r M o d u l e N a m e                                    %
1421 %                                                                             %
1422 %                                                                             %
1423 %                                                                             %
1424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1425 %
1426 %  TagToCoderModuleName() munges a module tag and obtains the filename of the
1427 %  corresponding module.
1428 %
1429 %  The format of the TagToCoderModuleName module is:
1430 %
1431 %      char *TagToCoderModuleName(const char *tag,char *name)
1432 %
1433 %  A description of each parameter follows:
1434 %
1435 %    o tag: a character string representing the module tag.
1436 %
1437 %    o name: return the module name here.
1438 %
1439 */
1440 static void TagToCoderModuleName(const char *tag,char *name)
1441 {
1442   assert(tag != (char *) NULL);
1443   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1444   assert(name != (char *) NULL);
1445 #if defined(MAGICKCORE_LTDL_DELEGATE)
1446   (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
1447   (void) LocaleLower(name);
1448 #else
1449 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1450   if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1451     (void) CopyMagickString(name,tag,MaxTextExtent);
1452   else
1453     {
1454 #if defined(_DEBUG)
1455       (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
1456 #else
1457       (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
1458 #endif
1459     }
1460 #endif
1461 #endif
1462 }
1463 \f
1464 /*
1465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466 %                                                                             %
1467 %                                                                             %
1468 %                                                                             %
1469 %  T a g T o F i l t e r M o d u l e N a m e                                  %
1470 %                                                                             %
1471 %                                                                             %
1472 %                                                                             %
1473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474 %
1475 %  TagToFilterModuleName() munges a module tag and returns the filename of the
1476 %  corresponding filter module.
1477 %
1478 %  The format of the TagToFilterModuleName module is:
1479 %
1480 %      void TagToFilterModuleName(const char *tag,char name)
1481 %
1482 %  A description of each parameter follows:
1483 %
1484 %    o tag: a character string representing the module tag.
1485 %
1486 %    o name: return the filter name here.
1487 %
1488 */
1489 static void TagToFilterModuleName(const char *tag,char *name)
1490 {
1491   assert(tag != (char *) NULL);
1492   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1493   assert(name != (char *) NULL);
1494 #if !defined(MAGICKCORE_LTDL_DELEGATE)
1495   (void) FormatLocaleString(name,MaxTextExtent,"%s.dll",tag);
1496 #else
1497   (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
1498 #endif
1499 }
1500 \f
1501 /*
1502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1503 %                                                                             %
1504 %                                                                             %
1505 %                                                                             %
1506 %   T a g T o M o d u l e N a m e                                             %
1507 %                                                                             %
1508 %                                                                             %
1509 %                                                                             %
1510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1511 %
1512 %  TagToModuleName() munges the module tag name and returns an upper-case tag
1513 %  name as the input string, and a user-provided format.
1514 %
1515 %  The format of the TagToModuleName module is:
1516 %
1517 %      TagToModuleName(const char *tag,const char *format,char *module)
1518 %
1519 %  A description of each parameter follows:
1520 %
1521 %    o tag: the module tag.
1522 %
1523 %    o format: a sprintf-compatible format string containing %s where the
1524 %      upper-case tag name is to be inserted.
1525 %
1526 %    o module: pointer to a destination buffer for the formatted result.
1527 %
1528 */
1529 static void TagToModuleName(const char *tag,const char *format,char *module)
1530 {
1531   char
1532     name[MaxTextExtent];
1533
1534   assert(tag != (const char *) NULL);
1535   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1536   assert(format != (const char *) NULL);
1537   assert(module != (char *) NULL);
1538   (void) CopyMagickString(name,tag,MaxTextExtent);
1539   LocaleUpper(name);
1540 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1541   (void) FormatLocaleString(module,MaxTextExtent,format,name);
1542 #else
1543   {
1544     char
1545       prefix_format[MaxTextExtent];
1546
1547     (void) FormatLocaleString(prefix_format,MaxTextExtent,"%s%s",
1548       MAGICKCORE_NAMESPACE_PREFIX,format);
1549     (void) FormatLocaleString(module,MaxTextExtent,prefix_format,name);
1550   }
1551 #endif
1552 }
1553 \f
1554 /*
1555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556 %                                                                             %
1557 %                                                                             %
1558 %                                                                             %
1559 %   U n r e g i s t e r M o d u l e                                           %
1560 %                                                                             %
1561 %                                                                             %
1562 %                                                                             %
1563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1564 %
1565 %  UnregisterModule() unloads a module, and invokes its de-registration module.
1566 %  Returns MagickTrue on success, and MagickFalse if there is an error.
1567 %
1568 %  The format of the UnregisterModule module is:
1569 %
1570 %      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1571 %        ExceptionInfo *exception)
1572 %
1573 %  A description of each parameter follows:
1574 %
1575 %    o module_info: the module info.
1576 %
1577 %    o exception: return any errors or warnings in this structure.
1578 %
1579 */
1580 static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1581   ExceptionInfo *exception)
1582 {
1583   /*
1584     Locate and execute UnregisterFORMATImage module.
1585   */
1586   assert(module_info != (const ModuleInfo *) NULL);
1587   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1588   assert(exception != (ExceptionInfo *) NULL);
1589   if (module_info->unregister_module == NULL)
1590     return(MagickTrue);
1591   module_info->unregister_module();
1592   if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1593     {
1594       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1595         "UnableToCloseModule","'%s': %s",module_info->tag,lt_dlerror());
1596       return(MagickFalse);
1597     }
1598   return(MagickTrue);
1599 }
1600 #else
1601
1602 #if !defined(MAGICKCORE_BUILD_MODULES)
1603 extern size_t
1604   analyzeImage(Image **,const int,const char **,ExceptionInfo *);
1605 #endif
1606
1607 MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1608   ExceptionInfo *magick_unused(exception))
1609 {
1610   return(MagickTrue);
1611 }
1612
1613 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1614   Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1615 {
1616   PolicyRights
1617     rights;
1618
1619   assert(image != (Image **) NULL);
1620   assert((*image)->signature == MagickSignature);
1621   if ((*image)->debug != MagickFalse)
1622     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1623   rights=ReadPolicyRights;
1624   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
1625     {
1626       errno=EPERM;
1627       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1628         "NotAuthorized","`%s'",tag);
1629       return(MagickFalse);
1630     }
1631 #if defined(MAGICKCORE_BUILD_MODULES)
1632   (void) tag;
1633   (void) argc;
1634   (void) argv;
1635   (void) exception;
1636 #else
1637   {
1638     ImageFilterHandler
1639       *image_filter;
1640
1641     image_filter=(ImageFilterHandler *) NULL;
1642     if (LocaleCompare("analyze",tag) == 0)
1643       image_filter=(ImageFilterHandler *) analyzeImage;
1644     if (image_filter == (ImageFilterHandler *) NULL)
1645       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1646         "UnableToLoadModule","`%s'",tag);
1647     else
1648       {
1649         size_t
1650           signature;
1651
1652         if ((*image)->debug != MagickFalse)
1653           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1654             "Invoking \"%s\" static image filter",tag);
1655         signature=image_filter(image,argc,argv,exception);
1656         if ((*image)->debug != MagickFalse)
1657           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
1658             tag);
1659         if (signature != MagickImageFilterSignature)
1660           {
1661             (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1662               "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1663               (unsigned long) signature,(unsigned long)
1664               MagickImageFilterSignature);
1665             return(MagickFalse);
1666           }
1667       }
1668   }
1669 #endif
1670   return(MagickTrue);
1671 }
1672 #endif