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