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