#include "stdafx.h" HANDLE hRecvMessage = nullptr; static int lua_GetProtocol(lua_State *L) { const char *szProto = nullptr; switch (lua_type(L, 1)) { case LUA_TNUMBER: { const char *szModule = GetContactProto(lua_tonumber(L, 1)); PROTOACCOUNT *pa = Proto_GetAccount(szModule); if (pa) szProto = pa->szProtoName; break; } case LUA_TSTRING: szProto = lua_tostring(L, 1); break; default: luaL_argerror(L, 1, luaL_typename(L, 1)); } PROTOCOLDESCRIPTOR *pd = Proto_IsProtocolLoaded(szProto); if (pd) MT::Apply(L, pd); else lua_pushnil(L); return 1; } static int lua_ProtocolIterator(lua_State *L) { int i = lua_tointeger(L, lua_upvalueindex(1)); int count = lua_tointeger(L, lua_upvalueindex(2)); PROTOCOLDESCRIPTOR **protos = (PROTOCOLDESCRIPTOR**)lua_touserdata(L, lua_upvalueindex(3)); if (i < count) { lua_pushinteger(L, (i + 1)); lua_replace(L, lua_upvalueindex(1)); MT::Apply(L, protos[i]); } else lua_pushnil(L); return 1; } static int lua_Protocols(lua_State *L) { int count; PROTOCOLDESCRIPTOR **protos; Proto_EnumProtocols(&count, &protos); lua_pushinteger(L, 0); lua_pushinteger(L, count); lua_pushlightuserdata(L, protos); lua_pushcclosure(L, lua_ProtocolIterator, 3); return 1; } static int lua_RegisterProtocol(lua_State *L) { ptrA name(mir_utf8decodeA(luaL_checkstring(L, 1))); PROTOCOLDESCRIPTOR pd = { 0 }; pd.cbSize = sizeof(pd); pd.szName = name; pd.type = PROTOTYPE_PROTOCOL; int res = Proto_RegisterModule(&pd); lua_pushboolean(L, res == 0); return 1; } static int lua_ChainSend(lua_State *L) { MCONTACT hContact = luaL_checknumber(L, 1); const char *service = luaL_checkstring(L, 2); WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); INT_PTR res = ProtoChainSend(hContact, service, wParam, lParam); lua_pushinteger(L, res); return 1; } static int lua_ChainRecv(lua_State *L) { MCONTACT hContact = luaL_checknumber(L, 1); const char *service = luaL_checkstring(L, 2); WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); INT_PTR res = ProtoChainRecv(hContact, service, wParam, lParam); lua_pushinteger(L, res); return 1; } /***********************************************/ static int lua_GetAccount(lua_State *L) { const char *name = nullptr; switch (lua_type(L, 1)) { case LUA_TNUMBER: name = GetContactProto(lua_tonumber(L, 1)); break; case LUA_TSTRING: name = lua_tostring(L, 1); break; default: luaL_argerror(L, 1, luaL_typename(L, 1)); } PROTOACCOUNT *pa = Proto_GetAccount(name); if (pa) MT::Apply(L, pa); else lua_pushnil(L); return 1; } static int lua_AccountIterator(lua_State *L) { int i = lua_tointeger(L, lua_upvalueindex(1)); int count = lua_tointeger(L, lua_upvalueindex(2)); PROTOACCOUNT **accounts = (PROTOACCOUNT**)lua_touserdata(L, lua_upvalueindex(3)); const char *szProto = lua_tostring(L, lua_upvalueindex(4)); if (szProto) while (i < count && mir_strcmp(szProto, accounts[i]->szProtoName)) i++; if (i < count) { lua_pushinteger(L, (i + 1)); lua_replace(L, lua_upvalueindex(1)); MT::Apply(L, accounts[i]); } else lua_pushnil(L); return 1; } static int lua_Accounts(lua_State *L) { const char *szProto = nullptr; switch (lua_type(L, 1)) { case LUA_TNONE: break; case LUA_TSTRING: szProto = lua_tostring(L, 1); break; case LUA_TUSERDATA: { PROTOCOLDESCRIPTOR *pd = *(PROTOCOLDESCRIPTOR**)luaL_checkudata(L, 1, MT_PROTOCOLDESCRIPTOR); szProto = pd->szName; break; } default: luaL_argerror(L, 1, luaL_typename(L, 1)); } int count; PROTOACCOUNT **accounts; Proto_EnumAccounts(&count, &accounts); lua_pushinteger(L, 0); lua_pushinteger(L, count); lua_pushlightuserdata(L, accounts); lua_pushstring(L, szProto); lua_pushcclosure(L, lua_AccountIterator, 4); return 1; } static int lua_CallService(lua_State *L) { const char *szModule = nullptr; switch (lua_type(L, 1)) { case LUA_TNUMBER: szModule = GetContactProto(lua_tonumber(L, 1)); break; case LUA_TSTRING: szModule = lua_tostring(L, 1); break; case LUA_TUSERDATA: { PROTOACCOUNT *pa = *(PROTOACCOUNT**)luaL_checkudata(L, 1, MT_PROTOACCOUNT); szModule = pa->szModuleName; break; } default: luaL_argerror(L, 1, luaL_typename(L, 1)); } const char *service = luaL_checkstring(L, 2); WPARAM wParam = (WPARAM)luaM_tomparam(L, 3); LPARAM lParam = (LPARAM)luaM_tomparam(L, 4); INT_PTR res = CallProtoService(szModule, service, wParam, lParam); lua_pushinteger(L, res); return 1; } /***********************************************/ INT_PTR FilterRecvMessage(WPARAM wParam, LPARAM lParam) { int res = NotifyEventHooks(hRecvMessage, wParam, lParam); if (res) return res; Proto_ChainRecv(wParam, (CCSDATA*)lParam); return 0; } /***********************************************/ static luaL_Reg protocolsApi[] = { { "GetProtocol", lua_GetProtocol }, { "Protocols", lua_Protocols }, { "RegisterProtocol", lua_Protocols }, { "CallSendChain", lua_ChainSend }, { "CallReceiveChain", lua_ChainRecv }, { "GetAccount", lua_GetAccount }, { "Accounts", lua_Accounts }, { "CallService", lua_CallService }, { nullptr, nullptr } }; /***********************************************/ LUAMOD_API int luaopen_m_protocols(lua_State *L) { luaL_newlib(L, protocolsApi); MT(L, MT_PROTOCOLDESCRIPTOR) .Field(&PROTOCOLDESCRIPTOR::szName, "Name", LUA_TSTRINGA) .Field(&PROTOCOLDESCRIPTOR::type, "Type", LUA_TINTEGER) .Field(lua_Accounts, "Accounts"); MT(L, MT_PROTOACCOUNT) .Field(&PROTOACCOUNT::szModuleName, "ModuleName", LUA_TSTRINGA) .Field(&PROTOACCOUNT::tszAccountName, "AccountName", LUA_TSTRINGW) .Field(&PROTOACCOUNT::szProtoName, "ProtoName", LUA_TSTRINGA) .Field(&PROTOACCOUNT::bIsEnabled, "IsEnabled", LUA_TBOOLEAN) .Field(&PROTOACCOUNT::bIsVisible, "IsVisible", LUA_TBOOLEAN) .Field(&PROTOACCOUNT::bIsVirtual, "IsVirtual", LUA_TBOOLEAN) .Field(&PROTOACCOUNT::bOldProto, "IsOldProto", LUA_TBOOLEAN) .Field(lua_CallService, "CallService"); MT(L, "ACKDATA") .Field(&ACKDATA::szModule, "Module", LUA_TSTRINGA) .Field(&ACKDATA::hContact, "hContact", LUA_TINTEGER) .Field(&ACKDATA::type, "Type", LUA_TINTEGER) .Field(&ACKDATA::result, "Result", LUA_TINTEGER) .Field(&ACKDATA::hProcess, "hProcess", LUA_TLIGHTUSERDATA) .Field(&ACKDATA::lParam, "lParam", LUA_TLIGHTUSERDATA); MT(L, "CCSDATA") .Field(&CCSDATA::hContact, "hContact", LUA_TINTEGER) .Field(&CCSDATA::szProtoService, "Service", LUA_TSTRINGA) .Field(&CCSDATA::wParam, "wParam", LUA_TLIGHTUSERDATA) .Field(&CCSDATA::lParam, "lParam", LUA_TLIGHTUSERDATA); MT(L, "PROTORECVEVENT") .Field(&PROTORECVEVENT::timestamp, "Timestamp", LUA_TINTEGER) .Field(&PROTORECVEVENT::flags, "Flags", LUA_TINTEGER) .Field(&PROTORECVEVENT::szMessage, "Message", LUA_TSTRING); return 1; }