MagickCore  6.9.13-46
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 s L i n k W i d e %
1637 % %
1638 % %
1639 % %
1640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1641 %
1642 % NTIsSymlinkWide() returns a boolean value indicating whether the specified path
1643 % is a a link.
1644 %
1645 % The format of the NTIsSymlinkWide method is:
1646 %
1647 % MagickBooleanType NTIsSymlinkWide(const char *path)
1648 %
1649 % A description of each parameter follows:
1650 %
1651 % o path: the file path.
1652 %
1653 */
1654 MagickExport MagickBooleanType NTIsSymlinkWide(const char *path)
1655 {
1656  DWORD
1657  attributes;
1658 
1659  wchar_t
1660  *path_wide;
1661 
1662  path_wide=NTCreateWidePath(path);
1663  attributes=GetFileAttributesW(path_wide);
1664  if (attributes == INVALID_FILE_ATTRIBUTES)
1665  return(MagickFalse);
1666  return(((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ? MagickTrue :
1667  MagickFalse);
1668 }
1669 
1670 /*
1671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1672 % %
1673 % %
1674 % %
1675 % N T I n i t i a l i z e L i b r a r y %
1676 % %
1677 % %
1678 % %
1679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1680 %
1681 % NTInitializeLibrary() initializes the dynamic module loading subsystem.
1682 %
1683 % The format of the NTInitializeLibrary method is:
1684 %
1685 % int NTInitializeLibrary(void)
1686 %
1687 */
1688 MagickPrivate int NTInitializeLibrary(void)
1689 {
1690  return(0);
1691 }
1692 
1693 /*
1694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1695 % %
1696 % %
1697 % %
1698 % N T I n i t i a l i z e W i n s o c k %
1699 % %
1700 % %
1701 % %
1702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1703 %
1704 % NTInitializeWinsock() initializes Winsock.
1705 %
1706 % The format of the NTInitializeWinsock method is:
1707 %
1708 % void NTInitializeWinsock(void)
1709 %
1710 */
1711 MagickPrivate void NTInitializeWinsock(MagickBooleanType use_lock)
1712 {
1713  if (use_lock)
1714  {
1715  if (winsock_semaphore == (SemaphoreInfo *) NULL)
1716  ActivateSemaphoreInfo(&winsock_semaphore);
1717  LockSemaphoreInfo(winsock_semaphore);
1718  }
1719  if (wsaData == (WSADATA *) NULL)
1720  {
1721  wsaData=(WSADATA *) AcquireMagickMemory(sizeof(WSADATA));
1722  if (WSAStartup(MAKEWORD(2,2),wsaData) != 0)
1723  ThrowFatalException(CacheFatalError,"WSAStartup failed");
1724  }
1725  if (use_lock)
1726  UnlockSemaphoreInfo(winsock_semaphore);
1727 }
1728 
1729 /*
1730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1731 % %
1732 % %
1733 % %
1734 % N T L o n g P a t h s E n a b l e d %
1735 % %
1736 % %
1737 % %
1738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1739 %
1740 % NTLongPathsEnabled() returns a boolean indicating whether long paths are
1741 $ enabled.
1742 %
1743 % The format of the NTLongPathsEnabled method is:
1744 %
1745 % MagickBooleanType NTLongPathsEnabled()
1746 %
1747 */
1748 MagickExport MagickBooleanType NTLongPathsEnabled()
1749 {
1750  if (long_paths_enabled == 2)
1751  {
1752  DWORD
1753  size,
1754  type,
1755  value;
1756 
1757  HKEY
1758  registry_key;
1759 
1760  LONG
1761  status;
1762 
1763  registry_key=(HKEY) INVALID_HANDLE_VALUE;
1764  status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1765  "SYSTEM\\CurrentControlSet\\Control\\FileSystem",0,KEY_READ,
1766  &registry_key);
1767  if (status != ERROR_SUCCESS)
1768  {
1769  long_paths_enabled=0;
1770  RegCloseKey(registry_key);
1771  return(MagickFalse);
1772  }
1773  value=0;
1774  status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,NULL,
1775  NULL);
1776  if ((status != ERROR_SUCCESS) || (type != REG_DWORD))
1777  {
1778  long_paths_enabled=0;
1779  RegCloseKey(registry_key);
1780  return(MagickFalse);
1781  }
1782  status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,
1783  (LPBYTE) &value,&size);
1784  RegCloseKey(registry_key);
1785  if (status != ERROR_SUCCESS)
1786  {
1787  long_paths_enabled=0;
1788  return(MagickFalse);
1789  }
1790  long_paths_enabled=(size_t) value;
1791  }
1792  return(long_paths_enabled == 1 ? MagickTrue : MagickFalse);
1793 }
1794 
1795 /*
1796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1797 % %
1798 % %
1799 % %
1800 + N T M a p M e m o r y %
1801 % %
1802 % %
1803 % %
1804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1805 %
1806 % NTMapMemory() emulates the Unix method of the same name.
1807 %
1808 % The format of the NTMapMemory method is:
1809 %
1810 % void *NTMapMemory(char *address,size_t length,int protection,int access,
1811 % int file,MagickOffsetType offset)
1812 %
1813 */
1814 MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1815  int flags,int file,MagickOffsetType offset)
1816 {
1817  DWORD
1818  access_mode,
1819  high_length,
1820  high_offset,
1821  low_length,
1822  low_offset,
1823  protection_mode;
1824 
1825  HANDLE
1826  file_handle,
1827  map_handle;
1828 
1829  void
1830  *map;
1831 
1832  (void) address;
1833  access_mode=0;
1834  file_handle=INVALID_HANDLE_VALUE;
1835  low_length=(DWORD) (length & 0xFFFFFFFFUL);
1836  high_length=(DWORD) ((((MagickOffsetType) length) >> 32) & 0xFFFFFFFFUL);
1837  map_handle=INVALID_HANDLE_VALUE;
1838  map=(void *) NULL;
1839  low_offset=(DWORD) (offset & 0xFFFFFFFFUL);
1840  high_offset=(DWORD) ((offset >> 32) & 0xFFFFFFFFUL);
1841  protection_mode=0;
1842  if (protection & PROT_WRITE)
1843  {
1844  access_mode=FILE_MAP_WRITE;
1845  if (!(flags & MAP_PRIVATE))
1846  protection_mode=PAGE_READWRITE;
1847  else
1848  {
1849  access_mode=FILE_MAP_COPY;
1850  protection_mode=PAGE_WRITECOPY;
1851  }
1852  }
1853  else
1854  if (protection & PROT_READ)
1855  {
1856  access_mode=FILE_MAP_READ;
1857  protection_mode=PAGE_READONLY;
1858  }
1859  if ((file == -1) && (flags & MAP_ANONYMOUS))
1860  file_handle=INVALID_HANDLE_VALUE;
1861  else
1862  file_handle=(HANDLE) _get_osfhandle(file);
1863  map_handle=CreateFileMapping(file_handle,0,protection_mode,high_length,
1864  low_length,0);
1865  if (map_handle)
1866  {
1867  map=(void *) MapViewOfFile(map_handle,access_mode,high_offset,low_offset,
1868  length);
1869  CloseHandle(map_handle);
1870  }
1871  if (map == (void *) NULL)
1872  return((void *) ((char *) MAP_FAILED));
1873  return((void *) ((char *) map));
1874 }
1875 
1876 /*
1877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1878 % %
1879 % %
1880 % %
1881 % N T O p e n D i r e c t o r y %
1882 % %
1883 % %
1884 % %
1885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1886 %
1887 % NTOpenDirectory() opens the directory named by filename and associates a
1888 % directory stream with it.
1889 %
1890 % The format of the NTOpenDirectory method is:
1891 %
1892 % DIR *NTOpenDirectory(const char *path)
1893 %
1894 % A description of each parameter follows:
1895 %
1896 % o entry: Specifies a pointer to a DIR structure.
1897 %
1898 */
1899 MagickPrivate DIR *NTOpenDirectory(const char *path)
1900 {
1901  DIR
1902  *entry;
1903 
1904  size_t
1905  length;
1906 
1907  wchar_t
1908  file_specification[MaxTextExtent];
1909 
1910  assert(path != (const char *) NULL);
1911  length=MultiByteToWideChar(CP_UTF8,0,path,-1,file_specification,
1912  MaxTextExtent);
1913  if (length == 0)
1914  return((DIR *) NULL);
1915  if(wcsncat(file_specification,L"\\*.*",MaxTextExtent-wcslen(
1916  file_specification)-1) == (wchar_t*) NULL)
1917  return((DIR *) NULL);
1918  entry=(DIR *) AcquireCriticalMemory(sizeof(DIR));
1919  entry->firsttime=TRUE;
1920  entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
1921  if (entry->hSearch == INVALID_HANDLE_VALUE)
1922  {
1923  entry=(DIR *) RelinquishMagickMemory(entry);
1924  return((DIR *) NULL);
1925  }
1926  return(entry);
1927 }
1928 
1929 /*
1930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1931 % %
1932 % %
1933 % %
1934 % N T O p e n L i b r a r y %
1935 % %
1936 % %
1937 % %
1938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1939 %
1940 % NTOpenLibrary() loads a dynamic module into memory and returns a handle that
1941 % can be used to access the various procedures in the module.
1942 %
1943 % The format of the NTOpenLibrary method is:
1944 %
1945 % void *NTOpenLibrary(const char *filename)
1946 %
1947 % A description of each parameter follows:
1948 %
1949 % o path: Specifies a pointer to string representing dynamic module that
1950 % is to be loaded.
1951 %
1952 */
1953 static inline const char *GetSearchPath(void)
1954 {
1955 #if defined(MAGICKCORE_LTDL_DELEGATE)
1956  return(lt_dlgetsearchpath());
1957 #else
1958  return(lt_slsearchpath);
1959 #endif
1960 }
1961 
1962 static UINT ChangeErrorMode(void)
1963 {
1964  typedef UINT
1965  (CALLBACK *GETERRORMODE)(void);
1966 
1967  GETERRORMODE
1968  getErrorMode;
1969 
1970  HMODULE
1971  handle;
1972 
1973  UINT
1974  mode;
1975 
1976  mode=SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1977 
1978  handle=GetModuleHandle("kernel32.dll");
1979  if (handle == (HMODULE) NULL)
1980  return SetErrorMode(mode);
1981 
1982  getErrorMode=(GETERRORMODE) NTGetLibrarySymbol(handle,"GetErrorMode");
1983  if (getErrorMode != (GETERRORMODE) NULL)
1984  mode=getErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1985 
1986  return SetErrorMode(mode);
1987 }
1988 
1989 static inline void *NTLoadLibrary(const char *filename)
1990 {
1991  int
1992  length;
1993 
1994  wchar_t
1995  path[MaxTextExtent];
1996 
1997  length=MultiByteToWideChar(CP_UTF8,0,filename,-1,path,MaxTextExtent);
1998  if (length == 0)
1999  return((void *) NULL);
2000  return (void *) LoadLibraryExW(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
2001 }
2002 
2003 MagickPrivate void *NTOpenLibrary(const char *filename)
2004 {
2005  char
2006  path[MaxTextExtent];
2007 
2008  const char
2009  *p,
2010  *q;
2011 
2012  UINT
2013  mode;
2014 
2015  void
2016  *handle;
2017 
2018  mode=ChangeErrorMode();
2019  handle=NTLoadLibrary(filename);
2020  if (handle == (void *) NULL)
2021  {
2022  p=GetSearchPath();
2023  while (p != (const char*) NULL)
2024  {
2025  q=strchr(p,DirectoryListSeparator);
2026  if (q != (const char*) NULL)
2027  (void) CopyMagickString(path,p,q-p+1);
2028  else
2029  (void) CopyMagickString(path,p,MaxTextExtent);
2030  (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
2031  (void) ConcatenateMagickString(path,filename,MaxTextExtent);
2032  handle=NTLoadLibrary(path);
2033  if (handle != (void *) NULL || q == (const char*) NULL)
2034  break;
2035  p=q+1;
2036  }
2037  }
2038  SetErrorMode(mode);
2039  return(handle);
2040 }
2041 
2042 /*
2043 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2044 % %
2045 % %
2046 % %
2047 % N T O p e n F i l e W i d e %
2048 % %
2049 % %
2050 % %
2051 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2052 %
2053 % NTOpenFileWide() opens a file and returns a file pointer.
2054 %
2055 % The format of the NTOpenFileWide method is:
2056 %
2057 % FILE *NTOpenFileWide(const char* path, const char* mode)
2058 %
2059 % A description of each parameter follows:
2060 %
2061 % o path: the file path.
2062 %
2063 % o mode: the file open mode.
2064 %
2065 */
2066 static inline wchar_t *create_wchar_mode(const char *mode)
2067 {
2068  int
2069  count;
2070 
2071  wchar_t
2072  *wide;
2073 
2074  count=MultiByteToWideChar(CP_UTF8,0,mode,-1,NULL,0);
2075  wide=(wchar_t *) AcquireQuantumMemory((size_t) count+1,
2076  sizeof(*wide));
2077  if (wide == (wchar_t *) NULL)
2078  return((wchar_t *) NULL);
2079  if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wide,count) == 0)
2080  {
2081  wide=(wchar_t *) RelinquishMagickMemory(wide);
2082  return((wchar_t *) NULL);
2083  }
2084  /* Specifies that the file is not inherited by child processes */
2085  wide[count] = L'\0';
2086  wide[count-1] = L'N';
2087  return(wide);
2088 }
2089 
2090 MagickExport FILE *NTOpenFileWide(const char* path, const char* mode)
2091 {
2092  FILE
2093  *file;
2094 
2095  wchar_t
2096  *mode_wide,
2097  *path_wide;
2098 
2099  path_wide=NTCreateWidePath(path);
2100  if (path_wide == (wchar_t *) NULL)
2101  return((FILE *) NULL);
2102  mode_wide=create_wchar_mode(mode);
2103  if (mode_wide == (wchar_t *) NULL)
2104  {
2105  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2106  return((FILE *) NULL);
2107  }
2108  if (_wfopen_s(&file,path_wide,mode_wide) != 0)
2109  file=(FILE *) NULL;
2110  mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
2111  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2112  return(file);
2113 }
2114 
2115 /*
2116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2117 % %
2118 % %
2119 % %
2120 % N T O p e n P i p e W i d e %
2121 % %
2122 % %
2123 % %
2124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2125 %
2126 % NTOpenPipeWide() opens a pipe and returns a file pointer.
2127 %
2128 % The format of the NTOpenPipeWide method is:
2129 %
2130 % FILE *NTOpenPipeWide(const char* command, const char* type)
2131 %
2132 % A description of each parameter follows:
2133 %
2134 % o command: the command to execute.
2135 %
2136 % o type: the file open mode.
2137 %
2138 */
2139 MagickExport FILE *NTOpenPipeWide(const char *command,const char *type)
2140 {
2141  FILE
2142  *file;
2143 
2144  int
2145  length;
2146 
2147  wchar_t
2148  *command_wide,
2149  type_wide[5];
2150 
2151  file=(FILE *) NULL;
2152  length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
2153  if (length == 0)
2154  return(file);
2155  length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
2156  if (length == 0)
2157  return(file);
2158  command_wide=(wchar_t *) AcquireQuantumMemory((size_t) length,
2159  sizeof(*command_wide));
2160  if (command_wide == (wchar_t *) NULL)
2161  return(file);
2162  length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
2163  if (length != 0)
2164  file=_wpopen(command_wide,type_wide);
2165  command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
2166  return(file);
2167 }
2168 
2169 /*
2170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2171 % %
2172 % %
2173 % %
2174 % N T O p e n W i d e %
2175 % %
2176 % %
2177 % %
2178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2179 %
2180 % NTOpenWide() opens the file specified by path and mode.
2181 %
2182 % The format of the NTOpenWide method is:
2183 %
2184 % FILE *NTOpenWide(const char* path, const char* mode)
2185 %
2186 % A description of each parameter follows:
2187 %
2188 % o path: the file path.
2189 %
2190 % o flags: the file open flags.
2191 %
2192 % o mode: the file open mode.
2193 %
2194 */
2195 MagickExport int NTOpenWide(const char* path,int flags,mode_t mode)
2196 {
2197  int
2198  file_handle,
2199  status;
2200 
2201  wchar_t
2202  *path_wide;
2203 
2204  path_wide=NTCreateWidePath(path);
2205  if (path_wide == (wchar_t *) NULL)
2206  return(-1);
2207  /* O_NOINHERIT specifies that the file is not inherited by child processes */
2208  status=_wsopen_s(&file_handle,path_wide,flags | O_NOINHERIT,_SH_DENYNO,mode);
2209  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2210  return(status == 0 ? file_handle : -1);
2211 }
2212 
2213 /*
2214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2215 % %
2216 % %
2217 % %
2218 % N T R e a d D i r e c t o r y %
2219 % %
2220 % %
2221 % %
2222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2223 %
2224 % NTReadDirectory() returns a pointer to a structure representing the
2225 % directory entry at the current position in the directory stream to which
2226 % entry refers.
2227 %
2228 % The format of the NTReadDirectory
2229 %
2230 % NTReadDirectory(entry)
2231 %
2232 % A description of each parameter follows:
2233 %
2234 % o entry: Specifies a pointer to a DIR structure.
2235 %
2236 */
2237 MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
2238 {
2239  int
2240  status;
2241 
2242  size_t
2243  length;
2244 
2245  if (entry == (DIR *) NULL)
2246  return((struct dirent *) NULL);
2247  if (!entry->firsttime)
2248  {
2249  status=FindNextFileW(entry->hSearch,&entry->Win32FindData);
2250  if (status == 0)
2251  return((struct dirent *) NULL);
2252  }
2253  length=WideCharToMultiByte(CP_UTF8,0,entry->Win32FindData.cFileName,-1,
2254  entry->file_info.d_name,sizeof(entry->file_info.d_name),NULL,NULL);
2255  if (length == 0)
2256  return((struct dirent *) NULL);
2257  entry->firsttime=FALSE;
2258  entry->file_info.d_namlen=(int) strlen(entry->file_info.d_name);
2259  return(&entry->file_info);
2260 }
2261 
2262 /*
2263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264 % %
2265 % %
2266 % %
2267 % N T R e a l P a t h W i d e %
2268 % %
2269 % %
2270 % %
2271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2272 %
2273 % NTRealPathWide returns the absolute path of the specified path.
2274 %
2275 % The format of the NTRealPathWide method is:
2276 %
2277 % char *NTRealPathWide(const char *path)
2278 %
2279 % A description of each parameter follows:
2280 %
2281 % o path: the file path.
2282 %
2283 */
2284 static inline wchar_t* resolve_symlink(const wchar_t* path)
2285 {
2286  DWORD
2287  link_length;
2288 
2289  HANDLE
2290  file_handle;
2291 
2292  wchar_t
2293  *link;
2294 
2295  file_handle=CreateFileW(path,GENERIC_READ,FILE_SHARE_READ |FILE_SHARE_WRITE |
2296  FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
2297  if (file_handle == INVALID_HANDLE_VALUE)
2298  return((wchar_t *) NULL);
2299  link_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
2300  FILE_NAME_NORMALIZED);
2301  link=(wchar_t *) AcquireQuantumMemory(link_length,sizeof(wchar_t));
2302  if (link == (wchar_t *) NULL)
2303  {
2304  CloseHandle(file_handle);
2305  return((wchar_t *) NULL);
2306  }
2307  GetFinalPathNameByHandleW(file_handle,link,link_length,FILE_NAME_NORMALIZED);
2308  CloseHandle(file_handle);
2309  return(link);
2310 }
2311 
2312 MagickExport char *NTRealPathWide(const char *path)
2313 {
2314  char
2315  *real_path;
2316 
2317  wchar_t
2318  *wide_real_path,
2319  *wide_path;
2320 
2321  wide_path=NTCreateWidePath(path);
2322  wide_real_path=resolve_symlink(wide_path);
2323  if (wide_real_path == (wchar_t*) NULL)
2324  {
2325  DWORD
2326  full_path_length;
2327 
2328  full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
2329  wide_real_path=(wchar_t *) AcquireQuantumMemory(full_path_length,
2330  sizeof(wchar_t));
2331  if (wide_real_path == (wchar_t*) NULL)
2332  {
2333  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
2334  return((char*) NULL);
2335  }
2336  GetFullPathNameW(wide_path,full_path_length,wide_real_path,NULL);
2337  }
2338  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
2339  /*
2340  Remove \\?\ prefix for POSIX-like behavior.
2341  */
2342  if (wcsncmp(wide_real_path,L"\\\\?\\",4) == 0)
2343  real_path=create_utf8_string(wide_real_path+4);
2344  else
2345  real_path=create_utf8_string(wide_real_path);
2346  wide_real_path=(wchar_t *) RelinquishMagickMemory(wide_real_path);
2347  return(real_path);
2348 }
2349 
2350 /*
2351 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2352 % %
2353 % %
2354 % %
2355 % N T R e g i s t r y K e y L o o k u p %
2356 % %
2357 % %
2358 % %
2359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2360 %
2361 % NTRegistryKeyLookup() returns ImageMagick installation path settings
2362 % stored in the Windows Registry. Path settings are specific to the
2363 % installed ImageMagick version so that multiple Image Magick installations
2364 % may coexist.
2365 %
2366 % Values are stored in the registry under a base path similar to
2367 % "HKEY_LOCAL_MACHINE/SOFTWARE\ImageMagick\6.7.4\Q:16" or
2368 % "HKEY_CURRENT_USER/SOFTWARE\ImageMagick\6.7.4\Q:16". The provided subkey
2369 % is appended to this base path to form the full key.
2370 %
2371 % The format of the NTRegistryKeyLookup method is:
2372 %
2373 % unsigned char *NTRegistryKeyLookup(const char *subkey)
2374 %
2375 % A description of each parameter follows:
2376 %
2377 % o subkey: Specifies a string that identifies the registry object.
2378 % Currently supported sub-keys include: "BinPath", "ConfigurePath",
2379 % "LibPath", "CoderModulesPath", "FilterModulesPath", "SharePath".
2380 %
2381 */
2382 MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
2383 {
2384  char
2385  package_key[MaxTextExtent] = "";
2386 
2387  unsigned char
2388  *value;
2389 
2390  (void) FormatLocaleString(package_key,MagickPathExtent,
2391  "SOFTWARE\\%s\\%s\\Q:%d",MagickPackageName,MagickLibVersionText,
2392  MAGICKCORE_QUANTUM_DEPTH);
2393  value=NTGetRegistryValue(HKEY_LOCAL_MACHINE,package_key,0,subkey);
2394  if (value == (unsigned char *) NULL)
2395  value=NTGetRegistryValue(HKEY_CURRENT_USER,package_key,0,subkey);
2396  return(value);
2397 }
2398 
2399 /*
2400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2401 % %
2402 % %
2403 % %
2404 % N T R e m o v e W i d e %
2405 % %
2406 % %
2407 % %
2408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2409 %
2410 % NTRemoveWide() removes the specified file.
2411 %
2412 % The format of the NTRemoveWide method is:
2413 %
2414 % int NTRemoveWide(const char *path)
2415 %
2416 % A description of each parameter follows:
2417 %
2418 % o path: the file path.
2419 %
2420 */
2421 MagickExport int NTRemoveWide(const char *path)
2422 {
2423  int
2424  status;
2425 
2426  wchar_t
2427  *path_wide;
2428 
2429  path_wide=NTCreateWidePath(path);
2430  if (path_wide == (wchar_t *) NULL)
2431  return(-1);
2432  status=_wremove(path_wide);
2433  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2434  return(status);
2435 }
2436 
2437 /*
2438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2439 % %
2440 % %
2441 % %
2442 % N T R e n a m e W i d e %
2443 % %
2444 % %
2445 % %
2446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2447 %
2448 % NTRenameWide() renames a file.
2449 %
2450 % The format of the NTRenameWide method is:
2451 %
2452 % int NTRenameWide(const char *source, const char *destination)
2453 %
2454 % A description of each parameter follows:
2455 %
2456 % o source: the source file path.
2457 %
2458 % o destination: the destination file path.
2459 %
2460 */
2461 MagickExport int NTRenameWide(const char* source, const char* destination)
2462 {
2463  int
2464  status;
2465 
2466  wchar_t
2467  *destination_wide,
2468  *source_wide;
2469 
2470  source_wide=NTCreateWidePath(source);
2471  if (source_wide == (wchar_t *) NULL)
2472  return(-1);
2473  destination_wide=NTCreateWidePath(destination);
2474  if (destination_wide == (wchar_t *) NULL)
2475  {
2476  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
2477  return(-1);
2478  }
2479  status=_wrename(source_wide,destination_wide);
2480  destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
2481  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
2482  return(status);
2483 }
2484 
2485 /*
2486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2487 % %
2488 % %
2489 % %
2490 % N T R e p o r t E v e n t %
2491 % %
2492 % %
2493 % %
2494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2495 %
2496 % NTReportEvent() reports an event.
2497 %
2498 % The format of the NTReportEvent method is:
2499 %
2500 % MagickBooleanType NTReportEvent(const char *event,
2501 % const MagickBooleanType error)
2502 %
2503 % A description of each parameter follows:
2504 %
2505 % o event: the event.
2506 %
2507 % o error: MagickTrue the event is an error.
2508 %
2509 */
2510 MagickPrivate MagickBooleanType NTReportEvent(const char *event,
2511  const MagickBooleanType error)
2512 {
2513  const char
2514  *events[1];
2515 
2516  HANDLE
2517  handle;
2518 
2519  WORD
2520  type;
2521 
2522  handle=RegisterEventSource(NULL,MAGICKCORE_PACKAGE_NAME);
2523  if (handle == NULL)
2524  return(MagickFalse);
2525  events[0]=event;
2526  type=error ? EVENTLOG_ERROR_TYPE : EVENTLOG_WARNING_TYPE;
2527  ReportEvent(handle,type,0,0,NULL,1,0,events,NULL);
2528  DeregisterEventSource(handle);
2529  return(MagickTrue);
2530 }
2531 
2532 /*
2533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2534 % %
2535 % %
2536 % %
2537 % N T R e s o u r c e T o B l o b %
2538 % %
2539 % %
2540 % %
2541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2542 %
2543 % NTResourceToBlob() returns a blob containing the contents of the resource
2544 % in the current executable specified by the id parameter. This currently
2545 % used to retrieve MGK files tha have been embedded into the various command
2546 % line utilities.
2547 %
2548 % The format of the NTResourceToBlob method is:
2549 %
2550 % unsigned char *NTResourceToBlob(const char *id)
2551 %
2552 % A description of each parameter follows:
2553 %
2554 % o id: Specifies a string that identifies the resource.
2555 %
2556 */
2557 MagickPrivate unsigned char *NTResourceToBlob(const char *id)
2558 {
2559 
2560 #ifndef MAGICKCORE_LIBRARY_NAME
2561  char
2562  path[MaxTextExtent];
2563 #endif
2564 
2565  DWORD
2566  length;
2567 
2568  HGLOBAL
2569  global;
2570 
2571  HMODULE
2572  handle;
2573 
2574  HRSRC
2575  resource;
2576 
2577  unsigned char
2578  *blob,
2579  *value;
2580 
2581  assert(id != (const char *) NULL);
2582  if (IsEventLogging() != MagickFalse)
2583  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
2584 #ifdef MAGICKCORE_LIBRARY_NAME
2585  handle=GetModuleHandle(MAGICKCORE_LIBRARY_NAME);
2586 #else
2587  (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
2588  DirectorySeparator,GetClientName());
2589  if (IsPathAccessible(path) != MagickFalse)
2590  handle=GetModuleHandle(path);
2591  else
2592  handle=GetModuleHandle(0);
2593 #endif
2594  if (!handle)
2595  return((unsigned char *) NULL);
2596  resource=FindResource(handle,id,"IMAGEMAGICK");
2597  if (!resource)
2598  return((unsigned char *) NULL);
2599  global=LoadResource(handle,resource);
2600  if (!global)
2601  return((unsigned char *) NULL);
2602  length=SizeofResource(handle,resource);
2603  value=(unsigned char *) LockResource(global);
2604  if (!value)
2605  {
2606  FreeResource(global);
2607  return((unsigned char *) NULL);
2608  }
2609  blob=(unsigned char *) AcquireQuantumMemory(length+MaxTextExtent,
2610  sizeof(*blob));
2611  if (blob != (unsigned char *) NULL)
2612  {
2613  (void) memcpy(blob,value,length);
2614  blob[length]='\0';
2615  }
2616  UnlockResource(global);
2617  FreeResource(global);
2618  return(blob);
2619 }
2620 
2621 /*
2622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2623 % %
2624 % %
2625 % %
2626 % NT S e t F i l e T i m e s t a m p %
2627 % %
2628 % %
2629 % %
2630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2631 %
2632 % NTSetFileTimestamp() sets the file timestamps for a specified file.
2633 %
2634 % The format of the NTSetFileTimestamp method is:
2635 %
2636 % int NTSetFileTimestamp(const char *path, struct stat *attributes)
2637 %
2638 % A description of each parameter follows:
2639 %
2640 % o path: the file path.
2641 %
2642 % o attributes: the file attributes.
2643 %
2644 */
2645 MagickExport int NTSetFileTimestamp(const char *path, struct stat *attributes)
2646 {
2647  HANDLE
2648  handle;
2649 
2650  int
2651  status;
2652 
2653  wchar_t
2654  *path_wide;
2655 
2656  status=(-1);
2657  path_wide=NTCreateWidePath(path);
2658  if (path_wide == (WCHAR *) NULL)
2659  return(status);
2660  handle=CreateFileW(path_wide,FILE_WRITE_ATTRIBUTES,FILE_SHARE_WRITE |
2661  FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
2662  if (handle != (HANDLE) NULL)
2663  {
2664  FILETIME
2665  creation_time,
2666  last_access_time,
2667  last_write_time;
2668 
2669  ULARGE_INTEGER
2670  date_time;
2671 
2672  date_time.QuadPart=(ULONGLONG) (attributes->st_ctime*10000000LL)+
2673  116444736000000000LL;
2674  creation_time.dwLowDateTime=date_time.LowPart;
2675  creation_time.dwHighDateTime=date_time.HighPart;
2676  date_time.QuadPart=(ULONGLONG) (attributes->st_atime*10000000LL)+
2677  116444736000000000LL;
2678  last_access_time.dwLowDateTime=date_time.LowPart;
2679  last_access_time.dwHighDateTime=date_time.HighPart;
2680  date_time.QuadPart=(ULONGLONG) (attributes->st_mtime*10000000LL)+
2681  116444736000000000LL;
2682  last_write_time.dwLowDateTime=date_time.LowPart;
2683  last_write_time.dwHighDateTime=date_time.HighPart;
2684  status=SetFileTime(handle,&creation_time,&last_access_time,&last_write_time);
2685  CloseHandle(handle);
2686  status=0;
2687  }
2688  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
2689  return(status);
2690 }
2691 
2692 /*
2693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2694 % %
2695 % %
2696 % %
2697 % N T S e t S e a r c h P a t h %
2698 % %
2699 % %
2700 % %
2701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2702 %
2703 % NTSetSearchPath() sets the current locations that the subsystem should
2704 % look at to find dynamically loadable modules.
2705 %
2706 % The format of the NTSetSearchPath method is:
2707 %
2708 % int NTSetSearchPath(const char *path)
2709 %
2710 % A description of each parameter follows:
2711 %
2712 % o path: Specifies a pointer to string representing the search path
2713 % for DLL's that can be dynamically loaded.
2714 %
2715 */
2716 MagickPrivate int NTSetSearchPath(const char *path)
2717 {
2718 #if defined(MAGICKCORE_LTDL_DELEGATE)
2719  lt_dlsetsearchpath(path);
2720 #else
2721  if (lt_slsearchpath != (char *) NULL)
2722  lt_slsearchpath=DestroyString(lt_slsearchpath);
2723  if (path != (char *) NULL)
2724  lt_slsearchpath=AcquireString(path);
2725 #endif
2726  return(0);
2727 }
2728 
2729 /*
2730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2731 % %
2732 % %
2733 % %
2734 % N T S t a t W i d e %
2735 % %
2736 % %
2737 % %
2738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2739 %
2740 % NTStatWide() gets the file attributes for a specified file.
2741 %
2742 % The format of the NTStatWide method is:
2743 %
2744 % int NTStatWide(const char *path,struct stat *attributes)
2745 %
2746 % A description of each parameter follows:
2747 %
2748 % o path: the file path.
2749 %
2750 % o attributes: the file attributes.
2751 %
2752 */
2753 MagickExport int NTStatWide(const char *path,struct stat *attributes)
2754 {
2755  int
2756  status;
2757 
2758  wchar_t
2759  *path_wide;
2760 
2761  path_wide=NTCreateWidePath(path);
2762  if (path_wide == (WCHAR *) NULL)
2763  return(-1);
2764  status=wstat(path_wide,attributes);
2765  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
2766  return(status);
2767 }
2768 
2769 /*
2770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2771 % %
2772 % %
2773 % %
2774 % N T S y s t e m C o m m a n d %
2775 % %
2776 % %
2777 % %
2778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2779 %
2780 % NTSystemCommand() executes the specified command and waits until it
2781 % terminates. The returned value is the exit status of the command.
2782 %
2783 % The format of the NTSystemCommand method is:
2784 %
2785 % int NTSystemCommand(MagickFalse,const char *command)
2786 %
2787 % A description of each parameter follows:
2788 %
2789 % o command: This string is the command to execute.
2790 %
2791 % o output: an optional buffer to store the output from stderr/stdout.
2792 %
2793 */
2794 MagickPrivate int NTSystemCommand(const char *command,char *output)
2795 {
2796 #define CleanupOutputHandles \
2797  if (read_output != (HANDLE) NULL) \
2798  { \
2799  CloseHandle(read_output); \
2800  read_output=(HANDLE) NULL; \
2801  CloseHandle(write_output); \
2802  write_output=(HANDLE) NULL; \
2803  }
2804 
2805 #define CopyLastError \
2806  last_error=GetLastError(); \
2807  if (output != (char *) NULL) \
2808  { \
2809  error=NTGetLastErrorMessage(last_error); \
2810  if (error != (char *) NULL) \
2811  { \
2812  CopyMagickString(output,error,MaxTextExtent); \
2813  error=DestroyString(error); \
2814  } \
2815  }
2816 
2817  char
2818  *error,
2819  local_command[MaxTextExtent];
2820 
2821  DWORD
2822  child_status,
2823  last_error;
2824 
2825  int
2826  status;
2827 
2828  MagickBooleanType
2829  asynchronous;
2830 
2831  HANDLE
2832  read_output,
2833  write_output;
2834 
2835  PROCESS_INFORMATION
2836  process_info;
2837 
2838  size_t
2839  output_offset;
2840 
2841  STARTUPINFO
2842  startup_info;
2843 
2844  if (command == (char *) NULL)
2845  return(-1);
2846  read_output=(HANDLE) NULL;
2847  write_output=(HANDLE) NULL;
2848  GetStartupInfo(&startup_info);
2849  startup_info.dwFlags=STARTF_USESHOWWINDOW;
2850  startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
2851  (void) CopyMagickString(local_command,command,MaxTextExtent);
2852  asynchronous=command[strlen(command)-1] == '&' ? MagickTrue : MagickFalse;
2853  if (asynchronous != MagickFalse)
2854  {
2855  local_command[strlen(command)-1]='\0';
2856  startup_info.wShowWindow=SW_SHOWDEFAULT;
2857  }
2858  else
2859  {
2860  if (command[strlen(command)-1] == '|')
2861  local_command[strlen(command)-1]='\0';
2862  else
2863  startup_info.wShowWindow=SW_HIDE;
2864  read_output=(HANDLE) NULL;
2865  if (output != (char *) NULL)
2866  {
2867  if (CreatePipe(&read_output,&write_output,NULL,0))
2868  {
2869  if (SetHandleInformation(write_output,HANDLE_FLAG_INHERIT,
2870  HANDLE_FLAG_INHERIT))
2871  {
2872  startup_info.dwFlags|=STARTF_USESTDHANDLES;
2873  startup_info.hStdOutput=write_output;
2874  startup_info.hStdError=write_output;
2875  }
2876  else
2877  CleanupOutputHandles;
2878  }
2879  else
2880  read_output=(HANDLE) NULL;
2881  }
2882  }
2883  status=CreateProcess((LPCTSTR) NULL,local_command,(LPSECURITY_ATTRIBUTES)
2884  NULL,(LPSECURITY_ATTRIBUTES) NULL,(BOOL) TRUE,(DWORD)
2885  NORMAL_PRIORITY_CLASS,(LPVOID) NULL,(LPCSTR) NULL,&startup_info,
2886  &process_info);
2887  if (status == 0)
2888  {
2889  CopyLastError;
2890  CleanupOutputHandles;
2891  return(last_error == ERROR_FILE_NOT_FOUND ? 127 : -1);
2892  }
2893  if (output != (char *) NULL)
2894  *output='\0';
2895  if (asynchronous != MagickFalse)
2896  return(status == 0);
2897  output_offset=0;
2898  status=STATUS_TIMEOUT;
2899  while (status == STATUS_TIMEOUT)
2900  {
2901  DWORD
2902  size;
2903 
2904  status=WaitForSingleObject(process_info.hProcess,1000);
2905  size=0;
2906  if (read_output != (HANDLE) NULL)
2907  if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2908  break;
2909  while (size > 0)
2910  {
2911  char
2912  buffer[MagickPathExtent];
2913 
2914  DWORD
2915  bytes_read;
2916 
2917  if (ReadFile(read_output,buffer,MagickPathExtent-1,&bytes_read,NULL))
2918  {
2919  size_t
2920  count;
2921 
2922  count=MagickMin(MagickPathExtent-output_offset,
2923  (size_t) bytes_read+1);
2924  if (count > 0)
2925  {
2926  CopyMagickString(output+output_offset,buffer,count);
2927  output_offset+=count-1;
2928  }
2929  }
2930  if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2931  break;
2932  }
2933  }
2934  if (status != WAIT_OBJECT_0)
2935  {
2936  CopyLastError;
2937  CleanupOutputHandles;
2938  return(status);
2939  }
2940  status=GetExitCodeProcess(process_info.hProcess,&child_status);
2941  if (status == 0)
2942  {
2943  CopyLastError;
2944  CleanupOutputHandles;
2945  return(-1);
2946  }
2947  CloseHandle(process_info.hProcess);
2948  CloseHandle(process_info.hThread);
2949  CleanupOutputHandles;
2950  return((int) child_status);
2951 }
2952 
2953 /*
2954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2955 % %
2956 % %
2957 % %
2958 % N T S y s t e m C o n i f i g u r a t i o n %
2959 % %
2960 % %
2961 % %
2962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2963 %
2964 % NTSystemConfiguration() provides a way for the application to determine
2965 % values for system limits or options at runtime.
2966 %
2967 % The format of the exit method is:
2968 %
2969 % ssize_t NTSystemConfiguration(int name)
2970 %
2971 % A description of each parameter follows:
2972 %
2973 % o name: _SC_PAGE_SIZE or _SC_PHYS_PAGES.
2974 %
2975 */
2976 MagickPrivate ssize_t NTSystemConfiguration(int name)
2977 {
2978  switch (name)
2979  {
2980  case _SC_PAGE_SIZE:
2981  {
2982  SYSTEM_INFO
2983  system_info;
2984 
2985  GetSystemInfo(&system_info);
2986  return(system_info.dwPageSize);
2987  }
2988  case _SC_PHYS_PAGES:
2989  {
2990  MEMORYSTATUSEX
2991  status;
2992 
2993  SYSTEM_INFO
2994  system_info;
2995 
2996  status.dwLength=sizeof(status);
2997  if (GlobalMemoryStatusEx(&status) == 0)
2998  return(0L);
2999  GetSystemInfo(&system_info);
3000  return((ssize_t) status.ullTotalPhys/system_info.dwPageSize);
3001  }
3002  case _SC_OPEN_MAX:
3003  return(2048);
3004  default:
3005  break;
3006  }
3007  return(-1);
3008 }
3009 
3010 /*
3011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3012 % %
3013 % %
3014 % %
3015 % N T T r u n c a t e F i l e %
3016 % %
3017 % %
3018 % %
3019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3020 %
3021 % NTTruncateFile() truncates a file to a specified length.
3022 %
3023 % The format of the NTTruncateFile method is:
3024 %
3025 % int NTTruncateFile(int file,off_t length)
3026 %
3027 % A description of each parameter follows:
3028 %
3029 % o file: the file.
3030 %
3031 % o length: the file length.
3032 %
3033 */
3034 MagickPrivate int NTTruncateFile(int file,off_t length)
3035 {
3036  DWORD
3037  file_pointer;
3038 
3039  HANDLE
3040  file_handle;
3041 
3042  long
3043  high,
3044  low;
3045 
3046  file_handle=(HANDLE) _get_osfhandle(file);
3047  if (file_handle == INVALID_HANDLE_VALUE)
3048  return(-1);
3049  low=(long) (length & 0xffffffffUL);
3050  high=(long) ((((MagickOffsetType) length) >> 32) & 0xffffffffUL);
3051  file_pointer=SetFilePointer(file_handle,low,&high,FILE_BEGIN);
3052  if ((file_pointer == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
3053  return(-1);
3054  if (SetEndOfFile(file_handle) == 0)
3055  return(-1);
3056  return(0);
3057 }
3058 
3059 /*
3060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3061 % %
3062 % %
3063 % %
3064 + N T U n m a p M e m o r y %
3065 % %
3066 % %
3067 % %
3068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3069 %
3070 % NTUnmapMemory() emulates the Unix munmap method.
3071 %
3072 % The format of the NTUnmapMemory method is:
3073 %
3074 % int NTUnmapMemory(void *map,size_t length)
3075 %
3076 % A description of each parameter follows:
3077 %
3078 % o map: the address of the binary large object.
3079 %
3080 % o length: the length of the binary large object.
3081 %
3082 */
3083 MagickPrivate int NTUnmapMemory(void *map,size_t length)
3084 {
3085  (void) length;
3086  if (UnmapViewOfFile(map) == 0)
3087  return(-1);
3088  return(0);
3089 }
3090 
3091 /*
3092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3093 % %
3094 % %
3095 % %
3096 % N T U s e r T i m e %
3097 % %
3098 % %
3099 % %
3100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3101 %
3102 % NTUserTime() returns the total time the process has been scheduled (e.g.
3103 % seconds) since the last call to StartTimer().
3104 %
3105 % The format of the UserTime method is:
3106 %
3107 % double NTUserTime(void)
3108 %
3109 */
3110 MagickPrivate double NTUserTime(void)
3111 {
3112  DWORD
3113  status;
3114 
3115  FILETIME
3116  create_time,
3117  exit_time;
3118 
3119  OSVERSIONINFO
3120  OsVersionInfo;
3121 
3122  union
3123  {
3124  FILETIME
3125  filetime;
3126 
3127  __int64
3128  filetime64;
3129  } kernel_time;
3130 
3131  union
3132  {
3133  FILETIME
3134  filetime;
3135 
3136  __int64
3137  filetime64;
3138  } user_time;
3139 
3140  OsVersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
3141  GetVersionEx(&OsVersionInfo);
3142  if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
3143  return(NTElapsedTime());
3144  status=GetProcessTimes(GetCurrentProcess(),&create_time,&exit_time,
3145  &kernel_time.filetime,&user_time.filetime);
3146  if (status != TRUE)
3147  return(0.0);
3148  return((double) 1.0e-7*(kernel_time.filetime64+user_time.filetime64));
3149 }
3150 
3151 /*
3152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3153 % %
3154 % %
3155 % %
3156 % N T W a r n i n g H a n d l e r %
3157 % %
3158 % %
3159 % %
3160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3161 %
3162 % NTWarningHandler() displays a warning reason.
3163 %
3164 % The format of the NTWarningHandler method is:
3165 %
3166 % void NTWarningHandler(const ExceptionType severity,const char *reason,
3167 % const char *description)
3168 %
3169 % A description of each parameter follows:
3170 %
3171 % o severity: Specifies the numeric warning category.
3172 %
3173 % o reason: Specifies the reason to display before terminating the
3174 % program.
3175 %
3176 % o description: Specifies any description to the reason.
3177 %
3178 */
3179 MagickPrivate void NTWarningHandler(const ExceptionType severity,
3180  const char *reason,const char *description)
3181 {
3182  char
3183  buffer[2*MaxTextExtent];
3184 
3185  (void) severity;
3186  if (reason == (char *) NULL)
3187  return;
3188  if (description == (char *) NULL)
3189  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
3190  reason);
3191  else
3192  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
3193  GetClientName(),reason,description);
3194  (void) MessageBox(NULL,buffer,"ImageMagick Warning",MB_OK | MB_TASKMODAL |
3195  MB_SETFOREGROUND | MB_ICONINFORMATION);
3196 }
3197 
3198 /*
3199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3200 % %
3201 % %
3202 % %
3203 % N T W i n d o w s G e n e s i s %
3204 % %
3205 % %
3206 % %
3207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3208 %
3209 % NTWindowsGenesis() initializes the MagickCore Windows environment.
3210 %
3211 % The format of the NTWindowsGenesis method is:
3212 %
3213 % void NTWindowsGenesis(void)
3214 %
3215 */
3216 MagickPrivate void NTWindowsGenesis(void)
3217 {
3218  char
3219  *mode;
3220 
3221  mode=GetEnvironmentValue("MAGICK_ERRORMODE");
3222  if (mode != (char *) NULL)
3223  {
3224  (void) SetErrorMode(StringToInteger(mode));
3225  mode=DestroyString(mode);
3226  }
3227 #if defined(_DEBUG) && !defined(__MINGW32__)
3228  if (IsEventLogging() != MagickFalse)
3229  {
3230  int
3231  debug;
3232 
3233  debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
3234  //debug |= _CRTDBG_CHECK_ALWAYS_DF;
3235  debug |= _CRTDBG_DELAY_FREE_MEM_DF;
3236  debug |= _CRTDBG_LEAK_CHECK_DF;
3237  (void) _CrtSetDbgFlag(debug);
3238 
3239  //_ASSERTE(_CrtCheckMemory());
3240 
3241  //_CrtSetBreakAlloc(42);
3242  }
3243 #endif
3244 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
3245  {
3246  unsigned char
3247  *path;
3248 
3249  path=NTRegistryKeyLookup("LibPath");
3250  if (path != (unsigned char *) NULL)
3251  {
3252  wchar_t
3253  *lib_path;
3254 
3255  lib_path=NTCreateWidePath((const char *) path);
3256  if (lib_path != (wchar_t *) NULL)
3257  {
3258  SetDllDirectoryW(lib_path);
3259  lib_path=(wchar_t *) RelinquishMagickMemory(lib_path);
3260  }
3261  path=(unsigned char *) RelinquishMagickMemory(path);
3262  }
3263  }
3264 #endif
3265 }
3266 
3267 /*
3268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3269 % %
3270 % %
3271 % %
3272 % N T W i n d o w s T e r m i n u s %
3273 % %
3274 % %
3275 % %
3276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3277 %
3278 % NTWindowsTerminus() terminates the MagickCore Windows environment.
3279 %
3280 % The format of the NTWindowsTerminus method is:
3281 %
3282 % void NTWindowsTerminus(void)
3283 %
3284 */
3285 MagickPrivate void NTWindowsTerminus(void)
3286 {
3287  NTGhostscriptUnLoadDLL();
3288  if (winsock_semaphore == (SemaphoreInfo *) NULL)
3289  ActivateSemaphoreInfo(&winsock_semaphore);
3290  LockSemaphoreInfo(winsock_semaphore);
3291  if (wsaData != (WSADATA *) NULL)
3292  {
3293  WSACleanup();
3294  wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData);
3295  }
3296  UnlockSemaphoreInfo(winsock_semaphore);
3297  DestroySemaphoreInfo(&winsock_semaphore);
3298 }
3299 #endif
Definition: mac.h:53
Definition: mac.h:41