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