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