From c628a13d98fde8d2555cc6fa8628e0b575021bd4 Mon Sep 17 00:00:00 2001 From: Szymon Tokarz Date: Mon, 27 May 2013 22:29:01 +0000 Subject: MirFox plugin for Miranda NG added Version 0.5.0.0 Compatible Firefox addon is now available at: https://addons.mozilla.org/pl/firefox/addon/mirfox/versions/0.5.0.0 or http://wsx22.xpdev-hosted.com/ git-svn-id: http://svn.miranda-ng.org/main/trunk@4826 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MirFox/src/MirfoxMiranda.cpp | 458 +++++++++++++++++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 plugins/MirFox/src/MirfoxMiranda.cpp (limited to 'plugins/MirFox/src/MirfoxMiranda.cpp') diff --git a/plugins/MirFox/src/MirfoxMiranda.cpp b/plugins/MirFox/src/MirfoxMiranda.cpp new file mode 100644 index 0000000000..13a302996f --- /dev/null +++ b/plugins/MirFox/src/MirfoxMiranda.cpp @@ -0,0 +1,458 @@ +#include "common.h" +#include "MirfoxMiranda.h" + + + + +CMirfoxMiranda::CMirfoxMiranda() + : sharedMemoryUtils(SharedMemoryUtils::getInstance()) + , mirandaUtils(MirandaUtils::getInstance()) + , logger(MFLogger::getInstance()) +{ +} + + + +CMirfoxMiranda::~CMirfoxMiranda() +{ +} + + +MirfoxData& +CMirfoxMiranda::getMirfoxData(){ + return mirfoxData; +} + + +bool +CMirfoxMiranda::onMirandaPluginInfoExCheck(DWORD actualMirandaVersion) +{ +// DWORD minimalMirandaVersion = PLUGIN_MAKE_VERSION(0,8,0,0); +// if ( actualMirandaVersion < minimalMirandaVersion) { +// return false; +// } else { + return true; +// } +} + + + +int +CMirfoxMiranda::onMirandaInterfaceLoad() +{ + + mirandaUtils->netlibRegister(); //for Miranda logger init + logger->initLogger(&MirandaUtils::netlibLog); + logger->set6CharsPrefix(L"MNG "); + + mirandaUtils->translateOldDBNames(); + + mirfoxData.initializeMirfoxData(); + logger->log(L"dll init, MirfoxData initialized"); + + initializeSharedMemory(mirfoxData); + if (mirfoxData.getPluginState() == MFENUM_PLUGIN_STATE_ERROR){ + return 0; + } + + initializeMessageQueue(mirfoxData); + if (mirfoxData.getPluginState() == MFENUM_PLUGIN_STATE_ERROR){ + return 0; + } + + mirfoxData.hhook_EventOpenMW = CreateHookableEvent("MirFox/OpenMW"); + mirfoxData.hhook_OpenMW = HookEvent("MirFox/OpenMW", MirandaUtils::on_hook_OpenMW); + + commitSharedMemory(); + + + return 0; +} + + +int +CMirfoxMiranda::onMirandaInterfaceUnload() +{ + + UnhookEvent(mirfoxData.hhook_OpenMW); + DestroyHookableEvent(mirfoxData.hhook_EventOpenMW); + + unloadMessageQueue(mirfoxData.processCsmId); + unloadSharedMemory(); + + mirfoxData.releaseMirfoxData(); + + logger->releaseLogger(); + mirandaUtils->netlibUnregister(); + + return 0; +} + + +void +CMirfoxMiranda::initializeSharedMemory(MirfoxData& mirfoxData) +{ + + //initialize CSM record and MSMs with data from mirfoxData + initializeSharedMemoryData(mirfoxData, sharedMemoryUtils); + + if (mirfoxData.getPluginState() == MFENUM_PLUGIN_STATE_ERROR){ + return; + } + + //Create new thread to maintain shared memory data + mir_forkthread(CMirfoxMiranda::csmThread, this); + +} + +void +CMirfoxMiranda::commitSharedMemory() +{ + //commitSM(); + sharedMemoryUtils->commitSM(); +} + + +void +CMirfoxMiranda::initializeSharedMemoryData(MirfoxData& mirfoxData, SharedMemoryUtils* sharedMemoryUtils) +{ + + std::wstring visableTo; + if (mirfoxData.getClientsProfilesFilterCheckbox()){ + visableTo = *mirfoxData.getClientsProfilesFilterStringPtr(); + }else{ + visableTo = TEXT(""); + } + OpenOrCreateSMReturnStruct result = sharedMemoryUtils->openOrCreateSM('M', mirandaUtils->getDisplayName(), visableTo, false); + logger->log_p(L"openOrCreateCSM('M') result = [%u]", result); + + if(result.errorCode != 0){ + //error + if (result.errorCode == -3){ //existing csm version is too high -> i'm too old + MessageBox(NULL, + MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtooold.message"), TEXT("This MirFox (Miranda) plugin is too old. Please update it.")), + MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtooold.title"), TEXT("MirFox (Miranda) - Error")), + MB_OK | MB_ICONWARNING ); + } + if (result.errorCode == -4){ //existing csm version is too low -> sb is too old + MessageBox(NULL, + MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtoonew.message"), TEXT("This MirFox (Miranda) plugin can not start beacouse some other MirFox component is too old. Please, check and update your MirFox components.")), + MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtoonew.title"), TEXT("MirFox (Miranda) - Error")), + MB_OK | MB_ICONWARNING ); + } + mirfoxData.setPluginState(MFENUM_PLUGIN_STATE_ERROR); + return; + } else { + mirfoxData.processCsmId = result.processCsmId; + wchar_t prefix[7]; + wsprintf(prefix, L"MNG%d", result.processCsmId); + logger->set6CharsPrefix(prefix); + } + + + sharedMemoryUtils->resetMsmParameters(); + + //addOptionToSM(); + // no options to add yet + + //addTranslationToSM(); + // no translations to add yet + + //addAccountToSM(); + boost::ptr_list* mirandaAccountsPtr = mirfoxData.getMirandaAccounts(); + boost::ptr_list::iterator mirandaAccountsIter; + for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){ + if (mirandaAccountsIter->accountState == MFENUM_MIRANDAACCOUNT_STATE_ON){ + std::wstring tszAccountNameW = mirandaAccountsIter->tszAccountName; + sharedMemoryUtils->addAccountToSM(mirandaAccountsIter->id, tszAccountNameW); + } + } + + //addGroupToSM(); + //TODO groups support + std::wstring groupName = L"ROOT GROUP"; + sharedMemoryUtils->addGroupToSM((uint64_t)1, (uint64_t)NULL, 'R', groupName); + + //addContactToSM(); + boost::ptr_list* mirandaContactsPtr = mirfoxData.getMirandaContacts(); + boost::ptr_list::iterator mirandaContactsIter; + for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){ + if (mirandaContactsIter->contactState == MFENUM_MIRANDACONTACT_STATE_ON){ + //TODO mirandaAccountHandle support + sharedMemoryUtils->addContactToSM((uint64_t)mirandaContactsIter->contactHandle, (uint64_t)NULL, (uint64_t)1, mirandaContactsIter->contactNameW); + } + } + + +} + + + +void +CMirfoxMiranda::unloadSharedMemory() +{ + + sharedMemoryUtils->unloadSharedMemory(mirfoxData.processCsmId); + //all msm's will be deleted when miranda process returns + +} + + + + + +/*static*/ void +CMirfoxMiranda::csmThread(void* threadArg) +{ + Thread_Push(0); + + CMirfoxMiranda* mirfoxMirandaPtr = (CMirfoxMiranda*)threadArg; + MirfoxData* mirfoxDataPtr = &(mirfoxMirandaPtr->getMirfoxData()); + SharedMemoryUtils* sharedMemoryUtils = SharedMemoryUtils::getInstance(); + MirandaUtils* mirandaUtils = MirandaUtils::getInstance(); + MFLogger* logger = MFLogger::getInstance(); + + mirfoxDataPtr->workerThreadsCount++; + + logger->log_p(L"MirfoxMiranda::csmThread (processCsmId = [%u]) - started", mirfoxDataPtr->processCsmId); + + int i = CSMTHREAD_FIRSTRUN_TIME; //first run after 10s (100 * 100ms) + for (;;) + { + if (i <= 0){ + i = CSMTHREAD_NEXTRUN_TIME; //next run after 10s + + logger->log_p(L"MirfoxMiranda::csmThread (processCsmId = [%u]) - checking", mirfoxDataPtr->processCsmId); + + boost::interprocess::windows_shared_memory* checkedCsm = + sharedMemoryUtils->getSmById(sharedMemoryUtils->getCsmName(), sharedMemoryUtils->getCsmTotalSize()); + + // - check if our csm record is correct + int result = sharedMemoryUtils->checkCSM(checkedCsm, mirfoxDataPtr->processCsmId, mirandaUtils->getDisplayName()); + + if (result == 1){ + //wrong record in CSM - try to recreate own record + logger->log_p(L"MirfoxMiranda::csmThread (old processCsmId = [%u]) - checkCSM returned 1, try to recreate record in CSM", mirfoxDataPtr->processCsmId); + + mirfoxDataPtr->setPluginState(MFENUM_PLUGIN_STATE_INIT); + + uint16_t unloadedMQProcessId = mirfoxDataPtr->processCsmId; + //refresh msm + mirfoxMirandaPtr->initializeSharedMemoryData(*mirfoxDataPtr, sharedMemoryUtils); + if (unloadedMQProcessId != mirfoxDataPtr->processCsmId){ + //refresh miranda message queue if id changed + mirfoxMirandaPtr->unloadMessageQueue(unloadedMQProcessId); + mirfoxMirandaPtr->initializeMessageQueue(*mirfoxDataPtr); + } + + if (mirfoxDataPtr->getPluginState() != MFENUM_PLUGIN_STATE_ERROR){ + + sharedMemoryUtils->commitSM(); + + mirfoxDataPtr->setPluginState(MFENUM_PLUGIN_STATE_WORK); + result = 0; //ok + logger->log_p(L"MirfoxMiranda::csmThread - Success of recreating own record in CSM and own MSMs. new processCsmId = [%u]", mirfoxDataPtr->processCsmId); + + } + + } + + if (result != 0){ //can't recreate own shared memory record + logger->log_p(L"ERROR. CSM record data is still corrupted. goto plugin error state result: %i", result); + mirfoxDataPtr->setPluginState(MFENUM_PLUGIN_STATE_ERROR); + break; //exit thread + } + + // - update our timestamp + sharedMemoryUtils->updateCsmTimestamp(*checkedCsm, mirfoxDataPtr->processCsmId); + + // - delete another records with too old timestamps + sharedMemoryUtils->checkAnotherCsm(*checkedCsm, mirfoxDataPtr->processCsmId); + + //delete checkedCsm object, clear handle + delete checkedCsm; + + } + + i--; + SleepEx(CSMTHREAD_TICK_TIME, TRUE); //check exit every 0,1s + + //if miranda is exiting - exit this thread + if (Miranda_Terminated() || mirfoxDataPtr->Plugin_Terminated){ + logger->log_p(L"MirfoxMiranda::csmThread break by Plugin_Terminated (=%d) or Miranda_Terminated()", mirfoxDataPtr->Plugin_Terminated); + break; + } + + } + + mirfoxDataPtr->workerThreadsCount--; + Thread_Pop(); + return; + +} + + + + +void +CMirfoxMiranda::initializeMessageQueue(MirfoxData& mirfoxData) +{ + + MessageQueueUtils* messageQueueUtils = MessageQueueUtils::getInstance(); + + //get name of message queue for this client + std::string mqName = messageQueueUtils->getMqName(mirfoxData.processCsmId); + //create own mq + int result = messageQueueUtils->createMessageQueue(mqName); + if (result > 0){ + mirfoxData.setPluginState(MFENUM_PLUGIN_STATE_ERROR); + //sm will not be commited + return; + } + + //Create new thread to maintain actions from message queue + mir_forkthread(CMirfoxMiranda::msgQueueThread, this); + +} + +void +CMirfoxMiranda::unloadMessageQueue(uint16_t unloadedMQProcessId) +{ + + MessageQueueUtils* messageQueueUtils = MessageQueueUtils::getInstance(); + messageQueueUtils->unloadMessageQueue(unloadedMQProcessId); + +} + + +/*static*/ void +CMirfoxMiranda::msgQueueThread(void* threadArg) +{ + Thread_Push(0); + + CMirfoxMiranda* mirfoxMirandaPtr = (CMirfoxMiranda*)threadArg; + MirfoxData* mirfoxDataPtr = &(mirfoxMirandaPtr->getMirfoxData()); + uint16_t myProcessCsmId = mirfoxDataPtr->processCsmId; + MFLogger* logger = MFLogger::getInstance(); + + mirfoxDataPtr->workerThreadsCount++; + + logger->log_p(L"MirfoxMiranda::msgQueueThread - started for processCsmId = [%u]", myProcessCsmId); + + MessageQueueUtils* messageQueueUtils = MessageQueueUtils::getInstance(); + MirandaUtils* mirandaUtils = MirandaUtils::getInstance(); + + char menuItemType; + char userActionType; + char userButton; + uint64_t targetHandle; + wchar_t* userActionSelection = new wchar_t[MQCONST_MQSM_TEXT_SIZEC + 1]; + + + //infinite loop for listening to messages from queue + int i = MQTHREAD_FIRSTRUN_TIME; //first run after 0s (0 * 100ms) + for (;;) + { + if (i<=0){ + i = MQTHREAD_NEXTRUN_TIME; //next run after 0,10s + + if (messageQueueUtils->tryReceiveMessage(menuItemType, userActionType, userButton, targetHandle, userActionSelection, MQCONST_MQSM_TEXT_SIZEC + 1) == true){ + //message received, variables are available + + logger->log_p(L"mqThread: message received menuItemType = [%c] userActionType = [%c] userButton = [%c] targetHandle = [%I64u]", + menuItemType, userActionType, userButton, targetHandle); + + if (menuItemType == 'B'){ + + //for B - one action thread per one account needed + + //for all enabled accounts; + boost::ptr_list* mirandaAccountsPtr = mirfoxDataPtr->getMirandaAccounts(); + boost::ptr_list::iterator mirandaAccountsIter; + for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){ + if (mirandaAccountsIter->accountState == MFENUM_MIRANDAACCOUNT_STATE_ON){ + + ActionThreadArgStruct* actionThreadArgPtr = new(ActionThreadArgStruct); + + actionThreadArgPtr->userActionType = userActionType; + actionThreadArgPtr->menuItemType = 'A'; + actionThreadArgPtr->userButton = userButton; + + actionThreadArgPtr->targetHandle = NULL; + + std::size_t mnSize = strlen(mirandaAccountsIter->szModuleName) + 1; + char* accountSzModuleName = new char[mnSize]; + memset(accountSzModuleName, 0, mnSize * sizeof(char)); + strcpy_s(accountSzModuleName, mnSize, mirandaAccountsIter->szModuleName); + actionThreadArgPtr->accountSzModuleName = accountSzModuleName; + + std::size_t uasSize = wcslen(userActionSelection) + 1; + actionThreadArgPtr->userActionSelection = new wchar_t[uasSize]; + memset(actionThreadArgPtr->userActionSelection, 0, uasSize * sizeof(wchar_t)); + wcsncpy_s(actionThreadArgPtr->userActionSelection, uasSize, userActionSelection, uasSize - 1); + + actionThreadArgPtr->instancePtr = mirandaUtils; + actionThreadArgPtr->mirfoxDataPtr = mirfoxDataPtr; + + mir_forkthread(MirandaUtils::userActionThread, actionThreadArgPtr); + + } + } + + } else { + + //for A and C - one action thread needed + + ActionThreadArgStruct* actionThreadArgPtr = new(ActionThreadArgStruct); + + actionThreadArgPtr->userActionType = userActionType; + actionThreadArgPtr->menuItemType = menuItemType; + actionThreadArgPtr->userButton = userButton; + + actionThreadArgPtr->targetHandle = (HANDLE)targetHandle; + if (menuItemType == 'A'){ //action on account + actionThreadArgPtr->accountSzModuleName = mirfoxDataPtr->getAccountSzModuleNameById(targetHandle); + } + + std::size_t uasSize = wcslen(userActionSelection) + 1; + actionThreadArgPtr->userActionSelection = new wchar_t[uasSize]; + memset(actionThreadArgPtr->userActionSelection, 0, uasSize * sizeof(wchar_t)); + wcsncpy_s(actionThreadArgPtr->userActionSelection, uasSize, userActionSelection, uasSize - 1); + + actionThreadArgPtr->instancePtr = mirandaUtils; + actionThreadArgPtr->mirfoxDataPtr = mirfoxDataPtr; + + mir_forkthread(MirandaUtils::userActionThread, actionThreadArgPtr); + + } + + + } + + } + + i--; + SleepEx(MQTHREAD_TICK_TIME, TRUE); //check exit every 0,1s + + //if miranda is exiting - exit this thread + if (Miranda_Terminated() || mirfoxDataPtr->Plugin_Terminated){ + logger->log_p(L"mqThread break by Plugin_Terminated (=%d) or Miranda_Terminated()", mirfoxDataPtr->Plugin_Terminated); + delete [] userActionSelection; + break; + } + if(messageQueueUtils->unloadedMQProcessId == myProcessCsmId){ + messageQueueUtils->unloadedMQProcessId = -1; + logger->log_p(L"mqThread [%u]: returning. unloadedMQProcessId == myProcessCsmId", myProcessCsmId); + delete [] userActionSelection; + break; + } + + } + + mirfoxDataPtr->workerThreadsCount--; + Thread_Pop(); + return; + +} + + -- cgit v1.2.3