| // Copyright 2011 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include"base/file_version_info_win.h" |
| |
| #include<windows.h> |
| |
| #include<stddef.h> |
| |
| #include<utility> |
| |
| #include"base/check.h" |
| #include"base/files/file_path.h" |
| #include"base/memory/ptr_util.h" |
| #include"base/strings/string_util.h" |
| #include"base/threading/scoped_blocking_call.h" |
| #include"base/win/resource_util.h" |
| |
| namespace{ |
| |
| structLanguageAndCodePage{ |
| WORD language; |
| WORD code_page; |
| }; |
| |
| // Returns the \VarFileInfo\Translation value extracted from the |
| // VS_VERSION_INFO resource in |data|. |
| LanguageAndCodePage*GetTranslate(constvoid* data){ |
| staticconstexprwchar_t kTranslation[]= L"\\VarFileInfo\\Translation"; |
| LPVOID translate=nullptr; |
| UINT dummy_size; |
| if(::VerQueryValue(data, kTranslation,&translate,&dummy_size)){ |
| returnstatic_cast<LanguageAndCodePage*>(translate); |
| } |
| returnnullptr; |
| } |
| |
| const VS_FIXEDFILEINFO&GetVsFixedFileInfo(constvoid* data){ |
| staticconstexprwchar_t kRoot[]= L"\\"; |
| LPVOID fixed_file_info=nullptr; |
| UINT dummy_size; |
| CHECK(::VerQueryValue(data, kRoot,&fixed_file_info,&dummy_size)); |
| return*static_cast<VS_FIXEDFILEINFO*>(fixed_file_info); |
| } |
| |
| }// namespace |
| |
| FileVersionInfoWin::~FileVersionInfoWin()=default; |
| |
| // static |
| std::unique_ptr<FileVersionInfo> |
| FileVersionInfo::CreateFileVersionInfoForModule(HMODULE module){ |
| void* data; |
| size_t version_info_length; |
| constbool has_version_resource= base::win::GetResourceFromModule( |
| module, VS_VERSION_INFO, RT_VERSION,&data,&version_info_length); |
| if(!has_version_resource){ |
| returnnullptr; |
| } |
| |
| constLanguageAndCodePage* translate=GetTranslate(data); |
| if(!translate){ |
| returnnullptr; |
| } |
| |
| return base::WrapUnique( |
| newFileVersionInfoWin(data, translate->language, translate->code_page)); |
| } |
| |
| // static |
| std::unique_ptr<FileVersionInfo>FileVersionInfo::CreateFileVersionInfo( |
| const base::FilePath& file_path){ |
| returnFileVersionInfoWin::CreateFileVersionInfoWin(file_path); |
| } |
| |
| // static |
| std::unique_ptr<FileVersionInfoWin> |
| FileVersionInfoWin::CreateFileVersionInfoWin(const base::FilePath& file_path){ |
| base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, |
| base::BlockingType::MAY_BLOCK); |
| |
| DWORD dummy; |
| constwchar_t* path= file_path.value().c_str(); |
| const DWORD length=::GetFileVersionInfoSize(path,&dummy); |
| if(length==0){ |
| returnnullptr; |
| } |
| |
| std::vector<uint8_t> data(length,0); |
| |
| if(!::GetFileVersionInfo(path, dummy, length, data.data())){ |
| returnnullptr; |
| } |
| |
| constLanguageAndCodePage* translate=GetTranslate(data.data()); |
| if(!translate){ |
| returnnullptr; |
| } |
| |
| return base::WrapUnique(newFileVersionInfoWin( |
| std::move(data), translate->language, translate->code_page)); |
| } |
| |
| std::u16stringFileVersionInfoWin::company_name(){ |
| returnGetStringValue(u"CompanyName"); |
| } |
| |
| std::u16stringFileVersionInfoWin::company_short_name(){ |
| returnGetStringValue(u"CompanyShortName"); |
| } |
| |
| std::u16stringFileVersionInfoWin::internal_name(){ |
| returnGetStringValue(u"InternalName"); |
| } |
| |
| std::u16stringFileVersionInfoWin::product_name(){ |
| returnGetStringValue(u"ProductName"); |
| } |
| |
| std::u16stringFileVersionInfoWin::product_short_name(){ |
| returnGetStringValue(u"ProductShortName"); |
| } |
| |
| std::u16stringFileVersionInfoWin::product_version(){ |
| returnGetStringValue(u"ProductVersion"); |
| } |
| |
| std::u16stringFileVersionInfoWin::file_description(){ |
| returnGetStringValue(u"FileDescription"); |
| } |
| |
| std::u16stringFileVersionInfoWin::file_version(){ |
| returnGetStringValue(u"FileVersion"); |
| } |
| |
| std::u16stringFileVersionInfoWin::original_filename(){ |
| returnGetStringValue(u"OriginalFilename"); |
| } |
| |
| std::u16stringFileVersionInfoWin::special_build(){ |
| returnGetStringValue(u"SpecialBuild"); |
| } |
| |
| boolFileVersionInfoWin::GetValue(constchar16_t* name, |
| std::u16string* value)const{ |
| conststructLanguageAndCodePage lang_codepages[]={ |
| // Use the language and codepage from the DLL. |
| {language_, code_page_}, |
| // Use the default language and codepage from the DLL. |
| {::GetUserDefaultLangID(), code_page_}, |
| // Use the language from the DLL and Latin codepage (most common). |
| {language_,1252}, |
| // Use the default language and Latin codepage (most common). |
| {::GetUserDefaultLangID(),1252}, |
| }; |
| |
| for(constauto& lang_codepage: lang_codepages){ |
| wchar_t sub_block[MAX_PATH]; |
| _snwprintf_s(sub_block, MAX_PATH, MAX_PATH, |
| L"\\StringFileInfo\\%04x%04x\\%ls", lang_codepage.language, |
| lang_codepage.code_page, base::as_wcstr(name)); |
| LPVOID value_ptr=nullptr; |
| uint32_t size; |
| BOOL r=::VerQueryValue(data_, sub_block,&value_ptr,&size); |
| if(r&& value_ptr&& size){ |
| value->assign(static_cast<char16_t*>(value_ptr), size-1); |
| returntrue; |
| } |
| } |
| returnfalse; |
| } |
| |
| std::u16stringFileVersionInfoWin::GetStringValue(constchar16_t* name)const{ |
| std::u16string str; |
| GetValue(name,&str); |
| return str; |
| } |
| |
| base::VersionFileVersionInfoWin::GetFileVersion()const{ |
| return base::Version({HIWORD(fixed_file_info_->dwFileVersionMS), |
| LOWORD(fixed_file_info_->dwFileVersionMS), |
| HIWORD(fixed_file_info_->dwFileVersionLS), |
| LOWORD(fixed_file_info_->dwFileVersionLS)}); |
| } |
| |
| FileVersionInfoWin::FileVersionInfoWin(std::vector<uint8_t>&& data, |
| WORD language, |
| WORD code_page) |
| : owned_data_(std::move(data)), |
| data_(owned_data_.data()), |
| language_(language), |
| code_page_(code_page), |
| fixed_file_info_(GetVsFixedFileInfo(data_)){ |
| DCHECK(!owned_data_.empty()); |
| } |
| |
| FileVersionInfoWin::FileVersionInfoWin(void* data, |
| WORD language, |
| WORD code_page) |
| : data_(data), |
| language_(language), |
| code_page_(code_page), |
| fixed_file_info_(GetVsFixedFileInfo(data)){ |
| DCHECK(data_); |
| } |