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