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