1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/file_version_info_win.h" 6 7 #include <windows.h> 8 9 #include "base/file_version_info.h" 10 #include "base/files/file_path.h" 11 #include "base/logging.h" 12 #include "base/path_service.h" 13 #include "base/threading/thread_restrictions.h" 14 15 using base::FilePath; 16 17 FileVersionInfoWin::FileVersionInfoWin(void* data, int language, int code_page) 18 : language_(language), code_page_(code_page) { 19 base::ThreadRestrictions::AssertIOAllowed(); 20 data_.reset((char*) data); 21 fixed_file_info_ = NULL; 22 UINT size; 23 ::VerQueryValue(data_.get(), L"\\", (LPVOID*)&fixed_file_info_, &size); 24 } 25 26 FileVersionInfoWin::~FileVersionInfoWin() { 27 DCHECK(data_.get()); 28 } 29 30 typedef struct { 31 WORD language; 32 WORD code_page; 33 } LanguageAndCodePage; 34 35 // static 36 FileVersionInfo* FileVersionInfo::CreateFileVersionInfoForModule( 37 HMODULE module) { 38 // Note that the use of MAX_PATH is basically in line with what we do for 39 // all registered paths (PathProviderWin). 40 wchar_t system_buffer[MAX_PATH]; 41 system_buffer[0] = 0; 42 if (!GetModuleFileName(module, system_buffer, MAX_PATH)) 43 return NULL; 44 45 FilePath app_path(system_buffer); 46 return CreateFileVersionInfo(app_path); 47 } 48 49 // static 50 FileVersionInfo* FileVersionInfo::CreateFileVersionInfo( 51 const FilePath& file_path) { 52 base::ThreadRestrictions::AssertIOAllowed(); 53 54 DWORD dummy; 55 const wchar_t* path = file_path.value().c_str(); 56 DWORD length = ::GetFileVersionInfoSize(path, &dummy); 57 if (length == 0) 58 return NULL; 59 60 void* data = calloc(length, 1); 61 if (!data) 62 return NULL; 63 64 if (!::GetFileVersionInfo(path, dummy, length, data)) { 65 free(data); 66 return NULL; 67 } 68 69 LanguageAndCodePage* translate = NULL; 70 uint32 page_count; 71 BOOL query_result = VerQueryValue(data, L"\\VarFileInfo\\Translation", 72 (void**) &translate, &page_count); 73 74 if (query_result && translate) { 75 return new FileVersionInfoWin(data, translate->language, 76 translate->code_page); 77 78 } else { 79 free(data); 80 return NULL; 81 } 82 } 83 84 base::string16 FileVersionInfoWin::company_name() { 85 return GetStringValue(L"CompanyName"); 86 } 87 88 base::string16 FileVersionInfoWin::company_short_name() { 89 return GetStringValue(L"CompanyShortName"); 90 } 91 92 base::string16 FileVersionInfoWin::internal_name() { 93 return GetStringValue(L"InternalName"); 94 } 95 96 base::string16 FileVersionInfoWin::product_name() { 97 return GetStringValue(L"ProductName"); 98 } 99 100 base::string16 FileVersionInfoWin::product_short_name() { 101 return GetStringValue(L"ProductShortName"); 102 } 103 104 base::string16 FileVersionInfoWin::comments() { 105 return GetStringValue(L"Comments"); 106 } 107 108 base::string16 FileVersionInfoWin::legal_copyright() { 109 return GetStringValue(L"LegalCopyright"); 110 } 111 112 base::string16 FileVersionInfoWin::product_version() { 113 return GetStringValue(L"ProductVersion"); 114 } 115 116 base::string16 FileVersionInfoWin::file_description() { 117 return GetStringValue(L"FileDescription"); 118 } 119 120 base::string16 FileVersionInfoWin::legal_trademarks() { 121 return GetStringValue(L"LegalTrademarks"); 122 } 123 124 base::string16 FileVersionInfoWin::private_build() { 125 return GetStringValue(L"PrivateBuild"); 126 } 127 128 base::string16 FileVersionInfoWin::file_version() { 129 return GetStringValue(L"FileVersion"); 130 } 131 132 base::string16 FileVersionInfoWin::original_filename() { 133 return GetStringValue(L"OriginalFilename"); 134 } 135 136 base::string16 FileVersionInfoWin::special_build() { 137 return GetStringValue(L"SpecialBuild"); 138 } 139 140 base::string16 FileVersionInfoWin::last_change() { 141 return GetStringValue(L"LastChange"); 142 } 143 144 bool FileVersionInfoWin::is_official_build() { 145 return (GetStringValue(L"Official Build").compare(L"1") == 0); 146 } 147 148 bool FileVersionInfoWin::GetValue(const wchar_t* name, 149 std::wstring* value_str) { 150 WORD lang_codepage[8]; 151 int i = 0; 152 // Use the language and codepage from the DLL. 153 lang_codepage[i++] = language_; 154 lang_codepage[i++] = code_page_; 155 // Use the default language and codepage from the DLL. 156 lang_codepage[i++] = ::GetUserDefaultLangID(); 157 lang_codepage[i++] = code_page_; 158 // Use the language from the DLL and Latin codepage (most common). 159 lang_codepage[i++] = language_; 160 lang_codepage[i++] = 1252; 161 // Use the default language and Latin codepage (most common). 162 lang_codepage[i++] = ::GetUserDefaultLangID(); 163 lang_codepage[i++] = 1252; 164 165 i = 0; 166 while (i < arraysize(lang_codepage)) { 167 wchar_t sub_block[MAX_PATH]; 168 WORD language = lang_codepage[i++]; 169 WORD code_page = lang_codepage[i++]; 170 _snwprintf_s(sub_block, MAX_PATH, MAX_PATH, 171 L"\\StringFileInfo\\%04x%04x\\%ls", language, code_page, name); 172 LPVOID value = NULL; 173 uint32 size; 174 BOOL r = ::VerQueryValue(data_.get(), sub_block, &value, &size); 175 if (r && value) { 176 value_str->assign(static_cast<wchar_t*>(value)); 177 return true; 178 } 179 } 180 return false; 181 } 182 183 std::wstring FileVersionInfoWin::GetStringValue(const wchar_t* name) { 184 std::wstring str; 185 if (GetValue(name, &str)) 186 return str; 187 else 188 return L""; 189 } 190