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