nt-base.c revision c56b56a57ca7159568e8d60b987dee51f5b6f438
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                                 N   N  TTTTT                                %
7%                                 NN  N    T                                  %
8%                                 N N N    T                                  %
9%                                 N  NN    T                                  %
10%                                 N   N    T                                  %
11%                                                                             %
12%                                                                             %
13%                   Windows NT Utility Methods for MagickCore                 %
14%                                                                             %
15%                               Software Design                               %
16%                                    Cristy                                   %
17%                                December 1996                                %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2016 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  Include declarations.
40*/
41#include "MagickCore/studio.h"
42#if defined(MAGICKCORE_WINDOWS_SUPPORT)
43#include "MagickCore/client.h"
44#include "MagickCore/exception-private.h"
45#include "MagickCore/locale_.h"
46#include "MagickCore/log.h"
47#include "MagickCore/magick.h"
48#include "MagickCore/memory_.h"
49#include "MagickCore/nt-base.h"
50#include "MagickCore/nt-base-private.h"
51#include "MagickCore/resource_.h"
52#include "MagickCore/resource-private.h"
53#include "MagickCore/timer.h"
54#include "MagickCore/string_.h"
55#include "MagickCore/string-private.h"
56#include "MagickCore/utility.h"
57#include "MagickCore/utility-private.h"
58#include "MagickCore/version.h"
59#if defined(MAGICKCORE_LTDL_DELEGATE)
60#  include "ltdl.h"
61#endif
62#if defined(MAGICKCORE_CIPHER_SUPPORT)
63#include <ntsecapi.h>
64#include <wincrypt.h>
65#endif
66
67/*
68  Define declarations.
69*/
70#if !defined(MAP_FAILED)
71#define MAP_FAILED      ((void *)(LONG_PTR)-1)
72#endif
73
74/*
75  Typdef declarations.
76*/
77
78/*
79  We need to make sure only one instance is created for each process and that
80  is why we wrap the new/delete instance methods.
81
82  From: http://www.ghostscript.com/doc/current/API.htm
83  "The Win32 DLL gsdll32.dll can be used by multiple programs simultaneously,
84   but only once within each process"
85*/
86typedef struct _NTGhostInfo
87{
88  void
89    (MagickDLLCall *delete_instance)(gs_main_instance *);
90
91  int
92    (MagickDLLCall *new_instance)(gs_main_instance **,void *);
93
94  MagickBooleanType
95    has_instance;
96} NTGhostInfo;
97
98/*
99  Static declarations.
100*/
101#if !defined(MAGICKCORE_LTDL_DELEGATE)
102static char
103  *lt_slsearchpath = (char *) NULL;
104#endif
105
106static NTGhostInfo
107  nt_ghost_info;
108
109static GhostInfo
110  ghost_info;
111
112static void
113  *ghost_handle = (void *) NULL;
114
115static SemaphoreInfo
116  *ghost_semaphore = (SemaphoreInfo *) NULL,
117  *winsock_semaphore = (SemaphoreInfo *) NULL;
118
119static WSADATA
120  *wsaData = (WSADATA*) NULL;
121
122struct
123{
124  const HKEY
125    hkey;
126
127  const char
128    *name;
129}
130const registry_roots[2] =
131{
132  { HKEY_CURRENT_USER,  "HKEY_CURRENT_USER"  },
133  { HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" }
134};
135
136/*
137  External declarations.
138*/
139#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
140extern "C" BOOL WINAPI
141  DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved);
142#endif
143
144static void MagickDLLCall NTGhostscriptDeleteInstance(
145  gs_main_instance *instance)
146{
147  LockSemaphoreInfo(ghost_semaphore);
148  nt_ghost_info.delete_instance(instance);
149  nt_ghost_info.has_instance=MagickFalse;
150  UnlockSemaphoreInfo(ghost_semaphore);
151}
152
153static int MagickDLLCall NTGhostscriptNewInstance(gs_main_instance **pinstance,
154  void *caller_handle)
155{
156  int
157    status;
158
159  LockSemaphoreInfo(ghost_semaphore);
160  status=-1;
161  if (nt_ghost_info.has_instance == MagickFalse)
162    {
163      status=nt_ghost_info.new_instance(pinstance,caller_handle);
164      if (status >= 0)
165        nt_ghost_info.has_instance=MagickTrue;
166    }
167  UnlockSemaphoreInfo(ghost_semaphore);
168  return(status);
169}
170
171static inline char *create_utf8_string(const wchar_t *wideChar)
172{
173  char
174    *utf8;
175
176  int
177    count;
178
179  count=WideCharToMultiByte(CP_UTF8,0,wideChar,-1,NULL,0,NULL,NULL);
180  if (count < 0)
181    return((char *) NULL);
182  utf8=(char *) AcquireQuantumMemory(count+1,sizeof(*utf8));
183  if (utf8 == (char *) NULL)
184    return((char *) NULL);
185  count=WideCharToMultiByte(CP_UTF8,0,wideChar,-1,utf8,count,NULL,NULL);
186  if (count == 0)
187    {
188      utf8=DestroyString(utf8);
189      return((char *) NULL);
190    }
191  utf8[count]=0;
192  return(utf8);
193}
194
195/*
196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197%                                                                             %
198%                                                                             %
199%                                                                             %
200%   D l l M a i n                                                             %
201%                                                                             %
202%                                                                             %
203%                                                                             %
204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205%
206%  DllMain() is an entry point to the DLL which is called when processes and
207%  threads are initialized and terminated, or upon calls to the Windows
208%  LoadLibrary and FreeLibrary functions.
209%
210%  The function returns TRUE of it succeeds, or FALSE if initialization fails.
211%
212%  The format of the DllMain method is:
213%
214%    BOOL WINAPI DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved)
215%
216%  A description of each parameter follows:
217%
218%    o handle: handle to the DLL module
219%
220%    o reason: reason for calling function:
221%
222%      DLL_PROCESS_ATTACH - DLL is being loaded into virtual address
223%                           space of current process.
224%      DLL_THREAD_ATTACH - Indicates that the current process is
225%                          creating a new thread.  Called under the
226%                          context of the new thread.
227%      DLL_THREAD_DETACH - Indicates that the thread is exiting.
228%                          Called under the context of the exiting
229%                          thread.
230%      DLL_PROCESS_DETACH - Indicates that the DLL is being unloaded
231%                           from the virtual address space of the
232%                           current process.
233%
234%    o lpvReserved: Used for passing additional info during DLL_PROCESS_ATTACH
235%                   and DLL_PROCESS_DETACH.
236%
237*/
238#if defined(_DLL) && defined(ProvideDllMain)
239BOOL WINAPI DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved)
240{
241  switch (reason)
242  {
243    case DLL_PROCESS_ATTACH:
244    {
245      char
246        *module_path;
247
248      ssize_t
249        count;
250
251      wchar_t
252        *wide_path;
253
254      MagickCoreGenesis((const char *) NULL,MagickFalse);
255      wide_path=(wchar_t *) AcquireQuantumMemory(MagickPathExtent,
256        sizeof(*wide_path));
257      if (wide_path == (wchar_t *) NULL)
258        return(FALSE);
259      count=(ssize_t) GetModuleFileNameW(handle,wide_path,MagickPathExtent);
260      if (count != 0)
261        {
262          char
263            *path;
264
265          module_path=create_utf8_string(wide_path);
266          for ( ; count > 0; count--)
267            if (module_path[count] == '\\')
268              {
269                module_path[count+1]='\0';
270                break;
271              }
272          path=(char *) AcquireQuantumMemory(16UL*MagickPathExtent,sizeof(*path));
273          if (path == (char *) NULL)
274            {
275              module_path=DestroyString(module_path);
276              wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
277              return(FALSE);
278            }
279          count=(ssize_t) GetEnvironmentVariable("PATH",path,16*MagickPathExtent);
280          if ((count != 0) && (strstr(path,module_path) == (char *) NULL))
281            {
282              if ((strlen(module_path)+count+1) < (16*MagickPathExtent-1))
283                {
284                  char
285                    *variable;
286
287                  variable=(char *) AcquireQuantumMemory(16UL*MagickPathExtent,
288                    sizeof(*variable));
289                  if (variable == (char *) NULL)
290                    {
291                      path=DestroyString(path);
292                      module_path=DestroyString(module_path);
293                      wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
294                      return(FALSE);
295                    }
296                  (void) FormatLocaleString(variable,16*MagickPathExtent,
297                    "%s;%s",module_path,path);
298                  SetEnvironmentVariable("PATH",variable);
299                  variable=DestroyString(variable);
300                }
301            }
302          path=DestroyString(path);
303          module_path=DestroyString(module_path);
304        }
305      wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
306      break;
307    }
308    case DLL_PROCESS_DETACH:
309    {
310      MagickCoreTerminus();
311      break;
312    }
313    default:
314      break;
315  }
316  return(TRUE);
317}
318#endif
319
320/*
321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322%                                                                             %
323%                                                                             %
324%                                                                             %
325%   E x i t                                                                   %
326%                                                                             %
327%                                                                             %
328%                                                                             %
329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330%
331%  Exit() calls TerminateProcess for Win95.
332%
333%  The format of the exit method is:
334%
335%      int Exit(int status)
336%
337%  A description of each parameter follows:
338%
339%    o status: an integer value representing the status of the terminating
340%      process.
341%
342*/
343MagickPrivate int Exit(int status)
344{
345  if (IsWindows95())
346    {
347      TerminateProcess(GetCurrentProcess(),(unsigned int) status);
348      return(0);
349    }
350  exit(status);
351}
352
353#if !defined(__MINGW32__) && !defined(__MINGW64__)
354/*
355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356%                                                                             %
357%                                                                             %
358%                                                                             %
359%   g e t t i m e o f d a y                                                   %
360%                                                                             %
361%                                                                             %
362%                                                                             %
363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364%
365%  The gettimeofday() method get the time of day.
366%
367%  The format of the gettimeofday method is:
368%
369%      int gettimeofday(struct timeval *time_value,struct timezone *time_zone)
370%
371%  A description of each parameter follows:
372%
373%    o time_value: the time value.
374%
375%    o time_zone: the time zone.
376%
377*/
378MagickPrivate int gettimeofday (struct timeval *time_value,
379  struct timezone *time_zone)
380{
381#define EpochFiletime  MagickLLConstant(116444736000000000)
382
383  static int
384    is_tz_set;
385
386  if (time_value != (struct timeval *) NULL)
387    {
388      FILETIME
389        file_time;
390
391      __int64
392        time;
393
394      LARGE_INTEGER
395        date_time;
396
397      GetSystemTimeAsFileTime(&file_time);
398      date_time.LowPart=file_time.dwLowDateTime;
399      date_time.HighPart=file_time.dwHighDateTime;
400      time=date_time.QuadPart;
401      time-=EpochFiletime;
402      time/=10;
403      time_value->tv_sec=(ssize_t) (time / 1000000);
404      time_value->tv_usec=(ssize_t) (time % 1000000);
405    }
406  if (time_zone != (struct timezone *) NULL)
407    {
408      if (is_tz_set == 0)
409        {
410          _tzset();
411          is_tz_set++;
412        }
413      time_zone->tz_minuteswest=_timezone/60;
414      time_zone->tz_dsttime=_daylight;
415    }
416  return(0);
417}
418#endif
419
420/*
421%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422%                                                                             %
423%                                                                             %
424%                                                                             %
425%   I s W i n d o w s 9 5                                                     %
426%                                                                             %
427%                                                                             %
428%                                                                             %
429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430%
431%  IsWindows95() returns true if the system is Windows 95.
432%
433%  The format of the IsWindows95 method is:
434%
435%      int IsWindows95()
436%
437*/
438MagickPrivate int IsWindows95()
439{
440  OSVERSIONINFO
441    version_info;
442
443  version_info.dwOSVersionInfoSize=sizeof(version_info);
444  if (GetVersionEx(&version_info) &&
445      (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS))
446    return(1);
447  return(0);
448}
449
450/*
451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
452%                                                                             %
453%                                                                             %
454%                                                                             %
455%   N T A r g v T o U T F 8                                                   %
456%                                                                             %
457%                                                                             %
458%                                                                             %
459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460%
461%  NTArgvToUTF8() converts the wide command line arguments to UTF-8 to ensure
462%  compatibility with Linux.
463%
464%  The format of the NTArgvToUTF8 method is:
465%
466%      char **NTArgvToUTF8(const int argc,wchar_t **argv)
467%
468%  A description of each parameter follows:
469%
470%    o argc: the number of command line arguments.
471%
472%    o argv:  the  wide-character command line arguments.
473%
474*/
475MagickPrivate char **NTArgvToUTF8(const int argc,wchar_t **argv)
476{
477  char
478    **utf8;
479
480  ssize_t
481    i;
482
483  utf8=(char **) AcquireQuantumMemory(argc,sizeof(*utf8));
484  if (utf8 == (char **) NULL)
485    ThrowFatalException(ResourceLimitFatalError,"UnableToConvertStringToARGV");
486  for (i=0; i < (ssize_t) argc; i++)
487  {
488    utf8[i]=create_utf8_string(argv[i]);
489    if (utf8[i] == (char *) NULL)
490      {
491        for (i--; i >= 0; i--)
492          utf8[i]=DestroyString(utf8[i]);
493        ThrowFatalException(ResourceLimitFatalError,
494          "UnableToConvertStringToARGV");
495      }
496  }
497  return(utf8);
498}
499
500/*
501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
502%                                                                             %
503%                                                                             %
504%                                                                             %
505%   N T C l o s e D i r e c t o r y                                           %
506%                                                                             %
507%                                                                             %
508%                                                                             %
509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510%
511%  NTCloseDirectory() closes the named directory stream and frees the DIR
512%  structure.
513%
514%  The format of the NTCloseDirectory method is:
515%
516%      int NTCloseDirectory(DIR *entry)
517%
518%  A description of each parameter follows:
519%
520%    o entry: Specifies a pointer to a DIR structure.
521%
522*/
523MagickPrivate int NTCloseDirectory(DIR *entry)
524{
525  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
526  assert(entry != (DIR *) NULL);
527  FindClose(entry->hSearch);
528  entry=(DIR *) RelinquishMagickMemory(entry);
529  return(0);
530}
531
532/*
533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534%                                                                             %
535%                                                                             %
536%                                                                             %
537%   N T C l o s e L i b r a r y                                               %
538%                                                                             %
539%                                                                             %
540%                                                                             %
541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
542%
543%  NTCloseLibrary() unloads the module associated with the passed handle.
544%
545%  The format of the NTCloseLibrary method is:
546%
547%      void NTCloseLibrary(void *handle)
548%
549%  A description of each parameter follows:
550%
551%    o handle: Specifies a handle to a previously loaded dynamic module.
552%
553*/
554MagickPrivate int NTCloseLibrary(void *handle)
555{
556  if (IsWindows95())
557    return(FreeLibrary((HINSTANCE) handle));
558  return(!(FreeLibrary((HINSTANCE) handle)));
559}
560
561/*
562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563%                                                                             %
564%                                                                             %
565%                                                                             %
566%   N T C o n t r o l H a n d l e r                                           %
567%                                                                             %
568%                                                                             %
569%                                                                             %
570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571%
572%  NTControlHandler() registers a control handler that is activated when, for
573%  example, a ctrl-c is received.
574%
575%  The format of the NTControlHandler method is:
576%
577%      int NTControlHandler(void)
578%
579*/
580
581static BOOL ControlHandler(DWORD type)
582{
583  (void) type;
584  AsynchronousResourceComponentTerminus();
585  return(FALSE);
586}
587
588MagickPrivate int NTControlHandler(void)
589{
590  return(SetConsoleCtrlHandler((PHANDLER_ROUTINE) ControlHandler,TRUE));
591}
592
593/*
594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595%                                                                             %
596%                                                                             %
597%                                                                             %
598%   N T E l a p s e d T i m e                                                 %
599%                                                                             %
600%                                                                             %
601%                                                                             %
602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603%
604%  NTElapsedTime() returns the elapsed time (in seconds) since the last call to
605%  StartTimer().
606%
607%  The format of the ElapsedTime method is:
608%
609%      double NTElapsedTime(void)
610%
611*/
612MagickPrivate double NTElapsedTime(void)
613{
614  union
615  {
616    FILETIME
617      filetime;
618
619    __int64
620      filetime64;
621  } elapsed_time;
622
623  SYSTEMTIME
624    system_time;
625
626  GetSystemTime(&system_time);
627  SystemTimeToFileTime(&system_time,&elapsed_time.filetime);
628  return((double) 1.0e-7*elapsed_time.filetime64);
629}
630
631/*
632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633%                                                                             %
634%                                                                             %
635%                                                                             %
636+   N T E r r o r H a n d l e r                                               %
637%                                                                             %
638%                                                                             %
639%                                                                             %
640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641%
642%  NTErrorHandler() displays an error reason and then terminates the program.
643%
644%  The format of the NTErrorHandler method is:
645%
646%      void NTErrorHandler(const ExceptionType severity,const char *reason,
647%        const char *description)
648%
649%  A description of each parameter follows:
650%
651%    o severity: Specifies the numeric error category.
652%
653%    o reason: Specifies the reason to display before terminating the
654%      program.
655%
656%    o description: Specifies any description to the reason.
657%
658*/
659MagickPrivate void NTErrorHandler(const ExceptionType severity,
660  const char *reason,const char *description)
661{
662  char
663    buffer[3*MagickPathExtent],
664    *message;
665
666  (void) severity;
667  if (reason == (char *) NULL)
668    {
669      MagickCoreTerminus();
670      exit(0);
671    }
672  message=GetExceptionMessage(errno);
673  if ((description != (char *) NULL) && errno)
674    (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s) [%s].\n",
675      GetClientName(),reason,description,message);
676  else
677    if (description != (char *) NULL)
678      (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s).\n",
679        GetClientName(),reason,description);
680    else
681      if (errno != 0)
682        (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s [%s].\n",
683          GetClientName(),reason,message);
684      else
685        (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s.\n",
686          GetClientName(),reason);
687  message=DestroyString(message);
688  (void) MessageBox(NULL,buffer,"ImageMagick Exception",MB_OK | MB_TASKMODAL |
689    MB_SETFOREGROUND | MB_ICONEXCLAMATION);
690  MagickCoreTerminus();
691  exit(0);
692}
693
694/*
695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696%                                                                             %
697%                                                                             %
698%                                                                             %
699%   N T E x i t L i b r a r y                                                 %
700%                                                                             %
701%                                                                             %
702%                                                                             %
703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704%
705%  NTExitLibrary() exits the dynamic module loading subsystem.
706%
707%  The format of the NTExitLibrary method is:
708%
709%      int NTExitLibrary(void)
710%
711*/
712MagickPrivate int NTExitLibrary(void)
713{
714  return(0);
715}
716
717/*
718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719%                                                                             %
720%                                                                             %
721%                                                                             %
722%   N T G a t h e r R a n d o m D a t a                                       %
723%                                                                             %
724%                                                                             %
725%                                                                             %
726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727%
728%  NTGatherRandomData() gathers random data and returns it.
729%
730%  The format of the GatherRandomData method is:
731%
732%      MagickBooleanType NTGatherRandomData(const size_t length,
733%        unsigned char *random)
734%
735%  A description of each parameter follows:
736%
737%    length: the length of random data buffer
738%
739%    random: the random data is returned here.
740%
741*/
742MagickPrivate MagickBooleanType NTGatherRandomData(const size_t length,
743  unsigned char *random)
744{
745#if defined(MAGICKCORE_CIPHER_SUPPORT) && defined(_MSC_VER) && (_MSC_VER > 1200)
746  HCRYPTPROV
747    handle;
748
749  int
750    status;
751
752  handle=(HCRYPTPROV) NULL;
753  status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
754    (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET));
755  if (status == 0)
756    status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
757      (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET));
758  if (status == 0)
759    return(MagickFalse);
760  status=CryptGenRandom(handle,(DWORD) length,random);
761  if (status == 0)
762    {
763      status=CryptReleaseContext(handle,0);
764      return(MagickFalse);
765    }
766  status=CryptReleaseContext(handle,0);
767  if (status == 0)
768    return(MagickFalse);
769#else
770  (void) random;
771  (void) length;
772#endif
773  return(MagickTrue);
774}
775
776/*
777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
778%                                                                             %
779%                                                                             %
780%                                                                             %
781%   N T G e t E x e c u t i o n P a t h                                       %
782%                                                                             %
783%                                                                             %
784%                                                                             %
785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
786%
787%  NTGetExecutionPath() returns the execution path of a program.
788%
789%  The format of the GetExecutionPath method is:
790%
791%      MagickBooleanType NTGetExecutionPath(char *path,const size_t extent)
792%
793%  A description of each parameter follows:
794%
795%    o path: the pathname of the executable that started the process.
796%
797%    o extent: the maximum extent of the path.
798%
799*/
800MagickPrivate MagickBooleanType NTGetExecutionPath(char *path,
801  const size_t extent)
802{
803  wchar_t
804    wide_path[MagickPathExtent];
805
806  (void) GetModuleFileNameW((HMODULE) NULL,wide_path,(DWORD) extent);
807  (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,
808    NULL);
809  return(MagickTrue);
810}
811
812/*
813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814%                                                                             %
815%                                                                             %
816%                                                                             %
817%   N T G e t L a s t E r r o r                                               %
818%                                                                             %
819%                                                                             %
820%                                                                             %
821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822%
823%  NTGetLastError() returns the last error that occurred.
824%
825%  The format of the NTGetLastError method is:
826%
827%      char *NTGetLastError(void)
828%
829*/
830char *NTGetLastError(void)
831{
832  char
833    *reason;
834
835  int
836    status;
837
838  LPVOID
839    buffer;
840
841  status=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
842    FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),
843    MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR) &buffer,0,NULL);
844  if (!status)
845    reason=AcquireString("An unknown error occurred");
846  else
847    {
848      reason=AcquireString((const char *) buffer);
849      LocalFree(buffer);
850    }
851  return(reason);
852}
853
854/*
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856%                                                                             %
857%                                                                             %
858%                                                                             %
859%   N T G e t L i b r a r y E r r o r                                         %
860%                                                                             %
861%                                                                             %
862%                                                                             %
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864%
865%  Lt_dlerror() returns a pointer to a string describing the last error
866%  associated with a lt_dl method.  Note that this function is not thread
867%  safe so it should only be used under the protection of a lock.
868%
869%  The format of the NTGetLibraryError method is:
870%
871%      const char *NTGetLibraryError(void)
872%
873*/
874MagickPrivate const char *NTGetLibraryError(void)
875{
876  static char
877    last_error[MagickPathExtent];
878
879  char
880    *error;
881
882  *last_error='\0';
883  error=NTGetLastError();
884  if (error)
885    (void) CopyMagickString(last_error,error,MagickPathExtent);
886  error=DestroyString(error);
887  return(last_error);
888}
889
890/*
891%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
892%                                                                             %
893%                                                                             %
894%                                                                             %
895%   N T G e t L i b r a r y S y m b o l                                       %
896%                                                                             %
897%                                                                             %
898%                                                                             %
899%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900%
901%  NTGetLibrarySymbol() retrieve the procedure address of the method
902%  specified by the passed character string.
903%
904%  The format of the NTGetLibrarySymbol method is:
905%
906%      void *NTGetLibrarySymbol(void *handle,const char *name)
907%
908%  A description of each parameter follows:
909%
910%    o handle: Specifies a handle to the previously loaded dynamic module.
911%
912%    o name: Specifies the procedure entry point to be returned.
913%
914*/
915void *NTGetLibrarySymbol(void *handle,const char *name)
916{
917  LPFNDLLFUNC1
918    lpfnDllFunc1;
919
920  lpfnDllFunc1=(LPFNDLLFUNC1) GetProcAddress((HINSTANCE) handle,name);
921  if (!lpfnDllFunc1)
922    return((void *) NULL);
923  return((void *) lpfnDllFunc1);
924}
925
926/*
927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928%                                                                             %
929%                                                                             %
930%                                                                             %
931%   N T G e t M o d u l e P a t h                                             %
932%                                                                             %
933%                                                                             %
934%                                                                             %
935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936%
937%  NTGetModulePath() returns the path of the specified module.
938%
939%  The format of the GetModulePath method is:
940%
941%      MagickBooleanType NTGetModulePath(const char *module,char *path)
942%
943%  A description of each parameter follows:
944%
945%    modith: the module name.
946%
947%    path: the module path is returned here.
948%
949*/
950MagickPrivate MagickBooleanType NTGetModulePath(const char *module,char *path)
951{
952  char
953    module_path[MagickPathExtent];
954
955  HMODULE
956    handle;
957
958  ssize_t
959    length;
960
961  *path='\0';
962  handle=GetModuleHandle(module);
963  if (handle == (HMODULE) NULL)
964    return(MagickFalse);
965  length=GetModuleFileName(handle,module_path,MagickPathExtent);
966  if (length != 0)
967    GetPathComponent(module_path,HeadPath,path);
968  return(MagickTrue);
969}
970
971/*
972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973%                                                                             %
974%                                                                             %
975%                                                                             %
976%   N T G h o s t s c r i p t D L L                                           %
977%                                                                             %
978%                                                                             %
979%                                                                             %
980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981%
982%  NTGhostscriptDLL() returns the path to the most recent Ghostscript version
983%  DLL.  The method returns TRUE on success otherwise FALSE.
984%
985%  The format of the NTGhostscriptDLL method is:
986%
987%      int NTGhostscriptDLL(char *path,int length)
988%
989%  A description of each parameter follows:
990%
991%    o path: return the Ghostscript DLL path here.
992%
993%    o length: the buffer length.
994%
995*/
996
997static int NTGetRegistryValue(HKEY root,const char *key,DWORD flags,
998  const char *name,char *value,int *length)
999{
1000  BYTE
1001    byte,
1002    *p;
1003
1004  DWORD
1005    extent,
1006    type;
1007
1008  HKEY
1009    hkey;
1010
1011  LONG
1012    status;
1013
1014  /*
1015    Get a registry value: key = root\\key, named value = name.
1016  */
1017  if (RegOpenKeyExA(root,key,0,KEY_READ | flags,&hkey) != ERROR_SUCCESS)
1018    return(1);  /* no match */
1019  p=(BYTE *) value;
1020  type=REG_SZ;
1021  extent=(*length);
1022  if (p == (BYTE *) NULL)
1023    p=(&byte);  /* ERROR_MORE_DATA only if value is NULL */
1024  status=RegQueryValueExA(hkey,(char *) name,0,&type,p,&extent);
1025  RegCloseKey(hkey);
1026  if (status == ERROR_SUCCESS)
1027    {
1028      *length=extent;
1029      return(0);  /* return the match */
1030    }
1031  if (status == ERROR_MORE_DATA)
1032    {
1033      *length=extent;
1034      return(-1);  /* buffer not large enough */
1035    }
1036  return(1);  /* not found */
1037}
1038
1039static int NTLocateGhostscript(DWORD flags,int *root_index,
1040  const char **product_family,int *major_version,int *minor_version)
1041{
1042  int
1043    i;
1044
1045  MagickBooleanType
1046    status;
1047
1048  static const char
1049    *products[4] =
1050    {
1051      "GPL Ghostscript",
1052      "GNU Ghostscript",
1053      "AFPL Ghostscript",
1054      "Aladdin Ghostscript"
1055    };
1056
1057  /*
1058    Find the most recent version of Ghostscript.
1059  */
1060  status=MagickFalse;
1061  *root_index=0;
1062  *product_family=NULL;
1063  *major_version=5;
1064  *minor_version=49; /* min version of Ghostscript is 5.50 */
1065  for (i=0; i < (ssize_t) (sizeof(products)/sizeof(products[0])); i++)
1066  {
1067    char
1068      key[MagickPathExtent];
1069
1070    HKEY
1071      hkey;
1072
1073    int
1074      j;
1075
1076    REGSAM
1077      mode;
1078
1079    (void) FormatLocaleString(key,MagickPathExtent,"SOFTWARE\\%s",products[i]);
1080    for (j=0; j < (ssize_t) (sizeof(registry_roots)/sizeof(registry_roots[0]));
1081         j++)
1082    {
1083      mode=KEY_READ | flags;
1084      if (RegOpenKeyExA(registry_roots[j].hkey,key,0,mode,&hkey) ==
1085            ERROR_SUCCESS)
1086        {
1087          DWORD
1088            extent;
1089
1090          int
1091            k;
1092
1093          /*
1094            Now enumerate the keys.
1095          */
1096          extent=sizeof(key)/sizeof(char);
1097          for (k=0; RegEnumKeyA(hkey,k,key,extent) == ERROR_SUCCESS; k++)
1098          {
1099            int
1100              major,
1101              minor;
1102
1103            major=0;
1104            minor=0;
1105            if (sscanf(key,"%d.%d",&major,&minor) != 2)
1106              continue;
1107            if ((major > *major_version) || ((major == *major_version) &&
1108                (minor > *minor_version)))
1109              {
1110                *root_index=j;
1111                *product_family=products[i];
1112                *major_version=major;
1113                *minor_version=minor;
1114                status=MagickTrue;
1115              }
1116         }
1117         (void) RegCloseKey(hkey);
1118       }
1119    }
1120  }
1121  if (status == MagickFalse)
1122    {
1123      *major_version=0;
1124      *minor_version=0;
1125    }
1126  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"Ghostscript (%s) "
1127    "version %d.%02d",*product_family,*major_version,*minor_version);
1128  return(status);
1129}
1130
1131static int NTGhostscriptGetString(const char *name,BOOL *is_64_bit,
1132  char *value,const size_t length)
1133{
1134  char
1135    buffer[MagickPathExtent],
1136    *directory;
1137
1138  int
1139    extent;
1140
1141  static const char
1142    *product_family=(const char *) NULL;
1143
1144  static BOOL
1145    is_64_bit_version=FALSE;
1146
1147  static int
1148    flags=0,
1149    major_version=0,
1150    minor_version=0,
1151    root_index=0;
1152
1153  /*
1154    Get a string from the installed Ghostscript.
1155  */
1156  *value='\0';
1157  directory=(char *) NULL;
1158  if (LocaleCompare(name, "GS_DLL") == 0)
1159    {
1160      directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_PATH");
1161      if (directory != (char *) NULL)
1162        {
1163          (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll32.dll",
1164            directory,DirectorySeparator);
1165          if (IsPathAccessible(buffer) != MagickFalse)
1166            {
1167              directory=DestroyString(directory);
1168              (void) CopyMagickString(value,buffer,length);
1169              if (is_64_bit != NULL)
1170                *is_64_bit=FALSE;
1171              return(TRUE);
1172            }
1173          (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll64.dll",
1174            directory,DirectorySeparator);
1175          if (IsPathAccessible(buffer) != MagickFalse)
1176            {
1177              directory=DestroyString(directory);
1178              (void) CopyMagickString(value,buffer,length);
1179              if (is_64_bit != NULL)
1180                *is_64_bit=TRUE;
1181              return(TRUE);
1182            }
1183          return(FALSE);
1184        }
1185    }
1186  if (product_family == NULL)
1187    {
1188      flags=0;
1189#if defined(KEY_WOW64_32KEY)
1190#if defined(_WIN64)
1191      flags=KEY_WOW64_64KEY;
1192#else
1193      flags=KEY_WOW64_32KEY;
1194#endif
1195      (void) NTLocateGhostscript(flags,&root_index,&product_family,
1196        &major_version,&minor_version);
1197      if (product_family == NULL)
1198#if defined(_WIN64)
1199        flags=KEY_WOW64_32KEY;
1200      else
1201        is_64_bit_version=TRUE;
1202#else
1203        flags=KEY_WOW64_64KEY;
1204#endif
1205#endif
1206    }
1207  if (product_family == NULL)
1208    {
1209      (void) NTLocateGhostscript(flags,&root_index,&product_family,
1210      &major_version,&minor_version);
1211#if !defined(_WIN64)
1212      is_64_bit_version=TRUE;
1213#endif
1214    }
1215  if (product_family == NULL)
1216    return(FALSE);
1217  if (is_64_bit != NULL)
1218    *is_64_bit=is_64_bit_version;
1219  (void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%02d",
1220    product_family,major_version,minor_version);
1221  extent=(int) length;
1222  if (NTGetRegistryValue(registry_roots[root_index].hkey,buffer,flags,name,
1223    value,&extent) == 0)
1224    {
1225      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1226        "registry: \"%s\\%s\\%s\"=\"%s\"",registry_roots[root_index].name,
1227        buffer,name,value);
1228      return(TRUE);
1229    }
1230  return(FALSE);
1231}
1232
1233MagickPrivate int NTGhostscriptDLL(char *path,int length)
1234{
1235  static char
1236    dll[MagickPathExtent] = { "" };
1237
1238  static BOOL
1239    is_64_bit_version;
1240
1241  *path='\0';
1242  if ((*dll == '\0') &&
1243      (NTGhostscriptGetString("GS_DLL",&is_64_bit_version,dll,sizeof(dll)) == FALSE))
1244    return(FALSE);
1245
1246#if defined(_WIN64)
1247  if (!is_64_bit_version)
1248    return(FALSE);
1249#else
1250  if (is_64_bit_version)
1251    return(FALSE);
1252#endif
1253  (void) CopyMagickString(path,dll,length);
1254  return(TRUE);
1255}
1256
1257/*
1258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259%                                                                             %
1260%                                                                             %
1261%                                                                             %
1262%   N T G h o s t s c r i p t D L L V e c t o r s                             %
1263%                                                                             %
1264%                                                                             %
1265%                                                                             %
1266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1267%
1268%  NTGhostscriptDLLVectors() returns a GhostInfo structure that includes
1269%  function vectors to invoke Ghostscript DLL functions. A null pointer is
1270%  returned if there is an error when loading the DLL or retrieving the
1271%  function vectors.
1272%
1273%  The format of the NTGhostscriptDLLVectors method is:
1274%
1275%      const GhostInfo *NTGhostscriptDLLVectors(void)
1276%
1277*/
1278MagickPrivate const GhostInfo *NTGhostscriptDLLVectors(void)
1279{
1280  if (NTGhostscriptLoadDLL() == FALSE)
1281    return((GhostInfo *) NULL);
1282  return(&ghost_info);
1283}
1284
1285/*
1286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1287%                                                                             %
1288%                                                                             %
1289%                                                                             %
1290%   N T G h o s t s c r i p t E X E                                           %
1291%                                                                             %
1292%                                                                             %
1293%                                                                             %
1294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1295%
1296%  NTGhostscriptEXE() obtains the path to the latest Ghostscript executable.
1297%  The method returns FALSE if a full path value is not obtained and returns
1298%  a default path of gswin32c.exe.
1299%
1300%  The format of the NTGhostscriptEXE method is:
1301%
1302%      int NTGhostscriptEXE(char *path,int length)
1303%
1304%  A description of each parameter follows:
1305%
1306%    o path: return the Ghostscript executable path here.
1307%
1308%    o length: length of buffer.
1309%
1310*/
1311MagickPrivate int NTGhostscriptEXE(char *path,int length)
1312{
1313  register char
1314    *p;
1315
1316  static char
1317    program[MagickPathExtent] = { "" };
1318
1319  static BOOL
1320    is_64_bit_version = FALSE;
1321
1322  (void) CopyMagickString(path,"gswin32c.exe",length);
1323  if ((*program == '\0') &&
1324      (NTGhostscriptGetString("GS_DLL",&is_64_bit_version,program,sizeof(program)) == FALSE))
1325    return(FALSE);
1326  p=strrchr(program,'\\');
1327  if (p != (char *) NULL)
1328    {
1329      p++;
1330      *p='\0';
1331      (void) ConcatenateMagickString(program,is_64_bit_version ?
1332        "gswin64c.exe" : "gswin32c.exe",sizeof(program));
1333    }
1334  (void) CopyMagickString(path,program,length);
1335  return(TRUE);
1336}
1337
1338/*
1339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1340%                                                                             %
1341%                                                                             %
1342%                                                                             %
1343%   N T G h o s t s c r i p t F o n t s                                       %
1344%                                                                             %
1345%                                                                             %
1346%                                                                             %
1347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1348%
1349%  NTGhostscriptFonts() obtains the path to the Ghostscript fonts.  The method
1350%  returns FALSE if it cannot determine the font path.
1351%
1352%  The format of the NTGhostscriptFonts method is:
1353%
1354%      int NTGhostscriptFonts(char *path, int length)
1355%
1356%  A description of each parameter follows:
1357%
1358%    o path: return the font path here.
1359%
1360%    o length: length of the path buffer.
1361%
1362*/
1363MagickPrivate int NTGhostscriptFonts(char *path,int length)
1364{
1365  char
1366    buffer[MagickPathExtent],
1367    *directory,
1368    filename[MagickPathExtent];
1369
1370  register char
1371    *p,
1372    *q;
1373
1374  *path='\0';
1375  directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_FONT_PATH");
1376  if (directory != (char *) NULL)
1377    {
1378      (void) CopyMagickString(buffer,directory,MagickPathExtent);
1379      directory=DestroyString(directory);
1380    }
1381  else
1382    {
1383      if (NTGhostscriptGetString("GS_LIB",NULL,buffer,MagickPathExtent) == FALSE)
1384        return(FALSE);
1385    }
1386  for (p=buffer-1; p != (char *) NULL; p=strchr(p+1,DirectoryListSeparator))
1387  {
1388    (void) CopyMagickString(path,p+1,length+1);
1389    q=strchr(path,DirectoryListSeparator);
1390    if (q != (char *) NULL)
1391      *q='\0';
1392    (void) FormatLocaleString(filename,MagickPathExtent,"%s%sfonts.dir",path,
1393      DirectorySeparator);
1394    if (IsPathAccessible(filename) != MagickFalse)
1395      return(TRUE);
1396  }
1397  *path='\0';
1398  return(FALSE);
1399}
1400
1401/*
1402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403%                                                                             %
1404%                                                                             %
1405%                                                                             %
1406%   N T G h o s t s c r i p t L o a d D L L                                   %
1407%                                                                             %
1408%                                                                             %
1409%                                                                             %
1410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1411%
1412%  NTGhostscriptLoadDLL() attempts to load the Ghostscript DLL and returns
1413%  TRUE if it succeeds.
1414%
1415%  The format of the NTGhostscriptLoadDLL method is:
1416%
1417%      int NTGhostscriptLoadDLL(void)
1418%
1419*/
1420static inline int NTGhostscriptHasValidHandle()
1421{
1422  if ((nt_ghost_info.delete_instance == NULL) || (ghost_info.exit == NULL) ||
1423      (ghost_info.init_with_args == NULL) ||
1424      (nt_ghost_info.new_instance == NULL) ||
1425      (ghost_info.run_string == NULL) || (ghost_info.set_stdio == NULL) ||
1426      (ghost_info.revision == NULL))
1427    {
1428      return(FALSE);
1429    }
1430  return(TRUE);
1431}
1432
1433MagickPrivate int NTGhostscriptLoadDLL(void)
1434{
1435  char
1436    path[MagickPathExtent];
1437
1438  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1439    ActivateSemaphoreInfo(&ghost_semaphore);
1440  LockSemaphoreInfo(ghost_semaphore);
1441  if (ghost_handle != (void *) NULL)
1442    {
1443      UnlockSemaphoreInfo(ghost_semaphore);
1444      return(NTGhostscriptHasValidHandle());
1445    }
1446  if (NTGhostscriptDLL(path,sizeof(path)) == FALSE)
1447    {
1448      UnlockSemaphoreInfo(ghost_semaphore);
1449      return(FALSE);
1450    }
1451  ghost_handle=lt_dlopen(path);
1452  if (ghost_handle == (void *) NULL)
1453    {
1454      UnlockSemaphoreInfo(ghost_semaphore);
1455      return(FALSE);
1456    }
1457  (void) ResetMagickMemory((void *) &nt_ghost_info,0,sizeof(NTGhostInfo));
1458  nt_ghost_info.delete_instance=(void (MagickDLLCall *)(gs_main_instance *)) (
1459    lt_dlsym(ghost_handle,"gsapi_delete_instance"));
1460  nt_ghost_info.new_instance=(int (MagickDLLCall *)(gs_main_instance **,
1461    void *)) (lt_dlsym(ghost_handle,"gsapi_new_instance"));
1462  nt_ghost_info.has_instance=MagickFalse;
1463  (void) ResetMagickMemory((void *) &ghost_info,0,sizeof(GhostInfo));
1464  ghost_info.delete_instance=NTGhostscriptDeleteInstance;
1465  ghost_info.exit=(int (MagickDLLCall *)(gs_main_instance*))
1466    lt_dlsym(ghost_handle,"gsapi_exit");
1467  ghost_info.init_with_args=(int (MagickDLLCall *)(gs_main_instance *,int,
1468    char **)) (lt_dlsym(ghost_handle,"gsapi_init_with_args"));
1469  ghost_info.new_instance=NTGhostscriptNewInstance;
1470  ghost_info.run_string=(int (MagickDLLCall *)(gs_main_instance *,const char *,
1471    int,int *)) (lt_dlsym(ghost_handle,"gsapi_run_string"));
1472  ghost_info.set_stdio=(int (MagickDLLCall *)(gs_main_instance *,int(
1473    MagickDLLCall *)(void *,char *,int),int(MagickDLLCall *)(void *,
1474    const char *,int),int(MagickDLLCall *)(void *,const char *,int)))
1475    (lt_dlsym(ghost_handle,"gsapi_set_stdio"));
1476  ghost_info.revision=(int (MagickDLLCall *)(gsapi_revision_t *,int)) (
1477    lt_dlsym(ghost_handle,"gsapi_revision"));
1478  UnlockSemaphoreInfo(ghost_semaphore);
1479  return(NTGhostscriptHasValidHandle());
1480}
1481
1482/*
1483%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1484%                                                                             %
1485%                                                                             %
1486%                                                                             %
1487%   N T G h o s t s c r i p t U n L o a d D L L                               %
1488%                                                                             %
1489%                                                                             %
1490%                                                                             %
1491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492%
1493%  NTGhostscriptUnLoadDLL() unloads the Ghostscript DLL and returns TRUE if
1494%  it succeeds.
1495%
1496%  The format of the NTGhostscriptUnLoadDLL method is:
1497%
1498%      int NTGhostscriptUnLoadDLL(void)
1499%
1500*/
1501MagickPrivate void NTGhostscriptUnLoadDLL(void)
1502{
1503  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1504    ActivateSemaphoreInfo(&ghost_semaphore);
1505  LockSemaphoreInfo(ghost_semaphore);
1506  if (ghost_handle != (void *) NULL)
1507    {
1508      (void) lt_dlclose(ghost_handle);
1509      ghost_handle=(void *) NULL;
1510      (void) ResetMagickMemory((void *) &ghost_info,0,sizeof(GhostInfo));
1511    }
1512  UnlockSemaphoreInfo(ghost_semaphore);
1513  RelinquishSemaphoreInfo(&ghost_semaphore);
1514}
1515
1516/*
1517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1518%                                                                             %
1519%                                                                             %
1520%                                                                             %
1521%   N T I n i t i a l i z e L i b r a r y                                     %
1522%                                                                             %
1523%                                                                             %
1524%                                                                             %
1525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1526%
1527%  NTInitializeLibrary() initializes the dynamic module loading subsystem.
1528%
1529%  The format of the NTInitializeLibrary method is:
1530%
1531%      int NTInitializeLibrary(void)
1532%
1533*/
1534MagickPrivate int NTInitializeLibrary(void)
1535{
1536  return(0);
1537}
1538
1539/*
1540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1541%                                                                             %
1542%                                                                             %
1543%                                                                             %
1544%   N T I n i t i a l i z e W i n s o c k                                     %
1545%                                                                             %
1546%                                                                             %
1547%                                                                             %
1548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1549%
1550%  NTInitializeWinsock() initializes Winsock.
1551%
1552%  The format of the NTInitializeWinsock method is:
1553%
1554%      void NTInitializeWinsock(void)
1555%
1556*/
1557MagickPrivate void NTInitializeWinsock(MagickBooleanType use_lock)
1558{
1559  if (use_lock)
1560    {
1561      if (winsock_semaphore == (SemaphoreInfo *) NULL)
1562        ActivateSemaphoreInfo(&winsock_semaphore);
1563      LockSemaphoreInfo(winsock_semaphore);
1564    }
1565  if (wsaData == (WSADATA *) NULL)
1566    {
1567      wsaData=(WSADATA *) AcquireMagickMemory(sizeof(WSADATA));
1568      if (WSAStartup(MAKEWORD(2,2),wsaData) != 0)
1569        ThrowFatalException(CacheFatalError,"WSAStartup failed");
1570    }
1571  if (use_lock)
1572    UnlockSemaphoreInfo(winsock_semaphore);
1573}
1574
1575/*
1576%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1577%                                                                             %
1578%                                                                             %
1579%                                                                             %
1580+  N T M a p M e m o r y                                                      %
1581%                                                                             %
1582%                                                                             %
1583%                                                                             %
1584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1585%
1586%  Mmap() emulates the Unix method of the same name.
1587%
1588%  The format of the NTMapMemory method is:
1589%
1590%    MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1591%      int access,int file,MagickOffsetType offset)
1592%
1593*/
1594MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1595  int flags,int file,MagickOffsetType offset)
1596{
1597  DWORD
1598    access_mode,
1599    high_length,
1600    high_offset,
1601    low_length,
1602    low_offset,
1603    protection_mode;
1604
1605  HANDLE
1606    file_handle,
1607    map_handle;
1608
1609  void
1610    *map;
1611
1612  (void) address;
1613  access_mode=0;
1614  file_handle=INVALID_HANDLE_VALUE;
1615  low_length=(DWORD) (length & 0xFFFFFFFFUL);
1616  high_length=(DWORD) ((((MagickOffsetType) length) >> 32) & 0xFFFFFFFFUL);
1617  map_handle=INVALID_HANDLE_VALUE;
1618  map=(void *) NULL;
1619  low_offset=(DWORD) (offset & 0xFFFFFFFFUL);
1620  high_offset=(DWORD) ((offset >> 32) & 0xFFFFFFFFUL);
1621  protection_mode=0;
1622  if (protection & PROT_WRITE)
1623    {
1624      access_mode=FILE_MAP_WRITE;
1625      if (!(flags & MAP_PRIVATE))
1626        protection_mode=PAGE_READWRITE;
1627      else
1628        {
1629          access_mode=FILE_MAP_COPY;
1630          protection_mode=PAGE_WRITECOPY;
1631        }
1632    }
1633  else
1634    if (protection & PROT_READ)
1635      {
1636        access_mode=FILE_MAP_READ;
1637        protection_mode=PAGE_READONLY;
1638      }
1639  if ((file == -1) && (flags & MAP_ANONYMOUS))
1640    file_handle=INVALID_HANDLE_VALUE;
1641  else
1642    file_handle=(HANDLE) _get_osfhandle(file);
1643  map_handle=CreateFileMapping(file_handle,0,protection_mode,high_length,
1644    low_length,0);
1645  if (map_handle)
1646    {
1647      map=(void *) MapViewOfFile(map_handle,access_mode,high_offset,low_offset,
1648        length);
1649      CloseHandle(map_handle);
1650    }
1651  if (map == (void *) NULL)
1652    return((void *) ((char *) MAP_FAILED));
1653  return((void *) ((char *) map));
1654}
1655
1656/*
1657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658%                                                                             %
1659%                                                                             %
1660%                                                                             %
1661%   N T O p e n D i r e c t o r y                                             %
1662%                                                                             %
1663%                                                                             %
1664%                                                                             %
1665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666%
1667%  NTOpenDirectory() opens the directory named by filename and associates a
1668%  directory stream with it.
1669%
1670%  The format of the NTOpenDirectory method is:
1671%
1672%      DIR *NTOpenDirectory(const char *path)
1673%
1674%  A description of each parameter follows:
1675%
1676%    o entry: Specifies a pointer to a DIR structure.
1677%
1678*/
1679MagickPrivate DIR *NTOpenDirectory(const char *path)
1680{
1681  DIR
1682    *entry;
1683
1684  size_t
1685    length;
1686
1687  wchar_t
1688    file_specification[MagickPathExtent];
1689
1690  assert(path != (const char *) NULL);
1691  length=MultiByteToWideChar(CP_UTF8,0,path,-1,file_specification,
1692    MagickPathExtent);
1693  if (length == 0)
1694    return((DIR *) NULL);
1695  if(wcsncat(file_specification,(const wchar_t*) DirectorySeparator,
1696       MagickPathExtent-wcslen(file_specification)-1) == (wchar_t*) NULL)
1697    return((DIR *) NULL);
1698  entry=(DIR *) AcquireMagickMemory(sizeof(DIR));
1699  if (entry != (DIR *) NULL)
1700    {
1701      entry->firsttime=TRUE;
1702      entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
1703    }
1704  if (entry->hSearch == INVALID_HANDLE_VALUE)
1705    {
1706      if(wcsncat(file_specification,L"*.*",
1707        MagickPathExtent-wcslen(file_specification)-1) == (wchar_t*) NULL)
1708        {
1709          entry=(DIR *) RelinquishMagickMemory(entry);
1710          return((DIR *) NULL);
1711        }
1712      entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
1713      if (entry->hSearch == INVALID_HANDLE_VALUE)
1714        {
1715          entry=(DIR *) RelinquishMagickMemory(entry);
1716          return((DIR *) NULL);
1717        }
1718    }
1719  return(entry);
1720}
1721
1722/*
1723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724%                                                                             %
1725%                                                                             %
1726%                                                                             %
1727%   N T O p e n L i b r a r y                                                 %
1728%                                                                             %
1729%                                                                             %
1730%                                                                             %
1731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1732%
1733%  NTOpenLibrary() loads a dynamic module into memory and returns a handle that
1734%  can be used to access the various procedures in the module.
1735%
1736%  The format of the NTOpenLibrary method is:
1737%
1738%      void *NTOpenLibrary(const char *filename)
1739%
1740%  A description of each parameter follows:
1741%
1742%    o path: Specifies a pointer to string representing dynamic module that
1743%      is to be loaded.
1744%
1745*/
1746
1747static inline const char *GetSearchPath(void)
1748{
1749#if defined(MAGICKCORE_LTDL_DELEGATE)
1750  return(lt_dlgetsearchpath());
1751#else
1752  return(lt_slsearchpath);
1753#endif
1754}
1755
1756static UINT ChangeErrorMode(void)
1757{
1758  typedef UINT
1759    (CALLBACK *GETERRORMODE)(void);
1760
1761  GETERRORMODE
1762    getErrorMode;
1763
1764  HMODULE
1765    handle;
1766
1767  UINT
1768    mode;
1769
1770  mode=SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1771
1772  handle=GetModuleHandle("kernel32.dll");
1773  if (handle == (HMODULE) NULL)
1774    return SetErrorMode(mode);
1775
1776  getErrorMode=(GETERRORMODE) NTGetLibrarySymbol(handle,"GetErrorMode");
1777  if (getErrorMode != (GETERRORMODE) NULL)
1778    mode=getErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1779
1780  return SetErrorMode(mode);
1781}
1782
1783static inline void *NTLoadLibrary(const char *filename)
1784{
1785  int
1786    length;
1787
1788  wchar_t
1789    path[MagickPathExtent];
1790
1791  length=MultiByteToWideChar(CP_UTF8,0,filename,-1,path,MagickPathExtent);
1792  if (length == 0)
1793    return((void *) NULL);
1794  return (void *) LoadLibraryExW(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
1795}
1796
1797MagickPrivate void *NTOpenLibrary(const char *filename)
1798{
1799  char
1800    path[MagickPathExtent];
1801
1802  register const char
1803    *p,
1804    *q;
1805
1806  UINT
1807    mode;
1808
1809  void
1810    *handle;
1811
1812  mode=ChangeErrorMode();
1813  handle=NTLoadLibrary(filename);
1814  if (handle == (void *) NULL)
1815    {
1816      p=GetSearchPath();
1817      while (p != (const char*) NULL)
1818      {
1819        q=strchr(p,DirectoryListSeparator);
1820        if (q != (const char*) NULL)
1821          (void) CopyMagickString(path,p,q-p+1);
1822        else
1823          (void) CopyMagickString(path,p,MagickPathExtent);
1824        (void) ConcatenateMagickString(path,DirectorySeparator,MagickPathExtent);
1825        (void) ConcatenateMagickString(path,filename,MagickPathExtent);
1826        handle=NTLoadLibrary(path);
1827        if (handle != (void *) NULL || q == (const char*) NULL)
1828          break;
1829        p=q+1;
1830      }
1831    }
1832  SetErrorMode(mode);
1833  return(handle);
1834}
1835
1836/*
1837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1838%                                                                             %
1839%                                                                             %
1840%                                                                             %
1841%    N T R e a d D i r e c t o r y                                            %
1842%                                                                             %
1843%                                                                             %
1844%                                                                             %
1845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1846%
1847%  NTReadDirectory() returns a pointer to a structure representing the
1848%  directory entry at the current position in the directory stream to which
1849%  entry refers.
1850%
1851%  The format of the NTReadDirectory
1852%
1853%      NTReadDirectory(entry)
1854%
1855%  A description of each parameter follows:
1856%
1857%    o entry: Specifies a pointer to a DIR structure.
1858%
1859*/
1860MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
1861{
1862  int
1863    status;
1864
1865  size_t
1866    length;
1867
1868  if (entry == (DIR *) NULL)
1869    return((struct dirent *) NULL);
1870  if (!entry->firsttime)
1871    {
1872      status=FindNextFileW(entry->hSearch,&entry->Win32FindData);
1873      if (status == 0)
1874        return((struct dirent *) NULL);
1875    }
1876  length=WideCharToMultiByte(CP_UTF8,0,entry->Win32FindData.cFileName,-1,
1877    entry->file_info.d_name,sizeof(entry->file_info.d_name),NULL,NULL);
1878  if (length == 0)
1879    return((struct dirent *) NULL);
1880  entry->firsttime=FALSE;
1881  entry->file_info.d_namlen=(int) strlen(entry->file_info.d_name);
1882  return(&entry->file_info);
1883}
1884
1885/*
1886%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1887%                                                                             %
1888%                                                                             %
1889%                                                                             %
1890%   N T R e g i s t r y K e y L o o k u p                                     %
1891%                                                                             %
1892%                                                                             %
1893%                                                                             %
1894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1895%
1896%  NTRegistryKeyLookup() returns ImageMagick installation path settings
1897%  stored in the Windows Registry.  Path settings are specific to the
1898%  installed ImageMagick version so that multiple Image Magick installations
1899%  may coexist.
1900%
1901%  Values are stored in the registry under a base path path similar to
1902%  "HKEY_LOCAL_MACHINE/SOFTWARE\ImageMagick\6.7.4\Q:16" or
1903%  "HKEY_CURRENT_USER/SOFTWARE\ImageMagick\6.7.4\Q:16". The provided subkey
1904%  is appended to this base path to form the full key.
1905%
1906%  The format of the NTRegistryKeyLookup method is:
1907%
1908%      unsigned char *NTRegistryKeyLookup(const char *subkey)
1909%
1910%  A description of each parameter follows:
1911%
1912%    o subkey: Specifies a string that identifies the registry object.
1913%      Currently supported sub-keys include: "BinPath", "ConfigurePath",
1914%      "LibPath", "CoderModulesPath", "FilterModulesPath", "SharePath".
1915%
1916*/
1917MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
1918{
1919  char
1920    package_key[MagickPathExtent];
1921
1922  DWORD
1923    size,
1924    type;
1925
1926  HKEY
1927    registry_key;
1928
1929  LONG
1930    status;
1931
1932  unsigned char
1933    *value;
1934
1935  /*
1936    Look-up base key.
1937  */
1938  (void) FormatLocaleString(package_key,MagickPathExtent,"SOFTWARE\\%s\\%s\\Q:%d",
1939    MagickPackageName,MagickLibVersionText,MAGICKCORE_QUANTUM_DEPTH);
1940  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"%s",package_key);
1941  registry_key=(HKEY) INVALID_HANDLE_VALUE;
1942  status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,package_key,0,KEY_READ,&registry_key);
1943  if (status != ERROR_SUCCESS)
1944    status=RegOpenKeyExA(HKEY_CURRENT_USER,package_key,0,KEY_READ,
1945      &registry_key);
1946  if (status != ERROR_SUCCESS)
1947    {
1948      registry_key=(HKEY) INVALID_HANDLE_VALUE;
1949      return((unsigned char *) NULL);
1950    }
1951  /*
1952    Look-up sub key.
1953  */
1954  size=32;
1955  value=(unsigned char *) AcquireQuantumMemory(size,sizeof(*value));
1956  if (value == (unsigned char *) NULL)
1957    {
1958      RegCloseKey(registry_key);
1959      return((unsigned char *) NULL);
1960    }
1961  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"%s",subkey);
1962  status=RegQueryValueExA(registry_key,subkey,0,&type,value,&size);
1963  if ((status == ERROR_MORE_DATA) && (type == REG_SZ))
1964    {
1965      value=(unsigned char *) ResizeQuantumMemory(value,size,sizeof(*value));
1966      if (value == (BYTE *) NULL)
1967        {
1968          RegCloseKey(registry_key);
1969          return((unsigned char *) NULL);
1970        }
1971      status=RegQueryValueExA(registry_key,subkey,0,&type,value,&size);
1972    }
1973  RegCloseKey(registry_key);
1974  if ((type != REG_SZ) || (status != ERROR_SUCCESS))
1975    value=(unsigned char *) RelinquishMagickMemory(value);
1976  return((unsigned char *) value);
1977}
1978
1979/*
1980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1981%                                                                             %
1982%                                                                             %
1983%                                                                             %
1984%   N T R e p o r t E v e n t                                                 %
1985%                                                                             %
1986%                                                                             %
1987%                                                                             %
1988%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1989%
1990%  NTReportEvent() reports an event.
1991%
1992%  The format of the NTReportEvent method is:
1993%
1994%      MagickBooleanType NTReportEvent(const char *event,
1995%        const MagickBooleanType error)
1996%
1997%  A description of each parameter follows:
1998%
1999%    o event: the event.
2000%
2001%    o error: MagickTrue the event is an error.
2002%
2003*/
2004MagickPrivate MagickBooleanType NTReportEvent(const char *event,
2005  const MagickBooleanType error)
2006{
2007  const char
2008    *events[1];
2009
2010  HANDLE
2011    handle;
2012
2013  WORD
2014    type;
2015
2016  handle=RegisterEventSource(NULL,MAGICKCORE_PACKAGE_NAME);
2017  if (handle == NULL)
2018    return(MagickFalse);
2019  events[0]=event;
2020  type=error ? EVENTLOG_ERROR_TYPE : EVENTLOG_WARNING_TYPE;
2021  ReportEvent(handle,type,0,0,NULL,1,0,events,NULL);
2022  DeregisterEventSource(handle);
2023  return(MagickTrue);
2024}
2025
2026/*
2027%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2028%                                                                             %
2029%                                                                             %
2030%                                                                             %
2031%   N T R e s o u r c e T o B l o b                                           %
2032%                                                                             %
2033%                                                                             %
2034%                                                                             %
2035%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2036%
2037%  NTResourceToBlob() returns a blob containing the contents of the resource
2038%  in the current executable specified by the id parameter. This currently
2039%  used to retrieve MGK files tha have been embedded into the various command
2040%  line utilities.
2041%
2042%  The format of the NTResourceToBlob method is:
2043%
2044%      unsigned char *NTResourceToBlob(const char *id)
2045%
2046%  A description of each parameter follows:
2047%
2048%    o id: Specifies a string that identifies the resource.
2049%
2050*/
2051MagickPrivate unsigned char *NTResourceToBlob(const char *id)
2052{
2053
2054#ifndef MAGICKCORE_LIBRARY_NAME
2055  char
2056    path[MagickPathExtent];
2057#endif
2058
2059  DWORD
2060    length;
2061
2062  HGLOBAL
2063    global;
2064
2065  HMODULE
2066    handle;
2067
2068  HRSRC
2069    resource;
2070
2071  unsigned char
2072    *blob,
2073    *value;
2074
2075  assert(id != (const char *) NULL);
2076  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
2077#ifdef MAGICKCORE_LIBRARY_NAME
2078  handle=GetModuleHandle(MAGICKCORE_LIBRARY_NAME);
2079#else
2080  (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",GetClientPath(),
2081    DirectorySeparator,GetClientName());
2082  if (IsPathAccessible(path) != MagickFalse)
2083    handle=GetModuleHandle(path);
2084  else
2085    handle=GetModuleHandle(0);
2086#endif
2087  if (!handle)
2088    return((unsigned char *) NULL);
2089  resource=FindResource(handle,id,"IMAGEMAGICK");
2090  if (!resource)
2091    return((unsigned char *) NULL);
2092  global=LoadResource(handle,resource);
2093  if (!global)
2094    return((unsigned char *) NULL);
2095  length=SizeofResource(handle,resource);
2096  value=(unsigned char *) LockResource(global);
2097  if (!value)
2098    {
2099      FreeResource(global);
2100      return((unsigned char *) NULL);
2101    }
2102  blob=(unsigned char *) AcquireQuantumMemory(length+MagickPathExtent,
2103    sizeof(*blob));
2104  if (blob != (unsigned char *) NULL)
2105    {
2106      (void) CopyMagickMemory(blob,value,length);
2107      blob[length]='\0';
2108    }
2109  UnlockResource(global);
2110  FreeResource(global);
2111  return(blob);
2112}
2113
2114/*
2115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2116%                                                                             %
2117%                                                                             %
2118%                                                                             %
2119%   N T S e e k D i r e c t o r y                                             %
2120%                                                                             %
2121%                                                                             %
2122%                                                                             %
2123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2124%
2125%  NTSeekDirectory() sets the position of the next NTReadDirectory() operation
2126%  on the directory stream.
2127%
2128%  The format of the NTSeekDirectory method is:
2129%
2130%      void NTSeekDirectory(DIR *entry,ssize_t position)
2131%
2132%  A description of each parameter follows:
2133%
2134%    o entry: Specifies a pointer to a DIR structure.
2135%
2136%    o position: specifies the position associated with the directory
2137%      stream.
2138%
2139*/
2140MagickPrivate void NTSeekDirectory(DIR *entry,ssize_t position)
2141{
2142  (void) position;
2143  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2144  assert(entry != (DIR *) NULL);
2145}
2146
2147/*
2148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2149%                                                                             %
2150%                                                                             %
2151%                                                                             %
2152%   N T S e t S e a r c h P a t h                                             %
2153%                                                                             %
2154%                                                                             %
2155%                                                                             %
2156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2157%
2158%  NTSetSearchPath() sets the current locations that the subsystem should
2159%  look at to find dynamically loadable modules.
2160%
2161%  The format of the NTSetSearchPath method is:
2162%
2163%      int NTSetSearchPath(const char *path)
2164%
2165%  A description of each parameter follows:
2166%
2167%    o path: Specifies a pointer to string representing the search path
2168%      for DLL's that can be dynamically loaded.
2169%
2170*/
2171MagickPrivate int NTSetSearchPath(const char *path)
2172{
2173#if defined(MAGICKCORE_LTDL_DELEGATE)
2174  lt_dlsetsearchpath(path);
2175#else
2176  if (lt_slsearchpath != (char *) NULL)
2177    lt_slsearchpath=DestroyString(lt_slsearchpath);
2178  if (path != (char *) NULL)
2179    lt_slsearchpath=AcquireString(path);
2180#endif
2181  return(0);
2182}
2183
2184/*
2185%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2186%                                                                             %
2187%                                                                             %
2188%                                                                             %
2189+  N T S y n c M e m o r y                                                    %
2190%                                                                             %
2191%                                                                             %
2192%                                                                             %
2193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2194%
2195%  NTSyncMemory() emulates the Unix method of the same name.
2196%
2197%  The format of the NTSyncMemory method is:
2198%
2199%      int NTSyncMemory(void *address,size_t length,int flags)
2200%
2201%  A description of each parameter follows:
2202%
2203%    o address: the address of the binary large object.
2204%
2205%    o length: the length of the binary large object.
2206%
2207%    o flags: Option flags (ignored for Windows).
2208%
2209*/
2210MagickPrivate int NTSyncMemory(void *address,size_t length,int flags)
2211{
2212  (void) flags;
2213  if (FlushViewOfFile(address,length) == MagickFalse)
2214    return(-1);
2215  return(0);
2216}
2217
2218/*
2219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2220%                                                                             %
2221%                                                                             %
2222%                                                                             %
2223%   N T S y s t e m C o m m a n d                                             %
2224%                                                                             %
2225%                                                                             %
2226%                                                                             %
2227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2228%
2229%  NTSystemCommand() executes the specified command and waits until it
2230%  terminates.  The returned value is the exit status of the command.
2231%
2232%  The format of the NTSystemCommand method is:
2233%
2234%      int NTSystemCommand(MagickFalse,const char *command)
2235%
2236%  A description of each parameter follows:
2237%
2238%    o command: This string is the command to execute.
2239%
2240%    o output: an optional buffer to store the output from stderr/stdout.
2241%
2242*/
2243MagickPrivate int NTSystemCommand(const char *command,char *output)
2244{
2245#define CleanupOutputHandles \
2246  if (read_output != (HANDLE) NULL) \
2247    { \
2248       CloseHandle(read_output); \
2249       read_output=(HANDLE) NULL; \
2250       CloseHandle(write_output); \
2251       write_output=(HANDLE) NULL; \
2252    }
2253
2254#define CopyLastError \
2255  if (output != (char *) NULL) \
2256    { \
2257      error=NTGetLastError(); \
2258      if (error != (char *) NULL) \
2259        { \
2260          CopyMagickString(output,error,MagickPathExtent); \
2261          error=DestroyString(error); \
2262        } \
2263    }
2264
2265  char
2266    *error,
2267    local_command[MagickPathExtent];
2268
2269  DWORD
2270    bytes_read,
2271    child_status,
2272    size;
2273
2274  int
2275    status;
2276
2277  MagickBooleanType
2278    asynchronous;
2279
2280  HANDLE
2281    read_output,
2282    write_output;
2283
2284  PROCESS_INFORMATION
2285    process_info;
2286
2287  SECURITY_ATTRIBUTES
2288    sa;
2289
2290  STARTUPINFO
2291    startup_info;
2292
2293  if (command == (char *) NULL)
2294    return(-1);
2295  read_output=(HANDLE) NULL;
2296  write_output=(HANDLE) NULL;
2297  GetStartupInfo(&startup_info);
2298  startup_info.dwFlags=STARTF_USESHOWWINDOW;
2299  startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
2300  (void) CopyMagickString(local_command,command,MagickPathExtent);
2301  asynchronous=command[strlen(command)-1] == '&' ? MagickTrue : MagickFalse;
2302  if (asynchronous != MagickFalse)
2303    {
2304      local_command[strlen(command)-1]='\0';
2305      startup_info.wShowWindow=SW_SHOWDEFAULT;
2306    }
2307  else
2308    {
2309      if (command[strlen(command)-1] == '|')
2310        local_command[strlen(command)-1]='\0';
2311      else
2312        startup_info.wShowWindow=SW_HIDE;
2313      read_output=(HANDLE) NULL;
2314      if (output != (char *) NULL)
2315        {
2316          sa.nLength=sizeof(SECURITY_ATTRIBUTES);
2317          sa.bInheritHandle=TRUE;
2318          sa.lpSecurityDescriptor=NULL;
2319          if (CreatePipe(&read_output,&write_output,NULL,0))
2320            {
2321              if (SetHandleInformation(write_output,HANDLE_FLAG_INHERIT,
2322                  HANDLE_FLAG_INHERIT))
2323                {
2324                  startup_info.dwFlags|=STARTF_USESTDHANDLES;
2325                  startup_info.hStdOutput=write_output;
2326                  startup_info.hStdError=write_output;
2327                }
2328              else
2329                CleanupOutputHandles;
2330            }
2331          else
2332            read_output=(HANDLE) NULL;
2333        }
2334    }
2335  status=CreateProcess((LPCTSTR) NULL,local_command,(LPSECURITY_ATTRIBUTES)
2336    NULL,(LPSECURITY_ATTRIBUTES) NULL,(BOOL) TRUE,(DWORD)
2337    NORMAL_PRIORITY_CLASS,(LPVOID) NULL,(LPCSTR) NULL,&startup_info,
2338    &process_info);
2339  if (status == 0)
2340    {
2341      CopyLastError;
2342      CleanupOutputHandles;
2343      return(-1);
2344    }
2345  if (asynchronous != MagickFalse)
2346    return(status == 0);
2347  status=WaitForSingleObject(process_info.hProcess,INFINITE);
2348  if (status != WAIT_OBJECT_0)
2349    {
2350      CopyLastError;
2351      CleanupOutputHandles;
2352      return(status);
2353    }
2354  status=GetExitCodeProcess(process_info.hProcess,&child_status);
2355  if (status == 0)
2356    {
2357      CopyLastError;
2358      CleanupOutputHandles;
2359      return(-1);
2360    }
2361  CloseHandle(process_info.hProcess);
2362  CloseHandle(process_info.hThread);
2363  if (read_output != (HANDLE) NULL)
2364    if (PeekNamedPipe(read_output,(LPVOID) NULL,0,(LPDWORD) NULL,&size,
2365          (LPDWORD) NULL))
2366      if ((size > 0) && (ReadFile(read_output,output,MagickPathExtent-1,
2367          &bytes_read,NULL)))
2368        output[bytes_read]='\0';
2369  CleanupOutputHandles;
2370  return((int) child_status);
2371}
2372
2373/*
2374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2375%                                                                             %
2376%                                                                             %
2377%                                                                             %
2378%   N T S y s t e m C o n i f i g u r a t i o n                               %
2379%                                                                             %
2380%                                                                             %
2381%                                                                             %
2382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2383%
2384%  NTSystemConfiguration() provides a way for the application to determine
2385%  values for system limits or options at runtime.
2386%
2387%  The format of the exit method is:
2388%
2389%      ssize_t NTSystemConfiguration(int name)
2390%
2391%  A description of each parameter follows:
2392%
2393%    o name: _SC_PAGE_SIZE or _SC_PHYS_PAGES.
2394%
2395*/
2396MagickPrivate ssize_t NTSystemConfiguration(int name)
2397{
2398  switch (name)
2399  {
2400    case _SC_PAGESIZE:
2401    {
2402      SYSTEM_INFO
2403        system_info;
2404
2405      GetSystemInfo(&system_info);
2406      return(system_info.dwPageSize);
2407    }
2408    case _SC_PHYS_PAGES:
2409    {
2410      HMODULE
2411        handle;
2412
2413      LPFNDLLFUNC2
2414        module;
2415
2416      NTMEMORYSTATUSEX
2417        status;
2418
2419      SYSTEM_INFO
2420        system_info;
2421
2422      handle=GetModuleHandle("kernel32.dll");
2423      if (handle == (HMODULE) NULL)
2424        return(0L);
2425      GetSystemInfo(&system_info);
2426      module=(LPFNDLLFUNC2) NTGetLibrarySymbol(handle,"GlobalMemoryStatusEx");
2427      if (module == (LPFNDLLFUNC2) NULL)
2428        {
2429          MEMORYSTATUS
2430            global_status;
2431
2432          GlobalMemoryStatus(&global_status);
2433          return((ssize_t) global_status.dwTotalPhys/system_info.dwPageSize/4);
2434        }
2435      status.dwLength=sizeof(status);
2436      if (module(&status) == 0)
2437        return(0L);
2438      return((ssize_t) status.ullTotalPhys/system_info.dwPageSize/4);
2439    }
2440    case _SC_OPEN_MAX:
2441      return(2048);
2442    default:
2443      break;
2444  }
2445  return(-1);
2446}
2447
2448/*
2449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2450%                                                                             %
2451%                                                                             %
2452%                                                                             %
2453%   N T T e l l D i r e c t o r y                                             %
2454%                                                                             %
2455%                                                                             %
2456%                                                                             %
2457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2458%
2459%  NTTellDirectory() returns the current location associated with the named
2460%  directory stream.
2461%
2462%  The format of the NTTellDirectory method is:
2463%
2464%      ssize_t NTTellDirectory(DIR *entry)
2465%
2466%  A description of each parameter follows:
2467%
2468%    o entry: Specifies a pointer to a DIR structure.
2469%
2470*/
2471MagickPrivate ssize_t NTTellDirectory(DIR *entry)
2472{
2473  assert(entry != (DIR *) NULL);
2474  return(0);
2475}
2476
2477/*
2478%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2479%                                                                             %
2480%                                                                             %
2481%                                                                             %
2482%   N T T r u n c a t e F i l e                                               %
2483%                                                                             %
2484%                                                                             %
2485%                                                                             %
2486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2487%
2488%  NTTruncateFile() truncates a file to a specified length.
2489%
2490%  The format of the NTTruncateFile method is:
2491%
2492%      int NTTruncateFile(int file,off_t length)
2493%
2494%  A description of each parameter follows:
2495%
2496%    o file: the file.
2497%
2498%    o length: the file length.
2499%
2500*/
2501MagickPrivate int NTTruncateFile(int file,off_t length)
2502{
2503  DWORD
2504    file_pointer;
2505
2506  HANDLE
2507    file_handle;
2508
2509  long
2510    high,
2511    low;
2512
2513  file_handle=(HANDLE) _get_osfhandle(file);
2514  if (file_handle == INVALID_HANDLE_VALUE)
2515    return(-1);
2516  low=(long) (length & 0xffffffffUL);
2517  high=(long) ((((MagickOffsetType) length) >> 32) & 0xffffffffUL);
2518  file_pointer=SetFilePointer(file_handle,low,&high,FILE_BEGIN);
2519  if ((file_pointer == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
2520    return(-1);
2521  if (SetEndOfFile(file_handle) == 0)
2522    return(-1);
2523  return(0);
2524}
2525
2526/*
2527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2528%                                                                             %
2529%                                                                             %
2530%                                                                             %
2531+  N T U n m a p M e m o r y                                                  %
2532%                                                                             %
2533%                                                                             %
2534%                                                                             %
2535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2536%
2537%  NTUnmapMemory() emulates the Unix munmap method.
2538%
2539%  The format of the NTUnmapMemory method is:
2540%
2541%      int NTUnmapMemory(void *map,size_t length)
2542%
2543%  A description of each parameter follows:
2544%
2545%    o map: the address of the binary large object.
2546%
2547%    o length: the length of the binary large object.
2548%
2549*/
2550MagickPrivate int NTUnmapMemory(void *map,size_t length)
2551{
2552  (void) length;
2553  if (UnmapViewOfFile(map) == 0)
2554    return(-1);
2555  return(0);
2556}
2557
2558/*
2559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2560%                                                                             %
2561%                                                                             %
2562%                                                                             %
2563%   N T U s e r T i m e                                                       %
2564%                                                                             %
2565%                                                                             %
2566%                                                                             %
2567%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2568%
2569%  NTUserTime() returns the total time the process has been scheduled (e.g.
2570%  seconds) since the last call to StartTimer().
2571%
2572%  The format of the UserTime method is:
2573%
2574%      double NTUserTime(void)
2575%
2576*/
2577MagickPrivate double NTUserTime(void)
2578{
2579  DWORD
2580    status;
2581
2582  FILETIME
2583    create_time,
2584    exit_time;
2585
2586  OSVERSIONINFO
2587    OsVersionInfo;
2588
2589  union
2590  {
2591    FILETIME
2592      filetime;
2593
2594    __int64
2595      filetime64;
2596  } kernel_time;
2597
2598  union
2599  {
2600    FILETIME
2601      filetime;
2602
2603    __int64
2604      filetime64;
2605  } user_time;
2606
2607  OsVersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
2608  GetVersionEx(&OsVersionInfo);
2609  if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
2610    return(NTElapsedTime());
2611  status=GetProcessTimes(GetCurrentProcess(),&create_time,&exit_time,
2612    &kernel_time.filetime,&user_time.filetime);
2613  if (status != TRUE)
2614    return(0.0);
2615  return((double) 1.0e-7*(kernel_time.filetime64+user_time.filetime64));
2616}
2617
2618/*
2619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2620%                                                                             %
2621%                                                                             %
2622%                                                                             %
2623%   N T W a r n i n g H a n d l e r                                           %
2624%                                                                             %
2625%                                                                             %
2626%                                                                             %
2627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2628%
2629%  NTWarningHandler() displays a warning reason.
2630%
2631%  The format of the NTWarningHandler method is:
2632%
2633%      void NTWarningHandler(const ExceptionType severity,const char *reason,
2634%        const char *description)
2635%
2636%  A description of each parameter follows:
2637%
2638%    o severity: Specifies the numeric warning category.
2639%
2640%    o reason: Specifies the reason to display before terminating the
2641%      program.
2642%
2643%    o description: Specifies any description to the reason.
2644%
2645*/
2646MagickPrivate void NTWarningHandler(const ExceptionType severity,
2647  const char *reason,const char *description)
2648{
2649  char
2650    buffer[2*MagickPathExtent];
2651
2652  (void) severity;
2653  if (reason == (char *) NULL)
2654    return;
2655  if (description == (char *) NULL)
2656    (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s.\n",GetClientName(),
2657      reason);
2658  else
2659    (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s).\n",
2660      GetClientName(),reason,description);
2661  (void) MessageBox(NULL,buffer,"ImageMagick Warning",MB_OK | MB_TASKMODAL |
2662    MB_SETFOREGROUND | MB_ICONINFORMATION);
2663}
2664
2665/*
2666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2667%                                                                             %
2668%                                                                             %
2669%                                                                             %
2670%   N T W i n d o w s G e n e s i s                                           %
2671%                                                                             %
2672%                                                                             %
2673%                                                                             %
2674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2675%
2676%  NTWindowsGenesis() initializes the MagickCore Windows environment.
2677%
2678%  The format of the NTWindowsGenesis method is:
2679%
2680%      void NTWindowsGenesis(void)
2681%
2682*/
2683
2684static LONG WINAPI NTUncaughtException(EXCEPTION_POINTERS *info)
2685{
2686  AsynchronousResourceComponentTerminus();
2687  return(EXCEPTION_CONTINUE_SEARCH);
2688}
2689
2690MagickPrivate void NTWindowsGenesis(void)
2691{
2692  char
2693    *mode;
2694
2695  SetUnhandledExceptionFilter(NTUncaughtException);
2696  mode=GetEnvironmentValue("MAGICK_ERRORMODE");
2697  if (mode != (char *) NULL)
2698    {
2699      (void) SetErrorMode(StringToInteger(mode));
2700      mode=DestroyString(mode);
2701    }
2702#if defined(_DEBUG) && !defined(__BORLANDC__) && !defined(__MINGW32__) && !defined(__MINGW64__)
2703  if (IsEventLogging() != MagickFalse)
2704    {
2705      int
2706        debug;
2707
2708      debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
2709      debug|=_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_DELAY_FREE_MEM_DF |
2710        _CRTDBG_LEAK_CHECK_DF;
2711      (void) _CrtSetDbgFlag(debug);
2712      _ASSERTE(_CrtCheckMemory());
2713    }
2714#endif
2715}
2716
2717/*
2718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2719%                                                                             %
2720%                                                                             %
2721%                                                                             %
2722%   N T W i n d o w s T e r m i n u s                                         %
2723%                                                                             %
2724%                                                                             %
2725%                                                                             %
2726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2727%
2728%  NTWindowsTerminus() terminates the MagickCore Windows environment.
2729%
2730%  The format of the NTWindowsTerminus method is:
2731%
2732%      void NTWindowsTerminus(void)
2733%
2734*/
2735MagickPrivate void NTWindowsTerminus(void)
2736{
2737  NTGhostscriptUnLoadDLL();
2738  if (winsock_semaphore == (SemaphoreInfo *) NULL)
2739    ActivateSemaphoreInfo(&winsock_semaphore);
2740  LockSemaphoreInfo(winsock_semaphore);
2741  if (wsaData != (WSADATA *) NULL)
2742    {
2743      WSACleanup();
2744      wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData);
2745    }
2746  UnlockSemaphoreInfo(winsock_semaphore);
2747  RelinquishSemaphoreInfo(&winsock_semaphore);
2748}
2749#endif
2750