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