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