OSDN Git Service

PATCH: [ 1514435 ] Optimize versioninfo reading
authorKimmo Varis <kimmov@gmail.com>
Tue, 4 Jul 2006 18:22:47 +0000 (18:22 +0000)
committerKimmo Varis <kimmov@gmail.com>
Tue, 4 Jul 2006 18:22:47 +0000 (18:22 +0000)
Src/AboutDlg.cpp
Src/Changes.txt
Src/Common/version.cpp
Src/Common/version.h
Src/ConfigLog.cpp
Src/Splash.cpp

index efea26f..fecdbbb 100644 (file)
@@ -24,6 +24,7 @@
 // $Id$
 
 #include "stdafx.h"
+#include "Merge.h"
 #include "AboutDlg.h"
 #include "version.h"
 #include "paths.h"
@@ -62,8 +63,11 @@ void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 BOOL CAboutDlg::OnInitDialog() 
 {
        CDialog::OnInitDialog();
+
+       CMergeApp *pApp = dynamic_cast<CMergeApp *> (AfxGetApp());
+       WORD langId = pApp->GetLangId();
        
-       CVersionInfo version;
+       CVersionInfo version(langId);
        CString sVersion = version.GetFixedProductVersion();
        AfxFormatString1(m_strVersion, IDS_VERSION_FMT, sVersion);
 
index ad62d97..34f161f 100644 (file)
@@ -5,6 +5,9 @@ Add new items to top.
 2006-07-04 Kimmo
  PATCH: [ 1516626 ] Enable double-click in column customization dialog
   Src: DirColsDlg.cpp DirColsDlg.h
+ PATCH: [ 1514435 ] Optimize versioninfo reading
+  Src: AboutDlg.cpp ConfigLog.cpp Splash.cpp
+  Src/Common: version.cpp version.h
 
 2006-07-04 Takashi
  BUG: [ 1303166 ] crash or freeze on closing all window
index f17c5e8..e87a9bf 100644 (file)
 #include "stdafx.h"
 #include "version.h"
 
+/** 
+ * @brief Structure used to store language and codepage.
+ */
+struct LANGUAGEANDCODEPAGE
+{
+       WORD wLanguage;
+       WORD wCodePage;
+};
+
+/** 
+ * @brief Constructor for asking only numeric version info.
+ * This constructor creates instance that only reads version numbers,
+ * not several strings there are. This saves some time.
+ * @param [in] bVersionOnly If TRUE only version numbers are read.
+ */
+CVersionInfo::CVersionInfo(BOOL bVersionOnly)
+: m_wLanguage(0)
+, m_bVersionOnly(bVersionOnly)
+, m_bDllVersion(FALSE)
+{
+       GetVersionInfo();
+}
+
+/** 
+ * @brief Constructor for asking version infor when language is known.
+ * This constructor creates instance which gets version-info matching
+ * given language-ID. There can be several different language-codepage
+ * combinations, but we use first version info block that matches the
+ * given language. So even if codepage isn't correct, we get correct
+ * version information.
+ * @param [in] wLanguage Language-ID for which the version info is wanted.
+ */
+CVersionInfo::CVersionInfo(WORD wLanguage)
+: m_wLanguage(wLanguage)
+, m_bVersionOnly(FALSE)
+, m_bDllVersion(FALSE)
+{
+       GetVersionInfo();
+}
+
+/** 
+ * @brief Constructor.
+ * @param [in] szFileToVersion Filename to read version from.
+ * @param [in] bDllVersion If TRUE queries DLL version.
+ */
+CVersionInfo::CVersionInfo(LPCTSTR szFileToVersion, 
+                                                  BOOL bDllVersion)
+: m_strFileName(szFileToVersion)
+, m_wLanguage(0)
+, m_bVersionOnly(FALSE)
+, m_bDllVersion(bDllVersion)
+{
+       GetVersionInfo();
+}
+
+/** 
+ * @brief Constructor.
+ * @param [in] szFileToVersion Filename to read version from.
+ * @param [in] szLanguage Language for version.
+ * @param [in] szCodePage Codepage for version.
+ */
 CVersionInfo::CVersionInfo(LPCTSTR szFileToVersion /* = NULL*/, 
                                                   LPCTSTR szLanguage /* = NULL*/,
                                                   LPCTSTR szCodepage /* = NULL*/)
+: m_strFileName(szFileToVersion)
+, m_strLanguage(szLanguage)
+, m_strCodepage(szCodepage)
+, m_wLanguage(0)
+, m_bVersionOnly(FALSE)
+, m_bDllVersion(FALSE)
 {
-       m_strFileName = szFileToVersion;
-       m_strLanguage = szLanguage;
-       m_strCodepage = szCodepage;
        GetVersionInfo();
 }
 
+/** 
+ * @brief Constructor for asking version number from known module.
+ * @param [in] hModule Handle to module for version info.
+ */
 CVersionInfo::CVersionInfo(HINSTANCE hModule)
+: m_wLanguage(0)
+, m_bVersionOnly(FALSE)
+, m_bDllVersion(FALSE)
 {
        TCHAR szFileName[MAX_PATH];
        GetModuleFileName(hModule, szFileName, MAX_PATH);
@@ -28,51 +99,96 @@ CVersionInfo::CVersionInfo(HINSTANCE hModule)
        GetVersionInfo();
 }
 
-CString CVersionInfo::GetFileVersion()
+/** 
+ * @brief Return file version string.
+ * @return File version as string.
+ */
+CString CVersionInfo::GetFileVersion() const
 {
        return m_strFileVersion;
 }
 
-CString CVersionInfo::GetPrivateBuild()
+/** 
+ * @brief Return private build number.
+ * @return Private build number as string.
+ */
+CString CVersionInfo::GetPrivateBuild() const
 {
        return m_strPrivateBuild;
 }
 
-CString CVersionInfo::GetSpecialBuild()
+/** 
+ * @brief Return special build number.
+ * @return Special build number as string.
+ */
+CString CVersionInfo::GetSpecialBuild() const
 {
        return m_strSpecialBuild;
 }
 
-CString CVersionInfo::GetCompanyName()
+/** 
+ * @brief Return company name.
+ * @return Company name.
+ */
+CString CVersionInfo::GetCompanyName() const
 {
        return m_strCompanyName;
 }
 
-CString CVersionInfo::GetFileDescription()
+/** 
+ * @brief Return file description string.
+ * @return File description string.
+ */
+CString CVersionInfo::GetFileDescription() const
 {
        return m_strFileDescription;
 }
 
-CString CVersionInfo::GetInternalName()
+/** 
+ * @brief Return internal name.
+ * @return Internal name.
+ */
+CString CVersionInfo::GetInternalName() const
 {
        return m_strInternalName;
 }
 
-CString CVersionInfo::GetLegalCopyright()
+/** 
+ * @brief Return copyright info.
+ * @return Copyright info.
+ */
+CString CVersionInfo::GetLegalCopyright() const
 {
        return m_strLegalCopyright;
 }
 
-CString CVersionInfo::GetOriginalFilename()
+/** 
+ * @brief Return original filename.
+ * @return Original filename.
+ */
+CString CVersionInfo::GetOriginalFilename() const
 {
        return m_strOriginalFilename;
 }
 
-CString CVersionInfo::GetProductVersion()
+/** 
+ * @brief Return product's version number.
+ * @return Product's version number as string.
+ */
+CString CVersionInfo::GetProductVersion() const
 {
        return m_strProductVersion;
 }
 
+/** 
+ * @brief Format version string from numbers.
+ * Version number consists of four WORD (16-bit) numbers. This function
+ * formats those numbers to string, where numbers are separated by
+ * dots.
+ * @param [in] First two (most significant) numbers for version number.
+ * @param [in] Last two numbers for version number.
+ * @return Formatted version string.
+ */
 static CString MakeVersionString(DWORD hi, DWORD lo)
 {
        CString sver;
@@ -80,6 +196,11 @@ static CString MakeVersionString(DWORD hi, DWORD lo)
        return sver;
 }
 
+/** 
+ * @brief Return numeric product's version number.
+ * This function returns version number given as a number in version info.
+ * @return Product's version number as string.
+ */
 CString CVersionInfo::GetFixedProductVersion()
 {
        if (!m_dwVerInfoSize)
@@ -88,6 +209,11 @@ CString CVersionInfo::GetFixedProductVersion()
                , m_FixedFileInfo.dwProductVersionLS);
 }
 
+/** 
+ * @brief Return numeric file's version number.
+ * This function returns version number given as a number in version info.
+ * @return File's version number as string.
+ */
 CString CVersionInfo::GetFixedFileVersion()
 {
        if (!m_dwVerInfoSize)
@@ -96,92 +222,121 @@ CString CVersionInfo::GetFixedFileVersion()
                , m_FixedFileInfo.dwFileVersionLS);
 }
 
-CString CVersionInfo::GetComments()
+/** 
+ * @brief Return comment string.
+ * @return Comment string.
+ */
+CString CVersionInfo::GetComments() const
 {
        return m_strComments;
 }
 
+/** 
+ * @brief Read version info from file.
+ * This function reads version information from file's version resource
+ * to member variables.
+ */
 void CVersionInfo::GetVersionInfo()
 {
-       m_lpstrVffInfo = NULL;
-       m_bQueryDone = FALSE;
-       ZeroMemory(&m_FixedFileInfo, sizeof m_FixedFileInfo);
-       ZeroMemory(&m_dvi, sizeof m_dvi);
+       m_pVffInfo = NULL;
+       ZeroMemory(&m_FixedFileInfo, sizeof(m_FixedFileInfo));
+       ZeroMemory(&m_dvi, sizeof(m_dvi));
 
        DWORD dwVerHnd = 0;                     // An 'ignored' parameter, always '0'
        TCHAR szFileName[MAX_PATH];
 
-       m_bQueryDone=TRUE;
        if (m_strFileName.IsEmpty())
                GetModuleFileName(NULL, szFileName, MAX_PATH);
        else
-               _tcscpy(szFileName, m_strFileName);
+               _tcsncpy(szFileName, m_strFileName, MAX_PATH - 1);
        
        m_dwVerInfoSize = GetFileVersionInfoSize(szFileName, &dwVerHnd);
        if (m_dwVerInfoSize)
        {
-               HANDLE  hMem;
-               hMem = GlobalAlloc(GMEM_MOVEABLE, m_dwVerInfoSize);
-               m_lpstrVffInfo = (LPTSTR)GlobalLock(hMem);
-               if (GetFileVersionInfo(szFileName, dwVerHnd, m_dwVerInfoSize, m_lpstrVffInfo))
+               m_pVffInfo = new BYTE[m_dwVerInfoSize];
+               if (GetFileVersionInfo(szFileName, dwVerHnd, m_dwVerInfoSize, m_pVffInfo))
                {
                        GetFixedVersionInfo();
-                       if (m_strLanguage.IsEmpty()
-                               || m_strCodepage.IsEmpty())
+                       if (m_bVersionOnly == FALSE)
+                               QueryStrings();
+               }
+               delete [] m_pVffInfo;
+               m_pVffInfo = NULL;
+       }
+
+       if (m_bDllVersion)
+       {
+               if (HINSTANCE hinstDll = LoadLibrary(szFileName))
+               {
+                       DLLGETVERSIONPROC DllGetVersion = (DLLGETVERSIONPROC) 
+                                       GetProcAddress(hinstDll, "DllGetVersion");
+                       if (DllGetVersion)
                        {
-                               LPWORD langInfo;
-                               DWORD langLen;
-                               if (VerQueryValue((LPVOID)m_lpstrVffInfo,
-                                       _T("\\VarFileInfo\\Translation"),
-                                       (LPVOID *)&langInfo, (UINT *)&langLen))
+                               m_dvi.cbSize = sizeof(m_dvi);
+                               if FAILED(DllGetVersion(&m_dvi))
                                {
-                                       m_strLanguage.Format(_T("%4.4X"), langInfo[0]); 
-                                       m_strCodepage.Format(_T("%4.4X"), langInfo[1]); 
+                                       m_dvi.cbSize = 0;
                                }
                        }
-                       QueryValue(_T("CompanyName"), m_strCompanyName);
-                       QueryValue(_T("FileDescription"), m_strFileDescription);
-                       QueryValue(_T("FileVersion"), m_strFileVersion); 
-                       QueryValue(_T("InternalName"), m_strInternalName); 
-                       QueryValue(_T("LegalCopyright"), m_strLegalCopyright); 
-                       QueryValue(_T("OriginalFilename"), m_strOriginalFilename); 
-                       QueryValue(_T("ProductName"), m_strProductName); 
-                       QueryValue(_T("ProductVersion"), m_strProductVersion); 
-                       QueryValue(_T("Comments"), m_strComments);
-                       QueryValue(_T("SpecialBuild"), m_strSpecialBuild);
-                       QueryValue(_T("PrivateBuild"), m_strPrivateBuild);
+                       FreeLibrary(hinstDll);
                }
-               GlobalUnlock(hMem);
-               GlobalFree(hMem);
-               m_lpstrVffInfo = 0;
        }
+}
 
-       if (HINSTANCE hinstDll = LoadLibrary(szFileName))
+/** 
+ * @brief Read strings from version info data.
+ */
+void CVersionInfo::QueryStrings()
+{
+       if (m_wLanguage != 0)
+       {
+               WORD codepage;
+               GetCodepageForLanguage(m_wLanguage, codepage);
+               m_strLanguage.Format(_T("%04x"), m_wLanguage);
+               m_strCodepage.Format(_T("%04x"), codepage);
+       }
+       else if (m_strLanguage.IsEmpty()
+               || m_strCodepage.IsEmpty())
        {
-               DLLGETVERSIONPROC DllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");
-               if (DllGetVersion)
+               LANGUAGEANDCODEPAGE *lpTranslate;
+               DWORD langLen;
+               if (VerQueryValue((LPVOID)m_pVffInfo,
+                       _T("\\VarFileInfo\\Translation"),
+                       (LPVOID *)&lpTranslate, (UINT *)&langLen))
                {
-                       m_dvi.cbSize = sizeof m_dvi;
-                       if FAILED(DllGetVersion(&m_dvi))
-                       {
-                               m_dvi.cbSize = 0;
-                       }
+                       m_strLanguage.Format(_T("%4.4X"), lpTranslate[0].wLanguage);
+                       m_strCodepage.Format(_T("%4.4X"), lpTranslate[0].wCodePage);
                }
-               FreeLibrary(hinstDll);
        }
+       QueryValue(_T("CompanyName"), m_strCompanyName);
+       QueryValue(_T("FileDescription"), m_strFileDescription);
+       QueryValue(_T("FileVersion"), m_strFileVersion); 
+       QueryValue(_T("InternalName"), m_strInternalName); 
+       QueryValue(_T("LegalCopyright"), m_strLegalCopyright); 
+       QueryValue(_T("OriginalFilename"), m_strOriginalFilename); 
+       QueryValue(_T("ProductName"), m_strProductName); 
+       QueryValue(_T("ProductVersion"), m_strProductVersion); 
+       QueryValue(_T("Comments"), m_strComments);
+       QueryValue(_T("SpecialBuild"), m_strSpecialBuild);
+       QueryValue(_T("PrivateBuild"), m_strPrivateBuild);
 }
 
+/** 
+ * @brief Read value from version info data.
+ * @param [in] szId Name of value/string to read.
+ * @param [out] Value read.
+ */
 void CVersionInfo::QueryValue(LPCTSTR szId, CString& s)
 {
-       ASSERT(m_lpstrVffInfo != NULL);
+       ASSERT(m_pVffInfo != NULL);
        LPTSTR   lpVersion;                     // String pointer to 'version' text
        UINT    uVersionLen;
        BOOL    bRetCode;
 
-       TCHAR szSelector[256];  
+       TCHAR szSelector[256];
        _stprintf(szSelector,_T("\\StringFileInfo\\%s%s\\%s"),
                        m_strLanguage, m_strCodepage, szId);
-       bRetCode = VerQueryValue((LPVOID)m_lpstrVffInfo,
+       bRetCode = VerQueryValue((LPVOID)m_pVffInfo,
                szSelector,
                (LPVOID *)&lpVersion,
                &uVersionLen);
@@ -196,20 +351,56 @@ void CVersionInfo::QueryValue(LPCTSTR szId, CString& s)
                s.Empty();
 }
 
+/** 
+ * @brief Read numeric version information.
+ */
 void CVersionInfo::GetFixedVersionInfo()
 {
        VS_FIXEDFILEINFO * pffi;
        UINT len = sizeof(*pffi);
        BOOL bRetCode = VerQueryValue(
-               (LPVOID)m_lpstrVffInfo, _T("\\"), (LPVOID *)&pffi, &len);
+               (LPVOID)m_pVffInfo, _T("\\"), (LPVOID *)&pffi, &len);
        memcpy(&m_FixedFileInfo, pffi, sizeof(m_FixedFileInfo));
        m_dvi.dwMajorVersion = HIWORD(m_FixedFileInfo.dwFileVersionMS);
        m_dvi.dwMinorVersion = LOWORD(m_FixedFileInfo.dwFileVersionMS);
        m_dvi.dwBuildNumber = HIWORD(m_FixedFileInfo.dwFileVersionLS);
 }
 
+/** 
+ * @brief Get codepage for given language.
+ * This function finds codepage value for given language from version info.
+ * That is, we have certain combinations of language-codepage in version info.
+ * This function tells which codepage exists with given language, so we can
+ * find existing version info data.
+ * @param [in] wLanguage Language ID for which we need matching codepage.
+ * @param [out] wCodePage Found codepage.
+ * @return TRUE if language was found from version info block.
+ */
+BOOL CVersionInfo::GetCodepageForLanguage(WORD wLanguage, WORD & wCodePage)
+{
+       LANGUAGEANDCODEPAGE *lpTranslate;
+       UINT cbTranslate;
+       // Read the list of languages and code pages.
+
+       VerQueryValue((LPVOID)m_pVffInfo, 
+                               _T("\\VarFileInfo\\Translation"),
+                               (LPVOID*)&lpTranslate,
+                               &cbTranslate);
 
-/*******************************************************************************
-       END OF FILE
-*******************************************************************************/
+       // Read the file description for each language and code page.
 
+       const int nLangCount = cbTranslate / sizeof(LANGUAGEANDCODEPAGE);
+       int i = 0;
+       BOOL bFound = FALSE;
+       while (bFound == FALSE && i < nLangCount)
+       {
+               if (lpTranslate[i].wLanguage == wLanguage)
+               {
+                       wCodePage = lpTranslate[i].wCodePage;
+                       bFound = TRUE;
+               }
+               else
+                       ++i;
+       }
+       return bFound;
+}
index a3eb422..5975bfc 100644 (file)
 #include <shlwapi.h>
 
 /**
- * @brief Class providing access to version information of a file
+ * @brief Class providing access to version information of a file.
+ * This class reads version information block from a file. Version information
+ * consists of version numbers, copyright, descriptions etc. Since that is
+ * many strings to read, there is constructor taking BOOL parameter and
+ * only reading version numbers. That constructor is suggested to be used
+ * if string information is not needed.
  */
 class CVersionInfo
 {
-       LPTSTR   m_lpstrVffInfo;
-       BOOL m_bQueryDone;
-       VS_FIXEDFILEINFO m_FixedFileInfo;
+private:
+       VS_FIXEDFILEINFO m_FixedFileInfo; /**< Fixed file information */
        DWORD m_dwVerInfoSize; /**< Size of version information block (0 if missing) */
+       BYTE * m_pVffInfo; /**< Pointer to version information block */
+       BOOL m_bVersionOnly; /**< Ask version numbers only */
+       BOOL m_bDllVersion;
+       WORD m_wLanguage; /**< Language-ID to use (if given) */
 
        CString m_strFileName;
        CString m_strLanguage;
@@ -35,28 +43,36 @@ class CVersionInfo
        CString m_strComments;
        CString m_strSpecialBuild;
        CString m_strPrivateBuild;
+
 public:
-       CVersionInfo(LPCTSTR szFileToVersion = NULL, 
+       CVersionInfo(BOOL bVersionOnly);
+       CVersionInfo(WORD wLanguage);
+       CVersionInfo(LPCTSTR szFileToVersion,
+                                  BOOL bDllVersion);
+       CVersionInfo(LPCTSTR szFileToVersion = NULL,
                                   LPCTSTR szLanguage = NULL,
                                   LPCTSTR szCodepage = NULL);
        CVersionInfo(HINSTANCE hModule);
-       CString GetFileVersion();
-       CString GetCompanyName();
-       CString GetFileDescription();
-       CString GetInternalName();
-       CString GetLegalCopyright();
-       CString GetOriginalFilename();
-       CString GetProductVersion();
-       CString GetComments();
-       CString GetSpecialBuild();
-       CString GetPrivateBuild();
+       CString GetFileVersion() const;
+       CString GetCompanyName() const;
+       CString GetFileDescription() const;
+       CString GetInternalName() const;
+       CString GetLegalCopyright() const;
+       CString GetOriginalFilename() const;
+       CString GetProductVersion() const;
+       CString GetComments() const;
+       CString GetSpecialBuild() const;
+       CString GetPrivateBuild() const;
        CString GetFixedProductVersion();
        CString GetFixedFileVersion();
        DLLVERSIONINFO m_dvi;
+
 protected:
        void GetVersionInfo();
        void GetFixedVersionInfo();
+       void QueryStrings();
        void QueryValue(LPCTSTR szId, CString& s);
+       BOOL GetCodepageForLanguage(WORD wLanguage, WORD & wCodePage);
 };
 
 
index ae4bdb2..743ea65 100644 (file)
@@ -210,7 +210,7 @@ static void WriteVersionOf1(CStdioFile &file, int indent, LPTSTR path)
        if (file.m_hFile == CFile::hFileNull) return;
 
        LPTSTR name = PathFindFileName(path);
-       CVersionInfo vi = path;
+       CVersionInfo vi(path, TRUE);
        CString text;
        text.Format
        (
index 2f2d318..ee20aa0 100644 (file)
@@ -207,7 +207,7 @@ void CSplashWnd::OnPaint()
        CPaintDC dc(this);
        m_pPicture->Render(&dc);
 
-       CVersionInfo version;
+       CVersionInfo version(TRUE);
        CString s;
        CFont versionFont;
        CFont textFont;