获取文件属性“详细信息” - StringFileInfo


参考链接:
1、MS docs - GetFileVersionInfoA:https://docs.microsoft.com/zh-cn/windows/desktop/api/winver/nf-winver-getfileversioninfoa
2、Cppblog - Win32汇编--使用资源—版本信息资源:http://www.cppblog.com/luqingfei/archive/2010/09/21/127239.html
3、CSDN blog - 【PE】Windows资源文件rc定义和使用:https://blog.csdn.net/soaringlee_fighting/article/details/80596261
4、CSDN blog - 获取EXE版本信息 GetFileVersionInfo:https://blog.csdn.net/mfkjq/article/details/53064243

在一些hips软件中,会显示一些exe、dll、sys等的厂商信息,这些信息便存在于"详细信息"中。

0、什么是StringFileInfo

通俗来说,这里的“详细信息”指PE文件(dll,exe,sys等)的信息,包括属性页中的“详细信息”tab页中一部分内容

对应VS中的.rc中的VS_VERSION_INFO信息

以及*.rc文件源码中的VS_VERSION_INFO部分

1、获取方法

如果E文可以,请直接阅读MS Docs中GetFileVersionInfoA说明,详细权威,且VerQueryValueA部分有一段示例代码。
微软version.lib(version.dll)提供了中的3个函数用来获取这些信息,获取步骤:

  • 首先使用GetFileVersionInfoSizeA(W)获取VersionInfo的大小,申请缓冲区;
  • 接着使用GetFileVersionInfoA(W)获取VersionInfo数据到缓冲区
  • 接着使用VerQueryValueA(W)依次获取\\VarFileInfo\Translation,再根据Translation获取语言类型,接着\VarFileInfo\080404B0\CompanyName便获取到了厂商信息。

附:CompanyName域可取值:

2、示例代码

// conGetVer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <tchar.h>
#include <windows.h>
#include <iostream>

//  pName可取值:
//    _T("CompanyName"),_T("FileDescription"),_T("FileVersion"),
//  _T("InternalName"),_T("LegalCopyright"),_T("OriginalFilename"),
//  _T("ProductName"),_T("ProductVersion"),
BOOL GetFileVersionString(LPCTSTR pFileName, LPCTSTR pName /* = NULL */, LPTSTR ptBuf, UINT lenBuf)
{
    DWORD   dwDummyHandle = 0; // will always be set to zero
    DWORD   dwLen = 0;
    BYTE*    pVersionInfo = NULL;
    BOOL    bRetVal;

    VS_FIXEDFILEINFO    FileVersion;

    HMODULE        hVerDll;
    hVerDll = LoadLibrary(_T("VERSION.dll"));
    if (hVerDll == NULL)
        return FALSE;

#ifdef _UNICODE
    typedef DWORD(WINAPI *Fun_GetFileVersionInfoSize)(LPCTSTR, DWORD *);
    typedef BOOL(WINAPI *Fun_GetFileVersionInfo)(LPCTSTR, DWORD, DWORD, LPVOID);
    typedef BOOL(WINAPI *Fun_VerQueryValue)(LPCVOID, LPCTSTR, LPVOID, PUINT);
#else
    typedef DWORD(WINAPI *Fun_GetFileVersionInfoSize)(LPCSTR, DWORD *);
    typedef BOOL(WINAPI *Fun_GetFileVersionInfo)(LPCSTR, DWORD, DWORD, LPVOID);
    typedef BOOL(WINAPI *Fun_VerQueryValue)(LPCVOID, LPCSTR, LPVOID, PUINT);
#endif

    Fun_GetFileVersionInfoSize        pGetFileVersionInfoSize;
    Fun_GetFileVersionInfo            pGetFileVersionInfo;
    Fun_VerQueryValue                pVerQueryValue;

#ifdef _UNICODE
    pGetFileVersionInfoSize = (Fun_GetFileVersionInfoSize)::GetProcAddress(hVerDll, "GetFileVersionInfoSizeW");
    pGetFileVersionInfo = (Fun_GetFileVersionInfo)::GetProcAddress(hVerDll, "GetFileVersionInfoW");
    pVerQueryValue = (Fun_VerQueryValue)::GetProcAddress(hVerDll, "VerQueryValueW");
#else
    pGetFileVersionInfoSize = (Fun_GetFileVersionInfoSize)::GetProcAddress(hVerDll, "GetFileVersionInfoSizeA");
    pGetFileVersionInfo = (Fun_GetFileVersionInfo)::GetProcAddress(hVerDll, "GetFileVersionInfoA");
    pVerQueryValue = (Fun_VerQueryValue)::GetProcAddress(hVerDll, "VerQueryValueA");
#endif

    struct TRANSLATION {
        WORD langID;            // language ID
        WORD charset;            // character set (code page)
    } Translation;

    Translation.langID = 0x0409;    //
    Translation.charset = 1252;        // default = ANSI code page

    dwLen = pGetFileVersionInfoSize(pFileName, &dwDummyHandle);
    if (dwLen == 0)
    {
        bRetVal = FALSE;
        goto End;
    }

    pVersionInfo = new BYTE[dwLen]; // allocate version info
    bRetVal = pGetFileVersionInfo(pFileName, 0, dwLen, pVersionInfo);
    if (bRetVal == FALSE)
    {
        goto End;
    }

    VOID    * pVI;
    UINT    uLen;

    bRetVal = pVerQueryValue(pVersionInfo, _T("\\"), &pVI, &uLen);
    if (bRetVal == FALSE)
    {
        goto End;
    }

    memcpy(&FileVersion, pVI, sizeof(VS_FIXEDFILEINFO));

    bRetVal = pVerQueryValue(pVersionInfo, _T("\\VarFileInfo\\Translation"),
        &pVI, &uLen);
    if (bRetVal && uLen >= 4)
    {
        memcpy(&Translation, pVI, sizeof(TRANSLATION));
    }
    else
    {
        bRetVal = FALSE;
        goto End;
    }

    //  BREAKIF(FileVersion.dwSignature != VS_FFI_SIGNATURE);
    if (FileVersion.dwSignature != VS_FFI_SIGNATURE)
    {
        bRetVal = FALSE;
        goto End;
    }

    VOID        *pVal;
    UINT        iLenVal;

    if (pName == NULL)
    {
        _stprintf_s(ptBuf, lenBuf, _T("%d.%d.%d.%d"),
            HIWORD(FileVersion.dwFileVersionMS), LOWORD(FileVersion.dwFileVersionMS),
            HIWORD(FileVersion.dwFileVersionLS), LOWORD(FileVersion.dwFileVersionLS));
    }
    else
    {
        TCHAR    szQuery[1024];
        _stprintf_s(szQuery, 1024, _T("\\StringFileInfo\\%04X%04X\\%s"),
            Translation.langID, Translation.charset, pName);

        bRetVal = pVerQueryValue(pVersionInfo, szQuery, &pVal, &iLenVal);
        if (bRetVal)
        {
            _stprintf_s(ptBuf, lenBuf, _T("%s"), (TCHAR*)pVal);
        }
        else
        {
            _stprintf_s(ptBuf, lenBuf, _T("%s"), _T(""));
        }
    }

End:
    FreeLibrary(hVerDll);
    hVerDll = NULL;
    delete[] pVersionInfo;
    pVersionInfo = NULL;

    return bRetVal;
}


int main()
{
    TCHAR* ptszStr = NULL;

    ptszStr = new TCHAR[1024];
    BOOL bRet = GetFileVersionString(_T("F:\\Wireshark-win32-1.11.2.exe"),
        _T("CompanyName"), ptszStr, 1024);

    delete ptszStr;
    ptszStr = NULL;

    std::cout << "Hello World!\n"; 
}




posted @ 2019-03-27 14:39  鞋带儿  阅读(3910)  评论(0编辑  收藏  举报