From 573be7e6023e73d736c341bdca1ee49594f56ee4 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 12 Jun 2020 10:55:21 +0200 Subject: [PATCH] ntdll: Load the case mapping table in the Unix library. Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/env.c | 103 ++++++++++++++++----------------- dlls/ntdll/unix/unix_private.h | 63 ++++++++++++++++++-- 2 files changed, 106 insertions(+), 60 deletions(-) diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c index c2674be2c62..8b37d3dccac 100644 --- a/dlls/ntdll/unix/env.c +++ b/dlls/ntdll/unix/env.c @@ -65,6 +65,8 @@ extern char **__wine_main_argv; extern char **__wine_main_environ; extern WCHAR **__wine_main_wargv; +USHORT *uctable = NULL, *lctable = NULL; + static int main_argc; static char **main_argv; static char **main_envp; @@ -74,6 +76,36 @@ static CPTABLEINFO unix_table; static WCHAR system_locale[LOCALE_NAME_MAX_LENGTH]; static WCHAR user_locale[LOCALE_NAME_MAX_LENGTH]; +static void *read_nls_file( const char *name ) +{ + const char *dir = build_dir ? build_dir : data_dir; + struct stat st; + char *path; + void *data, *ret = NULL; + int fd; + + if (!(path = malloc( strlen(dir) + 22 ))) return NULL; + sprintf( path, "%s/nls/%s.nls", dir, name ); + if ((fd = open( path, O_RDONLY )) != -1) + { + fstat( fd, &st ); + if ((data = malloc( st.st_size )) && st.st_size > 0x1000 && + read( fd, data, st.st_size ) == st.st_size) + { + ret = data; + } + else + { + free( data ); + data = NULL; + } + close( fd ); + } + else ERR( "failed to load %s\n", path ); + free( path ); + return ret; +} + #ifdef __APPLE__ @@ -112,31 +144,7 @@ static struct norm_table *nfc_table; static void init_unix_codepage(void) { - const char *dir = build_dir ? build_dir : data_dir; - struct stat st; - char *name; - void *data; - int fd; - - if (!(name = malloc( strlen(dir) + 17 ))) return; - sprintf( name, "%s/nls/normnfc.nls", dir ); - if ((fd = open( name, O_RDONLY )) != -1) - { - fstat( fd, &st ); - if ((data = malloc( st.st_size )) && - st.st_size > 0x4000 && - read( fd, data, st.st_size ) == st.st_size) - { - nfc_table = data; - } - else - { - free( data ); - } - close( fd ); - } - else ERR( "failed to load %s\n", name ); - free( name ); + nfc_table = read_nls_file( "normnfc" ); } static int get_utf16( const WCHAR *src, unsigned int srclen, unsigned int *ch ) @@ -343,34 +351,6 @@ static const struct { const char *name; UINT cp; } charset_names[] = { "UTF8", CP_UTF8 } }; -static void load_unix_cptable( unsigned int cp ) -{ - const char *dir = build_dir ? build_dir : data_dir; - struct stat st; - char *name; - void *data; - int fd; - - if (!(name = malloc( 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 = malloc( st.st_size )) && st.st_size > 0x10000 && - read( fd, data, st.st_size ) == st.st_size) - { - RtlInitCodePageTable( data, &unix_table ); - } - else - { - free( data ); - } - close( fd ); - } - else ERR( "failed to load %s\n", name ); - free( name ); -} - static void init_unix_codepage(void) { char charset_name[16]; @@ -396,7 +376,14 @@ static void init_unix_codepage(void) int res = strcmp( charset_names[pos].name, charset_name ); if (!res) { - if (charset_names[pos].cp != CP_UTF8) load_unix_cptable( charset_names[pos].cp ); + if (charset_names[pos].cp != CP_UTF8) + { + char name[16]; + void *data; + + sprintf( name, "c_%03u", charset_names[pos].cp ); + if ((data = read_nls_file( name ))) RtlInitCodePageTable( data, &unix_table ); + } return; } if (res > 0) max = pos - 1; @@ -797,9 +784,17 @@ static void init_locale(void) */ void init_environment( int argc, char *argv[], char *envp[] ) { + USHORT *case_table; + init_unix_codepage(); init_locale(); set_process_name( argc, argv ); + + if ((case_table = read_nls_file( "l_intl" ))) + { + uctable = case_table + 2; + lctable = case_table + case_table[1] + 2; + } __wine_main_argc = main_argc = argc; __wine_main_argv = main_argv = argv; __wine_main_wargv = main_wargv = build_wargv( argv ); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 1ef2111da19..b672321440d 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -123,6 +123,8 @@ extern NTSTATUS CDECL fork_and_exec( const char *unix_name, const char *unix_dir extern const char *data_dir DECLSPEC_HIDDEN; extern const char *build_dir DECLSPEC_HIDDEN; extern const char *config_dir DECLSPEC_HIDDEN; +extern USHORT *uctable DECLSPEC_HIDDEN; +extern USHORT *lctable DECLSPEC_HIDDEN; extern unsigned int server_cpus DECLSPEC_HIDDEN; extern BOOL is_wow64 DECLSPEC_HIDDEN; extern HANDLE keyed_event DECLSPEC_HIDDEN; @@ -212,6 +214,13 @@ static inline int ntdll_wcscmp( const WCHAR *str1, const WCHAR *str2 ) return *str1 - *str2; } +static inline int ntdll_wcsncmp( const WCHAR *str1, const WCHAR *str2, int n ) +{ + if (n <= 0) return 0; + while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; } + return *str1 - *str2; +} + static inline WCHAR *ntdll_wcschr( const WCHAR *str, WCHAR ch ) { do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++); @@ -224,11 +233,53 @@ static inline WCHAR *ntdll_wcspbrk( const WCHAR *str, const WCHAR *accept ) return NULL; } -#define wcslen(str) ntdll_wcslen(str) -#define wcscpy(dst,src) ntdll_wcscpy(dst,src) -#define wcscat(dst,src) ntdll_wcscat(dst,src) -#define wcscmp(s1,s2) ntdll_wcscmp(s1,s2) -#define wcschr(str,ch) ntdll_wcschr(str,ch) -#define wcspbrk(str,ac) ntdll_wcspbrk(str,ac) +static inline WCHAR ntdll_towupper( WCHAR ch ) +{ + return ch + uctable[uctable[uctable[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0x0f)]; +} + +static inline WCHAR ntdll_towlower( WCHAR ch ) +{ + return ch + lctable[lctable[lctable[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0x0f)]; +} + +static inline WCHAR *ntdll_wcsupr( WCHAR *str ) +{ + WCHAR *ret; + for (ret = str; *str; str++) *str = ntdll_towupper(*str); + return ret; +} + +static inline int ntdll_wcsicmp( const WCHAR *str1, const WCHAR *str2 ) +{ + int ret; + for (;;) + { + if ((ret = ntdll_towupper( *str1 ) - ntdll_towupper( *str2 )) || !*str1) return ret; + str1++; + str2++; + } +} + +static inline int ntdll_wcsnicmp( const WCHAR *str1, const WCHAR *str2, int n ) +{ + int ret; + for (ret = 0; n > 0; n--, str1++, str2++) + if ((ret = ntdll_towupper(*str1) - ntdll_towupper(*str2)) || !*str1) break; + return ret; +} + +#define wcslen(str) ntdll_wcslen(str) +#define wcscpy(dst,src) ntdll_wcscpy(dst,src) +#define wcscat(dst,src) ntdll_wcscat(dst,src) +#define wcscmp(s1,s2) ntdll_wcscmp(s1,s2) +#define wcsncmp(s1,s2,n) ntdll_wcsncmp(s1,s2,n) +#define wcschr(str,ch) ntdll_wcschr(str,ch) +#define wcspbrk(str,ac) ntdll_wcspbrk(str,ac) +#define wcsicmp(s1, s2) ntdll_wcsicmp(s1,s2) +#define wcsnicmp(s1, s2,n) ntdll_wcsnicmp(s1,s2,n) +#define wcsupr(str) ntdll_wcsupr(str) +#define towupper(c) ntdll_towupper(c) +#define towlower(c) ntdll_towlower(c) #endif /* __NTDLL_UNIX_PRIVATE_H */