Add support for long filenames on Windows 10
This commit is contained in:
@@ -7,6 +7,7 @@ vpath %.h $(SRCPATH)
|
|||||||
vpath %.S $(SRCPATH)
|
vpath %.S $(SRCPATH)
|
||||||
vpath %.asm $(SRCPATH)
|
vpath %.asm $(SRCPATH)
|
||||||
vpath %.rc $(SRCPATH)
|
vpath %.rc $(SRCPATH)
|
||||||
|
vpath %.manifest $(SRCPATH)
|
||||||
|
|
||||||
CFLAGS += $(CFLAGSPROF)
|
CFLAGS += $(CFLAGSPROF)
|
||||||
LDFLAGS += $(LDFLAGSPROF)
|
LDFLAGS += $(LDFLAGSPROF)
|
||||||
@@ -312,7 +313,7 @@ $(OBJS) $(OBJASM) $(OBJSO) $(OBJCLI) $(OBJCHK) $(OBJCHK_8) $(OBJCHK_10) $(OBJEXA
|
|||||||
%.dll.o: %.rc x264.h
|
%.dll.o: %.rc x264.h
|
||||||
$(RC) $(RCFLAGS)$@ -DDLL $<
|
$(RC) $(RCFLAGS)$@ -DDLL $<
|
||||||
|
|
||||||
%.o: %.rc x264.h
|
%.o: %.rc x264.h x264res.manifest
|
||||||
$(RC) $(RCFLAGS)$@ $<
|
$(RC) $(RCFLAGS)$@ $<
|
||||||
|
|
||||||
.depend: config.mak
|
.depend: config.mak
|
||||||
|
|||||||
+91
-41
@@ -116,30 +116,65 @@ static inline int x264_snprintf( char *s, size_t n, const char *fmt, ... )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define utf8_to_utf16( utf8, utf16 )\
|
|
||||||
MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, utf16, sizeof(utf16)/sizeof(wchar_t) )
|
|
||||||
|
|
||||||
/* Functions for dealing with Unicode on Windows. */
|
/* Functions for dealing with Unicode on Windows. */
|
||||||
static inline FILE *x264_fopen( const char *filename, const char *mode )
|
static inline wchar_t *x264_utf8_to_utf16( const char *utf8 )
|
||||||
{
|
{
|
||||||
wchar_t filename_utf16[MAX_PATH];
|
int len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, NULL, 0 );
|
||||||
wchar_t mode_utf16[16];
|
if( len )
|
||||||
if( utf8_to_utf16( filename, filename_utf16 ) && utf8_to_utf16( mode, mode_utf16 ) )
|
{
|
||||||
return _wfopen( filename_utf16, mode_utf16 );
|
wchar_t *utf16 = malloc( len * sizeof( wchar_t ) );
|
||||||
|
if( utf16 )
|
||||||
|
{
|
||||||
|
if( MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, utf16, len ) )
|
||||||
|
return utf16;
|
||||||
|
free( utf16 );
|
||||||
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline wchar_t *x264_utf8_to_utf16_try_buf( const char *utf8, wchar_t *buf_utf16, int buf_len ) {
|
||||||
|
if( MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, utf8, -1, buf_utf16, buf_len ) )
|
||||||
|
return buf_utf16;
|
||||||
|
return x264_utf8_to_utf16( utf8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#define x264_fopen( filename, mode ) x264_fopen_internal( filename, L##mode )
|
||||||
|
static inline FILE *x264_fopen_internal( const char *filename, const wchar_t *mode_utf16 )
|
||||||
|
{
|
||||||
|
FILE *f = NULL;
|
||||||
|
wchar_t filename_buf[MAX_PATH];
|
||||||
|
wchar_t *filename_utf16 = x264_utf8_to_utf16_try_buf( filename, filename_buf, MAX_PATH );
|
||||||
|
if( filename_utf16 )
|
||||||
|
{
|
||||||
|
f = _wfopen( filename_utf16, mode_utf16 );
|
||||||
|
if( filename_utf16 != filename_buf )
|
||||||
|
free( filename_utf16 );
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int x264_rename( const char *oldname, const char *newname )
|
static inline int x264_rename( const char *oldname, const char *newname )
|
||||||
{
|
{
|
||||||
wchar_t oldname_utf16[MAX_PATH];
|
int ret = -1;
|
||||||
wchar_t newname_utf16[MAX_PATH];
|
wchar_t oldname_buf[MAX_PATH];
|
||||||
if( utf8_to_utf16( oldname, oldname_utf16 ) && utf8_to_utf16( newname, newname_utf16 ) )
|
wchar_t *oldname_utf16 = x264_utf8_to_utf16_try_buf( oldname, oldname_buf, MAX_PATH );
|
||||||
|
if( oldname_utf16 )
|
||||||
{
|
{
|
||||||
/* POSIX says that rename() removes the destination, but Win32 doesn't. */
|
wchar_t newname_buf[MAX_PATH];
|
||||||
_wunlink( newname_utf16 );
|
wchar_t *newname_utf16 = x264_utf8_to_utf16_try_buf( newname, newname_buf, MAX_PATH );
|
||||||
return _wrename( oldname_utf16, newname_utf16 );
|
if( newname_utf16 )
|
||||||
|
{
|
||||||
|
/* POSIX says that rename() removes the destination, but Win32 doesn't. */
|
||||||
|
_wunlink( newname_utf16 );
|
||||||
|
ret = _wrename( oldname_utf16, newname_utf16 );
|
||||||
|
if( newname_utf16 != newname_buf )
|
||||||
|
free( newname_utf16 );
|
||||||
|
}
|
||||||
|
if( oldname_utf16 != oldname_buf )
|
||||||
|
free( oldname_utf16 );
|
||||||
}
|
}
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define x264_struct_stat struct _stati64
|
#define x264_struct_stat struct _stati64
|
||||||
@@ -147,10 +182,16 @@ static inline int x264_rename( const char *oldname, const char *newname )
|
|||||||
|
|
||||||
static inline int x264_stat( const char *path, x264_struct_stat *buf )
|
static inline int x264_stat( const char *path, x264_struct_stat *buf )
|
||||||
{
|
{
|
||||||
wchar_t path_utf16[MAX_PATH];
|
int ret = -1;
|
||||||
if( utf8_to_utf16( path, path_utf16 ) )
|
wchar_t path_buf[MAX_PATH];
|
||||||
return _wstati64( path_utf16, buf );
|
wchar_t *path_utf16 = x264_utf8_to_utf16_try_buf( path, path_buf, MAX_PATH );
|
||||||
return -1;
|
if( path_utf16 )
|
||||||
|
{
|
||||||
|
ret = _wstati64( path_utf16, buf );
|
||||||
|
if( path_utf16 != path_buf )
|
||||||
|
free( path_utf16 );
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define x264_fopen fopen
|
#define x264_fopen fopen
|
||||||
@@ -197,18 +238,43 @@ static inline int x264_vfprintf( FILE *stream, const char *format, va_list arg )
|
|||||||
return vfprintf( stream, format, arg );
|
return vfprintf( stream, format, arg );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int x264_is_pipe( const char *path )
|
static inline int x264_is_regular_file_path( const char *path )
|
||||||
{
|
{
|
||||||
wchar_t path_utf16[MAX_PATH];
|
int ret = -1;
|
||||||
if( utf8_to_utf16( path, path_utf16 ) )
|
wchar_t path_buf[MAX_PATH];
|
||||||
return WaitNamedPipeW( path_utf16, 0 );
|
wchar_t *path_utf16 = x264_utf8_to_utf16_try_buf( path, path_buf, MAX_PATH );
|
||||||
return 0;
|
if( path_utf16 )
|
||||||
|
{
|
||||||
|
x264_struct_stat buf;
|
||||||
|
if( _wstati64( path_utf16, &buf ) )
|
||||||
|
ret = !WaitNamedPipeW( path_utf16, 0 );
|
||||||
|
else
|
||||||
|
ret = S_ISREG( buf.st_mode );
|
||||||
|
if( path_utf16 != path_buf )
|
||||||
|
free( path_utf16 );
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define x264_vfprintf vfprintf
|
#define x264_vfprintf vfprintf
|
||||||
#define x264_is_pipe(x) 0
|
|
||||||
|
static inline int x264_is_regular_file_path( const char *filename )
|
||||||
|
{
|
||||||
|
x264_struct_stat file_stat;
|
||||||
|
if( x264_stat( filename, &file_stat ) )
|
||||||
|
return 1;
|
||||||
|
return S_ISREG( file_stat.st_mode );
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline int x264_is_regular_file( FILE *filehandle )
|
||||||
|
{
|
||||||
|
x264_struct_stat file_stat;
|
||||||
|
if( x264_fstat( fileno( filehandle ), &file_stat ) )
|
||||||
|
return 1;
|
||||||
|
return S_ISREG( file_stat.st_mode );
|
||||||
|
}
|
||||||
|
|
||||||
#define x264_glue3_expand(x,y,z) x##_##y##_##z
|
#define x264_glue3_expand(x,y,z) x##_##y##_##z
|
||||||
#define x264_glue3(x,y,z) x264_glue3_expand(x,y,z)
|
#define x264_glue3(x,y,z) x264_glue3_expand(x,y,z)
|
||||||
|
|
||||||
@@ -510,20 +576,4 @@ static ALWAYS_INLINE void x264_prefetch( void *p )
|
|||||||
#define x264_lower_thread_priority(p)
|
#define x264_lower_thread_priority(p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline int x264_is_regular_file( FILE *filehandle )
|
|
||||||
{
|
|
||||||
x264_struct_stat file_stat;
|
|
||||||
if( x264_fstat( fileno( filehandle ), &file_stat ) )
|
|
||||||
return 1;
|
|
||||||
return S_ISREG( file_stat.st_mode );
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int x264_is_regular_file_path( const char *filename )
|
|
||||||
{
|
|
||||||
x264_struct_stat file_stat;
|
|
||||||
if( x264_stat( filename, &file_stat ) )
|
|
||||||
return !x264_is_pipe( filename );
|
|
||||||
return S_ISREG( file_stat.st_mode );
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* X264_OSDEP_H */
|
#endif /* X264_OSDEP_H */
|
||||||
|
|||||||
+42
-16
@@ -254,28 +254,48 @@ static float get_avs_version( avs_hnd_t *h )
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static int utf16_to_ansi( const wchar_t *utf16, char *ansi )
|
static char *utf16_to_ansi( const wchar_t *utf16 )
|
||||||
{
|
{
|
||||||
BOOL invalid;
|
BOOL invalid;
|
||||||
return WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, utf16, -1, ansi, MAX_PATH, NULL, &invalid ) && !invalid;
|
int len = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, utf16, -1, NULL, 0, NULL, &invalid );
|
||||||
|
if( len && !invalid )
|
||||||
|
{
|
||||||
|
char *ansi = malloc( len * sizeof( char ) );
|
||||||
|
if( ansi )
|
||||||
|
{
|
||||||
|
if( WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, utf16, -1, ansi, len, NULL, &invalid ) && !invalid )
|
||||||
|
return ansi;
|
||||||
|
free( ansi );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int utf8_to_ansi( const char *filename, char *ansi_filename )
|
static char *utf8_to_ansi( const char *filename )
|
||||||
{
|
{
|
||||||
wchar_t filename_utf16[MAX_PATH];
|
char *ansi = NULL;
|
||||||
if( utf8_to_utf16( filename, filename_utf16 ) )
|
wchar_t *filename_utf16 = x264_utf8_to_utf16( filename );
|
||||||
|
if( filename_utf16 )
|
||||||
{
|
{
|
||||||
/* Check if the filename already is valid ANSI. */
|
/* Check if the filename already is valid ANSI. */
|
||||||
if( utf16_to_ansi( filename_utf16, ansi_filename ) )
|
if( !(ansi = utf16_to_ansi( filename_utf16 )) )
|
||||||
return 1;
|
{
|
||||||
|
/* Check for a legacy 8.3 short filename. */
|
||||||
/* Check for a legacy 8.3 short filename. */
|
int len = GetShortPathNameW( filename_utf16, NULL, 0 );
|
||||||
int short_length = GetShortPathNameW( filename_utf16, filename_utf16, MAX_PATH );
|
if( len )
|
||||||
if( short_length > 0 && short_length < MAX_PATH )
|
{
|
||||||
if( utf16_to_ansi( filename_utf16, ansi_filename ) )
|
wchar_t *short_utf16 = malloc( len * sizeof( wchar_t ) );
|
||||||
return 1;
|
if( short_utf16 )
|
||||||
|
{
|
||||||
|
if( GetShortPathNameW( filename_utf16, short_utf16, len ) )
|
||||||
|
ansi = utf16_to_ansi( short_utf16 );
|
||||||
|
free( short_utf16 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free( filename_utf16 );
|
||||||
}
|
}
|
||||||
return 0;
|
return ansi;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -305,8 +325,8 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* Avisynth doesn't support Unicode filenames. */
|
/* Avisynth doesn't support Unicode filenames. */
|
||||||
char ansi_filename[MAX_PATH];
|
char *ansi_filename = utf8_to_ansi( psz_filename );
|
||||||
FAIL_IF_ERROR( !utf8_to_ansi( psz_filename, ansi_filename ), "invalid ansi filename\n" );
|
FAIL_IF_ERROR( !ansi_filename, "invalid ansi filename\n" );
|
||||||
AVS_Value arg = avs_new_value_string( ansi_filename );
|
AVS_Value arg = avs_new_value_string( ansi_filename );
|
||||||
#else
|
#else
|
||||||
AVS_Value arg = avs_new_value_string( psz_filename );
|
AVS_Value arg = avs_new_value_string( psz_filename );
|
||||||
@@ -318,6 +338,9 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
|
|||||||
if( !strcasecmp( filename_ext, "avs" ) )
|
if( !strcasecmp( filename_ext, "avs" ) )
|
||||||
{
|
{
|
||||||
res = h->func.avs_invoke( h->env, "Import", arg, NULL );
|
res = h->func.avs_invoke( h->env, "Import", arg, NULL );
|
||||||
|
#ifdef _WIN32
|
||||||
|
free( ansi_filename );
|
||||||
|
#endif
|
||||||
FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_error( res ) );
|
FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_error( res ) );
|
||||||
/* check if the user is using a multi-threaded script and apply distributor if necessary.
|
/* check if the user is using a multi-threaded script and apply distributor if necessary.
|
||||||
adapted from avisynth's vfw interface */
|
adapted from avisynth's vfw interface */
|
||||||
@@ -358,6 +381,9 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
|
|||||||
}
|
}
|
||||||
x264_cli_printf( X264_LOG_INFO, "failed\n" );
|
x264_cli_printf( X264_LOG_INFO, "failed\n" );
|
||||||
}
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
free( ansi_filename );
|
||||||
|
#endif
|
||||||
FAIL_IF_ERROR( !filter[i], "unable to find source filter to open `%s'\n", psz_filename );
|
FAIL_IF_ERROR( !filter[i], "unable to find source filter to open `%s'\n", psz_filename );
|
||||||
}
|
}
|
||||||
FAIL_IF_ERROR( !avs_is_clip( res ), "`%s' didn't return a video clip\n", psz_filename );
|
FAIL_IF_ERROR( !avs_is_clip( res ), "`%s' didn't return a video clip\n", psz_filename );
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ static wchar_t org_console_title[CONSOLE_TITLE_SIZE] = L"";
|
|||||||
void x264_cli_set_console_title( const char *title )
|
void x264_cli_set_console_title( const char *title )
|
||||||
{
|
{
|
||||||
wchar_t title_utf16[CONSOLE_TITLE_SIZE];
|
wchar_t title_utf16[CONSOLE_TITLE_SIZE];
|
||||||
if( utf8_to_utf16( title, title_utf16 ) )
|
if( MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, title, -1, title_utf16, CONSOLE_TITLE_SIZE ) )
|
||||||
SetConsoleTitleW( title_utf16 );
|
SetConsoleTitleW( title_utf16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity type="win32" name="VideoLAN.x264" version="1.0.0.0"/>
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
||||||
|
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
</assembly>
|
||||||
@@ -35,6 +35,10 @@
|
|||||||
#define str(s) #s
|
#define str(s) #s
|
||||||
#define xstr(s) str(s)
|
#define xstr(s) str(s)
|
||||||
|
|
||||||
|
#ifndef DLL
|
||||||
|
1 RT_MANIFEST "x264res.manifest"
|
||||||
|
#endif
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0, X264_BUILD, X264_REV, X264_REV_DIFF
|
FILEVERSION 0, X264_BUILD, X264_REV, X264_REV_DIFF
|
||||||
PRODUCTVERSION 0, X264_BUILD, X264_REV, X264_REV_DIFF
|
PRODUCTVERSION 0, X264_BUILD, X264_REV, X264_REV_DIFF
|
||||||
|
|||||||
Reference in New Issue
Block a user