diff --git a/Plugins/PluginFolderInfo/FolderInfo.cpp b/Plugins/PluginFolderInfo/FolderInfo.cpp index d3962774..deccadee 100644 --- a/Plugins/PluginFolderInfo/FolderInfo.cpp +++ b/Plugins/PluginFolderInfo/FolderInfo.cpp @@ -1,165 +1,178 @@ +/* + Copyright (C) 2010 Elestel + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + #include "FolderInfo.h" #include #include +#include "../API/RainmeterAPI.h" -namespace PluginFolderInfo { - -FolderInfo::FolderInfo(const wchar_t* aPath, const wchar_t* aIniPath) +#define UPDATE_TIME_MIN_MS 10000 + +CFolderInfo::CFolderInfo(LPCWSTR path) : + m_InstanceCount(1), + m_Path(path), + m_IncludeSubFolders(false), + m_IncludeHiddenFiles(false), + m_IncludeSystemFiles(false), + m_Size(), + m_FileCount(), + m_FolderCount(), + m_RegExpFilter(), + m_LastUpdateTime() { - mySubFolderFlag = false; - myHiddenFileFlag = false; - mySystemFileFlag = false; - myRegExpFilter = NULL; - myRegExpFilterExtra = NULL; - myLastUpdateTime = 0; - Clear(); - SetPath(aPath, aIniPath); } -FolderInfo::~FolderInfo() +CFolderInfo::~CFolderInfo() { FreePcre(); } -void FolderInfo::Clear() +void CFolderInfo::AddInstance() { - mySize = 0; - myFileCount = 0; - myFolderCount = 0; + ++m_InstanceCount; } -void FolderInfo::FreePcre() +void CFolderInfo::RemoveInstance() { - if (myRegExpFilter) { - pcre_free(myRegExpFilter); - myRegExpFilter = NULL; - } - - if (myRegExpFilterExtra) { - pcre_free(myRegExpFilterExtra); - myRegExpFilterExtra = NULL; + --m_InstanceCount; + if (m_InstanceCount == 0) + { + delete this; } } -void FolderInfo::SetPath(const wchar_t* aPath, const wchar_t* aIniPath) +void CFolderInfo::Clear() { - if (!aPath || 0 == aPath[0]) { - myPath = L""; - return; - } + m_Size = 0; + m_FileCount = 0; + m_FolderCount = 0; +} - myPath = aPath; - if (wcsncmp(aPath, L".\\", 2) == 0 || wcsncmp(aPath, L"..\\", 3) == 0) { - wchar_t* buf = new wchar_t[wcslen(aIniPath) + 1]; - wcscpy(buf, aIniPath); - wchar_t* iniFileName = wcsrchr(buf, '\\'); - if (iniFileName) { - iniFileName[1] = 0; - myPath = buf; - myPath += aPath; +void CFolderInfo::FreePcre() +{ + if (m_RegExpFilter) + { + pcre_free(m_RegExpFilter); + m_RegExpFilter = NULL; + } +} + +void CFolderInfo::Update() +{ + DWORD now = GetTickCount(); + if (now - m_LastUpdateTime > UPDATE_TIME_MIN_MS) + { + Clear(); + + if (!m_Path.empty()) + { + CalculateSize(); } - delete[] buf; - } - if (myPath[myPath.size() - 1] != L'\\') { - myPath += L"\\"; + m_LastUpdateTime = now; } } -void FolderInfo::Update() +void CFolderInfo::CalculateSize() { - Clear(); + std::list folderQueue; + folderQueue.push_back(m_Path.c_str()); - if (myPath.length() == 0) { - return; - } - - CalculateSize(); - myLastUpdateTime = GetTickCount(); -} - -void FolderInfo::CalculateSize() -{ - std::list folderQueue; - folderQueue.push_back(myPath.c_str()); - - wchar_t searchPattern[MAX_PATH + 10]; - wchar_t buffer[MAX_PATH]; + WCHAR searchPattern[MAX_PATH + 10]; + WCHAR buffer[MAX_PATH]; char utf8Buf[MAX_PATH * 3]; WIN32_FIND_DATA findData; HANDLE findHandle; - while (!folderQueue.empty()) { - std::list::reference ref = folderQueue.front(); + while (!folderQueue.empty()) + { + const CRawString& ref = folderQueue.front(); wsprintf(searchPattern, L"%s%s", ref.c_str(), L"\\*.*"); - findHandle = ::FindFirstFile(searchPattern, &findData); - if (INVALID_HANDLE_VALUE == findHandle) { + + findHandle = FindFirstFile(searchPattern, &findData); + if (INVALID_HANDLE_VALUE == findHandle) + { folderQueue.pop_front(); continue; } - do { + do + { // special case for "." and ".." if (wcscmp(findData.cFileName, L".") == 0 || - wcscmp(findData.cFileName, L"..") == 0) { + wcscmp(findData.cFileName, L"..") == 0) + { continue; } bool isFolder = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; - if (!myHiddenFileFlag && (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) { + if (!m_IncludeHiddenFiles && (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) + { continue; } - else if (!mySystemFileFlag && (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) { + else if (!m_IncludeSystemFiles && (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) + { continue; } - else if (!isFolder && myRegExpFilter) { + else if (!isFolder && m_RegExpFilter) + { int utf8BufLen = WideCharToMultiByte(CP_UTF8, 0, findData.cFileName, wcslen(findData.cFileName) + 1, utf8Buf, MAX_PATH * 3, NULL, NULL); - if (0 != pcre_exec(myRegExpFilter, myRegExpFilterExtra, utf8Buf, utf8BufLen, 0, 0, NULL, 0)) { + if (0 != pcre_exec(m_RegExpFilter, NULL, utf8Buf, utf8BufLen, 0, 0, NULL, 0)) + { continue; } } - if (isFolder) { - myFolderCount++; - if (mySubFolderFlag) { + if (isFolder) + { + m_FolderCount++; + if (m_IncludeSubFolders) + { wsprintf(buffer, L"%s\\%s", ref.c_str(), findData.cFileName); folderQueue.push_back(buffer); } } - else { - myFileCount++; - mySize += ((UINT64)findData.nFileSizeHigh << 32) + findData.nFileSizeLow; + else + { + m_FileCount++; + m_Size += ((UINT64)findData.nFileSizeHigh << 32) + findData.nFileSizeLow; } } - while (::FindNextFile(findHandle, &findData)); + while (FindNextFile(findHandle, &findData)); FindClose(findHandle); folderQueue.pop_front(); } } -void FolderInfo::SetRegExpFilter(const wchar_t* aFilter) +void CFolderInfo::SetRegExpFilter(LPCWSTR filter) { FreePcre(); - if (aFilter == NULL) { - return; - } - - int filterLen = wcslen(aFilter) + 1; - int bufLen = WideCharToMultiByte(CP_UTF8, 0, aFilter, filterLen, NULL, 0, NULL, NULL); + int filterLen = wcslen(filter) + 1; + int bufLen = WideCharToMultiByte(CP_UTF8, 0, filter, filterLen, NULL, 0, NULL, NULL); char* buf = new char[bufLen]; - WideCharToMultiByte(CP_UTF8, 0, aFilter, filterLen, buf, bufLen, NULL, NULL); + WideCharToMultiByte(CP_UTF8, 0, filter, filterLen, buf, bufLen, NULL, NULL); const char* error; int erroffset; - myRegExpFilter = pcre_compile(buf, PCRE_UTF8, &error, &erroffset, NULL); - if (myRegExpFilter) { - myRegExpFilterExtra = pcre_study(myRegExpFilter, 0, &error); - } + m_RegExpFilter = pcre_compile(buf, PCRE_UTF8, &error, &erroffset, NULL); delete [] buf; } - -} // namespace PluginFolderInfo diff --git a/Plugins/PluginFolderInfo/FolderInfo.h b/Plugins/PluginFolderInfo/FolderInfo.h index 9e8d926f..d91a53c4 100644 --- a/Plugins/PluginFolderInfo/FolderInfo.h +++ b/Plugins/PluginFolderInfo/FolderInfo.h @@ -1,88 +1,68 @@ +/* + Copyright (C) 2010 Elestel + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + #pragma once #include -#include #include +#include "../../Library/RawString.h" #include "../../Library/pcre-8.10/config.h" #include "../../Library/pcre-8.10/pcre.h" -namespace PluginFolderInfo { - -struct FileInfo +class CFolderInfo { - std::wstring Name; - bool IsFolder; - UINT64 Size; +public: + CFolderInfo(LPCWSTR path); + ~CFolderInfo(); - FileInfo() - { - IsFolder = false; - Size = 0; - } -}; + void AddInstance(); + void RemoveInstance(); -class FolderInfo -{ -private: - bool mySubFolderFlag; - bool myHiddenFileFlag; - bool mySystemFileFlag; - std::wstring myPath; - UINT64 mySize; - unsigned int myFileCount; - unsigned int myFolderCount; - pcre* myRegExpFilter; - pcre_extra* myRegExpFilterExtra; - DWORD myLastUpdateTime; + DWORD GetLastUpdateTime() { return m_LastUpdateTime; } + + void SetRegExpFilter(LPCWSTR filter); + + void IncludeSubFolders(bool flag) { m_IncludeSubFolders = flag; } + void IncludeHiddenFiles(bool flag) { m_IncludeHiddenFiles = flag; } + void IncludeSystemFiles(bool flag) { m_IncludeSystemFiles = flag; } + + LPCWSTR GetPath() { return m_Path.c_str(); } + + UINT64 GetSize() { return m_Size; } + int GetFileCount() { return m_FileCount; } + int GetFolderCount() { return m_FolderCount; } + + void Update(); private: void Clear(); void FreePcre(); void CalculateSize(); - void SetPath(const wchar_t* aPath, const wchar_t* aIniPath); -public: - DWORD GetLastUpdateTime() - { - return myLastUpdateTime; - } + UINT m_InstanceCount; - void SetRegExpFilter(const wchar_t* aFilter); - - void IncludeSubFolders(bool aFlag) - { - mySubFolderFlag = aFlag; - } - - void IncludeHiddenFiles(bool aFlag) - { - myHiddenFileFlag = aFlag; - } - - void IncludeSystemFiles(bool aFlag) - { - mySystemFileFlag = aFlag; - } - - UINT64 GetSize() - { - return mySize; - } - - int GetFileCount() - { - return myFileCount; - } - - int GetFolderCount() - { - return myFolderCount; - } - - FolderInfo(const wchar_t* aPath, const wchar_t* aIniPath); - ~FolderInfo(); - - void Update(); -}; // class FolderInfo - -} // namespace PluginFolderInfo + CRawString m_Path; + bool m_IncludeSubFolders; + bool m_IncludeHiddenFiles; + bool m_IncludeSystemFiles; + UINT64 m_Size; + UINT m_FileCount; + UINT m_FolderCount; + pcre* m_RegExpFilter; + DWORD m_LastUpdateTime; +}; diff --git a/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp b/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp index 00938a5a..1ec2442a 100644 --- a/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp +++ b/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp @@ -17,216 +17,142 @@ */ #include -#include "../../Library/Export.h" // Rainmeter's exported functions - -#include +#include +#include #include "FolderInfo.h" - +#include "../API/RainmeterAPI.h" #include "../../Library/DisableThreadLibraryCalls.h" // contains DllMain entry point -#define UPDATE_TIME_MIN_MS 10000 - -using namespace PluginFolderInfo; - -/* The exported functions */ -extern "C" +enum MeasureType { - __declspec( dllexport ) UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id); - __declspec( dllexport ) void Finalize(HMODULE instance, UINT id); - __declspec( dllexport ) double Update2(UINT id); - __declspec( dllexport ) UINT GetPluginVersion(); - __declspec( dllexport ) LPCTSTR GetPluginAuthor(); -} - -enum InfoType -{ - INFOTYPE_FOLDERSIZE, - INFOTYPE_FILECOUNT, - INFOTYPE_FOLDERCOUNT, - - INFOTYPE_COUNT + MEASURE_FILECOUNT, + MEASURE_FOLDERCOUNT, + MEASURE_FOLDERSIZE }; -struct MeasureInfo +struct MeasureData { - InfoType Type; - std::wstring Section; - FolderInfo* Folder; + LPCWSTR section; + CFolderInfo* folder; + MeasureType type; - MeasureInfo(const wchar_t* aSection) + MeasureData(LPCWSTR section) : + section(section), + folder(), + type(MEASURE_FILECOUNT) { - Section = aSection; - Type = INFOTYPE_COUNT; } }; -/* Couple of globals */ -typedef std::map MeasureIdMap; // measure ID -> MeasureInfo -static MeasureIdMap sMeasures; -typedef std::map FolderInfoMap; // FolderInfo -> ref count -static FolderInfoMap sFolderRefCount; +std::vector g_Measures; -static MeasureInfo* GetMeasureInfo(UINT aId) +PLUGIN_EXPORT void Initialize(void** data, void* rm) { - MeasureIdMap::iterator it = sMeasures.find(aId); - if (it != sMeasures.end()) { - return it->second; - } - return NULL; + MeasureData* measure = new MeasureData(RmGetMeasureName(rm)); + *data = measure; + g_Measures.push_back(measure); } -static FolderInfo* GetFolderInfo(const wchar_t* aPath, const wchar_t* aIniPath) +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) { - int pathLen = wcslen(aPath); - if (pathLen > 2 && L'[' == aPath[0] && L']' == aPath[pathLen - 1]) { - MeasureIdMap::iterator it; - for (it = sMeasures.begin(); it != sMeasures.end(); it++) { - if (wcsncmp(&aPath[1], it->second->Section.c_str(), pathLen - 2) == 0) { - sFolderRefCount[it->second->Folder] = sFolderRefCount[it->second->Folder] + 1; - return it->second->Folder; + MeasureData* measure = (MeasureData*)data; + + LPCWSTR str = RmReadString(rm, L"Folder", L"", FALSE); + if (*str == L'[') + { + CFolderInfo* oldFolder = measure->folder; + measure->folder = NULL; + + int len = wcslen(str); + for (auto iter = g_Measures.cbegin(); iter != g_Measures.cend(); ++iter) + { + if (wcsncmp(&str[1], (*iter)->section, len - 2) == 0) + { + measure->folder = (*iter)->folder; + measure->folder->AddInstance(); } } - return NULL; - } - FolderInfo* folderInfo = new FolderInfo(aPath, aIniPath); - sFolderRefCount[folderInfo] = 1; - return folderInfo; -} - -/* - This function is called when the measure is initialized. - The function must return the maximum value that can be measured. - The return value can also be 0, which means that Rainmeter will - track the maximum value automatically. The parameters for this - function are: - - instance The instance of this DLL - iniFile The name of the ini-file (usually Rainmeter.ini) - section The name of the section in the ini-file for this measure - id The identifier for the measure. This is used to identify the measures that use the same plugin. -*/ -UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id) -{ - MeasureInfo* measureInfo = new MeasureInfo(section); - - const wchar_t* strFolder = ReadConfigString(section, L"Folder", L""); - measureInfo->Folder = GetFolderInfo(strFolder, iniFile); - - const wchar_t* strInfoType = ReadConfigString(section, L"InfoType", L""); - if (_wcsicmp(strInfoType, L"FolderSize") == 0 || _wcsicmp(strInfoType, L"FolderSizeStr") == 0) { - measureInfo->Type = INFOTYPE_FOLDERSIZE; - } - else if (_wcsicmp(strInfoType, L"FolderCount") == 0 || _wcsicmp(strInfoType, L"FolderCountStr") == 0) { - measureInfo->Type = INFOTYPE_FOLDERCOUNT; - } - else if (_wcsicmp(strInfoType, L"FileCount") == 0 || _wcsicmp(strInfoType, L"FileCountStr") == 0) { - measureInfo->Type = INFOTYPE_FILECOUNT; - } - - if (measureInfo->Folder) { - const wchar_t* strRegExpFilter = ReadConfigString(section, L"RegExpFilter", L""); - if (strRegExpFilter && wcslen(strRegExpFilter) > 0) { - measureInfo->Folder->SetRegExpFilter(strRegExpFilter); + if (oldFolder) + { + oldFolder->RemoveInstance(); } - - const wchar_t* strIncludeSubFolders = ReadConfigString(section, L"IncludeSubFolders", L""); - if (wcscmp(strIncludeSubFolders, L"1") == 0) { - measureInfo->Folder->IncludeSubFolders(true); - } - - const wchar_t* strShowHiddenFiles = ReadConfigString(section, L"IncludeHiddenFiles", L""); - if (wcscmp(strShowHiddenFiles, L"1") == 0) { - measureInfo->Folder->IncludeHiddenFiles(true); - } - - const wchar_t* strShowSystemFiles = ReadConfigString(section, L"IncludeSystemFiles", L""); - if (wcscmp(strShowSystemFiles, L"1") == 0) { - measureInfo->Folder->IncludeSystemFiles(true); - } - - measureInfo->Folder->Update(); } - - sMeasures[id] = measureInfo; - - return 0; -} - -/* - This function is called when new value should be measured. - The function returns the new value. -*/ -double Update2(UINT id) -{ - MeasureInfo* measureInfo = sMeasures[id]; - if (!measureInfo->Folder) { - return 0; - } - - DWORD now = GetTickCount(); - if (now - measureInfo->Folder->GetLastUpdateTime() > UPDATE_TIME_MIN_MS) { - measureInfo->Folder->Update(); - } - - switch (measureInfo->Type) + else if (*str) { - case INFOTYPE_FOLDERSIZE: - return (double)measureInfo->Folder->GetSize(); - break; + LPCWSTR path = RmPathToAbsolute(rm, str); + if (!measure->folder || wcscmp(measure->folder->GetPath(), path) != 0) + { + if (measure->folder) + { + measure->folder->RemoveInstance(); + } - case INFOTYPE_FILECOUNT: - return measureInfo->Folder->GetFileCount(); - break; + measure->folder = new CFolderInfo(path); - case INFOTYPE_FOLDERCOUNT: - return measureInfo->Folder->GetFolderCount(); - break; - } - return 0; -} - -/* - If the measure needs to free resources before quitting. - The plugin can export Finalize function, which is called - when Rainmeter quits (or refreshes). -*/ -void Finalize(HMODULE instance, UINT id) -{ - MeasureIdMap::iterator itm = sMeasures.find(id); - if (itm == sMeasures.end()) { - return; - } - - MeasureInfo* measureInfo = itm->second; - sMeasures.erase(itm); - FolderInfoMap::iterator itf = sFolderRefCount.find(measureInfo->Folder); - if (itf != sFolderRefCount.end()) { - if (1 == itf->second) { - delete itf->first; - sFolderRefCount.erase(itf); - } - else { - itf->second = itf->second - 1; + str = RmReadString(rm, L"RegExpFilter", L""); + if (*str) + { + measure->folder->SetRegExpFilter(str); + } + + measure->folder->IncludeSubFolders((bool)RmReadInt(rm, L"IncludeSubFolders", 0)); + measure->folder->IncludeHiddenFiles((bool)RmReadInt(rm, L"IncludeHiddenFiles", 0)); + measure->folder->IncludeSystemFiles((bool)RmReadInt(rm, L"IncludeSystemFiles", 0)); } } - delete measureInfo; + + str = RmReadString(rm, L"InfoType", L""); + if (_wcsicmp(str, L"FolderSize") == 0 || _wcsicmp(str, L"FolderSizeStr") == 0) + { + measure->type = MEASURE_FOLDERSIZE; + } + else if (_wcsicmp(str, L"FolderCount") == 0 || _wcsicmp(str, L"FolderCountStr") == 0) + { + measure->type = MEASURE_FOLDERCOUNT; + } + else if (_wcsicmp(str, L"FileCount") == 0 || _wcsicmp(str, L"FileCountStr") == 0) + { + measure->type = MEASURE_FILECOUNT; + } } -/* - Returns the version number of the plugin. The value - can be calculated like this: Major * 1000 + Minor. - So, e.g. 2.31 would be 2031. -*/ -UINT GetPluginVersion() +PLUGIN_EXPORT double Update(void* data) { - return 0003; + MeasureData* measure = (MeasureData*)data; + if (!measure->folder) + { + return 0.0; + } + + measure->folder->Update(); + + switch (measure->type) + { + case MEASURE_FOLDERSIZE: + return measure->folder->GetSize(); + + case MEASURE_FILECOUNT: + return measure->folder->GetFileCount(); + + case MEASURE_FOLDERCOUNT: + return measure->folder->GetFolderCount(); + } + + return 0.0; } -/* - Returns the author of the plugin for the about dialog. -*/ -LPCTSTR GetPluginAuthor() +PLUGIN_EXPORT void Finalize(void* data) { - return L"Elestel"; + MeasureData* measure = (MeasureData*)data; + + if (measure->folder) + { + measure->folder->RemoveInstance(); + } + + delete measure; + + std::vector::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); + g_Measures.erase(iter); } diff --git a/Plugins/PluginFolderInfo/PluginFolderInfo.rc b/Plugins/PluginFolderInfo/PluginFolderInfo.rc index af3daeb2..9ceccc25 100644 --- a/Plugins/PluginFolderInfo/PluginFolderInfo.rc +++ b/Plugins/PluginFolderInfo/PluginFolderInfo.rc @@ -1,10 +1,5 @@ -// Microsoft Developer Studio generated resource script. -// - +#include #include "../../Version.h" -#define APSTUDIO_READONLY_SYMBOLS -#include "windows.h" -#undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // @@ -12,37 +7,34 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,3,0,0 + FILEVERSION 1,0,0,0 PRODUCTVERSION PRODUCTVER FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 + FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT_UNKNOWN -BEGIN +{ BLOCK "StringFileInfo" - BEGIN + { BLOCK "040904E4" - BEGIN - VALUE "FileDescription", "FolderInfo Plugin for Rainmeter" - VALUE "FileVersion", "0.3.0.0" - VALUE "InternalName", "FolderInfo" - VALUE "LegalCopyright", "Copyright (C) 2010 - Elestel" - VALUE "OriginalFilename", "FolderInfo.dll" + { + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", "© 2010 - Elesetel" VALUE "ProductName", "Rainmeter" #ifdef _WIN64 VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" #else VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" #endif //_WIN64 - END - END + } + } BLOCK "VarFileInfo" - BEGIN + { VALUE "Translation", 0x409, 1252 - END -END + } +}