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