// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome_frame/simple_resource_loader.h" #include #include #include "base/base_paths.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/path_service.h" #include "base/i18n/rtl.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/win/windows_version.h" const wchar_t kLocalesDirName[] = L"Locales"; HINSTANCE SimpleResourceLoader::locale_dll_handle_; SimpleResourceLoader::SimpleResourceLoader() { // Find and load the resource DLL. std::wstring language; std::wstring region; GetSystemLocale(&language, ®ion); FilePath locale_dll_path; if (GetLocaleFilePath(language, region, &locale_dll_path)) { DCHECK(locale_dll_handle_ == NULL) << "Locale DLL is already loaded!"; locale_dll_handle_ = LoadLocaleDll(locale_dll_path); DCHECK(locale_dll_handle_ != NULL) << "Failed to load locale dll!"; } } SimpleResourceLoader::~SimpleResourceLoader() {} void SimpleResourceLoader::GetSystemLocale(std::wstring* language, std::wstring* region) { DCHECK(language); DCHECK(region); std::string icu_language, icu_region; base::i18n::GetLanguageAndRegionFromOS(&icu_language, &icu_region); if (!icu_language.empty()) { *language = ASCIIToWide(icu_language); } if (!icu_region.empty()) { *region = ASCIIToWide(icu_region); } } bool SimpleResourceLoader::GetLocaleFilePath(const std::wstring& language, const std::wstring& region, FilePath* file_path) { DCHECK(file_path); FilePath module_path; PathService::Get(base::DIR_MODULE, &module_path); FilePath locales_path = module_path.Append(kLocalesDirName); // We may be residing in the "locales" directory's parent, or we might be // in a sibling directory. Move up one and look for Locales again in the // latter case. if (!file_util::DirectoryExists(locales_path)) { locales_path = module_path.DirName(); locales_path = locales_path.Append(kLocalesDirName); } bool found_dll = false; if (file_util::DirectoryExists(locales_path)) { std::wstring dll_name(language); FilePath look_path; // First look for the [language]-[region].DLL. if (!region.empty()) { dll_name += L"-"; dll_name += region; dll_name += L".dll"; look_path = locales_path.Append(dll_name); if (file_util::PathExists(look_path)) { *file_path = look_path; found_dll = true; } } // Next look for just [language].DLL. if (!found_dll) { dll_name = language; dll_name += L".dll"; look_path = locales_path.Append(dll_name); if (file_util::PathExists(look_path)) { *file_path = look_path; found_dll = true; } } // Finally, try defaulting to en-US.dll. if (!found_dll) { look_path = locales_path.Append(L"en-US.dll"); if (file_util::PathExists(look_path)) { *file_path = look_path; found_dll = true; } } } else { NOTREACHED() << "Could not locate locales DLL directory."; } return found_dll; } HINSTANCE SimpleResourceLoader::LoadLocaleDll(const FilePath& dll_path) { DWORD load_flags = 0; if (base::win::GetVersion() >= base::win::VERSION_VISTA) { load_flags = LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE; } else { load_flags = DONT_RESOLVE_DLL_REFERENCES; } // The dll should only have resources, not executable code. HINSTANCE locale_dll_handle = LoadLibraryEx(dll_path.value().c_str(), NULL, load_flags); DCHECK(locale_dll_handle != NULL) << "unable to load generated resources: " << GetLastError(); return locale_dll_handle; } std::wstring SimpleResourceLoader::GetLocalizedResource(int message_id) { if (!locale_dll_handle_) { DLOG(ERROR) << "locale resources are not loaded"; return std::wstring(); } DCHECK(IS_INTRESOURCE(message_id)); const ATLSTRINGRESOURCEIMAGE* image = AtlGetStringResourceImage( locale_dll_handle_, message_id); if (!image) { // Fall back on the current module (shouldn't be any strings here except // in unittests). image = AtlGetStringResourceImage(_AtlBaseModule.GetModuleInstance(), message_id); if (!image) { NOTREACHED() << "unable to find resource: " << message_id; return std::wstring(); } } return std::wstring(image->achString, image->nLength); } // static std::wstring SimpleResourceLoader::Get(int message_id) { SimpleResourceLoader* loader = SimpleResourceLoader::instance(); return loader->GetLocalizedResource(message_id); } HINSTANCE SimpleResourceLoader::GetResourceModuleHandle() { return locale_dll_handle_; }