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