MagickCore 7.1.1
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/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38/*
39 Include declarations.
40*/
41#include "MagickCore/studio.h"
42#if defined(MAGICKCORE_WINDOWS_SUPPORT)
43#include "MagickCore/client.h"
44#include "MagickCore/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=(ssize_t) (time / 1000000);
410 time_value->tv_usec=(ssize_t) (time % 1000000);
411 }
412 if (time_zone != (struct timezone *) NULL)
413 {
414 if (is_tz_set == 0)
415 {
416 _tzset();
417 is_tz_set++;
418 }
419 time_zone->tz_minuteswest=_timezone/60;
420 time_zone->tz_dsttime=_daylight;
421 }
422 return(0);
423}
424#endif
425
426/*
427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428% %
429% %
430% %
431% N T A r g v T o U T F 8 %
432% %
433% %
434% %
435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
436%
437% NTArgvToUTF8() converts the wide command line arguments to UTF-8 to ensure
438% compatibility with Linux.
439%
440% The format of the NTArgvToUTF8 method is:
441%
442% char **NTArgvToUTF8(const int argc,wchar_t **argv)
443%
444% A description of each parameter follows:
445%
446% o argc: the number of command line arguments.
447%
448% o argv: the wide-character command line arguments.
449%
450*/
451MagickPrivate char **NTArgvToUTF8(const int argc,wchar_t **argv)
452{
453 char
454 **utf8;
455
456 ssize_t
457 i;
458
459 utf8=(char **) NTAcquireQuantumMemory(argc,sizeof(*utf8));
460 if (utf8 == (char **) NULL)
461 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertStringToARGV");
462 for (i=0; i < (ssize_t) argc; i++)
463 {
464 utf8[i]=create_utf8_string(argv[i]);
465 if (utf8[i] == (char *) NULL)
466 {
467 for (i--; i >= 0; i--)
468 utf8[i]=DestroyString(utf8[i]);
469 ThrowFatalException(ResourceLimitFatalError,
470 "UnableToConvertStringToARGV");
471 }
472 }
473 return(utf8);
474}
475
476/*
477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478% %
479% %
480% %
481% N T C l o s e D i r e c t o r y %
482% %
483% %
484% %
485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486%
487% NTCloseDirectory() closes the named directory stream and frees the DIR
488% structure.
489%
490% The format of the NTCloseDirectory method is:
491%
492% int NTCloseDirectory(DIR *entry)
493%
494% A description of each parameter follows:
495%
496% o entry: Specifies a pointer to a DIR structure.
497%
498*/
499MagickPrivate int NTCloseDirectory(DIR *entry)
500{
501 assert(entry != (DIR *) NULL);
502 if (IsEventLogging() != MagickFalse)
503 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
504 FindClose(entry->hSearch);
505 entry=(DIR *) RelinquishMagickMemory(entry);
506 return(0);
507}
508/*
509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510% %
511% %
512% %
513% N T C l o s e L i b r a r y %
514% %
515% %
516% %
517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518%
519% NTCloseLibrary() unloads the module associated with the passed handle.
520%
521% The format of the NTCloseLibrary method is:
522%
523% void NTCloseLibrary(void *handle)
524%
525% A description of each parameter follows:
526%
527% o handle: Specifies a handle to a previously loaded dynamic module.
528%
529*/
530MagickPrivate int NTCloseLibrary(void *handle)
531{
532 return(!(FreeLibrary((HINSTANCE) handle)));
533}
534
535
536/*
537%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
538% %
539% %
540% %
541% N T E l a p s e d T i m e %
542% %
543% %
544% %
545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546%
547% NTElapsedTime() returns the elapsed time (in seconds) since the last call to
548% StartTimer().
549%
550% The format of the ElapsedTime method is:
551%
552% double NTElapsedTime(void)
553%
554*/
555MagickPrivate double NTElapsedTime(void)
556{
557 union
558 {
559 FILETIME
560 filetime;
561
562 __int64
563 filetime64;
564 } elapsed_time;
565
566 LARGE_INTEGER
567 performance_count;
568
569 static LARGE_INTEGER
570 frequency = { 0 };
571
572 SYSTEMTIME
573 system_time;
574
575 if (frequency.QuadPart == 0)
576 {
577 if (QueryPerformanceFrequency(&frequency) == 0)
578 frequency.QuadPart=1;
579 }
580 if (frequency.QuadPart > 1)
581 {
582 QueryPerformanceCounter(&performance_count);
583 return((double) performance_count.QuadPart/frequency.QuadPart);
584 }
585 GetSystemTime(&system_time);
586 SystemTimeToFileTime(&system_time,&elapsed_time.filetime);
587 return((double) 1.0e-7*elapsed_time.filetime64);
588}
589
590/*
591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592% %
593% %
594% %
595% N T E r f %
596% %
597% %
598% %
599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
600%
601% NTErf() computes the error function of x.
602%
603% The format of the NTErf method is:
604%
605% double NTErf(double x)
606%
607% A description of each parameter follows:
608%
609% o x: The value to compute the error function for.
610%
611*/
612MagickPrivate double NTErf(double x)
613{
614 double
615 a1,
616 a2,
617 a3,
618 a4,
619 a5,
620 p,
621 t,
622 y;
623
624 int
625 sign;
626
627 a1=0.254829592;
628 a2=-0.284496736;
629 a3=1.421413741;
630 a4=-1.453152027;
631 a5=1.061405429;
632 p=0.3275911;
633 sign=x < 0 ? -1 : 1;
634 x=fabs(x);
635 t=1.0/(1.0+p*x);
636 y=1.0-(((((a5*t+a4)*t)+a3)*t+a2)*t+a1)*t*exp(-x*x);
637 return(sign*y);
638}
639
640
641/*
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643% %
644% %
645% %
646+ N T E r r o r H a n d l e r %
647% %
648% %
649% %
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651%
652% NTErrorHandler() displays an error reason and then terminates the program.
653%
654% The format of the NTErrorHandler method is:
655%
656% void NTErrorHandler(const ExceptionType severity,const char *reason,
657% const char *description)
658%
659% A description of each parameter follows:
660%
661% o severity: Specifies the numeric error category.
662%
663% o reason: Specifies the reason to display before terminating the
664% program.
665%
666% o description: Specifies any description to the reason.
667%
668*/
669MagickPrivate void NTErrorHandler(const ExceptionType severity,
670 const char *reason,const char *description)
671{
672 char
673 buffer[3*MagickPathExtent],
674 *message;
675
676 (void) severity;
677 if (reason == (char *) NULL)
678 {
679 MagickCoreTerminus();
680 exit(0);
681 }
682 message=GetExceptionMessage(errno);
683 if ((description != (char *) NULL) && errno)
684 (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s) [%s].\n",
685 GetClientName(),reason,description,message);
686 else
687 if (description != (char *) NULL)
688 (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s).\n",
689 GetClientName(),reason,description);
690 else
691 if (errno != 0)
692 (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s [%s].\n",
693 GetClientName(),reason,message);
694 else
695 (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s.\n",
696 GetClientName(),reason);
697 message=DestroyString(message);
698 (void) MessageBox(NULL,buffer,"ImageMagick Exception",MB_OK | MB_TASKMODAL |
699 MB_SETFOREGROUND | MB_ICONEXCLAMATION);
700 MagickCoreTerminus();
701 exit(0);
702}
703
704/*
705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706% %
707% %
708% %
709% N T G a t h e r R a n d o m D a t a %
710% %
711% %
712% %
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714%
715% NTGatherRandomData() gathers random data and returns it.
716%
717% The format of the GatherRandomData method is:
718%
719% MagickBooleanType NTGatherRandomData(const size_t length,
720% unsigned char *random)
721%
722% A description of each parameter follows:
723%
724% length: the length of random data buffer
725%
726% random: the random data is returned here.
727%
728*/
729MagickPrivate MagickBooleanType NTGatherRandomData(const size_t length,
730 unsigned char *random)
731{
732#if defined(MAGICKCORE_CIPHER_SUPPORT) && defined(_MSC_VER)
733 HCRYPTPROV
734 handle;
735
736 int
737 status;
738
739 handle=(HCRYPTPROV) NULL;
740 status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
741 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET));
742 if (status == 0)
743 status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
744 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET));
745 if (status == 0)
746 return(MagickFalse);
747 status=CryptGenRandom(handle,(DWORD) length,random);
748 if (status == 0)
749 {
750 status=CryptReleaseContext(handle,0);
751 return(MagickFalse);
752 }
753 status=CryptReleaseContext(handle,0);
754 if (status == 0)
755 return(MagickFalse);
756#else
757 (void) random;
758 (void) length;
759#endif
760 return(MagickTrue);
761}
762
763/*
764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
765% %
766% %
767% %
768% N T G e t E n v i r o n m e n t V a l u e %
769% %
770% %
771% %
772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
773%
774% NTGetEnvironmentValue() returns the environment string that matches the
775% specified name.
776%
777% The format of the NTGetEnvironmentValue method is:
778%
779% char *GetEnvironmentValue(const char *name)
780%
781% A description of each parameter follows:
782%
783% o name: the environment name.
784%
785*/
786extern MagickPrivate char *NTGetEnvironmentValue(const char *name)
787{
788 char
789 *environment = (char *) NULL;
790
791 DWORD
792 size;
793
794 LPWSTR
795 wide;
796
797 wchar_t
798 wide_name[MaxWideByteExtent];
799
800 if (MultiByteToWideChar(CP_UTF8,0,name,-1,wide_name,MaxWideByteExtent) == 0)
801 return(environment);
802 size=GetEnvironmentVariableW(wide_name,(LPWSTR) NULL,0);
803 if (size == 0)
804 return(environment);
805 wide=(LPWSTR) NTAcquireQuantumMemory((const size_t) size,sizeof(*wide));
806 if (wide == (LPWSTR) NULL)
807 return(environment);
808 if (GetEnvironmentVariableW(wide_name,wide,size) != 0)
809 environment=create_utf8_string(wide);
810 wide=(LPWSTR) RelinquishMagickMemory(wide);
811 return(environment);
812}
813
814/*
815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
816% %
817% %
818% %
819% N T G e t E x e c u t i o n P a t h %
820% %
821% %
822% %
823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824%
825% NTGetExecutionPath() returns the execution path of a program.
826%
827% The format of the GetExecutionPath method is:
828%
829% MagickBooleanType NTGetExecutionPath(char *path,const size_t extent)
830%
831% A description of each parameter follows:
832%
833% o path: the pathname of the executable that started the process.
834%
835% o extent: the maximum extent of the path.
836%
837*/
838MagickPrivate MagickBooleanType NTGetExecutionPath(char *path,
839 const size_t extent)
840{
841 wchar_t
842 wide_path[MagickPathExtent];
843
844 (void) GetModuleFileNameW((HMODULE) NULL,wide_path,(DWORD) extent);
845 (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,
846 NULL);
847 return(MagickTrue);
848}
849
850/*
851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852% %
853% %
854% %
855% N T G e t L a s t E r r o r M e s s a g e %
856% %
857% %
858% %
859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860%
861% NTGetLastErrorMessage() returns the last error that occurred.
862%
863% The format of the NTGetLastErrorMessage method is:
864%
865% char *NTGetLastErrorMessage(DWORD last_error)
866%
867% A description of each parameter follows:
868%
869% o last_error: The value of GetLastError.
870%
871*/
872static char *NTGetLastErrorMessage(DWORD last_error)
873{
874 char
875 *reason;
876
877 int
878 status;
879
880 LPVOID
881 buffer = (LPVOID) NULL;
882
883 status=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
884 FORMAT_MESSAGE_FROM_SYSTEM,NULL,last_error,
885 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR) &buffer,0,NULL);
886 if (!status)
887 reason=AcquireString("An unknown error occurred");
888 else
889 {
890 reason=AcquireString((const char *) buffer);
891 LocalFree(buffer);
892 }
893 return(reason);
894}
895
896/*
897%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
898% %
899% %
900% %
901% N T G e t L i b r a r y E r r o r %
902% %
903% %
904% %
905%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
906%
907% Lt_dlerror() returns a pointer to a string describing the last error
908% associated with a lt_dl method. Note that this function is not thread
909% safe so it should only be used under the protection of a lock.
910%
911% The format of the NTGetLibraryError method is:
912%
913% const char *NTGetLibraryError(void)
914%
915*/
916MagickPrivate const char *NTGetLibraryError(void)
917{
918 static char
919 last_error[MagickPathExtent];
920
921 char
922 *error;
923
924 *last_error='\0';
925 error=NTGetLastErrorMessage(GetLastError());
926 if (error)
927 (void) CopyMagickString(last_error,error,MagickPathExtent);
928 error=DestroyString(error);
929 return(last_error);
930}
931
932/*
933%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934% %
935% %
936% %
937% N T G e t L i b r a r y S y m b o l %
938% %
939% %
940% %
941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942%
943% NTGetLibrarySymbol() retrieve the procedure address of the method
944% specified by the passed character string.
945%
946% The format of the NTGetLibrarySymbol method is:
947%
948% void *NTGetLibrarySymbol(void *handle,const char *name)
949%
950% A description of each parameter follows:
951%
952% o handle: Specifies a handle to the previously loaded dynamic module.
953%
954% o name: Specifies the procedure entry point to be returned.
955%
956*/
957void *NTGetLibrarySymbol(void *handle,const char *name)
958{
959 FARPROC
960 proc_address;
961
962 proc_address=GetProcAddress((HMODULE) handle,(LPCSTR) name);
963 if (proc_address == (FARPROC) NULL)
964 return((void *) NULL);
965 return((void *) proc_address);
966}
967
968
969/*
970%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971% %
972% %
973% %
974% N T G e t M o d u l e P a t h %
975% %
976% %
977% %
978%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979%
980% NTGetModulePath() returns the path of the specified module.
981%
982% The format of the GetModulePath method is:
983%
984% MagickBooleanType NTGetModulePath(const char *module,char *path)
985%
986% A description of each parameter follows:
987%
988% modith: the module name.
989%
990% path: the module path is returned here.
991%
992*/
993MagickPrivate MagickBooleanType NTGetModulePath(const char *module,char *path)
994{
995 char
996 module_path[MagickPathExtent];
997
998 HMODULE
999 handle;
1000
1001 ssize_t
1002 length;
1003
1004 *path='\0';
1005 handle=GetModuleHandle(module);
1006 if (handle == (HMODULE) NULL)
1007 return(MagickFalse);
1008 length=GetModuleFileName(handle,module_path,MagickPathExtent);
1009 if (length != 0)
1010 GetPathComponent(module_path,HeadPath,path);
1011 return(MagickTrue);
1012}
1013
1014/*
1015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016% %
1017% %
1018% %
1019% N T G h o s t s c r i p t D L L V e c t o r s %
1020% %
1021% %
1022% %
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024%
1025% NTGhostscriptDLLVectors() returns a GhostInfo structure that includes
1026% function vectors to invoke Ghostscript DLL functions. A null pointer is
1027% returned if there is an error when loading the DLL or retrieving the
1028% function vectors.
1029%
1030% The format of the NTGhostscriptDLLVectors method is:
1031%
1032% const GhostInfo *NTGhostscriptDLLVectors(void)
1033%
1034*/
1035static int NTLocateGhostscript(DWORD flags,int *root_index,
1036 const char **product_family,int *major_version,int *minor_version,
1037 int *patch_version)
1038{
1039 int
1040 i;
1041
1042 MagickBooleanType
1043 status;
1044
1045 static const char
1046 *products[2] =
1047 {
1048 "Artifex Ghostscript",
1049 "GPL Ghostscript"
1050 };
1051
1052 /*
1053 Find the most recent version of Ghostscript.
1054 */
1055 status=MagickFalse;
1056 *root_index=0;
1057 *product_family=NULL;
1058 *major_version=5;
1059 *minor_version=49; /* min version of Ghostscript is 5.50 */
1060 for (i=0; i < (ssize_t) (sizeof(products)/sizeof(products[0])); i++)
1061 {
1062 char
1063 key[MagickPathExtent];
1064
1065 HKEY
1066 hkey;
1067
1068 int
1069 j;
1070
1071 REGSAM
1072 mode;
1073
1074 (void) FormatLocaleString(key,MagickPathExtent,"SOFTWARE\\%s",products[i]);
1075 for (j=0; j < (ssize_t) (sizeof(registry_roots)/sizeof(registry_roots[0]));
1076 j++)
1077 {
1078 mode=KEY_READ | flags;
1079 if (RegOpenKeyExA(registry_roots[j].hkey,key,0,mode,&hkey) ==
1080 ERROR_SUCCESS)
1081 {
1082 DWORD
1083 extent;
1084
1085 int
1086 k;
1087
1088 /*
1089 Now enumerate the keys.
1090 */
1091 extent=sizeof(key)/sizeof(char);
1092 for (k=0; RegEnumKeyA(hkey,k,key,extent) == ERROR_SUCCESS; k++)
1093 {
1094 int
1095 major,
1096 minor,
1097 patch;
1098
1099 major=0;
1100 minor=0;
1101 patch=0;
1102 if (sscanf(key,"%d.%d.%d",&major,&minor,&patch) != 3)
1103 if (sscanf(key,"%d.%d",&major,&minor) != 2)
1104 continue;
1105 if ((major > *major_version) ||
1106 ((major == *major_version) && (minor > *minor_version)) ||
1107 ((minor == *minor_version) && (patch > *patch_version)))
1108 {
1109 *root_index=j;
1110 *product_family=products[i];
1111 *major_version=major;
1112 *minor_version=minor;
1113 *patch_version=patch;
1114 status=MagickTrue;
1115 }
1116 }
1117 (void) RegCloseKey(hkey);
1118 }
1119 }
1120 }
1121 if (status == MagickFalse)
1122 {
1123 *major_version=0;
1124 *minor_version=0;
1125 *patch_version=0;
1126 }
1127 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"Ghostscript (%s) "
1128 "version %d.%d.%d",*product_family,*major_version,*minor_version,*patch_version);
1129 return(status);
1130}
1131
1132static MagickBooleanType NTGhostscriptGetString(const char *name,
1133 BOOL *is_64_bit,char *value,const size_t length)
1134{
1135 char
1136 buffer[MagickPathExtent],
1137 *directory;
1138
1139 static const char
1140 *product_family = (const char *) NULL;
1141
1142 static BOOL
1143 is_64_bit_version = FALSE;
1144
1145 static int
1146 flags = 0,
1147 major_version = 0,
1148 minor_version = 0,
1149 patch_version = 0,
1150 root_index = 0;
1151
1152 unsigned char
1153 *registry_value;
1154
1155 /*
1156 Get a string from the installed Ghostscript.
1157 */
1158 *value='\0';
1159 directory=(char *) NULL;
1160 if (LocaleCompare(name,"GS_DLL") == 0)
1161 {
1162 directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_PATH");
1163 if (directory != (char *) NULL)
1164 {
1165 (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll64.dll",
1166 directory,DirectorySeparator);
1167 if (IsPathAccessible(buffer) != MagickFalse)
1168 {
1169 directory=DestroyString(directory);
1170 (void) CopyMagickString(value,buffer,length);
1171 if (is_64_bit != NULL)
1172 *is_64_bit=TRUE;
1173 return(MagickTrue);
1174 }
1175 (void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll32.dll",
1176 directory,DirectorySeparator);
1177 if (IsPathAccessible(buffer) != MagickFalse)
1178 {
1179 directory=DestroyString(directory);
1180 (void) CopyMagickString(value,buffer,length);
1181 if (is_64_bit != NULL)
1182 *is_64_bit=FALSE;
1183 return(MagickTrue);
1184 }
1185 return(MagickFalse);
1186 }
1187 }
1188 if (product_family == (const char *) NULL)
1189 {
1190 flags=0;
1191#if defined(KEY_WOW64_32KEY)
1192#if defined(_WIN64)
1193 flags=KEY_WOW64_64KEY;
1194#else
1195 flags=KEY_WOW64_32KEY;
1196#endif
1197 (void) NTLocateGhostscript(flags,&root_index,&product_family,
1198 &major_version,&minor_version,&patch_version);
1199 if (product_family == (const char *) NULL)
1200#if defined(_WIN64)
1201 flags=KEY_WOW64_32KEY;
1202 else
1203 is_64_bit_version=TRUE;
1204#else
1205 flags=KEY_WOW64_64KEY;
1206#endif
1207#endif
1208 }
1209 if (product_family == (const char *) NULL)
1210 {
1211 (void) NTLocateGhostscript(flags,&root_index,&product_family,
1212 &major_version,&minor_version,&patch_version);
1213#if !defined(_WIN64)
1214 is_64_bit_version=TRUE;
1215#endif
1216 }
1217 if (product_family == (const char *) NULL)
1218 return(MagickFalse);
1219 if (is_64_bit != NULL)
1220 *is_64_bit=is_64_bit_version;
1221 (void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%.2d.%d",
1222 product_family,major_version,minor_version,patch_version);
1223 registry_value=NTGetRegistryValue(registry_roots[root_index].hkey,buffer,
1224 flags,name);
1225 if (registry_value == (unsigned char *) NULL)
1226 {
1227 (void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%02d",
1228 product_family,major_version,minor_version);
1229 registry_value=NTGetRegistryValue(registry_roots[root_index].hkey,buffer,
1230 flags,name);
1231 }
1232 if (registry_value == (unsigned char *) NULL)
1233 return(MagickFalse);
1234 (void) CopyMagickString(value,(const char *) registry_value,length);
1235 registry_value=(unsigned char *) RelinquishMagickMemory(registry_value);
1236 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1237 "registry: \"%s\\%s\\%s\"=\"%s\"",registry_roots[root_index].name,
1238 buffer,name,value);
1239 return(MagickTrue);
1240}
1241
1242static MagickBooleanType NTGhostscriptDLL(char *path,int length)
1243{
1244 static char
1245 dll[MagickPathExtent] = { "" };
1246
1247 static BOOL
1248 is_64_bit;
1249
1250 *path='\0';
1251 if ((*dll == '\0') &&
1252 (NTGhostscriptGetString("GS_DLL",&is_64_bit,dll,sizeof(dll)) != MagickTrue))
1253 return(MagickFalse);
1254#if defined(_WIN64)
1255 if (!is_64_bit)
1256 return(MagickFalse);
1257#else
1258 if (is_64_bit)
1259 return(MagickFalse);
1260#endif
1261 (void) CopyMagickString(path,dll,length);
1262 return(MagickTrue);
1263}
1264
1265static inline MagickBooleanType NTGhostscriptHasValidHandle()
1266{
1267 if ((nt_ghost_info.delete_instance == NULL) || (ghost_info.exit == NULL) ||
1268 (nt_ghost_info.new_instance == NULL) || (ghost_info.set_stdio == NULL) ||
1269 (ghost_info.init_with_args == NULL) || (ghost_info.revision == NULL))
1270 return(MagickFalse);
1271 return(MagickTrue);
1272}
1273
1274MagickPrivate const GhostInfo *NTGhostscriptDLLVectors(void)
1275{
1276 char
1277 path[MagickPathExtent];
1278
1279 if (ghost_semaphore == (SemaphoreInfo *) NULL)
1280 ActivateSemaphoreInfo(&ghost_semaphore);
1281 LockSemaphoreInfo(ghost_semaphore);
1282 if (ghost_handle != (void *) NULL)
1283 {
1284 UnlockSemaphoreInfo(ghost_semaphore);
1285 if (NTGhostscriptHasValidHandle() == MagickTrue)
1286 return(&ghost_info);
1287 return((GhostInfo *) NULL);
1288 }
1289 if (NTGhostscriptDLL(path,sizeof(path)) != MagickTrue)
1290 {
1291 UnlockSemaphoreInfo(ghost_semaphore);
1292 return((GhostInfo *) NULL);
1293 }
1294 ghost_handle=lt_dlopen(path);
1295 if (ghost_handle == (void *) NULL)
1296 {
1297 UnlockSemaphoreInfo(ghost_semaphore);
1298 return((GhostInfo *) NULL);
1299 }
1300 (void) memset((void *) &nt_ghost_info,0,sizeof(NTGhostInfo));
1301 nt_ghost_info.delete_instance=(void (MagickDLLCall *)(gs_main_instance *)) (
1302 lt_dlsym(ghost_handle,"gsapi_delete_instance"));
1303 nt_ghost_info.new_instance=(int (MagickDLLCall *)(gs_main_instance **,
1304 void *)) (lt_dlsym(ghost_handle,"gsapi_new_instance"));
1305 nt_ghost_info.has_instance=MagickFalse;
1306 (void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
1307 ghost_info.delete_instance=NTGhostscriptDeleteInstance;
1308 ghost_info.exit=(int (MagickDLLCall *)(gs_main_instance*))
1309 lt_dlsym(ghost_handle,"gsapi_exit");
1310 ghost_info.init_with_args=(int (MagickDLLCall *)(gs_main_instance *,int,
1311 char **)) (lt_dlsym(ghost_handle,"gsapi_init_with_args"));
1312 ghost_info.new_instance=NTGhostscriptNewInstance;
1313 ghost_info.run_string=(int (MagickDLLCall *)(gs_main_instance *,const char *,
1314 int,int *)) (lt_dlsym(ghost_handle,"gsapi_run_string"));
1315 ghost_info.set_arg_encoding=(int (MagickDLLCall*)(gs_main_instance*, int)) (
1316 lt_dlsym(ghost_handle, "gsapi_set_arg_encoding"));
1317 ghost_info.set_stdio=(int (MagickDLLCall *)(gs_main_instance *,int(
1318 MagickDLLCall *)(void *,char *,int),int(MagickDLLCall *)(void *,
1319 const char *,int),int(MagickDLLCall *)(void *,const char *,int)))
1320 (lt_dlsym(ghost_handle,"gsapi_set_stdio"));
1321 ghost_info.revision=(int (MagickDLLCall *)(gsapi_revision_t *,int)) (
1322 lt_dlsym(ghost_handle,"gsapi_revision"));
1323 UnlockSemaphoreInfo(ghost_semaphore);
1324 if (NTGhostscriptHasValidHandle() == MagickTrue)
1325 return(&ghost_info);
1326 return((GhostInfo *) NULL);
1327}
1328
1329/*
1330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331% %
1332% %
1333% %
1334% N T G h o s t s c r i p t E X E %
1335% %
1336% %
1337% %
1338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1339%
1340% NTGhostscriptEXE() obtains the path to the latest Ghostscript executable.
1341% The method returns FALSE if a full path value is not obtained and returns
1342% a default path of gswin32c.exe.
1343%
1344% The format of the NTGhostscriptEXE method is:
1345%
1346% void NTGhostscriptEXE(char *path,int length)
1347%
1348% A description of each parameter follows:
1349%
1350% o path: return the Ghostscript executable path here.
1351%
1352% o length: length of buffer.
1353%
1354*/
1355MagickPrivate void NTGhostscriptEXE(char *path,int length)
1356{
1357 char
1358 *p;
1359
1360 static char
1361 program[MagickPathExtent] = { "" };
1362
1363 static BOOL
1364 is_64_bit_version = FALSE;
1365
1366 if (*program == '\0')
1367 {
1368 if (ghost_semaphore == (SemaphoreInfo *) NULL)
1369 ActivateSemaphoreInfo(&ghost_semaphore);
1370 LockSemaphoreInfo(ghost_semaphore);
1371 if (*program == '\0')
1372 {
1373 if (NTGhostscriptGetString("GS_DLL",&is_64_bit_version,program,
1374 sizeof(program)) == MagickFalse)
1375 {
1376 UnlockSemaphoreInfo(ghost_semaphore);
1377#if defined(_WIN64)
1378 (void) CopyMagickString(program,"gswin64c.exe",sizeof(program));
1379#else
1380 (void) CopyMagickString(program,"gswin32c.exe",sizeof(program));
1381#endif
1382 (void) CopyMagickString(path,program,length);
1383 return;
1384 }
1385 p=strrchr(program,'\\');
1386 if (p != (char *) NULL)
1387 {
1388 p++;
1389 *p='\0';
1390 (void) ConcatenateMagickString(program,is_64_bit_version ?
1391 "gswin64c.exe" : "gswin32c.exe",sizeof(program));
1392 }
1393 }
1394 UnlockSemaphoreInfo(ghost_semaphore);
1395 }
1396 (void) CopyMagickString(path,program,length);
1397}
1398
1399/*
1400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1401% %
1402% %
1403% %
1404% N T G h o s t s c r i p t F o n t s %
1405% %
1406% %
1407% %
1408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1409%
1410% NTGhostscriptFonts() obtains the path to the Ghostscript fonts. The method
1411% returns false if it cannot determine the font path.
1412%
1413% The format of the NTGhostscriptFonts method is:
1414%
1415% MagickBooleanType NTGhostscriptFonts(char *path,int length)
1416%
1417% A description of each parameter follows:
1418%
1419% o path: return the font path here.
1420%
1421% o length: length of the path buffer.
1422%
1423*/
1424MagickPrivate MagickBooleanType NTGhostscriptFonts(char *path,int length)
1425{
1426 char
1427 buffer[MagickPathExtent],
1428 *directory,
1429 filename[MagickPathExtent];
1430
1431 char
1432 *p,
1433 *q;
1434
1435 *path='\0';
1436 directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_FONT_PATH");
1437 if (directory != (char *) NULL)
1438 {
1439 (void) CopyMagickString(buffer,directory,MagickPathExtent);
1440 directory=DestroyString(directory);
1441 }
1442 else
1443 {
1444 if (NTGhostscriptGetString("GS_LIB",NULL,buffer,
1445 MagickPathExtent) == MagickFalse)
1446 return(MagickFalse);
1447 }
1448 for (p=buffer-1; p != (char *) NULL; p=strchr(p+1,DirectoryListSeparator))
1449 {
1450 (void) CopyMagickString(path,p+1,length+1);
1451 q=strchr(path,DirectoryListSeparator);
1452 if (q != (char *) NULL)
1453 *q='\0';
1454 (void) FormatLocaleString(filename,MagickPathExtent,"%s%sfonts.dir",path,
1455 DirectorySeparator);
1456 if (IsPathAccessible(filename) != MagickFalse)
1457 return(MagickTrue);
1458 (void) FormatLocaleString(filename,MagickPathExtent,"%s%sn019003l.pfb",path,
1459 DirectorySeparator);
1460 if (IsPathAccessible(filename) != MagickFalse)
1461 return(MagickTrue);
1462 }
1463 *path='\0';
1464 return(MagickFalse);
1465}
1466
1467/*
1468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469% %
1470% %
1471% %
1472% N T G h o s t s c r i p t U n L o a d D L L %
1473% %
1474% %
1475% %
1476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1477%
1478% NTGhostscriptUnLoadDLL() unloads the Ghostscript DLL and returns TRUE if
1479% it succeeds.
1480%
1481% The format of the NTGhostscriptUnLoadDLL method is:
1482%
1483% int NTGhostscriptUnLoadDLL(void)
1484%
1485*/
1486MagickPrivate void NTGhostscriptUnLoadDLL(void)
1487{
1488 if (ghost_semaphore == (SemaphoreInfo *) NULL)
1489 ActivateSemaphoreInfo(&ghost_semaphore);
1490 LockSemaphoreInfo(ghost_semaphore);
1491 if (ghost_handle != (void *) NULL)
1492 {
1493 (void) lt_dlclose(ghost_handle);
1494 ghost_handle=(void *) NULL;
1495 (void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
1496 }
1497 UnlockSemaphoreInfo(ghost_semaphore);
1498 RelinquishSemaphoreInfo(&ghost_semaphore);
1499}
1500
1501/*
1502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1503% %
1504% %
1505% %
1506% N T L o n g P a t h s E n a b l e d %
1507% %
1508% %
1509% %
1510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1511%
1512% NTLongPathsEnabled() returns a boolean indicating whether long paths are
1513$ enabled.
1514%
1515% The format of the NTLongPathsEnabled method is:
1516%
1517% MagickBooleanType NTLongPathsEnabled()
1518%
1519*/
1520MagickExport MagickBooleanType NTLongPathsEnabled()
1521{
1522 static size_t
1523 long_paths_enabled = 2;
1524
1525 if (long_paths_enabled == 2)
1526 {
1527 DWORD
1528 size,
1529 type,
1530 value;
1531
1532 HKEY
1533 registry_key;
1534
1535 LONG
1536 status;
1537
1538 registry_key=(HKEY) INVALID_HANDLE_VALUE;
1539 status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1540 "SYSTEM\\CurrentControlSet\\Control\\FileSystem",0,KEY_READ,
1541 &registry_key);
1542 if (status != ERROR_SUCCESS)
1543 {
1544 RegCloseKey(registry_key);
1545 long_paths_enabled=0;
1546 return(MagickFalse);
1547 }
1548 value=0;
1549 status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,NULL,
1550 NULL);
1551 if ((status != ERROR_SUCCESS) || (type != REG_DWORD))
1552 {
1553 RegCloseKey(registry_key);
1554 long_paths_enabled=0;
1555 return(MagickFalse);
1556 }
1557 size=0;
1558 status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,
1559 (LPBYTE) &value,&size);
1560 RegCloseKey(registry_key);
1561 if (status != ERROR_SUCCESS)
1562 {
1563 long_paths_enabled=0;
1564 return(MagickFalse);
1565 }
1566 long_paths_enabled=(size_t) value;
1567 }
1568 return(long_paths_enabled == 1 ? MagickTrue : MagickFalse);
1569}
1570
1571/*
1572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573% %
1574% %
1575% %
1576+ N T M a p M e m o r y %
1577% %
1578% %
1579% %
1580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1581%
1582% Mmap() emulates the Unix method of the same name.
1583%
1584% The format of the NTMapMemory method is:
1585%
1586% MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1587% int access,int file,MagickOffsetType offset)
1588%
1589*/
1590MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
1591 int flags,int file,MagickOffsetType offset)
1592{
1593 DWORD
1594 access_mode,
1595 high_length,
1596 high_offset,
1597 low_length,
1598 low_offset,
1599 protection_mode;
1600
1601 HANDLE
1602 file_handle,
1603 map_handle;
1604
1605 void
1606 *map;
1607
1608 (void) address;
1609 access_mode=0;
1610 file_handle=INVALID_HANDLE_VALUE;
1611 low_length=(DWORD) (length & 0xFFFFFFFFUL);
1612 high_length=(DWORD) ((((MagickOffsetType) length) >> 32) & 0xFFFFFFFFUL);
1613 map_handle=INVALID_HANDLE_VALUE;
1614 map=(void *) NULL;
1615 low_offset=(DWORD) (offset & 0xFFFFFFFFUL);
1616 high_offset=(DWORD) ((offset >> 32) & 0xFFFFFFFFUL);
1617 protection_mode=0;
1618 if (protection & PROT_WRITE)
1619 {
1620 access_mode=FILE_MAP_WRITE;
1621 if (!(flags & MAP_PRIVATE))
1622 protection_mode=PAGE_READWRITE;
1623 else
1624 {
1625 access_mode=FILE_MAP_COPY;
1626 protection_mode=PAGE_WRITECOPY;
1627 }
1628 }
1629 else
1630 if (protection & PROT_READ)
1631 {
1632 access_mode=FILE_MAP_READ;
1633 protection_mode=PAGE_READONLY;
1634 }
1635 if ((file == -1) && (flags & MAP_ANONYMOUS))
1636 file_handle=INVALID_HANDLE_VALUE;
1637 else
1638 file_handle=(HANDLE) _get_osfhandle(file);
1639 map_handle=CreateFileMapping(file_handle,0,protection_mode,high_length,
1640 low_length,0);
1641 if (map_handle)
1642 {
1643 map=(void *) MapViewOfFile(map_handle,access_mode,high_offset,low_offset,
1644 length);
1645 CloseHandle(map_handle);
1646 }
1647 if (map == (void *) NULL)
1648 return((void *) ((char *) MAP_FAILED));
1649 return((void *) ((char *) map));
1650}
1651
1652/*
1653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1654% %
1655% %
1656% %
1657% N T O p e n D i r e c t o r y %
1658% %
1659% %
1660% %
1661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1662%
1663% NTOpenDirectory() opens the directory named by filename and associates a
1664% directory stream with it.
1665%
1666% The format of the NTOpenDirectory method is:
1667%
1668% DIR *NTOpenDirectory(const char *path)
1669%
1670% A description of each parameter follows:
1671%
1672% o entry: Specifies a pointer to a DIR structure.
1673%
1674*/
1675MagickPrivate DIR *NTOpenDirectory(const char *path)
1676{
1677 DIR
1678 *entry;
1679
1680 size_t
1681 length;
1682
1683 wchar_t
1684 file_specification[MagickPathExtent];
1685
1686 assert(path != (const char *) NULL);
1687 length=MultiByteToWideChar(CP_UTF8,0,path,-1,file_specification,
1688 MagickPathExtent);
1689 if (length == 0)
1690 return((DIR *) NULL);
1691 if(wcsncat(file_specification,L"\\*.*",MagickPathExtent-wcslen(
1692 file_specification)-1) == (wchar_t *) NULL)
1693 return((DIR *) NULL);
1694 entry=(DIR *) AcquireCriticalMemory(sizeof(DIR));
1695 entry->firsttime=TRUE;
1696 entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
1697 if (entry->hSearch == INVALID_HANDLE_VALUE)
1698 {
1699 entry=(DIR *) RelinquishMagickMemory(entry);
1700 return((DIR *) NULL);
1701 }
1702 return(entry);
1703}
1704
1705/*
1706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1707% %
1708% %
1709% %
1710% N T O p e n L i b r a r y %
1711% %
1712% %
1713% %
1714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1715%
1716% NTOpenLibrary() loads a dynamic module into memory and returns a handle that
1717% can be used to access the various procedures in the module.
1718%
1719% The format of the NTOpenLibrary method is:
1720%
1721% void *NTOpenLibrary(const char *filename)
1722%
1723% A description of each parameter follows:
1724%
1725% o path: Specifies a pointer to string representing dynamic module that
1726% is to be loaded.
1727%
1728*/
1729
1730static UINT ChangeErrorMode(void)
1731{
1732 typedef UINT
1733 (CALLBACK *GETERRORMODE)(void);
1734
1735 GETERRORMODE
1736 getErrorMode;
1737
1738 HMODULE
1739 handle;
1740
1741 UINT
1742 mode;
1743
1744 mode=SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1745
1746 handle=GetModuleHandle("kernel32.dll");
1747 if (handle == (HMODULE) NULL)
1748 return SetErrorMode(mode);
1749
1750 getErrorMode=(GETERRORMODE) NTGetLibrarySymbol(handle,"GetErrorMode");
1751 if (getErrorMode != (GETERRORMODE) NULL)
1752 mode=getErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
1753
1754 return SetErrorMode(mode);
1755}
1756
1757static inline void *NTLoadLibrary(const char *filename)
1758{
1759 void
1760 *library;
1761
1762 wchar_t
1763 *path;
1764
1765 library=(void *) NULL;
1766 path=create_wchar_path(filename);
1767 if (path != (wchar_t *) NULL)
1768 {
1769 library=LoadLibraryExW(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
1770 path=(wchar_t *) RelinquishMagickMemory(path);
1771 }
1772 return(library);
1773}
1774
1775MagickPrivate void *NTOpenLibrary(const char *filename)
1776{
1777 UINT
1778 mode;
1779
1780 void
1781 *handle;
1782
1783 mode=ChangeErrorMode();
1784 handle=NTLoadLibrary(filename);
1785#if defined(MAGICKCORE_LTDL_DELEGATE)
1786 if (handle == (void *) NULL)
1787 {
1788 char
1789 path[MagickPathExtent];
1790
1791 const char
1792 *p,
1793 *q;
1794
1795 p=lt_dlgetsearchpath();
1796 while (p != (const char*) NULL)
1797 {
1798 q=strchr(p,DirectoryListSeparator);
1799 if (q != (const char*) NULL)
1800 (void) CopyMagickString(path,p,q-p+1);
1801 else
1802 (void) CopyMagickString(path,p,MagickPathExtent);
1803 (void) ConcatenateMagickString(path,DirectorySeparator,MagickPathExtent);
1804 (void) ConcatenateMagickString(path,filename,MagickPathExtent);
1805 handle=NTLoadLibrary(path);
1806 if (handle != (void *) NULL || q == (const char*) NULL)
1807 break;
1808 p=q+1;
1809 }
1810 }
1811#endif
1812 SetErrorMode(mode);
1813 return(handle);
1814}
1815
1816/*
1817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1818% %
1819% %
1820% %
1821% N T R e a d D i r e c t o r y %
1822% %
1823% %
1824% %
1825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1826%
1827% NTReadDirectory() returns a pointer to a structure representing the
1828% directory entry at the current position in the directory stream to which
1829% entry refers.
1830%
1831% The format of the NTReadDirectory
1832%
1833% NTReadDirectory(entry)
1834%
1835% A description of each parameter follows:
1836%
1837% o entry: Specifies a pointer to a DIR structure.
1838%
1839*/
1840MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
1841{
1842 int
1843 status;
1844
1845 size_t
1846 length;
1847
1848 if (entry == (DIR *) NULL)
1849 return((struct dirent *) NULL);
1850 if (!entry->firsttime)
1851 {
1852 status=FindNextFileW(entry->hSearch,&entry->Win32FindData);
1853 if (status == 0)
1854 return((struct dirent *) NULL);
1855 }
1856 length=WideCharToMultiByte(CP_UTF8,0,entry->Win32FindData.cFileName,-1,
1857 entry->file_info.d_name,sizeof(entry->file_info.d_name),NULL,NULL);
1858 if (length == 0)
1859 return((struct dirent *) NULL);
1860 entry->firsttime=FALSE;
1861 entry->file_info.d_namlen=(int) strlen(entry->file_info.d_name);
1862 return(&entry->file_info);
1863}
1864
1865/*
1866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1867% %
1868% %
1869% %
1870% N T R e g i s t r y K e y L o o k u p %
1871% %
1872% %
1873% %
1874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1875%
1876% NTRegistryKeyLookup() returns ImageMagick installation path settings
1877% stored in the Windows Registry. Path settings are specific to the
1878% installed ImageMagick version so that multiple Image Magick installations
1879% may coexist.
1880%
1881% Values are stored in the registry under a base path similar to
1882% "HKEY_LOCAL_MACHINE/SOFTWARE\ImageMagick\6.7.4\Q:16" or
1883% "HKEY_CURRENT_USER/SOFTWARE\ImageMagick\6.7.4\Q:16". The provided subkey
1884% is appended to this base path to form the full key.
1885%
1886% The format of the NTRegistryKeyLookup method is:
1887%
1888% unsigned char *NTRegistryKeyLookup(const char *subkey)
1889%
1890% A description of each parameter follows:
1891%
1892% o subkey: Specifies a string that identifies the registry object.
1893% Currently supported sub-keys include: "BinPath", "ConfigurePath",
1894% "LibPath", "CoderModulesPath", "FilterModulesPath", "SharePath".
1895%
1896*/
1897MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
1898{
1899 char
1900 package_key[MagickPathExtent] = "";
1901
1902 unsigned char
1903 *value;
1904
1905 (void) FormatLocaleString(package_key,MagickPathExtent,
1906 "SOFTWARE\\%s\\%s\\Q:%d",MagickPackageName,MagickLibVersionText,
1907 MAGICKCORE_QUANTUM_DEPTH);
1908 value=NTGetRegistryValue(HKEY_LOCAL_MACHINE,package_key,0,subkey);
1909 if (value == (unsigned char *) NULL)
1910 value=NTGetRegistryValue(HKEY_CURRENT_USER,package_key,0,subkey);
1911 return(value);
1912}
1913
1914/*
1915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1916% %
1917% %
1918% %
1919% N T R e p o r t E v e n t %
1920% %
1921% %
1922% %
1923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1924%
1925% NTReportEvent() reports an event.
1926%
1927% The format of the NTReportEvent method is:
1928%
1929% MagickBooleanType NTReportEvent(const char *event,
1930% const MagickBooleanType error)
1931%
1932% A description of each parameter follows:
1933%
1934% o event: the event.
1935%
1936% o error: MagickTrue the event is an error.
1937%
1938*/
1939MagickPrivate MagickBooleanType NTReportEvent(const char *event,
1940 const MagickBooleanType error)
1941{
1942 const char
1943 *events[1];
1944
1945 HANDLE
1946 handle;
1947
1948 WORD
1949 type;
1950
1951 handle=RegisterEventSource(NULL,MAGICKCORE_PACKAGE_NAME);
1952 if (handle == NULL)
1953 return(MagickFalse);
1954 events[0]=event;
1955 type=error ? EVENTLOG_ERROR_TYPE : EVENTLOG_WARNING_TYPE;
1956 ReportEvent(handle,type,0,0,NULL,1,0,events,NULL);
1957 DeregisterEventSource(handle);
1958 return(MagickTrue);
1959}
1960
1961/*
1962%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1963% %
1964% %
1965% %
1966% N T R e s o u r c e T o B l o b %
1967% %
1968% %
1969% %
1970%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1971%
1972% NTResourceToBlob() returns a blob containing the contents of the resource
1973% in the current executable specified by the id parameter. This currently
1974% used to retrieve MGK files tha have been embedded into the various command
1975% line utilities.
1976%
1977% The format of the NTResourceToBlob method is:
1978%
1979% unsigned char *NTResourceToBlob(const char *id)
1980%
1981% A description of each parameter follows:
1982%
1983% o id: Specifies a string that identifies the resource.
1984%
1985*/
1986MagickPrivate unsigned char *NTResourceToBlob(const char *id)
1987{
1988
1989#ifndef MAGICKCORE_LIBRARY_NAME
1990 char
1991 path[MagickPathExtent];
1992#endif
1993
1994 DWORD
1995 length;
1996
1997 HGLOBAL
1998 global;
1999
2000 HMODULE
2001 handle;
2002
2003 HRSRC
2004 resource;
2005
2006 unsigned char
2007 *blob,
2008 *value;
2009
2010 assert(id != (const char *) NULL);
2011 if (IsEventLogging() != MagickFalse)
2012 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
2013#ifdef MAGICKCORE_LIBRARY_NAME
2014 handle=GetModuleHandle(MAGICKCORE_LIBRARY_NAME);
2015#else
2016 (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",GetClientPath(),
2017 DirectorySeparator,GetClientName());
2018 if (IsPathAccessible(path) != MagickFalse)
2019 handle=GetModuleHandle(path);
2020 else
2021 handle=GetModuleHandle(0);
2022#endif
2023 if (!handle)
2024 return((unsigned char *) NULL);
2025 resource=FindResource(handle,id,"IMAGEMAGICK");
2026 if (!resource)
2027 return((unsigned char *) NULL);
2028 global=LoadResource(handle,resource);
2029 if (!global)
2030 return((unsigned char *) NULL);
2031 length=SizeofResource(handle,resource);
2032 value=(unsigned char *) LockResource(global);
2033 if (!value)
2034 {
2035 FreeResource(global);
2036 return((unsigned char *) NULL);
2037 }
2038 blob=(unsigned char *) AcquireQuantumMemory(length+MagickPathExtent,
2039 sizeof(*blob));
2040 if (blob != (unsigned char *) NULL)
2041 {
2042 (void) memcpy(blob,value,length);
2043 blob[length]='\0';
2044 }
2045 UnlockResource(global);
2046 FreeResource(global);
2047 return(blob);
2048}
2049
2050/*
2051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2052% %
2053% %
2054% %
2055% N T S y s t e m C o m m a n d %
2056% %
2057% %
2058% %
2059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2060%
2061% NTSystemCommand() executes the specified command and waits until it
2062% terminates. The returned value is the exit status of the command.
2063%
2064% The format of the NTSystemCommand method is:
2065%
2066% int NTSystemCommand(MagickFalse,const char *command)
2067%
2068% A description of each parameter follows:
2069%
2070% o command: This string is the command to execute.
2071%
2072% o output: an optional buffer to store the output from stderr/stdout.
2073%
2074*/
2075MagickPrivate int NTSystemCommand(const char *command,char *output)
2076{
2077#define CleanupOutputHandles \
2078 if (read_output != (HANDLE) NULL) \
2079 { \
2080 CloseHandle(read_output); \
2081 read_output=(HANDLE) NULL; \
2082 CloseHandle(write_output); \
2083 write_output=(HANDLE) NULL; \
2084 }
2085
2086#define CopyLastError \
2087 last_error=GetLastError(); \
2088 if (output != (char *) NULL) \
2089 { \
2090 error=NTGetLastErrorMessage(last_error); \
2091 if (error != (char *) NULL) \
2092 { \
2093 CopyMagickString(output,error,MagickPathExtent); \
2094 error=DestroyString(error); \
2095 } \
2096 }
2097
2098 char
2099 *error,
2100 local_command[MagickPathExtent];
2101
2102 DWORD
2103 child_status,
2104 last_error;
2105
2106 int
2107 status;
2108
2109 MagickBooleanType
2110 asynchronous;
2111
2112 HANDLE
2113 read_output,
2114 write_output;
2115
2116 PROCESS_INFORMATION
2117 process_info;
2118
2119 size_t
2120 output_offset;
2121
2122 STARTUPINFO
2123 startup_info;
2124
2125 if (command == (char *) NULL)
2126 return(-1);
2127 read_output=(HANDLE) NULL;
2128 write_output=(HANDLE) NULL;
2129 GetStartupInfo(&startup_info);
2130 startup_info.dwFlags=STARTF_USESHOWWINDOW;
2131 startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
2132 (void) CopyMagickString(local_command,command,MagickPathExtent);
2133 asynchronous=command[strlen(command)-1] == '&' ? MagickTrue : MagickFalse;
2134 if (asynchronous != MagickFalse)
2135 {
2136 local_command[strlen(command)-1]='\0';
2137 startup_info.wShowWindow=SW_SHOWDEFAULT;
2138 }
2139 else
2140 {
2141 if (command[strlen(command)-1] == '|')
2142 local_command[strlen(command)-1]='\0';
2143 else
2144 startup_info.wShowWindow=SW_HIDE;
2145 read_output=(HANDLE) NULL;
2146 if (output != (char *) NULL)
2147 {
2148 if (CreatePipe(&read_output,&write_output,NULL,0))
2149 {
2150 if (SetHandleInformation(write_output,HANDLE_FLAG_INHERIT,
2151 HANDLE_FLAG_INHERIT))
2152 {
2153 startup_info.dwFlags|=STARTF_USESTDHANDLES;
2154 startup_info.hStdOutput=write_output;
2155 startup_info.hStdError=write_output;
2156 }
2157 else
2158 CleanupOutputHandles;
2159 }
2160 else
2161 read_output=(HANDLE) NULL;
2162 }
2163 }
2164 status=CreateProcess((LPCTSTR) NULL,local_command,(LPSECURITY_ATTRIBUTES)
2165 NULL,(LPSECURITY_ATTRIBUTES) NULL,(BOOL) TRUE,(DWORD)
2166 NORMAL_PRIORITY_CLASS,(LPVOID) NULL,(LPCSTR) NULL,&startup_info,
2167 &process_info);
2168 if (status == 0)
2169 {
2170 CopyLastError;
2171 CleanupOutputHandles;
2172 return(last_error == ERROR_FILE_NOT_FOUND ? 127 : -1);
2173 }
2174 if (output != (char *) NULL)
2175 *output='\0';
2176 if (asynchronous != MagickFalse)
2177 return(status == 0);
2178 output_offset=0;
2179 status=STATUS_TIMEOUT;
2180 while (status == STATUS_TIMEOUT)
2181 {
2182 DWORD
2183 size;
2184
2185 status=WaitForSingleObject(process_info.hProcess,1000);
2186 size=0;
2187 if (read_output != (HANDLE) NULL)
2188 if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2189 break;
2190 while (size > 0)
2191 {
2192 char
2193 buffer[MagickPathExtent];
2194
2195 DWORD
2196 bytes_read;
2197
2198 if (ReadFile(read_output,buffer,MagickPathExtent-1,&bytes_read,NULL))
2199 {
2200 size_t
2201 count;
2202
2203 count=MagickMin(MagickPathExtent-output_offset,
2204 (size_t) bytes_read+1);
2205 if (count > 0)
2206 {
2207 CopyMagickString(output+output_offset,buffer,count);
2208 output_offset+=count-1;
2209 }
2210 }
2211 if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
2212 break;
2213 }
2214 }
2215 if (status != WAIT_OBJECT_0)
2216 {
2217 CopyLastError;
2218 CleanupOutputHandles;
2219 return(status);
2220 }
2221 status=GetExitCodeProcess(process_info.hProcess,&child_status);
2222 if (status == 0)
2223 {
2224 CopyLastError;
2225 CleanupOutputHandles;
2226 return(-1);
2227 }
2228 CloseHandle(process_info.hProcess);
2229 CloseHandle(process_info.hThread);
2230 CleanupOutputHandles;
2231 return((int) child_status);
2232}
2233
2234/*
2235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2236% %
2237% %
2238% %
2239% N T S y s t e m C o n i f i g u r a t i o n %
2240% %
2241% %
2242% %
2243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244%
2245% NTSystemConfiguration() provides a way for the application to determine
2246% values for system limits or options at runtime.
2247%
2248% The format of the exit method is:
2249%
2250% ssize_t NTSystemConfiguration(int name)
2251%
2252% A description of each parameter follows:
2253%
2254% o name: _SC_PAGE_SIZE or _SC_PHYS_PAGES.
2255%
2256*/
2257MagickPrivate ssize_t NTSystemConfiguration(int name)
2258{
2259 switch (name)
2260 {
2261 case _SC_PAGE_SIZE:
2262 {
2263 SYSTEM_INFO
2264 system_info;
2265
2266 GetSystemInfo(&system_info);
2267 return(system_info.dwPageSize);
2268 }
2269 case _SC_PHYS_PAGES:
2270 {
2271 MEMORYSTATUSEX
2272 status;
2273
2274 SYSTEM_INFO
2275 system_info;
2276
2277 status.dwLength=sizeof(status);
2278 if (GlobalMemoryStatusEx(&status) == 0)
2279 return(0L);
2280 GetSystemInfo(&system_info);
2281 return((ssize_t) status.ullTotalPhys/system_info.dwPageSize);
2282 }
2283 case _SC_OPEN_MAX:
2284 return(2048);
2285 default:
2286 break;
2287 }
2288 return(-1);
2289}
2290
2291/*
2292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2293% %
2294% %
2295% %
2296% N T T r u n c a t e F i l e %
2297% %
2298% %
2299% %
2300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2301%
2302% NTTruncateFile() truncates a file to a specified length.
2303%
2304% The format of the NTTruncateFile method is:
2305%
2306% int NTTruncateFile(int file,off_t length)
2307%
2308% A description of each parameter follows:
2309%
2310% o file: the file.
2311%
2312% o length: the file length.
2313%
2314*/
2315MagickPrivate int NTTruncateFile(int file,off_t length)
2316{
2317 DWORD
2318 file_pointer;
2319
2320 HANDLE
2321 file_handle;
2322
2323 long
2324 high,
2325 low;
2326
2327 file_handle=(HANDLE) _get_osfhandle(file);
2328 if (file_handle == INVALID_HANDLE_VALUE)
2329 return(-1);
2330 low=(long) (length & 0xffffffffUL);
2331 high=(long) ((((MagickOffsetType) length) >> 32) & 0xffffffffUL);
2332 file_pointer=SetFilePointer(file_handle,low,&high,FILE_BEGIN);
2333 if ((file_pointer == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
2334 return(-1);
2335 if (SetEndOfFile(file_handle) == 0)
2336 return(-1);
2337 return(0);
2338}
2339
2340/*
2341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2342% %
2343% %
2344% %
2345+ N T U n m a p M e m o r y %
2346% %
2347% %
2348% %
2349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2350%
2351% NTUnmapMemory() emulates the Unix munmap method.
2352%
2353% The format of the NTUnmapMemory method is:
2354%
2355% int NTUnmapMemory(void *map,size_t length)
2356%
2357% A description of each parameter follows:
2358%
2359% o map: the address of the binary large object.
2360%
2361% o length: the length of the binary large object.
2362%
2363*/
2364MagickPrivate int NTUnmapMemory(void *map,size_t length)
2365{
2366 (void) length;
2367 if (UnmapViewOfFile(map) == 0)
2368 return(-1);
2369 return(0);
2370}
2371
2372/*
2373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2374% %
2375% %
2376% %
2377% N T W a r n i n g H a n d l e r %
2378% %
2379% %
2380% %
2381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2382%
2383% NTWarningHandler() displays a warning reason.
2384%
2385% The format of the NTWarningHandler method is:
2386%
2387% void NTWarningHandler(const ExceptionType severity,const char *reason,
2388% const char *description)
2389%
2390% A description of each parameter follows:
2391%
2392% o severity: Specifies the numeric warning category.
2393%
2394% o reason: Specifies the reason to display before terminating the
2395% program.
2396%
2397% o description: Specifies any description to the reason.
2398%
2399*/
2400MagickPrivate void NTWarningHandler(const ExceptionType severity,
2401 const char *reason,const char *description)
2402{
2403 char
2404 buffer[2*MagickPathExtent];
2405
2406 (void) severity;
2407 if (reason == (char *) NULL)
2408 return;
2409 if (description == (char *) NULL)
2410 (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s.\n",GetClientName(),
2411 reason);
2412 else
2413 (void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s).\n",
2414 GetClientName(),reason,description);
2415 (void) MessageBox(NULL,buffer,"ImageMagick Warning",MB_OK | MB_TASKMODAL |
2416 MB_SETFOREGROUND | MB_ICONINFORMATION);
2417}
2418
2419/*
2420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2421% %
2422% %
2423% %
2424% N T W i n d o w s G e n e s i s %
2425% %
2426% %
2427% %
2428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2429%
2430% NTWindowsGenesis() initializes the MagickCore Windows environment.
2431%
2432% The format of the NTWindowsGenesis method is:
2433%
2434% void NTWindowsGenesis(void)
2435%
2436*/
2437
2438MagickPrivate void NTWindowsGenesis(void)
2439{
2440 char
2441 *mode;
2442
2443 mode=GetEnvironmentValue("MAGICK_ERRORMODE");
2444 if (mode != (char *) NULL)
2445 {
2446 (void) SetErrorMode(StringToInteger(mode));
2447 mode=DestroyString(mode);
2448 }
2449#if defined(_DEBUG) && !defined(__BORLANDC__) && !defined(__MINGW32__)
2450 if (IsEventLogging() != MagickFalse)
2451 {
2452 int
2453 debug;
2454
2455 debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
2456 //debug |= _CRTDBG_CHECK_ALWAYS_DF;
2457 debug |= _CRTDBG_DELAY_FREE_MEM_DF;
2458 debug |= _CRTDBG_LEAK_CHECK_DF;
2459 (void) _CrtSetDbgFlag(debug);
2460
2461 //_ASSERTE(_CrtCheckMemory());
2462
2463 //_CrtSetBreakAlloc(42);
2464 }
2465#endif
2466#if defined(MAGICKCORE_INSTALLED_SUPPORT)
2467 {
2468 unsigned char
2469 *path;
2470
2471 path=NTRegistryKeyLookup("LibPath");
2472 if (path != (unsigned char *) NULL)
2473 {
2474 wchar_t
2475 *lib_path;
2476
2477 lib_path=create_wchar_path((const char *) path);
2478 if (lib_path != (wchar_t *) NULL)
2479 {
2480 SetDllDirectoryW(lib_path);
2481 lib_path=(wchar_t *) RelinquishMagickMemory(lib_path);
2482 }
2483 path=(unsigned char *) RelinquishMagickMemory(path);
2484 }
2485 }
2486#endif
2487}
2488
2489
2490/*
2491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2492% %
2493% %
2494% %
2495% N T W i n d o w s T e r m i n u s %
2496% %
2497% %
2498% %
2499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2500%
2501% NTWindowsTerminus() terminates the MagickCore Windows environment.
2502%
2503% The format of the NTWindowsTerminus method is:
2504%
2505% void NTWindowsTerminus(void)
2506%
2507*/
2508MagickPrivate void NTWindowsTerminus(void)
2509{
2510 NTGhostscriptUnLoadDLL();
2511 DistributeCacheTerminus();
2512}
2513#endif
Definition vms.h:942