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