ファイルバージョン情報の取得 (CFileVersionInfo)

(2003.09.18)
#pragma once
 
// WAC.com Class Liblary for Visual C++
// Copyright (C) WAC.com Inc. All rights reserved.
//
// This file is a part of the WAC.com Class Liblary.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
 
// '06.09.12 : UNICODE対応 (sha)
 
#include <WinVer.h>
#pragma comment(lib, "Version.lib")
 
#include <vector>
 
 
////////////////////////////////////////////////////////////////////////////////
// 言語&コードページ
 
struct LANGANDCODEPAGE
{
    WORD wLanguage;
    WORD wCodePage;
};
 
class CLangAndCodePage : public LANGANDCODEPAGE
{
public:
    CLangAndCodePage()
    {
        wLanguage = 0;
        wCodePage = 0;
    }
    CLangAndCodePage(const LANGANDCODEPAGE& wLangAndCodePageSrc)
    {
        wLanguage = wLangAndCodePageSrc.wLanguage;
        wCodePage = wLangAndCodePageSrc.wCodePage;
    }
    CLangAndCodePage(WORD wLanguageSrc, WORD wCodePageSrc)
    {
        wLanguage = wLanguageSrc;
        wCodePage = wCodePageSrc;
    }
};
 
 
////////////////////////////////////////////////////////////////////////////////
// CFileVersionInfo
 
class CFileVersionInfo
{
protected:
    typedef CFileVersionInfo                    thisClass;
 
public:
    CFileVersionInfo()
    {
    }
    CFileVersionInfo(LPCTSTR szFileName, CLangAndCodePage LangAndCodePage)
    {
        HRESULT hr = S_OK;
 
        hr = this->Load(szFileName, LangAndCodePage);
        if (FAILED(hr))
        {
            // 無視する。。
        }
    }
    CFileVersionInfo(LPCTSTR szFileName)
    {
        HRESULT hr = S_OK;
 
        hr = this->Load(szFileName);
        if (FAILED(hr))
        {
            // 無視する。。
        }
    }
    virtual ~CFileVersionInfo()
    {
    }
 
public:
    CString GetComments()
    {
        return m_strComments;
    }
    CString GetCompanyName()
    {
        return m_strCompanyName;
    }
    CString GetFileDescription()
    {
        return m_strFileDescription; 
    }
    CString GetFileVersion()
    {
        return m_strFileVersion; 
    }
    CString GetInternalName() 
    {
        return m_strInternalName; 
    }
    CString GetLegalCopyright()
    {
        return m_strLegalCopyright;
    }
    CString GetLegalTrademarks()
    {
        return m_strLegalTrademarks;
    }
    CString GetOriginalTrademarks()
    {
        return m_strOriginalFilename;
    }
    CString GetPrivateBuild()
    {
        return m_strPrivateBuild;
    }
    CString GetProductName()
    {
        return m_strProductName;
    }
    CString GetProductVersion()
    {
        return m_strProductVersion;
    }
    CString GetSpecialBuild()
    {
        return m_strSpecialBuild;
    }
 
public:
    HRESULT Load(LPCTSTR szFileName, CLangAndCodePage LangAndCodePage)
    {
        if (szFileName == NULL)
        {
            return E_FAIL;
        }
 
        HRESULT hr = S_OK;
 
        LPVOID lpBlock = thisClass::_AllocFileVersionInfoBlock(szFileName);
        if (lpBlock == NULL)
        {
            return E_OUTOFMEMORY;
        }
 
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("Comments"),            m_strComments);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("CompanyName"),        m_strCompanyName);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("FileDescription"),    m_strFileDescription);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("FileVersion"),        m_strFileVersion);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("InternalName"),        m_strInternalName);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("LegalCopyright"),    m_strLegalCopyright);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("LegalTrademarks"),    m_strLegalTrademarks);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("OriginalFilename"),    m_strOriginalFilename);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("PrivateBuild"),        m_strPrivateBuild);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("ProductName"),        m_strProductName);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("ProductVersion"),    m_strProductVersion);
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, _T("SpecialBuild"),        m_strSpecialBuild);
 
        thisClass::_FreeFileVersionInfoBlock(lpBlock);
 
        return S_OK;
    }
    HRESULT Load(LPCTSTR szFileName)
    {
        if (szFileName == NULL)
        {
            return E_FAIL;
        }
 
        HRESULT hr = S_OK;
 
        std::vector<CLangAndCodePage> LangAndCodePages;
        hr = thisClass::EnumLangAndCodePages(szFileName, LangAndCodePages);
        if (FAILED(hr))
        {
            return hr;
        }
 
        return this->Load(szFileName, LangAndCodePages[0]);
    }
 
public:
    static HRESULT EnumLangAndCodePages(LPCTSTR szFileName, std::vector<CLangAndCodePage>& LangAndCodePages)
    {
        if (szFileName == NULL)
        {
            return E_FAIL;
        }
 
        HRESULT hr = S_OK;
 
        LPVOID lpBlock = _AllocFileVersionInfoBlock(szFileName);
        if (lpBlock == NULL)
        {
//            return E_OUTOFMEMORY;
            return E_FAIL;
        }
 
        hr = InternalEnumLangAndCodePages(lpBlock, LangAndCodePages);
 
        _FreeFileVersionInfoBlock(lpBlock);
 
        return hr;
    }
    static HRESULT GetFileInfo(LPCTSTR szFileName, VS_FIXEDFILEINFO* pFileInfo)
    {
        if (szFileName == NULL)
        {
            return E_FAIL;
        }
 
        if (pFileInfo == NULL)
        {
            return E_FAIL;
        }
 
        HRESULT hr = S_OK;
 
        LPVOID lpBlock = thisClass::_AllocFileVersionInfoBlock(szFileName);
        if (lpBlock == NULL)
        {
//            return E_OUTOFMEMORY;
            return E_FAIL;
        }
 
 
        hr = thisClass::InternalGetFileInfo(lpBlock, pFileInfo);
 
        thisClass::_FreeFileVersionInfoBlock(lpBlock);
 
        return hr;
    }
    static HRESULT GetStringFileInfo(LPCTSTR szFileName, CLangAndCodePage LangAndCodePage, LPCTSTR szName, CString& strValue)
    {
        if (szFileName == NULL)
        {
            return E_FAIL;
        }
 
        HRESULT hr = S_OK;
 
        LPVOID lpBlock = thisClass::_AllocFileVersionInfoBlock(szFileName);
        if (lpBlock == NULL)
        {
//            return E_OUTOFMEMORY;
            return E_FAIL;
        }
 
 
        hr = thisClass::InternalGetStringFileInfo(lpBlock, LangAndCodePage, szName, strValue);
 
        thisClass::_FreeFileVersionInfoBlock(lpBlock);
 
        return hr;
    }
 
protected:
    // ファイルバージョン情報ブロック
    // http://support.microsoft.com/default.aspx?scid=kb;ja;826496
    static LPVOID _AllocFileVersionInfoBlock(LPCTSTR szFileName)
    {
        if (szFileName == NULL)
        {
            return NULL;
        }
 
        DWORD dwHandle = 0;
        DWORD dwBlockSize = ::GetFileVersionInfoSize((LPTSTR)szFileName, &dwHandle);
        if (dwBlockSize <= 0)
        {
            return NULL;
        }
 
        LPVOID lpBlock = ::CoTaskMemAlloc(dwBlockSize);
        if (lpBlock == NULL)
        {
            return NULL;
        }
 
        BOOL br = ::GetFileVersionInfo((LPTSTR)szFileName, dwHandle, dwBlockSize, lpBlock);
        if (br == FALSE)
        {
            ::CoTaskMemFree(lpBlock);
            return NULL;
        }
 
        return lpBlock;
    }
    static void _FreeFileVersionInfoBlock(LPVOID lpBlock)
    {
        ::CoTaskMemFree(lpBlock);
    }
 
protected:
    static HRESULT InternalEnumLangAndCodePages(const LPVOID lpBlock, std::vector<CLangAndCodePage>& LangAndCodePages)
    {
        if (lpBlock == NULL)
        {
            return E_FAIL;
        }
 
        // クリアする
        LangAndCodePages.clear();
 
        CString strSubBlock = _T("\\VarFileInfo\\Translation");
        LPVOID lpBuffer = NULL;
        UINT uLen = 0;
 
        BOOL br = ::VerQueryValue(lpBlock, (LPTSTR)(LPCTSTR)strSubBlock, (LPVOID*)&lpBuffer, &uLen);
        if (br == 0)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        for (int i = 0; i < (int)(uLen / sizeof(struct LANGANDCODEPAGE)); i++)
        {
            LANGANDCODEPAGE* pLangAndCodePage = (LANGANDCODEPAGE*)lpBuffer;
            ATLASSERT(pLangAndCodePage);
 
            LangAndCodePages.push_back(pLangAndCodePage[i]);
        }
 
        return S_OK;
    }
    static HRESULT InternalGetFileInfo(const LPVOID lpBlock, VS_FIXEDFILEINFO* pFileInfo)
    {
        if (lpBlock == NULL)
        {
            return E_FAIL;
        }
 
        if (pFileInfo == NULL)
        {
            return E_FAIL;
        }
 
        // クリアする
        ::ZeroMemory(pFileInfo, sizeof(VS_FIXEDFILEINFO));
 
        CString strSubBlock = _T("\\");
        LPVOID lpBuffer = NULL;
        UINT uLen = 0;
 
        BOOL br = ::VerQueryValue(lpBlock, (LPTSTR)(LPCTSTR)strSubBlock, &lpBuffer, &uLen);
        if (br == 0)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        memcpy(pFileInfo, lpBuffer, sizeof(VS_FIXEDFILEINFO));
 
        return S_OK;
    }
    // szName = "Comments" or "CompanyName" or "FileDescription" or "FileVersion" or
    //          "InternalName" or "LegalCopyright" or "LegalTrademarks" or "OriginalFilename" or
    //          "PrivateBuild" or "ProductName" or "ProductVersion" or "SpecialBuild"
    static HRESULT InternalGetStringFileInfo(const LPVOID lpBlock, CLangAndCodePage LangAndCodePage, LPCTSTR szName, CString& strValue)
    {
        if (lpBlock == NULL)
        {
            return E_FAIL;
        }
 
        // クリアする
        strValue = _T("");
 
        CString strSubBlock;
        strSubBlock.Format(_T("\\StringFileInfo\\%04x%04x\\%s"), LangAndCodePage.wLanguage, LangAndCodePage.wCodePage, szName);
        LPVOID lpBuffer = NULL;
        UINT uLen = 0;
 
        BOOL br = ::VerQueryValue(lpBlock, (LPTSTR)(LPCTSTR)strSubBlock, &lpBuffer, &uLen);
        if (br == 0)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        strValue = (LPCTSTR)lpBuffer;
 
        return S_OK;
    }
 
protected:
    CString m_strFileName;
 
    CString m_strComments;
    CString m_strCompanyName;
    CString m_strFileDescription;
    CString m_strFileVersion;
    CString m_strInternalName;
    CString m_strLegalCopyright;
    CString m_strLegalTrademarks;
    CString m_strOriginalFilename;
    CString m_strPrivateBuild;
    CString m_strProductName;
    CString m_strProductVersion;
    CString m_strSpecialBuild;
};
一覧に戻る
© 2003 WAC.com All Right Reserved.