]> 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-2012 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,
770         "%s/lib/%s/modules-Q%d/%s/%s",prefix,MAGICKCORE_LIBRARY_RELATIVE_PATH,
771         MAGICKCORE_QUANTUM_DEPTH,directory,filename);
772 #endif
773       if (IsPathAccessible(path) != MagickFalse)
774         return(MagickTrue);
775     }
776 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
777   {
778     /*
779       Search module path.
780     */
781     if ((NTGetModulePath("CORE_RL_magick_.dll",path) != MagickFalse) ||
782         (NTGetModulePath("CORE_DB_magick_.dll",path) != MagickFalse) ||
783         (NTGetModulePath("Magick.dll",path) != MagickFalse))
784       {
785         (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
786         (void) ConcatenateMagickString(path,filename,MaxTextExtent);
787         if (IsPathAccessible(path) != MagickFalse)
788           return(MagickTrue);
789       }
790   }
791 #endif
792   {
793     char
794       *home;
795
796     home=GetEnvironmentValue("HOME");
797     if (home == (char *) NULL)
798       home=GetEnvironmentValue("USERPROFILE");
799     if (home != (char *) NULL)
800       {
801         /*
802           Search $HOME/.magick.
803         */
804         (void) FormatLocaleString(path,MaxTextExtent,"%s%s.magick%s%s",home,
805           DirectorySeparator,DirectorySeparator,filename);
806         home=DestroyString(home);
807         if (IsPathAccessible(path) != MagickFalse)
808           return(MagickTrue);
809       }
810   }
811   /*
812     Search current directory.
813   */
814   if (IsPathAccessible(path) != MagickFalse)
815     return(MagickTrue);
816   if (exception->severity < ConfigureError)
817     ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
818       path);
819   return(MagickFalse);
820 #endif
821   return(MagickFalse);
822 }
823 \f
824 /*
825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
826 %                                                                             %
827 %                                                                             %
828 %                                                                             %
829 %   I n i t i a l i z e M o d u l e L i s t                                   %
830 %                                                                             %
831 %                                                                             %
832 %                                                                             %
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834 %
835 %  InitializeModuleList() initializes the module loader.
836 %
837 %  The format of the InitializeModuleList() method is:
838 %
839 %      InitializeModuleList(Exceptioninfo *exception)
840 %
841 %  A description of each parameter follows.
842 %
843 %    o exception: return any errors or warnings in this structure.
844 %
845 */
846
847 static void *DestroyModuleNode(void *module_info)
848 {
849   ExceptionInfo
850     *exception;
851
852   register ModuleInfo
853     *p;
854
855   exception=AcquireExceptionInfo();
856   p=(ModuleInfo *) module_info;
857   if (UnregisterModule(p,exception) == MagickFalse)
858     CatchException(exception);
859   if (p->tag != (char *) NULL)
860     p->tag=DestroyString(p->tag);
861   if (p->path != (char *) NULL)
862     p->path=DestroyString(p->path);
863   exception=DestroyExceptionInfo(exception);
864   return(RelinquishMagickMemory(p));
865 }
866
867 static MagickBooleanType InitializeModuleList(
868   ExceptionInfo *magick_unused(exception))
869 {
870   if ((module_list == (SplayTreeInfo *) NULL) &&
871       (instantiate_module == MagickFalse))
872     {
873       if (module_semaphore == (SemaphoreInfo *) NULL)
874         AcquireSemaphoreInfo(&module_semaphore);
875       LockSemaphoreInfo(module_semaphore);
876       if ((module_list == (SplayTreeInfo *) NULL) &&
877           (instantiate_module == MagickFalse))
878         {
879           MagickBooleanType
880             status;
881
882           ModuleInfo
883             *module_info;
884
885           module_list=NewSplayTree(CompareSplayTreeString,
886             (void *(*)(void *)) NULL,DestroyModuleNode);
887           if (module_list == (SplayTreeInfo *) NULL)
888             ThrowFatalException(ResourceLimitFatalError,
889               "MemoryAllocationFailed");
890           module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
891           module_info->stealth=MagickTrue;
892           status=AddValueToSplayTree(module_list,module_info->tag,module_info);
893           if (status == MagickFalse)
894             ThrowFatalException(ResourceLimitFatalError,
895               "MemoryAllocationFailed");
896           if (lt_dlinit() != 0)
897             ThrowFatalException(ModuleFatalError,
898               "UnableToInitializeModuleLoader");
899           instantiate_module=MagickTrue;
900         }
901       UnlockSemaphoreInfo(module_semaphore);
902     }
903   return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
904 }
905 \f
906 /*
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 %                                                                             %
909 %                                                                             %
910 %                                                                             %
911 %   I n v o k e D y n a m i c I m a g e F i l t e r                           %
912 %                                                                             %
913 %                                                                             %
914 %                                                                             %
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 %
917 %  InvokeDynamicImageFilter() invokes a dynamic image filter.
918 %
919 %  The format of the InvokeDynamicImageFilter module is:
920 %
921 %      MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
922 %        const int argc,const char **argv,ExceptionInfo *exception)
923 %
924 %  A description of each parameter follows:
925 %
926 %    o tag: a character string that represents the name of the particular
927 %      module.
928 %
929 %    o image: the image.
930 %
931 %    o argc: a pointer to an integer describing the number of elements in the
932 %      argument vector.
933 %
934 %    o argv: a pointer to a text array containing the command line arguments.
935 %
936 %    o exception: return any errors or warnings in this structure.
937 %
938 */
939 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
940   Image **images,const int argc,const char **argv,ExceptionInfo *exception)
941 {
942   char
943     name[MaxTextExtent],
944     path[MaxTextExtent];
945
946   ImageFilterHandler
947     *image_filter;
948
949   MagickBooleanType
950     status;
951
952   ModuleHandle
953     handle;
954
955   PolicyRights
956     rights;
957
958   /*
959     Find the module.
960   */
961   assert(images != (Image **) NULL);
962   assert((*images)->signature == MagickSignature);
963   if ((*images)->debug != MagickFalse)
964     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
965       (*images)->filename);
966 #if !defined(MAGICKCORE_BUILD_MODULES)
967   {
968     MagickBooleanType
969       status;
970
971     status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
972     if (status != MagickFalse)
973       return(status);
974   }
975 #endif
976   rights=ReadPolicyRights;
977   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
978     {
979       errno=EPERM;
980       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
981         "NotAuthorized","'%s'",tag);
982       return(MagickFalse);
983     }
984   TagToFilterModuleName(tag,name);
985   status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
986   if (status == MagickFalse)
987     {
988       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
989         "UnableToLoadModule","'%s': %s",name,path);
990       return(MagickFalse);
991     }
992   /*
993     Open the module.
994   */
995   handle=(ModuleHandle) lt_dlopen(path);
996   if (handle == (ModuleHandle) NULL)
997     {
998       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
999         "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1000       return(MagickFalse);
1001     }
1002   /*
1003     Locate the module.
1004   */
1005 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1006   (void) FormatLocaleString(name,MaxTextExtent,"%sImage",tag);
1007 #else
1008   (void) FormatLocaleString(name,MaxTextExtent,"%s%sImage",
1009     MAGICKCORE_NAMESPACE_PREFIX,tag);
1010 #endif
1011   /*
1012     Execute the module.
1013   */
1014   ClearMagickException(exception);
1015   image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
1016   if (image_filter == (ImageFilterHandler *) NULL)
1017     (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1018       "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1019   else
1020     {
1021       size_t
1022         signature;
1023
1024       if ((*images)->debug != MagickFalse)
1025         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1026           "Invoking \"%s\" dynamic image filter",tag);
1027       signature=image_filter(images,argc,argv,exception);
1028       if ((*images)->debug != MagickFalse)
1029         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1030           tag);
1031       if (signature != MagickImageFilterSignature)
1032         (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1033           "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1034           (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
1035     }
1036   /*
1037     Close the module.
1038   */
1039   if (lt_dlclose(handle) != 0)
1040     (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1041       "UnableToCloseModule","'%s': %s",name,lt_dlerror());
1042   return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
1043 }
1044 \f
1045 /*
1046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1047 %                                                                             %
1048 %                                                                             %
1049 %                                                                             %
1050 %  L i s t M o d u l e I n f o                                                %
1051 %                                                                             %
1052 %                                                                             %
1053 %                                                                             %
1054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1055 %
1056 %  ListModuleInfo() lists the module info to a file.
1057 %
1058 %  The format of the ListModuleInfo module is:
1059 %
1060 %      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1061 %
1062 %  A description of each parameter follows.
1063 %
1064 %    o file:  An pointer to a FILE.
1065 %
1066 %    o exception: return any errors or warnings in this structure.
1067 %
1068 */
1069 MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1070   ExceptionInfo *exception)
1071 {
1072   char
1073     filename[MaxTextExtent],
1074     module_path[MaxTextExtent],
1075     **modules,
1076     path[MaxTextExtent];
1077
1078   register ssize_t
1079     i;
1080
1081   size_t
1082     number_modules;
1083
1084   if (file == (const FILE *) NULL)
1085     file=stdout;
1086   /*
1087     List image coders.
1088   */
1089   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1090   if (modules == (char **) NULL)
1091     return(MagickFalse);
1092   TagToCoderModuleName("magick",filename);
1093   (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
1094     exception);
1095   GetPathComponent(module_path,HeadPath,path);
1096   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1097   (void) FormatLocaleFile(file,"Image Coder\n");
1098   (void) FormatLocaleFile(file,
1099     "-------------------------------------------------"
1100     "------------------------------\n");
1101   for (i=0; i < (ssize_t) number_modules; i++)
1102   {
1103     (void) FormatLocaleFile(file,"%s",modules[i]);
1104     (void) FormatLocaleFile(file,"\n");
1105   }
1106   (void) fflush(file);
1107   /*
1108     Relinquish resources.
1109   */
1110   for (i=0; i < (ssize_t) number_modules; i++)
1111     modules[i]=DestroyString(modules[i]);
1112   modules=(char **) RelinquishMagickMemory(modules);
1113   /*
1114     List image filters.
1115   */
1116   modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
1117   if (modules == (char **) NULL)
1118     return(MagickFalse);
1119   TagToFilterModuleName("analyze",filename);
1120   (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
1121     exception);
1122   GetPathComponent(module_path,HeadPath,path);
1123   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1124   (void) FormatLocaleFile(file,"Image Filter\n");
1125   (void) FormatLocaleFile(file,
1126     "-------------------------------------------------"
1127     "------------------------------\n");
1128   for (i=0; i < (ssize_t) number_modules; i++)
1129   {
1130     (void) FormatLocaleFile(file,"%s",modules[i]);
1131     (void) FormatLocaleFile(file,"\n");
1132   }
1133   (void) fflush(file);
1134   /*
1135     Relinquish resources.
1136   */
1137   for (i=0; i < (ssize_t) number_modules; i++)
1138     modules[i]=DestroyString(modules[i]);
1139   modules=(char **) RelinquishMagickMemory(modules);
1140   return(MagickTrue);
1141 }
1142 \f
1143 /*
1144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1145 %                                                                             %
1146 %                                                                             %
1147 %                                                                             %
1148 +   M o d u l e C o m p o n e n t G e n e s i s                               %
1149 %                                                                             %
1150 %                                                                             %
1151 %                                                                             %
1152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1153 %
1154 %  ModuleComponentGenesis() instantiates the module component.
1155 %
1156 %  The format of the ModuleComponentGenesis method is:
1157 %
1158 %      MagickBooleanType ModuleComponentGenesis(void)
1159 %
1160 */
1161 MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
1162 {
1163   ExceptionInfo
1164     *exception;
1165
1166   MagickBooleanType
1167     status;
1168
1169   AcquireSemaphoreInfo(&module_semaphore);
1170   exception=AcquireExceptionInfo();
1171   status=InitializeModuleList(exception);
1172   exception=DestroyExceptionInfo(exception);
1173   return(status);
1174 }
1175 \f
1176 /*
1177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1178 %                                                                             %
1179 %                                                                             %
1180 %                                                                             %
1181 +   M o d u l e C o m p o n e n t T e r m i n u s                             %
1182 %                                                                             %
1183 %                                                                             %
1184 %                                                                             %
1185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1186 %
1187 %  ModuleComponentTerminus() destroys the module component.
1188 %
1189 %  The format of the ModuleComponentTerminus method is:
1190 %
1191 %      ModuleComponentTerminus(void)
1192 %
1193 */
1194 MagickPrivate void ModuleComponentTerminus(void)
1195 {
1196   if (module_semaphore == (SemaphoreInfo *) NULL)
1197     AcquireSemaphoreInfo(&module_semaphore);
1198   DestroyModuleList();
1199   DestroySemaphoreInfo(&module_semaphore);
1200 }
1201 \f
1202 /*
1203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1204 %                                                                             %
1205 %                                                                             %
1206 %                                                                             %
1207 %   O p e n M o d u l e                                                       %
1208 %                                                                             %
1209 %                                                                             %
1210 %                                                                             %
1211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1212 %
1213 %  OpenModule() loads a module, and invokes its registration module.  It
1214 %  returns MagickTrue on success, and MagickFalse if there is an error.
1215 %
1216 %  The format of the OpenModule module is:
1217 %
1218 %      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1219 %
1220 %  A description of each parameter follows:
1221 %
1222 %    o module: a character string that indicates the module to load.
1223 %
1224 %    o exception: return any errors or warnings in this structure.
1225 %
1226 */
1227 MagickPrivate MagickBooleanType OpenModule(const char *module,
1228   ExceptionInfo *exception)
1229 {
1230   char
1231     filename[MaxTextExtent],
1232     module_name[MaxTextExtent],
1233     name[MaxTextExtent],
1234     path[MaxTextExtent];
1235
1236   MagickBooleanType
1237     status;
1238
1239   ModuleHandle
1240     handle;
1241
1242   ModuleInfo
1243     *module_info;
1244
1245   register const CoderInfo
1246     *p;
1247
1248   size_t
1249     signature;
1250
1251   /*
1252     Assign module name from alias.
1253   */
1254   assert(module != (const char *) NULL);
1255   module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1256   if (module_info != (ModuleInfo *) NULL)
1257     return(MagickTrue);
1258   (void) CopyMagickString(module_name,module,MaxTextExtent);
1259   p=GetCoderInfo(module,exception);
1260   if (p != (CoderInfo *) NULL)
1261     (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1262   if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1263     return(MagickTrue);  /* module already opened, return */
1264   /*
1265     Locate module.
1266   */
1267   handle=(ModuleHandle) NULL;
1268   TagToCoderModuleName(module_name,filename);
1269   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1270     "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1271   *path='\0';
1272   status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1273   if (status == MagickFalse)
1274     return(MagickFalse);
1275   /*
1276     Load module
1277   */
1278   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1279     "Opening module at path \"%s\"",path);
1280   handle=(ModuleHandle) lt_dlopen(path);
1281   if (handle == (ModuleHandle) NULL)
1282     {
1283       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1284         "UnableToLoadModule","'%s': %s",path,lt_dlerror());
1285       return(MagickFalse);
1286     }
1287   /*
1288     Register module.
1289   */
1290   module_info=AcquireModuleInfo(path,module_name);
1291   module_info->handle=handle;
1292   if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1293     return(MagickFalse);
1294   /*
1295     Define RegisterFORMATImage method.
1296   */
1297   TagToModuleName(module_name,"Register%sImage",name);
1298   module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1299   if (module_info->register_module == (size_t (*)(void)) NULL)
1300     {
1301       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1302         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1303       return(MagickFalse);
1304     }
1305   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1306     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1307     (void *) module_info->register_module);
1308   /*
1309     Define UnregisterFORMATImage method.
1310   */
1311   TagToModuleName(module_name,"Unregister%sImage",name);
1312   module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1313   if (module_info->unregister_module == (void (*)(void)) NULL)
1314     {
1315       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1316         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1317       return(MagickFalse);
1318     }
1319   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1320     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1321     (void *) module_info->unregister_module);
1322   signature=module_info->register_module();
1323   if (signature != MagickImageCoderSignature)
1324     {
1325       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1326         "ImageCoderSignatureMismatch","'%s': %8lx != %8lx",module_name,
1327         (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
1328       return(MagickFalse);
1329     }
1330   return(MagickTrue);
1331 }
1332 \f
1333 /*
1334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335 %                                                                             %
1336 %                                                                             %
1337 %                                                                             %
1338 %   O p e n M o d u l e s                                                     %
1339 %                                                                             %
1340 %                                                                             %
1341 %                                                                             %
1342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1343 %
1344 %  OpenModules() loads all available modules.
1345 %
1346 %  The format of the OpenModules module is:
1347 %
1348 %      MagickBooleanType OpenModules(ExceptionInfo *exception)
1349 %
1350 %  A description of each parameter follows:
1351 %
1352 %    o exception: return any errors or warnings in this structure.
1353 %
1354 */
1355 MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
1356 {
1357   char
1358     **modules;
1359
1360   register ssize_t
1361     i;
1362
1363   size_t
1364     number_modules;
1365
1366   /*
1367     Load all modules.
1368   */
1369   (void) GetMagickInfo((char *) NULL,exception);
1370   number_modules=0;
1371   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1372   if (modules == (char **) NULL)
1373     return(MagickFalse);
1374   for (i=0; i < (ssize_t) number_modules; i++)
1375     (void) OpenModule(modules[i],exception);
1376   /*
1377     Relinquish resources.
1378   */
1379   for (i=0; i < (ssize_t) number_modules; i++)
1380     modules[i]=DestroyString(modules[i]);
1381   modules=(char **) RelinquishMagickMemory(modules);
1382   return(MagickTrue);
1383 }
1384 \f
1385 /*
1386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387 %                                                                             %
1388 %                                                                             %
1389 %                                                                             %
1390 %   R e g i s t e r M o d u l e                                               %
1391 %                                                                             %
1392 %                                                                             %
1393 %                                                                             %
1394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395 %
1396 %  RegisterModule() adds an entry to the module list.  It returns a pointer to
1397 %  the registered entry on success.
1398 %
1399 %  The format of the RegisterModule module is:
1400 %
1401 %      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1402 %        ExceptionInfo *exception)
1403 %
1404 %  A description of each parameter follows:
1405 %
1406 %    o info: a pointer to the registered entry is returned.
1407 %
1408 %    o module_info: a pointer to the ModuleInfo structure to register.
1409 %
1410 %    o exception: return any errors or warnings in this structure.
1411 %
1412 */
1413 static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1414   ExceptionInfo *exception)
1415 {
1416   MagickBooleanType
1417     status;
1418
1419   assert(module_info != (ModuleInfo *) NULL);
1420   assert(module_info->signature == MagickSignature);
1421   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1422   if (module_list == (SplayTreeInfo *) NULL)
1423     return((const ModuleInfo *) NULL);
1424   status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1425   if (status == MagickFalse)
1426     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1427       "MemoryAllocationFailed","'%s'",module_info->tag);
1428   return(module_info);
1429 }
1430 \f
1431 /*
1432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433 %                                                                             %
1434 %                                                                             %
1435 %                                                                             %
1436 %  T a g T o C o d e r M o d u l e N a m e                                    %
1437 %                                                                             %
1438 %                                                                             %
1439 %                                                                             %
1440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441 %
1442 %  TagToCoderModuleName() munges a module tag and obtains the filename of the
1443 %  corresponding module.
1444 %
1445 %  The format of the TagToCoderModuleName module is:
1446 %
1447 %      char *TagToCoderModuleName(const char *tag,char *name)
1448 %
1449 %  A description of each parameter follows:
1450 %
1451 %    o tag: a character string representing the module tag.
1452 %
1453 %    o name: return the module name here.
1454 %
1455 */
1456 static void TagToCoderModuleName(const char *tag,char *name)
1457 {
1458   assert(tag != (char *) NULL);
1459   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1460   assert(name != (char *) NULL);
1461 #if defined(MAGICKCORE_LTDL_DELEGATE)
1462   (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
1463   (void) LocaleLower(name);
1464 #else
1465 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1466   if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1467     (void) CopyMagickString(name,tag,MaxTextExtent);
1468   else
1469     {
1470 #if defined(_DEBUG)
1471       (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
1472 #else
1473       (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
1474 #endif
1475     }
1476 #endif
1477 #endif
1478 }
1479 \f
1480 /*
1481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1482 %                                                                             %
1483 %                                                                             %
1484 %                                                                             %
1485 %  T a g T o F i l t e r M o d u l e N a m e                                  %
1486 %                                                                             %
1487 %                                                                             %
1488 %                                                                             %
1489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1490 %
1491 %  TagToFilterModuleName() munges a module tag and returns the filename of the
1492 %  corresponding filter module.
1493 %
1494 %  The format of the TagToFilterModuleName module is:
1495 %
1496 %      void TagToFilterModuleName(const char *tag,char name)
1497 %
1498 %  A description of each parameter follows:
1499 %
1500 %    o tag: a character string representing the module tag.
1501 %
1502 %    o name: return the filter name here.
1503 %
1504 */
1505 static void TagToFilterModuleName(const char *tag,char *name)
1506 {
1507   assert(tag != (char *) NULL);
1508   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1509   assert(name != (char *) NULL);
1510 #if !defined(MAGICKCORE_LTDL_DELEGATE)
1511   (void) FormatLocaleString(name,MaxTextExtent,"%s.dll",tag);
1512 #else
1513   (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
1514 #endif
1515 }
1516 \f
1517 /*
1518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1519 %                                                                             %
1520 %                                                                             %
1521 %                                                                             %
1522 %   T a g T o M o d u l e N a m e                                             %
1523 %                                                                             %
1524 %                                                                             %
1525 %                                                                             %
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 %
1528 %  TagToModuleName() munges the module tag name and returns an upper-case tag
1529 %  name as the input string, and a user-provided format.
1530 %
1531 %  The format of the TagToModuleName module is:
1532 %
1533 %      TagToModuleName(const char *tag,const char *format,char *module)
1534 %
1535 %  A description of each parameter follows:
1536 %
1537 %    o tag: the module tag.
1538 %
1539 %    o format: a sprintf-compatible format string containing %s where the
1540 %      upper-case tag name is to be inserted.
1541 %
1542 %    o module: pointer to a destination buffer for the formatted result.
1543 %
1544 */
1545 static void TagToModuleName(const char *tag,const char *format,char *module)
1546 {
1547   char
1548     name[MaxTextExtent];
1549
1550   assert(tag != (const char *) NULL);
1551   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1552   assert(format != (const char *) NULL);
1553   assert(module != (char *) NULL);
1554   (void) CopyMagickString(name,tag,MaxTextExtent);
1555   LocaleUpper(name);
1556 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1557   (void) FormatLocaleString(module,MaxTextExtent,format,name);
1558 #else
1559   {
1560     char
1561       prefix_format[MaxTextExtent];
1562
1563     (void) FormatLocaleString(prefix_format,MaxTextExtent,"%s%s",
1564       MAGICKCORE_NAMESPACE_PREFIX,format);
1565     (void) FormatLocaleString(module,MaxTextExtent,prefix_format,name);
1566   }
1567 #endif
1568 }
1569 \f
1570 /*
1571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1572 %                                                                             %
1573 %                                                                             %
1574 %                                                                             %
1575 %   U n r e g i s t e r M o d u l e                                           %
1576 %                                                                             %
1577 %                                                                             %
1578 %                                                                             %
1579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1580 %
1581 %  UnregisterModule() unloads a module, and invokes its de-registration module.
1582 %  Returns MagickTrue on success, and MagickFalse if there is an error.
1583 %
1584 %  The format of the UnregisterModule module is:
1585 %
1586 %      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1587 %        ExceptionInfo *exception)
1588 %
1589 %  A description of each parameter follows:
1590 %
1591 %    o module_info: the module info.
1592 %
1593 %    o exception: return any errors or warnings in this structure.
1594 %
1595 */
1596 static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1597   ExceptionInfo *exception)
1598 {
1599   /*
1600     Locate and execute UnregisterFORMATImage module.
1601   */
1602   assert(module_info != (const ModuleInfo *) NULL);
1603   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1604   assert(exception != (ExceptionInfo *) NULL);
1605   if (module_info->unregister_module == NULL)
1606     return(MagickTrue);
1607   module_info->unregister_module();
1608   if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1609     {
1610       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1611         "UnableToCloseModule","'%s': %s",module_info->tag,lt_dlerror());
1612       return(MagickFalse);
1613     }
1614   return(MagickTrue);
1615 }
1616 #else
1617 MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1618   ExceptionInfo *magick_unused(exception))
1619 {
1620   return(MagickTrue);
1621 }
1622
1623 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1624   Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1625 {
1626   PolicyRights
1627     rights;
1628
1629   assert(image != (Image **) NULL);
1630   assert((*image)->signature == MagickSignature);
1631   if ((*image)->debug != MagickFalse)
1632     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1633   rights=ReadPolicyRights;
1634   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
1635     {
1636       errno=EPERM;
1637       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1638         "NotAuthorized","'%s'",tag);
1639       return(MagickFalse);
1640     }
1641 #if defined(MAGICKCORE_BUILD_MODULES)
1642   (void) tag;
1643   (void) argc;
1644   (void) argv;
1645   (void) exception;
1646 #else
1647   {
1648     extern size_t
1649       analyzeImage(Image **,const int,const char **,ExceptionInfo *);
1650
1651     ImageFilterHandler
1652       *image_filter;
1653
1654     image_filter=(ImageFilterHandler *) NULL;
1655     if (LocaleCompare("analyze",tag) == 0)
1656       image_filter=(ImageFilterHandler *) analyzeImage;
1657     if (image_filter == (ImageFilterHandler *) NULL)
1658       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1659         "UnableToLoadModule","'%s'",tag);
1660     else
1661       {
1662         size_t
1663           signature;
1664
1665         if ((*image)->debug != MagickFalse)
1666           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1667             "Invoking \"%s\" static image filter",tag);
1668         signature=image_filter(image,argc,argv,exception);
1669         if ((*image)->debug != MagickFalse)
1670           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
1671             tag);
1672         if (signature != MagickImageFilterSignature)
1673           {
1674             (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1675               "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1676               (unsigned long) signature,(unsigned long)
1677               MagickImageFilterSignature);
1678             return(MagickFalse);
1679           }
1680       }
1681   }
1682 #endif
1683   return(MagickTrue);
1684 }
1685 #endif