This patch allows to use the UNIX code page inside of ntdll. The full change log: - moved code page & NLS resources from kernel32 to ntdll - moved locale initialisation from kernel32 to ntdll - created unix code page handling in ntdll - made use of this unix cp for the initial environment creation (in PEB)
in order to keep the size of the patch small, I didn't include in the patch the bits for moving dlls/kernel32/locale.rc (resp. dlls/kernel32/nls/*) to dlls/ntdll/locale.rc (resp dlls/ntdll/nls/*). This should be done by hand.
A+
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel39/kernel.rc dlls/kernel/kernel.rc --- dlls/kernel39/kernel.rc 2004-01-01 09:53:31.000000000 +0100 +++ dlls/kernel/kernel.rc 2004-01-01 09:53:34.000000000 +0100 @@ -16,8 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "locale_rc.rc" - #include "messages/winerr_enu.mc.rc" #include "version.rc" diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel39/locale.c dlls/kernel/locale.c --- dlls/kernel39/locale.c 2004-01-01 09:53:31.000000000 +0100 +++ dlls/kernel/locale.c 2004-01-01 09:53:34.000000000 +0100 @@ -47,7 +47,7 @@ #define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|LOCALE_RETURN_NUMBER) -static const WCHAR kernel32W[] = { 'K','E','R','N','E','L','3','2','\0' }; +static const WCHAR ntdllW[] = { 'N','T','D','L','L','\0' }; /* current code pages */ static const union cptable *ansi_cptable; @@ -55,103 +55,6 @@ static const union cptable *mac_cptable; static const union cptable *unix_cptable; /* NULL if UTF8 */ -/* Charset to codepage map, sorted by name. */ -static const struct charset_entry -{ - const char *charset_name; - UINT codepage; -} charset_names[] = -{ - { "CP1250", 1250 }, - { "CP1251", 1251 }, - { "CP1252", 1252 }, - { "CP1253", 1253 }, - { "CP1254", 1254 }, - { "CP1255", 1255 }, - { "CP1256", 1256 }, - { "CP1257", 1257 }, - { "CP1258", 1258 }, - { "EUCJP", 20932 }, - { "IBM037", 37 }, - { "IBM1026", 1026 }, - { "IBM424", 424 }, - { "IBM437", 437 }, - { "IBM500", 500 }, - { "IBM850", 850 }, - { "IBM852", 852 }, - { "IBM855", 855 }, - { "IBM857", 857 }, - { "IBM860", 860 }, - { "IBM861", 861 }, - { "IBM862", 862 }, - { "IBM863", 863 }, - { "IBM864", 864 }, - { "IBM865", 865 }, - { "IBM866", 866 }, - { "IBM869", 869 }, - { "IBM874", 874 }, - { "IBM875", 875 }, - { "ISO88591", 28591 }, - { "ISO885910", 28600 }, - { "ISO885913", 28603 }, - { "ISO885914", 28604 }, - { "ISO885915", 28605 }, - { "ISO88592", 28592 }, - { "ISO88593", 28593 }, - { "ISO88594", 28594 }, - { "ISO88595", 28595 }, - { "ISO88596", 28596 }, - { "ISO88597", 28597 }, - { "ISO88598", 28598 }, - { "ISO88599", 28599 }, - { "KOI8R", 20866 }, - { "KOI8U", 20866 }, - { "UTF8", CP_UTF8 } -}; - -#define NLS_MAX_LANGUAGES 20 -typedef struct { - WCHAR lang[128]; - WCHAR country[4]; - LANGID found_lang_id[NLS_MAX_LANGUAGES]; - WCHAR found_language[NLS_MAX_LANGUAGES][3]; - WCHAR found_country[NLS_MAX_LANGUAGES][3]; - int n_found; -} LANG_FIND_DATA; - - -/* copy Unicode string to Ascii without using codepages */ -static inline void strcpyWtoA( char *dst, const WCHAR *src ) -{ - while ((*dst++ = *src++)); -} - -/* Copy Ascii string to Unicode without using codepages */ -static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n ) -{ - while (n > 1 && *src) - { - *dst++ = (unsigned char)*src++; - n--; - } - if (n) *dst = 0; -} - -/* return a printable string for a language id */ -static const char *debugstr_lang( LANGID lang ) -{ - WCHAR langW[4], countryW[4]; - char buffer[8]; - LCID lcid = MAKELCID( lang, SORT_DEFAULT ); - - GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME|LOCALE_NOUSEROVERRIDE, langW, sizeof(langW)); - GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME|LOCALE_NOUSEROVERRIDE, countryW, sizeof(countryW)); - strcpyWtoA( buffer, langW ); - strcat( buffer, "_" ); - strcpyWtoA( buffer + strlen(buffer), countryW ); - return wine_dbg_sprintf( "%s", buffer ); -} - /*********************************************************************** * get_lcid_codepage * @@ -177,7 +80,7 @@ assert( ansi_cptable ); /* init must have been done already */ - switch(codepage) + switch (codepage) { case CP_ACP: return ansi_cptable; @@ -303,232 +206,6 @@ } } - -/*********************************************************************** - * find_language_id_proc - */ -static BOOL CALLBACK find_language_id_proc( HMODULE hModule, LPCWSTR type, - LPCWSTR name, WORD LangID, LPARAM lParam ) -{ - LANG_FIND_DATA *l_data = (LANG_FIND_DATA *)lParam; - LCID lcid = MAKELCID(LangID, SORT_DEFAULT); - WCHAR buf_language[128]; - WCHAR buf_country[128]; - WCHAR buf_en_language[128]; - - if(PRIMARYLANGID(LangID) == LANG_NEUTRAL) - return TRUE; /* continue search */ - - buf_language[0] = 0; - buf_country[0] = 0; - - GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME|LOCALE_NOUSEROVERRIDE, - buf_language, sizeof(buf_language)); - GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME|LOCALE_NOUSEROVERRIDE, - buf_country, sizeof(buf_country)); - - if(l_data->lang[0] && !strcmpiW(l_data->lang, buf_language)) - { - if(l_data->country[0]) - { - if(!strcmpiW(l_data->country, buf_country)) - { - l_data->found_lang_id[0] = LangID; - l_data->n_found = 1; - TRACE("Found id %04X for lang %s country %s\n", - LangID, debugstr_w(l_data->lang), debugstr_w(l_data->country)); - return FALSE; /* stop enumeration */ - } - } - else goto found; /* l_data->country not specified */ - } - - /* Just in case, check LOCALE_SENGLANGUAGE too, - * in hope that possible alias name might have that value. - */ - buf_en_language[0] = 0; - GetLocaleInfoW(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE, - buf_en_language, sizeof(buf_en_language)); - - if(l_data->lang[0] && !strcmpiW(l_data->lang, buf_en_language)) goto found; - return TRUE; /* not found, continue search */ - -found: - l_data->found_lang_id[l_data->n_found] = LangID; - strncpyW(l_data->found_country[l_data->n_found], buf_country, 3); - strncpyW(l_data->found_language[l_data->n_found], buf_language, 3); - l_data->n_found++; - TRACE("Found id %04X for lang %s\n", LangID, debugstr_w(l_data->lang)); - return (l_data->n_found < NLS_MAX_LANGUAGES); /* continue search, unless we have enough */ -} - - -/*********************************************************************** - * get_language_id - * - * INPUT: - * Lang: a string whose two first chars are the iso name of a language. - * Country: a string whose two first chars are the iso name of country - * Charset: a string defining the chosen charset encoding - * Dialect: a string defining a variation of the locale - * - * all those values are from the standardized format of locale - * name in unix which is: Lang[_Country][.Charset][@Dialect] - * - * RETURNS: - * the numeric code of the language used by Windows - * - * FIXME: Charset and Dialect are not handled - */ -static LANGID get_language_id(LPCSTR Lang, LPCSTR Country, LPCSTR Charset, LPCSTR Dialect) -{ - LANG_FIND_DATA l_data; - HMODULE hKernel32; - - if(!Lang) - { - l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); - goto END; - } - - l_data.n_found = 0; - strcpynAtoW(l_data.lang, Lang, sizeof(l_data.lang)); - - if (Country) strcpynAtoW(l_data.country, Country, sizeof(l_data.country)); - else l_data.country[0] = 0; - - hKernel32 = GetModuleHandleW(kernel32W); - - EnumResourceLanguagesW(hKernel32, (LPCWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE, - find_language_id_proc, (LPARAM)&l_data); - - if (l_data.n_found == 1) goto END; - - if(!l_data.n_found) - { - if(l_data.country[0]) - { - /* retry without country name */ - l_data.country[0] = 0; - EnumResourceLanguagesW(hKernel32, (LPCWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE, - find_language_id_proc, (LONG)&l_data); - if (!l_data.n_found) - { - MESSAGE("Warning: Language '%s_%s' was not recognized, defaulting to English.\n", - Lang, Country); - l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); - } - else MESSAGE("Warning: Language '%s_%s' was not recognized, defaulting to '%s'.\n", - Lang, Country, debugstr_lang(l_data.found_lang_id[0]) ); - } - else - { - MESSAGE("Warning: Language '%s' was not recognized, defaulting to English.\n", Lang); - l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); - } - } - else - { - int i; - - if (Country && Country[0]) - MESSAGE("For language '%s_%s' several language ids were found:\n", Lang, Country); - else - MESSAGE("For language '%s' several language ids were found:\n", Lang); - - /* print a list of languages with their description */ - for (i = 0; i < l_data.n_found; i++) - { - WCHAR buffW[128]; - char buffA[128]; - GetLocaleInfoW( MAKELCID( l_data.found_lang_id[i], SORT_DEFAULT ), - LOCALE_SLANGUAGE|LOCALE_NOUSEROVERRIDE, buffW, sizeof(buffW)); - strcpyWtoA( buffA, buffW ); - MESSAGE( " %s (%04X) - %s\n", debugstr_lang(l_data.found_lang_id[i]), - l_data.found_lang_id[i], buffA ); - } - MESSAGE("Defaulting to '%s'. You should specify the exact language you want\n" - "by defining your LANG environment variable like this: LANG=%s\n", - debugstr_lang(l_data.found_lang_id[0]), debugstr_lang(l_data.found_lang_id[0]) ); - } -END: - TRACE("Returning %04X (%s)\n", l_data.found_lang_id[0], debugstr_lang(l_data.found_lang_id[0])); - return l_data.found_lang_id[0]; -} - - -/*********************************************************************** - * charset_cmp (internal) - */ -static int charset_cmp( const void *name, const void *entry ) -{ - const struct charset_entry *charset = (struct charset_entry *)entry; - return strcasecmp( (char *)name, charset->charset_name ); -} - -/*********************************************************************** - * init_default_lcid - */ -static LCID init_default_lcid( UINT *unix_cp ) -{ - char *buf, *lang,*country,*charset,*dialect,*next; - LCID ret = 0; - - if ((lang = getenv( "LC_ALL" )) || - (lang = getenv( "LC_CTYPE" )) || - (lang = getenv( "LANGUAGE" )) || - (lang = getenv( "LC_MESSAGES" )) || - (lang = getenv( "LANG" ))) - { - if (!strcmp(lang,"POSIX") || !strcmp(lang,"C")) goto done; - - buf = RtlAllocateHeap( GetProcessHeap(), 0, strlen(lang) + 1 ); - strcpy( buf, lang ); - lang=buf; - - do { - next=strchr(lang,':'); if (next) *next++='\0'; - dialect=strchr(lang,'@'); if (dialect) *dialect++='\0'; - charset=strchr(lang,'.'); if (charset) *charset++='\0'; - country=strchr(lang,'_'); if (country) *country++='\0'; - - ret = get_language_id(lang, country, charset, dialect); - if (ret && charset) - { - const struct charset_entry *entry; - char charset_name[16]; - size_t i, j; - - /* remove punctuation characters from charset name */ - for (i = j = 0; charset[i] && j < sizeof(charset_name)-1; i++) - if (isalnum(charset[i])) charset_name[j++] = charset[i]; - charset_name[j] = 0; - - entry = bsearch( charset_name, charset_names, - sizeof(charset_names)/sizeof(charset_names[0]), - sizeof(charset_names[0]), charset_cmp ); - if (entry) - { - *unix_cp = entry->codepage; - TRACE("charset %s was mapped to cp %u\n", charset, *unix_cp); - } - else - FIXME("charset %s was not recognized\n", charset); - } - - lang=next; - } while (lang && !ret); - - if (!ret) MESSAGE("Warning: language '%s' not recognized, defaulting to English\n", buf); - RtlFreeHeap( GetProcessHeap(), 0, buf ); - } - - done: - if (!ret) ret = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT) ; - return ret; -} - - /*********************************************************************** * GetUserDefaultLangID (KERNEL32.@) * @@ -945,7 +622,7 @@ if (SUBLANGID(lang_id) == SUBLANG_NEUTRAL) lang_id = MAKELANGID(PRIMARYLANGID(lang_id), SUBLANG_DEFAULT); - hModule = GetModuleHandleW( kernel32W ); + hModule = GetModuleHandleW( ntdllW ); if (!(hrsrc = FindResourceExW( hModule, (LPWSTR)RT_STRING, (LPCWSTR)((lctype >> 4) + 1), lang_id ))) { SetLastError( ERROR_INVALID_FLAGS ); /* no such lctype */ @@ -1189,7 +866,7 @@ */ BOOL WINAPI IsValidCodePage( UINT codepage ) { - switch(codepage) { + switch (codepage) { case CP_SYMBOL: return FALSE; case CP_UTF7: @@ -1423,7 +1100,7 @@ if (flags & MB_USEGLYPHCHARS) FIXME("MB_USEGLYPHCHARS not supported\n"); - switch(page) + switch (page) { case CP_UTF7: FIXME("UTF-7 not supported\n"); @@ -1451,7 +1128,7 @@ if (ret < 0) { - switch(ret) + switch (ret) { case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break; case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break; @@ -1501,7 +1178,7 @@ if (srclen < 0) srclen = strlenW(src) + 1; - switch(page) + switch (page) { case CP_UTF7: FIXME("UTF-7 not supported\n"); @@ -1651,7 +1328,7 @@ BOOL WINAPI IsValidLocale( LCID lcid, DWORD flags ) { /* check if language is registered in the kernel32 resources */ - return FindResourceExW( GetModuleHandleW(kernel32W), (LPWSTR)RT_STRING, + return FindResourceExW( GetModuleHandleW(ntdllW), (LPWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE, LANGIDFROMLCID(lcid)) != 0; } @@ -1692,7 +1369,7 @@ BOOL WINAPI EnumSystemLocalesA( LOCALE_ENUMPROCA lpfnLocaleEnum, DWORD dwFlags ) { TRACE("(%p,%08lx)\n", lpfnLocaleEnum, dwFlags); - EnumResourceLanguagesA( GetModuleHandleW(kernel32W), (LPSTR)RT_STRING, + EnumResourceLanguagesA( GetModuleHandleW(ntdllW), (LPSTR)RT_STRING, (LPCSTR)LOCALE_ILANGUAGE, enum_lang_proc_a, (LONG)lpfnLocaleEnum); return TRUE; @@ -1707,7 +1384,7 @@ BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags ) { TRACE("(%p,%08lx)\n", lpfnLocaleEnum, dwFlags); - EnumResourceLanguagesW( GetModuleHandleW(kernel32W), (LPWSTR)RT_STRING, + EnumResourceLanguagesW( GetModuleHandleW(ntdllW), (LPWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE, enum_lang_proc_w, (LONG)lpfnLocaleEnum); return TRUE; @@ -1754,7 +1431,7 @@ BOOL WINAPI GetStringTypeW( DWORD type, LPCWSTR src, INT count, LPWORD chartype ) { if (count == -1) count = strlenW(src) + 1; - switch(type) + switch (type) { case CT_CTYPE1: while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff; @@ -2389,22 +2066,18 @@ */ void LOCALE_Init(void) { - extern void __wine_init_codepages( const union cptable *ansi_cp, const union cptable *oem_cp ); - - UINT ansi_cp = 1252, oem_cp = 437, mac_cp = 10000, unix_cp = ~0U; - LCID lcid = init_default_lcid( &unix_cp ); + LCID lcid; + UINT ansi_cp, oem_cp, mac_cp, unix_cp; - NtSetDefaultLocale( FALSE, lcid ); - NtSetDefaultLocale( TRUE, lcid ); + NtQueryDefaultLocale( TRUE, &lcid ); ansi_cp = get_lcid_codepage(lcid); + GetLocaleInfoW( lcid, LOCALE_IDEFAULTMACCODEPAGE | LOCALE_RETURN_NUMBER, (LPWSTR)&mac_cp, sizeof(mac_cp)/sizeof(WCHAR) ); GetLocaleInfoW( lcid, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER, (LPWSTR)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR) ); - if (unix_cp == ~0U) - GetLocaleInfoW( lcid, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER, - (LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) ); + unix_cp = NtCurrentTeb()->Peb->unix_code_page; if (!(ansi_cptable = wine_cp_get_table( ansi_cp ))) ansi_cptable = wine_cp_get_table( 1252 ); @@ -2412,13 +2085,9 @@ oem_cptable = wine_cp_get_table( 437 ); if (!(mac_cptable = wine_cp_get_table( mac_cp ))) mac_cptable = wine_cp_get_table( 10000 ); - if (unix_cp != CP_UTF8) - { - if (!(unix_cptable = wine_cp_get_table( unix_cp ))) - unix_cptable = wine_cp_get_table( 28591 ); - } - __wine_init_codepages( ansi_cptable, oem_cptable ); + if (unix_cp != CP_UTF8 && !(unix_cptable = wine_cp_get_table( unix_cp ))) + unix_cptable = wine_cp_get_table( 28591 ); TRACE( "ansi=%03d oem=%03d mac=%03d unix=%03d\n", ansi_cptable->info.codepage, oem_cptable->info.codepage, @@ -2523,7 +2192,7 @@ static BOOL NLS_GetLanguageGroupName(LGRPID lgrpid, LPWSTR szName, ULONG nameSize) { - HMODULE hModule = GetModuleHandleW(kernel32W); + HMODULE hModule = GetModuleHandleW(ntdllW); LANGID langId; LPCWSTR szResourceName = (LPCWSTR)(((lgrpid + 0x2000) >> 4) + 1); HRSRC hResource; @@ -3030,3 +2699,6 @@ FIXME("%ld\n",GeoID); return FALSE; } + + + diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel39/process.c dlls/kernel/process.c --- dlls/kernel39/process.c 2004-01-01 09:53:31.000000000 +0100 +++ dlls/kernel/process.c 2004-01-02 17:35:25.000000000 +0100 @@ -333,48 +333,6 @@ return module; } -/*********************************************************************** - * build_initial_environment - * - * Build the Win32 environment from the Unix environment - */ -static BOOL build_initial_environment( char **environ ) -{ - ULONG size = 1; - char **e; - WCHAR *p, *endptr; - void *ptr; - - /* Compute the total size of the Unix environment */ - for (e = environ; *e; e++) - { - if (!memcmp(*e, "PATH=", 5)) continue; - size += MultiByteToWideChar( CP_UNIXCP, 0, *e, -1, NULL, 0 ); - } - size *= sizeof(WCHAR); - - /* Now allocate the environment */ - if (NtAllocateVirtualMemory(NtCurrentProcess(), &ptr, 0, &size, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) != STATUS_SUCCESS) - return FALSE; - - NtCurrentTeb()->Peb->ProcessParameters->Environment = p = ptr; - endptr = p + size / sizeof(WCHAR); - - /* And fill it with the Unix environment */ - for (e = environ; *e; e++) - { - char *str = *e; - /* skip Unix PATH and store WINEPATH as PATH */ - if (!memcmp(str, "PATH=", 5)) continue; - if (!memcmp(str, "WINEPATH=", 9 )) str += 4; - MultiByteToWideChar( CP_UNIXCP, 0, str, -1, p, endptr - p ); - p += strlenW(p) + 1; - } - *p = 0; - return TRUE; -} - /*********************************************************************** * set_library_wargv @@ -611,7 +569,7 @@ * * Main process initialisation code */ -static BOOL process_init( char *argv[], char **environ ) +static BOOL process_init( char *argv[] ) { BOOL ret; size_t info_size = 0; @@ -695,9 +653,6 @@ LOCALE_Init(); - /* Copy the parent environment */ - if (!build_initial_environment( environ )) return FALSE; - /* Parse command line arguments */ OPTIONS_ParseOptions( !info_size ? argv : NULL ); @@ -771,7 +726,7 @@ PEB *peb = NtCurrentTeb()->Peb; /* Initialize everything */ - if (!process_init( __wine_main_argv, __wine_main_environ )) exit(1); + if (!process_init( __wine_main_argv )) exit(1); /* update argc in case options have been removed */ for (__wine_main_argc = 0; __wine_main_argv[__wine_main_argc]; __wine_main_argc++) /*nothing*/; @@ -1152,7 +1107,6 @@ return NULL; } - params->Environment = NULL; /* we pass it through the Unix environment */ params->hStdInput = startup->hStdInput; params->hStdOutput = startup->hStdOutput; params->hStdError = startup->hStdError; diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll39/env.c dlls/ntdll/env.c --- dlls/ntdll39/env.c 2004-01-01 09:53:16.000000000 +0100 +++ dlls/ntdll/env.c 2004-01-02 20:29:36.000000000 +0100 @@ -29,10 +29,53 @@ #include "winternl.h" #include "wine/unicode.h" #include "wine/debug.h" +#include "wine/library.h" #include "ntdll_misc.h" WINE_DEFAULT_DEBUG_CHANNEL(environ); +/*********************************************************************** + * build_initial_environment + * + * Build the Win32 environment from the Unix environment + */ +BOOL build_initial_environment( void ) +{ + ULONG size = 1; + char **e; + WCHAR *p, *endptr; + void* new_env; + + /* Compute the total size of the Unix environment */ + for (e = __wine_main_environ; *e; e++) + { + if (!memcmp(*e, "PATH=", 5)) continue; + size += ntdll_mbs2wcs( 0, *e, strlen(*e) + 1, NULL, 0 ); + } + size *= sizeof(WCHAR); + + /* Now allocate the environment */ + if (NtAllocateVirtualMemory(NtCurrentProcess(), &new_env, 0, &size, + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) != STATUS_SUCCESS) + return FALSE; + p = ntdll_get_process_pmts()->Environment = new_env; + endptr = p + size / sizeof(WCHAR); + + /* And fill it with the Unix environment */ + for (e = __wine_main_environ; *e; e++) + { + char *str = *e; + /* skip Unix PATH and store WINEPATH as PATH */ + if (!memcmp(str, "PATH=", 5)) continue; + if (!memcmp(str, "WINEPATH=", 9 )) str += 4; + ntdll_mbs2wcs( 0, str, strlen(str) + 1, p, endptr - p ); + p += strlenW(p) + 1; + } + *p = 0; + return TRUE; +} + + /****************************************************************************** * RtlCreateEnvironment [NTDLL.@] */ diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll39/loader.c dlls/ntdll/loader.c --- dlls/ntdll39/loader.c 2004-01-02 20:34:06.000000000 +0100 +++ dlls/ntdll/loader.c 2004-01-02 20:45:31.000000000 +0100 @@ -1962,6 +1962,9 @@ /* setup the load callback and create ntdll modref */ wine_dll_set_callback( load_builtin_callback ); + LOCALE_Init(); + build_initial_environment(); + if ((status = load_builtin_dll( NULL, kernel32W, 0, &wm )) != STATUS_SUCCESS) { MESSAGE( "wine: could not load kernel32.dll, status %lx\n", status ); diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll39/locale.c dlls/ntdll/locale.c --- dlls/ntdll39/locale.c 1970-01-01 01:00:00.000000000 +0100 +++ dlls/ntdll/locale.c 2004-01-01 09:53:20.000000000 +0100 @@ -0,0 +1,517 @@ +/* + * Locale support + * + * Copyright 1995 Martin von Loewis + * Copyright 1998 David Lee Lambert + * Copyright 2000 Julio César Gázquez + * Copyright 2002 Alexandre Julliard for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "wine/port.h" + +#include <assert.h> +#include <string.h> +#include <stdarg.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#include "ntstatus.h" +#include "windef.h" +#include "winbase.h" +#include "winuser.h" /* for RT_STRINGW */ +#include "winreg.h" +#include "winternl.h" +#include "wine/unicode.h" +#include "winnls.h" +#include "winerror.h" +#include "thread.h" +#include "ntdll_misc.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(nls); + +#define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|LOCALE_RETURN_NUMBER) + +UINT NlsAnsiCodePage = 0; +BYTE NlsMbCodePageTag = 0; +BYTE NlsMbOemCodePageTag = 0; + +/* current code page tables */ +const union cptable *ansi_cptable; +const union cptable *oem_cptable; +const union cptable *unix_cptable; /* NULL if UTF8 */ + +/* Charset to codepage map, sorted by name. */ +static const struct charset_entry +{ + const char *charset_name; + UINT codepage; +} charset_names[] = +{ + { "CP1250", 1250 }, + { "CP1251", 1251 }, + { "CP1252", 1252 }, + { "CP1253", 1253 }, + { "CP1254", 1254 }, + { "CP1255", 1255 }, + { "CP1256", 1256 }, + { "CP1257", 1257 }, + { "CP1258", 1258 }, + { "EUCJP", 20932 }, + { "IBM037", 37 }, + { "IBM1026", 1026 }, + { "IBM424", 424 }, + { "IBM437", 437 }, + { "IBM500", 500 }, + { "IBM850", 850 }, + { "IBM852", 852 }, + { "IBM855", 855 }, + { "IBM857", 857 }, + { "IBM860", 860 }, + { "IBM861", 861 }, + { "IBM862", 862 }, + { "IBM863", 863 }, + { "IBM864", 864 }, + { "IBM865", 865 }, + { "IBM866", 866 }, + { "IBM869", 869 }, + { "IBM874", 874 }, + { "IBM875", 875 }, + { "ISO88591", 28591 }, + { "ISO885910", 28600 }, + { "ISO885913", 28603 }, + { "ISO885914", 28604 }, + { "ISO885915", 28605 }, + { "ISO88592", 28592 }, + { "ISO88593", 28593 }, + { "ISO88594", 28594 }, + { "ISO88595", 28595 }, + { "ISO88596", 28596 }, + { "ISO88597", 28597 }, + { "ISO88598", 28598 }, + { "ISO88599", 28599 }, + { "KOI8R", 20866 }, + { "KOI8U", 20866 }, + { "UTF8", CP_UTF8 } +}; + +#define NLS_MAX_LANGUAGES 20 +typedef struct { + WCHAR lang[128]; + WCHAR country[4]; + LANGID found_lang_id[NLS_MAX_LANGUAGES]; + WCHAR found_language[NLS_MAX_LANGUAGES][3]; + WCHAR found_country[NLS_MAX_LANGUAGES][3]; + int n_found; +} LANG_FIND_DATA; + + +/* copy Unicode string to Ascii without using codepages */ +static inline void strcpyWtoA( char *dst, const WCHAR *src ) +{ + while ((*dst++ = *src++)); +} + +/* Copy Ascii string to Unicode without using codepages */ +static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n ) +{ + while (n > 1 && *src) + { + *dst++ = (unsigned char)*src++; + n--; + } + if (n) *dst = 0; +} + +static LPCWSTR get_locale_info_head( LCID lcid, LCTYPE lctype ) +{ + LANGID lang_id; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL; + UINT i, lcflags; + LPCWSTR p; + LDR_MODULE* mod; + + lang_id = LANGIDFROMLCID(lcid); + if (SUBLANGID(lang_id) == SUBLANG_NEUTRAL) + { + lang_id = MAKELANGID(PRIMARYLANGID(lang_id), SUBLANG_DEFAULT); + lcid = MAKELCID(lang_id, SORTIDFROMLCID(lcid)); + } + + lcflags = lctype & LOCALE_LOCALEINFOFLAGSMASK; + lctype &= 0xffff; + + /* now load it from kernel resources */ + info.Type = (ULONG)RT_STRING; + info.Name = (lctype >> 4) + 1; + info.Language = lang_id; + + mod = CONTAINING_RECORD(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList.Flink->Flink, LDR_MODULE, InLoadOrderModuleList); + + if (LdrFindResource_U( mod->BaseAddress, &info, 3, &entry ) || + LdrAccessResource( mod->BaseAddress, entry, (void**)&p, NULL )) return NULL; + + for (i = 0; i < (lctype & 0x0f); i++) p += *p + 1; + return p; +} + +static BOOL get_locale_info_number( LCID lcid, LCTYPE lctype, UINT* val ) +{ + LPCWSTR p; + LPWSTR end, tmp; + BOOL ret; + + p = get_locale_info_head(lcid, lctype); + if (!p) return FALSE; + + tmp = RtlAllocateHeap( GetProcessHeap(), 0, (*p + 1) * sizeof(WCHAR) ); + if (!tmp) return FALSE; + memcpy( tmp, p + 1, *p * sizeof(WCHAR) ); + tmp[*p] = 0; + *val = strtolW( tmp, &end, 10 ); + ret = !*end; + RtlFreeHeap( GetProcessHeap(), 0, tmp ); + + TRACE( "(lcid=0x%lx,lctype=0x%lx) returning number %d\n", lcid, lctype, *val ); + return ret; +} + +static UINT get_locale_info_str( LCID lcid, LCTYPE lctype, WCHAR* buffer, INT len) +{ + LPCWSTR p; + UINT efflen; + + p = get_locale_info_head(lcid, lctype); + if (!p) return 0; + + efflen = (lctype == LOCALE_FONTSIGNATURE) ? *p : *p + 1; + + if (buffer && efflen <= len) + { + memcpy( buffer, p + 1, *p * sizeof(WCHAR) ); + if (lctype != LOCALE_FONTSIGNATURE) buffer[efflen-1] = 0; + + TRACE( "(lcid=0x%lx,lctype=0x%lx,%p,%d) returning %d %s\n", + lcid, lctype, buffer, len, efflen, debugstr_w(buffer) ); + } + return efflen; +} + + +/* return a printable string for a language id */ +static const char *debugstr_lang( LANGID lang ) +{ + WCHAR langW[4], countryW[4]; + char buffer[8]; + LCID lcid = MAKELCID( lang, SORT_DEFAULT ); + + get_locale_info_str(lcid, LOCALE_SISO639LANGNAME|LOCALE_NOUSEROVERRIDE, langW, sizeof(langW)); + get_locale_info_str(lcid, LOCALE_SISO3166CTRYNAME|LOCALE_NOUSEROVERRIDE, countryW, sizeof(countryW)); + strcpyWtoA( buffer, langW ); + strcat( buffer, "_" ); + strcpyWtoA( buffer + strlen(buffer), countryW ); + return wine_dbg_sprintf( "%s", buffer ); +} + +/*********************************************************************** + * get_lcid_codepage + * + * Retrieve the ANSI codepage for a given locale. + */ +inline static UINT get_lcid_codepage( LCID lcid ) +{ + UINT ret; + if (!get_locale_info_number( lcid, LOCALE_IDEFAULTANSICODEPAGE, &ret )) + ret = 0; + return ret; +} + +/*********************************************************************** + * find_language_id_proc + */ +static BOOL find_language_id_proc( WORD LangID, LONG_PTR lParam ) +{ + LANG_FIND_DATA *l_data = (LANG_FIND_DATA *)lParam; + LCID lcid = MAKELCID(LangID, SORT_DEFAULT); + WCHAR buf_language[128]; + WCHAR buf_country[128]; + WCHAR buf_en_language[128]; + + if (PRIMARYLANGID(LangID) == LANG_NEUTRAL) + return TRUE; /* continue search */ + + buf_language[0] = 0; + buf_country[0] = 0; + + get_locale_info_str(lcid, LOCALE_SISO639LANGNAME, buf_language, sizeof(buf_language)); + get_locale_info_str(lcid, LOCALE_SISO3166CTRYNAME, buf_country, sizeof(buf_country)); + + if (l_data->lang[0] && !strcmpiW(l_data->lang, buf_language)) + { + if (l_data->country[0]) + { + if (!strcmpiW(l_data->country, buf_country)) + { + l_data->found_lang_id[0] = LangID; + l_data->n_found = 1; + TRACE("Found id %04X for lang %s country %s\n", + LangID, debugstr_w(l_data->lang), debugstr_w(l_data->country)); + return FALSE; /* stop enumeration */ + } + } + else goto found; /* l_data->country not specified */ + } + + /* Just in case, check LOCALE_SENGLANGUAGE too, + * in hope that possible alias name might have that value. + */ + buf_en_language[0] = 0; + get_locale_info_str(lcid, LOCALE_SENGLANGUAGE, buf_en_language, sizeof(buf_en_language)); + + if (l_data->lang[0] && !strcmpiW(l_data->lang, buf_en_language)) goto found; + return TRUE; /* not found, continue search */ + +found: + l_data->found_lang_id[l_data->n_found] = LangID; + strncpyW(l_data->found_country[l_data->n_found], buf_country, 3); + strncpyW(l_data->found_language[l_data->n_found], buf_language, 3); + l_data->n_found++; + TRACE("Found id %04X for lang %s\n", LangID, debugstr_w(l_data->lang)); + return (l_data->n_found < NLS_MAX_LANGUAGES); /* continue search, unless we have enough */ +} + +static NTSTATUS enum_res_lang(HMODULE hmod, BOOL (*lpfun)(WORD, LONG_PTR), LONG_PTR lparam) +{ + int i; + NTSTATUS status = STATUS_INVALID_PARAMETER; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS) + goto done; + info.Type = (ULONG)RT_STRING; + info.Name = (ULONG)LOCALE_ILANGUAGE; + if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS) + goto done; + + status = STATUS_SUCCESS; + et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1); + for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++) + { + if (!lpfun( et[i].u1.s2.Id, lparam )) break; + } +done: + return status; +} + +/*********************************************************************** + * get_language_id + * + * INPUT: + * Lang: a string whose two first chars are the iso name of a language. + * Country: a string whose two first chars are the iso name of country + * Charset: a string defining the chosen charset encoding + * Dialect: a string defining a variation of the locale + * + * all those values are from the standardized format of locale + * name in unix which is: Lang[_Country][.Charset][@Dialect] + * + * RETURNS: + * the numeric code of the language used by Windows + * + * FIXME: Charset and Dialect are not handled + */ +static LANGID get_language_id(LPCSTR Lang, LPCSTR Country, LPCSTR Charset, LPCSTR Dialect) +{ + LANG_FIND_DATA l_data; + LDR_MODULE* mod; + + if (!Lang) + { + l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); + goto END; + } + + l_data.n_found = 0; + strcpynAtoW(l_data.lang, Lang, sizeof(l_data.lang)); + + if (Country) strcpynAtoW(l_data.country, Country, sizeof(l_data.country)); + else l_data.country[0] = 0; + + mod = CONTAINING_RECORD(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList.Flink->Flink, LDR_MODULE, InLoadOrderModuleList); + + enum_res_lang(mod->BaseAddress, find_language_id_proc, (LPARAM)&l_data); + + if (l_data.n_found == 1) goto END; + + if (!l_data.n_found) + { + if (l_data.country[0]) + { + /* retry without country name */ + l_data.country[0] = 0; + enum_res_lang(mod->BaseAddress, find_language_id_proc, (LONG)&l_data); + if (!l_data.n_found) + { + MESSAGE("Warning: Language '%s_%s' was not recognized, defaulting to English.\n", + Lang, Country); + l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); + } + else MESSAGE("Warning: Language '%s_%s' was not recognized, defaulting to '%s'.\n", + Lang, Country, debugstr_lang(l_data.found_lang_id[0]) ); + } + else + { + MESSAGE("Warning: Language '%s' was not recognized, defaulting to English.\n", Lang); + l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); + } + } + else + { + int i; + + if (Country && Country[0]) + MESSAGE("For language '%s_%s' several language ids were found:\n", Lang, Country); + else + MESSAGE("For language '%s' several language ids were found:\n", Lang); + + /* print a list of languages with their description */ + for (i = 0; i < l_data.n_found; i++) + { + WCHAR buffW[128]; + char buffA[128]; + get_locale_info_str( MAKELCID( l_data.found_lang_id[i], SORT_DEFAULT ), + LOCALE_SLANGUAGE, buffW, sizeof(buffW)); + strcpyWtoA( buffA, buffW ); + MESSAGE( " %s (%04X) - %s\n", debugstr_lang(l_data.found_lang_id[i]), + l_data.found_lang_id[i], buffA ); + } + MESSAGE("Defaulting to '%s'. You should specify the exact language you want\n" + "by defining your LANG environment variable like this: LANG=%s\n", + debugstr_lang(l_data.found_lang_id[0]), debugstr_lang(l_data.found_lang_id[0]) ); + } +END: + TRACE("Returning %04X (%s)\n", l_data.found_lang_id[0], debugstr_lang(l_data.found_lang_id[0])); + return l_data.found_lang_id[0]; +} + + +/*********************************************************************** + * charset_cmp (internal) + */ +static int charset_cmp( const void *name, const void *entry ) +{ + const struct charset_entry *charset = (struct charset_entry *)entry; + return strcasecmp( (char *)name, charset->charset_name ); +} + +/*********************************************************************** + * init_default_lcid + */ +static LCID init_default_lcid( UINT *unix_cp ) +{ + char *buf, *lang, *country, *charset, *dialect, *next; + LCID ret = 0; + + if ((lang = getenv( "LC_ALL" )) || + (lang = getenv( "LC_CTYPE" )) || + (lang = getenv( "LANGUAGE" )) || + (lang = getenv( "LC_MESSAGES" )) || + (lang = getenv( "LANG" ))) + { + if (!strcmp(lang, "POSIX") || !strcmp(lang, "C")) goto done; + if ((buf = RtlAllocateHeap( GetProcessHeap(), 0, strlen(lang) + 1 ))) + strcpy( buf, lang ); + + for (lang = buf; lang && !ret; lang = next) + { + next = strchr(lang,':'); if (next) *next++ = '\0'; + dialect = strchr(lang,'@'); if (dialect) *dialect++ = '\0'; + charset = strchr(lang,'.'); if (charset) *charset++ = '\0'; + country = strchr(lang,'_'); if (country) *country++ = '\0'; + + ret = get_language_id(lang, country, charset, dialect); + if (ret && charset) + { + const struct charset_entry *entry; + char charset_name[16]; + size_t i, j; + + /* remove punctuation characters from charset name */ + for (i = j = 0; charset[i] && j < sizeof(charset_name)-1; i++) + if (isalnum(charset[i])) charset_name[j++] = charset[i]; + charset_name[j] = 0; + + entry = bsearch( charset_name, charset_names, + sizeof(charset_names)/sizeof(charset_names[0]), + sizeof(charset_names[0]), charset_cmp ); + if (entry) + { + *unix_cp = entry->codepage; + TRACE("charset %s was mapped to cp %u\n", charset, *unix_cp); + } + else + FIXME("charset %s was not recognized\n", charset); + } + } + + if (!ret) MESSAGE("Warning: language '%s' not recognized, defaulting to English\n", buf); + RtlFreeHeap( GetProcessHeap(), 0, buf ); + } + + done: + if (!ret) ret = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT) ; + return ret; +} + +/****************************************************************************** + * LOCALE_Init + */ +void LOCALE_Init(void) +{ + UINT ansi_cp = 1252, oem_cp = 437, unix_cp = ~0U; + LCID lcid; + + lcid = init_default_lcid( &unix_cp ); + + NtSetDefaultLocale( FALSE, lcid ); + NtSetDefaultLocale( TRUE, lcid ); + + ansi_cp = get_lcid_codepage(lcid); + get_locale_info_number( lcid, LOCALE_IDEFAULTCODEPAGE, &oem_cp ); + if (unix_cp == ~0U) + get_locale_info_number( lcid, LOCALE_IDEFAULTUNIXCODEPAGE, &unix_cp ); + + if (!(ansi_cptable = wine_cp_get_table( ansi_cp ))) + ansi_cptable = wine_cp_get_table( 1252 ); + if (!(oem_cptable = wine_cp_get_table( oem_cp ))) + oem_cptable = wine_cp_get_table( 437 ); + if (unix_cp != CP_UTF8 && !(unix_cptable = wine_cp_get_table( unix_cp ))) + unix_cptable = wine_cp_get_table( 28591 ); + + NlsAnsiCodePage = ansi_cptable->info.codepage; + NtCurrentTeb()->Peb->unix_code_page = unix_cp; + + TRACE( "ansi=%03d oem=%03d unix=%03d\n", + ansi_cptable->info.codepage, oem_cptable->info.codepage, unix_cp ); +} diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll39/Makefile.in dlls/ntdll/Makefile.in --- dlls/ntdll39/Makefile.in 2004-01-01 09:53:17.000000000 +0100 +++ dlls/ntdll/Makefile.in 2004-01-01 09:53:19.000000000 +0100 @@ -18,6 +18,7 @@ large_int.c \ loader.c \ loadorder.c \ + locale.c \ misc.c \ nt.c \ om.c \ @@ -42,6 +43,8 @@ virtual.c \ wcstring.c +RC_SRCS = locale_rc.rc + ASM_SRCS = relay32.s EXTRA_OBJS = $(ASM_SRCS:.s=.o) diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll39/ntdll_misc.h dlls/ntdll/ntdll_misc.h --- dlls/ntdll39/ntdll_misc.h 2004-01-01 09:53:17.000000000 +0100 +++ dlls/ntdll/ntdll_misc.h 2004-01-02 20:44:51.000000000 +0100 @@ -29,6 +29,7 @@ #include "winternl.h" #include "thread.h" #include "wine/server.h" +#include "wine/unicode.h" /* The per-thread signal stack size */ #ifdef __i386__ @@ -46,6 +47,8 @@ const LARGE_INTEGER *timeout ); /* init routines */ +extern BOOL build_initial_environment(void); +extern void LOCALE_Init(void); extern BOOL SIGNAL_Init(void); extern void thread_init(void); @@ -100,4 +103,16 @@ extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, HANDLERPROC proc, LPVOID arg); extern DWORD VIRTUAL_HandleFault(LPCVOID addr); +/* locale */ +extern const union cptable *ansi_cptable; +extern const union cptable *oem_cptable; +extern const union cptable *unix_cptable; /* NULL if UTF8 */ + +static inline int ntdll_mbs2wcs(DWORD flags, const char* src, int srclen, WCHAR* dst, int dstlen) +{ + return (unix_cptable) ? + wine_cp_mbstowcs( unix_cptable, flags, src, srclen, dst, dstlen ) : + wine_utf8_mbstowcs( flags, src, srclen, dst, dstlen ); +} + #endif diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll39/ntdll.spec dlls/ntdll/ntdll.spec --- dlls/ntdll39/ntdll.spec 2004-01-01 09:53:18.000000000 +0100 +++ dlls/ntdll/ntdll.spec 2004-01-01 09:53:20.000000000 +0100 @@ -1075,9 +1075,6 @@ @ cdecl wine_server_release_fd(long long) @ cdecl wine_server_send_fd(long) -# Codepages -@ cdecl __wine_init_codepages(ptr ptr) - # signal handling @ cdecl __wine_set_signal_handler(long ptr) diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll39/rtlstr.c dlls/ntdll/rtlstr.c --- dlls/ntdll39/rtlstr.c 2004-01-01 09:53:17.000000000 +0100 +++ dlls/ntdll/rtlstr.c 2004-01-01 09:53:19.000000000 +0100 @@ -38,25 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); -UINT NlsAnsiCodePage = 0; -BYTE NlsMbCodePageTag = 0; -BYTE NlsMbOemCodePageTag = 0; - -static const union cptable *ansi_table; -static const union cptable *oem_table; - -/************************************************************************** - * __wine_init_codepages (NTDLL.@) - * - * Set the code page once kernel32 is loaded. Should be done differently. - */ -void __wine_init_codepages( const union cptable *ansi, const union cptable *oem ) -{ - ansi_table = ansi; - oem_table = oem; - NlsAnsiCodePage = ansi->info.codepage; -} - /************************************************************************** * RtlInitAnsiString (NTDLL.@) @@ -706,7 +690,7 @@ LPCSTR src, DWORD srclen ) { - int ret = wine_cp_mbstowcs( ansi_table, 0, src, srclen, dst, dstlen/sizeof(WCHAR) ); + int ret = wine_cp_mbstowcs( ansi_cptable, 0, src, srclen, dst, dstlen/sizeof(WCHAR) ); if (reslen) *reslen = (ret >= 0) ? ret*sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */ return STATUS_SUCCESS; @@ -719,7 +703,7 @@ NTSTATUS WINAPI RtlOemToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen, LPCSTR src, DWORD srclen ) { - int ret = wine_cp_mbstowcs( oem_table, 0, src, srclen, dst, dstlen/sizeof(WCHAR) ); + int ret = wine_cp_mbstowcs( oem_cptable, 0, src, srclen, dst, dstlen/sizeof(WCHAR) ); if (reslen) *reslen = (ret >= 0) ? ret*sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */ return STATUS_SUCCESS; @@ -732,7 +716,7 @@ NTSTATUS WINAPI RtlUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen, LPCWSTR src, DWORD srclen ) { - int ret = wine_cp_wcstombs( ansi_table, 0, src, srclen / sizeof(WCHAR), + int ret = wine_cp_wcstombs( ansi_cptable, 0, src, srclen / sizeof(WCHAR), dst, dstlen, NULL, NULL ); if (reslen) *reslen = (ret >= 0) ? ret : dstlen; /* overflow -> we filled up to dstlen */ @@ -746,7 +730,7 @@ NTSTATUS WINAPI RtlUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen, LPCWSTR src, DWORD srclen ) { - int ret = wine_cp_wcstombs( oem_table, 0, src, srclen / sizeof(WCHAR), + int ret = wine_cp_wcstombs( oem_cptable, 0, src, srclen / sizeof(WCHAR), dst, dstlen, NULL, NULL ); if (reslen) *reslen = (ret >= 0) ? ret : dstlen; /* overflow -> we filled up to dstlen */ @@ -1070,7 +1054,7 @@ */ UINT WINAPI RtlOemStringToUnicodeSize( const STRING *str ) { - int ret = wine_cp_mbstowcs( oem_table, 0, str->Buffer, str->Length, NULL, 0 ); + int ret = wine_cp_mbstowcs( oem_cptable, 0, str->Buffer, str->Length, NULL, 0 ); return (ret + 1) * sizeof(WCHAR); } @@ -1112,7 +1096,7 @@ */ NTSTATUS WINAPI RtlMultiByteToUnicodeSize( DWORD *size, LPCSTR str, UINT len ) { - *size = wine_cp_mbstowcs( ansi_table, 0, str, len, NULL, 0 ) * sizeof(WCHAR); + *size = wine_cp_mbstowcs( ansi_cptable, 0, str, len, NULL, 0 ) * sizeof(WCHAR); return STATUS_SUCCESS; } @@ -1133,7 +1117,7 @@ */ NTSTATUS WINAPI RtlUnicodeToMultiByteSize( PULONG size, LPCWSTR str, ULONG len ) { - *size = wine_cp_wcstombs( ansi_table, 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL ); + *size = wine_cp_wcstombs( ansi_cptable, 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL ); return STATUS_SUCCESS; } @@ -1174,7 +1158,7 @@ */ DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str ) { - return wine_cp_wcstombs( oem_table, 0, str->Buffer, str->Length / sizeof(WCHAR), + return wine_cp_wcstombs( oem_cptable, 0, str->Buffer, str->Length / sizeof(WCHAR), NULL, 0, NULL, NULL ) + 1; } diff -u -N -r -x '*~' -x '.#*' -x CVS include39/winternl.h include/winternl.h --- include39/winternl.h 2004-01-01 09:54:11.000000000 +0100 +++ include/winternl.h 2004-01-01 09:54:14.000000000 +0100 @@ -158,7 +158,8 @@ PRTL_BITMAP TlsBitmap; /* 40 */ ULONG TlsBitmapBits[2]; /* 44 */ BYTE __pad_4c[156]; /* 4c */ - PVOID Reserved3[59]; /* e8 */ + PVOID Reserved3[58]; /* e8 */ + unsigned int unix_code_page; /* 1d0 wine only */ ULONG SessionId; /* 1d4 */ } PEB, *PPEB;