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