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