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