From 4b307145205f8aef34467317f696c2b82dbd26f5 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Sun, 30 Jan 2011 10:39:10 +0000 Subject: [PATCH] - Fixed: Rainmeter crashes if the Lua GetStringValue() function returns an invalid value - Fixed: Rainmeter crashes on initialization if Lua is invalid (e.g. syntax error) - Fixed: Rainmeter crashes on mouse action if Lua file is not initialized - Fixed: Measure=SCRIPT tries to process mouse actions even if corresponding function does not exist in the Lua file causing log to fill with 'nil value' warnings - Mainly cosmetic changes to logging of erros in Measure=SCRIPT --- Library/MeasureScript.cpp | 200 ++++++++++++++----------- Library/lua/LuaManager.cpp | 13 +- Library/lua/LuaManager.h | 2 +- Library/lua/LuaScript.cpp | 29 ++-- Library/lua/glue/lua_rainmeter_ext.cpp | 2 +- 5 files changed, 128 insertions(+), 118 deletions(-) diff --git a/Library/MeasureScript.cpp b/Library/MeasureScript.cpp index edf2a3bc..f043f523 100644 --- a/Library/MeasureScript.cpp +++ b/Library/MeasureScript.cpp @@ -22,7 +22,6 @@ CMeasureScript::CMeasureScript(CMeterWindow* meterWindow) : CMeasure(meterWindow CMeasureScript::~CMeasureScript() { delete m_pLuaScript; - } void CMeasureScript::Initialize() @@ -92,26 +91,33 @@ const WCHAR* CMeasureScript::GetStringValue(AUTOSCALE autoScale, double scale, i return CMeasure::GetStringValue(autoScale, scale, decimals, percentual); } -static void stackDump (lua_State *L) { - int i=lua_gettop(L); - LuaManager::LuaLog(" ---------------- Stack Dump ----------------" ); - while( i ) { - int t = lua_type(L, i); - switch (t) { - case LUA_TSTRING: - LuaManager::LuaLog("%d:`%s'", i, lua_tostring(L, i)); - break; - case LUA_TBOOLEAN: - LuaManager::LuaLog("%d: %s",i,lua_toboolean(L, i) ? "true" : "false"); - break; - case LUA_TNUMBER: - LuaManager::LuaLog("%d: %g", i, lua_tonumber(L, i)); - break; - default: LuaManager::LuaLog("%d: %s", i, lua_typename(L, t)); break; - } - i--; - } - LuaManager::LuaLog("--------------- Stack Dump Finished ---------------" ); +static void stackDump(lua_State *L) +{ + int i = lua_gettop(L); + LuaManager::LuaLog(LOG_DEBUG, " ---------------- Stack Dump ----------------" ); + while(i) + { + int t = lua_type(L, i); + switch (t) + { + case LUA_TSTRING: + LuaManager::LuaLog(LOG_DEBUG, "%d:`%s'", i, lua_tostring(L, i)); + break; + + case LUA_TBOOLEAN: + LuaManager::LuaLog(LOG_DEBUG, "%d: %s",i,lua_toboolean(L, i) ? "true" : "false"); + break; + + case LUA_TNUMBER: + LuaManager::LuaLog(LOG_DEBUG, "%d: %g", i, lua_tonumber(L, i)); + break; + + default: + LuaManager::LuaLog(LOG_DEBUG, "%d: %s", i, lua_typename(L, t)); break; + } + i--; + } + LuaManager::LuaLog(LOG_DEBUG, "--------------- Stack Dump Finished ---------------" ); } @@ -123,98 +129,97 @@ static void stackDump (lua_State *L) { */ void CMeasureScript::ReadConfig(CConfigParser& parser, const WCHAR* section) { - CMeasure::ReadConfig(parser, section); std::string strScriptFile = ConvertToAscii(parser.ReadString(section, L"ScriptFile", L"").c_str()); std::string strTableName = ConvertToAscii(parser.ReadString(section, L"TableName", L"").c_str()); - if(strScriptFile.empty() == false) + if (strScriptFile.empty() == false) { - - if(strTableName.empty() == false) + if (strTableName.empty() == false) { lua_State* L = LuaManager::GetState(); + m_pLuaScript = new LuaScript(LuaManager::GetState(), strScriptFile.c_str(), strTableName.c_str()); - m_bUpdateDefined = m_pLuaScript->FunctionExists(g_strUpdateFunction); - m_bInitializeDefined = m_pLuaScript->FunctionExists(g_strInitFunction); - m_bGetValueDefined = m_pLuaScript->FunctionExists(g_strGetValueFunction); - m_bGetStringValueDefined = m_pLuaScript->FunctionExists(g_strGetStringValueFunction); - - - m_pLuaScript->PushTable(); - - // Push the variable name we want to put a value in. - lua_pushstring(L, "SELF"); - // Push the value - tolua_pushusertype(L, this, "CMeasure"); - // Bind the variable - lua_settable(L, -3); - - // Push the variable name we want to put a value in. - lua_pushstring(L, "SKIN"); - // Push the value - tolua_pushusertype(L, m_MeterWindow, "CMeterWindow"); - // Bind the variable - lua_settable(L, -3); - - // Push the variable name we want to put a value in. - lua_pushstring(L, "RAINMETER"); - // Push the value - tolua_pushusertype(L, m_MeterWindow->GetMainObject(), "CRainmeter"); - // Bind the variable - lua_settable(L, -3); - - // Look i nthe properties table for values to read from the section. - lua_getfield(L, -1, "PROPERTIES"); - if(lua_isnil(L, -1) == 0) + if (m_pLuaScript->IsInitialized()) { - lua_pushnil(L); + m_bUpdateDefined = m_pLuaScript->FunctionExists(g_strUpdateFunction); + m_bInitializeDefined = m_pLuaScript->FunctionExists(g_strInitFunction); + m_bGetValueDefined = m_pLuaScript->FunctionExists(g_strGetValueFunction); + m_bGetStringValueDefined = m_pLuaScript->FunctionExists(g_strGetStringValueFunction); - while(lua_next(L, -2)) - { - lua_pop(L, 1); + m_pLuaScript->PushTable(); - const char* strKey = lua_tostring(L, -1); + // Push the variable name we want to put a value in. + lua_pushstring(L, "SELF"); + // Push the value + tolua_pushusertype(L, this, "CMeasure"); + // Bind the variable + lua_settable(L, -3); - std::wstring wstrKey = ConvertToWide(strKey); - std::wstring wstrValue = parser.ReadString(section, wstrKey.c_str(), L"").c_str(); - - if( !wstrValue.empty() ) + // Push the variable name we want to put a value in. + lua_pushstring(L, "SKIN"); + // Push the value + tolua_pushusertype(L, m_MeterWindow, "CMeterWindow"); + // Bind the variable + lua_settable(L, -3); + + // Push the variable name we want to put a value in. + lua_pushstring(L, "RAINMETER"); + // Push the value + tolua_pushusertype(L, m_MeterWindow->GetMainObject(), "CRainmeter"); + // Bind the variable + lua_settable(L, -3); + + // Look i nthe properties table for values to read from the section. + lua_getfield(L, -1, "PROPERTIES"); + if (lua_isnil(L, -1) == 0) + { + lua_pushnil(L); + + while(lua_next(L, -2)) { - const wchar_t* wstrValue2 = wstrValue.c_str(); - std::string strStrVal = ConvertToAscii(wstrValue2); - const char* strValue = strStrVal.c_str(); + lua_pop(L, 1); + + const char* strKey = lua_tostring(L, -1); + + std::wstring wstrKey = ConvertToWide(strKey); + std::wstring wstrValue = parser.ReadString(section, wstrKey.c_str(), L"").c_str(); - lua_pushstring(L,strValue); - lua_settable(L, -3); + if (!wstrValue.empty()) + { + const wchar_t* wstrValue2 = wstrValue.c_str(); + std::string strStrVal = ConvertToAscii(wstrValue2); + const char* strValue = strStrVal.c_str(); + + lua_pushstring(L,strValue); + lua_settable(L, -3); + + lua_pushstring(L,strKey); + } - lua_pushstring(L,strKey); } - } - } - // Pop PROPERTIES table - lua_pop(L, 1); + // Pop PROPERTIES table + lua_pop(L, 1); - // Pop the table - lua_pop(L, 1); + // Pop the table + lua_pop(L, 1); + } } else { - LuaManager::LuaLog("%s : TableName missing.", m_ANSIName.c_str()); + LuaManager::LuaLog(LOG_ERROR, "Script: TableName missing in %s.", m_ANSIName.c_str()); } } else { - LuaManager::LuaLog("%s : ScriptFile missing.", m_ANSIName.c_str()); + LuaManager::LuaLog(LOG_ERROR, "Script: ScriptFile missing in %s.", m_ANSIName.c_str()); } - } void CMeasureScript::RunFunctionWithMeter(const char* p_strFunction, CMeter* p_pMeter) { - // Get the Lua State lua_State* L = m_pLuaScript->GetState(); @@ -222,14 +227,18 @@ void CMeasureScript::RunFunctionWithMeter(const char* p_strFunction, CMeter* p_p m_pLuaScript->PushTable(); // Push the function onto the stack - lua_getfield(L,-1, p_strFunction); + lua_getfield(L, -1, p_strFunction); - // Push the Meter - tolua_pushusertype(L, (void*) p_pMeter ,"CMeter"); - - if( lua_pcall(L, 1, 0, 0) ) + // Check if the function exists + if (!lua_isnil(L, -1)) { - LuaManager::ReportErrors(L); + // Push the Meter + tolua_pushusertype(L, (void*) p_pMeter, "CMeter"); + + if (lua_pcall(L, 1, 0, 0)) + { + LuaManager::ReportErrors(L); + } } // Clean up @@ -238,36 +247,45 @@ void CMeasureScript::RunFunctionWithMeter(const char* p_strFunction, CMeter* p_p void CMeasureScript::MeterMouseEvent(CMeter* p_pMeter, MOUSE p_eMouse) { - switch (p_eMouse) + if (m_pLuaScript->IsInitialized()) { + switch (p_eMouse) + { case MOUSE_LMB_DOWN: RunFunctionWithMeter("LeftMouseDown", p_pMeter); break; + case MOUSE_LMB_UP: RunFunctionWithMeter("LeftMouseUp", p_pMeter); break; + case MOUSE_LMB_DBLCLK: RunFunctionWithMeter("LeftMouseDoubleClick", p_pMeter); break; + case MOUSE_RMB_DOWN: RunFunctionWithMeter("RightMouseDown", p_pMeter); break; + case MOUSE_RMB_UP: RunFunctionWithMeter("RightMouseUp", p_pMeter); break; + case MOUSE_RMB_DBLCLK: RunFunctionWithMeter("RightMouseDoubleClick", p_pMeter); break; + case MOUSE_MMB_DOWN: RunFunctionWithMeter("MiddleMouseDown", p_pMeter); break; + case MOUSE_MMB_UP: RunFunctionWithMeter("MiddleMouseUp", p_pMeter); break; + case MOUSE_MMB_DBLCLK: RunFunctionWithMeter("MiddleMouseDoubleClick", p_pMeter); break; + } } - - } \ No newline at end of file diff --git a/Library/lua/LuaManager.cpp b/Library/lua/LuaManager.cpp index 0b05d1cc..dac3b79c 100644 --- a/Library/lua/LuaManager.cpp +++ b/Library/lua/LuaManager.cpp @@ -12,7 +12,6 @@ #include "lua_rainmeter_ext.h" - bool LuaManager::m_bInitialized = false; lua_State* LuaManager::m_pState = 0; @@ -20,7 +19,6 @@ void LuaManager::Init() { if(m_pState == 0) { - // initialize Lua m_pState = lua_open(); @@ -36,7 +34,6 @@ void LuaManager::Init() //tolua_meter_image_open(m_pState); luaopen_rainmeter_ext(m_pState); - } } @@ -47,13 +44,11 @@ void LuaManager::CleanUp() void LuaManager::ReportErrors(lua_State * L) { - - LuaLog("Lua Error: %s", lua_tostring(L, -1)); + LuaLog(LOG_ERROR, "Script: %s", lua_tostring(L, -1)); lua_pop(L, 1); - } -void LuaManager::LuaLog(const char* format, ... ) +void LuaManager::LuaLog(int nLevel, const char* format, ... ) { char buffer[4096]; va_list args; @@ -66,7 +61,7 @@ void LuaManager::LuaLog(const char* format, ... ) _vsnprintf_s( buffer, _TRUNCATE, format, args ); if (errno != 0) { - _snprintf_s(buffer, _TRUNCATE, "LuaLog internal error: %s", format); + _snprintf_s(buffer, _TRUNCATE, "Script: LuaLog internal error: %s", format); } _set_invalid_parameter_handler(oldHandler); @@ -79,6 +74,6 @@ void LuaManager::LuaLog(const char* format, ... ) std::wstring str = ConvertToWide(buffer); - LSLog(LOG_NOTICE, L"Lua", str.c_str()); + LSLog(nLevel, L"Rainmeter", str.c_str()); va_end(args); } \ No newline at end of file diff --git a/Library/lua/LuaManager.h b/Library/lua/LuaManager.h index e6e06e2a..9441a057 100644 --- a/Library/lua/LuaManager.h +++ b/Library/lua/LuaManager.h @@ -16,7 +16,7 @@ public: static void ReportErrors(lua_State * L); - static void LuaLog(const char* format, ... ); + static void LuaLog(int nLevel, const char* format, ... ); protected: diff --git a/Library/lua/LuaScript.cpp b/Library/lua/LuaScript.cpp index 52340828..5b7eb9db 100644 --- a/Library/lua/LuaScript.cpp +++ b/Library/lua/LuaScript.cpp @@ -9,7 +9,7 @@ LuaScript::LuaScript(lua_State* p_pState, const char* p_strFile, const char* p_s int result = luaL_loadfile(m_pState, p_strFile); // If the file loaded okay. - if(result == 0) + if (result == 0) { // Create the table this script will reside in lua_newtable(m_pState); @@ -38,20 +38,19 @@ LuaScript::LuaScript(lua_State* p_pState, const char* p_strFile, const char* p_s // Execute the Lua script result = lua_pcall(m_pState, 0, LUA_MULTRET, 0); - if(result) + if (result) { m_bInitialized = false; - LuaManager::LuaLog("Lua cannot run file:"); - LuaManager::LuaLog("%s", lua_tostring(m_pState, -1) ); + LuaManager::LuaLog(LOG_ERROR, "Script: Cannot run file: %s", p_strFile); + LuaManager::LuaLog(LOG_ERROR, "Script: %s", lua_tostring(m_pState, -1)); } } else { m_bInitialized = false; - LuaManager::LuaLog("Lua cannot run file:"); - LuaManager::LuaLog("%s", lua_tostring(m_pState, -1) ); + LuaManager::LuaLog(LOG_ERROR, "Script: Cannot run file: %s", p_strFile); + LuaManager::LuaLog(LOG_ERROR, "Script: %s", lua_tostring(m_pState, -1)); } - } LuaScript::~LuaScript(void) @@ -61,7 +60,6 @@ LuaScript::~LuaScript(void) void LuaScript::BindVariable(const char* p_strName, void* p_pValue, const char* p_strTypeName) { - PushTable(); /* @@ -89,7 +87,7 @@ void LuaScript::BindVariable(const char* p_strName, void* p_pValue, const char* double LuaScript::RunFunctionDouble(const char* p_strFuncName) { - if( m_bInitialized && p_strFuncName ) + if (m_bInitialized && p_strFuncName) { // Push our table onto the stack lua_getglobal(m_pState, m_strTableName); @@ -97,7 +95,7 @@ double LuaScript::RunFunctionDouble(const char* p_strFuncName) // Push the function onto the stack lua_getfield(m_pState,-1, p_strFuncName); - if( lua_pcall(m_pState, 0, 1, 0) ) + if(lua_pcall(m_pState, 0, 1, 0)) { LuaManager::ReportErrors(m_pState); } @@ -105,7 +103,7 @@ double LuaScript::RunFunctionDouble(const char* p_strFuncName) { if (!lua_isnumber(m_pState, -1)) { - LuaManager::LuaLog("Function `%s:%s' must return a number",m_strTableName, p_strFuncName); + LuaManager::LuaLog(LOG_ERROR, "Script: Function '%s:%s' must return a number", m_strTableName, p_strFuncName); } double d = lua_tonumber(m_pState, -1); @@ -121,7 +119,6 @@ double LuaScript::RunFunctionDouble(const char* p_strFuncName) return -1; } - std::wstring LuaScript::RunFunctionString(const char* p_strFuncName) { if( m_bInitialized && p_strFuncName ) @@ -130,9 +127,9 @@ std::wstring LuaScript::RunFunctionString(const char* p_strFuncName) lua_getglobal(m_pState, m_strTableName); // Push the function onto the stack - lua_getfield(m_pState,-1, p_strFuncName); + lua_getfield(m_pState, -1, p_strFuncName); - if( lua_pcall(m_pState, 0, 1, 0) ) + if (lua_pcall(m_pState, 0, 1, 0)) { LuaManager::ReportErrors(m_pState); } @@ -140,7 +137,7 @@ std::wstring LuaScript::RunFunctionString(const char* p_strFuncName) { if (!lua_isstring(m_pState, -1)) { - LuaManager::LuaLog("Function `%s:%s' must return a string",m_strTableName, p_strFuncName); + LuaManager::LuaLog(LOG_ERROR, "Script: Function '%s:%s' must return a string",m_strTableName, p_strFuncName); } const char* str = lua_tostring(m_pState, -1); @@ -153,7 +150,7 @@ std::wstring LuaScript::RunFunctionString(const char* p_strFuncName) lua_pop(m_pState, 1); } - return 0; + return L""; } void LuaScript::RunFunction(const char* p_strFuncName) diff --git a/Library/lua/glue/lua_rainmeter_ext.cpp b/Library/lua/glue/lua_rainmeter_ext.cpp index f6069457..bb6fbccc 100644 --- a/Library/lua/glue/lua_rainmeter_ext.cpp +++ b/Library/lua/glue/lua_rainmeter_ext.cpp @@ -91,7 +91,7 @@ static int AsMeterString(lua_State* tolua_S) static int staticLuaLog(lua_State* tolua_S) { const char* str = tolua_tostring(tolua_S,1,0); - LuaManager::LuaLog(str); + LuaManager::LuaLog(LOG_NOTICE, str); return 0; }