--- /dev/null
+ src/8svx.c | 3 +-
+ src/adpcm.c | 1 +
+ src/effects_i.c | 3 +-
+ src/formats.c | 9 ++-
+ src/libsox.c | 2 +
+ src/libsox_i.c | 7 +-
+ src/noiseprof.c | 3 +-
+ src/sox.c | 37 +++++++---
+ src/unicode_support.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/unicode_support.h | 49 +++++++++++++
+ src/util.h | 5 ++
+ 11 files changed, 299 insertions(+), 19 deletions(-)
+
+diff --git a/src/8svx.c b/src/8svx.c
+index 63c30e6..fd712f4 100644
+--- a/src/8svx.c
++++ b/src/8svx.c
+@@ -1,6 +1,7 @@
+ /* Amiga 8SVX format handler: W V Neisius, February 1992 */
+
+ #include "sox_i.h"
++#include "unicode_support.h"
+
+ #include <errno.h>
+ #include <string.h>
+@@ -161,7 +162,7 @@ static int startread(sox_format_t * ft)
+ chan1_pos = lsx_tell(ft);
+
+ for (i = 1; i < channels; i++) {
+- if ((p->ch[i] = fopen(ft->filename, "rb")) == NULL)
++ if ((p->ch[i] = fopen_utf8(ft->filename, "rb")) == NULL)
+ {
+ lsx_fail_errno(ft,errno,"Can't open channel file '%s'",
+ ft->filename);
+diff --git a/src/adpcm.c b/src/adpcm.c
+index 2e13867..15c27c2 100644
+--- a/src/adpcm.c
++++ b/src/adpcm.c
+@@ -33,6 +33,7 @@
+
+ #include "sox_i.h"
+ #include "adpcm.h"
++#include "unicode_support.h"
+
+ #include <sys/types.h>
+ #include <stdio.h>
+diff --git a/src/effects_i.c b/src/effects_i.c
+index 7d72166..65d6a0b 100644
+--- a/src/effects_i.c
++++ b/src/effects_i.c
+@@ -20,6 +20,7 @@
+
+ #define LSX_EFF_ALIAS
+ #include "sox_i.h"
++#include "unicode_support.h"
+ #include <string.h>
+ #include <ctype.h>
+
+@@ -355,7 +356,7 @@ FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename)
+ effp->global_info->global_info->stdin_in_use_by = effp->handler.name;
+ file = stdin;
+ }
+- else if (!(file = fopen(filename, "r"))) {
++ else if (!(file = fopen_utf8(filename, "r"))) {
+ lsx_fail("couldn't open file %s: %s", filename, strerror(errno));
+ return NULL;
+ }
+diff --git a/src/formats.c b/src/formats.c
+index 785eca7..31993a5 100644
+--- a/src/formats.c
++++ b/src/formats.c
+@@ -19,6 +19,7 @@
+ */
+
+ #include "sox_i.h"
++#include "unicode_support.h"
+
+ #include <assert.h>
+ #include <ctype.h>
+@@ -397,7 +398,7 @@ static FILE * xfopen(char const * identifier, char const * mode, lsx_io_type * i
+ #endif
+ return f;
+ }
+- return fopen(identifier, mode);
++ return fopen_utf8(identifier, mode);
+ }
+
+ /* Hack to rewind pipes (a small amount).
+@@ -848,8 +849,8 @@ static sox_format_t * open_write(
+ ft->fp = stdout;
+ }
+ else {
+- struct stat st;
+- if (!stat(path, &st) && (st.st_mode & S_IFMT) == S_IFREG &&
++ struct _stat st;
++ if (!stat_utf8(path, &st) && (st.st_mode & S_IFMT) == S_IFREG &&
+ (overwrite_permitted && !overwrite_permitted(path))) {
+ lsx_fail("permission to overwrite `%s' denied", path);
+ goto error;
+@@ -859,7 +860,7 @@ static sox_format_t * open_write(
+ buffer? fmemopen(buffer, buffer_size, "w+b") :
+ buffer_ptr? open_memstream(buffer_ptr, buffer_size_ptr) :
+ #endif
+- fopen(path, "w+b");
++ fopen_utf8(path, "w+b");
+ if (ft->fp == NULL) {
+ lsx_fail("can't open output file `%s': %s", path, strerror(errno));
+ goto error;
+diff --git a/src/libsox.c b/src/libsox.c
+index 75354e4..a766aa9 100644
+--- a/src/libsox.c
++++ b/src/libsox.c
+@@ -19,6 +19,8 @@
+ */
+
+ #include "sox_i.h"
++#include "unicode_support.h"
++
+ #include <string.h>
+
+ const char *sox_version(void)
+diff --git a/src/libsox_i.c b/src/libsox_i.c
+index 8a7074a..b498cc0 100644
+--- a/src/libsox_i.c
++++ b/src/libsox_i.c
+@@ -20,6 +20,7 @@
+
+
+ #include "sox_i.h"
++#include "unicode_support.h"
+
+ #ifdef HAVE_IO_H
+ #include <io.h>
+@@ -48,8 +49,8 @@
+ #ifdef WIN32
+ static int check_dir(char * buf, size_t buflen, char const * name)
+ {
+- struct stat st;
+- if (!name || stat(name, &st) || (st.st_mode & S_IFMT) != S_IFDIR)
++ struct _stat st;
++ if (!name || stat_utf8(name, &st) || (st.st_mode & S_IFMT) != S_IFDIR)
+ {
+ return 0;
+ }
+@@ -102,7 +103,7 @@ FILE * lsx_tmpfile(void)
+ fildes = mkstemp(name);
+ #ifdef HAVE_UNISTD_H
+ lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (unlinked)", name);
+- unlink(name);
++ unlink_utf8(name);
+ #else
+ lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (O_TEMPORARY)", name);
+ #endif
+diff --git a/src/noiseprof.c b/src/noiseprof.c
+index 603402f..d46c280 100644
+--- a/src/noiseprof.c
++++ b/src/noiseprof.c
+@@ -19,6 +19,7 @@
+ */
+
+ #include "noisered.h"
++#include "unicode_support.h"
+
+ #include <assert.h>
+ #include <string.h>
+@@ -75,7 +76,7 @@ static int sox_noiseprof_start(sox_effect_t * effp)
+ effp->global_info->global_info->stdout_in_use_by = effp->handler.name;
+ data->output_file = stdout;
+ }
+- else if ((data->output_file = fopen(data->output_filename, "w")) == NULL) {
++ else if ((data->output_file = fopen_utf8(data->output_filename, "w")) == NULL) {
+ lsx_fail("Couldn't open profile file %s: %s", data->output_filename, strerror(errno));
+ return SOX_EOF;
+ }
+diff --git a/src/sox.c b/src/sox.c
+index 8160fc1..74cad4d 100644
+--- a/src/sox.c
++++ b/src/sox.c
+@@ -24,6 +24,7 @@
+ #include "soxconfig.h"
+ #include "sox.h"
+ #include "util.h"
++#include "unicode_support.h"
+
+ #include <ctype.h>
+ #include <errno.h>
+@@ -236,12 +237,12 @@ static void cleanup(void)
+ if (file_count) {
+ if (ofile->ft) {
+ if (!success && ofile->ft->fp) { /* If we failed part way through */
+- struct stat st; /* writing a normal file, remove it. */
+- if (!stat(ofile->ft->filename, &st) &&
++ struct _stat st; /* writing a normal file, remove it. */
++ if (!stat_utf8(ofile->ft->filename, &st) &&
+ (st.st_mode & S_IFMT) == S_IFREG)
+- unlink(ofile->ft->filename);
++ unlink_utf8(ofile->ft->filename);
+ }
+- sox_close(ofile->ft); /* Assume we can unlink a file before closing it. */
++ sox_close(ofile->ft); /* Assume we can unlink_utf8 a file before closing it. */
+ }
+ free(ofile->filename);
+ free(ofile);
+@@ -293,8 +294,8 @@ static char const * str_time(double seconds)
+
+ static char const * size_and_bitrate(sox_format_t * ft, char const * * text)
+ {
+- struct stat st; /* ft->fp may validly be NULL, so stat not fstat */
+- if (stat(ft->filename, &st) || (st.st_mode & S_IFMT) != S_IFREG)
++ struct _stat st; /* ft->fp may validly be NULL, so stat not fstat */
++ if (stat_utf8(ft->filename, &st) || (st.st_mode & S_IFMT) != S_IFREG)
+ return NULL;
+ if (ft->signal.length && ft->signal.channels && ft->signal.rate && text) {
+ double secs = ft->signal.length / ft->signal.channels / ft->signal.rate;
+@@ -906,7 +907,7 @@ static char * * strtoargv(char * s, int * argc)
+
+ static void read_user_effects(char const *filename)
+ {
+- FILE *file = fopen(filename, "rt");
++ FILE *file = fopen_utf8(filename, "rt");
+ const size_t buffer_size_step = 1024;
+ size_t buffer_size = buffer_size_step;
+ char *s = lsx_malloc(buffer_size); /* buffer for one input line */
+@@ -1269,6 +1270,7 @@ static void display_status(sox_bool all_done)
+ lsx_sigfigs3((double)output_samples),
+ vu(0), vu(1), headroom(), lsx_sigfigs3((double)total_clips()));
+ }
++ fflush(stderr);
+ if (all_done)
+ fputc('\n', stderr);
+ }
+@@ -2127,7 +2129,7 @@ static void read_comment_file(sox_comments_t * comments, char const * const file
+ int c;
+ size_t text_length = 100;
+ char * text = lsx_malloc(text_length + 1);
+- FILE * file = fopen(filename, "rt");
++ FILE * file = fopen_utf8(filename, "rt");
+
+ if (file == NULL) {
+ lsx_fail("Cannot open comment file `%s'", filename);
+@@ -2853,7 +2855,7 @@ static sox_bool cmp_comment_text(char const * c1, char const * c2)
+ return c1 && c2 && !strcasecmp(c1, c2);
+ }
+
+-int main(int argc, char **argv)
++static int sox_main(int argc, char **argv)
+ {
+ size_t i;
+ char mybase[6];
+@@ -3055,3 +3057,20 @@ int main(int argc, char **argv)
+
+ return 0;
+ }
++
++int main( int argc, char **argv )
++{
++ int sox_argc;
++ char **sox_argv;
++ int exit_code;
++
++ init_console_utf8();
++ init_commandline_arguments_utf8(&sox_argc, &sox_argv);
++
++ exit_code = sox_main(sox_argc, sox_argv);
++
++ uninit_console_utf8();
++ free_commandline_arguments_utf8(&sox_argc, &sox_argv);
++
++ return exit_code;
++}
+diff --git a/src/unicode_support.c b/src/unicode_support.c
+new file mode 100644
+index 0000000..f2a0a9e
+--- /dev/null
++++ b/src/unicode_support.c
+@@ -0,0 +1,199 @@
++/* Copyright (c) 2004-2012 LoRd_MuldeR <mulder2@gmx.de>
++ File: unicode_support.c
++
++ This file was originally part of a patch included with LameXP,
++ released under the same license as the original audio tools.
++
++ Redistribution and use in source and binary forms, with or without
++ modification, are permitted provided that the following conditions
++ are met:
++
++ - Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++
++ - Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++
++ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
++ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++#if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
++
++#include "unicode_support.h"
++
++#include <windows.h>
++#include <io.h>
++
++static UINT g_old_output_cp = ((UINT)-1);
++
++char *utf16_to_utf8(const wchar_t *input)
++{
++ char *Buffer;
++ int BuffSize = 0, Result = 0;
++
++ BuffSize = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL);
++ Buffer = (char*) malloc(sizeof(char) * BuffSize);
++ if(Buffer)
++ {
++ Result = WideCharToMultiByte(CP_UTF8, 0, input, -1, Buffer, BuffSize, NULL, NULL);
++ }
++
++ return ((Result > 0) && (Result <= BuffSize)) ? Buffer : NULL;
++}
++
++char *utf16_to_ansi(const wchar_t *input)
++{
++ char *Buffer;
++ int BuffSize = 0, Result = 0;
++
++ BuffSize = WideCharToMultiByte(CP_ACP, 0, input, -1, NULL, 0, NULL, NULL);
++ Buffer = (char*) malloc(sizeof(char) * BuffSize);
++ if(Buffer)
++ {
++ Result = WideCharToMultiByte(CP_ACP, 0, input, -1, Buffer, BuffSize, NULL, NULL);
++ }
++
++ return ((Result > 0) && (Result <= BuffSize)) ? Buffer : NULL;
++}
++
++wchar_t *utf8_to_utf16(const char *input)
++{
++ wchar_t *Buffer;
++ int BuffSize = 0, Result = 0;
++
++ BuffSize = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
++ Buffer = (wchar_t*) malloc(sizeof(wchar_t) * BuffSize);
++ if(Buffer)
++ {
++ Result = MultiByteToWideChar(CP_UTF8, 0, input, -1, Buffer, BuffSize);
++ }
++
++ return ((Result > 0) && (Result <= BuffSize)) ? Buffer : NULL;
++}
++
++void init_commandline_arguments_utf8(int *argc, char ***argv)
++{
++ int i, nArgs;
++ LPWSTR *szArglist;
++
++ szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
++
++ if(NULL == szArglist)
++ {
++ fprintf(stderr, "\nFATAL: CommandLineToArgvW failed\n\n");
++ exit(-1);
++ }
++
++ *argv = (char**) malloc(sizeof(char*) * nArgs);
++ *argc = nArgs;
++
++ if(NULL == *argv)
++ {
++ fprintf(stderr, "\nFATAL: Malloc failed\n\n");
++ exit(-1);
++ }
++
++ for(i = 0; i < nArgs; i++)
++ {
++ (*argv)[i] = utf16_to_utf8(szArglist[i]);
++ if(NULL == (*argv)[i])
++ {
++ fprintf(stderr, "\nFATAL: utf16_to_utf8 failed\n\n");
++ exit(-1);
++ }
++ }
++
++ LocalFree(szArglist);
++}
++
++void free_commandline_arguments_utf8(int *argc, char ***argv)
++{
++ int i = 0;
++
++ if(*argv != NULL)
++ {
++ for(i = 0; i < *argc; i++)
++ {
++ if((*argv)[i] != NULL)
++ {
++ free((*argv)[i]);
++ (*argv)[i] = NULL;
++ }
++ }
++ free(*argv);
++ *argv = NULL;
++ }
++}
++
++FILE *fopen_utf8(const char *filename_utf8, const char *mode_utf8)
++{
++ FILE *ret = NULL;
++ wchar_t *filename_utf16 = utf8_to_utf16(filename_utf8);
++ wchar_t *mode_utf16 = utf8_to_utf16(mode_utf8);
++
++ if(filename_utf16 && mode_utf16)
++ {
++ FILE *fh = NULL;
++ int err = _wfopen_s(&fh, filename_utf16, mode_utf16);
++ if(err == 0) ret = fh;
++ }
++
++ if(filename_utf16) free(filename_utf16);
++ if(mode_utf16) free(mode_utf16);
++
++ return ret;
++}
++
++int stat_utf8(const char *path_utf8, struct _stat *buf)
++{
++ int ret = -1;
++
++ wchar_t *path_utf16 = utf8_to_utf16(path_utf8);
++ if(path_utf16)
++ {
++ ret = _wstat(path_utf16, buf);
++ free(path_utf16);
++ }
++
++ return ret;
++}
++
++int unlink_utf8(const char *path_utf8)
++{
++ int ret = -1;
++
++ wchar_t *path_utf16 = utf8_to_utf16(path_utf8);
++ if(path_utf16)
++ {
++ ret = _wunlink(path_utf16);
++ free(path_utf16);
++ }
++
++ return ret;
++}
++
++void init_console_utf8(void)
++{
++ g_old_output_cp = GetConsoleOutputCP();
++ SetConsoleOutputCP(CP_UTF8);
++}
++
++void uninit_console_utf8(void)
++{
++ if(g_old_output_cp != ((UINT)-1))
++ {
++ SetConsoleOutputCP(g_old_output_cp);
++ }
++}
++
++#endif
+\ No newline at end of file
+diff --git a/src/unicode_support.h b/src/unicode_support.h
+new file mode 100644
+index 0000000..cf55719
+--- /dev/null
++++ b/src/unicode_support.h
+@@ -0,0 +1,49 @@
++/* Copyright (c) 2004-2012 LoRd_MuldeR <mulder2@gmx.de>
++ File: unicode_support.h
++
++ This file was originally part of a patch included with LameXP,
++ released under the same license as the original audio tools.
++
++ Redistribution and use in source and binary forms, with or without
++ modification, are permitted provided that the following conditions
++ are met:
++
++ - Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++
++ - Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++
++ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
++ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++#ifndef UNICODE_SUPPORT_H_INCLUDED
++#define UNICODE_SUPPORT_H_INCLUDED
++
++#include <stdio.h>
++#include <sys/stat.h>
++
++#define WIN_UNICODE 1
++
++char *utf16_to_utf8(const wchar_t *input);
++char *utf16_to_ansi(const wchar_t *input);
++wchar_t *utf8_to_utf16(const char *input);
++void init_commandline_arguments_utf8(int *argc, char ***argv);
++void free_commandline_arguments_utf8(int *argc, char ***argv);
++FILE *fopen_utf8(const char *filename_utf8, const char *mode_utf8);
++int stat_utf8(const char *path_utf8, struct _stat *buf);
++int unlink_utf8(const char *path_utf8);
++void init_console_utf8(void);
++void uninit_console_utf8(void);
++
++#endif
+\ No newline at end of file
+diff --git a/src/util.h b/src/util.h
+index 89bbe75..941d727 100644
+--- a/src/util.h
++++ b/src/util.h
+@@ -91,6 +91,10 @@
+
+ #ifdef _MSC_VER
+
++#define inline __inline
++#define snprintf _snprintf
++
++/*
+ #define __STDC__ 1
+ #define O_BINARY _O_BINARY
+ #define O_CREAT _O_CREAT
+@@ -140,6 +144,7 @@
+ #define off_t __int64
+ #define HAVE_FSEEKO 1
+ #endif
++*/
+
+ #elif defined(__MINGW32__)
+