MagickCore  6.9.13-44
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/license/ %
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 "magick/studio.h"
42 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
43 #include "magick/client.h"
44 #include "magick/exception-private.h"
45 #include "magick/image-private.h"
46 #include "magick/locale_.h"
47 #include "magick/log.h"
48 #include "magick/magick.h"
49 #include "magick/memory_.h"
50 #include "magick/memory-private.h"
51 #include "magick/nt-base.h"
52 #include "magick/nt-base-private.h"
53 #include "magick/resource_.h"
54 #include "magick/timer.h"
55 #include "magick/string_.h"
56 #include "magick/string-private.h"
57 #include "magick/utility.h"
58 #include "magick/utility-private.h"
59 #include "magick/version.h"
60 #if defined(MAGICKCORE_LTDL_DELEGATE)
61 # include "ltdl.h"
62 #endif
63 #if defined(MAGICKCORE_CIPHER_SUPPORT)
64 #include <ntsecapi.h>
65 #include <wincrypt.h>
66 #endif
67 
68 /*
69  Define declarations.
70 */
71 #if !defined(MAP_FAILED)
72 #define MAP_FAILED ((void *)(LONG_PTR) -1)
73 #endif
74 #define MaxWideByteExtent 100
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[MaxWideByteExtent];
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,MaxWideByteExtent) == 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  magick_unreferenced(lpvReserved);
294 
295  switch (reason)
296  {
297  case DLL_PROCESS_ATTACH:
298  {
299  char
300  *module_path;
301 
302  ssize_t
303  count;
304 
305  wchar_t
306  *wide_path;
307 
308  MagickCoreGenesis((const char*) NULL,MagickFalse);
309  wide_path=(wchar_t *) NTAcquireQuantumMemory(MaxTextExtent,
310  sizeof(*wide_path));
311  if (wide_path == (wchar_t *) NULL)
312  return(FALSE);
313  count=(ssize_t) GetModuleFileNameW(handle,wide_path,MaxTextExtent);
314  if (count != 0)
315  {
316  char
317  *path;
318 
319  module_path=create_utf8_string(wide_path);
320  for ( ; count > 0; count--)
321  if (module_path[count] == '\\')
322  {
323  module_path[count+1]='\0';
324  break;
325  }
326  path=(char *) NTAcquireQuantumMemory(MaxTextExtent,16*sizeof(*path));
327  if (path == (char *) NULL)
328  {
329  module_path=DestroyString(module_path);
330  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
331  return(FALSE);
332  }
333  count=(ssize_t) GetEnvironmentVariable("PATH",path,16*MaxTextExtent);
334  if ((count != 0) && (strstr(path,module_path) == (char *) NULL))
335  {
336  if ((strlen(module_path)+count+1) < (16*MaxTextExtent-1))
337  {
338  char
339  *variable;
340 
341  variable=(char *) NTAcquireQuantumMemory(MaxTextExtent,
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*MaxTextExtent,
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 c c e s s W i d e %
447 % %
448 % %
449 % %
450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 %
452 % NTAccessWide() checks the file accessibility of a wide-character path.
453 #
454 # The format of the NTAccessWide method is:
455 %
456 % int NTAccessWide(const char *path, int mode)
457 %
458 % A description of each parameter follows:
459 %
460 % o path: the file path.
461 %
462 % o mode: the accessibility mode.
463 %
464 */
465 MagickExport int NTAccessWide(const char *path, int mode)
466 {
467  int
468  status;
469 
470  wchar_t
471  *path_wide;
472 
473  path_wide=NTCreateWidePath(path);
474  if (path_wide == (wchar_t *) NULL)
475  return(-1);
476  status=_waccess(path_wide,mode);
477  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
478  return(status);
479 }
480 
481 /*
482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483 % %
484 % %
485 % %
486 % N T A r g v T o U T F 8 %
487 % %
488 % %
489 % %
490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491 %
492 % NTArgvToUTF8() converts the wide command line arguments to UTF-8 to ensure
493 % compatibility with Linux.
494 %
495 % The format of the NTArgvToUTF8 method is:
496 %
497 % char **NTArgvToUTF8(const int argc,wchar_t **argv)
498 %
499 % A description of each parameter follows:
500 %
501 % o argc: the number of command line arguments.
502 %
503 % o argv: the wide-character command line arguments.
504 %
505 */
506 MagickPrivate char **NTArgvToUTF8(const int argc,wchar_t **argv)
507 {
508  char
509  **utf8;
510 
511  ssize_t
512  i;
513 
514  utf8=(char **) NTAcquireQuantumMemory(argc,sizeof(*utf8));
515  if (utf8 == (char **) NULL)
516  ThrowFatalException(ResourceLimitFatalError,"UnableToConvertStringToARGV");
517  for (i=0; i < (ssize_t) argc; i++)
518  {
519  utf8[i]=create_utf8_string(argv[i]);
520  if (utf8[i] == (char *) NULL)
521  {
522  for (i--; i >= 0; i--)
523  utf8[i]=DestroyString(utf8[i]);
524  ThrowFatalException(ResourceLimitFatalError,
525  "UnableToConvertStringToARGV");
526  }
527  }
528  return(utf8);
529 }
530 
531 /*
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 % %
534 % %
535 % %
536 % N T C l o s e D i r e c t o r y %
537 % %
538 % %
539 % %
540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541 %
542 % NTCloseDirectory() closes the named directory stream and frees the DIR
543 % structure.
544 %
545 % The format of the NTCloseDirectory method is:
546 %
547 % int NTCloseDirectory(DIR *entry)
548 %
549 % A description of each parameter follows:
550 %
551 % o entry: Specifies a pointer to a DIR structure.
552 %
553 */
554 MagickPrivate int NTCloseDirectory(DIR *entry)
555 {
556  assert(entry != (DIR *) NULL);
557  if (IsEventLogging() != MagickFalse)
558  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
559  FindClose(entry->hSearch);
560  entry=(DIR *) RelinquishMagickMemory(entry);
561  return(0);
562 }
563 
564 /*
565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
566 % %
567 % %
568 % %
569 % N T C l o s e L i b r a r y %
570 % %
571 % %
572 % %
573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 %
575 % NTCloseLibrary() unloads the module associated with the passed handle.
576 %
577 % The format of the NTCloseLibrary method is:
578 %
579 % void NTCloseLibrary(void *handle)
580 %
581 % A description of each parameter follows:
582 %
583 % o handle: Specifies a handle to a previously loaded dynamic module.
584 %
585 */
586 MagickPrivate int NTCloseLibrary(void *handle)
587 {
588  return(!(FreeLibrary((HINSTANCE) handle)));
589 }
590 
591 /*
592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 % %
594 % %
595 % %
596 % N T C r e a t e W i d e P a t h %
597 % %
598 % %
599 % %
600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601 %
602 % NTCreateWidePath() returns the wide-character version of the specified
603 % UTF-8 path.
604 %
605 % The format of the NTCreateWidePath method is:
606 %
607 % void NTCreateWidePath(void *handle)
608 %
609 % A description of each parameter follows:
610 %
611 % o utf8: Specifies a handle to a previously loaded dynamic module.
612 %
613 */
614 MagickExport wchar_t* NTCreateWidePath(const char *utf8)
615 {
616  int
617  count;
618 
619  wchar_t
620  *wide;
621 
622  count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);
623  if ((count > MAX_PATH) && (strncmp(utf8,"\\\\?\\",4) != 0) &&
624  (NTLongPathsEnabled() == MagickFalse))
625  {
626  char
627  buffer[MagickPathExtent];
628 
629  wchar_t
630  shortPath[MAX_PATH],
631  *longPath;
632 
633  size_t
634  length;
635 
636  (void) FormatLocaleString(buffer,MagickPathExtent,"\\\\?\\%s",utf8);
637  count+=4;
638  longPath=(wchar_t *) NTAcquireQuantumMemory((size_t) count,
639  sizeof(*longPath));
640  if (longPath == (wchar_t *) NULL)
641  return((wchar_t *) NULL);
642  count=MultiByteToWideChar(CP_UTF8,0,buffer,-1,longPath,count);
643  if (count != 0)
644  count=(int) GetShortPathNameW(longPath,shortPath,MAX_PATH);
645  longPath=(wchar_t *) RelinquishMagickMemory(longPath);
646  if ((count < 5) || (count >= MAX_PATH))
647  return((wchar_t *) NULL);
648  length=(size_t) count-3;
649  wide=(wchar_t *) NTAcquireQuantumMemory(length,sizeof(*wide));
650  wcscpy_s(wide,length,shortPath+4);
651  return(wide);
652  }
653  wide=(wchar_t *) NTAcquireQuantumMemory((size_t) count,sizeof(*wide));
654  if ((wide != (wchar_t *) NULL) &&
655  (MultiByteToWideChar(CP_UTF8,0,utf8,-1,wide,count) == 0))
656  wide=(wchar_t *) RelinquishMagickMemory(wide);
657  return(wide);
658 }
659 
660 /*
661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662 % %
663 % %
664 % %
665 % N T C o n t r o l H a n d l e r %
666 % %
667 % %
668 % %
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 %
671 % NTControlHandler() registers a control handler that is activated when, for
672 % example, a ctrl-c is received.
673 %
674 % The format of the NTControlHandler method is:
675 %
676 % int NTControlHandler(void)
677 %
678 */
679 
680 static BOOL ControlHandler(DWORD type)
681 {
682  (void) type;
683  AsynchronousResourceComponentTerminus();
684  return(FALSE);
685 }
686 
687 MagickPrivate int NTControlHandler(void)
688 {
689  return(SetConsoleCtrlHandler((PHANDLER_ROUTINE) ControlHandler,TRUE));
690 }
691 
692 /*
693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694 % %
695 % %
696 % %
697 % N T E l a p s e d T i m e %
698 % %
699 % %
700 % %
701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702 %
703 % NTElapsedTime() returns the elapsed time (in seconds) since the last call to
704 % StartTimer().
705 %
706 % The format of the ElapsedTime method is:
707 %
708 % double NTElapsedTime(void)
709 %
710 */
711 MagickPrivate double NTElapsedTime(void)
712 {
713  union
714  {
715  FILETIME
716  filetime;
717 
718  __int64
719  filetime64;
720  } elapsed_time;
721 
722  LARGE_INTEGER
723  performance_count;
724 
725  static LARGE_INTEGER
726  frequency = { 0 };
727 
728  SYSTEMTIME
729  system_time;
730 
731  if (frequency.QuadPart == 0)
732  {
733  if (QueryPerformanceFrequency(&frequency) == 0)
734  frequency.QuadPart=1;
735  }
736  if (frequency.QuadPart > 1)
737  {
738  QueryPerformanceCounter(&performance_count);
739  return((double) performance_count.QuadPart/frequency.QuadPart);
740  }
741  GetSystemTime(&system_time);
742  SystemTimeToFileTime(&system_time,&elapsed_time.filetime);
743  return((double) 1.0e-7*elapsed_time.filetime64);
744 }
745 
746 /*
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748 % %
749 % %
750 % %
751 + N T E r r o r H a n d l e r %
752 % %
753 % %
754 % %
755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
756 %
757 % NTErrorHandler() displays an error reason and then terminates the program.
758 %
759 % The format of the NTErrorHandler method is:
760 %
761 % void NTErrorHandler(const ExceptionType severity,const char *reason,
762 % const char *description)
763 %
764 % A description of each parameter follows:
765 %
766 % o severity: Specifies the numeric error category.
767 %
768 % o reason: Specifies the reason to display before terminating the
769 % program.
770 %
771 % o description: Specifies any description to the reason.
772 %
773 */
774 MagickPrivate void NTErrorHandler(const ExceptionType severity,
775  const char *reason,const char *description)
776 {
777  char
778  buffer[3*MaxTextExtent],
779  *message;
780 
781  (void) severity;
782  if (reason == (char *) NULL)
783  {
784  MagickCoreTerminus();
785  exit(0);
786  }
787  message=GetExceptionMessage(errno);
788  if ((description != (char *) NULL) && errno)
789  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s) [%s].\n",
790  GetClientName(),reason,description,message);
791  else
792  if (description != (char *) NULL)
793  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
794  GetClientName(),reason,description);
795  else
796  if (errno != 0)
797  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s [%s].\n",
798  GetClientName(),reason,message);
799  else
800  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",
801  GetClientName(),reason);
802  message=DestroyString(message);
803  (void) MessageBox(NULL,buffer,"ImageMagick Exception",MB_OK | MB_TASKMODAL |
804  MB_SETFOREGROUND | MB_ICONEXCLAMATION);
805  MagickCoreTerminus();
806  exit(0);
807 }
808 
809 /*
810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
811 % %
812 % %
813 % %
814 % N T E x i t L i b r a r y %
815 % %
816 % %
817 % %
818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819 %
820 % NTExitLibrary() exits the dynamic module loading subsystem.
821 %
822 % The format of the NTExitLibrary method is:
823 %
824 % int NTExitLibrary(void)
825 %
826 */
827 MagickPrivate int NTExitLibrary(void)
828 {
829  return(0);
830 }
831 
832 /*
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834 % %
835 % %
836 % %
837 % N T G a t h e r R a n d o m D a t a %
838 % %
839 % %
840 % %
841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842 %
843 % NTGatherRandomData() gathers random data and returns it.
844 %
845 % The format of the GatherRandomData method is:
846 %
847 % MagickBooleanType NTGatherRandomData(const size_t length,
848 % unsigned char *random)
849 %
850 % A description of each parameter follows:
851 %
852 % length: the length of random data buffer
853 %
854 % random: the random data is returned here.
855 %
856 */
857 MagickPrivate MagickBooleanType NTGatherRandomData(const size_t length,
858  unsigned char *random)
859 {
860 #if defined(MAGICKCORE_CIPHER_SUPPORT) && defined(_MSC_VER) && (_MSC_VER > 1200)
861  HCRYPTPROV
862  handle;
863 
864  int
865  status;
866 
867  handle=(HCRYPTPROV) NULL;
868  status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
869  (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET));
870  if (status == 0)
871  status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
872  (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET));
873  if (status == 0)
874  return(MagickFalse);
875  status=CryptGenRandom(handle,(DWORD) length,random);
876  if (status == 0)
877  {
878  status=CryptReleaseContext(handle,0);
879  return(MagickFalse);
880  }
881  status=CryptReleaseContext(handle,0);
882  if (status == 0)
883  return(MagickFalse);
884 #else
885  (void) random;
886  (void) length;
887 #endif
888  return(MagickTrue);
889 }
890 
891 /*
892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
893 % %
894 % %
895 % %
896 % N T G e t E n v i r o n m e n t V a l u e %
897 % %
898 % %
899 % %
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 %
902 % NTGetEnvironmentValue() returns the environment string that matches the
903 % specified name.
904 %
905 % The format of the NTGetEnvironmentValue method is:
906 %
907 % char *GetEnvironmentValue(const char *name)
908 %
909 % A description of each parameter follows:
910 %
911 % o name: the environment name.
912 %
913 */
914 extern MagickPrivate char *NTGetEnvironmentValue(const char *name)
915 {
916  char
917  *environment = (char *) NULL;
918 
919  DWORD
920  size;
921 
922  LPWSTR
923  wide;
924 
925  wchar_t
926  wide_name[MaxWideByteExtent];
927 
928  if (MultiByteToWideChar(CP_UTF8,0,name,-1,wide_name,MaxWideByteExtent) == 0)
929  return(environment);
930  size=GetEnvironmentVariableW(wide_name,(LPWSTR) NULL,0);
931  if (size == 0)
932  return(environment);
933  wide=(LPWSTR) NTAcquireQuantumMemory((const size_t) size,sizeof(*wide));
934  if (wide == (LPWSTR) NULL)
935  return(environment);
936  if (GetEnvironmentVariableW(wide_name,wide,size) != 0)
937  environment=create_utf8_string(wide);
938  wide=(LPWSTR) RelinquishMagickMemory(wide);
939  return(environment);
940 }
941 
942 /*
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 % %
945 % %
946 % %
947 % N T G e t E x e c u t i o n P a t h %
948 % %
949 % %
950 % %
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 %
953 % NTGetExecutionPath() returns the execution path of a program.
954 %
955 % The format of the GetExecutionPath method is:
956 %
957 % MagickBooleanType NTGetExecutionPath(char *path,const size_t extent)
958 %
959 % A description of each parameter follows:
960 %
961 % o path: the pathname of the executable that started the process.
962 %
963 % o extent: the maximum extent of the path.
964 %
965 */
966 MagickPrivate MagickBooleanType NTGetExecutionPath(char *path,
967  const size_t extent)
968 {
969  wchar_t
970  wide_path[MaxTextExtent];
971 
972  (void) GetModuleFileNameW((HMODULE) NULL,wide_path,(DWORD) extent);
973  (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,
974  NULL);
975  return(MagickTrue);
976 }
977 
978 /*
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 % %
981 % %
982 % %
983 % N T G e t L a s t E r r o r M e s s a g e %
984 % %
985 % %
986 % %
987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
988 %
989 % NTGetLastErrorMessage() returns the last error that occurred.
990 %
991 % The format of the NTGetLastErrorMessage method is:
992 %
993 % char *NTGetLastErrorMessage(DWORD last_error)
994 %
995 % A description of each parameter follows:
996 %
997 % o last_error: The value of GetLastError.
998 %
999 */
1000 static char *NTGetLastErrorMessage(DWORD last_error)
1001 {
1002  char
1003  *reason;
1004 
1005  int
1006  status;
1007 
1008  LPVOID
1009  buffer = (LPVOID) NULL;
1010 
1011  status=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1012  FORMAT_MESSAGE_FROM_SYSTEM,NULL,last_error,
1013  MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR) &buffer,0,NULL);
1014  if (!status)
1015  reason=AcquireString("An unknown error occurred");
1016  else
1017  {
1018  reason=AcquireString((const char *) buffer);
1019  LocalFree(buffer);
1020  }
1021  return(reason);
1022 }
1023 
1024 /*
1025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 % %
1027 % %
1028 % %
1029 % N T G e t L i b r a r y E r r o r %
1030 % %
1031 % %
1032 % %
1033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 %
1035 % Lt_dlerror() returns a pointer to a string describing the last error
1036 % associated with a lt_dl method. Note that this function is not thread
1037 % safe so it should only be used under the protection of a lock.
1038 %
1039 % The format of the NTGetLibraryError method is:
1040 %
1041 % const char *NTGetLibraryError(void)
1042 %
1043 */
1044 MagickPrivate const char *NTGetLibraryError(void)
1045 {
1046  static char
1047  last_error[MaxTextExtent];
1048 
1049  char
1050  *error;
1051 
1052  *last_error='\0';
1053  error=NTGetLastErrorMessage(GetLastError());
1054  if (error)
1055  (void) CopyMagickString(last_error,error,MaxTextExtent);
1056  error=DestroyString(error);
1057  return(last_error);
1058 }
1059 
1060 /*
1061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062 % %
1063 % %
1064 % %
1065 % N T G e t L i b r a r y S y m b o l %
1066 % %
1067 % %
1068 % %
1069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070 %
1071 % NTGetLibrarySymbol() retrieve the procedure address of the method
1072 % specified by the passed character string.
1073 %
1074 % The format of the NTGetLibrarySymbol method is:
1075 %
1076 % void *NTGetLibrarySymbol(void *handle,const char *name)
1077 %
1078 % A description of each parameter follows:
1079 %
1080 % o handle: Specifies a handle to the previously loaded dynamic module.
1081 %
1082 % o name: Specifies the procedure entry point to be returned.
1083 %
1084 */
1085 void *NTGetLibrarySymbol(void *handle,const char *name)
1086 {
1087  FARPROC
1088  proc_address;
1089 
1090  proc_address=GetProcAddress((HMODULE) handle,(LPCSTR) name);
1091  if (proc_address == (FARPROC) NULL)
1092  return((void *) NULL);
1093  return((void *) proc_address);
1094 }
1095 
1096 /*
1097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098 % %
1099 % %
1100 % %
1101 % N T G e t M o d u l e P a t h %
1102 % %
1103 % %
1104 % %
1105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106 %
1107 % NTGetModulePath() returns the path of the specified module.
1108 %
1109 % The format of the GetModulePath method is:
1110 %
1111 % MagickBooleanType NTGetModulePath(const char *module,char *path)
1112 %
1113 % A description of each parameter follows:
1114 %
1115 % modith: the module name.
1116 %
1117 % path: the module path is returned here.
1118 %
1119 */
1120 MagickPrivate MagickBooleanType NTGetModulePath(const char *module,char *path)
1121 {
1122  char
1123  module_path[MaxTextExtent];
1124 
1125  HMODULE
1126  handle;
1127 
1128  ssize_t
1129  length;
1130 
1131  *path='\0';
1132  handle=GetModuleHandle(module);
1133  if (handle == (HMODULE) NULL)
1134  return(MagickFalse);
1135  length=GetModuleFileName(handle,module_path,MaxTextExtent);
1136  if (length != 0)
1137  GetPathComponent(module_path,HeadPath,path);
1138  return(MagickTrue);
1139 }
1140 
1141 /*
1142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1143 % %
1144 % %
1145 % %
1146 % N T G h o s t s c r i p t D L L V e c t o r s %
1147 % %
1148 % %
1149 % %
1150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1151 %
1152 % NTGhostscriptDLLVectors() returns a GhostInfo structure that includes
1153 % function vectors to invoke Ghostscript DLL functions. A null pointer is
1154 % returned if there is an error when loading the DLL or retrieving the
1155 % function vectors.
1156 %
1157 % The format of the NTGhostscriptDLLVectors method is:
1158 %
1159 % const GhostInfo *NTGhostscriptDLLVectors(void)
1160 %
1161 */
1162 static int NTLocateGhostscript(DWORD flags,int *root_index,
1163  const char **product_family,int *major_version,int *minor_version,
1164  int *patch_version)
1165 {
1166  int
1167  i;
1168 
1169  MagickBooleanType
1170  status;
1171 
1172  static const char
1173  *products[2] =
1174  {
1175  "Artifex Ghostscript",
1176  "GPL Ghostscript"
1177  };
1178 
1179  /*
1180  Find the most recent version of Ghostscript.
1181  */
1182  status=MagickFalse;
1183  *root_index=0;
1184  *product_family=NULL;
1185  *major_version=5;
1186  *minor_version=49; /* min version of Ghostscript is 5.50 */
1187  for (i=0; i < (ssize_t) (sizeof(products)/sizeof(products[0])); i++)
1188  {
1189  char
1190  key[MagickPathExtent];
1191 
1192  HKEY
1193  hkey;
1194 
1195  int
1196  j;
1197 
1198  REGSAM
1199  mode;
1200 
1201  (void) FormatLocaleString(key,MagickPathExtent,"SOFTWARE\\%s",products[i]);
1202  for (j=0; j < (ssize_t) (sizeof(registry_roots)/sizeof(registry_roots[0]));
1203  j++)
1204  {
1205  mode=KEY_READ | flags;
1206  if (RegOpenKeyExA(registry_roots[j].hkey,key,0,mode,&hkey) ==
1207  ERROR_SUCCESS)
1208  {
1209  DWORD
1210  extent;
1211 
1212  int
1213  k;
1214 
1215  /*
1216  Now enumerate the keys.
1217  */
1218  extent=sizeof(key)/sizeof(char);
1219  for (k=0; RegEnumKeyA(hkey,k,key,extent) == ERROR_SUCCESS; k++)
1220  {
1221  int
1222  major,
1223  minor,
1224  patch;
1225 
1226  major=0;
1227  minor=0;
1228  patch=0;
1229  if (sscanf(key,"%d.%d.%d",&major,&minor,&patch) != 3)
1230  if (sscanf(key,"%d.%d",&major,&minor) != 2)
1231  continue;
1232  if ((major > *major_version) ||
1233  ((major == *major_version) && (minor > *minor_version)) ||
1234  ((minor == *minor_version) && (patch > *patch_version)))
1235  {
1236  *root_index=j;
1237  *product_family=products[i];
1238  *major_version=major;
1239  *minor_version=minor;
1240  *patch_version=patch;
1241  status=MagickTrue;
1242  }
1243  }
1244  (void) RegCloseKey(hkey);
1245  }
1246  }
1247  }
1248  if (status == MagickFalse)
1249  {
1250  *major_version=0;
1251  *minor_version=0;
1252  *patch_version=0;
1253  }
1254  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"Ghostscript (%s) "
1255  "version %d.%d.%d",*product_family,*major_version,*minor_version,*patch_version);
1256  return(status);
1257 }
1258 
1259 static MagickBooleanType NTGhostscriptGetString(const char *name,
1260  BOOL *is_64_bit,char *value,const size_t length)
1261 {
1262  char
1263  buffer[MagickPathExtent],
1264  *directory;
1265 
1266  static const char
1267  *product_family = (const char *) NULL;
1268 
1269  static BOOL
1270  is_64_bit_version = FALSE;
1271 
1272  static int
1273  flags = 0,
1274  major_version = 0,
1275  minor_version = 0,
1276  patch_version = 0,
1277  root_index = 0;
1278 
1279  unsigned char
1280  *registry_value;
1281 
1282  /*
1283  Get a string from the installed Ghostscript.
1284  */
1285  *value='\0';
1286  directory=(char *) NULL;
1287  if (LocaleCompare(name,"GS_DLL") == 0)
1288  {
1289  directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_PATH");
1290  if (directory != (char *) NULL)
1291  {
1292  (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll64.dll",
1293  directory,DirectorySeparator);
1294  if (IsPathAccessible(buffer) != MagickFalse)
1295  {
1296  directory=DestroyString(directory);
1297  (void) CopyMagickString(value,buffer,length);
1298  if (is_64_bit != NULL)
1299  *is_64_bit=TRUE;
1300  return(MagickTrue);
1301  }
1302  (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll32.dll",
1303  directory,DirectorySeparator);
1304  if (IsPathAccessible(buffer) != MagickFalse)
1305  {
1306  directory=DestroyString(directory);
1307  (void) CopyMagickString(value,buffer,length);
1308  if (is_64_bit != NULL)
1309  *is_64_bit=FALSE;
1310  return(MagickTrue);
1311  }
1312  return(MagickFalse);
1313  }
1314  }
1315  if (product_family == (const char *) NULL)
1316  {
1317  flags=0;
1318 #if defined(KEY_WOW64_32KEY)
1319 #if defined(_WIN64)
1320  flags=KEY_WOW64_64KEY;
1321 #else
1322  flags=KEY_WOW64_32KEY;
1323 #endif
1324  (void) NTLocateGhostscript(flags,&root_index,&product_family,
1325  &major_version,&minor_version,&patch_version);
1326  if (product_family == (const char *) NULL)
1327 #if defined(_WIN64)
1328  flags=KEY_WOW64_32KEY;
1329  else
1330  is_64_bit_version=TRUE;
1331 #else
1332  flags=KEY_WOW64_64KEY;
1333 #endif
1334 #endif
1335  }
1336  if (product_family == (const char *) NULL)
1337  {
1338  (void) NTLocateGhostscript(flags,&root_index,&product_family,
1339  &major_version,&minor_version,&patch_version);
1340 #if !defined(_WIN64)
1341  is_64_bit_version=TRUE;
1342 #endif
1343  }
1344  if (product_family == (const char *) NULL)
1345  return(MagickFalse);
1346  if (is_64_bit != NULL)
1347  *is_64_bit=is_64_bit_version;
1348  (void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%.2d.%d",
1349  product_family,major_version,minor_version,patch_version);
1350  registry_value=NTGetRegistryValue(registry_roots[root_index].hkey,buffer,
1351  flags,name);
1352  if (registry_value == (unsigned char *) NULL)
1353  {
1354  (void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%02d",
1355  product_family,major_version,minor_version);
1356  registry_value=NTGetRegistryValue(registry_roots[root_index].hkey,buffer,
1357  flags,name);
1358  }
1359  if (registry_value == (unsigned char *) NULL)
1360  return(MagickFalse);
1361  (void) CopyMagickString(value,(const char *) registry_value,length);
1362  registry_value=(unsigned char *) RelinquishMagickMemory(registry_value);
1363  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1364  "registry: \"%s\\%s\\%s\"=\"%s\"",registry_roots[root_index].name,
1365  buffer,name,value);
1366  return(MagickTrue);
1367 }
1368 
1369 static MagickBooleanType NTGhostscriptDLL(char *path,int length)
1370 {
1371  static char
1372  dll[MagickPathExtent] = { "" };
1373 
1374  static BOOL
1375  is_64_bit;
1376 
1377  *path='\0';
1378  if ((*dll == '\0') &&
1379  (NTGhostscriptGetString("GS_DLL",&is_64_bit,dll,sizeof(dll)) != MagickTrue))
1380  return(MagickFalse);
1381 #if defined(_WIN64)
1382  if (!is_64_bit)
1383  return(MagickFalse);
1384 #else
1385  if (is_64_bit)
1386  return(MagickFalse);
1387 #endif
1388  (void) CopyMagickString(path,dll,length);
1389  return(MagickTrue);
1390 }
1391 
1392 static inline MagickBooleanType NTGhostscriptHasValidHandle()
1393 {
1394  if ((nt_ghost_info.delete_instance == NULL) || (ghost_info.exit == NULL) ||
1395  (nt_ghost_info.new_instance == NULL) || (ghost_info.set_stdio == NULL) ||
1396  (ghost_info.init_with_args == NULL) || (ghost_info.revision == NULL))
1397  return(MagickFalse);
1398  return(MagickTrue);
1399 }
1400 
1401 MagickPrivate const GhostInfo *NTGhostscriptDLLVectors(void)
1402 {
1403  char
1404  path[MaxTextExtent];
1405 
1406  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1407  ActivateSemaphoreInfo(&ghost_semaphore);
1408  LockSemaphoreInfo(ghost_semaphore);
1409  if (ghost_handle != (void *) NULL)
1410  {
1411  UnlockSemaphoreInfo(ghost_semaphore);
1412  if (NTGhostscriptHasValidHandle() == MagickFalse)
1413  return((GhostInfo *) NULL);
1414  return(&ghost_info);
1415  }
1416  if (NTGhostscriptDLL(path,sizeof(path)) == MagickFalse)
1417  {
1418  UnlockSemaphoreInfo(ghost_semaphore);
1419  return(FALSE);
1420  }
1421  ghost_handle=lt_dlopen(path);
1422  if (ghost_handle == (void *) NULL)
1423  {
1424  UnlockSemaphoreInfo(ghost_semaphore);
1425  return(FALSE);
1426  }
1427  (void) memset((void *) &nt_ghost_info,0,sizeof(NTGhostInfo));
1428  nt_ghost_info.delete_instance=(void (MagickDLLCall *)(gs_main_instance *)) (
1429  lt_dlsym(ghost_handle,"gsapi_delete_instance"));
1430  nt_ghost_info.new_instance=(int (MagickDLLCall *)(gs_main_instance **,
1431  void *)) (lt_dlsym(ghost_handle,"gsapi_new_instance"));
1432  nt_ghost_info.has_instance=MagickFalse;
1433  (void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
1434  ghost_info.delete_instance=NTGhostscriptDeleteInstance;
1435  ghost_info.exit=(int (MagickDLLCall *)(gs_main_instance*))
1436  lt_dlsym(ghost_handle,"gsapi_exit");
1437  ghost_info.init_with_args=(int (MagickDLLCall *)(gs_main_instance *,int,
1438  char **)) (lt_dlsym(ghost_handle,"gsapi_init_with_args"));
1439  ghost_info.new_instance=NTGhostscriptNewInstance;
1440  ghost_info.run_string=(int (MagickDLLCall *)(gs_main_instance *,const char *,
1441  int,int *)) (lt_dlsym(ghost_handle,"gsapi_run_string"));
1442  ghost_info.set_stdio=(int (MagickDLLCall *)(gs_main_instance *,int(
1443  MagickDLLCall *)(void *,char *,int),int(MagickDLLCall *)(void *,
1444  const char *,int),int(MagickDLLCall *)(void *,const char *,int)))
1445  (lt_dlsym(ghost_handle,"gsapi_set_stdio"));
1446  ghost_info.revision=(int (MagickDLLCall *)(gsapi_revision_t *,int)) (
1447  lt_dlsym(ghost_handle,"gsapi_revision"));
1448  UnlockSemaphoreInfo(ghost_semaphore);
1449  if (NTGhostscriptHasValidHandle() == MagickFalse)
1450  return((GhostInfo *) NULL);
1451  return(&ghost_info);
1452 }
1453 
1454 /*
1455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1456 % %
1457 % %
1458 % %
1459 % N T G h o s t s c r i p t E X E %
1460 % %
1461 % %
1462 % %
1463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1464 %
1465 % NTGhostscriptEXE() obtains the path to the latest Ghostscript executable.
1466 % The method returns FALSE if a full path value is not obtained and returns
1467 % a default path of gswin32c.exe.
1468 %
1469 % The format of the NTGhostscriptEXE method is:
1470 %
1471 % int NTGhostscriptEXE(char *path,int length)
1472 %
1473 % A description of each parameter follows:
1474 %
1475 % o path: return the Ghostscript executable path here.
1476 %
1477 % o length: length of buffer.
1478 %
1479 */
1480 MagickPrivate int NTGhostscriptEXE(char *path,int length)
1481 {
1482  char
1483  *p;
1484 
1485  static char
1486  program[MaxTextExtent] = { "" };
1487 
1488  static BOOL
1489  is_64_bit_version = FALSE;
1490 
1491  if (*program == '\0')
1492  {
1493  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1494  ActivateSemaphoreInfo(&ghost_semaphore);
1495  LockSemaphoreInfo(ghost_semaphore);
1496  if (*program == '\0')
1497  {
1498  if (NTGhostscriptGetString("GS_DLL",&is_64_bit_version,program,
1499  sizeof(program)) == MagickFalse)
1500  {
1501  UnlockSemaphoreInfo(ghost_semaphore);
1502 #if defined(_WIN64)
1503  (void) CopyMagickString(program,"gswin64c.exe",sizeof(program));
1504 #else
1505  (void) CopyMagickString(program,"gswin32c.exe",sizeof(program));
1506 #endif
1507  (void) CopyMagickString(path,program,length);
1508  return(FALSE);
1509  }
1510  p=strrchr(program,'\\');
1511  if (p != (char *) NULL)
1512  {
1513  p++;
1514  *p='\0';
1515  (void) ConcatenateMagickString(program,is_64_bit_version ?
1516  "gswin64c.exe" : "gswin32c.exe",sizeof(program));
1517  }
1518  }
1519  UnlockSemaphoreInfo(ghost_semaphore);
1520  }
1521  (void) CopyMagickString(path,program,length);
1522  return(TRUE);
1523 }
1524 
1525 /*
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 % %
1528 % %
1529 % %
1530 % N T G h o s t s c r i p t F o n t s %
1531 % %
1532 % %
1533 % %
1534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1535 %
1536 % NTGhostscriptFonts() obtains the path to the Ghostscript fonts. The method
1537 % returns FALSE if it cannot determine the font path.
1538 %
1539 % The format of the NTGhostscriptFonts method is:
1540 %
1541 % int NTGhostscriptFonts(char *path,int length)
1542 %
1543 % A description of each parameter follows:
1544 %
1545 % o path: return the font path here.
1546 %
1547 % o length: length of the path buffer.
1548 %
1549 */
1550 MagickPrivate int NTGhostscriptFonts(char *path,int length)
1551 {
1552  char
1553  buffer[MaxTextExtent],
1554  *directory,
1555  filename[MaxTextExtent];
1556 
1557  char
1558  *p,
1559  *q;
1560 
1561  *path='\0';
1562  directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_FONT_PATH");
1563  if (directory != (char *) NULL)
1564  {
1565  (void) CopyMagickString(buffer,directory,MaxTextExtent);
1566  directory=DestroyString(directory);
1567  }
1568  else
1569  {
1570  if (NTGhostscriptGetString("GS_LIB",NULL,buffer,MaxTextExtent) == MagickFalse)
1571  return(FALSE);
1572  }
1573  for (p=buffer-1; p != (char *) NULL; p=strchr(p+1,DirectoryListSeparator))
1574  {
1575  (void) CopyMagickString(path,p+1,length+1);
1576  q=strchr(path,DirectoryListSeparator);
1577  if (q != (char *) NULL)
1578  *q='\0';
1579  (void) FormatLocaleString(filename,MaxTextExtent,"%s%sfonts.dir",path,
1580  DirectorySeparator);
1581  if (IsPathAccessible(filename) != MagickFalse)
1582  return(TRUE);
1583  (void) FormatLocaleString(filename,MaxTextExtent,"%s%sn019003l.pfb",path,
1584  DirectorySeparator);
1585  if (IsPathAccessible(filename) != MagickFalse)
1586  return(TRUE);
1587  }
1588  *path='\0';
1589  return(FALSE);
1590 }
1591 
1592 /*
1593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1594 % %
1595 % %
1596 % %
1597 % N T G h o s t s c r i p t U n L o a d D L L %
1598 % %
1599 % %
1600 % %
1601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1602 %
1603 % NTGhostscriptUnLoadDLL() unloads the Ghostscript DLL and returns TRUE if
1604 % it succeeds.
1605 %
1606 % The format of the NTGhostscriptUnLoadDLL method is:
1607 %
1608 % int NTGhostscriptUnLoadDLL(void)
1609 %
1610 */
1611 MagickPrivate int NTGhostscriptUnLoadDLL(void)
1612 {
1613  int
1614  status;
1615 
1616  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1617  ActivateSemaphoreInfo(&ghost_semaphore);
1618  LockSemaphoreInfo(ghost_semaphore);
1619  status=FALSE;
1620  if (ghost_handle != (void *) NULL)
1621  {
1622  status=lt_dlclose(ghost_handle);
1623  ghost_handle=(void *) NULL;
1624  (void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
1625  }
1626  UnlockSemaphoreInfo(ghost_semaphore);
1627  DestroySemaphoreInfo(&ghost_semaphore);
1628  return(status);
1629 }
1630 
1631 /*
1632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1633 % %
1634 % %
1635 % %
1636 % N T I n i t i a l i z e L i b r a r y %
1637 % %
1638 % %
1639 % %
1640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1641 %
1642 % NTInitializeLibrary() initializes the dynamic module loading subsystem.
1643 %
1644 % The format of the NTInitializeLibrary method is:
1645 %
1646 % int NTInitializeLibrary(void)
1647 %
1648 */
1649 MagickPrivate int NTInitializeLibrary(void)
1650 {
1651  return(0);
1652 }
1653 
1654 /*
1655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1656 % %
1657 % %
1658 % %
1659 % N T I n i t i a l i z e W i n s o c k %
1660 % %
1661 % %
1662 % %
1663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1664 %
1665 % NTInitializeWinsock() initializes Winsock.
1666 %
1667 % The format of the NTInitializeWinsock method is:
1668 %
1669 % void NTInitializeWinsock(void)
1670 %
1671 */
1672 MagickPrivate void NTInitializeWinsock(MagickBooleanType use_lock)
1673 {
1674  if (use_lock)
1675  {
1676  if (winsock_semaphore == (SemaphoreInfo *) NULL)
1677  ActivateSemaphoreInfo(&winsock_semaphore);
1678  LockSemaphoreInfo(winsock_semaphore);
1679  }
1680  if (wsaData == (WSADATA *) NULL)
1681  {
1682  wsaData=(WSADATA *) AcquireMagickMemory(sizeof(WSADATA));
1683  if (WSAStartup(MAKEWORD(2,2),wsaData) != 0)
1684  ThrowFatalException(CacheFatalError,"WSAStartup failed");
1685  }
1686  if (use_lock)
1687  UnlockSemaphoreInfo(winsock_semaphore);
1688 }
1689 
1690 /*
1691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1692 % %
1693 % %
1694 % %
1695 % N T L o n g P a t h s E n a b l e d %
1696 % %
1697 % %
1698 % %
1699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1700 %
1701 % NTLongPathsEnabled() returns a boolean indicating whether long paths are
1702 $ enabled.
1703 %
1704 % The format of the NTLongPathsEnabled method is:
1705 %
1706 % MagickBooleanType NTLongPathsEnabled()
1707 %
1708 */
1709 MagickExport MagickBooleanType NTLongPathsEnabled()
1710 {
1711  if (long_paths_enabled == 2)
1712  {
1713  DWORD
1714  size,
1715  type,
1716  value;
1717 
1718  HKEY
1719  registry_key;
1720 
1721  LONG
1722  status;
1723 
1724  registry_key=(HKEY) INVALID_HANDLE_VALUE;
1725  status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1726  "SYSTEM\\CurrentControlSet\\Control\\FileSystem",0,KEY_READ,
1727  &registry_key);
1728  if (status != ERROR_SUCCESS)
1729  {
1730  long_paths_enabled=0;
1731  RegCloseKey(registry_key);
1732  return(MagickFalse);
1733  }
1734  value=0;
1735  status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,NULL,
1736  NULL);
1737  if ((status != ERROR_SUCCESS) || (type != REG_DWORD))
1738  {
1739  long_paths_enabled=0;
1740  RegCloseKey(registry_key);
1741  return(MagickFalse);
1742  }
1743  status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,
1744  (LPBYTE) &value,&size);
1745  RegCloseKey(registry_key);
1746  if (status != ERROR_SUCCESS)
1747  {
1748  long_paths_enabled=0;
1749  return(MagickFalse);
1750  }
1751  long_paths_enabled=(size_t) value;
1752  }
1753  return(long_paths_enabled == 1 ? MagickTrue : MagickFalse);
1754 }
1755 
1756 /*
1757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1758 % %
1759 % %
1760 % %
1761 + N T M a p M e m o r y %
1762 % %
1763 % %
1764 % %
1765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1766 %
1767 % NTMapMemory() emulates the Unix method of the same name.
1768 %
1769 % The format of the NTMapMemory method is:
1770 %
1771 % void *NTMapMemory(char *address,size_t length,int protection,int access,
1772 % int file,MagickOffsetType offset)
1773 %
1774 */
1775 MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1776  int flags,int file,MagickOffsetType offset)
1777 {
1778  DWORD
1779  access_mode,
1780  high_length,
1781  high_offset,
1782  low_length,
1783  low_offset,
1784  protection_mode;
1785 
1786  HANDLE
1787  file_handle,
1788  map_handle;
1789 
1790  void
1791  *map;
1792 
1793  (void) address;
1794  access_mode=0;
1795  file_handle=INVALID_HANDLE_VALUE;
1796  low_length=(DWORD) (length & 0xFFFFFFFFUL);
1797  high_length=(DWORD) ((((MagickOffsetType) length) >> 32) & 0xFFFFFFFFUL);
1798  map_handle=INVALID_HANDLE_VALUE;
1799  map=(void *) NULL;
1800  low_offset=(DWORD) (offset & 0xFFFFFFFFUL);
1801  high_offset=(DWORD) ((offset >> 32) & 0xFFFFFFFFUL);
1802  protection_mode=0;
1803  if (protection & PROT_WRITE)
1804  {
1805  access_mode=FILE_MAP_WRITE;
1806  if (!(flags & MAP_PRIVATE))
1807  protection_mode=PAGE_READWRITE;
1808  else
1809  {
1810  access_mode=FILE_MAP_COPY;
1811  protection_mode=PAGE_WRITECOPY;
1812  }
1813  }
1814  else
1815  if (protection & PROT_READ)
1816  {
1817  access_mode=FILE_MAP_READ;
1818  protection_mode=PAGE_READONLY;
1819  }
1820  if ((file == -1) && (flags & MAP_ANONYMOUS))
1821  file_handle=INVALID_HANDLE_VALUE;
1822  else
1823  file_handle=(HANDLE) _get_osfhandle(file);
1824  map_handle=CreateFileMapping(file_handle,0,protection_mode,high_length,
1825  low_length,0);
1826  if (map_handle)
1827  {
1828  map=(void *) MapViewOfFile(map_handle,access_mode,high_offset,low_offset,
1829  length);
1830  CloseHandle(map_handle);
1831  }
1832  if (map == (void *) NULL)
1833  return((void *) ((char *) MAP_FAILED));
1834  return((void *) ((char *) map));
1835 }
1836 
1837 /*
1838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1839 % %
1840 % %
1841 % %
1842 % N T O p e n D i r e c t o r y %
1843 % %
1844 % %
1845 % %
1846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1847 %
1848 % NTOpenDirectory() opens the directory named by filename and associates a
1849 % directory stream with it.
1850 %
1851 % The format of the NTOpenDirectory method is:
1852 %
1853 % DIR *NTOpenDirectory(const char *path)
1854 %
1855 % A description of each parameter follows:
1856 %
1857 % o entry: Specifies a pointer to a DIR structure.
1858 %
1859 */
1860 MagickPrivate DIR *NTOpenDirectory(const char *path)
1861 {
1862  DIR
1863  *entry;
1864 
1865  size_t
1866  length;
1867 
1868  wchar_t
1869  file_specification[MaxTextExtent];
1870 
1871  assert(path != (const char *) NULL);
1872  length=MultiByteToWideChar(CP_UTF8,0,path,-1,file_specification,
1873  MaxTextExtent);
1874  if (length == 0)
1875  return((DIR *) NULL);
1876  if(wcsncat(file_specification,L"\\*.*",MaxTextExtent-wcslen(
1877  file_specification)-1) == (wchar_t*) NULL)
1878  return((DIR *) NULL);
1879  entry=(DIR *) AcquireCriticalMemory(sizeof(DIR));
1880  entry->firsttime=TRUE;
1881  entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
1882  if (entry->hSearch == INVALID_HANDLE_VALUE)
1883  {
1884  entry=(DIR *) RelinquishMagickMemory(entry);
1885  return((DIR *) NULL);
1886  }
1887  return(entry);
1888 }
1889 
1890 /*
1891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1892 % %
1893 % %
1894 % %
1895 % N T O p e n L i b r a r y %
1896 % %
1897 % %
1898 % %
1899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1900 %
1901 % NTOpenLibrary() loads a dynamic module into memory and returns a handle that
1902 % can be used to access the various procedures in the module.
1903 %
1904 % The format of the NTOpenLibrary method is:
1905 %
1906 % void *NTOpenLibrary(const char *filename)
1907 %
1908 % A description of each parameter follows:
1909 %
1910 % o path: Specifies a pointer to string representing dynamic module that
1911 % is to be loaded.
1912 %
1913 */
1914 static inline const char *GetSearchPath(void)
1915 {
1916 #if defined(MAGICKCORE_LTDL_DELEGATE)
1917  return(lt_dlgetsearchpath());
1918 #else
1919  return(lt_slsearchpath);
1920 #endif
1921 }
1922 
1923 static UINT ChangeErrorMode(void)
1924 {
1925  typedef UINT
1926  (CALLBACK *GETERRORMODE)(void);
1927 
1928  GETERRORMODE
1929  getErrorMode;
1930 
1931  HMODULE
1932  handle;
1933 
1934  UINT
1935  mode;
1936 
1937  mode=SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1938 
1939  handle=GetModuleHandle("kernel32.dll");
1940  if (handle == (HMODULE) NULL)
1941  return SetErrorMode(mode);
1942 
1943  getErrorMode=(GETERRORMODE) NTGetLibrarySymbol(handle,"GetErrorMode");
1944  if (getErrorMode != (GETERRORMODE) NULL)
1945  mode=getErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1946 
1947  return SetErrorMode(mode);
1948 }
1949 
1950 static inline void *NTLoadLibrary(const char *filename)
1951 {
1952  int
1953  length;
1954 
1955  wchar_t
1956  path[MaxTextExtent];
1957 
1958  length=MultiByteToWideChar(CP_UTF8,0,filename,-1,path,MaxTextExtent);
1959  if (length == 0)
1960  return((void *) NULL);
1961  return (void *) LoadLibraryExW(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
1962 }
1963 
1964 MagickPrivate void *NTOpenLibrary(const char *filename)
1965 {
1966  char
1967  path[MaxTextExtent];
1968 
1969  const char
1970  *p,
1971  *q;
1972 
1973  UINT
1974  mode;
1975 
1976  void
1977  *handle;
1978 
1979  mode=ChangeErrorMode();
1980  handle=NTLoadLibrary(filename);
1981  if (handle == (void *) NULL)
1982  {
1983  p=GetSearchPath();
1984  while (p != (const char*) NULL)
1985  {
1986  q=strchr(p,DirectoryListSeparator);
1987  if (q != (const char*) NULL)
1988  (void) CopyMagickString(path,p,q-p+1);
1989  else
1990  (void) CopyMagickString(path,p,MaxTextExtent);
1991  (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
1992  (void) ConcatenateMagickString(path,filename,MaxTextExtent);
1993  handle=NTLoadLibrary(path);
1994  if (handle != (void *) NULL || q == (const char*) NULL)
1995  break;
1996  p=q+1;
1997  }
1998  }
1999  SetErrorMode(mode);
2000  return(handle);
2001 }
2002 
2003 /*
2004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2005 % %
2006 % %
2007 % %
2008 % N T O p e n F i l e W i d e %
2009 % %
2010 % %
2011 % %
2012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2013 %
2014 % NTOpenFileWide() opens a file and returns a file pointer.
2015 %
2016 % The format of the NTOpenFileWide method is:
2017 %
2018 % FILE *NTOpenFileWide(const char* path, const char* mode)
2019 %
2020 % A description of each parameter follows:
2021 %
2022 % o path: the file path.
2023 %
2024 % o mode: the file open mode.
2025 %
2026 */
2027 static inline wchar_t *create_wchar_mode(const char *mode)
2028 {
2029  int
2030  count;
2031 
2032  wchar_t
2033  *wide;
2034 
2035  count=MultiByteToWideChar(CP_UTF8,0,mode,-1,NULL,0);
2036  wide=(wchar_t *) AcquireQuantumMemory((size_t) count+1,
2037  sizeof(*wide));
2038  if (wide == (wchar_t *) NULL)
2039  return((wchar_t *) NULL);
2040  if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wide,count) == 0)
2041  {
2042  wide=(wchar_t *) RelinquishMagickMemory(wide);
2043  return((wchar_t *) NULL);
2044  }
2045  /* Specifies that the file is not inherited by child processes */
2046  wide[count] = L'\0';
2047  wide[count-1] = L'N';
2048  return(wide);
2049 }
2050 
2051 MagickExport FILE *NTOpenFileWide(const char* path, const char* mode)
2052 {
2053  FILE
2054  *file;
2055 
2056  wchar_t
2057  *mode_wide,
2058  *path_wide;
2059 
2060  path_wide=NTCreateWidePath(path);
2061  if (path_wide == (wchar_t *) NULL)
2062  return((FILE *) NULL);
2063  mode_wide=create_wchar_mode(mode);
2064  if (mode_wide == (wchar_t *) NULL)
2065  {
2066  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2067  return((FILE *) NULL);
2068  }
2069  if (_wfopen_s(&file,path_wide,mode_wide) != 0)
2070  file=(FILE *) NULL;
2071  mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
2072  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2073  return(file);
2074 }
2075 
2076 /*
2077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2078 % %
2079 % %
2080 % %
2081 % N T O p e n P i p e W i d e %
2082 % %
2083 % %
2084 % %
2085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086 %
2087 % NTOpenPipeWide() opens a pipe and returns a file pointer.
2088 %
2089 % The format of the NTOpenPipeWide method is:
2090 %
2091 % FILE *NTOpenPipeWide(const char* command, const char* type)
2092 %
2093 % A description of each parameter follows:
2094 %
2095 % o command: the command to execute.
2096 %
2097 % o type: the file open mode.
2098 %
2099 */
2100 MagickExport FILE *NTOpenPipeWide(const char *command,const char *type)
2101 {
2102  FILE
2103  *file;
2104 
2105  int
2106  length;
2107 
2108  wchar_t
2109  *command_wide,
2110  type_wide[5];
2111 
2112  file=(FILE *) NULL;
2113  length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
2114  if (length == 0)
2115  return(file);
2116  length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
2117  if (length == 0)
2118  return(file);
2119  command_wide=(wchar_t *) AcquireQuantumMemory((size_t) length,
2120  sizeof(*command_wide));
2121  if (command_wide == (wchar_t *) NULL)
2122  return(file);
2123  length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
2124  if (length != 0)
2125  file=_wpopen(command_wide,type_wide);
2126  command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
2127  return(file);
2128 }
2129 
2130 /*
2131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2132 % %
2133 % %
2134 % %
2135 % N T O p e n W i d e %
2136 % %
2137 % %
2138 % %
2139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2140 %
2141 % NTOpenWide() opens the file specified by path and mode.
2142 %
2143 % The format of the NTOpenWide method is:
2144 %
2145 % FILE *NTOpenWide(const char* path, const char* mode)
2146 %
2147 % A description of each parameter follows:
2148 %
2149 % o path: the file path.
2150 %
2151 % o flags: the file open flags.
2152 %
2153 % o mode: the file open mode.
2154 %
2155 */
2156 MagickExport int NTOpenWide(const char* path,int flags,mode_t mode)
2157 {
2158  int
2159  file_handle,
2160  status;
2161 
2162  wchar_t
2163  *path_wide;
2164 
2165  path_wide=NTCreateWidePath(path);
2166  if (path_wide == (wchar_t *) NULL)
2167  return(-1);
2168  /* O_NOINHERIT specifies that the file is not inherited by child processes */
2169  status=_wsopen_s(&file_handle,path_wide,flags | O_NOINHERIT,_SH_DENYNO,mode);
2170  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2171  return(status == 0 ? file_handle : -1);
2172 }
2173 
2174 /*
2175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2176 % %
2177 % %
2178 % %
2179 % N T R e a d D i r e c t o r y %
2180 % %
2181 % %
2182 % %
2183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2184 %
2185 % NTReadDirectory() returns a pointer to a structure representing the
2186 % directory entry at the current position in the directory stream to which
2187 % entry refers.
2188 %
2189 % The format of the NTReadDirectory
2190 %
2191 % NTReadDirectory(entry)
2192 %
2193 % A description of each parameter follows:
2194 %
2195 % o entry: Specifies a pointer to a DIR structure.
2196 %
2197 */
2198 MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
2199 {
2200  int
2201  status;
2202 
2203  size_t
2204  length;
2205 
2206  if (entry == (DIR *) NULL)
2207  return((struct dirent *) NULL);
2208  if (!entry->firsttime)
2209  {
2210  status=FindNextFileW(entry->hSearch,&entry->Win32FindData);
2211  if (status == 0)
2212  return((struct dirent *) NULL);
2213  }
2214  length=WideCharToMultiByte(CP_UTF8,0,entry->Win32FindData.cFileName,-1,
2215  entry->file_info.d_name,sizeof(entry->file_info.d_name),NULL,NULL);
2216  if (length == 0)
2217  return((struct dirent *) NULL);
2218  entry->firsttime=FALSE;
2219  entry->file_info.d_namlen=(int) strlen(entry->file_info.d_name);
2220  return(&entry->file_info);
2221 }
2222 
2223 /*
2224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2225 % %
2226 % %
2227 % %
2228 % N T R e a l P a t h W i d e %
2229 % %
2230 % %
2231 % %
2232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2233 %
2234 % NTRealPathWide returns the absolute path of the specified path.
2235 %
2236 % The format of the NTRealPathWide method is:
2237 %
2238 % char *NTRealPathWide(const char *path)
2239 %
2240 % A description of each parameter follows:
2241 %
2242 % o path: the file path.
2243 %
2244 */
2245 static inline wchar_t* resolve_symlink(const wchar_t* path)
2246 {
2247  DWORD
2248  link_length;
2249 
2250  HANDLE
2251  file_handle;
2252 
2253  wchar_t
2254  *link;
2255 
2256  file_handle=CreateFileW(path,GENERIC_READ,FILE_SHARE_READ |FILE_SHARE_WRITE |
2257  FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
2258  if (file_handle == INVALID_HANDLE_VALUE)
2259  return((wchar_t *) NULL);
2260  link_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
2261  FILE_NAME_NORMALIZED);
2262  link=(wchar_t *) AcquireQuantumMemory(link_length,sizeof(wchar_t));
2263  if (link == (wchar_t *) NULL)
2264  {
2265  CloseHandle(file_handle);
2266  return((wchar_t *) NULL);
2267  }
2268  GetFinalPathNameByHandleW(file_handle,link,link_length,FILE_NAME_NORMALIZED);
2269  CloseHandle(file_handle);
2270  return(link);
2271 }
2272 
2273 MagickExport char *NTRealPathWide(const char *path)
2274 {
2275  char
2276  *real_path;
2277 
2278  wchar_t
2279  *wide_real_path,
2280  *wide_path;
2281 
2282  wide_path=NTCreateWidePath(path);
2283  wide_real_path=resolve_symlink(wide_path);
2284  if (wide_real_path == (wchar_t*) NULL)
2285  {
2286  DWORD
2287  full_path_length;
2288 
2289  full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
2290  wide_real_path=(wchar_t *) AcquireQuantumMemory(full_path_length,
2291  sizeof(wchar_t));
2292  if (wide_real_path == (wchar_t*) NULL)
2293  {
2294  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
2295  return((char*) NULL);
2296  }
2297  GetFullPathNameW(wide_path,full_path_length,wide_real_path,NULL);
2298  }
2299  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
2300  /*
2301  Remove \\?\ prefix for POSIX-like behavior.
2302  */
2303  if (wcsncmp(wide_real_path,L"\\\\?\\",4) == 0)
2304  real_path=create_utf8_string(wide_real_path+4);
2305  else
2306  real_path=create_utf8_string(wide_real_path);
2307  wide_real_path=(wchar_t *) RelinquishMagickMemory(wide_real_path);
2308  return(real_path);
2309 }
2310 
2311 /*
2312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2313 % %
2314 % %
2315 % %
2316 % N T R e g i s t r y K e y L o o k u p %
2317 % %
2318 % %
2319 % %
2320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2321 %
2322 % NTRegistryKeyLookup() returns ImageMagick installation path settings
2323 % stored in the Windows Registry. Path settings are specific to the
2324 % installed ImageMagick version so that multiple Image Magick installations
2325 % may coexist.
2326 %
2327 % Values are stored in the registry under a base path similar to
2328 % "HKEY_LOCAL_MACHINE/SOFTWARE\ImageMagick\6.7.4\Q:16" or
2329 % "HKEY_CURRENT_USER/SOFTWARE\ImageMagick\6.7.4\Q:16". The provided subkey
2330 % is appended to this base path to form the full key.
2331 %
2332 % The format of the NTRegistryKeyLookup method is:
2333 %
2334 % unsigned char *NTRegistryKeyLookup(const char *subkey)
2335 %
2336 % A description of each parameter follows:
2337 %
2338 % o subkey: Specifies a string that identifies the registry object.
2339 % Currently supported sub-keys include: "BinPath", "ConfigurePath",
2340 % "LibPath", "CoderModulesPath", "FilterModulesPath", "SharePath".
2341 %
2342 */
2343 MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
2344 {
2345  char
2346  package_key[MaxTextExtent] = "";
2347 
2348  unsigned char
2349  *value;
2350 
2351  (void) FormatLocaleString(package_key,MagickPathExtent,
2352  "SOFTWARE\\%s\\%s\\Q:%d",MagickPackageName,MagickLibVersionText,
2353  MAGICKCORE_QUANTUM_DEPTH);
2354  value=NTGetRegistryValue(HKEY_LOCAL_MACHINE,package_key,0,subkey);
2355  if (value == (unsigned char *) NULL)
2356  value=NTGetRegistryValue(HKEY_CURRENT_USER,package_key,0,subkey);
2357  return(value);
2358 }
2359 
2360 /*
2361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2362 % %
2363 % %
2364 % %
2365 % N T R e m o v e W i d e %
2366 % %
2367 % %
2368 % %
2369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2370 %
2371 % NTRemoveWide() removes the specified file.
2372 %
2373 % The format of the NTRemoveWide method is:
2374 %
2375 % int NTRemoveWide(const char *path)
2376 %
2377 % A description of each parameter follows:
2378 %
2379 % o path: the file path.
2380 %
2381 */
2382 MagickExport int NTRemoveWide(const char *path)
2383 {
2384  int
2385  status;
2386 
2387  wchar_t
2388  *path_wide;
2389 
2390  path_wide=NTCreateWidePath(path);
2391  if (path_wide == (wchar_t *) NULL)
2392  return(-1);
2393  status=_wremove(path_wide);
2394  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2395  return(status);
2396 }
2397 
2398 /*
2399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2400 % %
2401 % %
2402 % %
2403 % N T R e n a m e W i d e %
2404 % %
2405 % %
2406 % %
2407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2408 %
2409 % NTRenameWide() renames a file.
2410 %
2411 % The format of the NTRenameWide method is:
2412 %
2413 % int NTRenameWide(const char *source, const char *destination)
2414 %
2415 % A description of each parameter follows:
2416 %
2417 % o source: the source file path.
2418 %
2419 % o destination: the destination file path.
2420 %
2421 */
2422 MagickExport int NTRenameWide(const char* source, const char* destination)
2423 {
2424  int
2425  status;
2426 
2427  wchar_t
2428  *destination_wide,
2429  *source_wide;
2430 
2431  source_wide=NTCreateWidePath(source);
2432  if (source_wide == (wchar_t *) NULL)
2433  return(-1);
2434  destination_wide=NTCreateWidePath(destination);
2435  if (destination_wide == (wchar_t *) NULL)
2436  {
2437  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
2438  return(-1);
2439  }
2440  status=_wrename(source_wide,destination_wide);
2441  destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
2442  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
2443  return(status);
2444 }
2445 
2446 /*
2447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2448 % %
2449 % %
2450 % %
2451 % N T R e p o r t E v e n t %
2452 % %
2453 % %
2454 % %
2455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2456 %
2457 % NTReportEvent() reports an event.
2458 %
2459 % The format of the NTReportEvent method is:
2460 %
2461 % MagickBooleanType NTReportEvent(const char *event,
2462 % const MagickBooleanType error)
2463 %
2464 % A description of each parameter follows:
2465 %
2466 % o event: the event.
2467 %
2468 % o error: MagickTrue the event is an error.
2469 %
2470 */
2471 MagickPrivate MagickBooleanType NTReportEvent(const char *event,
2472  const MagickBooleanType error)
2473 {
2474  const char
2475  *events[1];
2476 
2477  HANDLE
2478  handle;
2479 
2480  WORD
2481  type;
2482 
2483  handle=RegisterEventSource(NULL,MAGICKCORE_PACKAGE_NAME);
2484  if (handle == NULL)
2485  return(MagickFalse);
2486  events[0]=event;
2487  type=error ? EVENTLOG_ERROR_TYPE : EVENTLOG_WARNING_TYPE;
2488  ReportEvent(handle,type,0,0,NULL,1,0,events,NULL);
2489  DeregisterEventSource(handle);
2490  return(MagickTrue);
2491 }
2492 
2493 /*
2494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2495 % %
2496 % %
2497 % %
2498 % N T R e s o u r c e T o B l o b %
2499 % %
2500 % %
2501 % %
2502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2503 %
2504 % NTResourceToBlob() returns a blob containing the contents of the resource
2505 % in the current executable specified by the id parameter. This currently
2506 % used to retrieve MGK files tha have been embedded into the various command
2507 % line utilities.
2508 %
2509 % The format of the NTResourceToBlob method is:
2510 %
2511 % unsigned char *NTResourceToBlob(const char *id)
2512 %
2513 % A description of each parameter follows:
2514 %
2515 % o id: Specifies a string that identifies the resource.
2516 %
2517 */
2518 MagickPrivate unsigned char *NTResourceToBlob(const char *id)
2519 {
2520 
2521 #ifndef MAGICKCORE_LIBRARY_NAME
2522  char
2523  path[MaxTextExtent];
2524 #endif
2525 
2526  DWORD
2527  length;
2528 
2529  HGLOBAL
2530  global;
2531 
2532  HMODULE
2533  handle;
2534 
2535  HRSRC
2536  resource;
2537 
2538  unsigned char
2539  *blob,
2540  *value;
2541 
2542  assert(id != (const char *) NULL);
2543  if (IsEventLogging() != MagickFalse)
2544  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
2545 #ifdef MAGICKCORE_LIBRARY_NAME
2546  handle=GetModuleHandle(MAGICKCORE_LIBRARY_NAME);
2547 #else
2548  (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
2549  DirectorySeparator,GetClientName());
2550  if (IsPathAccessible(path) != MagickFalse)
2551  handle=GetModuleHandle(path);
2552  else
2553  handle=GetModuleHandle(0);
2554 #endif
2555  if (!handle)
2556  return((unsigned char *) NULL);
2557  resource=FindResource(handle,id,"IMAGEMAGICK");
2558  if (!resource)
2559  return((unsigned char *) NULL);
2560  global=LoadResource(handle,resource);
2561  if (!global)
2562  return((unsigned char *) NULL);
2563  length=SizeofResource(handle,resource);
2564  value=(unsigned char *) LockResource(global);
2565  if (!value)
2566  {
2567  FreeResource(global);
2568  return((unsigned char *) NULL);
2569  }
2570  blob=(unsigned char *) AcquireQuantumMemory(length+MaxTextExtent,
2571  sizeof(*blob));
2572  if (blob != (unsigned char *) NULL)
2573  {
2574  (void) memcpy(blob,value,length);
2575  blob[length]='\0';
2576  }
2577  UnlockResource(global);
2578  FreeResource(global);
2579  return(blob);
2580 }
2581 
2582 /*
2583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2584 % %
2585 % %
2586 % %
2587 % NT S e t F i l e T i m e s t a m p %
2588 % %
2589 % %
2590 % %
2591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2592 %
2593 % NTSetFileTimestamp() sets the file timestamps for a specified file.
2594 %
2595 % The format of the NTSetFileTimestamp method is:
2596 %
2597 % int NTSetFileTimestamp(const char *path, struct stat *attributes)
2598 %
2599 % A description of each parameter follows:
2600 %
2601 % o path: the file path.
2602 %
2603 % o attributes: the file attributes.
2604 %
2605 */
2606 MagickExport int NTSetFileTimestamp(const char *path, struct stat *attributes)
2607 {
2608  HANDLE
2609  handle;
2610 
2611  int
2612  status;
2613 
2614  wchar_t
2615  *path_wide;
2616 
2617  status=(-1);
2618  path_wide=NTCreateWidePath(path);
2619  if (path_wide == (WCHAR *) NULL)
2620  return(status);
2621  handle=CreateFileW(path_wide,FILE_WRITE_ATTRIBUTES,FILE_SHARE_WRITE |
2622  FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
2623  if (handle != (HANDLE) NULL)
2624  {
2625  FILETIME
2626  creation_time,
2627  last_access_time,
2628  last_write_time;
2629 
2630  ULARGE_INTEGER
2631  date_time;
2632 
2633  date_time.QuadPart=(ULONGLONG) (attributes->st_ctime*10000000LL)+
2634  116444736000000000LL;
2635  creation_time.dwLowDateTime=date_time.LowPart;
2636  creation_time.dwHighDateTime=date_time.HighPart;
2637  date_time.QuadPart=(ULONGLONG) (attributes->st_atime*10000000LL)+
2638  116444736000000000LL;
2639  last_access_time.dwLowDateTime=date_time.LowPart;
2640  last_access_time.dwHighDateTime=date_time.HighPart;
2641  date_time.QuadPart=(ULONGLONG) (attributes->st_mtime*10000000LL)+
2642  116444736000000000LL;
2643  last_write_time.dwLowDateTime=date_time.LowPart;
2644  last_write_time.dwHighDateTime=date_time.HighPart;
2645  status=SetFileTime(handle,&creation_time,&last_access_time,&last_write_time);
2646  CloseHandle(handle);
2647  status=0;
2648  }
2649  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
2650  return(status);
2651 }
2652 
2653 /*
2654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2655 % %
2656 % %
2657 % %
2658 % N T S e t S e a r c h P a t h %
2659 % %
2660 % %
2661 % %
2662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2663 %
2664 % NTSetSearchPath() sets the current locations that the subsystem should
2665 % look at to find dynamically loadable modules.
2666 %
2667 % The format of the NTSetSearchPath method is:
2668 %
2669 % int NTSetSearchPath(const char *path)
2670 %
2671 % A description of each parameter follows:
2672 %
2673 % o path: Specifies a pointer to string representing the search path
2674 % for DLL's that can be dynamically loaded.
2675 %
2676 */
2677 MagickPrivate int NTSetSearchPath(const char *path)
2678 {
2679 #if defined(MAGICKCORE_LTDL_DELEGATE)
2680  lt_dlsetsearchpath(path);
2681 #else
2682  if (lt_slsearchpath != (char *) NULL)
2683  lt_slsearchpath=DestroyString(lt_slsearchpath);
2684  if (path != (char *) NULL)
2685  lt_slsearchpath=AcquireString(path);
2686 #endif
2687  return(0);
2688 }
2689 
2690 /*
2691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2692 % %
2693 % %
2694 % %
2695 % N T S t a t W i d e %
2696 % %
2697 % %
2698 % %
2699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2700 %
2701 % NTStatWide() gets the file attributes for a specified file.
2702 %
2703 % The format of the NTStatWide method is:
2704 %
2705 % int NTStatWide(const char *path,struct stat *attributes)
2706 %
2707 % A description of each parameter follows:
2708 %
2709 % o path: the file path.
2710 %
2711 % o attributes: the file attributes.
2712 %
2713 */
2714 MagickExport int NTStatWide(const char *path,struct stat *attributes)
2715 {
2716  int
2717  status;
2718 
2719  wchar_t
2720  *path_wide;
2721 
2722  path_wide=NTCreateWidePath(path);
2723  if (path_wide == (WCHAR *) NULL)
2724  return(-1);
2725  status=wstat(path_wide,attributes);
2726  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
2727  return(status);
2728 }
2729 
2730 /*
2731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2732 % %
2733 % %
2734 % %
2735 % N T S y s t e m C o m m a n d %
2736 % %
2737 % %
2738 % %
2739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2740 %
2741 % NTSystemCommand() executes the specified command and waits until it
2742 % terminates. The returned value is the exit status of the command.
2743 %
2744 % The format of the NTSystemCommand method is:
2745 %
2746 % int NTSystemCommand(MagickFalse,const char *command)
2747 %
2748 % A description of each parameter follows:
2749 %
2750 % o command: This string is the command to execute.
2751 %
2752 % o output: an optional buffer to store the output from stderr/stdout.
2753 %
2754 */
2755 MagickPrivate int NTSystemCommand(const char *command,char *output)
2756 {
2757 #define CleanupOutputHandles \
2758  if (read_output != (HANDLE) NULL) \
2759  { \
2760  CloseHandle(read_output); \
2761  read_output=(HANDLE) NULL; \
2762  CloseHandle(write_output); \
2763  write_output=(HANDLE) NULL; \
2764  }
2765 
2766 #define CopyLastError \
2767  last_error=GetLastError(); \
2768  if (output != (char *) NULL) \
2769  { \
2770  error=NTGetLastErrorMessage(last_error); \
2771  if (error != (char *) NULL) \
2772  { \
2773  CopyMagickString(output,error,MaxTextExtent); \
2774  error=DestroyString(error); \
2775  } \
2776  }
2777 
2778  char
2779  *error,
2780  local_command[MaxTextExtent];
2781 
2782  DWORD
2783  child_status,
2784  last_error;
2785 
2786  int
2787  status;
2788 
2789  MagickBooleanType
2790  asynchronous;
2791 
2792  HANDLE
2793  read_output,
2794  write_output;
2795 
2796  PROCESS_INFORMATION
2797  process_info;
2798 
2799  size_t
2800  output_offset;
2801 
2802  STARTUPINFO
2803  startup_info;
2804 
2805  if (command == (char *) NULL)
2806  return(-1);
2807  read_output=(HANDLE) NULL;
2808  write_output=(HANDLE) NULL;
2809  GetStartupInfo(&startup_info);
2810  startup_info.dwFlags=STARTF_USESHOWWINDOW;
2811  startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
2812  (void) CopyMagickString(local_command,command,MaxTextExtent);
2813  asynchronous=command[strlen(command)-1] == '&' ? MagickTrue : MagickFalse;
2814  if (asynchronous != MagickFalse)
2815  {
2816  local_command[strlen(command)-1]='\0';
2817  startup_info.wShowWindow=SW_SHOWDEFAULT;
2818  }
2819  else
2820  {
2821  if (command[strlen(command)-1] == '|')
2822  local_command[strlen(command)-1]='\0';
2823  else
2824  startup_info.wShowWindow=SW_HIDE;
2825  read_output=(HANDLE) NULL;
2826  if (output != (char *) NULL)
2827  {
2828  if (CreatePipe(&read_output,&write_output,NULL,0))
2829  {
2830  if (SetHandleInformation(write_output,HANDLE_FLAG_INHERIT,
2831  HANDLE_FLAG_INHERIT))
2832  {
2833  startup_info.dwFlags|=STARTF_USESTDHANDLES;
2834  startup_info.hStdOutput=write_output;
2835  startup_info.hStdError=write_output;
2836  }
2837  else
2838  CleanupOutputHandles;
2839  }
2840  else
2841  read_output=(HANDLE) NULL;
2842  }
2843  }
2844  status=CreateProcess((LPCTSTR) NULL,local_command,(LPSECURITY_ATTRIBUTES)
2845  NULL,(LPSECURITY_ATTRIBUTES) NULL,(BOOL) TRUE,(DWORD)
2846  NORMAL_PRIORITY_CLASS,(LPVOID) NULL,(LPCSTR) NULL,&startup_info,
2847  &process_info);
2848  if (status == 0)
2849  {
2850  CopyLastError;
2851  CleanupOutputHandles;
2852  return(last_error == ERROR_FILE_NOT_FOUND ? 127 : -1);
2853  }
2854  if (output != (char *) NULL)
2855  *output='\0';
2856  if (asynchronous != MagickFalse)
2857  return(status == 0);
2858  output_offset=0;
2859  status=STATUS_TIMEOUT;
2860  while (status == STATUS_TIMEOUT)
2861  {
2862  DWORD
2863  size;
2864 
2865  status=WaitForSingleObject(process_info.hProcess,1000);
2866  size=0;
2867  if (read_output != (HANDLE) NULL)
2868  if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2869  break;
2870  while (size > 0)
2871  {
2872  char
2873  buffer[MagickPathExtent];
2874 
2875  DWORD
2876  bytes_read;
2877 
2878  if (ReadFile(read_output,buffer,MagickPathExtent-1,&bytes_read,NULL))
2879  {
2880  size_t
2881  count;
2882 
2883  count=MagickMin(MagickPathExtent-output_offset,
2884  (size_t) bytes_read+1);
2885  if (count > 0)
2886  {
2887  CopyMagickString(output+output_offset,buffer,count);
2888  output_offset+=count-1;
2889  }
2890  }
2891  if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2892  break;
2893  }
2894  }
2895  if (status != WAIT_OBJECT_0)
2896  {
2897  CopyLastError;
2898  CleanupOutputHandles;
2899  return(status);
2900  }
2901  status=GetExitCodeProcess(process_info.hProcess,&child_status);
2902  if (status == 0)
2903  {
2904  CopyLastError;
2905  CleanupOutputHandles;
2906  return(-1);
2907  }
2908  CloseHandle(process_info.hProcess);
2909  CloseHandle(process_info.hThread);
2910  CleanupOutputHandles;
2911  return((int) child_status);
2912 }
2913 
2914 /*
2915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2916 % %
2917 % %
2918 % %
2919 % N T S y s t e m C o n i f i g u r a t i o n %
2920 % %
2921 % %
2922 % %
2923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2924 %
2925 % NTSystemConfiguration() provides a way for the application to determine
2926 % values for system limits or options at runtime.
2927 %
2928 % The format of the exit method is:
2929 %
2930 % ssize_t NTSystemConfiguration(int name)
2931 %
2932 % A description of each parameter follows:
2933 %
2934 % o name: _SC_PAGE_SIZE or _SC_PHYS_PAGES.
2935 %
2936 */
2937 MagickPrivate ssize_t NTSystemConfiguration(int name)
2938 {
2939  switch (name)
2940  {
2941  case _SC_PAGE_SIZE:
2942  {
2943  SYSTEM_INFO
2944  system_info;
2945 
2946  GetSystemInfo(&system_info);
2947  return(system_info.dwPageSize);
2948  }
2949  case _SC_PHYS_PAGES:
2950  {
2951  MEMORYSTATUSEX
2952  status;
2953 
2954  SYSTEM_INFO
2955  system_info;
2956 
2957  status.dwLength=sizeof(status);
2958  if (GlobalMemoryStatusEx(&status) == 0)
2959  return(0L);
2960  GetSystemInfo(&system_info);
2961  return((ssize_t) status.ullTotalPhys/system_info.dwPageSize);
2962  }
2963  case _SC_OPEN_MAX:
2964  return(2048);
2965  default:
2966  break;
2967  }
2968  return(-1);
2969 }
2970 
2971 /*
2972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2973 % %
2974 % %
2975 % %
2976 % N T T r u n c a t e F i l e %
2977 % %
2978 % %
2979 % %
2980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2981 %
2982 % NTTruncateFile() truncates a file to a specified length.
2983 %
2984 % The format of the NTTruncateFile method is:
2985 %
2986 % int NTTruncateFile(int file,off_t length)
2987 %
2988 % A description of each parameter follows:
2989 %
2990 % o file: the file.
2991 %
2992 % o length: the file length.
2993 %
2994 */
2995 MagickPrivate int NTTruncateFile(int file,off_t length)
2996 {
2997  DWORD
2998  file_pointer;
2999 
3000  HANDLE
3001  file_handle;
3002 
3003  long
3004  high,
3005  low;
3006 
3007  file_handle=(HANDLE) _get_osfhandle(file);
3008  if (file_handle == INVALID_HANDLE_VALUE)
3009  return(-1);
3010  low=(long) (length & 0xffffffffUL);
3011  high=(long) ((((MagickOffsetType) length) >> 32) & 0xffffffffUL);
3012  file_pointer=SetFilePointer(file_handle,low,&high,FILE_BEGIN);
3013  if ((file_pointer == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
3014  return(-1);
3015  if (SetEndOfFile(file_handle) == 0)
3016  return(-1);
3017  return(0);
3018 }
3019 
3020 /*
3021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3022 % %
3023 % %
3024 % %
3025 + N T U n m a p M e m o r y %
3026 % %
3027 % %
3028 % %
3029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3030 %
3031 % NTUnmapMemory() emulates the Unix munmap method.
3032 %
3033 % The format of the NTUnmapMemory method is:
3034 %
3035 % int NTUnmapMemory(void *map,size_t length)
3036 %
3037 % A description of each parameter follows:
3038 %
3039 % o map: the address of the binary large object.
3040 %
3041 % o length: the length of the binary large object.
3042 %
3043 */
3044 MagickPrivate int NTUnmapMemory(void *map,size_t length)
3045 {
3046  (void) length;
3047  if (UnmapViewOfFile(map) == 0)
3048  return(-1);
3049  return(0);
3050 }
3051 
3052 /*
3053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3054 % %
3055 % %
3056 % %
3057 % N T U s e r T i m e %
3058 % %
3059 % %
3060 % %
3061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3062 %
3063 % NTUserTime() returns the total time the process has been scheduled (e.g.
3064 % seconds) since the last call to StartTimer().
3065 %
3066 % The format of the UserTime method is:
3067 %
3068 % double NTUserTime(void)
3069 %
3070 */
3071 MagickPrivate double NTUserTime(void)
3072 {
3073  DWORD
3074  status;
3075 
3076  FILETIME
3077  create_time,
3078  exit_time;
3079 
3080  OSVERSIONINFO
3081  OsVersionInfo;
3082 
3083  union
3084  {
3085  FILETIME
3086  filetime;
3087 
3088  __int64
3089  filetime64;
3090  } kernel_time;
3091 
3092  union
3093  {
3094  FILETIME
3095  filetime;
3096 
3097  __int64
3098  filetime64;
3099  } user_time;
3100 
3101  OsVersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
3102  GetVersionEx(&OsVersionInfo);
3103  if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
3104  return(NTElapsedTime());
3105  status=GetProcessTimes(GetCurrentProcess(),&create_time,&exit_time,
3106  &kernel_time.filetime,&user_time.filetime);
3107  if (status != TRUE)
3108  return(0.0);
3109  return((double) 1.0e-7*(kernel_time.filetime64+user_time.filetime64));
3110 }
3111 
3112 /*
3113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3114 % %
3115 % %
3116 % %
3117 % N T W a r n i n g H a n d l e r %
3118 % %
3119 % %
3120 % %
3121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3122 %
3123 % NTWarningHandler() displays a warning reason.
3124 %
3125 % The format of the NTWarningHandler method is:
3126 %
3127 % void NTWarningHandler(const ExceptionType severity,const char *reason,
3128 % const char *description)
3129 %
3130 % A description of each parameter follows:
3131 %
3132 % o severity: Specifies the numeric warning category.
3133 %
3134 % o reason: Specifies the reason to display before terminating the
3135 % program.
3136 %
3137 % o description: Specifies any description to the reason.
3138 %
3139 */
3140 MagickPrivate void NTWarningHandler(const ExceptionType severity,
3141  const char *reason,const char *description)
3142 {
3143  char
3144  buffer[2*MaxTextExtent];
3145 
3146  (void) severity;
3147  if (reason == (char *) NULL)
3148  return;
3149  if (description == (char *) NULL)
3150  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
3151  reason);
3152  else
3153  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
3154  GetClientName(),reason,description);
3155  (void) MessageBox(NULL,buffer,"ImageMagick Warning",MB_OK | MB_TASKMODAL |
3156  MB_SETFOREGROUND | MB_ICONINFORMATION);
3157 }
3158 
3159 /*
3160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3161 % %
3162 % %
3163 % %
3164 % N T W i n d o w s G e n e s i s %
3165 % %
3166 % %
3167 % %
3168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3169 %
3170 % NTWindowsGenesis() initializes the MagickCore Windows environment.
3171 %
3172 % The format of the NTWindowsGenesis method is:
3173 %
3174 % void NTWindowsGenesis(void)
3175 %
3176 */
3177 MagickPrivate void NTWindowsGenesis(void)
3178 {
3179  char
3180  *mode;
3181 
3182  mode=GetEnvironmentValue("MAGICK_ERRORMODE");
3183  if (mode != (char *) NULL)
3184  {
3185  (void) SetErrorMode(StringToInteger(mode));
3186  mode=DestroyString(mode);
3187  }
3188 #if defined(_DEBUG) && !defined(__MINGW32__)
3189  if (IsEventLogging() != MagickFalse)
3190  {
3191  int
3192  debug;
3193 
3194  debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
3195  //debug |= _CRTDBG_CHECK_ALWAYS_DF;
3196  debug |= _CRTDBG_DELAY_FREE_MEM_DF;
3197  debug |= _CRTDBG_LEAK_CHECK_DF;
3198  (void) _CrtSetDbgFlag(debug);
3199 
3200  //_ASSERTE(_CrtCheckMemory());
3201 
3202  //_CrtSetBreakAlloc(42);
3203  }
3204 #endif
3205 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
3206  {
3207  unsigned char
3208  *path;
3209 
3210  path=NTRegistryKeyLookup("LibPath");
3211  if (path != (unsigned char *) NULL)
3212  {
3213  wchar_t
3214  *lib_path;
3215 
3216  lib_path=NTCreateWidePath((const char *) path);
3217  if (lib_path != (wchar_t *) NULL)
3218  {
3219  SetDllDirectoryW(lib_path);
3220  lib_path=(wchar_t *) RelinquishMagickMemory(lib_path);
3221  }
3222  path=(unsigned char *) RelinquishMagickMemory(path);
3223  }
3224  }
3225 #endif
3226 }
3227 
3228 /*
3229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3230 % %
3231 % %
3232 % %
3233 % N T W i n d o w s T e r m i n u s %
3234 % %
3235 % %
3236 % %
3237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3238 %
3239 % NTWindowsTerminus() terminates the MagickCore Windows environment.
3240 %
3241 % The format of the NTWindowsTerminus method is:
3242 %
3243 % void NTWindowsTerminus(void)
3244 %
3245 */
3246 MagickPrivate void NTWindowsTerminus(void)
3247 {
3248  NTGhostscriptUnLoadDLL();
3249  if (winsock_semaphore == (SemaphoreInfo *) NULL)
3250  ActivateSemaphoreInfo(&winsock_semaphore);
3251  LockSemaphoreInfo(winsock_semaphore);
3252  if (wsaData != (WSADATA *) NULL)
3253  {
3254  WSACleanup();
3255  wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData);
3256  }
3257  UnlockSemaphoreInfo(winsock_semaphore);
3258  DestroySemaphoreInfo(&winsock_semaphore);
3259 }
3260 #endif
Definition: mac.h:53
Definition: mac.h:41