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