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