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