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