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