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