Applied backgroundcolors.patch
[TortoiseGit.git] / src / Utils / LangDll.cpp
blobd99534a480f2f0f5936cc11794e3450d83ffaaaf
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 wcscpy_s(sVer, MAX_PATH, _T(STRPRODUCTVER));
43 GetModuleFileName(nullptr, langpath, MAX_PATH);
44 TCHAR* pSlash = wcsrchr(langpath, L'\\');
45 if (!pSlash)
46 return m_hInstance;
48 *pSlash = 0;
49 pSlash = wcsrchr(langpath, L'\\');
50 if (!pSlash)
51 return m_hInstance;
53 *pSlash = 0;
54 wcscat_s(langpath, MAX_PATH, L"\\Languages\\");
55 assert(m_hInstance == nullptr);
58 swprintf_s(langdllpath, MAX_PATH, L"%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(), L"\\VarFileInfo\\Translation", &lpFixedPointer, &nFixedLength);
119 lpTransArray = (TRANSARRAY*)lpFixedPointer;
121 swprintf_s(strLangProductVersion, MAX_PATH, L"\\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 (wcscmp(sVer, (LPCTSTR)lpVersion) == 0);
127 return false;