MagickCore  6.9.13-24
Convert, Edit, Or Compose Bitmap Images
nt-base.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % N N TTTTT %
7 % NN N T %
8 % N N N T %
9 % N NN T %
10 % N N T %
11 % %
12 % %
13 % Windows NT Utility Methods for MagickCore %
14 % %
15 % Software Design %
16 % Cristy %
17 % December 1996 %
18 % %
19 % %
20 % Copyright 1999 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/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 M e s s a g e %
875 % %
876 % %
877 % %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879 %
880 % NTGetLastErrorMessage() returns the last error that occurred.
881 %
882 % The format of the NTGetLastErrorMessage method is:
883 %
884 % char *NTGetLastErrorMessage(DWORD last_error)
885 %
886 % A description of each parameter follows:
887 %
888 % o last_error: The value of GetLastError.
889 %
890 */
891 static char *NTGetLastErrorMessage(DWORD last_error)
892 {
893  char
894  *reason;
895 
896  int
897  status;
898 
899  LPVOID
900  buffer = (LPVOID) NULL;
901 
902  status=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
903  FORMAT_MESSAGE_FROM_SYSTEM,NULL,last_error,
904  MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR) &buffer,0,NULL);
905  if (!status)
906  reason=AcquireString("An unknown error occurred");
907  else
908  {
909  reason=AcquireString((const char *) buffer);
910  LocalFree(buffer);
911  }
912  return(reason);
913 }
914 
915 /*
916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917 % %
918 % %
919 % %
920 % N T G e t L i b r a r y E r r o r %
921 % %
922 % %
923 % %
924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
925 %
926 % Lt_dlerror() returns a pointer to a string describing the last error
927 % associated with a lt_dl method. Note that this function is not thread
928 % safe so it should only be used under the protection of a lock.
929 %
930 % The format of the NTGetLibraryError method is:
931 %
932 % const char *NTGetLibraryError(void)
933 %
934 */
935 MagickPrivate const char *NTGetLibraryError(void)
936 {
937  static char
938  last_error[MaxTextExtent];
939 
940  char
941  *error;
942 
943  *last_error='\0';
944  error=NTGetLastErrorMessage(GetLastError());
945  if (error)
946  (void) CopyMagickString(last_error,error,MaxTextExtent);
947  error=DestroyString(error);
948  return(last_error);
949 }
950 
951 /*
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 % %
954 % %
955 % %
956 % N T G e t L i b r a r y S y m b o l %
957 % %
958 % %
959 % %
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961 %
962 % NTGetLibrarySymbol() retrieve the procedure address of the method
963 % specified by the passed character string.
964 %
965 % The format of the NTGetLibrarySymbol method is:
966 %
967 % void *NTGetLibrarySymbol(void *handle,const char *name)
968 %
969 % A description of each parameter follows:
970 %
971 % o handle: Specifies a handle to the previously loaded dynamic module.
972 %
973 % o name: Specifies the procedure entry point to be returned.
974 %
975 */
976 void *NTGetLibrarySymbol(void *handle,const char *name)
977 {
978  FARPROC
979  proc_address;
980 
981  proc_address=GetProcAddress((HMODULE) handle,(LPCSTR) name);
982  if (proc_address == (FARPROC) NULL)
983  return((void *) NULL);
984  return((void *) proc_address);
985 }
986 
987 /*
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989 % %
990 % %
991 % %
992 % N T G e t M o d u l e P a t h %
993 % %
994 % %
995 % %
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 %
998 % NTGetModulePath() returns the path of the specified module.
999 %
1000 % The format of the GetModulePath method is:
1001 %
1002 % MagickBooleanType NTGetModulePath(const char *module,char *path)
1003 %
1004 % A description of each parameter follows:
1005 %
1006 % modith: the module name.
1007 %
1008 % path: the module path is returned here.
1009 %
1010 */
1011 MagickPrivate MagickBooleanType NTGetModulePath(const char *module,char *path)
1012 {
1013  char
1014  module_path[MaxTextExtent];
1015 
1016  HMODULE
1017  handle;
1018 
1019  ssize_t
1020  length;
1021 
1022  *path='\0';
1023  handle=GetModuleHandle(module);
1024  if (handle == (HMODULE) NULL)
1025  return(MagickFalse);
1026  length=GetModuleFileName(handle,module_path,MaxTextExtent);
1027  if (length != 0)
1028  GetPathComponent(module_path,HeadPath,path);
1029  return(MagickTrue);
1030 }
1031 
1032 /*
1033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 % %
1035 % %
1036 % %
1037 % N T G h o s t s c r i p t D L L V e c t o r s %
1038 % %
1039 % %
1040 % %
1041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1042 %
1043 % NTGhostscriptDLLVectors() returns a GhostInfo structure that includes
1044 % function vectors to invoke Ghostscript DLL functions. A null pointer is
1045 % returned if there is an error when loading the DLL or retrieving the
1046 % function vectors.
1047 %
1048 % The format of the NTGhostscriptDLLVectors method is:
1049 %
1050 % const GhostInfo *NTGhostscriptDLLVectors(void)
1051 %
1052 */
1053 static int NTLocateGhostscript(DWORD flags,int *root_index,
1054  const char **product_family,int *major_version,int *minor_version,
1055  int *patch_version)
1056 {
1057  int
1058  i;
1059 
1060  MagickBooleanType
1061  status;
1062 
1063  static const char
1064  *products[2] =
1065  {
1066  "Artifex Ghostscript",
1067  "GPL Ghostscript"
1068  };
1069 
1070  /*
1071  Find the most recent version of Ghostscript.
1072  */
1073  status=MagickFalse;
1074  *root_index=0;
1075  *product_family=NULL;
1076  *major_version=5;
1077  *minor_version=49; /* min version of Ghostscript is 5.50 */
1078  for (i=0; i < (ssize_t) (sizeof(products)/sizeof(products[0])); i++)
1079  {
1080  char
1081  key[MagickPathExtent];
1082 
1083  HKEY
1084  hkey;
1085 
1086  int
1087  j;
1088 
1089  REGSAM
1090  mode;
1091 
1092  (void) FormatLocaleString(key,MagickPathExtent,"SOFTWARE\\%s",products[i]);
1093  for (j=0; j < (ssize_t) (sizeof(registry_roots)/sizeof(registry_roots[0]));
1094  j++)
1095  {
1096  mode=KEY_READ | flags;
1097  if (RegOpenKeyExA(registry_roots[j].hkey,key,0,mode,&hkey) ==
1098  ERROR_SUCCESS)
1099  {
1100  DWORD
1101  extent;
1102 
1103  int
1104  k;
1105 
1106  /*
1107  Now enumerate the keys.
1108  */
1109  extent=sizeof(key)/sizeof(char);
1110  for (k=0; RegEnumKeyA(hkey,k,key,extent) == ERROR_SUCCESS; k++)
1111  {
1112  int
1113  major,
1114  minor,
1115  patch;
1116 
1117  major=0;
1118  minor=0;
1119  patch=0;
1120  if (sscanf(key,"%d.%d.%d",&major,&minor,&patch) != 3)
1121  if (sscanf(key,"%d.%d",&major,&minor) != 2)
1122  continue;
1123  if ((major > *major_version) ||
1124  ((major == *major_version) && (minor > *minor_version)) ||
1125  ((minor == *minor_version) && (patch > *patch_version)))
1126  {
1127  *root_index=j;
1128  *product_family=products[i];
1129  *major_version=major;
1130  *minor_version=minor;
1131  *patch_version=patch;
1132  status=MagickTrue;
1133  }
1134  }
1135  (void) RegCloseKey(hkey);
1136  }
1137  }
1138  }
1139  if (status == MagickFalse)
1140  {
1141  *major_version=0;
1142  *minor_version=0;
1143  *patch_version=0;
1144  }
1145  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"Ghostscript (%s) "
1146  "version %d.%d.%d",*product_family,*major_version,*minor_version,*patch_version);
1147  return(status);
1148 }
1149 
1150 static MagickBooleanType NTGhostscriptGetString(const char *name,
1151  BOOL *is_64_bit,char *value,const size_t length)
1152 {
1153  char
1154  buffer[MagickPathExtent],
1155  *directory;
1156 
1157  static const char
1158  *product_family = (const char *) NULL;
1159 
1160  static BOOL
1161  is_64_bit_version = FALSE;
1162 
1163  static int
1164  flags = 0,
1165  major_version = 0,
1166  minor_version = 0,
1167  patch_version = 0,
1168  root_index = 0;
1169 
1170  unsigned char
1171  *registry_value;
1172 
1173  /*
1174  Get a string from the installed Ghostscript.
1175  */
1176  *value='\0';
1177  directory=(char *) NULL;
1178  if (LocaleCompare(name,"GS_DLL") == 0)
1179  {
1180  directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_PATH");
1181  if (directory != (char *) NULL)
1182  {
1183  (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll64.dll",
1184  directory,DirectorySeparator);
1185  if (IsPathAccessible(buffer) != MagickFalse)
1186  {
1187  directory=DestroyString(directory);
1188  (void) CopyMagickString(value,buffer,length);
1189  if (is_64_bit != NULL)
1190  *is_64_bit=TRUE;
1191  return(MagickTrue);
1192  }
1193  (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll32.dll",
1194  directory,DirectorySeparator);
1195  if (IsPathAccessible(buffer) != MagickFalse)
1196  {
1197  directory=DestroyString(directory);
1198  (void) CopyMagickString(value,buffer,length);
1199  if (is_64_bit != NULL)
1200  *is_64_bit=FALSE;
1201  return(MagickTrue);
1202  }
1203  return(MagickFalse);
1204  }
1205  }
1206  if (product_family == (const char *) NULL)
1207  {
1208  flags=0;
1209 #if defined(KEY_WOW64_32KEY)
1210 #if defined(_WIN64)
1211  flags=KEY_WOW64_64KEY;
1212 #else
1213  flags=KEY_WOW64_32KEY;
1214 #endif
1215  (void) NTLocateGhostscript(flags,&root_index,&product_family,
1216  &major_version,&minor_version,&patch_version);
1217  if (product_family == (const char *) NULL)
1218 #if defined(_WIN64)
1219  flags=KEY_WOW64_32KEY;
1220  else
1221  is_64_bit_version=TRUE;
1222 #else
1223  flags=KEY_WOW64_64KEY;
1224 #endif
1225 #endif
1226  }
1227  if (product_family == (const char *) NULL)
1228  {
1229  (void) NTLocateGhostscript(flags,&root_index,&product_family,
1230  &major_version,&minor_version,&patch_version);
1231 #if !defined(_WIN64)
1232  is_64_bit_version=TRUE;
1233 #endif
1234  }
1235  if (product_family == (const char *) NULL)
1236  return(MagickFalse);
1237  if (is_64_bit != NULL)
1238  *is_64_bit=is_64_bit_version;
1239  (void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%.2d.%d",
1240  product_family,major_version,minor_version,patch_version);
1241  registry_value=NTGetRegistryValue(registry_roots[root_index].hkey,buffer,
1242  flags,name);
1243  if (registry_value == (unsigned char *) NULL)
1244  {
1245  (void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%02d",
1246  product_family,major_version,minor_version);
1247  registry_value=NTGetRegistryValue(registry_roots[root_index].hkey,buffer,
1248  flags,name);
1249  }
1250  if (registry_value == (unsigned char *) NULL)
1251  return(MagickFalse);
1252  (void) CopyMagickString(value,(const char *) registry_value,length);
1253  registry_value=(unsigned char *) RelinquishMagickMemory(registry_value);
1254  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1255  "registry: \"%s\\%s\\%s\"=\"%s\"",registry_roots[root_index].name,
1256  buffer,name,value);
1257  return(MagickTrue);
1258 }
1259 
1260 static MagickBooleanType NTGhostscriptDLL(char *path,int length)
1261 {
1262  static char
1263  dll[MagickPathExtent] = { "" };
1264 
1265  static BOOL
1266  is_64_bit;
1267 
1268  *path='\0';
1269  if ((*dll == '\0') &&
1270  (NTGhostscriptGetString("GS_DLL",&is_64_bit,dll,sizeof(dll)) != MagickTrue))
1271  return(MagickFalse);
1272 #if defined(_WIN64)
1273  if (!is_64_bit)
1274  return(MagickFalse);
1275 #else
1276  if (is_64_bit)
1277  return(MagickFalse);
1278 #endif
1279  (void) CopyMagickString(path,dll,length);
1280  return(MagickTrue);
1281 }
1282 
1283 static inline MagickBooleanType NTGhostscriptHasValidHandle()
1284 {
1285  if ((nt_ghost_info.delete_instance == NULL) || (ghost_info.exit == NULL) ||
1286  (nt_ghost_info.new_instance == NULL) || (ghost_info.set_stdio == NULL) ||
1287  (ghost_info.init_with_args == NULL) || (ghost_info.revision == NULL))
1288  return(MagickFalse);
1289  return(MagickTrue);
1290 }
1291 
1292 MagickPrivate const GhostInfo *NTGhostscriptDLLVectors(void)
1293 {
1294  char
1295  path[MaxTextExtent];
1296 
1297  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1298  ActivateSemaphoreInfo(&ghost_semaphore);
1299  LockSemaphoreInfo(ghost_semaphore);
1300  if (ghost_handle != (void *) NULL)
1301  {
1302  UnlockSemaphoreInfo(ghost_semaphore);
1303  if (NTGhostscriptHasValidHandle() == MagickFalse)
1304  return((GhostInfo *) NULL);
1305  return(&ghost_info);
1306  }
1307  if (NTGhostscriptDLL(path,sizeof(path)) == MagickFalse)
1308  {
1309  UnlockSemaphoreInfo(ghost_semaphore);
1310  return(FALSE);
1311  }
1312  ghost_handle=lt_dlopen(path);
1313  if (ghost_handle == (void *) NULL)
1314  {
1315  UnlockSemaphoreInfo(ghost_semaphore);
1316  return(FALSE);
1317  }
1318  (void) memset((void *) &nt_ghost_info,0,sizeof(NTGhostInfo));
1319  nt_ghost_info.delete_instance=(void (MagickDLLCall *)(gs_main_instance *)) (
1320  lt_dlsym(ghost_handle,"gsapi_delete_instance"));
1321  nt_ghost_info.new_instance=(int (MagickDLLCall *)(gs_main_instance **,
1322  void *)) (lt_dlsym(ghost_handle,"gsapi_new_instance"));
1323  nt_ghost_info.has_instance=MagickFalse;
1324  (void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
1325  ghost_info.delete_instance=NTGhostscriptDeleteInstance;
1326  ghost_info.exit=(int (MagickDLLCall *)(gs_main_instance*))
1327  lt_dlsym(ghost_handle,"gsapi_exit");
1328  ghost_info.init_with_args=(int (MagickDLLCall *)(gs_main_instance *,int,
1329  char **)) (lt_dlsym(ghost_handle,"gsapi_init_with_args"));
1330  ghost_info.new_instance=NTGhostscriptNewInstance;
1331  ghost_info.run_string=(int (MagickDLLCall *)(gs_main_instance *,const char *,
1332  int,int *)) (lt_dlsym(ghost_handle,"gsapi_run_string"));
1333  ghost_info.set_stdio=(int (MagickDLLCall *)(gs_main_instance *,int(
1334  MagickDLLCall *)(void *,char *,int),int(MagickDLLCall *)(void *,
1335  const char *,int),int(MagickDLLCall *)(void *,const char *,int)))
1336  (lt_dlsym(ghost_handle,"gsapi_set_stdio"));
1337  ghost_info.revision=(int (MagickDLLCall *)(gsapi_revision_t *,int)) (
1338  lt_dlsym(ghost_handle,"gsapi_revision"));
1339  UnlockSemaphoreInfo(ghost_semaphore);
1340  if (NTGhostscriptHasValidHandle() == MagickFalse)
1341  return((GhostInfo *) NULL);
1342  return(&ghost_info);
1343 }
1344 
1345 /*
1346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1347 % %
1348 % %
1349 % %
1350 % N T G h o s t s c r i p t E X E %
1351 % %
1352 % %
1353 % %
1354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1355 %
1356 % NTGhostscriptEXE() obtains the path to the latest Ghostscript executable.
1357 % The method returns FALSE if a full path value is not obtained and returns
1358 % a default path of gswin32c.exe.
1359 %
1360 % The format of the NTGhostscriptEXE method is:
1361 %
1362 % int NTGhostscriptEXE(char *path,int length)
1363 %
1364 % A description of each parameter follows:
1365 %
1366 % o path: return the Ghostscript executable path here.
1367 %
1368 % o length: length of buffer.
1369 %
1370 */
1371 MagickPrivate int NTGhostscriptEXE(char *path,int length)
1372 {
1373  char
1374  *p;
1375 
1376  static char
1377  program[MaxTextExtent] = { "" };
1378 
1379  static BOOL
1380  is_64_bit_version = FALSE;
1381 
1382  if (*program == '\0')
1383  {
1384  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1385  ActivateSemaphoreInfo(&ghost_semaphore);
1386  LockSemaphoreInfo(ghost_semaphore);
1387  if (*program == '\0')
1388  {
1389  if (NTGhostscriptGetString("GS_DLL",&is_64_bit_version,program,
1390  sizeof(program)) == MagickFalse)
1391  {
1392  UnlockSemaphoreInfo(ghost_semaphore);
1393 #if defined(_WIN64)
1394  (void) CopyMagickString(program,"gswin64c.exe",sizeof(program));
1395 #else
1396  (void) CopyMagickString(program,"gswin32c.exe",sizeof(program));
1397 #endif
1398  (void) CopyMagickString(path,program,length);
1399  return(FALSE);
1400  }
1401  p=strrchr(program,'\\');
1402  if (p != (char *) NULL)
1403  {
1404  p++;
1405  *p='\0';
1406  (void) ConcatenateMagickString(program,is_64_bit_version ?
1407  "gswin64c.exe" : "gswin32c.exe",sizeof(program));
1408  }
1409  }
1410  UnlockSemaphoreInfo(ghost_semaphore);
1411  }
1412  (void) CopyMagickString(path,program,length);
1413  return(TRUE);
1414 }
1415 
1416 /*
1417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1418 % %
1419 % %
1420 % %
1421 % N T G h o s t s c r i p t F o n t s %
1422 % %
1423 % %
1424 % %
1425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1426 %
1427 % NTGhostscriptFonts() obtains the path to the Ghostscript fonts. The method
1428 % returns FALSE if it cannot determine the font path.
1429 %
1430 % The format of the NTGhostscriptFonts method is:
1431 %
1432 % int NTGhostscriptFonts(char *path,int length)
1433 %
1434 % A description of each parameter follows:
1435 %
1436 % o path: return the font path here.
1437 %
1438 % o length: length of the path buffer.
1439 %
1440 */
1441 MagickPrivate int NTGhostscriptFonts(char *path,int length)
1442 {
1443  char
1444  buffer[MaxTextExtent],
1445  *directory,
1446  filename[MaxTextExtent];
1447 
1448  char
1449  *p,
1450  *q;
1451 
1452  *path='\0';
1453  directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_FONT_PATH");
1454  if (directory != (char *) NULL)
1455  {
1456  (void) CopyMagickString(buffer,directory,MaxTextExtent);
1457  directory=DestroyString(directory);
1458  }
1459  else
1460  {
1461  if (NTGhostscriptGetString("GS_LIB",NULL,buffer,MaxTextExtent) == MagickFalse)
1462  return(FALSE);
1463  }
1464  for (p=buffer-1; p != (char *) NULL; p=strchr(p+1,DirectoryListSeparator))
1465  {
1466  (void) CopyMagickString(path,p+1,length+1);
1467  q=strchr(path,DirectoryListSeparator);
1468  if (q != (char *) NULL)
1469  *q='\0';
1470  (void) FormatLocaleString(filename,MaxTextExtent,"%s%sfonts.dir",path,
1471  DirectorySeparator);
1472  if (IsPathAccessible(filename) != MagickFalse)
1473  return(TRUE);
1474  (void) FormatLocaleString(filename,MaxTextExtent,"%s%sn019003l.pfb",path,
1475  DirectorySeparator);
1476  if (IsPathAccessible(filename) != MagickFalse)
1477  return(TRUE);
1478  }
1479  *path='\0';
1480  return(FALSE);
1481 }
1482 
1483 /*
1484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1485 % %
1486 % %
1487 % %
1488 % N T G h o s t s c r i p t U n L o a d D L L %
1489 % %
1490 % %
1491 % %
1492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1493 %
1494 % NTGhostscriptUnLoadDLL() unloads the Ghostscript DLL and returns TRUE if
1495 % it succeeds.
1496 %
1497 % The format of the NTGhostscriptUnLoadDLL method is:
1498 %
1499 % int NTGhostscriptUnLoadDLL(void)
1500 %
1501 */
1502 MagickPrivate int NTGhostscriptUnLoadDLL(void)
1503 {
1504  int
1505  status;
1506 
1507  if (ghost_semaphore == (SemaphoreInfo *) NULL)
1508  ActivateSemaphoreInfo(&ghost_semaphore);
1509  LockSemaphoreInfo(ghost_semaphore);
1510  status=FALSE;
1511  if (ghost_handle != (void *) NULL)
1512  {
1513  status=lt_dlclose(ghost_handle);
1514  ghost_handle=(void *) NULL;
1515  (void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
1516  }
1517  UnlockSemaphoreInfo(ghost_semaphore);
1518  DestroySemaphoreInfo(&ghost_semaphore);
1519  return(status);
1520 }
1521 
1522 /*
1523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1524 % %
1525 % %
1526 % %
1527 % N T I n i t i a l i z e L i b r a r y %
1528 % %
1529 % %
1530 % %
1531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1532 %
1533 % NTInitializeLibrary() initializes the dynamic module loading subsystem.
1534 %
1535 % The format of the NTInitializeLibrary method is:
1536 %
1537 % int NTInitializeLibrary(void)
1538 %
1539 */
1540 MagickPrivate int NTInitializeLibrary(void)
1541 {
1542  return(0);
1543 }
1544 
1545 /*
1546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1547 % %
1548 % %
1549 % %
1550 % N T I n i t i a l i z e W i n s o c k %
1551 % %
1552 % %
1553 % %
1554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1555 %
1556 % NTInitializeWinsock() initializes Winsock.
1557 %
1558 % The format of the NTInitializeWinsock method is:
1559 %
1560 % void NTInitializeWinsock(void)
1561 %
1562 */
1563 MagickPrivate void NTInitializeWinsock(MagickBooleanType use_lock)
1564 {
1565  if (use_lock)
1566  {
1567  if (winsock_semaphore == (SemaphoreInfo *) NULL)
1568  ActivateSemaphoreInfo(&winsock_semaphore);
1569  LockSemaphoreInfo(winsock_semaphore);
1570  }
1571  if (wsaData == (WSADATA *) NULL)
1572  {
1573  wsaData=(WSADATA *) AcquireMagickMemory(sizeof(WSADATA));
1574  if (WSAStartup(MAKEWORD(2,2),wsaData) != 0)
1575  ThrowFatalException(CacheFatalError,"WSAStartup failed");
1576  }
1577  if (use_lock)
1578  UnlockSemaphoreInfo(winsock_semaphore);
1579 }
1580 
1581 /*
1582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1583 % %
1584 % %
1585 % %
1586 % N T L o n g P a t h s E n a b l e d %
1587 % %
1588 % %
1589 % %
1590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1591 %
1592 % NTLongPathsEnabled() returns a boolean indicating whether long paths are
1593 $ enabled.
1594 %
1595 % The format of the NTLongPathsEnabled method is:
1596 %
1597 % MagickBooleanType NTLongPathsEnabled()
1598 %
1599 */
1600 MagickExport MagickBooleanType NTLongPathsEnabled()
1601 {
1602  if (long_paths_enabled == 2)
1603  {
1604  DWORD
1605  size,
1606  type,
1607  value;
1608 
1609  HKEY
1610  registry_key;
1611 
1612  LONG
1613  status;
1614 
1615  registry_key=(HKEY) INVALID_HANDLE_VALUE;
1616  status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1617  "SYSTEM\\CurrentControlSet\\Control\\FileSystem",0,KEY_READ,
1618  &registry_key);
1619  if (status != ERROR_SUCCESS)
1620  {
1621  long_paths_enabled=0;
1622  RegCloseKey(registry_key);
1623  return(MagickFalse);
1624  }
1625  value=0;
1626  status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,NULL,
1627  NULL);
1628  if ((status != ERROR_SUCCESS) || (type != REG_DWORD))
1629  {
1630  long_paths_enabled=0;
1631  RegCloseKey(registry_key);
1632  return(MagickFalse);
1633  }
1634  status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,
1635  (LPBYTE) &value,&size);
1636  RegCloseKey(registry_key);
1637  if (status != ERROR_SUCCESS)
1638  {
1639  long_paths_enabled=0;
1640  return(MagickFalse);
1641  }
1642  long_paths_enabled=(size_t) value;
1643  }
1644  return(long_paths_enabled == 1 ? MagickTrue : MagickFalse);
1645 }
1646 
1647 /*
1648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1649 % %
1650 % %
1651 % %
1652 + N T M a p M e m o r y %
1653 % %
1654 % %
1655 % %
1656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1657 %
1658 % NTMapMemory() emulates the Unix method of the same name.
1659 %
1660 % The format of the NTMapMemory method is:
1661 %
1662 % void *NTMapMemory(char *address,size_t length,int protection,int access,
1663 % int file,MagickOffsetType offset)
1664 %
1665 */
1666 MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1667  int flags,int file,MagickOffsetType offset)
1668 {
1669  DWORD
1670  access_mode,
1671  high_length,
1672  high_offset,
1673  low_length,
1674  low_offset,
1675  protection_mode;
1676 
1677  HANDLE
1678  file_handle,
1679  map_handle;
1680 
1681  void
1682  *map;
1683 
1684  (void) address;
1685  access_mode=0;
1686  file_handle=INVALID_HANDLE_VALUE;
1687  low_length=(DWORD) (length & 0xFFFFFFFFUL);
1688  high_length=(DWORD) ((((MagickOffsetType) length) >> 32) & 0xFFFFFFFFUL);
1689  map_handle=INVALID_HANDLE_VALUE;
1690  map=(void *) NULL;
1691  low_offset=(DWORD) (offset & 0xFFFFFFFFUL);
1692  high_offset=(DWORD) ((offset >> 32) & 0xFFFFFFFFUL);
1693  protection_mode=0;
1694  if (protection & PROT_WRITE)
1695  {
1696  access_mode=FILE_MAP_WRITE;
1697  if (!(flags & MAP_PRIVATE))
1698  protection_mode=PAGE_READWRITE;
1699  else
1700  {
1701  access_mode=FILE_MAP_COPY;
1702  protection_mode=PAGE_WRITECOPY;
1703  }
1704  }
1705  else
1706  if (protection & PROT_READ)
1707  {
1708  access_mode=FILE_MAP_READ;
1709  protection_mode=PAGE_READONLY;
1710  }
1711  if ((file == -1) && (flags & MAP_ANONYMOUS))
1712  file_handle=INVALID_HANDLE_VALUE;
1713  else
1714  file_handle=(HANDLE) _get_osfhandle(file);
1715  map_handle=CreateFileMapping(file_handle,0,protection_mode,high_length,
1716  low_length,0);
1717  if (map_handle)
1718  {
1719  map=(void *) MapViewOfFile(map_handle,access_mode,high_offset,low_offset,
1720  length);
1721  CloseHandle(map_handle);
1722  }
1723  if (map == (void *) NULL)
1724  return((void *) ((char *) MAP_FAILED));
1725  return((void *) ((char *) map));
1726 }
1727 
1728 /*
1729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1730 % %
1731 % %
1732 % %
1733 % N T O p e n D i r e c t o r y %
1734 % %
1735 % %
1736 % %
1737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1738 %
1739 % NTOpenDirectory() opens the directory named by filename and associates a
1740 % directory stream with it.
1741 %
1742 % The format of the NTOpenDirectory method is:
1743 %
1744 % DIR *NTOpenDirectory(const char *path)
1745 %
1746 % A description of each parameter follows:
1747 %
1748 % o entry: Specifies a pointer to a DIR structure.
1749 %
1750 */
1751 MagickPrivate DIR *NTOpenDirectory(const char *path)
1752 {
1753  DIR
1754  *entry;
1755 
1756  size_t
1757  length;
1758 
1759  wchar_t
1760  file_specification[MaxTextExtent];
1761 
1762  assert(path != (const char *) NULL);
1763  length=MultiByteToWideChar(CP_UTF8,0,path,-1,file_specification,
1764  MaxTextExtent);
1765  if (length == 0)
1766  return((DIR *) NULL);
1767  if(wcsncat(file_specification,L"\\*.*",MaxTextExtent-wcslen(
1768  file_specification)-1) == (wchar_t*) NULL)
1769  return((DIR *) NULL);
1770  entry=(DIR *) AcquireCriticalMemory(sizeof(DIR));
1771  entry->firsttime=TRUE;
1772  entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
1773  if (entry->hSearch == INVALID_HANDLE_VALUE)
1774  {
1775  entry=(DIR *) RelinquishMagickMemory(entry);
1776  return((DIR *) NULL);
1777  }
1778  return(entry);
1779 }
1780 
1781 /*
1782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1783 % %
1784 % %
1785 % %
1786 % N T O p e n L i b r a r y %
1787 % %
1788 % %
1789 % %
1790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1791 %
1792 % NTOpenLibrary() loads a dynamic module into memory and returns a handle that
1793 % can be used to access the various procedures in the module.
1794 %
1795 % The format of the NTOpenLibrary method is:
1796 %
1797 % void *NTOpenLibrary(const char *filename)
1798 %
1799 % A description of each parameter follows:
1800 %
1801 % o path: Specifies a pointer to string representing dynamic module that
1802 % is to be loaded.
1803 %
1804 */
1805 
1806 static inline const char *GetSearchPath(void)
1807 {
1808 #if defined(MAGICKCORE_LTDL_DELEGATE)
1809  return(lt_dlgetsearchpath());
1810 #else
1811  return(lt_slsearchpath);
1812 #endif
1813 }
1814 
1815 static UINT ChangeErrorMode(void)
1816 {
1817  typedef UINT
1818  (CALLBACK *GETERRORMODE)(void);
1819 
1820  GETERRORMODE
1821  getErrorMode;
1822 
1823  HMODULE
1824  handle;
1825 
1826  UINT
1827  mode;
1828 
1829  mode=SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1830 
1831  handle=GetModuleHandle("kernel32.dll");
1832  if (handle == (HMODULE) NULL)
1833  return SetErrorMode(mode);
1834 
1835  getErrorMode=(GETERRORMODE) NTGetLibrarySymbol(handle,"GetErrorMode");
1836  if (getErrorMode != (GETERRORMODE) NULL)
1837  mode=getErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1838 
1839  return SetErrorMode(mode);
1840 }
1841 
1842 static inline void *NTLoadLibrary(const char *filename)
1843 {
1844  int
1845  length;
1846 
1847  wchar_t
1848  path[MaxTextExtent];
1849 
1850  length=MultiByteToWideChar(CP_UTF8,0,filename,-1,path,MaxTextExtent);
1851  if (length == 0)
1852  return((void *) NULL);
1853  return (void *) LoadLibraryExW(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
1854 }
1855 
1856 MagickPrivate void *NTOpenLibrary(const char *filename)
1857 {
1858  char
1859  path[MaxTextExtent];
1860 
1861  const char
1862  *p,
1863  *q;
1864 
1865  UINT
1866  mode;
1867 
1868  void
1869  *handle;
1870 
1871  mode=ChangeErrorMode();
1872  handle=NTLoadLibrary(filename);
1873  if (handle == (void *) NULL)
1874  {
1875  p=GetSearchPath();
1876  while (p != (const char*) NULL)
1877  {
1878  q=strchr(p,DirectoryListSeparator);
1879  if (q != (const char*) NULL)
1880  (void) CopyMagickString(path,p,q-p+1);
1881  else
1882  (void) CopyMagickString(path,p,MaxTextExtent);
1883  (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
1884  (void) ConcatenateMagickString(path,filename,MaxTextExtent);
1885  handle=NTLoadLibrary(path);
1886  if (handle != (void *) NULL || q == (const char*) NULL)
1887  break;
1888  p=q+1;
1889  }
1890  }
1891  SetErrorMode(mode);
1892  return(handle);
1893 }
1894 
1895 /*
1896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1897 % %
1898 % %
1899 % %
1900 % N T R e a d D i r e c t o r y %
1901 % %
1902 % %
1903 % %
1904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1905 %
1906 % NTReadDirectory() returns a pointer to a structure representing the
1907 % directory entry at the current position in the directory stream to which
1908 % entry refers.
1909 %
1910 % The format of the NTReadDirectory
1911 %
1912 % NTReadDirectory(entry)
1913 %
1914 % A description of each parameter follows:
1915 %
1916 % o entry: Specifies a pointer to a DIR structure.
1917 %
1918 */
1919 MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
1920 {
1921  int
1922  status;
1923 
1924  size_t
1925  length;
1926 
1927  if (entry == (DIR *) NULL)
1928  return((struct dirent *) NULL);
1929  if (!entry->firsttime)
1930  {
1931  status=FindNextFileW(entry->hSearch,&entry->Win32FindData);
1932  if (status == 0)
1933  return((struct dirent *) NULL);
1934  }
1935  length=WideCharToMultiByte(CP_UTF8,0,entry->Win32FindData.cFileName,-1,
1936  entry->file_info.d_name,sizeof(entry->file_info.d_name),NULL,NULL);
1937  if (length == 0)
1938  return((struct dirent *) NULL);
1939  entry->firsttime=FALSE;
1940  entry->file_info.d_namlen=(int) strlen(entry->file_info.d_name);
1941  return(&entry->file_info);
1942 }
1943 
1944 /*
1945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1946 % %
1947 % %
1948 % %
1949 % N T R e g i s t r y K e y L o o k u p %
1950 % %
1951 % %
1952 % %
1953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1954 %
1955 % NTRegistryKeyLookup() returns ImageMagick installation path settings
1956 % stored in the Windows Registry. Path settings are specific to the
1957 % installed ImageMagick version so that multiple Image Magick installations
1958 % may coexist.
1959 %
1960 % Values are stored in the registry under a base path similar to
1961 % "HKEY_LOCAL_MACHINE/SOFTWARE\ImageMagick\6.7.4\Q:16" or
1962 % "HKEY_CURRENT_USER/SOFTWARE\ImageMagick\6.7.4\Q:16". The provided subkey
1963 % is appended to this base path to form the full key.
1964 %
1965 % The format of the NTRegistryKeyLookup method is:
1966 %
1967 % unsigned char *NTRegistryKeyLookup(const char *subkey)
1968 %
1969 % A description of each parameter follows:
1970 %
1971 % o subkey: Specifies a string that identifies the registry object.
1972 % Currently supported sub-keys include: "BinPath", "ConfigurePath",
1973 % "LibPath", "CoderModulesPath", "FilterModulesPath", "SharePath".
1974 %
1975 */
1976 MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
1977 {
1978  char
1979  package_key[MaxTextExtent] = "";
1980 
1981  unsigned char
1982  *value;
1983 
1984  (void) FormatLocaleString(package_key,MagickPathExtent,
1985  "SOFTWARE\\%s\\%s\\Q:%d",MagickPackageName,MagickLibVersionText,
1986  MAGICKCORE_QUANTUM_DEPTH);
1987  value=NTGetRegistryValue(HKEY_LOCAL_MACHINE,package_key,0,subkey);
1988  if (value == (unsigned char *) NULL)
1989  value=NTGetRegistryValue(HKEY_CURRENT_USER,package_key,0,subkey);
1990  return(value);
1991 }
1992 
1993 /*
1994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1995 % %
1996 % %
1997 % %
1998 % N T R e p o r t E v e n t %
1999 % %
2000 % %
2001 % %
2002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2003 %
2004 % NTReportEvent() reports an event.
2005 %
2006 % The format of the NTReportEvent method is:
2007 %
2008 % MagickBooleanType NTReportEvent(const char *event,
2009 % const MagickBooleanType error)
2010 %
2011 % A description of each parameter follows:
2012 %
2013 % o event: the event.
2014 %
2015 % o error: MagickTrue the event is an error.
2016 %
2017 */
2018 MagickPrivate MagickBooleanType NTReportEvent(const char *event,
2019  const MagickBooleanType error)
2020 {
2021  const char
2022  *events[1];
2023 
2024  HANDLE
2025  handle;
2026 
2027  WORD
2028  type;
2029 
2030  handle=RegisterEventSource(NULL,MAGICKCORE_PACKAGE_NAME);
2031  if (handle == NULL)
2032  return(MagickFalse);
2033  events[0]=event;
2034  type=error ? EVENTLOG_ERROR_TYPE : EVENTLOG_WARNING_TYPE;
2035  ReportEvent(handle,type,0,0,NULL,1,0,events,NULL);
2036  DeregisterEventSource(handle);
2037  return(MagickTrue);
2038 }
2039 
2040 /*
2041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2042 % %
2043 % %
2044 % %
2045 % N T R e s o u r c e T o B l o b %
2046 % %
2047 % %
2048 % %
2049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2050 %
2051 % NTResourceToBlob() returns a blob containing the contents of the resource
2052 % in the current executable specified by the id parameter. This currently
2053 % used to retrieve MGK files tha have been embedded into the various command
2054 % line utilities.
2055 %
2056 % The format of the NTResourceToBlob method is:
2057 %
2058 % unsigned char *NTResourceToBlob(const char *id)
2059 %
2060 % A description of each parameter follows:
2061 %
2062 % o id: Specifies a string that identifies the resource.
2063 %
2064 */
2065 MagickPrivate unsigned char *NTResourceToBlob(const char *id)
2066 {
2067 
2068 #ifndef MAGICKCORE_LIBRARY_NAME
2069  char
2070  path[MaxTextExtent];
2071 #endif
2072 
2073  DWORD
2074  length;
2075 
2076  HGLOBAL
2077  global;
2078 
2079  HMODULE
2080  handle;
2081 
2082  HRSRC
2083  resource;
2084 
2085  unsigned char
2086  *blob,
2087  *value;
2088 
2089  assert(id != (const char *) NULL);
2090  if (IsEventLogging() != MagickFalse)
2091  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
2092 #ifdef MAGICKCORE_LIBRARY_NAME
2093  handle=GetModuleHandle(MAGICKCORE_LIBRARY_NAME);
2094 #else
2095  (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
2096  DirectorySeparator,GetClientName());
2097  if (IsPathAccessible(path) != MagickFalse)
2098  handle=GetModuleHandle(path);
2099  else
2100  handle=GetModuleHandle(0);
2101 #endif
2102  if (!handle)
2103  return((unsigned char *) NULL);
2104  resource=FindResource(handle,id,"IMAGEMAGICK");
2105  if (!resource)
2106  return((unsigned char *) NULL);
2107  global=LoadResource(handle,resource);
2108  if (!global)
2109  return((unsigned char *) NULL);
2110  length=SizeofResource(handle,resource);
2111  value=(unsigned char *) LockResource(global);
2112  if (!value)
2113  {
2114  FreeResource(global);
2115  return((unsigned char *) NULL);
2116  }
2117  blob=(unsigned char *) AcquireQuantumMemory(length+MaxTextExtent,
2118  sizeof(*blob));
2119  if (blob != (unsigned char *) NULL)
2120  {
2121  (void) memcpy(blob,value,length);
2122  blob[length]='\0';
2123  }
2124  UnlockResource(global);
2125  FreeResource(global);
2126  return(blob);
2127 }
2128 
2129 /*
2130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2131 % %
2132 % %
2133 % %
2134 % N T S e t S e a r c h P a t h %
2135 % %
2136 % %
2137 % %
2138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2139 %
2140 % NTSetSearchPath() sets the current locations that the subsystem should
2141 % look at to find dynamically loadable modules.
2142 %
2143 % The format of the NTSetSearchPath method is:
2144 %
2145 % int NTSetSearchPath(const char *path)
2146 %
2147 % A description of each parameter follows:
2148 %
2149 % o path: Specifies a pointer to string representing the search path
2150 % for DLL's that can be dynamically loaded.
2151 %
2152 */
2153 MagickPrivate int NTSetSearchPath(const char *path)
2154 {
2155 #if defined(MAGICKCORE_LTDL_DELEGATE)
2156  lt_dlsetsearchpath(path);
2157 #else
2158  if (lt_slsearchpath != (char *) NULL)
2159  lt_slsearchpath=DestroyString(lt_slsearchpath);
2160  if (path != (char *) NULL)
2161  lt_slsearchpath=AcquireString(path);
2162 #endif
2163  return(0);
2164 }
2165 
2166 /*
2167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2168 % %
2169 % %
2170 % %
2171 % N T S y s t e m C o m m a n d %
2172 % %
2173 % %
2174 % %
2175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2176 %
2177 % NTSystemCommand() executes the specified command and waits until it
2178 % terminates. The returned value is the exit status of the command.
2179 %
2180 % The format of the NTSystemCommand method is:
2181 %
2182 % int NTSystemCommand(MagickFalse,const char *command)
2183 %
2184 % A description of each parameter follows:
2185 %
2186 % o command: This string is the command to execute.
2187 %
2188 % o output: an optional buffer to store the output from stderr/stdout.
2189 %
2190 */
2191 MagickPrivate int NTSystemCommand(const char *command,char *output)
2192 {
2193 #define CleanupOutputHandles \
2194  if (read_output != (HANDLE) NULL) \
2195  { \
2196  CloseHandle(read_output); \
2197  read_output=(HANDLE) NULL; \
2198  CloseHandle(write_output); \
2199  write_output=(HANDLE) NULL; \
2200  }
2201 
2202 #define CopyLastError \
2203  last_error=GetLastError(); \
2204  if (output != (char *) NULL) \
2205  { \
2206  error=NTGetLastErrorMessage(last_error); \
2207  if (error != (char *) NULL) \
2208  { \
2209  CopyMagickString(output,error,MaxTextExtent); \
2210  error=DestroyString(error); \
2211  } \
2212  }
2213 
2214  char
2215  *error,
2216  local_command[MaxTextExtent];
2217 
2218  DWORD
2219  child_status,
2220  last_error;
2221 
2222  int
2223  status;
2224 
2225  MagickBooleanType
2226  asynchronous;
2227 
2228  HANDLE
2229  read_output,
2230  write_output;
2231 
2232  PROCESS_INFORMATION
2233  process_info;
2234 
2235  size_t
2236  output_offset;
2237 
2238  STARTUPINFO
2239  startup_info;
2240 
2241  if (command == (char *) NULL)
2242  return(-1);
2243  read_output=(HANDLE) NULL;
2244  write_output=(HANDLE) NULL;
2245  GetStartupInfo(&startup_info);
2246  startup_info.dwFlags=STARTF_USESHOWWINDOW;
2247  startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
2248  (void) CopyMagickString(local_command,command,MaxTextExtent);
2249  asynchronous=command[strlen(command)-1] == '&' ? MagickTrue : MagickFalse;
2250  if (asynchronous != MagickFalse)
2251  {
2252  local_command[strlen(command)-1]='\0';
2253  startup_info.wShowWindow=SW_SHOWDEFAULT;
2254  }
2255  else
2256  {
2257  if (command[strlen(command)-1] == '|')
2258  local_command[strlen(command)-1]='\0';
2259  else
2260  startup_info.wShowWindow=SW_HIDE;
2261  read_output=(HANDLE) NULL;
2262  if (output != (char *) NULL)
2263  {
2264  if (CreatePipe(&read_output,&write_output,NULL,0))
2265  {
2266  if (SetHandleInformation(write_output,HANDLE_FLAG_INHERIT,
2267  HANDLE_FLAG_INHERIT))
2268  {
2269  startup_info.dwFlags|=STARTF_USESTDHANDLES;
2270  startup_info.hStdOutput=write_output;
2271  startup_info.hStdError=write_output;
2272  }
2273  else
2274  CleanupOutputHandles;
2275  }
2276  else
2277  read_output=(HANDLE) NULL;
2278  }
2279  }
2280  status=CreateProcess((LPCTSTR) NULL,local_command,(LPSECURITY_ATTRIBUTES)
2281  NULL,(LPSECURITY_ATTRIBUTES) NULL,(BOOL) TRUE,(DWORD)
2282  NORMAL_PRIORITY_CLASS,(LPVOID) NULL,(LPCSTR) NULL,&startup_info,
2283  &process_info);
2284  if (status == 0)
2285  {
2286  CopyLastError;
2287  CleanupOutputHandles;
2288  return(last_error == ERROR_FILE_NOT_FOUND ? 127 : -1);
2289  }
2290  if (output != (char *) NULL)
2291  *output='\0';
2292  if (asynchronous != MagickFalse)
2293  return(status == 0);
2294  output_offset=0;
2295  status=STATUS_TIMEOUT;
2296  while (status == STATUS_TIMEOUT)
2297  {
2298  DWORD
2299  size;
2300 
2301  status=WaitForSingleObject(process_info.hProcess,1000);
2302  size=0;
2303  if (read_output != (HANDLE) NULL)
2304  if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2305  break;
2306  while (size > 0)
2307  {
2308  char
2309  buffer[MagickPathExtent];
2310 
2311  DWORD
2312  bytes_read;
2313 
2314  if (ReadFile(read_output,buffer,MagickPathExtent-1,&bytes_read,NULL))
2315  {
2316  size_t
2317  count;
2318 
2319  count=MagickMin(MagickPathExtent-output_offset,
2320  (size_t) bytes_read+1);
2321  if (count > 0)
2322  {
2323  CopyMagickString(output+output_offset,buffer,count);
2324  output_offset+=count-1;
2325  }
2326  }
2327  if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2328  break;
2329  }
2330  }
2331  if (status != WAIT_OBJECT_0)
2332  {
2333  CopyLastError;
2334  CleanupOutputHandles;
2335  return(status);
2336  }
2337  status=GetExitCodeProcess(process_info.hProcess,&child_status);
2338  if (status == 0)
2339  {
2340  CopyLastError;
2341  CleanupOutputHandles;
2342  return(-1);
2343  }
2344  CloseHandle(process_info.hProcess);
2345  CloseHandle(process_info.hThread);
2346  CleanupOutputHandles;
2347  return((int) child_status);
2348 }
2349 
2350 /*
2351 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2352 % %
2353 % %
2354 % %
2355 % N T S y s t e m C o n i f i g u r a t i o n %
2356 % %
2357 % %
2358 % %
2359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2360 %
2361 % NTSystemConfiguration() provides a way for the application to determine
2362 % values for system limits or options at runtime.
2363 %
2364 % The format of the exit method is:
2365 %
2366 % ssize_t NTSystemConfiguration(int name)
2367 %
2368 % A description of each parameter follows:
2369 %
2370 % o name: _SC_PAGE_SIZE or _SC_PHYS_PAGES.
2371 %
2372 */
2373 MagickPrivate ssize_t NTSystemConfiguration(int name)
2374 {
2375  switch (name)
2376  {
2377  case _SC_PAGE_SIZE:
2378  {
2379  SYSTEM_INFO
2380  system_info;
2381 
2382  GetSystemInfo(&system_info);
2383  return(system_info.dwPageSize);
2384  }
2385  case _SC_PHYS_PAGES:
2386  {
2387  MEMORYSTATUSEX
2388  status;
2389 
2390  SYSTEM_INFO
2391  system_info;
2392 
2393  status.dwLength=sizeof(status);
2394  if (GlobalMemoryStatusEx(&status) == 0)
2395  return(0L);
2396  GetSystemInfo(&system_info);
2397  return((ssize_t) status.ullTotalPhys/system_info.dwPageSize);
2398  }
2399  case _SC_OPEN_MAX:
2400  return(2048);
2401  default:
2402  break;
2403  }
2404  return(-1);
2405 }
2406 
2407 /*
2408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2409 % %
2410 % %
2411 % %
2412 % N T T r u n c a t e F i l e %
2413 % %
2414 % %
2415 % %
2416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2417 %
2418 % NTTruncateFile() truncates a file to a specified length.
2419 %
2420 % The format of the NTTruncateFile method is:
2421 %
2422 % int NTTruncateFile(int file,off_t length)
2423 %
2424 % A description of each parameter follows:
2425 %
2426 % o file: the file.
2427 %
2428 % o length: the file length.
2429 %
2430 */
2431 MagickPrivate int NTTruncateFile(int file,off_t length)
2432 {
2433  DWORD
2434  file_pointer;
2435 
2436  HANDLE
2437  file_handle;
2438 
2439  long
2440  high,
2441  low;
2442 
2443  file_handle=(HANDLE) _get_osfhandle(file);
2444  if (file_handle == INVALID_HANDLE_VALUE)
2445  return(-1);
2446  low=(long) (length & 0xffffffffUL);
2447  high=(long) ((((MagickOffsetType) length) >> 32) & 0xffffffffUL);
2448  file_pointer=SetFilePointer(file_handle,low,&high,FILE_BEGIN);
2449  if ((file_pointer == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
2450  return(-1);
2451  if (SetEndOfFile(file_handle) == 0)
2452  return(-1);
2453  return(0);
2454 }
2455 
2456 /*
2457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2458 % %
2459 % %
2460 % %
2461 + N T U n m a p M e m o r y %
2462 % %
2463 % %
2464 % %
2465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2466 %
2467 % NTUnmapMemory() emulates the Unix munmap method.
2468 %
2469 % The format of the NTUnmapMemory method is:
2470 %
2471 % int NTUnmapMemory(void *map,size_t length)
2472 %
2473 % A description of each parameter follows:
2474 %
2475 % o map: the address of the binary large object.
2476 %
2477 % o length: the length of the binary large object.
2478 %
2479 */
2480 MagickPrivate int NTUnmapMemory(void *map,size_t length)
2481 {
2482  (void) length;
2483  if (UnmapViewOfFile(map) == 0)
2484  return(-1);
2485  return(0);
2486 }
2487 
2488 /*
2489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2490 % %
2491 % %
2492 % %
2493 % N T U s e r T i m e %
2494 % %
2495 % %
2496 % %
2497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2498 %
2499 % NTUserTime() returns the total time the process has been scheduled (e.g.
2500 % seconds) since the last call to StartTimer().
2501 %
2502 % The format of the UserTime method is:
2503 %
2504 % double NTUserTime(void)
2505 %
2506 */
2507 MagickPrivate double NTUserTime(void)
2508 {
2509  DWORD
2510  status;
2511 
2512  FILETIME
2513  create_time,
2514  exit_time;
2515 
2516  OSVERSIONINFO
2517  OsVersionInfo;
2518 
2519  union
2520  {
2521  FILETIME
2522  filetime;
2523 
2524  __int64
2525  filetime64;
2526  } kernel_time;
2527 
2528  union
2529  {
2530  FILETIME
2531  filetime;
2532 
2533  __int64
2534  filetime64;
2535  } user_time;
2536 
2537  OsVersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
2538  GetVersionEx(&OsVersionInfo);
2539  if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
2540  return(NTElapsedTime());
2541  status=GetProcessTimes(GetCurrentProcess(),&create_time,&exit_time,
2542  &kernel_time.filetime,&user_time.filetime);
2543  if (status != TRUE)
2544  return(0.0);
2545  return((double) 1.0e-7*(kernel_time.filetime64+user_time.filetime64));
2546 }
2547 
2548 /*
2549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2550 % %
2551 % %
2552 % %
2553 % N T W a r n i n g H a n d l e r %
2554 % %
2555 % %
2556 % %
2557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2558 %
2559 % NTWarningHandler() displays a warning reason.
2560 %
2561 % The format of the NTWarningHandler method is:
2562 %
2563 % void NTWarningHandler(const ExceptionType severity,const char *reason,
2564 % const char *description)
2565 %
2566 % A description of each parameter follows:
2567 %
2568 % o severity: Specifies the numeric warning category.
2569 %
2570 % o reason: Specifies the reason to display before terminating the
2571 % program.
2572 %
2573 % o description: Specifies any description to the reason.
2574 %
2575 */
2576 MagickPrivate void NTWarningHandler(const ExceptionType severity,
2577  const char *reason,const char *description)
2578 {
2579  char
2580  buffer[2*MaxTextExtent];
2581 
2582  (void) severity;
2583  if (reason == (char *) NULL)
2584  return;
2585  if (description == (char *) NULL)
2586  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
2587  reason);
2588  else
2589  (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
2590  GetClientName(),reason,description);
2591  (void) MessageBox(NULL,buffer,"ImageMagick Warning",MB_OK | MB_TASKMODAL |
2592  MB_SETFOREGROUND | MB_ICONINFORMATION);
2593 }
2594 
2595 /*
2596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2597 % %
2598 % %
2599 % %
2600 % N T W i n d o w s G e n e s i s %
2601 % %
2602 % %
2603 % %
2604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2605 %
2606 % NTWindowsGenesis() initializes the MagickCore Windows environment.
2607 %
2608 % The format of the NTWindowsGenesis method is:
2609 %
2610 % void NTWindowsGenesis(void)
2611 %
2612 */
2613 MagickPrivate void NTWindowsGenesis(void)
2614 {
2615  char
2616  *mode;
2617 
2618  mode=GetEnvironmentValue("MAGICK_ERRORMODE");
2619  if (mode != (char *) NULL)
2620  {
2621  (void) SetErrorMode(StringToInteger(mode));
2622  mode=DestroyString(mode);
2623  }
2624 #if defined(_DEBUG) && !defined(__MINGW32__)
2625  if (IsEventLogging() != MagickFalse)
2626  {
2627  int
2628  debug;
2629 
2630  debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
2631  //debug |= _CRTDBG_CHECK_ALWAYS_DF;
2632  debug |= _CRTDBG_DELAY_FREE_MEM_DF;
2633  debug |= _CRTDBG_LEAK_CHECK_DF;
2634  (void) _CrtSetDbgFlag(debug);
2635 
2636  //_ASSERTE(_CrtCheckMemory());
2637 
2638  //_CrtSetBreakAlloc(42);
2639  }
2640 #endif
2641 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
2642  {
2643  unsigned char
2644  *path;
2645 
2646  path=NTRegistryKeyLookup("LibPath");
2647  if (path != (unsigned char *) NULL)
2648  {
2649  size_t
2650  length;
2651 
2652  wchar_t
2653  lib_path[MagickPathExtent];
2654 
2655  length=MultiByteToWideChar(CP_UTF8,0,(char *) path,-1,lib_path,
2656  MagickPathExtent);
2657  if (length != 0)
2658  SetDllDirectoryW(lib_path);
2659  path=(unsigned char *) RelinquishMagickMemory(path);
2660  }
2661  }
2662 #endif
2663 }
2664 
2665 /*
2666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2667 % %
2668 % %
2669 % %
2670 % N T W i n d o w s T e r m i n u s %
2671 % %
2672 % %
2673 % %
2674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2675 %
2676 % NTWindowsTerminus() terminates the MagickCore Windows environment.
2677 %
2678 % The format of the NTWindowsTerminus method is:
2679 %
2680 % void NTWindowsTerminus(void)
2681 %
2682 */
2683 MagickPrivate void NTWindowsTerminus(void)
2684 {
2685  NTGhostscriptUnLoadDLL();
2686  if (winsock_semaphore == (SemaphoreInfo *) NULL)
2687  ActivateSemaphoreInfo(&winsock_semaphore);
2688  LockSemaphoreInfo(winsock_semaphore);
2689  if (wsaData != (WSADATA *) NULL)
2690  {
2691  WSACleanup();
2692  wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData);
2693  }
2694  UnlockSemaphoreInfo(winsock_semaphore);
2695  DestroySemaphoreInfo(&winsock_semaphore);
2696 }
2697 #endif
Definition: mac.h:53
Definition: mac.h:41