]> granicus.if.org Git - imagemagick/blob - MagickCore/nt-base.c
(no commit message)
[imagemagick] / MagickCore / nt-base.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                                 N   N  TTTTT                                %
7 %                                 NN  N    T                                  %
8 %                                 N N N    T                                  %
9 %                                 N  NN    T                                  %
10 %                                 N   N    T                                  %
11 %                                                                             %
12 %                                                                             %
13 %                   Windows NT Utility Methods for MagickCore                 %
14 %                                                                             %
15 %                               Software Design                               %
16 %                                 John Cristy                                 %
17 %                                December 1996                                %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-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 \f
75 /*
76   Define declarations.
77 */
78 #if !defined(MAP_FAILED)
79 #define MAP_FAILED      ((void *) -1)
80 #endif
81 \f
82 /*
83   Static declarations.
84 */
85 #if !defined(MAGICKCORE_LTDL_DELEGATE)
86 static char
87   *lt_slsearchpath = (char *) NULL;
88 #endif
89
90 static GhostInfo
91   ghost_info;
92
93 static void
94   *ghost_handle = (void *) NULL;
95 \f
96 /*
97   External declarations.
98 */
99 #if !defined(MAGICKCORE_WINDOWS_SUPPORT)
100 extern "C" BOOL WINAPI
101   DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved);
102 #endif
103 \f
104 /*
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 %                                                                             %
107 %                                                                             %
108 %                                                                             %
109 %   C r o p I m a g e T o H B i t m a p                                       %
110 %                                                                             %
111 %                                                                             %
112 %                                                                             %
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %
115 %  CropImageToHBITMAP() extracts a specified region of the image and returns
116 %  it as a Windows HBITMAP. While the same functionality can be accomplished by
117 %  invoking CropImage() followed by ImageToHBITMAP(), this method is more
118 %  efficient since it copies pixels directly to the HBITMAP.
119 %
120 %  The format of the CropImageToHBITMAP method is:
121 %
122 %      HBITMAP CropImageToHBITMAP(Image* image,const RectangleInfo *geometry,
123 %        ExceptionInfo *exception)
124 %
125 %  A description of each parameter follows:
126 %
127 %    o image: the image.
128 %
129 %    o geometry: Define the region of the image to crop with members
130 %      x, y, width, and height.
131 %
132 %    o exception: return any errors or warnings in this structure.
133 %
134 */
135 MagickExport void *CropImageToHBITMAP(Image *image,
136   const RectangleInfo *geometry,ExceptionInfo *exception)
137 {
138 #define CropImageTag  "Crop/Image"
139
140   BITMAP
141     bitmap;
142
143   HBITMAP
144     bitmapH;
145
146   HANDLE
147     bitmap_bitsH;
148
149   MagickBooleanType
150     proceed;
151
152   RectangleInfo
153     page;
154
155   register const Quantum
156     *p;
157
158   register RGBQUAD
159     *q;
160
161   RGBQUAD
162     *bitmap_bits;
163
164   ssize_t
165     y;
166
167   /*
168     Check crop geometry.
169   */
170   assert(image != (const Image *) NULL);
171   assert(image->signature == MagickSignature);
172   if (image->debug != MagickFalse)
173     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
174   assert(geometry != (const RectangleInfo *) NULL);
175   assert(exception != (ExceptionInfo *) NULL);
176   assert(exception->signature == MagickSignature);
177   if (((geometry->x+(ssize_t) geometry->width) < 0) ||
178       ((geometry->y+(ssize_t) geometry->height) < 0) ||
179       (geometry->x >= (ssize_t) image->columns) ||
180       (geometry->y >= (ssize_t) image->rows))
181     ThrowImageException(OptionError,"GeometryDoesNotContainImage");
182   page=(*geometry);
183   if ((page.x+(ssize_t) page.width) > (ssize_t) image->columns)
184     page.width=image->columns-page.x;
185   if ((page.y+(ssize_t) page.height) > (ssize_t) image->rows)
186     page.height=image->rows-page.y;
187   if (page.x < 0)
188     {
189       page.width+=page.x;
190       page.x=0;
191     }
192   if (page.y < 0)
193     {
194       page.height+=page.y;
195       page.y=0;
196     }
197
198   if ((page.width == 0) || (page.height == 0))
199     ThrowImageException(OptionError,"GeometryDimensionsAreZero");
200   /*
201     Initialize crop image attributes.
202   */
203   bitmap.bmType         = 0;
204   bitmap.bmWidth        = (LONG) page.width;
205   bitmap.bmHeight       = (LONG) page.height;
206   bitmap.bmWidthBytes   = bitmap.bmWidth * 4;
207   bitmap.bmPlanes       = 1;
208   bitmap.bmBitsPixel    = 32;
209   bitmap.bmBits         = NULL;
210
211   bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,page.width*
212     page.height*bitmap.bmBitsPixel);
213   if (bitmap_bitsH == NULL)
214     return(NULL);
215   bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
216   if ( bitmap.bmBits == NULL )
217     bitmap.bmBits = bitmap_bits;
218   if (IsRGBColorspace(image->colorspace) == MagickFalse)
219     TransformImageColorspace(image,RGBColorspace,exception);
220   /*
221     Extract crop image.
222   */
223   q=bitmap_bits;
224   for (y=0; y < (ssize_t) page.height; y++)
225   {
226     p=GetVirtualPixels(image,page.x,page.y+y,page.width,1,exception);
227     if (p == (const Quantum *) NULL)
228       break;
229
230 #if MAGICKCORE_QUANTUM_DEPTH == 8
231       /* Form of PixelInfo is identical to RGBQUAD when MAGICKCORE_QUANTUM_DEPTH==8 */
232       CopyMagickMemory((void*)q,(const void*)p,page.width*sizeof(PixelInfo));
233       q += page.width;
234
235 #else  /* 16 or 32 bit Quantum */
236       {
237         ssize_t
238           x;
239
240         /* Transfer pixels, scaling to Quantum */
241         for( x=(ssize_t) page.width ; x> 0 ; x-- )
242           {
243             q->rgbRed = ScaleQuantumToChar(GetPixelRed(image,p));
244             q->rgbGreen = ScaleQuantumToChar(GetPixelGreen(image,p));
245             q->rgbBlue = ScaleQuantumToChar(GetPixelBlue(image,p));
246             q->rgbReserved = 0;
247             ++q;
248             ++p;
249           }
250       }
251 #endif
252     proceed=SetImageProgress(image,CropImageTag,y,page.height);
253     if (proceed == MagickFalse)
254       break;
255   }
256   if (y < (ssize_t) page.height)
257     {
258       GlobalUnlock((HGLOBAL) bitmap_bitsH);
259       GlobalFree((HGLOBAL) bitmap_bitsH);
260       return((void *) NULL);
261     }
262   bitmap.bmBits=bitmap_bits;
263   bitmapH=CreateBitmapIndirect(&bitmap);
264   GlobalUnlock((HGLOBAL) bitmap_bitsH);
265   GlobalFree((HGLOBAL) bitmap_bitsH);
266   return((void *) bitmapH);
267 }
268 \f
269 /*
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 %                                                                             %
272 %                                                                             %
273 %                                                                             %
274 %   D l l M a i n                                                             %
275 %                                                                             %
276 %                                                                             %
277 %                                                                             %
278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279 %
280 %  DllMain() is an entry point to the DLL which is called when processes and
281 %  threads are initialized and terminated, or upon calls to the Windows
282 %  LoadLibrary and FreeLibrary functions.
283 %
284 %  The function returns TRUE of it succeeds, or FALSE if initialization fails.
285 %
286 %  The format of the DllMain method is:
287 %
288 %    BOOL WINAPI DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved)
289 %
290 %  A description of each parameter follows:
291 %
292 %    o handle: handle to the DLL module
293 %
294 %    o reason: reason for calling function:
295 %
296 %      DLL_PROCESS_ATTACH - DLL is being loaded into virtual address
297 %                           space of current process.
298 %      DLL_THREAD_ATTACH - Indicates that the current process is
299 %                          creating a new thread.  Called under the
300 %                          context of the new thread.
301 %      DLL_THREAD_DETACH - Indicates that the thread is exiting.
302 %                          Called under the context of the exiting
303 %                          thread.
304 %      DLL_PROCESS_DETACH - Indicates that the DLL is being unloaded
305 %                           from the virtual address space of the
306 %                           current process.
307 %
308 %    o lpvReserved: Used for passing additional info during DLL_PROCESS_ATTACH
309 %                   and DLL_PROCESS_DETACH.
310 %
311 */
312 #if defined(_DLL) && defined( ProvideDllMain )
313 BOOL WINAPI DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved)
314 {
315   switch (reason)
316   {
317     case DLL_PROCESS_ATTACH:
318     {
319       char
320         *module_path;
321
322       ssize_t
323         count;
324
325       module_path=(char *) AcquireQuantumMemory(MaxTextExtent,
326         sizeof(*module_path));
327       if (module_path == (char *) NULL)
328         return(FALSE);
329       count=(ssize_t) GetModuleFileName(handle,module_path,MaxTextExtent);
330       if (count != 0)
331         {
332           char
333             *path;
334
335           for ( ; count > 0; count--)
336             if (module_path[count] == '\\')
337               {
338                 module_path[count+1]='\0';
339                 break;
340               }
341           MagickCoreGenesis(module_path,MagickFalse);
342           path=(char *) AcquireQuantumMemory(16UL*MaxTextExtent,sizeof(*path));
343           if (path == (char *) NULL)
344             {
345               module_path=DestroyString(module_path);
346               return(FALSE);
347             }
348           count=(ssize_t) GetEnvironmentVariable("PATH",path,16*MaxTextExtent);
349           if ((count != 0) && (strstr(path,module_path) == (char *) NULL))
350             {
351               if ((strlen(module_path)+count+1) < (16*MaxTextExtent-1))
352                 {
353                   char
354                     *variable;
355
356                   variable=(char *) AcquireQuantumMemory(16UL*MaxTextExtent,
357                     sizeof(*variable));
358                   if (variable == (char *) NULL)
359                     {
360                       path=DestroyString(path);
361                       module_path=DestroyString(module_path);
362                       return(FALSE);
363                     }
364                   (void) FormatLocaleString(variable,16*MaxTextExtent,
365                     "%s;%s",module_path,path);
366                   SetEnvironmentVariable("PATH",variable);
367                   variable=DestroyString(variable);
368                 }
369             }
370           path=DestroyString(path);
371         }
372       module_path=DestroyString(module_path);
373       break;
374     }
375     case DLL_PROCESS_DETACH:
376     {
377       MagickCoreTerminus();
378       break;
379     }
380     default:
381       break;
382   }
383   return(TRUE);
384 }
385 #endif
386 \f
387 /*
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 %                                                                             %
390 %                                                                             %
391 %                                                                             %
392 %   E x i t                                                                   %
393 %                                                                             %
394 %                                                                             %
395 %                                                                             %
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397 %
398 %  Exit() calls TerminateProcess for Win95.
399 %
400 %  The format of the exit method is:
401 %
402 %      int Exit(int status)
403 %
404 %  A description of each parameter follows:
405 %
406 %    o status: an integer value representing the status of the terminating
407 %      process.
408 %
409 */
410 MagickPrivate int Exit(int status)
411 {
412   if (IsWindows95())
413     TerminateProcess(GetCurrentProcess(),(unsigned int) status);
414   exit(status);
415   return(0);
416 }
417 \f
418 #if !defined(__MINGW32__)
419 /*
420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421 %                                                                             %
422 %                                                                             %
423 %                                                                             %
424 %   g e t t i m e o f d a y                                                   %
425 %                                                                             %
426 %                                                                             %
427 %                                                                             %
428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429 %
430 %  The gettimeofday() method get the time of day.
431 %
432 %  The format of the gettimeofday method is:
433 %
434 %      int gettimeofday(struct timeval *time_value,struct timezone *time_zone)
435 %
436 %  A description of each parameter follows:
437 %
438 %    o time_value: the time value.
439 %
440 %    o time_zone: the time zone.
441 %
442 */
443 MagickPrivate int gettimeofday (struct timeval *time_value,
444   struct timezone *time_zone)
445 {
446 #define EpochFiletime  MagickLLConstant(116444736000000000)
447
448   static int
449     is_tz_set;
450
451   if (time_value != (struct timeval *) NULL)
452     {
453       FILETIME
454         file_time;
455
456       __int64
457         time;
458
459       LARGE_INTEGER
460         date_time;
461
462       GetSystemTimeAsFileTime(&file_time);
463       date_time.LowPart=file_time.dwLowDateTime;
464       date_time.HighPart=file_time.dwHighDateTime;
465       time=date_time.QuadPart;
466       time-=EpochFiletime;
467       time/=10;
468       time_value->tv_sec=(ssize_t) (time / 1000000);
469       time_value->tv_usec=(ssize_t) (time % 1000000);
470     }
471   if (time_zone != (struct timezone *) NULL)
472     {
473       if (is_tz_set == 0)
474         {
475           _tzset();
476           is_tz_set++;
477         }
478       time_zone->tz_minuteswest=_timezone/60;
479       time_zone->tz_dsttime=_daylight;
480     }
481   return(0);
482 }
483 #endif
484 \f
485 /*
486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487 %                                                                             %
488 %                                                                             %
489 %                                                                             %
490 %   I m a g e T o H B i t m a p                                               %
491 %                                                                             %
492 %                                                                             %
493 %                                                                             %
494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
495 %
496 %  ImageToHBITMAP() creates a Windows HBITMAP from an image.
497 %
498 %  The format of the ImageToHBITMAP method is:
499 %
500 %      HBITMAP ImageToHBITMAP(Image *image)
501 %
502 %  A description of each parameter follows:
503 %
504 %    o image: the image to convert.
505 %
506 */
507 MagickExport 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,exception);
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 \f
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 */
616 MagickPrivate 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 \f
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 */
653 MagickExport 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 \f
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 */
710 MagickPrivate 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 \f
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 */
741 MagickPrivate int NTCloseLibrary(void *handle)
742 {
743   if (IsWindows95())
744     return(FreeLibrary((HINSTANCE) handle));
745   return(!(FreeLibrary((HINSTANCE) handle)));
746 }
747 \f
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
768 static BOOL ControlHandler(DWORD type)
769 {
770   (void) type;
771   AsynchronousResourceComponentTerminus();
772   return(FALSE);
773 }
774
775 MagickPrivate int NTControlHandler(void)
776 {
777   return(SetConsoleCtrlHandler((PHANDLER_ROUTINE) ControlHandler,TRUE));
778 }
779 \f
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 */
799 MagickPrivate 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 \f
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 */
846 MagickExport 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 \f
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 */
899 MagickPrivate int NTExitLibrary(void)
900 {
901   return(0);
902 }
903 \f
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 */
929 MagickPrivate 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 \f
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 */
987 MagickPrivate MagickBooleanType NTGetExecutionPath(char *path,
988   const size_t extent)
989 {
990   GetModuleFileName(0,path,(DWORD) extent);
991   return(MagickTrue);
992 }
993 \f
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 */
1012 MagickPrivate 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 \f
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 */
1056 MagickPrivate 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 \f
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 */
1097 void *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 \f
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 */
1132 MagickPrivate 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 \f
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 */
1175 MagickPrivate 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 \f
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
1473 static 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
1515 static 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 (RegOpenKeyExA(root,key,0,mode,&hkey) == ERROR_SUCCESS)
1556       {
1557         DWORD
1558           extent;
1559
1560         int
1561           j;
1562
1563         /*
1564           Now enumerate the keys.
1565         */
1566         extent=sizeof(key)/sizeof(char);
1567         for (j=0; RegEnumKeyA(hkey,j,key,extent) == ERROR_SUCCESS; j++)
1568         {
1569           int
1570             major,
1571             minor;
1572
1573           major=0;
1574           minor=0;
1575           if (sscanf(key,"%d.%d",&major,&minor) != 2)
1576             continue;
1577           if ((major > *major_version) || ((major == *major_version) &&
1578               (minor > *minor_version)))
1579             {
1580               *product_family=products[i];
1581               *major_version=major;
1582               *minor_version=minor;
1583               status=TRUE;
1584             }
1585        }
1586        (void) RegCloseKey(hkey);
1587      }
1588   }
1589   if (status == FALSE)
1590     {
1591       *major_version=0;
1592       *minor_version=0;
1593     }
1594   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"Ghostscript (%s) "
1595     "version %d.%02d",*product_family,*major_version,*minor_version);
1596   return(status);
1597 }
1598
1599 static int NTGhostscriptGetString(const char *name,char *value,
1600   const size_t length)
1601 {
1602   char
1603     key[MaxTextExtent];
1604
1605   int
1606     i,
1607     extent;
1608
1609   static const char
1610     *product_family = (const char *) NULL;
1611
1612   static int
1613     major_version=0,
1614     minor_version=0;
1615
1616   struct
1617   {
1618     const HKEY
1619       hkey;
1620
1621     const char
1622       *name;
1623   }
1624   hkeys[2] =
1625   {
1626     { HKEY_CURRENT_USER,  "HKEY_CURRENT_USER"  },
1627     { HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" }
1628   };
1629
1630   /*
1631     Get a string from the installed Ghostscript.
1632   */
1633   *value='\0';
1634   if (product_family == NULL)
1635     (void) NTLocateGhostscript(&product_family,&major_version,&minor_version);
1636   if (product_family == NULL)
1637     return(FALSE);
1638   (void) FormatLocaleString(key,MaxTextExtent,"SOFTWARE\\%s\\%d.%02d",
1639     product_family,major_version,minor_version);
1640   for (i=0; i < (ssize_t) (sizeof(hkeys)/sizeof(hkeys[0])); i++)
1641   {
1642     extent=(int) length;
1643     if (NTGetRegistryValue(hkeys[i].hkey,key,name,value,&extent) == 0)
1644       {
1645         (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1646           "registry: \"%s\\%s\\%s\"=\"%s\"",hkeys[i].name,key,name,value);
1647         return(TRUE);
1648       }
1649     (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1650       "registry: \"%s\\%s\\%s\" (failed)",hkeys[i].name,key,name);
1651   }
1652   return(FALSE);
1653 }
1654
1655 MagickPrivate int NTGhostscriptDLL(char *path,int length)
1656 {
1657   static char
1658     dll[MaxTextExtent] = { "" };
1659
1660   *path='\0';
1661   if ((*dll == '\0') &&
1662       (NTGhostscriptGetString("GS_DLL",dll,sizeof(dll)) == FALSE))
1663     return(FALSE);
1664   (void) CopyMagickString(path,dll,length);
1665   return(TRUE);
1666 }
1667 \f
1668 /*
1669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1670 %                                                                             %
1671 %                                                                             %
1672 %                                                                             %
1673 %   N T G h o s t s c r i p t D L L V e c t o r s                             %
1674 %                                                                             %
1675 %                                                                             %
1676 %                                                                             %
1677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1678 %
1679 %  NTGhostscriptDLLVectors() returns a GhostInfo structure that includes
1680 %  function vectors to invoke Ghostscript DLL functions. A null pointer is
1681 %  returned if there is an error when loading the DLL or retrieving the
1682 %  function vectors.
1683 %
1684 %  The format of the NTGhostscriptDLLVectors method is:
1685 %
1686 %      const GhostInfo *NTGhostscriptDLLVectors(void)
1687 %
1688 */
1689 MagickExport const GhostInfo *NTGhostscriptDLLVectors(void)
1690 {
1691   if (NTGhostscriptLoadDLL() == FALSE)
1692     return((GhostInfo *) NULL);
1693   return(&ghost_info);
1694 }
1695 \f
1696 /*
1697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1698 %                                                                             %
1699 %                                                                             %
1700 %                                                                             %
1701 %   N T G h o s t s c r i p t E X E                                           %
1702 %                                                                             %
1703 %                                                                             %
1704 %                                                                             %
1705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1706 %
1707 %  NTGhostscriptEXE() obtains the path to the latest Ghostscript executable.
1708 %  The method returns FALSE if a full path value is not obtained and returns
1709 %  a default path of gswin32c.exe.
1710 %
1711 %  The format of the NTGhostscriptEXE method is:
1712 %
1713 %      int NTGhostscriptEXE(char *path,int length)
1714 %
1715 %  A description of each parameter follows:
1716 %
1717 %    o path: return the Ghostscript executable path here.
1718 %
1719 %    o length: length of buffer.
1720 %
1721 */
1722 MagickPrivate int NTGhostscriptEXE(char *path,int length)
1723 {
1724   register char
1725     *p;
1726
1727   static char
1728     program[MaxTextExtent] = { "" };
1729
1730   (void) CopyMagickString(path,"gswin32c.exe",length);
1731   if ((*program == '\0') &&
1732       (NTGhostscriptGetString("GS_DLL",program,sizeof(program)) == FALSE))
1733     return(FALSE);
1734   p=strrchr(program,'\\');
1735   if (p != (char *) NULL)
1736     {
1737       p++;
1738       *p='\0';
1739       (void) ConcatenateMagickString(program,"gswin32c.exe",sizeof(program));
1740     }
1741   (void) CopyMagickString(path,program,length);
1742   return(TRUE);
1743 }
1744 \f
1745 /*
1746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1747 %                                                                             %
1748 %                                                                             %
1749 %                                                                             %
1750 %   N T G h o s t s c r i p t F o n t s                                       %
1751 %                                                                             %
1752 %                                                                             %
1753 %                                                                             %
1754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1755 %
1756 %  NTGhostscriptFonts() obtains the path to the Ghostscript fonts.  The method
1757 %  returns FALSE if it cannot determine the font path.
1758 %
1759 %  The format of the NTGhostscriptFonts method is:
1760 %
1761 %      int NTGhostscriptFonts(char *path, int length)
1762 %
1763 %  A description of each parameter follows:
1764 %
1765 %    o path: return the font path here.
1766 %
1767 %    o length: length of the path buffer.
1768 %
1769 */
1770 MagickPrivate int NTGhostscriptFonts(char *path,int length)
1771 {
1772   char
1773     buffer[MaxTextExtent],
1774     filename[MaxTextExtent];
1775
1776   register char
1777     *p,
1778     *q;
1779
1780   *path='\0';
1781   if (NTGhostscriptGetString("GS_LIB",buffer,MaxTextExtent) == FALSE)
1782     return(FALSE);
1783   for (p=buffer-1; p != (char *) NULL; p=strchr(p+1,DirectoryListSeparator))
1784   {
1785     (void) CopyMagickString(path,p+1,length+1);
1786     q=strchr(path,DirectoryListSeparator);
1787     if (q != (char *) NULL)
1788       *q='\0';
1789     (void) FormatLocaleString(filename,MaxTextExtent,"%s%sfonts.dir",path,
1790       DirectorySeparator);
1791     if (IsPathAccessible(filename) != MagickFalse)
1792       return(TRUE);
1793   }
1794   return(FALSE);
1795 }
1796 \f
1797 /*
1798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1799 %                                                                             %
1800 %                                                                             %
1801 %                                                                             %
1802 %   N T G h o s t s c r i p t L o a d D L L                                   %
1803 %                                                                             %
1804 %                                                                             %
1805 %                                                                             %
1806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1807 %
1808 %  NTGhostscriptLoadDLL() attempts to load the Ghostscript DLL and returns
1809 %  TRUE if it succeeds.
1810 %
1811 %  The format of the NTGhostscriptLoadDLL method is:
1812 %
1813 %      int NTGhostscriptLoadDLL(void)
1814 %
1815 */
1816 MagickPrivate int NTGhostscriptLoadDLL(void)
1817 {
1818   char
1819     path[MaxTextExtent];
1820
1821   if (ghost_handle != (void *) NULL)
1822     return(TRUE);
1823   if (NTGhostscriptDLL(path,sizeof(path)) == FALSE)
1824     return(FALSE);
1825   ghost_handle=lt_dlopen(path);
1826   if (ghost_handle == (void *) NULL)
1827     return(FALSE);
1828   (void) ResetMagickMemory((void *) &ghost_info,0,sizeof(GhostInfo));
1829   ghost_info.exit=(int (MagickDLLCall *)(gs_main_instance*))
1830     lt_dlsym(ghost_handle,"gsapi_exit");
1831   ghost_info.init_with_args=(int (MagickDLLCall *)(gs_main_instance *,int,
1832     char **)) (lt_dlsym(ghost_handle,"gsapi_init_with_args"));
1833   ghost_info.new_instance=(int (MagickDLLCall *)(gs_main_instance **,void *)) (
1834     lt_dlsym(ghost_handle,"gsapi_new_instance"));
1835   ghost_info.run_string=(int (MagickDLLCall *)(gs_main_instance *,const char *,
1836     int,int *)) (lt_dlsym(ghost_handle,"gsapi_run_string"));
1837   ghost_info.delete_instance=(void (MagickDLLCall *) (gs_main_instance *)) (
1838     lt_dlsym(ghost_handle,"gsapi_delete_instance"));
1839   if ((ghost_info.exit == NULL) || (ghost_info.init_with_args == NULL) ||
1840       (ghost_info.new_instance == NULL) || (ghost_info.run_string == NULL) ||
1841       (ghost_info.delete_instance == NULL))
1842     return(FALSE);
1843   return(TRUE);
1844 }
1845 \f
1846 /*
1847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1848 %                                                                             %
1849 %                                                                             %
1850 %                                                                             %
1851 %   N T G h o s t s c r i p t U n L o a d D L L                               %
1852 %                                                                             %
1853 %                                                                             %
1854 %                                                                             %
1855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1856 %
1857 %  NTGhostscriptUnLoadDLL() unloads the Ghostscript DLL and returns TRUE if
1858 %  it succeeds.
1859 %
1860 %  The format of the NTGhostscriptUnLoadDLL method is:
1861 %
1862 %      int NTGhostscriptUnLoadDLL(void)
1863 %
1864 */
1865 MagickExport int NTGhostscriptUnLoadDLL(void)
1866 {
1867   int
1868     status;
1869
1870   if (ghost_handle == (void *) NULL)
1871     return(FALSE);
1872   status=lt_dlclose(ghost_handle);
1873   ghost_handle=(void *) NULL;
1874   (void) ResetMagickMemory((void *) &ghost_info,0,sizeof(GhostInfo));
1875   return(status);
1876 }
1877 \f
1878 /*
1879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1880 %                                                                             %
1881 %                                                                             %
1882 %                                                                             %
1883 %   N T I n i t i a l i z e L i b r a r y                                     %
1884 %                                                                             %
1885 %                                                                             %
1886 %                                                                             %
1887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1888 %
1889 %  NTInitializeLibrary() initializes the dynamic module loading subsystem.
1890 %
1891 %  The format of the NTInitializeLibrary method is:
1892 %
1893 %      int NTInitializeLibrary(void)
1894 %
1895 */
1896 MagickPrivate int NTInitializeLibrary(void)
1897 {
1898   return(0);
1899 }
1900 \f
1901 /*
1902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1903 %                                                                             %
1904 %                                                                             %
1905 %                                                                             %
1906 %   N T I s M a g i c k C o n f l i c t                                       %
1907 %                                                                             %
1908 %                                                                             %
1909 %                                                                             %
1910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1911 %
1912 %  NTIsMagickConflict() returns true if the image format conflicts with a
1913 %  logical drive (.e.g. X:).
1914 %
1915 %  The format of the IsMagickConflict method is:
1916 %
1917 %      MagickBooleanType IsMagickConflict(const char *magick)
1918 %
1919 %  A description of each parameter follows:
1920 %
1921 %    o magick: Specifies the image format.
1922 %
1923 */
1924 MagickPrivate MagickBooleanType NTIsMagickConflict(const char *magick)
1925 {
1926   MagickBooleanType
1927     status;
1928
1929   assert(magick != (char *) NULL);
1930   if (strlen(magick) > 1)
1931     return(MagickFalse);
1932   status=(GetLogicalDrives() & (1 << ((toupper((int) (*magick)))-'A'))) != 0 ?
1933     MagickTrue : MagickFalse;
1934   return(status);
1935 }
1936 \f
1937 /*
1938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1939 %                                                                             %
1940 %                                                                             %
1941 %                                                                             %
1942 +  N T M a p M e m o r y                                                      %
1943 %                                                                             %
1944 %                                                                             %
1945 %                                                                             %
1946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1947 %
1948 %  Mmap() emulates the Unix method of the same name.
1949 %
1950 %  The format of the NTMapMemory method is:
1951 %
1952 %    MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1953 %      int access,int file,MagickOffsetType offset)
1954 %
1955 */
1956 MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1957   int flags,int file,MagickOffsetType offset)
1958 {
1959   DWORD
1960     access_mode,
1961     high_length,
1962     high_offset,
1963     low_length,
1964     low_offset,
1965     protection_mode;
1966
1967   HANDLE
1968     file_handle,
1969     map_handle;
1970
1971   void
1972     *map;
1973
1974   (void) address;
1975   access_mode=0;
1976   file_handle=INVALID_HANDLE_VALUE;
1977   low_length=(DWORD) (length & 0xFFFFFFFFUL);
1978   high_length=(DWORD) ((((MagickOffsetType) length) >> 32) & 0xFFFFFFFFUL);
1979   map_handle=INVALID_HANDLE_VALUE;
1980   map=(void *) NULL;
1981   low_offset=(DWORD) (offset & 0xFFFFFFFFUL);
1982   high_offset=(DWORD) ((offset >> 32) & 0xFFFFFFFFUL);
1983   protection_mode=0;
1984   if (protection & PROT_WRITE)
1985     {
1986       access_mode=FILE_MAP_WRITE;
1987       if (!(flags & MAP_PRIVATE))
1988         protection_mode=PAGE_READWRITE;
1989       else
1990         {
1991           access_mode=FILE_MAP_COPY;
1992           protection_mode=PAGE_WRITECOPY;
1993         }
1994     }
1995   else
1996     if (protection & PROT_READ)
1997       {
1998         access_mode=FILE_MAP_READ;
1999         protection_mode=PAGE_READONLY;
2000       }
2001   if ((file == -1) && (flags & MAP_ANONYMOUS))
2002     file_handle=INVALID_HANDLE_VALUE;
2003   else
2004     file_handle=(HANDLE) _get_osfhandle(file);
2005   map_handle=CreateFileMapping(file_handle,0,protection_mode,high_length,
2006     low_length,0);
2007   if (map_handle)
2008     {
2009       map=(void *) MapViewOfFile(map_handle,access_mode,high_offset,low_offset,
2010         length);
2011       CloseHandle(map_handle);
2012     }
2013   if (map == (void *) NULL)
2014     return((void *) MAP_FAILED);
2015   return((void *) ((char *) map));
2016 }
2017 \f
2018 /*
2019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2020 %                                                                             %
2021 %                                                                             %
2022 %                                                                             %
2023 %   N T O p e n D i r e c t o r y                                             %
2024 %                                                                             %
2025 %                                                                             %
2026 %                                                                             %
2027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2028 %
2029 %  NTOpenDirectory() opens the directory named by filename and associates a
2030 %  directory stream with it.
2031 %
2032 %  The format of the NTOpenDirectory method is:
2033 %
2034 %      DIR *NTOpenDirectory(const char *path)
2035 %
2036 %  A description of each parameter follows:
2037 %
2038 %    o entry: Specifies a pointer to a DIR structure.
2039 %
2040 */
2041 MagickPrivate DIR *NTOpenDirectory(const char *path)
2042 {
2043   char
2044     file_specification[MaxTextExtent];
2045
2046   DIR
2047     *entry;
2048
2049   size_t
2050     length;
2051
2052   assert(path != (const char *) NULL);
2053   length=CopyMagickString(file_specification,path,MaxTextExtent);
2054   if (length >= (MaxTextExtent-1))
2055     return((DIR *) NULL);
2056   length=ConcatenateMagickString(file_specification,DirectorySeparator,
2057     MaxTextExtent);
2058   if (length >= (MaxTextExtent-1))
2059     return((DIR *) NULL);
2060   entry=(DIR *) AcquireMagickMemory(sizeof(DIR));
2061   if (entry != (DIR *) NULL)
2062     {
2063       entry->firsttime=TRUE;
2064       entry->hSearch=FindFirstFile(file_specification,&entry->Win32FindData);
2065     }
2066   if (entry->hSearch == INVALID_HANDLE_VALUE)
2067     {
2068       length=ConcatenateMagickString(file_specification,"\\*.*",MaxTextExtent);
2069       if (length >= (MaxTextExtent-1))
2070         {
2071           entry=(DIR *) RelinquishMagickMemory(entry);
2072           return((DIR *) NULL);
2073         }
2074       entry->hSearch=FindFirstFile(file_specification,&entry->Win32FindData);
2075       if (entry->hSearch == INVALID_HANDLE_VALUE)
2076         {
2077           entry=(DIR *) RelinquishMagickMemory(entry);
2078           return((DIR *) NULL);
2079         }
2080     }
2081   return(entry);
2082 }
2083 \f
2084 /*
2085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086 %                                                                             %
2087 %                                                                             %
2088 %                                                                             %
2089 %   N T O p e n L i b r a r y                                                 %
2090 %                                                                             %
2091 %                                                                             %
2092 %                                                                             %
2093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2094 %
2095 %  NTOpenLibrary() loads a dynamic module into memory and returns a handle that
2096 %  can be used to access the various procedures in the module.
2097 %
2098 %  The format of the NTOpenLibrary method is:
2099 %
2100 %      void *NTOpenLibrary(const char *filename)
2101 %
2102 %  A description of each parameter follows:
2103 %
2104 %    o path: Specifies a pointer to string representing dynamic module that
2105 %      is to be loaded.
2106 %
2107 */
2108
2109 static const char *GetSearchPath( void )
2110 {
2111 #if defined(MAGICKCORE_LTDL_DELEGATE)
2112   return(lt_dlgetsearchpath());
2113 #else
2114   return(lt_slsearchpath);
2115 #endif
2116 }
2117
2118 MagickPrivate void *NTOpenLibrary(const char *filename)
2119 {
2120 #define MaxPathElements  31
2121
2122   char
2123     buffer[MaxTextExtent];
2124
2125   int
2126     index;
2127
2128   register const char
2129     *p,
2130     *q;
2131
2132   register int
2133     i;
2134
2135   UINT
2136     mode;
2137
2138   void
2139     *handle;
2140
2141   mode=SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
2142   handle=(void *) LoadLibraryEx(filename,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
2143   if ((handle != (void *) NULL) || (GetSearchPath() == (char *) NULL))
2144     {
2145       SetErrorMode(mode);
2146       return(handle);
2147     }
2148   p=(char *) GetSearchPath();
2149   index=0;
2150   while (index < MaxPathElements)
2151   {
2152     q=strchr(p,DirectoryListSeparator);
2153     if (q == (char *) NULL)
2154       {
2155         (void) CopyMagickString(buffer,p,MaxTextExtent);
2156         (void) ConcatenateMagickString(buffer,"\\",MaxTextExtent);
2157         (void) ConcatenateMagickString(buffer,filename,MaxTextExtent);
2158         handle=(void *) LoadLibraryEx(buffer,NULL,
2159           LOAD_WITH_ALTERED_SEARCH_PATH);
2160         break;
2161       }
2162     i=q-p;
2163     (void) CopyMagickString(buffer,p,i+1);
2164     (void) ConcatenateMagickString(buffer,"\\",MaxTextExtent);
2165     (void) ConcatenateMagickString(buffer,filename,MaxTextExtent);
2166     handle=(void *) LoadLibraryEx(buffer,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
2167     if (handle != (void *) NULL)
2168       break;
2169     p=q+1;
2170   }
2171   SetErrorMode(mode);
2172   return(handle);
2173 }
2174 \f
2175 /*
2176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2177 %                                                                             %
2178 %                                                                             %
2179 %                                                                             %
2180 %    N T R e a d D i r e c t o r y                                            %
2181 %                                                                             %
2182 %                                                                             %
2183 %                                                                             %
2184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2185 %
2186 %  NTReadDirectory() returns a pointer to a structure representing the
2187 %  directory entry at the current position in the directory stream to which
2188 %  entry refers.
2189 %
2190 %  The format of the NTReadDirectory
2191 %
2192 %      NTReadDirectory(entry)
2193 %
2194 %  A description of each parameter follows:
2195 %
2196 %    o entry: Specifies a pointer to a DIR structure.
2197 %
2198 */
2199 MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
2200 {
2201   int
2202     status;
2203
2204   size_t
2205     length;
2206
2207   if (entry == (DIR *) NULL)
2208     return((struct dirent *) NULL);
2209   if (!entry->firsttime)
2210     {
2211       status=FindNextFile(entry->hSearch,&entry->Win32FindData);
2212       if (status == 0)
2213         return((struct dirent *) NULL);
2214     }
2215   length=CopyMagickString(entry->file_info.d_name,
2216     entry->Win32FindData.cFileName,sizeof(entry->file_info.d_name));
2217   if (length >= sizeof(entry->file_info.d_name))
2218     return((struct dirent *) NULL);
2219   entry->firsttime=FALSE;
2220   entry->file_info.d_namlen=(int) strlen(entry->file_info.d_name);
2221   return(&entry->file_info);
2222 }
2223 \f
2224 /*
2225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2226 %                                                                             %
2227 %                                                                             %
2228 %                                                                             %
2229 %   N T R e g i s t r y K e y L o o k u p                                     %
2230 %                                                                             %
2231 %                                                                             %
2232 %                                                                             %
2233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2234 %
2235 %  NTRegistryKeyLookup() returns ImageMagick installation path settings
2236 %  stored in the Windows Registry.  Path settings are specific to the
2237 %  installed ImageMagick version so that multiple Image Magick installations
2238 %  may coexist.
2239 %
2240 %  Values are stored in the registry under a base path path similar to
2241 %  "HKEY_LOCAL_MACHINE/SOFTWARE\ImageMagick\5.5.7\Q:16". The provided subkey
2242 %  is appended to this base path to form the full key.
2243 %
2244 %  The format of the NTRegistryKeyLookup method is:
2245 %
2246 %      unsigned char *NTRegistryKeyLookup(const char *subkey)
2247 %
2248 %  A description of each parameter follows:
2249 %
2250 %    o subkey: Specifies a string that identifies the registry object.
2251 %      Currently supported sub-keys include: "BinPath", "ConfigurePath",
2252 %      "LibPath", "CoderModulesPath", "FilterModulesPath", "SharePath".
2253 %
2254 */
2255 MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
2256 {
2257   char
2258     package_key[MaxTextExtent];
2259
2260   DWORD
2261     size,
2262     type;
2263
2264   HKEY
2265     registry_key;
2266
2267   LONG
2268     status;
2269
2270   unsigned char
2271     *value;
2272
2273   /*
2274     Look-up base key.
2275   */
2276   (void) FormatLocaleString(package_key,MaxTextExtent,"SOFTWARE\\%s\\%s\\Q:%d",
2277     MagickPackageName,MagickLibVersionText,MAGICKCORE_QUANTUM_DEPTH);
2278   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"%s",package_key);
2279   registry_key=(HKEY) INVALID_HANDLE_VALUE;
2280   status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,package_key,0,KEY_READ,&registry_key);
2281   if (status != ERROR_SUCCESS)
2282     {
2283       registry_key=(HKEY) INVALID_HANDLE_VALUE;
2284       return((unsigned char *) NULL);
2285     }
2286   /*
2287     Look-up sub key.
2288   */
2289   size=32;
2290   value=(unsigned char *) AcquireQuantumMemory(size,sizeof(*value));
2291   if (value == (unsigned char *) NULL)
2292     {
2293       RegCloseKey(registry_key);
2294       return((unsigned char *) NULL);
2295     }
2296   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"%s",subkey);
2297   status=RegQueryValueExA(registry_key,subkey,0,&type,value,&size);
2298   if ((status == ERROR_MORE_DATA) && (type == REG_SZ))
2299     {
2300       value=(unsigned char *) ResizeQuantumMemory(value,size,sizeof(*value));
2301       if (value == (BYTE *) NULL)
2302         {
2303           RegCloseKey(registry_key);
2304           return((unsigned char *) NULL);
2305         }
2306       status=RegQueryValueExA(registry_key,subkey,0,&type,value,&size);
2307     }
2308   RegCloseKey(registry_key);
2309   if ((type != REG_SZ) || (status != ERROR_SUCCESS))
2310     value=(unsigned char *) RelinquishMagickMemory(value);
2311   return((unsigned char *) value);
2312 }
2313 \f
2314 /*
2315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2316 %                                                                             %
2317 %                                                                             %
2318 %                                                                             %
2319 %   N T R e p o r t E v e n t                                                 %
2320 %                                                                             %
2321 %                                                                             %
2322 %                                                                             %
2323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2324 %
2325 %  NTReportEvent() reports an event.
2326 %
2327 %  The format of the NTReportEvent method is:
2328 %
2329 %      MagickBooleanType NTReportEvent(const char *event,
2330 %        const MagickBooleanType error)
2331 %
2332 %  A description of each parameter follows:
2333 %
2334 %    o event: the event.
2335 %
2336 %    o error: MagickTrue the event is an error.
2337 %
2338 */
2339 MagickPrivate MagickBooleanType NTReportEvent(const char *event,
2340   const MagickBooleanType error)
2341 {
2342   const char
2343     *events[1];
2344
2345   HANDLE
2346     handle;
2347
2348   WORD
2349     type;
2350
2351   handle=RegisterEventSource(NULL,MAGICKCORE_PACKAGE_NAME);
2352   if (handle == NULL)
2353     return(MagickFalse);
2354   events[0]=event;
2355   type=error ? EVENTLOG_ERROR_TYPE : EVENTLOG_WARNING_TYPE;
2356   ReportEvent(handle,type,0,0,NULL,1,0,events,NULL);
2357   DeregisterEventSource(handle);
2358   return(MagickTrue);
2359 }
2360 \f
2361 /*
2362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2363 %                                                                             %
2364 %                                                                             %
2365 %                                                                             %
2366 %   N T R e s o u r c e T o B l o b                                           %
2367 %                                                                             %
2368 %                                                                             %
2369 %                                                                             %
2370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2371 %
2372 %  NTResourceToBlob() returns a blob containing the contents of the resource
2373 %  in the current executable specified by the id parameter. This currently
2374 %  used to retrieve MGK files tha have been embedded into the various command
2375 %  line utilities.
2376 %
2377 %  The format of the NTResourceToBlob method is:
2378 %
2379 %      unsigned char *NTResourceToBlob(const char *id)
2380 %
2381 %  A description of each parameter follows:
2382 %
2383 %    o id: Specifies a string that identifies the resource.
2384 %
2385 */
2386 MagickPrivate unsigned char *NTResourceToBlob(const char *id)
2387 {
2388   char
2389     path[MaxTextExtent];
2390
2391   DWORD
2392     length;
2393
2394   HGLOBAL
2395     global;
2396
2397   HMODULE
2398     handle;
2399
2400   HRSRC
2401     resource;
2402
2403   unsigned char
2404     *blob,
2405     *value;
2406
2407   assert(id != (const char *) NULL);
2408   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
2409   (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
2410     DirectorySeparator,GetClientName());
2411   if (IsPathAccessible(path) != MagickFalse)
2412     handle=GetModuleHandle(path);
2413   else
2414     handle=GetModuleHandle(0);
2415   if (!handle)
2416     return((unsigned char *) NULL);
2417   resource=FindResource(handle,id,"IMAGEMAGICK");
2418   if (!resource)
2419     return((unsigned char *) NULL);
2420   global=LoadResource(handle,resource);
2421   if (!global)
2422     return((unsigned char *) NULL);
2423   length=SizeofResource(handle,resource);
2424   value=(unsigned char *) LockResource(global);
2425   if (!value)
2426     {
2427       FreeResource(global);
2428       return((unsigned char *) NULL);
2429     }
2430   blob=(unsigned char *) AcquireQuantumMemory(length+MaxTextExtent,
2431     sizeof(*blob));
2432   if (blob != (unsigned char *) NULL)
2433     {
2434       (void) CopyMagickMemory(blob,value,length);
2435       blob[length]='\0';
2436     }
2437   UnlockResource(global);
2438   FreeResource(global);
2439   return(blob);
2440 }
2441 \f
2442 /*
2443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2444 %                                                                             %
2445 %                                                                             %
2446 %                                                                             %
2447 %   N T S e e k D i r e c t o r y                                             %
2448 %                                                                             %
2449 %                                                                             %
2450 %                                                                             %
2451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2452 %
2453 %  NTSeekDirectory() sets the position of the next NTReadDirectory() operation
2454 %  on the directory stream.
2455 %
2456 %  The format of the NTSeekDirectory method is:
2457 %
2458 %      void NTSeekDirectory(DIR *entry,ssize_t position)
2459 %
2460 %  A description of each parameter follows:
2461 %
2462 %    o entry: Specifies a pointer to a DIR structure.
2463 %
2464 %    o position: specifies the position associated with the directory
2465 %      stream.
2466 %
2467 */
2468 MagickPrivate void NTSeekDirectory(DIR *entry,ssize_t position)
2469 {
2470   (void) position;
2471   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2472   assert(entry != (DIR *) NULL);
2473 }
2474 \f
2475 /*
2476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2477 %                                                                             %
2478 %                                                                             %
2479 %                                                                             %
2480 %   N T S e t S e a r c h P a t h                                             %
2481 %                                                                             %
2482 %                                                                             %
2483 %                                                                             %
2484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2485 %
2486 %  NTSetSearchPath() sets the current locations that the subsystem should
2487 %  look at to find dynamically loadable modules.
2488 %
2489 %  The format of the NTSetSearchPath method is:
2490 %
2491 %      int NTSetSearchPath(const char *path)
2492 %
2493 %  A description of each parameter follows:
2494 %
2495 %    o path: Specifies a pointer to string representing the search path
2496 %      for DLL's that can be dynamically loaded.
2497 %
2498 */
2499 MagickPrivate int NTSetSearchPath(const char *path)
2500 {
2501 #if defined(MAGICKCORE_LTDL_DELEGATE)
2502   lt_dlsetsearchpath(path);
2503 #else
2504   if (lt_slsearchpath != (char *) NULL)
2505     lt_slsearchpath=DestroyString(lt_slsearchpath);
2506   if (path != (char *) NULL)
2507     lt_slsearchpath=AcquireString(path);
2508 #endif
2509   return(0);
2510 }
2511 \f
2512 /*
2513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2514 %                                                                             %
2515 %                                                                             %
2516 %                                                                             %
2517 +  N T S y n c M e m o r y                                                    %
2518 %                                                                             %
2519 %                                                                             %
2520 %                                                                             %
2521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2522 %
2523 %  NTSyncMemory() emulates the Unix method of the same name.
2524 %
2525 %  The format of the NTSyncMemory method is:
2526 %
2527 %      int NTSyncMemory(void *address,size_t length,int flags)
2528 %
2529 %  A description of each parameter follows:
2530 %
2531 %    o address: the address of the binary large object.
2532 %
2533 %    o length: the length of the binary large object.
2534 %
2535 %    o flags: Option flags (ignored for Windows).
2536 %
2537 */
2538 MagickPrivate int NTSyncMemory(void *address,size_t length,int flags)
2539 {
2540   (void) flags;
2541   if (FlushViewOfFile(address,length) == MagickFalse)
2542     return(-1);
2543   return(0);
2544 }
2545 \f
2546 /*
2547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2548 %                                                                             %
2549 %                                                                             %
2550 %                                                                             %
2551 %   N T S y s t e m C o m m a n d                                             %
2552 %                                                                             %
2553 %                                                                             %
2554 %                                                                             %
2555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2556 %
2557 %  NTSystemCommand() executes the specified command and waits until it
2558 %  terminates.  The returned value is the exit status of the command.
2559 %
2560 %  The format of the NTSystemCommand method is:
2561 %
2562 %      int NTSystemCommand(MagickFalse,const char *command)
2563 %
2564 %  A description of each parameter follows:
2565 %
2566 %    o command: This string is the command to execute.
2567 %
2568 */
2569 MagickPrivate int NTSystemCommand(const char *command)
2570 {
2571   char
2572     local_command[MaxTextExtent];
2573
2574   DWORD
2575     child_status;
2576
2577   int
2578     status;
2579
2580   MagickBooleanType
2581     background_process;
2582
2583   PROCESS_INFORMATION
2584     process_info;
2585
2586   STARTUPINFO
2587     startup_info;
2588
2589   if (command == (char *) NULL)
2590     return(-1);
2591   GetStartupInfo(&startup_info);
2592   startup_info.dwFlags=STARTF_USESHOWWINDOW;
2593   startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
2594   (void) CopyMagickString(local_command,command,MaxTextExtent);
2595   background_process=command[strlen(command)-1] == '&' ? MagickTrue :
2596     MagickFalse;
2597   if (background_process)
2598     local_command[strlen(command)-1]='\0';
2599   if (command[strlen(command)-1] == '|')
2600      local_command[strlen(command)-1]='\0';
2601    else
2602      startup_info.wShowWindow=SW_SHOWDEFAULT;
2603   status=CreateProcess((LPCTSTR) NULL,local_command,
2604     (LPSECURITY_ATTRIBUTES) NULL,(LPSECURITY_ATTRIBUTES) NULL,(BOOL) FALSE,
2605     (DWORD) NORMAL_PRIORITY_CLASS,(LPVOID) NULL,(LPCSTR) NULL,&startup_info,
2606     &process_info);
2607   if (status == 0)
2608     return(-1);
2609   if (background_process)
2610     return(status == 0);
2611   status=WaitForSingleObject(process_info.hProcess,INFINITE);
2612   if (status != WAIT_OBJECT_0)
2613     return(status);
2614   status=GetExitCodeProcess(process_info.hProcess,&child_status);
2615   if (status == 0)
2616     return(-1);
2617   CloseHandle(process_info.hProcess);
2618   CloseHandle(process_info.hThread);
2619   return((int) child_status);
2620 }
2621 \f
2622 /*
2623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2624 %                                                                             %
2625 %                                                                             %
2626 %                                                                             %
2627 %   N T S y s t e m C o n i f i g u r a t i o n                               %
2628 %                                                                             %
2629 %                                                                             %
2630 %                                                                             %
2631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2632 %
2633 %  NTSystemConfiguration() provides a way for the application to determine
2634 %  values for system limits or options at runtime.
2635 %
2636 %  The format of the exit method is:
2637 %
2638 %      ssize_t NTSystemConfiguration(int name)
2639 %
2640 %  A description of each parameter follows:
2641 %
2642 %    o name: _SC_PAGE_SIZE or _SC_PHYS_PAGES.
2643 %
2644 */
2645 MagickPrivate ssize_t NTSystemConfiguration(int name)
2646 {
2647   switch (name)
2648   {
2649     case _SC_PAGESIZE:
2650     {
2651       SYSTEM_INFO
2652         system_info;
2653
2654       GetSystemInfo(&system_info);
2655       return(system_info.dwPageSize);
2656     }
2657     case _SC_PHYS_PAGES:
2658     {
2659       HMODULE
2660         handle;
2661
2662       LPFNDLLFUNC2
2663         module;
2664
2665       NTMEMORYSTATUSEX
2666         status;
2667
2668       SYSTEM_INFO
2669         system_info;
2670
2671       handle=GetModuleHandle("kernel32.dll");
2672       if (handle == (HMODULE) NULL)
2673         return(0L);
2674       GetSystemInfo(&system_info);
2675       module=(LPFNDLLFUNC2) NTGetLibrarySymbol(handle,"GlobalMemoryStatusEx");
2676       if (module == (LPFNDLLFUNC2) NULL)
2677         {
2678           MEMORYSTATUS
2679             status;
2680
2681           GlobalMemoryStatus(&status);
2682           return((ssize_t) status.dwTotalPhys/system_info.dwPageSize);
2683         }
2684       status.dwLength=sizeof(status);
2685       if (module(&status) == 0)
2686         return(0L);
2687       return((ssize_t) status.ullTotalPhys/system_info.dwPageSize);
2688     }
2689     case _SC_OPEN_MAX:
2690       return(2048);
2691     default:
2692       break;
2693   }
2694   return(-1);
2695 }
2696 \f
2697 /*
2698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2699 %                                                                             %
2700 %                                                                             %
2701 %                                                                             %
2702 %   N T T e l l D i r e c t o r y                                             %
2703 %                                                                             %
2704 %                                                                             %
2705 %                                                                             %
2706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2707 %
2708 %  NTTellDirectory() returns the current location associated with the named
2709 %  directory stream.
2710 %
2711 %  The format of the NTTellDirectory method is:
2712 %
2713 %      ssize_t NTTellDirectory(DIR *entry)
2714 %
2715 %  A description of each parameter follows:
2716 %
2717 %    o entry: Specifies a pointer to a DIR structure.
2718 %
2719 */
2720 MagickPrivate ssize_t NTTellDirectory(DIR *entry)
2721 {
2722   assert(entry != (DIR *) NULL);
2723   return(0);
2724 }
2725 \f
2726 /*
2727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2728 %                                                                             %
2729 %                                                                             %
2730 %                                                                             %
2731 %   N T T r u n c a t e F i l e                                               %
2732 %                                                                             %
2733 %                                                                             %
2734 %                                                                             %
2735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2736 %
2737 %  NTTruncateFile() truncates a file to a specified length.
2738 %
2739 %  The format of the NTTruncateFile method is:
2740 %
2741 %      int NTTruncateFile(int file,off_t length)
2742 %
2743 %  A description of each parameter follows:
2744 %
2745 %    o file: the file.
2746 %
2747 %    o length: the file length.
2748 %
2749 */
2750 MagickPrivate int NTTruncateFile(int file,off_t length)
2751 {
2752   DWORD
2753     file_pointer;
2754
2755   long
2756     file_handle,
2757     high,
2758     low;
2759
2760   file_handle=_get_osfhandle(file);
2761   if (file_handle == -1L)
2762     return(-1);
2763   low=(long) (length & 0xffffffffUL);
2764   high=(long) ((((MagickOffsetType) length) >> 32) & 0xffffffffUL);
2765   file_pointer=SetFilePointer((HANDLE) file_handle,low,&high,FILE_BEGIN);
2766   if ((file_pointer == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
2767     return(-1);
2768   if (SetEndOfFile((HANDLE) file_handle) == 0)
2769     return(-1);
2770   return(0);
2771 }
2772 \f
2773 /*
2774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2775 %                                                                             %
2776 %                                                                             %
2777 %                                                                             %
2778 +  N T U n m a p M e m o r y                                                  %
2779 %                                                                             %
2780 %                                                                             %
2781 %                                                                             %
2782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2783 %
2784 %  NTUnmapMemory() emulates the Unix munmap method.
2785 %
2786 %  The format of the NTUnmapMemory method is:
2787 %
2788 %      int NTUnmapMemory(void *map,size_t length)
2789 %
2790 %  A description of each parameter follows:
2791 %
2792 %    o map: the address of the binary large object.
2793 %
2794 %    o length: the length of the binary large object.
2795 %
2796 */
2797 MagickPrivate int NTUnmapMemory(void *map,size_t length)
2798 {
2799   (void) length;
2800   if (UnmapViewOfFile(map) == 0)
2801     return(-1);
2802   return(0);
2803 }
2804 \f
2805 /*
2806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2807 %                                                                             %
2808 %                                                                             %
2809 %                                                                             %
2810 %   N T U s e r T i m e                                                       %
2811 %                                                                             %
2812 %                                                                             %
2813 %                                                                             %
2814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2815 %
2816 %  NTUserTime() returns the total time the process has been scheduled (e.g.
2817 %  seconds) since the last call to StartTimer().
2818 %
2819 %  The format of the UserTime method is:
2820 %
2821 %      double NTUserTime(void)
2822 %
2823 */
2824 MagickPrivate double NTUserTime(void)
2825 {
2826   DWORD
2827     status;
2828
2829   FILETIME
2830     create_time,
2831     exit_time;
2832
2833   OSVERSIONINFO
2834     OsVersionInfo;
2835
2836   union
2837   {
2838     FILETIME
2839       filetime;
2840
2841     __int64
2842       filetime64;
2843   } kernel_time;
2844
2845   union
2846   {
2847     FILETIME
2848       filetime;
2849
2850     __int64
2851       filetime64;
2852   } user_time;
2853
2854   OsVersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
2855   GetVersionEx(&OsVersionInfo);
2856   if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
2857     return(NTElapsedTime());
2858   status=GetProcessTimes(GetCurrentProcess(),&create_time,&exit_time,
2859     &kernel_time.filetime,&user_time.filetime);
2860   if (status != TRUE)
2861     return(0.0);
2862   return((double) 1.0e-7*(kernel_time.filetime64+user_time.filetime64));
2863 }
2864 \f
2865 /*
2866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2867 %                                                                             %
2868 %                                                                             %
2869 %                                                                             %
2870 %   N T W a r n i n g H a n d l e r                                           %
2871 %                                                                             %
2872 %                                                                             %
2873 %                                                                             %
2874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2875 %
2876 %  NTWarningHandler() displays a warning reason.
2877 %
2878 %  The format of the NTWarningHandler method is:
2879 %
2880 %      void NTWarningHandler(const ExceptionType severity,const char *reason,
2881 %        const char *description)
2882 %
2883 %  A description of each parameter follows:
2884 %
2885 %    o severity: Specifies the numeric warning category.
2886 %
2887 %    o reason: Specifies the reason to display before terminating the
2888 %      program.
2889 %
2890 %    o description: Specifies any description to the reason.
2891 %
2892 */
2893 MagickExport void NTWarningHandler(const ExceptionType severity,
2894   const char *reason,const char *description)
2895 {
2896   char
2897     buffer[2*MaxTextExtent];
2898
2899   (void) severity;
2900   if (reason == (char *) NULL)
2901     return;
2902   if (description == (char *) NULL)
2903     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
2904       reason);
2905   else
2906     (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
2907       GetClientName(),reason,description);
2908   (void) MessageBox(NULL,buffer,"ImageMagick Warning",MB_OK | MB_TASKMODAL |
2909     MB_SETFOREGROUND | MB_ICONINFORMATION);
2910 }
2911 #endif