Commit afc7d4aff for imagemagick.org
commit afc7d4aff34cfb085bfdae303f0b69ceb653d839
Author: Dirk Lemstra <dirk@lemstra.org>
Date: Fri Feb 6 12:00:38 2026 +0100
Moved all windows implementations in utility-private to nt-base-private.
diff --git a/MagickCore/blob.c b/MagickCore/blob.c
index addf50b5a..48fd4e66f 100644
--- a/MagickCore/blob.c
+++ b/MagickCore/blob.c
@@ -3254,7 +3254,7 @@ static inline gzFile gzopen_utf8(const char *path,const char *mode)
wchar_t
*path_wide;
- path_wide=create_wchar_path(path);
+ path_wide=NTCreateWidePath(path);
if (path_wide == (wchar_t *) NULL)
return((gzFile) NULL);
file=gzopen_w(path_wide,mode);
diff --git a/MagickCore/nt-base-private.h b/MagickCore/nt-base-private.h
index 2b9b4525d..e839f42d6 100644
--- a/MagickCore/nt-base-private.h
+++ b/MagickCore/nt-base-private.h
@@ -114,6 +114,9 @@ struct timezone
tz_minuteswest,
tz_dsttime;
};
+
+typedef int
+ mode_t;
#endif
#endif
@@ -132,6 +135,9 @@ static inline void *NTAcquireQuantumMemory(const size_t count,
return(AcquireMagickMemory(size));
}
+extern MagickExport char
+ *NTRealPathWide(const char *);
+
extern MagickPrivate char
*NTGetEnvironmentValue(const char *);
@@ -151,6 +157,18 @@ extern MagickPrivate double
NTElapsedTime(void),
NTErf(double);
+extern MagickExport FILE
+ *NTOpenFileWide(const char *,const char *),
+ *NTOpenPipeWide(const char *,const char *);
+
+extern MagickExport int
+ NTAccessWide(const char *,int),
+ NTOpenWide(const char *,int,mode_t),
+ NTRemoveWide(const char *),
+ NTRenameWide(const char *, const char *),
+ NTSetFileTimestamp(const char *,struct stat *),
+ NTStatWide(const char *,struct stat *);
+
extern MagickPrivate int
#if !defined(__MINGW32__)
gettimeofday(struct timeval *,struct timezone *),
@@ -189,6 +207,9 @@ extern MagickPrivate void
NTWindowsGenesis(void),
NTWindowsTerminus(void);
+extern MagickExport wchar_t
+ *NTCreateWidePath(const char *);
+
#endif /* !XS_VERSION */
#endif /* MAGICKCORE_WINDOWS_SUPPORT */
diff --git a/MagickCore/nt-base.c b/MagickCore/nt-base.c
index d9109aacd..c9e138199 100644
--- a/MagickCore/nt-base.c
+++ b/MagickCore/nt-base.c
@@ -436,6 +436,46 @@ MagickPrivate int gettimeofday (struct timeval *time_value,
% %
% %
% %
+% N T A c c e s s W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTAccessWide() checks the file accessibility of a file path.
+#
+# The format of the NTAccessWide method is:
+%
+% int NTAccessWide(const char *path, int mode)
+%
+% A description of each parameter follows:
+%
+% o path: the file path.
+%
+% o mode: the accessibility mode.
+%
+*/
+MagickExport int NTAccessWide(const char *path, int mode)
+{
+ int
+ status;
+
+ wchar_t
+ *path_wide;
+
+ path_wide=NTCreateWidePath(path);
+ if (path_wide == (wchar_t *) NULL)
+ return(-1);
+ status=_waccess(path_wide,mode);
+ path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% N T A r g v T o U T F 8 %
% %
% %
@@ -540,6 +580,74 @@ MagickPrivate int NTCloseLibrary(void *handle)
return(FreeLibrary((HINSTANCE) handle) ? 0 : 1);
}
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% N T C r e a t e W i d e P a t h %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTCreateWidePath() returns the wide-character version of the specified
+% UTF-8 path.
+%
+% The format of the NTCreateWidePath method is:
+%
+% void NTCreateWidePath(void *handle)
+%
+% A description of each parameter follows:
+%
+% o utf8: Specifies a handle to a previously loaded dynamic module.
+%
+*/
+MagickExport wchar_t* NTCreateWidePath(const char *utf8)
+{
+ int
+ count;
+
+ wchar_t
+ *wide;
+
+ count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);
+ if ((count > MAX_PATH) && (strncmp(utf8,"\\\\?\\",4) != 0) &&
+ (NTLongPathsEnabled() == MagickFalse))
+ {
+ char
+ buffer[MagickPathExtent];
+
+ wchar_t
+ shortPath[MAX_PATH],
+ *longPath;
+
+ size_t
+ length;
+
+ (void) FormatLocaleString(buffer,MagickPathExtent,"\\\\?\\%s",utf8);
+ count+=4;
+ longPath=(wchar_t *) NTAcquireQuantumMemory((size_t) count,
+ sizeof(*longPath));
+ if (longPath == (wchar_t *) NULL)
+ return((wchar_t *) NULL);
+ count=MultiByteToWideChar(CP_UTF8,0,buffer,-1,longPath,count);
+ if (count != 0)
+ count=(int) GetShortPathNameW(longPath,shortPath,MAX_PATH);
+ longPath=(wchar_t *) RelinquishMagickMemory(longPath);
+ if ((count < 5) || (count >= MAX_PATH))
+ return((wchar_t *) NULL);
+ length=(size_t) count-3;
+ wide=(wchar_t *) NTAcquireQuantumMemory(length,sizeof(*wide));
+ wcscpy_s(wide,length,shortPath+4);
+ return(wide);
+ }
+ wide=(wchar_t *) NTAcquireQuantumMemory((size_t) count,sizeof(*wide));
+ if ((wide != (wchar_t *) NULL) &&
+ (MultiByteToWideChar(CP_UTF8,0,utf8,-1,wide,count) == 0))
+ wide=(wchar_t *) RelinquishMagickMemory(wide);
+ return(wide);
+}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -645,7 +753,6 @@ MagickPrivate double NTErf(double x)
return(sign*y);
}
-
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
@@ -972,8 +1079,7 @@ void *NTGetLibrarySymbol(void *handle,const char *name)
return((void *) NULL);
return((void *) proc_address);
}
-
-
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
@@ -1734,7 +1840,6 @@ MagickPrivate DIR *NTOpenDirectory(const char *path)
% is to be loaded.
%
*/
-
static UINT ChangeErrorMode(void)
{
typedef UINT
@@ -1771,7 +1876,7 @@ static inline void *NTLoadLibrary(const char *filename)
*path;
library=(void *) NULL;
- path=create_wchar_path(filename);
+ path=NTCreateWidePath(filename);
if (path != (wchar_t *) NULL)
{
library=LoadLibraryExW(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
@@ -1826,6 +1931,177 @@ MagickPrivate void *NTOpenLibrary(const char *filename)
% %
% %
% %
+% N T O p e n F i l e W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTOpenFileWide() opens a file and returns a file pointer.
+%
+% The format of the NTOpenFileWide method is:
+%
+% FILE *NTOpenFileWide(const char* path, const char* mode)
+%
+% A description of each parameter follows:
+%
+% o path: the file path.
+%
+% o mode: the file open mode.
+%
+*/
+static inline wchar_t *create_wchar_mode(const char *mode)
+{
+ int
+ count;
+
+ wchar_t
+ *wide;
+
+ count=MultiByteToWideChar(CP_UTF8,0,mode,-1,NULL,0);
+ wide=(wchar_t *) AcquireQuantumMemory((size_t) count+1,
+ sizeof(*wide));
+ if (wide == (wchar_t *) NULL)
+ return((wchar_t *) NULL);
+ if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wide,count) == 0)
+ {
+ wide=(wchar_t *) RelinquishMagickMemory(wide);
+ return((wchar_t *) NULL);
+ }
+ /* Specifies that the file is not inherited by child processes */
+ wide[count] = L'\0';
+ wide[count-1] = L'N';
+ return(wide);
+}
+
+MagickExport FILE *NTOpenFileWide(const char* path, const char* mode)
+{
+ FILE
+ *file;
+
+ wchar_t
+ *mode_wide,
+ *path_wide;
+
+ path_wide=NTCreateWidePath(path);
+ if (path_wide == (wchar_t *) NULL)
+ return((FILE *) NULL);
+ mode_wide=create_wchar_mode(mode);
+ if (mode_wide == (wchar_t *) NULL)
+ {
+ path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
+ return((FILE *) NULL);
+ }
+ if (_wfopen_s(&file,path_wide,mode_wide) != 0)
+ file=(FILE *) NULL;
+ mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
+ path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
+ return(file);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% N T O p e n P i p e W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTOpenPipeWide() opens a pipe and returns a file pointer.
+%
+% The format of the NTOpenPipeWide method is:
+%
+% FILE *NTOpenPipeWide(const char* command, const char* type)
+%
+% A description of each parameter follows:
+%
+% o command: the command to execute.
+%
+% o type: the file open mode.
+%
+*/
+MagickExport FILE *NTOpenPipeWide(const char *command,const char *type)
+{
+ FILE
+ *file;
+
+ int
+ length;
+
+ wchar_t
+ *command_wide,
+ type_wide[5];
+
+ file=(FILE *) NULL;
+ length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
+ if (length == 0)
+ return(file);
+ length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
+ if (length == 0)
+ return(file);
+ command_wide=(wchar_t *) AcquireQuantumMemory((size_t) length,
+ sizeof(*command_wide));
+ if (command_wide == (wchar_t *) NULL)
+ return(file);
+ length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
+ if (length != 0)
+ file=_wpopen(command_wide,type_wide);
+ command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
+ return(file);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% N T O p e n W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTOpenWide() opens the file specified by path and mode.
+%
+% The format of the NTOpenWide method is:
+%
+% FILE *NTOpenWide(const char* path, const char* mode)
+%
+% A description of each parameter follows:
+%
+% o path: the file path.
+%
+% o flags: the file open flags.
+%
+% o mode: the file open mode.
+%
+*/
+MagickExport int NTOpenWide(const char* path,int flags,mode_t mode)
+{
+ int
+ file_handle,
+ status;
+
+ wchar_t
+ *path_wide;
+
+ path_wide=NTCreateWidePath(path);
+ if (path_wide == (wchar_t *) NULL)
+ return(-1);
+ /* O_NOINHERIT specifies that the file is not inherited by child processes */
+ status=_wsopen_s(&file_handle,path_wide,flags | O_NOINHERIT,_SH_DENYNO,mode);
+ path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
+ return(status == 0 ? file_handle : -1);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% N T R e a d D i r e c t o r y %
% %
% %
@@ -1875,6 +2151,135 @@ MagickPrivate struct dirent *NTReadDirectory(DIR *entry)
% %
% %
% %
+% N T R e a l P a t h W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTRealPathWide returns the absolute path of the specified path.
+%
+% The format of the NTRealPathWide method is:
+%
+% char *NTRealPathWide(const char *path)
+%
+% A description of each parameter follows:
+%
+% o path: the file path.
+%
+*/
+MagickExport char *NTRealPathWide(const char *path)
+{
+ char
+ *real_path;
+
+ DWORD
+ final_path_length,
+ full_path_length;
+
+ HANDLE
+ file_handle;
+
+ int
+ length,
+ utf8_length;
+
+ wchar_t
+ *clean_path,
+ *full_path,
+ *wide_path;
+
+ /*
+ Convert UTF-8 to UTF-16.
+ */
+ if (path == (const char *) NULL)
+ return((char *) NULL);
+ length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
+ if (length <= 0)
+ return((char *) NULL);
+ wide_path=(wchar_t *) AcquireQuantumMemory(length,sizeof(wchar_t));
+ if (wide_path == (wchar_t *) NULL)
+ return((char *) NULL);
+ MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
+ /*
+ Normalize syntactically.
+ */
+ full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
+ if (full_path_length == 0)
+ {
+ wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
+ return((char *) NULL);
+ }
+ full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
+ if (full_path == (wchar_t *) NULL)
+ {
+ wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
+ return((char *) NULL);
+ }
+ GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
+ wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
+ /*
+ Open the file/directory to resolve symlinks.
+ */
+ file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
+ FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,NULL);
+ if (file_handle != INVALID_HANDLE_VALUE)
+ {
+ /*
+ Resolve final canonical path.
+ */
+ final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
+ FILE_NAME_NORMALIZED);
+ if (final_path_length == 0)
+ {
+ CloseHandle(file_handle);
+ full_path=(wchar_t *) RelinquishMagickMemory(full_path);
+ return((char *) NULL);
+ }
+ full_path=(wchar_t *) RelinquishMagickMemory(full_path);
+ full_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
+ sizeof(wchar_t));
+ if (full_path == (wchar_t *) NULL)
+ {
+ CloseHandle(file_handle);
+ return((char *) NULL);
+ }
+ GetFinalPathNameByHandleW(file_handle,full_path,final_path_length,
+ FILE_NAME_NORMALIZED);
+ CloseHandle(file_handle);
+ }
+ /*
+ Remove \\?\ prefix for POSIX-like behavior.
+ */
+ clean_path=full_path;
+ if (wcsncmp(full_path,L"\\\\?\\",4) == 0)
+ clean_path=full_path+4;
+ /*
+ Convert UTF-16 to UTF-8.
+ */
+ utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
+ if (utf8_length <= 0)
+ {
+ full_path=(wchar_t *) RelinquishMagickMemory(full_path);
+ return NULL;
+ }
+ real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
+ if (real_path == (char *) NULL)
+ {
+ full_path=(wchar_t *) RelinquishMagickMemory(full_path);
+ return NULL;
+ }
+ WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
+ full_path=(wchar_t *) RelinquishMagickMemory(full_path);
+ return(real_path);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% N T R e g i s t r y K e y L o o k u p %
% %
% %
@@ -1924,6 +2329,92 @@ MagickPrivate unsigned char *NTRegistryKeyLookup(const char *subkey)
% %
% %
% %
+% N T R e m o v e W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTRemoveWide() removes the specified file.
+%
+% The format of the NTRemoveWide method is:
+%
+% int NTRemoveWide(const char *path)
+%
+% A description of each parameter follows:
+%
+% o path: the file path.
+%
+*/
+MagickExport int NTRemoveWide(const char *path)
+{
+ int
+ status;
+
+ wchar_t
+ *path_wide;
+
+ path_wide=NTCreateWidePath(path);
+ if (path_wide == (wchar_t *) NULL)
+ return(-1);
+ status=_wremove(path_wide);
+ path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% N T R e n a m e W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTRenameWide() renames a file.
+%
+% The format of the NTRenameWide method is:
+%
+% int NTRenameWide(const char *source, const char *destination)
+%
+% A description of each parameter follows:
+%
+% o source: the source file path.
+%
+% o destination: the destination file path.
+%
+*/
+MagickExport int NTRenameWide(const char* source, const char* destination)
+{
+ int
+ status;
+
+ wchar_t
+ *destination_wide,
+ *source_wide;
+
+ source_wide=NTCreateWidePath(source);
+ if (source_wide == (wchar_t *) NULL)
+ return(-1);
+ destination_wide=NTCreateWidePath(destination);
+ if (destination_wide == (wchar_t *) NULL)
+ {
+ source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
+ return(-1);
+ }
+ status=_wrename(source_wide,destination_wide);
+ destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
+ source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% N T R e p o r t E v e n t %
% %
% %
@@ -2059,6 +2550,117 @@ MagickPrivate unsigned char *NTResourceToBlob(const char *id)
% %
% %
% %
+% NT S e t F i l e T i m e s t a m p %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTSetFileTimestamp() sets the file timestamps for a specified file.
+%
+% The format of the NTSetFileTimestamp method is:
+%
+% int NTSetFileTimestamp(const char *path, struct stat *attributes)
+%
+% A description of each parameter follows:
+%
+% o path: the file path.
+%
+% o attributes: the file attributes.
+%
+*/
+MagickExport int NTSetFileTimestamp(const char *path, struct stat *attributes)
+{
+ HANDLE
+ handle;
+
+ int
+ status;
+
+ wchar_t
+ *path_wide;
+
+ status=(-1);
+ path_wide=NTCreateWidePath(path);
+ if (path_wide == (WCHAR *) NULL)
+ return(status);
+ handle=CreateFileW(path_wide,FILE_WRITE_ATTRIBUTES,FILE_SHARE_WRITE |
+ FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
+ if (handle != (HANDLE) NULL)
+ {
+ FILETIME
+ creation_time,
+ last_access_time,
+ last_write_time;
+
+ ULARGE_INTEGER
+ date_time;
+
+ date_time.QuadPart=(ULONGLONG) (attributes->st_ctime*10000000LL)+
+ 116444736000000000LL;
+ creation_time.dwLowDateTime=date_time.LowPart;
+ creation_time.dwHighDateTime=date_time.HighPart;
+ date_time.QuadPart=(ULONGLONG) (attributes->st_atime*10000000LL)+
+ 116444736000000000LL;
+ last_access_time.dwLowDateTime=date_time.LowPart;
+ last_access_time.dwHighDateTime=date_time.HighPart;
+ date_time.QuadPart=(ULONGLONG) (attributes->st_mtime*10000000LL)+
+ 116444736000000000LL;
+ last_write_time.dwLowDateTime=date_time.LowPart;
+ last_write_time.dwHighDateTime=date_time.HighPart;
+ status=SetFileTime(handle,&creation_time,&last_access_time,&last_write_time);
+ CloseHandle(handle);
+ status=0;
+ }
+ path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% N T S t a t W i d e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NTStatWide() gets the file attributes for a specified file.
+%
+% The format of the NTStatWide method is:
+%
+% int NTStatWide(const char *path,struct stat *attributes)
+%
+% A description of each parameter follows:
+%
+% o path: the file path.
+%
+% o attributes: the file attributes.
+%
+*/
+MagickExport int NTStatWide(const char *path,struct stat *attributes)
+{
+ int
+ status;
+
+ wchar_t
+ *path_wide;
+
+ path_wide=NTCreateWidePath(path);
+ if (path_wide == (WCHAR *) NULL)
+ return(-1);
+ status=wstat(path_wide,attributes);
+ path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% N T S y s t e m C o m m a n d %
% %
% %
@@ -2441,7 +3043,6 @@ MagickPrivate void NTWarningHandler(const ExceptionType severity,
% void NTWindowsGenesis(void)
%
*/
-
MagickPrivate void NTWindowsGenesis(void)
{
char
@@ -2492,8 +3093,7 @@ MagickPrivate void NTWindowsGenesis(void)
}
#endif
}
-
-
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
diff --git a/MagickCore/utility-private.h b/MagickCore/utility-private.h
index d8b68e0e1..dea9cf71a 100644
--- a/MagickCore/utility-private.h
+++ b/MagickCore/utility-private.h
@@ -56,82 +56,6 @@ static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
return(errno);
}
-/*
- Windows UTF8 compatibility methods.
-*/
-
-#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__)
-static inline wchar_t *create_wchar_path(const char *utf8)
-{
- int
- count;
-
- wchar_t
- *wide;
-
- count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);
- if ((count > MAX_PATH) && (strncmp(utf8,"\\\\?\\",4) != 0) &&
- (NTLongPathsEnabled() == MagickFalse))
- {
- char
- buffer[MagickPathExtent];
-
- wchar_t
- shortPath[MAX_PATH],
- *longPath;
-
- size_t
- length;
-
- (void) FormatLocaleString(buffer,MagickPathExtent,"\\\\?\\%s",utf8);
- count+=4;
- longPath=(wchar_t *) NTAcquireQuantumMemory((size_t) count,
- sizeof(*longPath));
- if (longPath == (wchar_t *) NULL)
- return((wchar_t *) NULL);
- count=MultiByteToWideChar(CP_UTF8,0,buffer,-1,longPath,count);
- if (count != 0)
- count=(int) GetShortPathNameW(longPath,shortPath,MAX_PATH);
- longPath=(wchar_t *) RelinquishMagickMemory(longPath);
- if ((count < 5) || (count >= MAX_PATH))
- return((wchar_t *) NULL);
- length=(size_t) count-3;
- wide=(wchar_t *) NTAcquireQuantumMemory(length,sizeof(*wide));
- wcscpy_s(wide,length,shortPath+4);
- return(wide);
- }
- wide=(wchar_t *) NTAcquireQuantumMemory((size_t) count,sizeof(*wide));
- if ((wide != (wchar_t *) NULL) &&
- (MultiByteToWideChar(CP_UTF8,0,utf8,-1,wide,count) == 0))
- wide=(wchar_t *) RelinquishMagickMemory(wide);
- return(wide);
-}
-
-static inline wchar_t *create_wchar_mode(const char *mode)
-{
- int
- count;
-
- wchar_t
- *wide;
-
- count=MultiByteToWideChar(CP_UTF8,0,mode,-1,NULL,0);
- wide=(wchar_t *) AcquireQuantumMemory((size_t) count+1,
- sizeof(*wide));
- if (wide == (wchar_t *) NULL)
- return((wchar_t *) NULL);
- if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wide,count) == 0)
- {
- wide=(wchar_t *) RelinquishMagickMemory(wide);
- return((wchar_t *) NULL);
- }
- /* Specifies that the file is not inherited by child processes */
- wide[count] = L'\0';
- wide[count-1] = L'N';
- return(wide);
-}
-#endif
-
static inline int access_utf8(const char *path,int mode)
{
if (path == (const char *) NULL)
@@ -139,18 +63,7 @@ static inline int access_utf8(const char *path,int mode)
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
return(access(path,mode));
#else
- int
- status;
-
- wchar_t
- *path_wide;
-
- path_wide=create_wchar_path(path);
- if (path_wide == (wchar_t *) NULL)
- return(-1);
- status=_waccess(path_wide,mode);
- path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
- return(status);
+ return(NTAccessWide(path,mode));
#endif
}
@@ -165,71 +78,16 @@ static inline FILE *fopen_utf8(const char *path,const char *mode)
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
return(fopen(path,mode));
#else
- FILE
- *file;
-
- wchar_t
- *mode_wide,
- *path_wide;
-
- path_wide=create_wchar_path(path);
- if (path_wide == (wchar_t *) NULL)
- return((FILE *) NULL);
- mode_wide=create_wchar_mode(mode);
- if (mode_wide == (wchar_t *) NULL)
- {
- path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
- return((FILE *) NULL);
- }
- if (_wfopen_s(&file,path_wide,mode_wide) != 0)
- file=(FILE *) NULL;
- mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
- path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
- return(file);
-#endif
-}
-
-static inline void getcwd_utf8(char *path,size_t extent)
-{
-#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
- char
- *directory;
-
- directory=getcwd(path,extent);
- (void) directory;
-#else
- wchar_t
- wide_path[MagickPathExtent];
-
- (void) _wgetcwd(wide_path,MagickPathExtent-1);
- (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
+ return(NTOpenFileWide(path,mode));
#endif
}
-#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__)
-typedef int
- mode_t;
-#endif
-
static inline int open_utf8(const char *path,int flags,mode_t mode)
{
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
return(open(path,flags,mode));
#else
- int
- file_handle,
- status;
-
- wchar_t
- *path_wide;
-
- path_wide=create_wchar_path(path);
- if (path_wide == (wchar_t *) NULL)
- return(-1);
- /* O_NOINHERIT specifies that the file is not inherited by child processes */
- status=_wsopen_s(&file_handle,path_wide,flags | O_NOINHERIT,_SH_DENYNO,mode);
- path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
- return(status == 0 ? file_handle : -1);
+ return(NTOpenWide(path,flags,mode));
#endif
}
@@ -238,32 +96,7 @@ static inline FILE *popen_utf8(const char *command,const char *type)
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
return(popen(command,type));
#else
- FILE
- *file;
-
- int
- length;
-
- wchar_t
- *command_wide,
- type_wide[5];
-
- file=(FILE *) NULL;
- length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
- if (length == 0)
- return(file);
- length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
- if (length == 0)
- return(file);
- command_wide=(wchar_t *) AcquireQuantumMemory((size_t) length,
- sizeof(*command_wide));
- if (command_wide == (wchar_t *) NULL)
- return(file);
- length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
- if (length != 0)
- file=_wpopen(command_wide,type_wide);
- command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
- return(file);
+ return(NTOpenPipeWide(command,type));
#endif
}
@@ -276,109 +109,7 @@ static inline char *realpath_utf8(const char *path)
return(AcquireString(path));
#endif
#else
- char
- *real_path;
-
- DWORD
- final_path_length,
- full_path_length;
-
- HANDLE
- file_handle;
-
- int
- length,
- utf8_length;
-
- wchar_t
- *clean_path,
- *full_path,
- *wide_path;
-
- /*
- Convert UTF-8 to UTF-16.
- */
- if (path == (const char *) NULL)
- return((char *) NULL);
- length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
- if (length <= 0)
- return((char *) NULL);
- wide_path=(wchar_t *) AcquireQuantumMemory(length,sizeof(wchar_t));
- if (wide_path == (wchar_t *) NULL)
- return((char *) NULL);
- MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
- /*
- Normalize syntactically.
- */
- full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
- if (full_path_length == 0)
- {
- wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
- return((char *) NULL);
- }
- full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
- if (full_path == (wchar_t *) NULL)
- {
- wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
- return((char *) NULL);
- }
- GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
- wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
- /*
- Open the file/directory to resolve symlinks.
- */
- file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
- FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,NULL);
- if (file_handle != INVALID_HANDLE_VALUE)
- {
- /*
- Resolve final canonical path.
- */
- final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
- FILE_NAME_NORMALIZED);
- if (final_path_length == 0)
- {
- CloseHandle(file_handle);
- full_path=(wchar_t *) RelinquishMagickMemory(full_path);
- return((char *) NULL);
- }
- full_path=(wchar_t *) RelinquishMagickMemory(full_path);
- full_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
- sizeof(wchar_t));
- if (full_path == (wchar_t *) NULL)
- {
- CloseHandle(file_handle);
- return((char *) NULL);
- }
- GetFinalPathNameByHandleW(file_handle,full_path,final_path_length,
- FILE_NAME_NORMALIZED);
- CloseHandle(file_handle);
- }
- /*
- Remove \\?\ prefix for POSIX-like behavior.
- */
- clean_path=full_path;
- if (wcsncmp(full_path,L"\\\\?\\",4) == 0)
- clean_path=full_path+4;
- /*
- Convert UTF-16 to UTF-8.
- */
- utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
- if (utf8_length <= 0)
- {
- full_path=(wchar_t *) RelinquishMagickMemory(full_path);
- return NULL;
- }
- real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
- if (real_path == (char *) NULL)
- {
- full_path=(wchar_t *) RelinquishMagickMemory(full_path);
- return NULL;
- }
- WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
- full_path=(wchar_t *) RelinquishMagickMemory(full_path);
- return(real_path);
+ return(NTRealPathWide(path));
#endif
}
@@ -387,18 +118,7 @@ static inline int remove_utf8(const char *path)
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
return(unlink(path));
#else
- int
- status;
-
- wchar_t
- *path_wide;
-
- path_wide=create_wchar_path(path);
- if (path_wide == (wchar_t *) NULL)
- return(-1);
- status=_wremove(path_wide);
- path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
- return(status);
+ return(NTRemoveWide(path));
#endif
}
@@ -407,26 +127,7 @@ static inline int rename_utf8(const char *source,const char *destination)
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
return(rename(source,destination));
#else
- int
- status;
-
- wchar_t
- *destination_wide,
- *source_wide;
-
- source_wide=create_wchar_path(source);
- if (source_wide == (wchar_t *) NULL)
- return(-1);
- destination_wide=create_wchar_path(destination);
- if (destination_wide == (wchar_t *) NULL)
- {
- source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
- return(-1);
- }
- status=_wrename(source_wide,destination_wide);
- destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
- source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
- return(status);
+ return(NTRenameWide(source,destination));
#endif
}
@@ -460,45 +161,7 @@ static inline int set_file_timestamp(const char *path,struct stat *attributes)
status=utime(path,×tamp);
#endif
#else
- HANDLE
- handle;
-
- wchar_t
- *path_wide;
-
- status=(-1);
- path_wide=create_wchar_path(path);
- if (path_wide == (WCHAR *) NULL)
- return(status);
- handle=CreateFileW(path_wide,FILE_WRITE_ATTRIBUTES,FILE_SHARE_WRITE |
- FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
- if (handle != (HANDLE) NULL)
- {
- FILETIME
- creation_time,
- last_access_time,
- last_write_time;
-
- ULARGE_INTEGER
- date_time;
-
- date_time.QuadPart=(ULONGLONG) (attributes->st_ctime*10000000LL)+
- 116444736000000000LL;
- creation_time.dwLowDateTime=date_time.LowPart;
- creation_time.dwHighDateTime=date_time.HighPart;
- date_time.QuadPart=(ULONGLONG) (attributes->st_atime*10000000LL)+
- 116444736000000000LL;
- last_access_time.dwLowDateTime=date_time.LowPart;
- last_access_time.dwHighDateTime=date_time.HighPart;
- date_time.QuadPart=(ULONGLONG) (attributes->st_mtime*10000000LL)+
- 116444736000000000LL;
- last_write_time.dwLowDateTime=date_time.LowPart;
- last_write_time.dwHighDateTime=date_time.HighPart;
- status=SetFileTime(handle,&creation_time,&last_access_time,&last_write_time);
- CloseHandle(handle);
- status=0;
- }
- path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
+ status=NTSetFileTimestamp(path,attributes);
#endif
return(status);
}
@@ -508,18 +171,7 @@ static inline int stat_utf8(const char *path,struct stat *attributes)
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
return(stat(path,attributes));
#else
- int
- status;
-
- wchar_t
- *path_wide;
-
- path_wide=create_wchar_path(path);
- if (path_wide == (WCHAR *) NULL)
- return(-1);
- status=wstat(path_wide,attributes);
- path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
- return(status);
+ return(NTStatWide(path,attributes));
#endif
}
diff --git a/MagickCore/utility.c b/MagickCore/utility.c
index 4e78d2891..acb344149 100644
--- a/MagickCore/utility.c
+++ b/MagickCore/utility.c
@@ -745,6 +745,23 @@ MagickPrivate void ExpandFilename(char *path)
% line arguments.
%
*/
+static inline void getcwd_utf8(char *path,size_t extent)
+{
+#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
+ char
+ *directory;
+
+ directory=getcwd(path,extent);
+ (void) directory;
+#else
+ wchar_t
+ wide_path[MagickPathExtent];
+
+ (void) _wgetcwd(wide_path,MagickPathExtent-1);
+ (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
+#endif
+}
+
MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
char ***arguments)
{
diff --git a/coders/dng.c b/coders/dng.c
index 8b619ea36..93af18fbd 100644
--- a/coders/dng.c
+++ b/coders/dng.c
@@ -493,7 +493,7 @@ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
wchar_t
*path;
- path=create_wchar_path(image->filename);
+ path=NTCreateWidePath(image->filename);
if (path != (wchar_t *) NULL)
{
errcode=libraw_open_wfile(raw_info,path);
diff --git a/coders/emf.c b/coders/emf.c
index a9cb7017b..787b1f01c 100644
--- a/coders/emf.c
+++ b/coders/emf.c
@@ -714,7 +714,7 @@ static Image *ReadEMFImage(const ImageInfo *image_info,
Gdiplus::Status::Ok)
ThrowReaderException(CoderError, "GdiplusStartupFailed");
source=(Gdiplus::Image *) NULL;
- path=create_wchar_path(image->filename);
+ path=NTCreateWidePath(image->filename);
if (path != (wchar_t *) NULL)
{
source=Gdiplus::Image::FromFile(path);