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