From 415c905d0aa87556e989095da11a3e93c7857958 Mon Sep 17 00:00:00 2001 From: spx Date: Fri, 2 Apr 2010 01:35:53 +0000 Subject: [PATCH] - Fixed a problem that !RainmeterQuit isn't executed when no meter window is running. - Fixed a problem that StyleTemplate affects to Meters which have no relation. - Added a workaround to avoid the "IniFileMapping" function when reading skins. - Some small code cosmetics. --- Library/ConfigParser.cpp | 130 ++++++++++++++++++++++++++++++++++++--- Library/ConfigParser.h | 6 ++ Library/MeasureCalc.cpp | 4 +- Library/MeterWindow.cpp | 22 +------ Library/MeterWindow.h | 3 - Library/Rainmeter.cpp | 25 +++++--- Library/Rainmeter.h | 2 +- Library/TrayWindow.cpp | 8 +++ Library/TrayWindow.h | 1 + 9 files changed, 157 insertions(+), 44 deletions(-) diff --git a/Library/ConfigParser.cpp b/Library/ConfigParser.cpp index af56dfa8..411d55d0 100644 --- a/Library/ConfigParser.cpp +++ b/Library/ConfigParser.cpp @@ -78,8 +78,15 @@ void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterW // Set the SCREENAREA/WORKAREA variables for present monitor SetAutoSelectedMonitorVariables(meterWindow); + if (meterWindow) + { + GetIniFileMappingList(); + } + ReadIniFile(m_Filename); ReadVariables(); + + m_IniFileMappings.clear(); } /* @@ -288,7 +295,6 @@ void CConfigParser::SetMonitorVariable(const std::wstring& strVariable, const st */ void CConfigParser::SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow) { - if (meterWindow) { if (CSystem::GetMonitorCount() > 0) @@ -798,17 +804,36 @@ Color CConfigParser::ParseColor(LPCTSTR string) */ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth) { - if (CRainmeter::GetDebug()) - { - DebugLog(L"Reading file: %s", iniFile.c_str()); - } - if (depth > 100) // Is 100 enough to assume the include loop never ends? { MessageBox(NULL, L"It looks like you've made an infinite\nloop with the @include statements.\nPlease check your skin.", L"Rainmeter", MB_OK | MB_ICONERROR); return; } + // Avoid "IniFileMapping" + std::wstring iniRead = GetAlternateFileName(iniFile); + bool alternate = false; + + if (!iniRead.empty()) + { + // Copy iniFile to temporary directory + if (CRainmeter::CopyFiles(iniFile, iniRead)) + { + if (CRainmeter::GetDebug()) DebugLog(L"Reading file: %s (Alternate: %s)", iniFile.c_str(), iniRead.c_str()); + alternate = true; + } + else // copy failed + { + DeleteFile(iniRead.c_str()); + } + } + + if (!alternate) + { + if (CRainmeter::GetDebug()) DebugLog(L"Reading file: %s", iniFile.c_str()); + iniRead = iniFile; + } + // Get all the sections (i.e. different meters) WCHAR* items = new WCHAR[MAX_LINE_LENGTH]; int size = MAX_LINE_LENGTH; @@ -817,8 +842,13 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth) while(true) { items[0] = 0; - int res = GetPrivateProfileString( NULL, NULL, NULL, items, size, iniFile.c_str()); - if (res == 0) { delete [] items; return; } // File not found + int res = GetPrivateProfileString( NULL, NULL, NULL, items, size, iniRead.c_str()); + if (res == 0) // File not found + { + delete [] items; + if (alternate) DeleteFile(iniRead.c_str()); + return; + } if (res < size - 2) break; // Fits in the buffer delete [] items; @@ -850,7 +880,7 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth) while(true) { items[0] = 0; - int res = GetPrivateProfileString((*iter).first.c_str(), NULL, NULL, items, size, iniFile.c_str()); + int res = GetPrivateProfileString((*iter).first.c_str(), NULL, NULL, items, size, iniRead.c_str()); if (res < size - 2) break; // Fits in the buffer delete [] items; @@ -866,7 +896,7 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth) while(true) { buffer[0] = 0; - int res = GetPrivateProfileString((*iter).first.c_str(), strKey.c_str(), L"", buffer, bufferSize, iniFile.c_str()); + int res = GetPrivateProfileString((*iter).first.c_str(), strKey.c_str(), L"", buffer, bufferSize, iniRead.c_str()); if (res < bufferSize - 2) break; // Fits in the buffer delete [] buffer; @@ -895,6 +925,7 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth) } delete [] buffer; delete [] items; + if (alternate) DeleteFile(iniRead.c_str()); } //============================================================================== @@ -978,3 +1009,82 @@ std::vector CConfigParser::GetKeys(const std::wstring& strSection) return std::vector(); } +void CConfigParser::GetIniFileMappingList() +{ + HKEY hKey; + LONG ret; + + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", 0, KEY_ENUMERATE_SUB_KEYS, &hKey); + if (ret == ERROR_SUCCESS) + { + WCHAR buffer[MAX_PATH]; + DWORD index = 0, cch = MAX_PATH; + + while (true) + { + ret = RegEnumKeyEx(hKey, index++, buffer, &cch, NULL, NULL, NULL, NULL); + if (ret == ERROR_NO_MORE_ITEMS) break; + + if (ret == ERROR_SUCCESS) + { + m_IniFileMappings.push_back(buffer); + } + cch = MAX_PATH; + } + RegCloseKey(hKey); + } +} + +std::wstring CConfigParser::GetAlternateFileName(const std::wstring &iniFile) +{ + std::wstring alternate; + + if (!m_IniFileMappings.empty()) + { + std::wstring::size_type pos = iniFile.find_last_of(L'\\'); + std::wstring filename; + + if (pos != std::wstring::npos) + { + filename = iniFile.substr(pos + 1); + } + else + { + filename = iniFile; + } + + for (size_t i = 0; i < m_IniFileMappings.size(); ++i) + { + if (wcsicmp(m_IniFileMappings[i].c_str(), filename.c_str()) == 0) + { + WCHAR buffer[4096]; + + GetTempPath(4096, buffer); + alternate = buffer; + if (GetTempFileName(alternate.c_str(), L"cfg", 0, buffer) != 0) + { + alternate = buffer; + + std::wstring tmp = GetAlternateFileName(alternate); + if (tmp.empty()) + { + return alternate; + } + else // alternate is reserved + { + DeleteFile(alternate.c_str()); + return tmp; + } + } + else // failed + { + DebugLog(L"Unable to create a temporary file to: %s", alternate.c_str()); + alternate.clear(); + break; + } + } + } + } + + return alternate; +} diff --git a/Library/ConfigParser.h b/Library/ConfigParser.h index 97117f3f..f8c47466 100644 --- a/Library/ConfigParser.h +++ b/Library/ConfigParser.h @@ -41,6 +41,7 @@ public: void AddMeasure(CMeasure* pMeasure); void SetVariable(const std::wstring& strVariable, const std::wstring& strValue); void SetStyleTemplate(const std::wstring& strStyle) { m_StyleTemplate = strStyle; } + void ResetStyleTemplate() { m_StyleTemplate.clear(); } void ResetVariables(CRainmeter* pRainmeter, CMeterWindow* meterWindow = NULL); @@ -76,6 +77,9 @@ private: void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow); + void GetIniFileMappingList(); + std::wstring GetAlternateFileName(const std::wstring& iniFile); + static void SetMultiMonitorVariables(bool reset); static void SetMonitorVariable(const std::wstring& strVariable, const std::wstring& strValue); @@ -91,6 +95,8 @@ private: stdext::hash_map > m_Keys; stdext::hash_map m_Values; + std::vector m_IniFileMappings; + static std::map c_MonitorVariables; }; diff --git a/Library/MeasureCalc.cpp b/Library/MeasureCalc.cpp index 220edc48..739f3573 100644 --- a/Library/MeasureCalc.cpp +++ b/Library/MeasureCalc.cpp @@ -148,9 +148,9 @@ void CMeasureCalc::RandomFormulaReplace() //To implement random numbers the word "Random" in the string //formula is being replaced by the random number value m_Formula = m_FormulaHolder; - int loc = m_Formula.find(L"Random"); + std::wstring::size_type loc = m_Formula.find(L"Random"); - while(loc > -1) + while(loc != std::wstring::npos) { int range = (m_HighBound - m_LowBound); srand((unsigned) rand()); diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index f45fe81a..e82ae7e2 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -786,11 +786,6 @@ void CMeterWindow::RunBang(BANGCOMMAND bang, const WCHAR* arg) } break; - case BANG_QUIT: - // Quit needs to be delayed since it crashes if done during Update() - PostMessage(m_Window, WM_DELAYED_QUIT, (WPARAM)NULL, (LPARAM)NULL); - break; - case BANG_SETVARIABLE: pos = wcschr(arg, ' '); if (pos != NULL) @@ -1751,6 +1746,8 @@ void CMeterWindow::ReadSkin() meter->ReadConfig(strSection.c_str()); m_Meters.push_back(meter); + + m_Parser.ResetStyleTemplate(); } } catch (CError& error) @@ -2171,6 +2168,7 @@ void CMeterWindow::Update(bool nodraw) if ((*j)->HasDynamicVariables()) { (*j)->ReadConfig((*j)->GetName()); + m_Parser.ResetStyleTemplate(); } (*j)->Update(); } @@ -3871,7 +3869,6 @@ LRESULT CALLBACK CMeterWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR MESSAGE(OnDelayedExecute, WM_DELAYED_EXECUTE) MESSAGE(OnDelayedRefresh, WM_DELAYED_REFRESH) MESSAGE(OnDelayedMove, WM_DELAYED_MOVE) - MESSAGE(OnDelayedQuit, WM_DELAYED_QUIT) MESSAGE(OnSettingChange, WM_SETTINGCHANGE) MESSAGE(OnDisplayChange, WM_DISPLAYCHANGE) END_MESSAGEPROC @@ -3949,19 +3946,6 @@ LRESULT CMeterWindow::OnDelayedMove(WPARAM wParam, LPARAM lParam) return 0; } -/* -** OnDelayedQuit -** -** Handles delayed quit -** -*/ -LRESULT CMeterWindow::OnDelayedQuit(WPARAM wParam, LPARAM lParam) -{ - if (Rainmeter->GetDummyLitestep()) PostQuitMessage(0); - quitModule(Rainmeter->GetInstance()); - return 0; -} - /* ** OnCopyData ** diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index 014cf4f5..8a51c9db 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -36,7 +36,6 @@ #define WM_DELAYED_EXECUTE WM_APP + 0 #define WM_DELAYED_REFRESH WM_APP + 1 -#define WM_DELAYED_QUIT WM_APP + 2 #define WM_DELAYED_MOVE WM_APP + 3 enum MOUSE @@ -109,7 +108,6 @@ enum BANGCOMMAND BANG_ABOUT, BANG_MOVEMETER, BANG_PLUGIN, - BANG_QUIT, BANG_SETVARIABLE }; @@ -213,7 +211,6 @@ protected: LRESULT OnDelayedExecute(WPARAM wParam, LPARAM lParam); LRESULT OnDelayedRefresh(WPARAM wParam, LPARAM lParam); LRESULT OnDelayedMove(WPARAM wParam, LPARAM lParam); - LRESULT OnDelayedQuit(WPARAM wParam, LPARAM lParam); LRESULT OnSettingChange(WPARAM wParam, LPARAM lParam); LRESULT OnDisplayChange(WPARAM wParam, LPARAM lParam); diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index 2e0f9bd5..fcbbef16 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -637,7 +637,11 @@ void RainmeterPluginBang(HWND, const char* arg) */ void RainmeterQuit(HWND, const char* arg) { - BangWithArgs(BANG_QUIT, ConvertToWide(arg).c_str(), 0); + if (Rainmeter) + { + // Quit needs to be delayed since it crashes if done during Update() + PostMessage(Rainmeter->GetTrayWindow()->GetWindow(), WM_DELAYED_QUIT, (WPARAM)NULL, (LPARAM)NULL); + } } /* @@ -1190,18 +1194,20 @@ int CRainmeter::CompareVersions(std::wstring strA, std::wstring strB) ** Copies files and folders from one location to another. ** */ -bool CRainmeter::CopyFiles(std::wstring strFrom, std::wstring strTo, bool bMove) +bool CRainmeter::CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove) { + std::wstring tmpFrom(strFrom), tmpTo(strTo); + // The strings must end with double nul - strFrom.append(L"0"); - strFrom[strFrom.size() - 1] = L'\0'; - strTo.append(L"0"); - strTo[strTo.size() - 1] = L'\0'; + tmpFrom.append(L"0"); + tmpFrom[tmpFrom.size() - 1] = L'\0'; + tmpTo.append(L"0"); + tmpTo[tmpTo.size() - 1] = L'\0'; SHFILEOPSTRUCT fo = {0}; fo.wFunc = bMove ? FO_MOVE : FO_COPY; - fo.pFrom = strFrom.c_str(); - fo.pTo = strTo.c_str(); + fo.pFrom = tmpFrom.c_str(); + fo.pTo = tmpTo.c_str(); fo.fFlags = FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO; int result = SHFileOperation(&fo); @@ -1774,7 +1780,8 @@ BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg, } else if (wcsicmp(bang.c_str(), L"!RainmeterQuit") == 0) { - BangWithArgs(BANG_QUIT, arg.c_str(), 0); + // Quit needs to be delayed since it crashes if done during Update() + PostMessage(m_TrayWindow->GetWindow(), WM_DELAYED_QUIT, (WPARAM)NULL, (LPARAM)NULL); } else if (wcsicmp(bang.c_str(), L"!Execute") == 0) { diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index 8ce02898..a693bc18 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -179,6 +179,7 @@ public: static PLATFORM IsNT(); static std::wstring ExtractPath(const std::wstring& strFilePath); static void ExpandEnvironmentVariables(std::wstring& strPath); + static bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove = false); private: void CreateMeterWindow(std::wstring path, std::wstring config, std::wstring iniFile); @@ -197,7 +198,6 @@ private: HMENU CreateMonitorMenu(CMeterWindow* meterWindow); void CreateDefaultConfigFile(std::wstring strFile); void TestSettingsFile(bool bDefaultIniLocation); - bool CopyFiles(std::wstring strFrom, std::wstring strTo, bool bMove = false); void CheckSkinVersions(); int CompareVersions(std::wstring strA, std::wstring strB); diff --git a/Library/TrayWindow.cpp b/Library/TrayWindow.cpp index bf2ec664..59322b14 100644 --- a/Library/TrayWindow.cpp +++ b/Library/TrayWindow.cpp @@ -631,6 +631,14 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } return 0; + case WM_DELAYED_QUIT: + if (Rainmeter) + { + if (Rainmeter->GetDummyLitestep()) PostQuitMessage(0); + quitModule(Rainmeter->GetInstance()); + } + return 0; + case WM_DESTROY: if (Rainmeter->GetDummyLitestep()) PostQuitMessage(0); break; diff --git a/Library/TrayWindow.h b/Library/TrayWindow.h index 5db8dcd6..ecc5f7c3 100644 --- a/Library/TrayWindow.h +++ b/Library/TrayWindow.h @@ -25,6 +25,7 @@ #include "Measure.h" #define WM_DELAYED_REFRESH_ALL WM_APP + 0 +#define WM_DELAYED_QUIT WM_APP + 1 #define WM_NOTIFYICON WM_USER + 101 #define TRAYICON_SIZE 16