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