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