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