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