Improve readability of version string
[TortoiseGit.git] / src / Utils / LangDll.cpp
blob16b13dfeaa150c9a4e20fdf5ef01f0f6f2e31c20
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2016 - TortoiseGit
4 // Copyright (C) 2003-2006, 2008, 2013-2015 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include <assert.h>
22 #include "LangDll.h"
23 #include "..\version.h"
24 #include <memory>
26 #pragma comment(lib, "Version.lib")
28 CLangDll::CLangDll()
30 m_hInstance = nullptr;
33 CLangDll::~CLangDll()
37 HINSTANCE CLangDll::Init(LPCTSTR appname, unsigned long langID)
39 TCHAR langpath[MAX_PATH] = {0};
40 TCHAR langdllpath[MAX_PATH] = {0};
41 TCHAR sVer[MAX_PATH] = {0};
42 _tcscpy_s(sVer, MAX_PATH, _T(STRPRODUCTVER));
43 GetModuleFileName(nullptr, langpath, MAX_PATH);
44 TCHAR * pSlash = _tcsrchr(langpath, '\\');
45 if (!pSlash)
46 return m_hInstance;
48 *pSlash = 0;
49 pSlash = _tcsrchr(langpath, '\\');
50 if (!pSlash)
51 return m_hInstance;
53 *pSlash = 0;
54 _tcscat_s(langpath, MAX_PATH, _T("\\Languages\\"));
55 assert(m_hInstance == nullptr);
58 _stprintf_s(langdllpath, MAX_PATH, _T("%s%s%lu.dll"), langpath, appname, langID);
60 m_hInstance = LoadLibrary(langdllpath);
62 if (!DoVersionStringsMatch(sVer, langdllpath))
64 FreeLibrary(m_hInstance);
65 m_hInstance = nullptr;
67 if (!m_hInstance)
69 DWORD lid = SUBLANGID(langID);
70 lid--;
71 if (lid > 0)
72 langID = MAKELANGID(PRIMARYLANGID(langID), lid);
73 else
74 langID = 0;
76 } while (!m_hInstance && (langID != 0));
78 return m_hInstance;
81 void CLangDll::Close()
83 if (!m_hInstance)
84 return;
86 FreeLibrary(m_hInstance);
87 m_hInstance = nullptr;
90 bool CLangDll::DoVersionStringsMatch(LPCTSTR sVer, LPCTSTR langDll) const
92 struct TRANSARRAY
94 WORD wLanguageID;
95 WORD wCharacterSet;
98 DWORD dwReserved = 0;
99 DWORD dwBufferSize = GetFileVersionInfoSize((LPTSTR)langDll,&dwReserved);
101 if (dwBufferSize <= 0)
102 return false;
104 auto pBuffer = std::make_unique<BYTE[]>(dwBufferSize);
106 if (!pBuffer)
107 return false;
109 UINT nInfoSize = 0, nFixedLength = 0;
110 LPSTR lpVersion = nullptr;
111 VOID* lpFixedPointer;
112 TRANSARRAY* lpTransArray;
113 TCHAR strLangProductVersion[MAX_PATH] = { 0 };
115 if (!GetFileVersionInfo((LPTSTR)langDll, dwReserved, dwBufferSize, pBuffer.get()))
116 return false;
118 VerQueryValue(pBuffer.get(), _T("\\VarFileInfo\\Translation"), &lpFixedPointer, &nFixedLength);
119 lpTransArray = (TRANSARRAY*)lpFixedPointer;
121 _stprintf_s(strLangProductVersion, MAX_PATH, _T("\\StringFileInfo\\%04x%04x\\ProductVersion"), lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet);
123 VerQueryValue(pBuffer.get(), (LPTSTR)strLangProductVersion, (LPVOID*)&lpVersion, &nInfoSize);
124 if (lpVersion && nInfoSize)
125 return (_tcscmp(sVer, (LPCTSTR)lpVersion) == 0);
127 return false;