Commit 9b01eda7 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Use external codepage tables for the Unix codepage too.

parent fb316c33
...@@ -1451,8 +1451,8 @@ static BOOL append_entry( struct dir_data *data, const char *long_name, ...@@ -1451,8 +1451,8 @@ static BOOL append_entry( struct dir_data *data, const char *long_name,
WCHAR short_nameW[13]; WCHAR short_nameW[13];
UNICODE_STRING str; UNICODE_STRING str;
long_len = ntdll_umbstowcs( 0, long_name, strlen(long_name), long_nameW, MAX_DIR_ENTRY_LEN ); long_len = ntdll_umbstowcs( long_name, strlen(long_name), long_nameW, ARRAY_SIZE(long_nameW) );
if (long_len == -1) return TRUE; if (long_len == ARRAY_SIZE(long_nameW)) return TRUE;
long_nameW[long_len] = 0; long_nameW[long_len] = 0;
str.Buffer = long_nameW; str.Buffer = long_nameW;
...@@ -1461,9 +1461,8 @@ static BOOL append_entry( struct dir_data *data, const char *long_name, ...@@ -1461,9 +1461,8 @@ static BOOL append_entry( struct dir_data *data, const char *long_name,
if (short_name) if (short_name)
{ {
short_len = ntdll_umbstowcs( 0, short_name, strlen(short_name), short_len = ntdll_umbstowcs( short_name, strlen(short_name),
short_nameW, ARRAY_SIZE( short_nameW ) - 1 ); short_nameW, ARRAY_SIZE( short_nameW ) - 1 );
if (short_len == -1) short_len = ARRAY_SIZE( short_nameW ) - 1;
for (i = 0; i < short_len; i++) short_nameW[i] = toupperW( short_nameW[i] ); for (i = 0; i < short_len; i++) short_nameW[i] = toupperW( short_nameW[i] );
} }
else /* generate a short name if necessary */ else /* generate a short name if necessary */
...@@ -1795,12 +1794,10 @@ static NTSTATUS read_directory_data( struct dir_data *data, int fd, const UNICOD ...@@ -1795,12 +1794,10 @@ static NTSTATUS read_directory_data( struct dir_data *data, int fd, const UNICOD
if (!has_wildcard( mask )) if (!has_wildcard( mask ))
{ {
/* convert the mask to a Unix name and check for it */ /* convert the mask to a Unix name and check for it */
int ret, used_default;
char unix_name[MAX_DIR_ENTRY_LEN * 3 + 1]; char unix_name[MAX_DIR_ENTRY_LEN * 3 + 1];
int ret = ntdll_wcstoumbs( mask->Buffer, mask->Length / sizeof(WCHAR),
ret = ntdll_wcstoumbs( 0, mask->Buffer, mask->Length / sizeof(WCHAR), unix_name, sizeof(unix_name) - 1, TRUE );
unix_name, sizeof(unix_name) - 1, NULL, &used_default ); if (ret > 0)
if (ret > 0 && !used_default)
{ {
unix_name[ret] = 0; unix_name[ret] = 0;
#ifdef HAVE_GETATTRLIST #ifdef HAVE_GETATTRLIST
...@@ -2047,16 +2044,13 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i ...@@ -2047,16 +2044,13 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
DIR *dir; DIR *dir;
struct dirent *de; struct dirent *de;
struct stat st; struct stat st;
int ret, used_default; int ret;
/* try a shortcut for this directory */ /* try a shortcut for this directory */
unix_name[pos++] = '/'; unix_name[pos++] = '/';
ret = ntdll_wcstoumbs( 0, name, length, unix_name + pos, MAX_DIR_ENTRY_LEN, ret = ntdll_wcstoumbs( name, length, unix_name + pos, MAX_DIR_ENTRY_LEN + 1, TRUE );
NULL, &used_default ); if (ret >= 0 && ret <= MAX_DIR_ENTRY_LEN)
/* if we used the default char, the Unix name won't round trip properly back to Unicode */
/* so it cannot match the file we are looking for */
if (ret >= 0 && !used_default)
{ {
unix_name[pos + ret] = 0; unix_name[pos + ret] = 0;
if (!stat( unix_name, &st )) if (!stat( unix_name, &st ))
...@@ -2106,7 +2100,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i ...@@ -2106,7 +2100,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
if (kde[1].d_name[0]) if (kde[1].d_name[0])
{ {
ret = ntdll_umbstowcs( 0, kde[1].d_name, strlen(kde[1].d_name), ret = ntdll_umbstowcs( kde[1].d_name, strlen(kde[1].d_name),
buffer, MAX_DIR_ENTRY_LEN ); buffer, MAX_DIR_ENTRY_LEN );
if (ret == length && !strncmpiW( buffer, name, length)) if (ret == length && !strncmpiW( buffer, name, length))
{ {
...@@ -2116,7 +2110,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i ...@@ -2116,7 +2110,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
goto success; goto success;
} }
} }
ret = ntdll_umbstowcs( 0, kde[0].d_name, strlen(kde[0].d_name), ret = ntdll_umbstowcs( kde[0].d_name, strlen(kde[0].d_name),
buffer, MAX_DIR_ENTRY_LEN ); buffer, MAX_DIR_ENTRY_LEN );
if (ret == length && !strncmpiW( buffer, name, length)) if (ret == length && !strncmpiW( buffer, name, length))
{ {
...@@ -2151,7 +2145,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i ...@@ -2151,7 +2145,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
str.MaximumLength = sizeof(buffer); str.MaximumLength = sizeof(buffer);
while ((de = readdir( dir ))) while ((de = readdir( dir )))
{ {
ret = ntdll_umbstowcs( 0, de->d_name, strlen(de->d_name), buffer, MAX_DIR_ENTRY_LEN ); ret = ntdll_umbstowcs( de->d_name, strlen(de->d_name), buffer, MAX_DIR_ENTRY_LEN );
if (ret == length && !strncmpiW( buffer, name, length )) if (ret == length && !strncmpiW( buffer, name, length ))
{ {
strcpy( unix_name + pos, de->d_name ); strcpy( unix_name + pos, de->d_name );
...@@ -2564,7 +2558,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer ...@@ -2564,7 +2558,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
UINT disposition, BOOLEAN check_case ) UINT disposition, BOOLEAN check_case )
{ {
NTSTATUS status; NTSTATUS status;
int ret, used_default, len; int ret, len;
struct stat st; struct stat st;
char *unix_name = *buffer; char *unix_name = *buffer;
const BOOL redirect = nb_redirects && ntdll_get_thread_data()->wow64_redir; const BOOL redirect = nb_redirects && ntdll_get_thread_data()->wow64_redir;
...@@ -2578,10 +2572,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer ...@@ -2578,10 +2572,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
} }
unix_name[pos] = '/'; unix_name[pos] = '/';
ret = ntdll_wcstoumbs( 0, name, name_len, unix_name + pos + 1, unix_len - pos - 2, ret = ntdll_wcstoumbs( name, name_len, unix_name + pos + 1, unix_len - pos - 1, TRUE );
NULL, &used_default ); if (ret >= 0 && ret < unix_len - pos - 1)
if (ret >= 0 && !used_default) /* if we used the default char the name didn't convert properly */
{ {
char *p; char *p;
unix_name[pos + 1 + ret] = 0; unix_name[pos + 1 + ret] = 0;
...@@ -2637,9 +2629,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer ...@@ -2637,9 +2629,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
status = STATUS_OBJECT_NAME_NOT_FOUND; status = STATUS_OBJECT_NAME_NOT_FOUND;
if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE) if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
{ {
ret = ntdll_wcstoumbs( 0, name, end - name, unix_name + pos + 1, ret = ntdll_wcstoumbs( name, end - name, unix_name + pos + 1, MAX_DIR_ENTRY_LEN + 1, TRUE );
MAX_DIR_ENTRY_LEN, NULL, &used_default ); if (ret > 0 && ret <= MAX_DIR_ENTRY_LEN)
if (ret > 0 && !used_default)
{ {
unix_name[pos] = '/'; unix_name[pos] = '/';
unix_name[pos + 1 + ret] = 0; unix_name[pos + 1 + ret] = 0;
...@@ -2699,8 +2690,7 @@ NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING * ...@@ -2699,8 +2690,7 @@ NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *
for (p = name; p < name + name_len; p++) for (p = name; p < name + name_len; p++)
if (*p < 32 || strchrW( invalid_charsW, *p )) return STATUS_OBJECT_NAME_INVALID; if (*p < 32 || strchrW( invalid_charsW, *p )) return STATUS_OBJECT_NAME_INVALID;
unix_len = ntdll_wcstoumbs( 0, name, name_len, NULL, 0, NULL, NULL ); unix_len = name_len * 3 + MAX_DIR_ENTRY_LEN + 3;
unix_len += MAX_DIR_ENTRY_LEN + 3;
if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len ))) if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len )))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
unix_name[0] = '.'; unix_name[0] = '.';
...@@ -2765,7 +2755,7 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI ...@@ -2765,7 +2755,7 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI
const WCHAR *name, *p; const WCHAR *name, *p;
struct stat st; struct stat st;
char *unix_name; char *unix_name;
int pos, ret, name_len, unix_len, prefix_len, used_default; int pos, ret, name_len, unix_len, prefix_len;
WCHAR prefix[MAX_DIR_ENTRY_LEN]; WCHAR prefix[MAX_DIR_ENTRY_LEN];
BOOLEAN is_unix = FALSE; BOOLEAN is_unix = FALSE;
...@@ -2815,9 +2805,7 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI ...@@ -2815,9 +2805,7 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI
if (*p < 32 || strchrW( invalid_charsW, *p )) return STATUS_OBJECT_NAME_INVALID; if (*p < 32 || strchrW( invalid_charsW, *p )) return STATUS_OBJECT_NAME_INVALID;
} }
unix_len = ntdll_wcstoumbs( 0, prefix, prefix_len, NULL, 0, NULL, NULL ); unix_len = (prefix_len + name_len) * 3 + MAX_DIR_ENTRY_LEN + 3;
unix_len += ntdll_wcstoumbs( 0, name, name_len, NULL, 0, NULL, NULL );
unix_len += MAX_DIR_ENTRY_LEN + 3;
unix_len += strlen(config_dir) + sizeof("/dosdevices/"); unix_len += strlen(config_dir) + sizeof("/dosdevices/");
if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len ))) if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len )))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
...@@ -2825,9 +2813,8 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI ...@@ -2825,9 +2813,8 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI
strcat( unix_name, "/dosdevices/" ); strcat( unix_name, "/dosdevices/" );
pos = strlen(unix_name); pos = strlen(unix_name);
ret = ntdll_wcstoumbs( 0, prefix, prefix_len, unix_name + pos, unix_len - pos - 1, ret = ntdll_wcstoumbs( prefix, prefix_len, unix_name + pos, unix_len - pos - 1, TRUE );
NULL, &used_default ); if (ret <= 0)
if (!ret || used_default)
{ {
RtlFreeHeap( GetProcessHeap(), 0, unix_name ); RtlFreeHeap( GetProcessHeap(), 0, unix_name );
return STATUS_OBJECT_NAME_INVALID; return STATUS_OBJECT_NAME_INVALID;
......
...@@ -478,7 +478,7 @@ static WCHAR *build_initial_environment( char **env ) ...@@ -478,7 +478,7 @@ static WCHAR *build_initial_environment( char **env )
for (e = env; *e; e++) for (e = env; *e; e++)
{ {
if (is_special_env_var( *e )) continue; if (is_special_env_var( *e )) continue;
size += ntdll_umbstowcs( 0, *e, strlen(*e) + 1, NULL, 0 ); size += strlen(*e) + 1;
} }
if (!(ptr = RtlAllocateHeap( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return NULL; if (!(ptr = RtlAllocateHeap( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return NULL;
...@@ -498,7 +498,7 @@ static WCHAR *build_initial_environment( char **env ) ...@@ -498,7 +498,7 @@ static WCHAR *build_initial_environment( char **env )
} }
else if (is_special_env_var( str )) continue; /* skip it */ else if (is_special_env_var( str )) continue; /* skip it */
ntdll_umbstowcs( 0, str, strlen(str) + 1, p, size - (p - ptr) ); ntdll_umbstowcs( str, strlen(str) + 1, p, size - (p - ptr) );
p += strlenW(p) + 1; p += strlenW(p) + 1;
} }
*p = 0; *p = 0;
...@@ -522,9 +522,8 @@ char **build_envp( const WCHAR *envW ) ...@@ -522,9 +522,8 @@ char **build_envp( const WCHAR *envW )
unsigned int i; unsigned int i;
lenW = get_env_length( envW ); lenW = get_env_length( envW );
length = ntdll_wcstoumbs( 0, envW, lenW, NULL, 0, NULL, NULL ); if (!(env = RtlAllocateHeap( GetProcessHeap(), 0, lenW * 3 ))) return NULL;
if (!(env = RtlAllocateHeap( GetProcessHeap(), 0, length ))) return NULL; length = ntdll_wcstoumbs( envW, lenW, env, lenW * 3, FALSE );
ntdll_wcstoumbs( 0, envW, lenW, env, length, NULL, NULL );
for (p = env; *p; p += strlen(p) + 1, count++) for (p = env; *p; p += strlen(p) + 1, count++)
if (is_special_env_var( p )) length += 4; /* prefix it with "WINE" */ if (is_special_env_var( p )) length += 4; /* prefix it with "WINE" */
...@@ -676,11 +675,10 @@ static void get_image_path( const char *argv0, UNICODE_STRING *path ) ...@@ -676,11 +675,10 @@ static void get_image_path( const char *argv0, UNICODE_STRING *path )
{ {
static const WCHAR exeW[] = {'.','e','x','e',0}; static const WCHAR exeW[] = {'.','e','x','e',0};
WCHAR *load_path, *file_part, *name, full_name[MAX_PATH]; WCHAR *load_path, *file_part, *name, full_name[MAX_PATH];
DWORD len; DWORD len = strlen(argv0) + 1;
len = ntdll_umbstowcs( 0, argv0, strlen(argv0) + 1, NULL, 0 );
if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto failed; if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto failed;
ntdll_umbstowcs( 0, argv0, strlen(argv0) + 1, name, len ); ntdll_umbstowcs( argv0, len, name, len );
if (RtlDetermineDosPathNameType_U( name ) != RELATIVE_PATH || if (RtlDetermineDosPathNameType_U( name ) != RELATIVE_PATH ||
strchrW( name, '/' ) || strchrW( name, '\\' )) strchrW( name, '/' ) || strchrW( name, '\\' ))
...@@ -739,8 +737,7 @@ static void set_library_wargv( char **argv, const UNICODE_STRING *image ) ...@@ -739,8 +737,7 @@ static void set_library_wargv( char **argv, const UNICODE_STRING *image )
DWORD total = 0; DWORD total = 0;
if (image) total += 1 + image->Length / sizeof(WCHAR); if (image) total += 1 + image->Length / sizeof(WCHAR);
for (argc = (image != NULL); argv[argc]; argc++) for (argc = (image != NULL); argv[argc]; argc++) total += strlen(argv[argc]) + 1;
total += ntdll_umbstowcs( 0, argv[argc], strlen(argv[argc]) + 1, NULL, 0 );
wargv = RtlAllocateHeap( GetProcessHeap(), 0, wargv = RtlAllocateHeap( GetProcessHeap(), 0,
total * sizeof(WCHAR) + (argc + 1) * sizeof(*wargv) ); total * sizeof(WCHAR) + (argc + 1) * sizeof(*wargv) );
...@@ -754,7 +751,7 @@ static void set_library_wargv( char **argv, const UNICODE_STRING *image ) ...@@ -754,7 +751,7 @@ static void set_library_wargv( char **argv, const UNICODE_STRING *image )
} }
for (argc = (image != NULL); argv[argc]; argc++) for (argc = (image != NULL); argv[argc]; argc++)
{ {
DWORD reslen = ntdll_umbstowcs( 0, argv[argc], strlen(argv[argc]) + 1, p, total ); DWORD reslen = ntdll_umbstowcs( argv[argc], strlen(argv[argc]) + 1, p, total );
wargv[argc] = p; wargv[argc] = p;
p += reslen; p += reslen;
total -= reslen; total -= reslen;
......
...@@ -1773,7 +1773,7 @@ static NTSTATUS read_changes_apc( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS st ...@@ -1773,7 +1773,7 @@ static NTSTATUS read_changes_apc( void *user, IO_STATUS_BLOCK *iosb, NTSTATUS st
if (event->name[i] == '/') event->name[i] = '\\'; if (event->name[i] == '/') event->name[i] = '\\';
pfni->Action = event->action; pfni->Action = event->action;
pfni->FileNameLength = ntdll_umbstowcs( 0, event->name, event->len, pfni->FileName, pfni->FileNameLength = ntdll_umbstowcs( event->name, event->len, pfni->FileName,
(left - offsetof(FILE_NOTIFY_INFORMATION, FileName)) / sizeof(WCHAR)); (left - offsetof(FILE_NOTIFY_INFORMATION, FileName)) / sizeof(WCHAR));
last_entry_offset = &pfni->NextEntryOffset; last_entry_offset = &pfni->NextEntryOffset;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "ntstatus.h" #include "ntstatus.h"
#define WIN32_NO_STATUS #define WIN32_NO_STATUS
#include "ntdll_misc.h" #include "ntdll_misc.h"
#include "wine/library.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
...@@ -80,7 +81,7 @@ LCID user_lcid = 0, system_lcid = 0; ...@@ -80,7 +81,7 @@ LCID user_lcid = 0, system_lcid = 0;
static LANGID user_ui_language, system_ui_language; static LANGID user_ui_language, system_ui_language;
static NLSTABLEINFO nls_info; static NLSTABLEINFO nls_info;
static HMODULE kernel32_handle; static HMODULE kernel32_handle;
static const union cptable *unix_table; /* NULL if UTF8 */ static CPTABLEINFO unix_table;
extern WCHAR wine_compose( const WCHAR *str ) DECLSPEC_HIDDEN; extern WCHAR wine_compose( const WCHAR *str ) DECLSPEC_HIDDEN;
extern const unsigned short combining_class_table[] DECLSPEC_HIDDEN; extern const unsigned short combining_class_table[] DECLSPEC_HIDDEN;
...@@ -498,6 +499,37 @@ static const struct { const char *name; UINT cp; } charset_names[] = ...@@ -498,6 +499,37 @@ static const struct { const char *name; UINT cp; } charset_names[] =
{ "UTF8", CP_UTF8 } { "UTF8", CP_UTF8 }
}; };
static void load_unix_cptable( unsigned int cp )
{
const char *build_dir = wine_get_build_dir();
const char *data_dir = wine_get_data_dir();
const char *dir = build_dir ? build_dir : data_dir;
struct stat st;
char *name;
USHORT *data;
int fd;
if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, strlen(dir) + 22 ))) return;
sprintf( name, "%s/nls/c_%03u.nls", dir, cp );
if ((fd = open( name, O_RDONLY )) != -1)
{
fstat( fd, &st );
if ((data = RtlAllocateHeap( GetProcessHeap(), 0, st.st_size )) &&
st.st_size > 0x10000 &&
read( fd, data, st.st_size ) == st.st_size)
{
RtlInitCodePageTable( data, &unix_table );
}
else
{
RtlFreeHeap( GetProcessHeap(), 0, data );
}
close( fd );
}
else ERR( "failed to load %s\n", debugstr_a(name) );
RtlFreeHeap( GetProcessHeap(), 0, name );
}
void init_unix_codepage(void) void init_unix_codepage(void)
{ {
char charset_name[16]; char charset_name[16];
...@@ -519,8 +551,7 @@ void init_unix_codepage(void) ...@@ -519,8 +551,7 @@ void init_unix_codepage(void)
int res = _strnicmp( charset_names[pos].name, charset_name, -1 ); int res = _strnicmp( charset_names[pos].name, charset_name, -1 );
if (!res) if (!res)
{ {
if (charset_names[pos].cp == CP_UTF8) return; if (charset_names[pos].cp != CP_UTF8) load_unix_cptable( charset_names[pos].cp );
unix_table = wine_cp_get_table( charset_names[pos].cp );
return; return;
} }
if (res > 0) max = pos - 1; if (res > 0) max = pos - 1;
...@@ -547,6 +578,7 @@ static LCID unix_locale_to_lcid( const char *unix_name ) ...@@ -547,6 +578,7 @@ static LCID unix_locale_to_lcid( const char *unix_name )
static const WCHAR latnW[] = {'-','L','a','t','n',0}; static const WCHAR latnW[] = {'-','L','a','t','n',0};
WCHAR buffer[LOCALE_NAME_MAX_LENGTH], win_name[LOCALE_NAME_MAX_LENGTH]; WCHAR buffer[LOCALE_NAME_MAX_LENGTH], win_name[LOCALE_NAME_MAX_LENGTH];
WCHAR *p, *country = NULL, *modifier = NULL; WCHAR *p, *country = NULL, *modifier = NULL;
DWORD len;
LCID lcid; LCID lcid;
if (!unix_name || !unix_name[0] || !strcmp( unix_name, "C" )) if (!unix_name || !unix_name[0] || !strcmp( unix_name, "C" ))
...@@ -555,7 +587,9 @@ static LCID unix_locale_to_lcid( const char *unix_name ) ...@@ -555,7 +587,9 @@ static LCID unix_locale_to_lcid( const char *unix_name )
if (!unix_name || !unix_name[0]) return 0; if (!unix_name || !unix_name[0]) return 0;
} }
if (ntdll_umbstowcs( 0, unix_name, strlen(unix_name) + 1, buffer, ARRAY_SIZE(buffer) ) < 0) return 0; len = ntdll_umbstowcs( unix_name, strlen(unix_name), buffer, ARRAY_SIZE(buffer) );
if (len == ARRAY_SIZE(buffer)) return 0;
buffer[len] = 0;
if (!(p = strpbrkW( buffer, sepW ))) if (!(p = strpbrkW( buffer, sepW )))
{ {
...@@ -702,16 +736,15 @@ void init_locale( HMODULE module ) ...@@ -702,16 +736,15 @@ void init_locale( HMODULE module )
/****************************************************************** /******************************************************************
* ntdll_umbstowcs * ntdll_umbstowcs
*/ */
int ntdll_umbstowcs( DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen ) DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen )
{ {
DWORD reslen; DWORD reslen;
NTSTATUS status;
if (unix_table) return wine_cp_mbstowcs( unix_table, flags, src, srclen, dst, dstlen ); if (unix_table.CodePage)
RtlCustomCPToUnicodeN( &unix_table, dst, dstlen * sizeof(WCHAR), &reslen, src, srclen );
else
RtlUTF8ToUnicodeN( dst, dstlen * sizeof(WCHAR), &reslen, src, srclen );
if (!dstlen) dst = NULL;
status = RtlUTF8ToUnicodeN( dst, dstlen * sizeof(WCHAR), &reslen, src, srclen );
if (status && status != STATUS_SOME_NOT_MAPPED) return -1;
reslen /= sizeof(WCHAR); reslen /= sizeof(WCHAR);
#ifdef __APPLE__ /* work around broken Mac OS X filesystem that enforces decomposed Unicode */ #ifdef __APPLE__ /* work around broken Mac OS X filesystem that enforces decomposed Unicode */
if (reslen && dst) reslen = compose_string( dst, reslen ); if (reslen && dst) reslen = compose_string( dst, reslen );
...@@ -723,18 +756,50 @@ int ntdll_umbstowcs( DWORD flags, const char *src, int srclen, WCHAR *dst, int d ...@@ -723,18 +756,50 @@ int ntdll_umbstowcs( DWORD flags, const char *src, int srclen, WCHAR *dst, int d
/****************************************************************** /******************************************************************
* ntdll_wcstoumbs * ntdll_wcstoumbs
*/ */
int ntdll_wcstoumbs( DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen, int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict )
const char *defchar, int *used )
{ {
DWORD reslen; DWORD i, reslen;
NTSTATUS status;
if (unix_table) return wine_cp_wcstombs( unix_table, flags, src, srclen, dst, dstlen, defchar, used ); if (!unix_table.CodePage)
RtlUnicodeToUTF8N( dst, dstlen, &reslen, src, srclen * sizeof(WCHAR) );
if (used) *used = 0; /* all chars are valid for UTF-8 */ else if (!strict)
if (!dstlen) dst = NULL; RtlUnicodeToCustomCPN( &unix_table, dst, dstlen, &reslen, src, srclen * sizeof(WCHAR) );
status = RtlUnicodeToUTF8N( dst, dstlen, &reslen, src, srclen * sizeof(WCHAR) ); else /* do it by hand to make sure every character roundtrips correctly */
if (status && status != STATUS_SOME_NOT_MAPPED) return -1; {
if (unix_table.DBCSOffsets)
{
const unsigned short *uni2cp = unix_table.WideCharTable;
for (i = dstlen; srclen && i; i--, srclen--, src++)
{
unsigned short ch = uni2cp[*src];
if (ch >> 8)
{
if (unix_table.DBCSOffsets[unix_table.DBCSOffsets[ch >> 8] + (ch & 0xff)] != *src)
return -1;
if (i == 1) break; /* do not output a partial char */
i--;
*dst++ = ch >> 8;
}
else
{
if (unix_table.MultiByteTable[ch] != *src) return -1;
*dst++ = (char)ch;
}
}
reslen = dstlen - i;
}
else
{
const unsigned char *uni2cp = unix_table.WideCharTable;
reslen = min( srclen, dstlen );
for (i = 0; i < reslen; i++)
{
unsigned char ch = uni2cp[src[i]];
if (unix_table.MultiByteTable[ch] != src[i]) return -1;
dst[i] = ch;
}
}
}
return reslen; return reslen;
} }
...@@ -744,8 +809,8 @@ int ntdll_wcstoumbs( DWORD flags, const WCHAR *src, int srclen, char *dst, int d ...@@ -744,8 +809,8 @@ int ntdll_wcstoumbs( DWORD flags, const WCHAR *src, int srclen, char *dst, int d
*/ */
UINT CDECL __wine_get_unix_codepage(void) UINT CDECL __wine_get_unix_codepage(void)
{ {
if (!unix_table) return CP_UTF8; if (!unix_table.CodePage) return CP_UTF8;
return unix_table->info.codepage; return unix_table.CodePage;
} }
......
...@@ -204,9 +204,8 @@ extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, ...@@ -204,9 +204,8 @@ extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue,
/* locale */ /* locale */
extern LCID user_lcid, system_lcid; extern LCID user_lcid, system_lcid;
extern int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst, int dstlen) DECLSPEC_HIDDEN; extern DWORD ntdll_umbstowcs( const char* src, DWORD srclen, WCHAR* dst, DWORD dstlen ) DECLSPEC_HIDDEN;
extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst, int dstlen, extern int ntdll_wcstoumbs( const WCHAR* src, DWORD srclen, char* dst, DWORD dstlen, BOOL strict ) DECLSPEC_HIDDEN;
const char* defchar, int *used ) DECLSPEC_HIDDEN;
extern int CDECL NTDLL__vsnprintf( char *str, SIZE_T len, const char *format, __ms_va_list args ) DECLSPEC_HIDDEN; extern int CDECL NTDLL__vsnprintf( char *str, SIZE_T len, const char *format, __ms_va_list args ) DECLSPEC_HIDDEN;
extern int CDECL NTDLL__vsnwprintf( WCHAR *str, SIZE_T len, const WCHAR *format, __ms_va_list args ) DECLSPEC_HIDDEN; extern int CDECL NTDLL__vsnwprintf( WCHAR *str, SIZE_T len, const WCHAR *format, __ms_va_list args ) DECLSPEC_HIDDEN;
......
...@@ -200,14 +200,14 @@ static int find_drive_rootW( LPCWSTR *ppath ) ...@@ -200,14 +200,14 @@ static int find_drive_rootW( LPCWSTR *ppath )
while (lenW > 1 && IS_SEPARATOR(path[lenW - 1])) lenW--; while (lenW > 1 && IS_SEPARATOR(path[lenW - 1])) lenW--;
/* convert path to Unix encoding */ /* convert path to Unix encoding */
lenA = ntdll_wcstoumbs( 0, path, lenW, NULL, 0, NULL, NULL ); if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, lenW * 3 + 1 ))) return -1;
if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, lenA + 1 ))) return -1;
lenA = ntdll_wcstoumbs( 0, path, lenW, buffer, lenA, NULL, NULL );
buffer[lenA] = 0;
for (p = buffer; *p; p++) if (*p == '\\') *p = '/';
for (;;) for (;;)
{ {
lenA = ntdll_wcstoumbs( path, lenW, buffer, lenW * 3, FALSE );
buffer[lenA] = 0;
for (p = buffer; *p; p++) if (*p == '\\') *p = '/';
if (!stat( buffer, &st ) && S_ISDIR( st.st_mode )) if (!stat( buffer, &st ) && S_ISDIR( st.st_mode ))
{ {
/* Find the drive */ /* Find the drive */
...@@ -226,10 +226,6 @@ static int find_drive_rootW( LPCWSTR *ppath ) ...@@ -226,10 +226,6 @@ static int find_drive_rootW( LPCWSTR *ppath )
} }
if (lenW <= 1) break; /* reached root */ if (lenW <= 1) break; /* reached root */
lenW = remove_last_componentW( path, lenW ); lenW = remove_last_componentW( path, lenW );
/* we only need the new length, buffer already contains the converted string */
lenA = ntdll_wcstoumbs( 0, path, lenW, NULL, 0, NULL, NULL );
buffer[lenA] = 0;
} }
RtlFreeHeap( GetProcessHeap(), 0, buffer ); RtlFreeHeap( GetProcessHeap(), 0, buffer );
return -1; return -1;
...@@ -1117,17 +1113,16 @@ NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRIN ...@@ -1117,17 +1113,16 @@ NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRIN
{ {
if (status == STATUS_OBJECT_PATH_NOT_FOUND) if (status == STATUS_OBJECT_PATH_NOT_FOUND)
{ {
lenW = ntdll_umbstowcs( 0, path, lenA, NULL, 0 );
nt->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, nt->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
(lenW + 1) * sizeof(WCHAR) + sizeof(unix_prefixW) ); (lenA + 1) * sizeof(WCHAR) + sizeof(unix_prefixW) );
if (nt->Buffer == NULL) if (nt->Buffer == NULL)
{ {
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
goto done; goto done;
} }
memcpy( nt->Buffer, unix_prefixW, sizeof(unix_prefixW) ); memcpy( nt->Buffer, unix_prefixW, sizeof(unix_prefixW) );
ntdll_umbstowcs( 0, path, lenA, nt->Buffer + ARRAY_SIZE( unix_prefixW ), lenW ); lenW = ARRAY_SIZE( unix_prefixW );
lenW += ARRAY_SIZE( unix_prefixW ); lenW += ntdll_umbstowcs( path, lenA, nt->Buffer + lenW, lenA );
nt->Buffer[lenW] = 0; nt->Buffer[lenW] = 0;
nt->Length = lenW * sizeof(WCHAR); nt->Length = lenW * sizeof(WCHAR);
nt->MaximumLength = nt->Length + sizeof(WCHAR); nt->MaximumLength = nt->Length + sizeof(WCHAR);
...@@ -1138,9 +1133,8 @@ NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRIN ...@@ -1138,9 +1133,8 @@ NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRIN
} }
while (lenA && path[0] == '/') { lenA--; path++; } while (lenA && path[0] == '/') { lenA--; path++; }
lenW = ntdll_umbstowcs( 0, path, lenA, NULL, 0 );
if (!(nt->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, if (!(nt->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
(lenW + 1) * sizeof(WCHAR) + sizeof(prefixW) ))) (lenA + 1) * sizeof(WCHAR) + sizeof(prefixW) )))
{ {
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
goto done; goto done;
...@@ -1148,8 +1142,8 @@ NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRIN ...@@ -1148,8 +1142,8 @@ NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRIN
memcpy( nt->Buffer, prefixW, sizeof(prefixW) ); memcpy( nt->Buffer, prefixW, sizeof(prefixW) );
nt->Buffer[4] += drive; nt->Buffer[4] += drive;
ntdll_umbstowcs( 0, path, lenA, nt->Buffer + ARRAY_SIZE( prefixW ), lenW ); lenW = ARRAY_SIZE( prefixW );
lenW += ARRAY_SIZE( prefixW ); lenW += ntdll_umbstowcs( path, lenA, nt->Buffer + lenW, lenA );
nt->Buffer[lenW] = 0; nt->Buffer[lenW] = 0;
nt->Length = lenW * sizeof(WCHAR); nt->Length = lenW * sizeof(WCHAR);
nt->MaximumLength = nt->Length + sizeof(WCHAR); nt->MaximumLength = nt->Length + sizeof(WCHAR);
......
...@@ -814,9 +814,9 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved ) ...@@ -814,9 +814,9 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
char *arg, *s, *d, *cmdline; char *arg, *s, *d, *cmdline;
int in_quotes, bcount, len; int in_quotes, bcount, len;
len = ntdll_wcstoumbs( 0, cmdlineW->Buffer, cmdlineW->Length / sizeof(WCHAR), NULL, 0, NULL, NULL ); len = cmdlineW->Length / sizeof(WCHAR);
if (!(cmdline = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 ))) return NULL; if (!(cmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * 3 + 1 ))) return NULL;
ntdll_wcstoumbs( 0, cmdlineW->Buffer, cmdlineW->Length / sizeof(WCHAR), cmdline, len, NULL, NULL ); len = ntdll_wcstoumbs( cmdlineW->Buffer, len, cmdline, len * 3, FALSE );
cmdline[len++] = 0; cmdline[len++] = 0;
argc = reserved + 1; argc = reserved + 1;
...@@ -1436,9 +1436,9 @@ static ULONG get_env_size( const RTL_USER_PROCESS_PARAMETERS *params, char **win ...@@ -1436,9 +1436,9 @@ static ULONG get_env_size( const RTL_USER_PROCESS_PARAMETERS *params, char **win
static const WCHAR WINEDEBUG[] = {'W','I','N','E','D','E','B','U','G','=',0}; static const WCHAR WINEDEBUG[] = {'W','I','N','E','D','E','B','U','G','=',0};
if (!*winedebug && !strncmpW( ptr, WINEDEBUG, ARRAY_SIZE( WINEDEBUG ) - 1 )) if (!*winedebug && !strncmpW( ptr, WINEDEBUG, ARRAY_SIZE( WINEDEBUG ) - 1 ))
{ {
DWORD len = ntdll_wcstoumbs( 0, ptr, strlenW(ptr) + 1, NULL, 0, NULL, NULL ); DWORD len = strlenW(ptr) * 3 + 1;
if ((*winedebug = RtlAllocateHeap( GetProcessHeap(), 0, len ))) if ((*winedebug = RtlAllocateHeap( GetProcessHeap(), 0, len )))
ntdll_wcstoumbs( 0, ptr, strlenW(ptr) + 1, *winedebug, len, NULL, NULL ); ntdll_wcstoumbs( ptr, strlenW(ptr) + 1, *winedebug, len, FALSE );
} }
ptr += strlenW(ptr) + 1; ptr += strlenW(ptr) + 1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment