Index: dll/win32/kernel32/winnls/string/lang.c =================================================================== --- dll/win32/kernel32/winnls/string/lang.c (revision 74411) +++ dll/win32/kernel32/winnls/string/lang.c (working copy) @@ -33,7 +33,7 @@ extern int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen); extern int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen); extern int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2); -extern DWORD GetLocalisedText(DWORD dwResId, WCHAR *lpszDest, DWORD dwDestSize); +extern UINT GetLocalisedText(IN UINT uID, IN LPWSTR lpszDest, IN UINT cchDest); #define NLSRC_OFFSET 5000 /* FIXME */ extern HMODULE kernel32_handle; @@ -3093,33 +3093,16 @@ static int NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData) { - LPWSTR szBuffer; - DWORD dwSize; - /* FIXME: move *.nls resources out of kernel32 into locale.nls */ Location += NLSRC_OFFSET; Location &= 0xFFFF; - if(cchData == 0) + if (cchData == 0) return GetLocalisedText(Location, NULL, 0); - dwSize = cchData * sizeof(WCHAR); - szBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize); - - if (!szBuffer) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - if(GetLocalisedText(Location, szBuffer, dwSize)) - { - memcpy(szFriendlyName, szBuffer, dwSize); - HeapFree(GetProcessHeap(), 0, szBuffer); + if (GetLocalisedText(Location, szFriendlyName, (UINT)cchData)) return strlenW(szFriendlyName) + 1; - } - HeapFree(GetProcessHeap(), 0, szBuffer); return 0; } Index: dll/win32/kernel32/winnls/string/nls.c =================================================================== --- dll/win32/kernel32/winnls/string/nls.c (revision 74411) +++ dll/win32/kernel32/winnls/string/nls.c (working copy) @@ -1714,18 +1714,30 @@ return dest_index; } -DWORD -GetLocalisedText(DWORD dwResId, WCHAR *lpszDest, DWORD dwDestSize) +/* + * A function similar to LoadStringW, but adapted for usage by GetCPInfoExW + * and GetGeoInfoW. It uses the current user localization, otherwise falls back + * to English (US). Contrary to LoadStringW which always saves the loaded string + * into the user-given buffer, truncating the string if needed, this function + * returns instead an ERROR_INSUFFICIENT_BUFFER error code if the user buffer + * is not large enough. + */ +UINT +GetLocalisedText( + IN UINT uID, + IN LPWSTR lpszDest, + IN UINT cchDest) { HRSRC hrsrc; + HGLOBAL hmem; LCID lcid; LANGID langId; - DWORD dwId; + const WCHAR *p; + UINT i; - if (dwResId == 37) - dwId = dwResId * 100; - else - dwId = dwResId; + /* See HACK in winnls/lang/xx-XX.rc files */ + if (uID == 37) + uID = uID * 100; lcid = GetUserDefaultLCID(); lcid = ConvertDefaultLocale(lcid); @@ -1737,53 +1749,60 @@ hrsrc = FindResourceExW(hCurrentModule, (LPWSTR)RT_STRING, - MAKEINTRESOURCEW((dwId >> 4) + 1), + MAKEINTRESOURCEW((uID >> 4) + 1), langId); - /* english fallback */ - if(!hrsrc) + /* English fallback */ + if (!hrsrc) { hrsrc = FindResourceExW(hCurrentModule, - (LPWSTR)RT_STRING, - MAKEINTRESOURCEW((dwId >> 4) + 1), - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); + (LPWSTR)RT_STRING, + MAKEINTRESOURCEW((uID >> 4) + 1), + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); } - if (hrsrc) - { - HGLOBAL hmem = LoadResource(hCurrentModule, hrsrc); + if (!hrsrc) + goto NotFound; - if (hmem) - { - const WCHAR *p; - unsigned int i; - unsigned int len; + hmem = LoadResource(hCurrentModule, hrsrc); + if (!hmem) + goto NotFound; - p = LockResource(hmem); + p = LockResource(hmem); - for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1; + for (i = 0; i < (uID & 0x0F); i++) + p += *p + 1; - if(dwDestSize == 0) - return *p + 1; + /* Needed for GetGeoInfo(): return the needed string size including the NULL terminator */ + if (cchDest == 0) + return *p + 1; + /* Needed for GetGeoInfo(): bail out if the user buffer is not large enough */ + if (*p + 1 > cchDest) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } - len = *p * sizeof(WCHAR); - - if(len + sizeof(WCHAR) > dwDestSize) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - memcpy(lpszDest, p + 1, len); - lpszDest[*p] = '\0'; - - return TRUE; - } + i = *p; + if (i > 0) + { + memcpy(lpszDest, p + 1, i * sizeof(WCHAR)); + lpszDest[i] = L'\0'; + return i; } +#if 0 + else + { + if (cchDest >= 1) + lpszDest[0] = L'\0'; + /* Fall-back */ + } +#endif - DPRINT1("Resource not found: dwResId = %lu\n", dwResId); +NotFound: + DPRINT1("Resource not found: uID = %lu\n", uID); SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + return 0; } /* @@ -1849,7 +1868,7 @@ DWORD dwFlags, LPCPINFOEXW lpCPInfoEx) { - if (!GetCPInfo(CodePage, (LPCPINFO) lpCPInfoEx)) + if (!GetCPInfo(CodePage, (LPCPINFO)lpCPInfoEx)) return FALSE; switch(CodePage) @@ -1858,7 +1877,9 @@ { lpCPInfoEx->CodePage = CP_UTF7; lpCPInfoEx->UnicodeDefaultChar = 0x3f; - return GetLocalisedText((DWORD)CodePage, lpCPInfoEx->CodePageName, sizeof(lpCPInfoEx->CodePageName)) != 0; + return GetLocalisedText(lpCPInfoEx->CodePage, + lpCPInfoEx->CodePageName, + ARRAYSIZE(lpCPInfoEx->CodePageName)) != 0; } break; @@ -1866,7 +1887,9 @@ { lpCPInfoEx->CodePage = CP_UTF8; lpCPInfoEx->UnicodeDefaultChar = 0x3f; - return GetLocalisedText((DWORD)CodePage, lpCPInfoEx->CodePageName, sizeof(lpCPInfoEx->CodePageName)) != 0; + return GetLocalisedText(lpCPInfoEx->CodePage, + lpCPInfoEx->CodePageName, + ARRAYSIZE(lpCPInfoEx->CodePageName)) != 0; } default: @@ -1876,7 +1899,7 @@ CodePageEntry = IntGetCodePageEntry(CodePage); if (CodePageEntry == NULL) { - DPRINT1("Could not get CodePage Entry! CodePageEntry = 0\n"); + DPRINT1("Could not get CodePage Entry! CodePageEntry = NULL\n"); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -1883,7 +1906,9 @@ lpCPInfoEx->CodePage = CodePageEntry->CodePageTable.CodePage; lpCPInfoEx->UnicodeDefaultChar = CodePageEntry->CodePageTable.UniDefaultChar; - return GetLocalisedText(CodePageEntry->CodePageTable.CodePage, lpCPInfoEx->CodePageName, sizeof(lpCPInfoEx->CodePageName)) != 0; + return GetLocalisedText(lpCPInfoEx->CodePage, + lpCPInfoEx->CodePageName, + ARRAYSIZE(lpCPInfoEx->CodePageName)) != 0; } break; }