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