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