1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2799 lines
89 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N N TTTTT %
% NN N T %
% N N N T %
% N NN T %
% N N T %
% %
% %
% Windows NT Utility Methods for MagickCore %
% %
% Software Design %
% Cristy %
% December 1996 %
% %
% %
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
/*
Include declarations.
*/
#include "MagickCore/studio.h"
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
#include "MagickCore/client.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/image-private.h"
#include "MagickCore/locale_.h"
#include "MagickCore/log.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/memory-private.h"
#include "MagickCore/nt-base.h"
#include "MagickCore/nt-base-private.h"
#include "MagickCore/resource_.h"
#include "MagickCore/resource-private.h"
#include "MagickCore/timer.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
#include "MagickCore/utility.h"
#include "MagickCore/utility-private.h"
#include "MagickCore/version.h"
#if defined(MAGICKCORE_LTDL_DELEGATE)
# include "ltdl.h"
#endif
#if defined(MAGICKCORE_CIPHER_SUPPORT)
#include <ntsecapi.h>
#include <wincrypt.h>
#endif
/*
Define declarations.
*/
#if !defined(MAP_FAILED)
#define MAP_FAILED ((void *)(LONG_PTR)-1)
#endif
/*
Typdef declarations.
*/
/*
We need to make sure only one instance is created for each process and that
is why we wrap the new/delete instance methods.
From: http://www.ghostscript.com/doc/current/API.htm
"The Win32 DLL gsdll32.dll can be used by multiple programs simultaneously,
but only once within each process"
*/
typedef struct _NTGhostInfo
{
void
(MagickDLLCall *delete_instance)(gs_main_instance *);
int
(MagickDLLCall *new_instance)(gs_main_instance **,void *);
MagickBooleanType
has_instance;
} NTGhostInfo;
/*
Static declarations.
*/
#if !defined(MAGICKCORE_LTDL_DELEGATE)
static char
*lt_slsearchpath = (char *) NULL;
#endif
static NTGhostInfo
nt_ghost_info;
static GhostInfo
ghost_info;
static void
*ghost_handle = (void *) NULL;
static SemaphoreInfo
*ghost_semaphore = (SemaphoreInfo *) NULL,
*winsock_semaphore = (SemaphoreInfo *) NULL;
static WSADATA
*wsaData = (WSADATA*) NULL;
static size_t
long_paths_enabled = 2;
struct
{
const HKEY
hkey;
const char
*name;
}
const registry_roots[2] =
{
{ HKEY_CURRENT_USER, "HKEY_CURRENT_USER" },
{ HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" }
};
/*
External declarations.
*/
#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
extern "C" BOOL WINAPI
DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved);
#endif
static void MagickDLLCall NTGhostscriptDeleteInstance(
gs_main_instance *instance)
{
LockSemaphoreInfo(ghost_semaphore);
nt_ghost_info.delete_instance(instance);
nt_ghost_info.has_instance=MagickFalse;
UnlockSemaphoreInfo(ghost_semaphore);
}
static int MagickDLLCall NTGhostscriptNewInstance(gs_main_instance **pinstance,
void *caller_handle)
{
int
status;
LockSemaphoreInfo(ghost_semaphore);
status=-1;
if (nt_ghost_info.has_instance == MagickFalse)
{
status=nt_ghost_info.new_instance(pinstance,caller_handle);
if (status >= 0)
nt_ghost_info.has_instance=MagickTrue;
}
UnlockSemaphoreInfo(ghost_semaphore);
return(status);
}
static inline char *create_utf8_string(const wchar_t *wideChar)
{
char
*utf8;
int
count;
count=WideCharToMultiByte(CP_UTF8,0,wideChar,-1,NULL,0,NULL,NULL);
if (count < 0)
return((char *) NULL);
utf8=(char *) AcquireQuantumMemory(count+1,sizeof(*utf8));
if (utf8 == (char *) NULL)
return((char *) NULL);
count=WideCharToMultiByte(CP_UTF8,0,wideChar,-1,utf8,count,NULL,NULL);
if (count == 0)
{
utf8=DestroyString(utf8);
return((char *) NULL);
}
utf8[count]=0;
return(utf8);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D l l M a i n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DllMain() is an entry point to the DLL which is called when processes and
% threads are initialized and terminated, or upon calls to the Windows
% LoadLibrary and FreeLibrary functions.
%
% The function returns TRUE of it succeeds, or FALSE if initialization fails.
%
% The format of the DllMain method is:
%
% BOOL WINAPI DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved)
%
% A description of each parameter follows:
%
% o handle: handle to the DLL module
%
% o reason: reason for calling function:
%
% DLL_PROCESS_ATTACH - DLL is being loaded into virtual address
% space of current process.
% DLL_THREAD_ATTACH - Indicates that the current process is
% creating a new thread. Called under the
% context of the new thread.
% DLL_THREAD_DETACH - Indicates that the thread is exiting.
% Called under the context of the exiting
% thread.
% DLL_PROCESS_DETACH - Indicates that the DLL is being unloaded
% from the virtual address space of the
% current process.
%
% o lpvReserved: Used for passing additional info during DLL_PROCESS_ATTACH
% and DLL_PROCESS_DETACH.
%
*/
#if defined(_DLL) && defined(ProvideDllMain)
BOOL WINAPI DllMain(HINSTANCE handle,DWORD reason,LPVOID lpvReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
{
char
*module_path;
ssize_t
count;
wchar_t
*wide_path;
MagickCoreGenesis((const char *) NULL,MagickFalse);
wide_path=(wchar_t *) AcquireQuantumMemory(MagickPathExtent,
sizeof(*wide_path));
if (wide_path == (wchar_t *) NULL)
return(FALSE);
count=(ssize_t) GetModuleFileNameW(handle,wide_path,MagickPathExtent);
if (count != 0)
{
char
*path;
module_path=create_utf8_string(wide_path);
for ( ; count > 0; count--)
if (module_path[count] == '\\')
{
module_path[count+1]='\0';
break;
}
path=(char *) AcquireQuantumMemory(MagickPathExtent,16*sizeof(*path));
if (path == (char *) NULL)
{
module_path=DestroyString(module_path);
wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
return(FALSE);
}
count=(ssize_t) GetEnvironmentVariable("PATH",path,16*
MagickPathExtent);
if ((count != 0) && (strstr(path,module_path) == (char *) NULL))
{
if ((strlen(module_path)+count+1) < (16*MagickPathExtent-1))
{
char
*variable;
variable=(char *) AcquireQuantumMemory(MagickPathExtent,
16*sizeof(*variable));
if (variable == (char *) NULL)
{
path=DestroyString(path);
module_path=DestroyString(module_path);
wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
return(FALSE);
}
(void) FormatLocaleString(variable,16*MagickPathExtent,
"%s;%s",module_path,path);
SetEnvironmentVariable("PATH",variable);
variable=DestroyString(variable);
}
}
path=DestroyString(path);
module_path=DestroyString(module_path);
}
wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
break;
}
case DLL_PROCESS_DETACH:
{
MagickCoreTerminus();
break;
}
default:
break;
}
return(TRUE);
}
#endif
#if !defined(__MINGW32__)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% g e t t i m e o f d a y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The gettimeofday() method get the time of day.
%
% The format of the gettimeofday method is:
%
% int gettimeofday(struct timeval *time_value,struct timezone *time_zone)
%
% A description of each parameter follows:
%
% o time_value: the time value.
%
% o time_zone: the time zone.
%
*/
MagickPrivate int gettimeofday (struct timeval *time_value,
struct timezone *time_zone)
{
#define EpochFiletime MagickLLConstant(116444736000000000)
static int
is_tz_set;
if (time_value != (struct timeval *) NULL)
{
FILETIME
file_time;
__int64
time;
LARGE_INTEGER
date_time;
GetSystemTimeAsFileTime(&file_time);
date_time.LowPart=file_time.dwLowDateTime;
date_time.HighPart=file_time.dwHighDateTime;
time=date_time.QuadPart;
time-=EpochFiletime;
time/=10;
time_value->tv_sec=(ssize_t) (time / 1000000);
time_value->tv_usec=(ssize_t) (time % 1000000);
}
if (time_zone != (struct timezone *) NULL)
{
if (is_tz_set == 0)
{
_tzset();
is_tz_set++;
}
time_zone->tz_minuteswest=_timezone/60;
time_zone->tz_dsttime=_daylight;
}
return(0);
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T A r g v T o U T F 8 %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTArgvToUTF8() converts the wide command line arguments to UTF-8 to ensure
% compatibility with Linux.
%
% The format of the NTArgvToUTF8 method is:
%
% char **NTArgvToUTF8(const int argc,wchar_t **argv)
%
% A description of each parameter follows:
%
% o argc: the number of command line arguments.
%
% o argv: the wide-character command line arguments.
%
*/
MagickPrivate char **NTArgvToUTF8(const int argc,wchar_t **argv)
{
char
**utf8;
ssize_t
i;
utf8=(char **) AcquireQuantumMemory(argc,sizeof(*utf8));
if (utf8 == (char **) NULL)
ThrowFatalException(ResourceLimitFatalError,"UnableToConvertStringToARGV");
for (i=0; i < (ssize_t) argc; i++)
{
utf8[i]=create_utf8_string(argv[i]);
if (utf8[i] == (char *) NULL)
{
for (i--; i >= 0; i--)
utf8[i]=DestroyString(utf8[i]);
ThrowFatalException(ResourceLimitFatalError,
"UnableToConvertStringToARGV");
}
}
return(utf8);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T C l o s e D i r e c t o r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTCloseDirectory() closes the named directory stream and frees the DIR
% structure.
%
% The format of the NTCloseDirectory method is:
%
% int NTCloseDirectory(DIR *entry)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
*/
MagickPrivate int NTCloseDirectory(DIR *entry)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(entry != (DIR *) NULL);
FindClose(entry->hSearch);
entry=(DIR *) RelinquishMagickMemory(entry);
return(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T C l o s e L i b r a r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTCloseLibrary() unloads the module associated with the passed handle.
%
% The format of the NTCloseLibrary method is:
%
% void NTCloseLibrary(void *handle)
%
% A description of each parameter follows:
%
% o handle: Specifies a handle to a previously loaded dynamic module.
%
*/
MagickPrivate int NTCloseLibrary(void *handle)
{
return(!(FreeLibrary((HINSTANCE) handle)));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T C o n t r o l H a n d l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTControlHandler() registers a control handler that is activated when, for
% example, a ctrl-c is received.
%
% The format of the NTControlHandler method is:
%
% int NTControlHandler(void)
%
*/
static BOOL ControlHandler(DWORD type)
{
(void) type;
AsynchronousResourceComponentTerminus();
return(FALSE);
}
MagickPrivate int NTControlHandler(void)
{
return(SetConsoleCtrlHandler((PHANDLER_ROUTINE) ControlHandler,TRUE));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T E l a p s e d T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTElapsedTime() returns the elapsed time (in seconds) since the last call to
% StartTimer().
%
% The format of the ElapsedTime method is:
%
% double NTElapsedTime(void)
%
*/
MagickPrivate double NTElapsedTime(void)
{
union
{
FILETIME
filetime;
__int64
filetime64;
} elapsed_time;
LARGE_INTEGER
performance_count;
static LARGE_INTEGER
frequency = { 0 };
SYSTEMTIME
system_time;
if (frequency.QuadPart == 0)
{
if (QueryPerformanceFrequency(&frequency) == 0)
frequency.QuadPart=1;
}
if (frequency.QuadPart > 1)
{
QueryPerformanceCounter(&performance_count);
return((double) performance_count.QuadPart/frequency.QuadPart);
}
GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time,&elapsed_time.filetime);
return((double) 1.0e-7*elapsed_time.filetime64);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T E r f %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTErf() computes the error function of x.
%
% The format of the NTErf method is:
%
% double NTCloseDirectory(DIR *entry)
%
% A description of each parameter follows:
%
% o x: Specifies a pointer to a DIR structure.
%
*/
MagickPrivate double NTErf(double x)
{
double
a1,
a2,
a3,
a4,
a5,
p,
t,
y;
int
sign;
a1=0.254829592;
a2=-0.284496736;
a3=1.421413741;
a4=-1.453152027;
a5=1.061405429;
p=0.3275911;
sign=1;
if (x < 0)
sign=-1;
x=abs(x);
t=1.0/(1.0+p*x);
y=1.0-(((((a5*t+a4)*t)+a3)*t+a2)*t+a1)*t*exp(-x*x);
return(sign*y);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ N T E r r o r H a n d l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTErrorHandler() displays an error reason and then terminates the program.
%
% The format of the NTErrorHandler method is:
%
% void NTErrorHandler(const ExceptionType severity,const char *reason,
% const char *description)
%
% A description of each parameter follows:
%
% o severity: Specifies the numeric error category.
%
% o reason: Specifies the reason to display before terminating the
% program.
%
% o description: Specifies any description to the reason.
%
*/
MagickPrivate void NTErrorHandler(const ExceptionType severity,
const char *reason,const char *description)
{
char
buffer[3*MagickPathExtent],
*message;
(void) severity;
if (reason == (char *) NULL)
{
MagickCoreTerminus();
exit(0);
}
message=GetExceptionMessage(errno);
if ((description != (char *) NULL) && errno)
(void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s) [%s].\n",
GetClientName(),reason,description,message);
else
if (description != (char *) NULL)
(void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s).\n",
GetClientName(),reason,description);
else
if (errno != 0)
(void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s [%s].\n",
GetClientName(),reason,message);
else
(void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s.\n",
GetClientName(),reason);
message=DestroyString(message);
(void) MessageBox(NULL,buffer,"ImageMagick Exception",MB_OK | MB_TASKMODAL |
MB_SETFOREGROUND | MB_ICONEXCLAMATION);
MagickCoreTerminus();
exit(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T E x i t L i b r a r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTExitLibrary() exits the dynamic module loading subsystem.
%
% The format of the NTExitLibrary method is:
%
% int NTExitLibrary(void)
%
*/
MagickPrivate int NTExitLibrary(void)
{
return(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G a t h e r R a n d o m D a t a %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGatherRandomData() gathers random data and returns it.
%
% The format of the GatherRandomData method is:
%
% MagickBooleanType NTGatherRandomData(const size_t length,
% unsigned char *random)
%
% A description of each parameter follows:
%
% length: the length of random data buffer
%
% random: the random data is returned here.
%
*/
MagickPrivate MagickBooleanType NTGatherRandomData(const size_t length,
unsigned char *random)
{
#if defined(MAGICKCORE_CIPHER_SUPPORT) && defined(_MSC_VER) && (_MSC_VER > 1200)
HCRYPTPROV
handle;
int
status;
handle=(HCRYPTPROV) NULL;
status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET));
if (status == 0)
status=CryptAcquireContext(&handle,NULL,MS_DEF_PROV,PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET));
if (status == 0)
return(MagickFalse);
status=CryptGenRandom(handle,(DWORD) length,random);
if (status == 0)
{
status=CryptReleaseContext(handle,0);
return(MagickFalse);
}
status=CryptReleaseContext(handle,0);
if (status == 0)
return(MagickFalse);
#else
(void) random;
(void) length;
#endif
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G e t E x e c u t i o n P a t h %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGetExecutionPath() returns the execution path of a program.
%
% The format of the GetExecutionPath method is:
%
% MagickBooleanType NTGetExecutionPath(char *path,const size_t extent)
%
% A description of each parameter follows:
%
% o path: the pathname of the executable that started the process.
%
% o extent: the maximum extent of the path.
%
*/
MagickPrivate MagickBooleanType NTGetExecutionPath(char *path,
const size_t extent)
{
wchar_t
wide_path[MagickPathExtent];
(void) GetModuleFileNameW((HMODULE) NULL,wide_path,(DWORD) extent);
(void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,
NULL);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G e t L a s t E r r o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGetLastError() returns the last error that occurred.
%
% The format of the NTGetLastError method is:
%
% char *NTGetLastError(void)
%
*/
char *NTGetLastError(void)
{
char
*reason;
int
status;
LPVOID
buffer;
status=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR) &buffer,0,NULL);
if (!status)
reason=AcquireString("An unknown error occurred");
else
{
reason=AcquireString((const char *) buffer);
LocalFree(buffer);
}
return(reason);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G e t L i b r a r y E r r o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Lt_dlerror() returns a pointer to a string describing the last error
% associated with a lt_dl method. Note that this function is not thread
% safe so it should only be used under the protection of a lock.
%
% The format of the NTGetLibraryError method is:
%
% const char *NTGetLibraryError(void)
%
*/
MagickPrivate const char *NTGetLibraryError(void)
{
static char
last_error[MagickPathExtent];
char
*error;
*last_error='\0';
error=NTGetLastError();
if (error)
(void) CopyMagickString(last_error,error,MagickPathExtent);
error=DestroyString(error);
return(last_error);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G e t L i b r a r y S y m b o l %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGetLibrarySymbol() retrieve the procedure address of the method
% specified by the passed character string.
%
% The format of the NTGetLibrarySymbol method is:
%
% void *NTGetLibrarySymbol(void *handle,const char *name)
%
% A description of each parameter follows:
%
% o handle: Specifies a handle to the previously loaded dynamic module.
%
% o name: Specifies the procedure entry point to be returned.
%
*/
void *NTGetLibrarySymbol(void *handle,const char *name)
{
FARPROC
proc_address;
proc_address=GetProcAddress((HMODULE) handle,(LPCSTR) name);
if (proc_address == (FARPROC) NULL)
return((void *) NULL);
return((void *) proc_address);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G e t M o d u l e P a t h %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGetModulePath() returns the path of the specified module.
%
% The format of the GetModulePath method is:
%
% MagickBooleanType NTGetModulePath(const char *module,char *path)
%
% A description of each parameter follows:
%
% modith: the module name.
%
% path: the module path is returned here.
%
*/
MagickPrivate MagickBooleanType NTGetModulePath(const char *module,char *path)
{
char
module_path[MagickPathExtent];
HMODULE
handle;
ssize_t
length;
*path='\0';
handle=GetModuleHandle(module);
if (handle == (HMODULE) NULL)
return(MagickFalse);
length=GetModuleFileName(handle,module_path,MagickPathExtent);
if (length != 0)
GetPathComponent(module_path,HeadPath,path);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G h o s t s c r i p t D L L %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGhostscriptDLL() returns the path to the most recent Ghostscript version
% DLL. The method returns TRUE on success otherwise FALSE.
%
% The format of the NTGhostscriptDLL method is:
%
% int NTGhostscriptDLL(char *path,int length)
%
% A description of each parameter follows:
%
% o path: return the Ghostscript DLL path here.
%
% o length: the buffer length.
%
*/
static int NTGetRegistryValue(HKEY root,const char *key,DWORD flags,
const char *name,char *value,int *length)
{
BYTE
byte,
*p;
DWORD
extent,
type;
HKEY
hkey;
LONG
status;
/*
Get a registry value: key = root\\key, named value = name.
*/
if (RegOpenKeyExA(root,key,0,KEY_READ | flags,&hkey) != ERROR_SUCCESS)
return(1); /* no match */
p=(BYTE *) value;
type=REG_SZ;
extent=(*length);
if (p == (BYTE *) NULL)
p=(&byte); /* ERROR_MORE_DATA only if value is NULL */
status=RegQueryValueExA(hkey,(char *) name,0,&type,p,&extent);
RegCloseKey(hkey);
if (status == ERROR_SUCCESS)
{
*length=extent;
return(0); /* return the match */
}
if (status == ERROR_MORE_DATA)
{
*length=extent;
return(-1); /* buffer not large enough */
}
return(1); /* not found */
}
static int NTLocateGhostscript(DWORD flags,int *root_index,
const char **product_family,int *major_version,int *minor_version,
int *patch_version)
{
int
i;
MagickBooleanType
status;
static const char
*products[4] =
{
"GPL Ghostscript",
"GNU Ghostscript",
"AFPL Ghostscript",
"Aladdin Ghostscript"
};
/*
Find the most recent version of Ghostscript.
*/
status=MagickFalse;
*root_index=0;
*product_family=NULL;
*major_version=5;
*minor_version=49; /* min version of Ghostscript is 5.50 */
for (i=0; i < (ssize_t) (sizeof(products)/sizeof(products[0])); i++)
{
char
key[MagickPathExtent];
HKEY
hkey;
int
j;
REGSAM
mode;
(void) FormatLocaleString(key,MagickPathExtent,"SOFTWARE\\%s",products[i]);
for (j=0; j < (ssize_t) (sizeof(registry_roots)/sizeof(registry_roots[0]));
j++)
{
mode=KEY_READ | flags;
if (RegOpenKeyExA(registry_roots[j].hkey,key,0,mode,&hkey) ==
ERROR_SUCCESS)
{
DWORD
extent;
int
k;
/*
Now enumerate the keys.
*/
extent=sizeof(key)/sizeof(char);
for (k=0; RegEnumKeyA(hkey,k,key,extent) == ERROR_SUCCESS; k++)
{
int
major,
minor,
patch;
major=0;
minor=0;
patch=0;
if (sscanf(key,"%d.%d.%d",&major,&minor,&patch) != 3)
if (sscanf(key,"%d.%d",&major,&minor) != 2)
continue;
if ((major > *major_version) ||
((major == *major_version) && (minor > *minor_version)) ||
((minor == *minor_version) && (patch > *patch_version)))
{
*root_index=j;
*product_family=products[i];
*major_version=major;
*minor_version=minor;
*patch_version=patch;
status=MagickTrue;
}
}
(void) RegCloseKey(hkey);
}
}
}
if (status == MagickFalse)
{
*major_version=0;
*minor_version=0;
*patch_version=0;
}
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"Ghostscript (%s) "
"version %d.%d.%d",*product_family,*major_version,*minor_version,*patch_version);
return(status);
}
static int NTGhostscriptGetString(const char *name,BOOL *is_64_bit,char *value,
const size_t length)
{
char
buffer[MagickPathExtent],
*directory;
int
extent;
static const char
*product_family = (const char *) NULL;
static BOOL
is_64_bit_version = FALSE;
static int
flags = 0,
major_version = 0,
minor_version = 0,
patch_version = 0,
root_index = 0;
/*
Get a string from the installed Ghostscript.
*/
*value='\0';
directory=(char *) NULL;
if (LocaleCompare(name,"GS_DLL") == 0)
{
directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_PATH");
if (directory != (char *) NULL)
{
(void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll64.dll",
directory,DirectorySeparator);
if (IsPathAccessible(buffer) != MagickFalse)
{
directory=DestroyString(directory);
(void) CopyMagickString(value,buffer,length);
if (is_64_bit != NULL)
*is_64_bit=TRUE;
return(TRUE);
}
(void) FormatLocaleString(buffer,MagickPathExtent,"%s%sgsdll32.dll",
directory,DirectorySeparator);
if (IsPathAccessible(buffer) != MagickFalse)
{
directory=DestroyString(directory);
(void) CopyMagickString(value,buffer,length);
if (is_64_bit != NULL)
*is_64_bit=FALSE;
return(TRUE);
}
return(FALSE);
}
}
if (product_family == NULL)
{
flags=0;
#if defined(KEY_WOW64_32KEY)
#if defined(_WIN64)
flags=KEY_WOW64_64KEY;
#else
flags=KEY_WOW64_32KEY;
#endif
(void) NTLocateGhostscript(flags,&root_index,&product_family,
&major_version,&minor_version,&patch_version);
if (product_family == NULL)
#if defined(_WIN64)
flags=KEY_WOW64_32KEY;
else
is_64_bit_version=TRUE;
#else
flags=KEY_WOW64_64KEY;
#endif
#endif
}
if (product_family == NULL)
{
(void) NTLocateGhostscript(flags,&root_index,&product_family,
&major_version,&minor_version,&patch_version);
#if !defined(_WIN64)
is_64_bit_version=TRUE;
#endif
}
if (product_family == NULL)
return(FALSE);
if (is_64_bit != NULL)
*is_64_bit=is_64_bit_version;
extent=(int) length;
(void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%d.%d",
product_family,major_version,minor_version,patch_version);
if (NTGetRegistryValue(registry_roots[root_index].hkey,buffer,flags,name,value,&extent) != 0)
{
extent=(int) length;
(void) FormatLocaleString(buffer,MagickPathExtent,"SOFTWARE\\%s\\%d.%02d",
product_family,major_version,minor_version);
if (NTGetRegistryValue(registry_roots[root_index].hkey,buffer,flags,name,value,&extent) != 0)
return(FALSE);
}
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
"registry: \"%s\\%s\\%s\"=\"%s\"",registry_roots[root_index].name,
buffer,name,value);
return(TRUE);
}
MagickPrivate int NTGhostscriptDLL(char *path,int length)
{
static char
dll[MagickPathExtent] = { "" };
static BOOL
is_64_bit_version;
*path='\0';
if ((*dll == '\0') &&
(NTGhostscriptGetString("GS_DLL",&is_64_bit_version,dll,sizeof(dll)) == FALSE))
return(FALSE);
#if defined(_WIN64)
if (!is_64_bit_version)
return(FALSE);
#else
if (is_64_bit_version)
return(FALSE);
#endif
(void) CopyMagickString(path,dll,length);
return(TRUE);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G h o s t s c r i p t D L L V e c t o r s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGhostscriptDLLVectors() returns a GhostInfo structure that includes
% function vectors to invoke Ghostscript DLL functions. A null pointer is
% returned if there is an error when loading the DLL or retrieving the
% function vectors.
%
% The format of the NTGhostscriptDLLVectors method is:
%
% const GhostInfo *NTGhostscriptDLLVectors(void)
%
*/
MagickPrivate const GhostInfo *NTGhostscriptDLLVectors(void)
{
if (NTGhostscriptLoadDLL() == FALSE)
return((GhostInfo *) NULL);
return(&ghost_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G h o s t s c r i p t E X E %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGhostscriptEXE() obtains the path to the latest Ghostscript executable.
% The method returns FALSE if a full path value is not obtained and returns
% a default path of gswin32c.exe.
%
% The format of the NTGhostscriptEXE method is:
%
% void NTGhostscriptEXE(char *path,int length)
%
% A description of each parameter follows:
%
% o path: return the Ghostscript executable path here.
%
% o length: length of buffer.
%
*/
MagickPrivate void NTGhostscriptEXE(char *path,int length)
{
char
*p;
static char
program[MagickPathExtent] = { "" };
static BOOL
is_64_bit_version = FALSE;
if (*program == '\0')
{
if (ghost_semaphore == (SemaphoreInfo *) NULL)
ActivateSemaphoreInfo(&ghost_semaphore);
LockSemaphoreInfo(ghost_semaphore);
if (*program == '\0')
{
if (NTGhostscriptGetString("GS_DLL",&is_64_bit_version,program,
sizeof(program)) == FALSE)
{
UnlockSemaphoreInfo(ghost_semaphore);
#if defined(_WIN64)
(void) CopyMagickString(program,"gswin64c.exe",sizeof(program));
#else
(void) CopyMagickString(program,"gswin32c.exe",sizeof(program));
#endif
(void) CopyMagickString(path,program,length);
return;
}
p=strrchr(program,'\\');
if (p != (char *) NULL)
{
p++;
*p='\0';
(void) ConcatenateMagickString(program,is_64_bit_version ?
"gswin64c.exe" : "gswin32c.exe",sizeof(program));
}
}
UnlockSemaphoreInfo(ghost_semaphore);
}
(void) CopyMagickString(path,program,length);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G h o s t s c r i p t F o n t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGhostscriptFonts() obtains the path to the Ghostscript fonts. The method
% returns FALSE if it cannot determine the font path.
%
% The format of the NTGhostscriptFonts method is:
%
% int NTGhostscriptFonts(char *path,int length)
%
% A description of each parameter follows:
%
% o path: return the font path here.
%
% o length: length of the path buffer.
%
*/
MagickPrivate int NTGhostscriptFonts(char *path,int length)
{
char
buffer[MagickPathExtent],
*directory,
filename[MagickPathExtent];
char
*p,
*q;
*path='\0';
directory=GetEnvironmentValue("MAGICK_GHOSTSCRIPT_FONT_PATH");
if (directory != (char *) NULL)
{
(void) CopyMagickString(buffer,directory,MagickPathExtent);
directory=DestroyString(directory);
}
else
{
if (NTGhostscriptGetString("GS_LIB",NULL,buffer,MagickPathExtent) == FALSE)
return(FALSE);
}
for (p=buffer-1; p != (char *) NULL; p=strchr(p+1,DirectoryListSeparator))
{
(void) CopyMagickString(path,p+1,length+1);
q=strchr(path,DirectoryListSeparator);
if (q != (char *) NULL)
*q='\0';
(void) FormatLocaleString(filename,MagickPathExtent,"%s%sfonts.dir",path,
DirectorySeparator);
if (IsPathAccessible(filename) != MagickFalse)
return(TRUE);
(void) FormatLocaleString(filename,MagickPathExtent,"%s%sn019003l.pfb",path,
DirectorySeparator);
if (IsPathAccessible(filename) != MagickFalse)
return(TRUE);
}
*path='\0';
return(FALSE);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G h o s t s c r i p t L o a d D L L %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGhostscriptLoadDLL() attempts to load the Ghostscript DLL and returns
% TRUE if it succeeds.
%
% The format of the NTGhostscriptLoadDLL method is:
%
% int NTGhostscriptLoadDLL(void)
%
*/
static inline int NTGhostscriptHasValidHandle()
{
if ((nt_ghost_info.delete_instance == NULL) || (ghost_info.exit == NULL) ||
(ghost_info.init_with_args == NULL) ||
(nt_ghost_info.new_instance == NULL) ||
(ghost_info.run_string == NULL) || (ghost_info.set_stdio == NULL) ||
(ghost_info.revision == NULL))
{
return(FALSE);
}
return(TRUE);
}
MagickPrivate int NTGhostscriptLoadDLL(void)
{
char
path[MagickPathExtent];
if (ghost_semaphore == (SemaphoreInfo *) NULL)
ActivateSemaphoreInfo(&ghost_semaphore);
LockSemaphoreInfo(ghost_semaphore);
if (ghost_handle != (void *) NULL)
{
UnlockSemaphoreInfo(ghost_semaphore);
return(NTGhostscriptHasValidHandle());
}
if (NTGhostscriptDLL(path,sizeof(path)) == FALSE)
{
UnlockSemaphoreInfo(ghost_semaphore);
return(FALSE);
}
ghost_handle=lt_dlopen(path);
if (ghost_handle == (void *) NULL)
{
UnlockSemaphoreInfo(ghost_semaphore);
return(FALSE);
}
(void) memset((void *) &nt_ghost_info,0,sizeof(NTGhostInfo));
nt_ghost_info.delete_instance=(void (MagickDLLCall *)(gs_main_instance *)) (
lt_dlsym(ghost_handle,"gsapi_delete_instance"));
nt_ghost_info.new_instance=(int (MagickDLLCall *)(gs_main_instance **,
void *)) (lt_dlsym(ghost_handle,"gsapi_new_instance"));
nt_ghost_info.has_instance=MagickFalse;
(void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
ghost_info.delete_instance=NTGhostscriptDeleteInstance;
ghost_info.exit=(int (MagickDLLCall *)(gs_main_instance*))
lt_dlsym(ghost_handle,"gsapi_exit");
ghost_info.init_with_args=(int (MagickDLLCall *)(gs_main_instance *,int,
char **)) (lt_dlsym(ghost_handle,"gsapi_init_with_args"));
ghost_info.new_instance=NTGhostscriptNewInstance;
ghost_info.run_string=(int (MagickDLLCall *)(gs_main_instance *,const char *,
int,int *)) (lt_dlsym(ghost_handle,"gsapi_run_string"));
ghost_info.set_stdio=(int (MagickDLLCall *)(gs_main_instance *,int(
MagickDLLCall *)(void *,char *,int),int(MagickDLLCall *)(void *,
const char *,int),int(MagickDLLCall *)(void *,const char *,int)))
(lt_dlsym(ghost_handle,"gsapi_set_stdio"));
ghost_info.revision=(int (MagickDLLCall *)(gsapi_revision_t *,int)) (
lt_dlsym(ghost_handle,"gsapi_revision"));
UnlockSemaphoreInfo(ghost_semaphore);
return(NTGhostscriptHasValidHandle());
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T G h o s t s c r i p t U n L o a d D L L %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTGhostscriptUnLoadDLL() unloads the Ghostscript DLL and returns TRUE if
% it succeeds.
%
% The format of the NTGhostscriptUnLoadDLL method is:
%
% int NTGhostscriptUnLoadDLL(void)
%
*/
MagickPrivate void NTGhostscriptUnLoadDLL(void)
{
if (ghost_semaphore == (SemaphoreInfo *) NULL)
ActivateSemaphoreInfo(&ghost_semaphore);
LockSemaphoreInfo(ghost_semaphore);
if (ghost_handle != (void *) NULL)
{
(void) lt_dlclose(ghost_handle);
ghost_handle=(void *) NULL;
(void) memset((void *) &ghost_info,0,sizeof(GhostInfo));
}
UnlockSemaphoreInfo(ghost_semaphore);
RelinquishSemaphoreInfo(&ghost_semaphore);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T I n i t i a l i z e L i b r a r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTInitializeLibrary() initializes the dynamic module loading subsystem.
%
% The format of the NTInitializeLibrary method is:
%
% int NTInitializeLibrary(void)
%
*/
MagickPrivate int NTInitializeLibrary(void)
{
return(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T I n i t i a l i z e W i n s o c k %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTInitializeWinsock() initializes Winsock.
%
% The format of the NTInitializeWinsock method is:
%
% void NTInitializeWinsock(void)
%
*/
MagickPrivate void NTInitializeWinsock(MagickBooleanType use_lock)
{
if (use_lock)
{
if (winsock_semaphore == (SemaphoreInfo *) NULL)
ActivateSemaphoreInfo(&winsock_semaphore);
LockSemaphoreInfo(winsock_semaphore);
}
if (wsaData == (WSADATA *) NULL)
{
wsaData=(WSADATA *) AcquireMagickMemory(sizeof(WSADATA));
if (WSAStartup(MAKEWORD(2,2),wsaData) != 0)
ThrowFatalException(CacheFatalError,"WSAStartup failed");
}
if (use_lock)
UnlockSemaphoreInfo(winsock_semaphore);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T L o n g P a t h s E n a b l e d %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTLongPathsEnabled() returns a boolean indicating whether long paths are
$ enabled.
%
% The format of the NTLongPathsEnabled method is:
%
% MagickBooleanType NTLongPathsEnabled()
%
*/
MagickExport MagickBooleanType NTLongPathsEnabled()
{
if (long_paths_enabled == 2)
{
DWORD
size,
type,
value;
HKEY
registry_key;
LONG
status;
registry_key=(HKEY) INVALID_HANDLE_VALUE;
status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\FileSystem",0,KEY_READ,
&registry_key);
if (status != ERROR_SUCCESS)
{
RegCloseKey(registry_key);
long_paths_enabled=0;
return(MagickFalse);
}
value=0;
status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,NULL,
NULL);
if ((status != ERROR_SUCCESS) || (type != REG_DWORD))
{
RegCloseKey(registry_key);
long_paths_enabled=0;
return(MagickFalse);
}
size=0;
status=RegQueryValueExA(registry_key,"LongPathsEnabled",0,&type,
(LPBYTE) &value,&size);
RegCloseKey(registry_key);
if (status != ERROR_SUCCESS)
{
long_paths_enabled=0;
return(MagickFalse);
}
long_paths_enabled=(size_t) value;
}
return(long_paths_enabled == 1 ? MagickTrue : MagickFalse);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ N T M a p M e m o r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Mmap() emulates the Unix method of the same name.
%
% The format of the NTMapMemory method is:
%
% MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
% int access,int file,MagickOffsetType offset)
%
*/
MagickPrivate void *NTMapMemory(char *address,size_t length,int protection,
int flags,int file,MagickOffsetType offset)
{
DWORD
access_mode,
high_length,
high_offset,
low_length,
low_offset,
protection_mode;
HANDLE
file_handle,
map_handle;
void
*map;
(void) address;
access_mode=0;
file_handle=INVALID_HANDLE_VALUE;
low_length=(DWORD) (length & 0xFFFFFFFFUL);
high_length=(DWORD) ((((MagickOffsetType) length) >> 32) & 0xFFFFFFFFUL);
map_handle=INVALID_HANDLE_VALUE;
map=(void *) NULL;
low_offset=(DWORD) (offset & 0xFFFFFFFFUL);
high_offset=(DWORD) ((offset >> 32) & 0xFFFFFFFFUL);
protection_mode=0;
if (protection & PROT_WRITE)
{
access_mode=FILE_MAP_WRITE;
if (!(flags & MAP_PRIVATE))
protection_mode=PAGE_READWRITE;
else
{
access_mode=FILE_MAP_COPY;
protection_mode=PAGE_WRITECOPY;
}
}
else
if (protection & PROT_READ)
{
access_mode=FILE_MAP_READ;
protection_mode=PAGE_READONLY;
}
if ((file == -1) && (flags & MAP_ANONYMOUS))
file_handle=INVALID_HANDLE_VALUE;
else
file_handle=(HANDLE) _get_osfhandle(file);
map_handle=CreateFileMapping(file_handle,0,protection_mode,high_length,
low_length,0);
if (map_handle)
{
map=(void *) MapViewOfFile(map_handle,access_mode,high_offset,low_offset,
length);
CloseHandle(map_handle);
}
if (map == (void *) NULL)
return((void *) ((char *) MAP_FAILED));
return((void *) ((char *) map));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T O p e n D i r e c t o r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTOpenDirectory() opens the directory named by filename and associates a
% directory stream with it.
%
% The format of the NTOpenDirectory method is:
%
% DIR *NTOpenDirectory(const char *path)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
*/
MagickPrivate DIR *NTOpenDirectory(const char *path)
{
DIR
*entry;
size_t
length;
wchar_t
file_specification[MagickPathExtent];
assert(path != (const char *) NULL);
length=MultiByteToWideChar(CP_UTF8,0,path,-1,file_specification,
MagickPathExtent);
if (length == 0)
return((DIR *) NULL);
if (wcsncat(file_specification,(const wchar_t*) DirectorySeparator,
MagickPathExtent-wcslen(file_specification)-1) == (wchar_t *) NULL)
return((DIR *) NULL);
entry=(DIR *) AcquireCriticalMemory(sizeof(DIR));
entry->firsttime=TRUE;
entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
if (entry->hSearch == INVALID_HANDLE_VALUE)
{
if(wcsncat(file_specification,L"*.*",
MagickPathExtent-wcslen(file_specification)-1) == (wchar_t *) NULL)
{
entry=(DIR *) RelinquishMagickMemory(entry);
return((DIR *) NULL);
}
entry->hSearch=FindFirstFileW(file_specification,&entry->Win32FindData);
if (entry->hSearch == INVALID_HANDLE_VALUE)
{
entry=(DIR *) RelinquishMagickMemory(entry);
return((DIR *) NULL);
}
}
return(entry);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T O p e n L i b r a r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTOpenLibrary() loads a dynamic module into memory and returns a handle that
% can be used to access the various procedures in the module.
%
% The format of the NTOpenLibrary method is:
%
% void *NTOpenLibrary(const char *filename)
%
% A description of each parameter follows:
%
% o path: Specifies a pointer to string representing dynamic module that
% is to be loaded.
%
*/
static inline const char *GetSearchPath(void)
{
#if defined(MAGICKCORE_LTDL_DELEGATE)
return(lt_dlgetsearchpath());
#else
return(lt_slsearchpath);
#endif
}
static UINT ChangeErrorMode(void)
{
typedef UINT
(CALLBACK *GETERRORMODE)(void);
GETERRORMODE
getErrorMode;
HMODULE
handle;
UINT
mode;
mode=SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
handle=GetModuleHandle("kernel32.dll");
if (handle == (HMODULE) NULL)
return SetErrorMode(mode);
getErrorMode=(GETERRORMODE) NTGetLibrarySymbol(handle,"GetErrorMode");
if (getErrorMode != (GETERRORMODE) NULL)
mode=getErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
return SetErrorMode(mode);
}
static inline void *NTLoadLibrary(const char *filename)
{
int
length;
wchar_t
path[MagickPathExtent];
length=MultiByteToWideChar(CP_UTF8,0,filename,-1,path,MagickPathExtent);
if (length == 0)
return((void *) NULL);
return (void *) LoadLibraryExW(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
}
MagickPrivate void *NTOpenLibrary(const char *filename)
{
char
path[MagickPathExtent];
const char
*p,
*q;
UINT
mode;
void
*handle;
mode=ChangeErrorMode();
handle=NTLoadLibrary(filename);
if (handle == (void *) NULL)
{
p=GetSearchPath();
while (p != (const char*) NULL)
{
q=strchr(p,DirectoryListSeparator);
if (q != (const char*) NULL)
(void) CopyMagickString(path,p,q-p+1);
else
(void) CopyMagickString(path,p,MagickPathExtent);
(void) ConcatenateMagickString(path,DirectorySeparator,MagickPathExtent);
(void) ConcatenateMagickString(path,filename,MagickPathExtent);
handle=NTLoadLibrary(path);
if (handle != (void *) NULL || q == (const char*) NULL)
break;
p=q+1;
}
}
SetErrorMode(mode);
return(handle);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T R e a d D i r e c t o r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTReadDirectory() returns a pointer to a structure representing the
% directory entry at the current position in the directory stream to which
% entry refers.
%
% The format of the NTReadDirectory
%
% NTReadDirectory(entry)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
*/
MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
{
int
status;
size_t
length;
if (entry == (DIR *) NULL)
return((struct dirent *) NULL);
if (!entry->firsttime)
{
status=FindNextFileW(entry->hSearch,&entry->Win32FindData);
if (status == 0)
return((struct dirent *) NULL);
}
length=WideCharToMultiByte(CP_UTF8,0,entry->Win32FindData.cFileName,-1,
entry->file_info.d_name,sizeof(entry->file_info.d_name),NULL,NULL);
if (length == 0)
return((struct dirent *) NULL);
entry->firsttime=FALSE;
entry->file_info.d_namlen=(int) strlen(entry->file_info.d_name);
return(&entry->file_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T R e g i s t r y K e y L o o k u p %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTRegistryKeyLookup() returns ImageMagick installation path settings
% stored in the Windows Registry. Path settings are specific to the
% installed ImageMagick version so that multiple Image Magick installations
% may coexist.
%
% Values are stored in the registry under a base path path similar to
% "HKEY_LOCAL_MACHINE/SOFTWARE\ImageMagick\6.7.4\Q:16" or
% "HKEY_CURRENT_USER/SOFTWARE\ImageMagick\6.7.4\Q:16". The provided subkey
% is appended to this base path to form the full key.
%
% The format of the NTRegistryKeyLookup method is:
%
% unsigned char *NTRegistryKeyLookup(const char *subkey)
%
% A description of each parameter follows:
%
% o subkey: Specifies a string that identifies the registry object.
% Currently supported sub-keys include: "BinPath", "ConfigurePath",
% "LibPath", "CoderModulesPath", "FilterModulesPath", "SharePath".
%
*/
MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
{
char
package_key[MagickPathExtent];
DWORD
size,
type;
HKEY
registry_key;
LONG
status;
unsigned char
*value;
/*
Look-up base key.
*/
(void) FormatLocaleString(package_key,MagickPathExtent,
"SOFTWARE\\%s\\%s\\Q:%d",MagickPackageName,MagickLibVersionText,
MAGICKCORE_QUANTUM_DEPTH);
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"%s",package_key);
registry_key=(HKEY) INVALID_HANDLE_VALUE;
status=RegOpenKeyExA(HKEY_LOCAL_MACHINE,package_key,0,KEY_READ,&registry_key);
if (status != ERROR_SUCCESS)
status=RegOpenKeyExA(HKEY_CURRENT_USER,package_key,0,KEY_READ,
&registry_key);
if (status != ERROR_SUCCESS)
return((unsigned char *) NULL);
/*
Look-up sub key.
*/
size=32;
value=(unsigned char *) AcquireQuantumMemory(size,sizeof(*value));
if (value == (unsigned char *) NULL)
{
RegCloseKey(registry_key);
return((unsigned char *) NULL);
}
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),"%s",subkey);
status=RegQueryValueExA(registry_key,subkey,0,&type,value,&size);
if ((status == ERROR_MORE_DATA) && (type == REG_SZ))
{
value=(unsigned char *) ResizeQuantumMemory(value,size,sizeof(*value));
if (value == (BYTE *) NULL)
{
RegCloseKey(registry_key);
return((unsigned char *) NULL);
}
status=RegQueryValueExA(registry_key,subkey,0,&type,value,&size);
}
RegCloseKey(registry_key);
if ((type != REG_SZ) || (status != ERROR_SUCCESS))
value=(unsigned char *) RelinquishMagickMemory(value);
return((unsigned char *) value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T R e p o r t E v e n t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTReportEvent() reports an event.
%
% The format of the NTReportEvent method is:
%
% MagickBooleanType NTReportEvent(const char *event,
% const MagickBooleanType error)
%
% A description of each parameter follows:
%
% o event: the event.
%
% o error: MagickTrue the event is an error.
%
*/
MagickPrivate MagickBooleanType NTReportEvent(const char *event,
const MagickBooleanType error)
{
const char
*events[1];
HANDLE
handle;
WORD
type;
handle=RegisterEventSource(NULL,MAGICKCORE_PACKAGE_NAME);
if (handle == NULL)
return(MagickFalse);
events[0]=event;
type=error ? EVENTLOG_ERROR_TYPE : EVENTLOG_WARNING_TYPE;
ReportEvent(handle,type,0,0,NULL,1,0,events,NULL);
DeregisterEventSource(handle);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T R e s o u r c e T o B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTResourceToBlob() returns a blob containing the contents of the resource
% in the current executable specified by the id parameter. This currently
% used to retrieve MGK files tha have been embedded into the various command
% line utilities.
%
% The format of the NTResourceToBlob method is:
%
% unsigned char *NTResourceToBlob(const char *id)
%
% A description of each parameter follows:
%
% o id: Specifies a string that identifies the resource.
%
*/
MagickPrivate unsigned char *NTResourceToBlob(const char *id)
{
#ifndef MAGICKCORE_LIBRARY_NAME
char
path[MagickPathExtent];
#endif
DWORD
length;
HGLOBAL
global;
HMODULE
handle;
HRSRC
resource;
unsigned char
*blob,
*value;
assert(id != (const char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
#ifdef MAGICKCORE_LIBRARY_NAME
handle=GetModuleHandle(MAGICKCORE_LIBRARY_NAME);
#else
(void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",GetClientPath(),
DirectorySeparator,GetClientName());
if (IsPathAccessible(path) != MagickFalse)
handle=GetModuleHandle(path);
else
handle=GetModuleHandle(0);
#endif
if (!handle)
return((unsigned char *) NULL);
resource=FindResource(handle,id,"IMAGEMAGICK");
if (!resource)
return((unsigned char *) NULL);
global=LoadResource(handle,resource);
if (!global)
return((unsigned char *) NULL);
length=SizeofResource(handle,resource);
value=(unsigned char *) LockResource(global);
if (!value)
{
FreeResource(global);
return((unsigned char *) NULL);
}
blob=(unsigned char *) AcquireQuantumMemory(length+MagickPathExtent,
sizeof(*blob));
if (blob != (unsigned char *) NULL)
{
(void) memcpy(blob,value,length);
blob[length]='\0';
}
UnlockResource(global);
FreeResource(global);
return(blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T S e t S e a r c h P a t h %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTSetSearchPath() sets the current locations that the subsystem should
% look at to find dynamically loadable modules.
%
% The format of the NTSetSearchPath method is:
%
% int NTSetSearchPath(const char *path)
%
% A description of each parameter follows:
%
% o path: Specifies a pointer to string representing the search path
% for DLL's that can be dynamically loaded.
%
*/
MagickPrivate int NTSetSearchPath(const char *path)
{
#if defined(MAGICKCORE_LTDL_DELEGATE)
lt_dlsetsearchpath(path);
#else
if (lt_slsearchpath != (char *) NULL)
lt_slsearchpath=DestroyString(lt_slsearchpath);
if (path != (char *) NULL)
lt_slsearchpath=AcquireString(path);
#endif
return(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T S y s t e m C o m m a n d %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTSystemCommand() executes the specified command and waits until it
% terminates. The returned value is the exit status of the command.
%
% The format of the NTSystemCommand method is:
%
% int NTSystemCommand(MagickFalse,const char *command)
%
% A description of each parameter follows:
%
% o command: This string is the command to execute.
%
% o output: an optional buffer to store the output from stderr/stdout.
%
*/
MagickPrivate int NTSystemCommand(const char *command,char *output)
{
#define CleanupOutputHandles \
if (read_output != (HANDLE) NULL) \
{ \
CloseHandle(read_output); \
read_output=(HANDLE) NULL; \
CloseHandle(write_output); \
write_output=(HANDLE) NULL; \
}
#define CopyLastError \
if (output != (char *) NULL) \
{ \
error=NTGetLastError(); \
if (error != (char *) NULL) \
{ \
CopyMagickString(output,error,MagickPathExtent); \
error=DestroyString(error); \
} \
}
char
*error,
local_command[MagickPathExtent];
DWORD
child_status;
int
status;
MagickBooleanType
asynchronous;
HANDLE
read_output,
write_output;
PROCESS_INFORMATION
process_info;
SECURITY_ATTRIBUTES
sa;
size_t
output_offset;
STARTUPINFO
startup_info;
if (command == (char *) NULL)
return(-1);
read_output=(HANDLE) NULL;
write_output=(HANDLE) NULL;
GetStartupInfo(&startup_info);
startup_info.dwFlags=STARTF_USESHOWWINDOW;
startup_info.wShowWindow=SW_SHOWMINNOACTIVE;
(void) CopyMagickString(local_command,command,MagickPathExtent);
asynchronous=command[strlen(command)-1] == '&' ? MagickTrue : MagickFalse;
if (asynchronous != MagickFalse)
{
local_command[strlen(command)-1]='\0';
startup_info.wShowWindow=SW_SHOWDEFAULT;
}
else
{
if (command[strlen(command)-1] == '|')
local_command[strlen(command)-1]='\0';
else
startup_info.wShowWindow=SW_HIDE;
read_output=(HANDLE) NULL;
if (output != (char *) NULL)
{
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle=TRUE;
sa.lpSecurityDescriptor=NULL;
if (CreatePipe(&read_output,&write_output,NULL,0))
{
if (SetHandleInformation(write_output,HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT))
{
startup_info.dwFlags|=STARTF_USESTDHANDLES;
startup_info.hStdOutput=write_output;
startup_info.hStdError=write_output;
}
else
CleanupOutputHandles;
}
else
read_output=(HANDLE) NULL;
}
}
status=CreateProcess((LPCTSTR) NULL,local_command,(LPSECURITY_ATTRIBUTES)
NULL,(LPSECURITY_ATTRIBUTES) NULL,(BOOL) TRUE,(DWORD)
NORMAL_PRIORITY_CLASS,(LPVOID) NULL,(LPCSTR) NULL,&startup_info,
&process_info);
if (status == 0)
{
CopyLastError;
CleanupOutputHandles;
return(-1);
}
if (output != (char *) NULL)
*output='\0';
if (asynchronous != MagickFalse)
return(status == 0);
output_offset=0;
status=STATUS_TIMEOUT;
while (status == STATUS_TIMEOUT)
{
DWORD
size;
status=WaitForSingleObject(process_info.hProcess,1000);
size=0;
if (read_output != (HANDLE) NULL)
if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
break;
while (size > 0)
{
char
buffer[MagickPathExtent];
DWORD
bytes_read;
if (ReadFile(read_output,buffer,MagickPathExtent-1,&bytes_read,NULL))
{
size_t
count;
count=MagickMin(MagickPathExtent-output_offset,
(size_t) bytes_read+1);
if (count > 0)
{
CopyMagickString(output+output_offset,buffer,count);
output_offset+=count-1;
}
}
if (!PeekNamedPipe(read_output,NULL,0,NULL,&size,NULL))
break;
}
}
if (status != WAIT_OBJECT_0)
{
CopyLastError;
CleanupOutputHandles;
return(status);
}
status=GetExitCodeProcess(process_info.hProcess,&child_status);
if (status == 0)
{
CopyLastError;
CleanupOutputHandles;
return(-1);
}
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
CleanupOutputHandles;
return((int) child_status);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T S y s t e m C o n i f i g u r a t i o n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTSystemConfiguration() provides a way for the application to determine
% values for system limits or options at runtime.
%
% The format of the exit method is:
%
% ssize_t NTSystemConfiguration(int name)
%
% A description of each parameter follows:
%
% o name: _SC_PAGE_SIZE or _SC_PHYS_PAGES.
%
*/
MagickPrivate ssize_t NTSystemConfiguration(int name)
{
switch (name)
{
case _SC_PAGE_SIZE:
{
SYSTEM_INFO
system_info;
GetSystemInfo(&system_info);
return(system_info.dwPageSize);
}
case _SC_PHYS_PAGES:
{
MEMORYSTATUSEX
status;
SYSTEM_INFO
system_info;
status.dwLength=sizeof(status);
if (GlobalMemoryStatusEx(&status) == 0)
return(0L);
GetSystemInfo(&system_info);
return((ssize_t) status.ullTotalPhys/system_info.dwPageSize);
}
case _SC_OPEN_MAX:
return(2048);
default:
break;
}
return(-1);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T T r u n c a t e F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTTruncateFile() truncates a file to a specified length.
%
% The format of the NTTruncateFile method is:
%
% int NTTruncateFile(int file,off_t length)
%
% A description of each parameter follows:
%
% o file: the file.
%
% o length: the file length.
%
*/
MagickPrivate int NTTruncateFile(int file,off_t length)
{
DWORD
file_pointer;
HANDLE
file_handle;
long
high,
low;
file_handle=(HANDLE) _get_osfhandle(file);
if (file_handle == INVALID_HANDLE_VALUE)
return(-1);
low=(long) (length & 0xffffffffUL);
high=(long) ((((MagickOffsetType) length) >> 32) & 0xffffffffUL);
file_pointer=SetFilePointer(file_handle,low,&high,FILE_BEGIN);
if ((file_pointer == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
return(-1);
if (SetEndOfFile(file_handle) == 0)
return(-1);
return(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ N T U n m a p M e m o r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTUnmapMemory() emulates the Unix munmap method.
%
% The format of the NTUnmapMemory method is:
%
% int NTUnmapMemory(void *map,size_t length)
%
% A description of each parameter follows:
%
% o map: the address of the binary large object.
%
% o length: the length of the binary large object.
%
*/
MagickPrivate int NTUnmapMemory(void *map,size_t length)
{
(void) length;
if (UnmapViewOfFile(map) == 0)
return(-1);
return(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T U s e r T i m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTUserTime() returns the total time the process has been scheduled (e.g.
% seconds) since the last call to StartTimer().
%
% The format of the UserTime method is:
%
% double NTUserTime(void)
%
*/
MagickPrivate double NTUserTime(void)
{
DWORD
status;
FILETIME
create_time,
exit_time;
OSVERSIONINFO
OsVersionInfo;
union
{
FILETIME
filetime;
__int64
filetime64;
} kernel_time;
union
{
FILETIME
filetime;
__int64
filetime64;
} user_time;
OsVersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo);
if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
return(NTElapsedTime());
status=GetProcessTimes(GetCurrentProcess(),&create_time,&exit_time,
&kernel_time.filetime,&user_time.filetime);
if (status != TRUE)
return(0.0);
return((double) 1.0e-7*(kernel_time.filetime64+user_time.filetime64));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T W a r n i n g H a n d l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTWarningHandler() displays a warning reason.
%
% The format of the NTWarningHandler method is:
%
% void NTWarningHandler(const ExceptionType severity,const char *reason,
% const char *description)
%
% A description of each parameter follows:
%
% o severity: Specifies the numeric warning category.
%
% o reason: Specifies the reason to display before terminating the
% program.
%
% o description: Specifies any description to the reason.
%
*/
MagickPrivate void NTWarningHandler(const ExceptionType severity,
const char *reason,const char *description)
{
char
buffer[2*MagickPathExtent];
(void) severity;
if (reason == (char *) NULL)
return;
if (description == (char *) NULL)
(void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s.\n",GetClientName(),
reason);
else
(void) FormatLocaleString(buffer,MagickPathExtent,"%s: %s (%s).\n",
GetClientName(),reason,description);
(void) MessageBox(NULL,buffer,"ImageMagick Warning",MB_OK | MB_TASKMODAL |
MB_SETFOREGROUND | MB_ICONINFORMATION);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T W i n d o w s G e n e s i s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTWindowsGenesis() initializes the MagickCore Windows environment.
%
% The format of the NTWindowsGenesis method is:
%
% void NTWindowsGenesis(void)
%
*/
static LONG WINAPI NTUncaughtException(EXCEPTION_POINTERS *info)
{
magick_unreferenced(info);
AsynchronousResourceComponentTerminus();
return(EXCEPTION_CONTINUE_SEARCH);
}
MagickPrivate void NTWindowsGenesis(void)
{
char
*mode;
SetUnhandledExceptionFilter(NTUncaughtException);
mode=GetEnvironmentValue("MAGICK_ERRORMODE");
if (mode != (char *) NULL)
{
(void) SetErrorMode(StringToInteger(mode));
mode=DestroyString(mode);
}
#if defined(_DEBUG) && !defined(__BORLANDC__) && !defined(__MINGW32__)
if (IsEventLogging() != MagickFalse)
{
int
debug;
debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
//debug |= _CRTDBG_CHECK_ALWAYS_DF;
debug |= _CRTDBG_DELAY_FREE_MEM_DF;
debug |= _CRTDBG_LEAK_CHECK_DF;
(void) _CrtSetDbgFlag(debug);
//_ASSERTE(_CrtCheckMemory());
//_CrtSetBreakAlloc(42);
}
#endif
#if defined(MAGICKCORE_INSTALLED_SUPPORT)
{
unsigned char
*path;
path=NTRegistryKeyLookup("LibPath");
if (path != (unsigned char *) NULL)
{
size_t
length;
wchar_t
lib_path[MagickPathExtent];
length=MultiByteToWideChar(CP_UTF8,0,(char *) path,-1,lib_path,
MagickPathExtent);
if (length != 0)
SetDllDirectoryW(lib_path);
path=(unsigned char *) RelinquishMagickMemory(path);
}
}
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% N T W i n d o w s T e r m i n u s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NTWindowsTerminus() terminates the MagickCore Windows environment.
%
% The format of the NTWindowsTerminus method is:
%
% void NTWindowsTerminus(void)
%
*/
MagickPrivate void NTWindowsTerminus(void)
{
NTGhostscriptUnLoadDLL();
if (winsock_semaphore == (SemaphoreInfo *) NULL)
ActivateSemaphoreInfo(&winsock_semaphore);
LockSemaphoreInfo(winsock_semaphore);
if (wsaData != (WSADATA *) NULL)
{
WSACleanup();
wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData);
}
UnlockSemaphoreInfo(winsock_semaphore);
RelinquishSemaphoreInfo(&winsock_semaphore);
}
#endif