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