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