]> granicus.if.org Git - imagemagick/blob - magick/module.c
1a88e503193f4bdba915e414b2a6f802986c22de
[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(__WINDOWS__)
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(__WINDOWS__)
677 # error MAGICKCORE_CODER_PATH or __WINDOWS__ 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(__WINDOWS__)
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   image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
992   if (image_filter == (ImageFilterHandler *) NULL)
993     (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
994       "UnableToLoadModule","`%s': %s",name,lt_dlerror());
995   else
996     {
997       unsigned long
998         signature;
999
1000       if ((*images)->debug != MagickFalse)
1001         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1002           "Invoking \"%s\" dynamic image filter",tag);
1003       signature=image_filter(images,argc,argv,exception);
1004       if ((*images)->debug != MagickFalse)
1005         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1006           tag);
1007       if (signature != MagickImageFilterSignature)
1008         {
1009           (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1010             "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,signature,
1011             MagickImageFilterSignature);
1012           return(MagickFalse);
1013         }
1014     }
1015   /*
1016     Close the module.
1017   */
1018   if (lt_dlclose(handle) != 0)
1019     {
1020       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1021         "UnableToCloseModule","`%s': %s",name,lt_dlerror());
1022       return(MagickFalse);
1023     }
1024   return(MagickTrue);
1025 }
1026 \f
1027 /*
1028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029 %                                                                             %
1030 %                                                                             %
1031 %                                                                             %
1032 %  L i s t M o d u l e I n f o                                                %
1033 %                                                                             %
1034 %                                                                             %
1035 %                                                                             %
1036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037 %
1038 %  ListModuleInfo() lists the module info to a file.
1039 %
1040 %  The format of the ListModuleInfo module is:
1041 %
1042 %      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1043 %
1044 %  A description of each parameter follows.
1045 %
1046 %    o file:  An pointer to a FILE.
1047 %
1048 %    o exception: return any errors or warnings in this structure.
1049 %
1050 */
1051 MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1052   ExceptionInfo *exception)
1053 {
1054   const ModuleInfo
1055     **module_info;
1056
1057   register long
1058     i;
1059
1060   unsigned long
1061     number_modules;
1062
1063   if (file == (const FILE *) NULL)
1064     file=stdout;
1065   module_info=GetModuleInfoList("*",&number_modules,exception);
1066   if (module_info == (const ModuleInfo **) NULL)
1067     return(MagickFalse);
1068   if (module_info[0]->path != (char *) NULL)
1069     {
1070       char
1071         path[MaxTextExtent];
1072
1073       GetPathComponent(module_info[0]->path,HeadPath,path);
1074       (void) fprintf(file,"\nPath: %s\n\n",path);
1075     }
1076   (void) fprintf(file,"Module\n");
1077   (void) fprintf(file,"-------------------------------------------------"
1078     "------------------------------\n");
1079   for (i=0; i < (long) number_modules; i++)
1080   {
1081     if (module_info[i]->stealth != MagickFalse)
1082       continue;
1083     (void) fprintf(file,"%s",module_info[i]->tag);
1084     (void) fprintf(file,"\n");
1085   }
1086   (void) fflush(file);
1087   module_info=(const ModuleInfo **)
1088     RelinquishMagickMemory((void *) module_info);
1089   return(MagickTrue);
1090 }
1091 \f
1092 /*
1093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1094 %                                                                             %
1095 %                                                                             %
1096 %                                                                             %
1097 +   M o d u l e C o m p o n e n t G e n e s i s                               %
1098 %                                                                             %
1099 %                                                                             %
1100 %                                                                             %
1101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1102 %
1103 %  ModuleComponentGenesis() instantiates the module component.
1104 %
1105 %  The format of the ModuleComponentGenesis method is:
1106 %
1107 %      MagickBooleanType ModuleComponentGenesis(void)
1108 %
1109 */
1110 MagickExport MagickBooleanType ModuleComponentGenesis(void)
1111 {
1112   ExceptionInfo
1113     *exception;
1114
1115   AcquireSemaphoreInfo(&module_semaphore);
1116   exception=AcquireExceptionInfo();
1117   InitializeModuleList(exception);
1118   exception=DestroyExceptionInfo(exception);
1119   return(MagickTrue);
1120 }
1121 \f
1122 /*
1123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1124 %                                                                             %
1125 %                                                                             %
1126 %                                                                             %
1127 +   M o d u l e C o m p o n e n t T e r m i n u s                             %
1128 %                                                                             %
1129 %                                                                             %
1130 %                                                                             %
1131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132 %
1133 %  ModuleComponentTerminus() destroys the module component.
1134 %
1135 %  The format of the ModuleComponentTerminus method is:
1136 %
1137 %      ModuleComponentTerminus(void)
1138 %
1139 */
1140 MagickExport void ModuleComponentTerminus(void)
1141 {
1142   if (module_semaphore == (SemaphoreInfo *) NULL)
1143     AcquireSemaphoreInfo(&module_semaphore);
1144   DestroyModuleList();
1145   DestroySemaphoreInfo(&module_semaphore);
1146 }
1147 \f
1148 /*
1149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1150 %                                                                             %
1151 %                                                                             %
1152 %                                                                             %
1153 %   O p e n M o d u l e                                                       %
1154 %                                                                             %
1155 %                                                                             %
1156 %                                                                             %
1157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1158 %
1159 %  OpenModule() loads a module, and invokes its registration module.  It
1160 %  returns MagickTrue on success, and MagickFalse if there is an error.
1161 %
1162 %  The format of the OpenModule module is:
1163 %
1164 %      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1165 %
1166 %  A description of each parameter follows:
1167 %
1168 %    o module: a character string that indicates the module to load.
1169 %
1170 %    o exception: return any errors or warnings in this structure.
1171 %
1172 */
1173 MagickExport MagickBooleanType OpenModule(const char *module,
1174   ExceptionInfo *exception)
1175 {
1176   char
1177     filename[MaxTextExtent],
1178     module_name[MaxTextExtent],
1179     name[MaxTextExtent],
1180     path[MaxTextExtent];
1181
1182   ModuleHandle
1183     handle;
1184
1185   ModuleInfo
1186     *module_info;
1187
1188   register const CoderInfo
1189     *p;
1190
1191   size_t
1192     length;
1193
1194   unsigned long
1195     signature;
1196
1197   /*
1198     Assign module name from alias.
1199   */
1200   assert(module != (const char *) NULL);
1201   module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1202   if (module_info != (ModuleInfo *) NULL)
1203     return(MagickTrue);
1204   (void) CopyMagickString(module_name,module,MaxTextExtent);
1205   p=GetCoderInfo(module,exception);
1206   if (p != (CoderInfo *) NULL)
1207     (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1208   if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1209     return(MagickTrue);  /* module already opened, return */
1210   /*
1211     Locate module.
1212   */
1213   handle=(ModuleHandle) NULL;
1214   TagToCoderModuleName(module_name,filename);
1215   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1216     "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1217   *path='\0';
1218   length=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1219   if (length == 0)
1220     return(MagickFalse);
1221   /*
1222     Load module
1223   */
1224   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1225     "Opening module at path \"%s\"",path);
1226   handle=(ModuleHandle) lt_dlopen(path);
1227   if (handle == (ModuleHandle) NULL)
1228     {
1229       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1230         "UnableToLoadModule","`%s': %s",path,lt_dlerror());
1231       return(MagickFalse);
1232     }
1233   /*
1234     Register module.
1235   */
1236   module_info=AcquireModuleInfo(path,module_name);
1237   module_info->handle=handle;
1238   if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1239     return(MagickFalse);
1240   /*
1241     Define RegisterFORMATImage method.
1242   */
1243   TagToModuleName(module_name,"Register%sImage",name);
1244   module_info->register_module=(unsigned long (*)(void)) lt_dlsym(handle,name);
1245   if (module_info->register_module == (unsigned long (*)(void)) NULL)
1246     {
1247       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1248         "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1249       return(MagickFalse);
1250     }
1251   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1252     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1253     (void *) module_info->register_module);
1254   /*
1255     Define UnregisterFORMATImage method.
1256   */
1257   TagToModuleName(module_name,"Unregister%sImage",name);
1258   module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1259   if (module_info->unregister_module == (void (*)(void)) NULL)
1260     {
1261       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1262         "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1263       return(MagickFalse);
1264     }
1265   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1266     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1267     (void *) module_info->unregister_module);
1268   signature=module_info->register_module();
1269   if (signature != MagickImageCoderSignature)
1270     {
1271       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1272         "ImageCoderSignatureMismatch","`%s': %8lx != %8lx",module_name,
1273         signature,MagickImageCoderSignature);
1274       return(MagickFalse);
1275     }
1276   return(MagickTrue);
1277 }
1278 \f
1279 /*
1280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1281 %                                                                             %
1282 %                                                                             %
1283 %                                                                             %
1284 %   O p e n M o d u l e s                                                     %
1285 %                                                                             %
1286 %                                                                             %
1287 %                                                                             %
1288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1289 %
1290 %  OpenModules() loads all available modules.
1291 %
1292 %  The format of the OpenModules module is:
1293 %
1294 %      MagickBooleanType OpenModules(ExceptionInfo *exception)
1295 %
1296 %  A description of each parameter follows:
1297 %
1298 %    o exception: return any errors or warnings in this structure.
1299 %
1300 */
1301 MagickExport MagickBooleanType OpenModules(ExceptionInfo *exception)
1302 {
1303   char
1304     **modules;
1305
1306   register long
1307     i;
1308
1309   unsigned long
1310     number_modules;
1311
1312   /*
1313     Load all modules.
1314   */
1315   (void) GetMagickInfo((char *) NULL,exception);
1316   number_modules=0;
1317   modules=GetModuleList("*",&number_modules,exception);
1318   if (modules == (char **) NULL)
1319     return(MagickFalse);
1320   for (i=0; i < (long) number_modules; i++)
1321     (void) OpenModule(modules[i],exception);
1322   /*
1323     Relinquish resources.
1324   */
1325   for (i=0; i < (long) number_modules; i++)
1326     modules[i]=DestroyString(modules[i]);
1327   modules=(char **) RelinquishMagickMemory(modules);
1328   return(MagickTrue);
1329 }
1330 \f
1331 /*
1332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1333 %                                                                             %
1334 %                                                                             %
1335 %                                                                             %
1336 %   R e g i s t e r M o d u l e                                               %
1337 %                                                                             %
1338 %                                                                             %
1339 %                                                                             %
1340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341 %
1342 %  RegisterModule() adds an entry to the module list.  It returns a pointer to
1343 %  the registered entry on success.
1344 %
1345 %  The format of the RegisterModule module is:
1346 %
1347 %      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1348 %        ExceptionInfo *exception)
1349 %
1350 %  A description of each parameter follows:
1351 %
1352 %    o info: a pointer to the registered entry is returned.
1353 %
1354 %    o module_info: a pointer to the ModuleInfo structure to register.
1355 %
1356 %    o exception: return any errors or warnings in this structure.
1357 %
1358 */
1359 static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1360   ExceptionInfo *exception)
1361 {
1362   MagickBooleanType
1363     status;
1364
1365   assert(module_info != (ModuleInfo *) NULL);
1366   assert(module_info->signature == MagickSignature);
1367   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1368   if (module_list == (SplayTreeInfo *) NULL)
1369     return((const ModuleInfo *) NULL);
1370   status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1371   if (status == MagickFalse)
1372     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1373       "MemoryAllocationFailed","`%s'",module_info->tag);
1374   return(module_info);
1375 }
1376 \f
1377 /*
1378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379 %                                                                             %
1380 %                                                                             %
1381 %                                                                             %
1382 %  T a g T o C o d e r M o d u l e N a m e                                    %
1383 %                                                                             %
1384 %                                                                             %
1385 %                                                                             %
1386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387 %
1388 %  TagToCoderModuleName() munges a module tag and obtains the filename of the
1389 %  corresponding module.
1390 %
1391 %  The format of the TagToCoderModuleName module is:
1392 %
1393 %      char *TagToCoderModuleName(const char *tag,char *name)
1394 %
1395 %  A description of each parameter follows:
1396 %
1397 %    o tag: a character string representing the module tag.
1398 %
1399 %    o name: return the module name here.
1400 %
1401 */
1402 static void TagToCoderModuleName(const char *tag,char *name)
1403 {
1404   assert(tag != (char *) NULL);
1405   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1406   assert(name != (char *) NULL);
1407 #if defined(MAGICKCORE_LTDL_DELEGATE)
1408   (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
1409   (void) LocaleLower(name);
1410 #else
1411 #if defined(__WINDOWS__)
1412   if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1413     (void) CopyMagickString(name,tag,MaxTextExtent);
1414   else
1415     {
1416 #if defined(_DEBUG)
1417       (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
1418 #else
1419       (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
1420 #endif
1421     }
1422 #endif
1423 #endif
1424 }
1425 \f
1426 /*
1427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428 %                                                                             %
1429 %                                                                             %
1430 %                                                                             %
1431 %  T a g T o F i l t e r M o d u l e N a m e                                  %
1432 %                                                                             %
1433 %                                                                             %
1434 %                                                                             %
1435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 %
1437 %  TagToFilterModuleName() munges a module tag and returns the filename of the
1438 %  corresponding filter module.
1439 %
1440 %  The format of the TagToFilterModuleName module is:
1441 %
1442 %      void TagToFilterModuleName(const char *tag,char name)
1443 %
1444 %  A description of each parameter follows:
1445 %
1446 %    o tag: a character string representing the module tag.
1447 %
1448 %    o name: return the filter name here.
1449 %
1450 */
1451 static void TagToFilterModuleName(const char *tag,char *name)
1452 {
1453   assert(tag != (char *) NULL);
1454   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1455   assert(name != (char *) NULL);
1456 #if !defined(MAGICKCORE_LTDL_DELEGATE)
1457   (void) FormatMagickString(name,MaxTextExtent,"%s.dll",tag);
1458 #else
1459   (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
1460   (void) LocaleLower(name);
1461 #endif
1462 }
1463 \f
1464 /*
1465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466 %                                                                             %
1467 %                                                                             %
1468 %                                                                             %
1469 %   T a g T o M o d u l e N a m e                                             %
1470 %                                                                             %
1471 %                                                                             %
1472 %                                                                             %
1473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474 %
1475 %  TagToModuleName() munges the module tag name and returns an upper-case tag
1476 %  name as the input string, and a user-provided format.
1477 %
1478 %  The format of the TagToModuleName module is:
1479 %
1480 %      TagToModuleName(const char *tag,const char *format,char *module)
1481 %
1482 %  A description of each parameter follows:
1483 %
1484 %    o tag: the module tag.
1485 %
1486 %    o format: a sprintf-compatible format string containing %s where the
1487 %      upper-case tag name is to be inserted.
1488 %
1489 %    o module: pointer to a destination buffer for the formatted result.
1490 %
1491 */
1492 static void TagToModuleName(const char *tag,const char *format,char *module)
1493 {
1494   char
1495     name[MaxTextExtent];
1496
1497   assert(tag != (const char *) NULL);
1498   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1499   assert(format != (const char *) NULL);
1500   assert(module != (char *) NULL);
1501   (void) CopyMagickString(name,tag,MaxTextExtent);
1502   LocaleUpper(name);
1503 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1504   (void) FormatMagickString(module,MaxTextExtent,format,name);
1505 #else
1506   {
1507     char
1508       prefix_format[MaxTextExtent];
1509
1510     (void) FormatMagickString(prefix_format,MaxTextExtent,"%s%s",
1511       MAGICKCORE_NAMESPACE_PREFIX,format);
1512     (void) FormatMagickString(module,MaxTextExtent,prefix_format,name);
1513   }
1514 #endif
1515 }
1516 \f
1517 /*
1518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1519 %                                                                             %
1520 %                                                                             %
1521 %                                                                             %
1522 %   U n r e g i s t e r M o d u l e                                           %
1523 %                                                                             %
1524 %                                                                             %
1525 %                                                                             %
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 %
1528 %  UnregisterModule() unloads a module, and invokes its de-registration module.
1529 %  Returns MagickTrue on success, and MagickFalse if there is an error.
1530 %
1531 %  The format of the UnregisterModule module is:
1532 %
1533 %      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1534 %        ExceptionInfo *exception)
1535 %
1536 %  A description of each parameter follows:
1537 %
1538 %    o module_info: the module info.
1539 %
1540 %    o exception: return any errors or warnings in this structure.
1541 %
1542 */
1543 static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1544   ExceptionInfo *exception)
1545 {
1546   /*
1547     Locate and execute UnregisterFORMATImage module.
1548   */
1549   assert(module_info != (const ModuleInfo *) NULL);
1550   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1551   assert(exception != (ExceptionInfo *) NULL);
1552   if (module_info->unregister_module == NULL)
1553     return(MagickTrue);
1554   module_info->unregister_module();
1555   if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1556     {
1557       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1558         "UnableToCloseModule","`%s': %s",module_info->tag,lt_dlerror());
1559       return(MagickFalse);
1560     }
1561   return(MagickTrue);
1562 }
1563 #else
1564 MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1565   ExceptionInfo *magick_unused(exception))
1566 {
1567   return(MagickTrue);
1568 }
1569
1570 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1571   Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1572 {
1573 #if !defined(MAGICKCORE_BUILD_MODULES)
1574   {
1575     extern unsigned long
1576       analyzeImage(Image **,const int,const char **,ExceptionInfo *),
1577       convolveImage(Image **,const int,const char **,ExceptionInfo *);
1578
1579     ImageFilterHandler
1580       *image_filter;
1581
1582     image_filter=(ImageFilterHandler *) NULL;
1583     if (LocaleCompare("analyze",tag) == 0)
1584       image_filter=analyzeImage;
1585     if (LocaleCompare("convolve",tag) == 0)
1586       image_filter=convolveImage;
1587     if (image_filter != (ImageFilterHandler *) NULL)
1588       {
1589         unsigned long
1590           signature;
1591
1592         signature=image_filter(image,argc,argv,exception);
1593         if (signature != MagickImageFilterSignature)
1594           {
1595             (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1596               "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,signature,
1597               MagickImageFilterSignature);
1598             return(MagickFalse);
1599           }
1600       }
1601   }
1602 #endif
1603   return(MagickTrue);
1604 }
1605 #endif