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