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