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