From 4f7cb79f7c8d1b46260f135e3ab7ba615cf8ea29 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 6 Oct 2023 14:03:42 +0300 Subject: =?UTF-8?q?fixes=20#3704=20(YAMN:=20=D0=9C=D0=B8=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=B4=D0=B0=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B0=D0=B5=D1=82?= =?UTF-8?q?=20=D0=B5=D1=81=D0=BB=D0=B8=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=20YAMN=20=D0=B2=D0=BE=20=D0=B2=D1=80=D0=B5=D0=BC?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=B8=D0=BB=D1=91=D1=82=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D1=8C=D0=BC=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/ExternalAPI/m_account.h | 200 +++++++++++++++++++++++++++--------- plugins/ExternalAPI/m_protoplugin.h | 28 ++--- plugins/ExternalAPI/m_synchro.h | 160 ----------------------------- plugins/ExternalAPI/m_yamn.h | 11 +- 4 files changed, 167 insertions(+), 232 deletions(-) delete mode 100644 plugins/ExternalAPI/m_synchro.h (limited to 'plugins/ExternalAPI') diff --git a/plugins/ExternalAPI/m_account.h b/plugins/ExternalAPI/m_account.h index 331b066d93..c316923cd3 100644 --- a/plugins/ExternalAPI/m_account.h +++ b/plugins/ExternalAPI/m_account.h @@ -11,7 +11,6 @@ #include #include -#include "m_synchro.h" //include synchronizing objects. If you want to write protocol plugin, which works with YAMN accounts, it must use YAMN synchronizing objects // //================================== OTHER DEFINITIONS ======================================== @@ -87,7 +86,153 @@ struct CServer //================================== ACCOUNT DEFINITION ================================== // -typedef struct CAccount +#define WAIT_FINISH WAIT_OBJECT_0+1 + +// This structure is used to get semaphore-like synchronization: +// Includes incrementing, decrementing DWORD value and if DWORD is zero, sets event +class SCOUNTER +{ + HANDLE Event; + uint32_t Number = 0; + CRITICAL_SECTION CounterCS; + +public: + SCOUNTER(); + SCOUNTER(HANDLE InitializedEvent); + ~SCOUNTER(); + + __forceinline HANDLE GetEvent() const { return Event; } + + uint32_t GetNumber(); + uint32_t Inc(); + uint32_t Dec(); +}; + +struct SCGuard +{ + SCOUNTER &pSC; + + __forceinline SCGuard(SCOUNTER &sc) : + pSC(sc) + { + sc.Inc(); + } + + __forceinline ~SCGuard() + { + pSC.Dec(); + } +}; + +// The single-writer/multiple-reader guard +// compound synchronization object (SO) +// Notices: Copyright (c) 1995-1997 Jeffrey Richter +// Changes: majvan, only one process implementation, +// hFinishEV event added- signals when we do not want to use this SO anymore + +class SWMRG +{ + // This event guards access to the other objects + // managed by this data structure and also indicates + // whether any writer threads are writing. + HANDLE hEventNoWriter; + + // This manual-reset event is signaled when + // no reader threads are reading. + HANDLE hEventNoReaders; + + // This value is used simply as a counter. + // (the count is the number of reader threads) + HANDLE hSemNumReaders; + + // The request is for not to enter critical section + // for writing or reading due to going to delete guard + HANDLE hFinishEV; + +public: + SWMRG(wchar_t *Name = nullptr); + ~SWMRG(); + + uint32_t WaitToWrite(uint32_t dwTimeout = INFINITE); + void DoneWriting(); + + uint32_t WaitToRead(uint32_t dwTimeout = INFINITE); + void DoneReading(); + + void Stop() + { + ::SetEvent(hFinishEV); + } +}; + +struct SReadGuard +{ + SWMRG &pSO; + uint32_t dwError; + + SReadGuard(SWMRG &so, uint32_t timeout = INFINITE) : + pSO(so) + { + dwError = so.WaitToRead(timeout); + } + + ~SReadGuard() + { + Uninit(); + } + + bool Succeeded() const + { + return dwError == WAIT_OBJECT_0; + } + + void Uninit() + { + if (dwError == WAIT_OBJECT_0) { + pSO.DoneReading(); + dwError = WAIT_FINISH; + } + } + + operator uint32_t() const { return dwError; } +}; + +struct SWriteGuard +{ + SWMRG &pSO; + uint32_t dwError; + + SWriteGuard(SWMRG &so, uint32_t timeout = INFINITE) : + pSO(so) + { + dwError = so.WaitToWrite(timeout); + } + + ~SWriteGuard() + { + Uninit(); + } + + bool Succeeded() const + { + return dwError == WAIT_OBJECT_0; + } + + void Uninit() + { + if (dwError == WAIT_OBJECT_0) { + pSO.DoneWriting(); + dwError = WAIT_FINISH; + } + } + + operator uint32_t() const { return dwError; } +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// CAccount - basic email account class + +struct CAccount { #define YAMN_ACCOUNTFILEVERSION 2 //version of standard file format (YAMN book file format) #define YAMN_ACCOUNTVERSION 3 @@ -97,7 +242,7 @@ typedef struct CAccount BOOL AbleToWork; // This is set to TRUE by default. When it is needed to stop working on this account, YAMN sets this to zero. - struct CYAMNProtoPlugin *Plugin; // free access, because this member should not be changed. The same as YAMN_PLUGIN structure + struct YAMN_PROTOPLUGIN *Plugin; // free access, because this member should not be changed. The same as YAMN_PLUGIN structure char *Name; // access only through AccountAccessSO @@ -159,7 +304,7 @@ typedef struct CAccount // This is event with counter. Event is signaled when no threads are using account (and will not be using) // Very usefull for account delete operation - PSCOUNTER UsingThreads; + SCOUNTER UsingThreads; // We have to achieve, that only one thread can write to account and more threads can read. // Writing to account means that we change account parameters @@ -168,7 +313,7 @@ typedef struct CAccount // For plugins, this is a pointer to void. It does not matter for plugin what is this variable for, // because plugin works only with synchronization routines. And why is this void * ? It is because // plugin does not need to include headers for SWMRG structures... - PSWMRG AccountAccessSO; + SWMRG AccountAccessSO; // We have to achieve, that only one thread can write to account mails and more threads can read. // While some thread writes mails, other thread can write to account. This can be small problem, but it never appears in YAMN. @@ -176,7 +321,7 @@ typedef struct CAccount // Writing to messages means any changes to message queue or message data // Reading from messages means reading message queue (browsing through all messages) or reading message data // Use MsgsWaitToRead(),MsgsReadDone(),MsgsWaitToWrite(),MsgsWriteDone() synchronization functions - PSWMRG MessagesAccessSO; + SWMRG MessagesAccessSO; //For clist contact notification MCONTACT hContact; @@ -185,47 +330,4 @@ typedef struct CAccount CAccount *Next; }; -// -//================================== FUNCTIONS DEFINITIONS ======================================== -// - -typedef void (WINAPI *YAMN_SETSTATUSFCN)(CAccount*, TCHAR *); -typedef void (WINAPI *YAMN_GETSTATUSFCN)(CAccount*, TCHAR *); - -// -//================================== QUICK FUNCTION CALL DEFINITIONS ======================================== -// - -//These are defininitions for YAMN exported functions. Your plugin can use them. -//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions. -//It is something similar like pluginLink variable in Miranda plugin. If you use -//this name of variable, you have already defined these functions and you can use them. -//It's similar to Miranda's CreateService function. - -//How to use YAMN functions: -//Create a structure containing pointer to functions you want to use in your plugin -//This structure can look something like this: -// -// struct -// { -// YAMN_SETSTATUSFCN SetStatusFcn; -// YAMN_GETSTATUSFCN GetStatusFcn; -// } *pYAMNFcn; -// -//then you have to fill this structure with pointers... -// -// pYAMNFcn->SetStatusFcn=(YAMN_SETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETSTATUSID,0); -// pYAMNFcn->GetStatusFcn=(YAMN_GETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_GETSTATUSID,0); -// -//and in your plugin just simply use e.g.: -// -// SetAccountStatus(ActualAccount,ACC_CONNECTING); //this command set account status to "connecting to server" -// - -#define YAMN_SETSTATUSID "YAMN/SetStatus" -#define YAMN_GETSTATUSID "YAMN/GetStatus" - -#define SetAccountStatus(x,y) pYAMNFcn->SetStatusFcn(x,y) -#define GetAccountStatus(x,y) pYAMNFcn->GetStatusFcn(x,y) - #endif diff --git a/plugins/ExternalAPI/m_protoplugin.h b/plugins/ExternalAPI/m_protoplugin.h index 1d6eccee84..c2085d25a0 100644 --- a/plugins/ExternalAPI/m_protoplugin.h +++ b/plugins/ExternalAPI/m_protoplugin.h @@ -61,7 +61,7 @@ struct DeleteParam typedef DWORD(WINAPI *YAMN_STANDARDFCN)(LPVOID); #endif typedef struct CYAMNVariables *(WINAPI *YAMN_GETVARIABLESFCN)(DWORD); -typedef CAccount *(WINAPI *YAMN_NEWACCOUNTFCN)(struct CYAMNProtoPlugin *, DWORD); +typedef CAccount *(WINAPI *YAMN_NEWACCOUNTFCN)(struct YAMN_PROTOPLUGIN *, DWORD); typedef void (WINAPI *YAMN_STOPACCOUNTFCN)(CAccount *); typedef void (WINAPI *YAMN_DELETEACCOUNTFCN)(CAccount *); typedef DWORD(WINAPI *YAMN_WRITEPLUGINOPTS)(HANDLE File, CAccount *); @@ -207,15 +207,15 @@ typedef struct CProtoPluginRegistration } YAMN_PROTOREGISTRATION, *PYAMN_PROTOREGISTRATION; -typedef struct CYAMNProtoPlugin +struct YAMN_PROTOPLUGIN { - //Pointer to first protocol plugin account - CAccount * FirstAccount; + // Pointer to first protocol plugin account + CAccount *FirstAccount; - //We prevent browsing through accounts (chained list) from deleting or adding any account - //If we want to delete or add, we must have "write" access to AccountBrowserSO - //Note that accounts can be changed during AccountBrowser is in "read" mode, because we do not add or delete account. - PSWMRG AccountBrowserSO; + // We prevent browsing through accounts (chained list) from deleting or adding any account + // If we want to delete or add, we must have "write" access to AccountBrowserSO + // Note that accounts can be changed during AccountBrowser is in "read" mode, because we do not add or delete account. + SWMRG AccountBrowserSO; //All needed other info from plugin PYAMN_PROTOREGISTRATION PluginInfo; @@ -223,13 +223,13 @@ typedef struct CYAMNProtoPlugin //Imported functions PYAMN_PROTOIMPORTFCN Fcn; PYAMN_MAILIMPORTFCN MailFcn; -} YAMN_PROTOPLUGIN, *PYAMN_PROTOPLUGIN, *HYAMNPROTOPLUGIN; +}; -typedef struct CProtoPluginQueue +struct YAMN_PROTOPLUGINQUEUE { - HYAMNPROTOPLUGIN Plugin; - struct CProtoPluginQueue *Next; -} YAMN_PROTOPLUGINQUEUE, *PYAMN_PROTOPLUGINQUEUE; + YAMN_PROTOPLUGIN *Plugin; + YAMN_PROTOPLUGINQUEUE *Next; +}; // //================================== YAMN SERVICES FOR PROTOCOL PLUGIN ================================== @@ -331,7 +331,7 @@ typedef struct CProtoPluginQueue //================================== FUNCTIONS DEFINITIONS ======================================== // -typedef int (WINAPI *YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, DWORD YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, DWORD YAMNMailFcnVer); +typedef int (WINAPI *YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)(YAMN_PROTOPLUGIN *Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, DWORD YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, DWORD YAMNMailFcnVer); // //================================== QUICK FUNCTION CALL DEFINITIONS ======================================== diff --git a/plugins/ExternalAPI/m_synchro.h b/plugins/ExternalAPI/m_synchro.h deleted file mode 100644 index 33d605bf50..0000000000 --- a/plugins/ExternalAPI/m_synchro.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef __SYNCHRO_H -#define __SYNCHRO_H - -#include - -// -//================================== OTHER DEFINITIONS ======================================== -// - -#define WAIT_FINISH WAIT_OBJECT_0+1 - -// This structure is used to get semaphore-like synchronization: -// Includes incrementing, decrementing DWORD value and if DWORD is zero, sets event -typedef struct SynchronisedCounter -{ -// Stores number value - HANDLE Event; - DWORD Number; - -// These methods are deleted due to external plugins. Use SCGetNumber,SCInc and SCDec instead -// DWORD GetNumber(); -// DWORD Inc(); -// DWORD Dec(); - -// Yes, some code is defined here. But it is not so problematic, because it uses only Win32 API calls and Win32 structures, - SynchronisedCounter(): Number(0) - { - InitializeCriticalSection(&CounterCS); - Event = CreateEvent(nullptr, FALSE, TRUE, nullptr); - SetEvent(Event); - } - - SynchronisedCounter(HANDLE InitializedEvent): Number(0) - { - InitializeCriticalSection(&CounterCS); - Event=InitializedEvent; - SetEvent(Event); - } - - ~SynchronisedCounter() - { - DeleteCriticalSection(&CounterCS); - CloseHandle(Event); - } - -//private: //it is not private as other functions (not methods) use these members - CRITICAL_SECTION CounterCS; -} SCOUNTER, *PSCOUNTER; - -// The single-writer/multiple-reader guard -// compound synchronization object (SO) -// Notices: Copyright (c) 1995-1997 Jeffrey Richter -// Changes: majvan, only one process implementation, -// hFinishEV event added- signals when we do not want to use this SO anymore -typedef struct SingleWriterMultiReaderGuard -{ -// This event guards access to the other objects -// managed by this data structure and also indicates -// whether any writer threads are writing. - HANDLE hEventNoWriter; - -// This manual-reset event is signaled when -// no reader threads are reading. - HANDLE hEventNoReaders; - -// This value is used simply as a counter. -// (the count is the number of reader threads) - HANDLE hSemNumReaders; - -// The request is for not to enter critical section -// for writing or reading due to going to delete guard - HANDLE hFinishEV; -} SWMRG, *PSWMRG; - -// -//================================== FUNCTIONS DEFINITIONS ======================================== -// - -typedef DWORD (WINAPI *YAMN_WAITTOWRITEFCN)(PSWMRG,PSCOUNTER); -typedef void (WINAPI *YAMN_WRITEDONEFCN)(PSWMRG,PSCOUNTER); -typedef DWORD (WINAPI *YAMN_WAITTOREADFCN)(PSWMRG); -typedef void (WINAPI *YAMN_READDONEFCN)(PSWMRG); -typedef DWORD (WINAPI *YAMN_SCMANAGEFCN)(PSCOUNTER); - -// -//================================== QUICK FUNCTION CALL DEFINITIONS ======================================== -// - -//These are defininitions for YAMN exported functions. Your plugin can use them. -//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions. -//It is something similar like pluginLink variable in Miranda plugin. If you use -//this name of variable, you have already defined these functions and you can use them. -//It's similar to Miranda's CreateService function. -//These functions are used to synchronize accounts. YAMN could create service for these -//functions and you could call them then e.g. CallService(MS_YAMNWAITTOWRITE,WPARAM,LPARAM), -//but I think this solution is better, because these functions are much used. It is more -//"normal" if you call function for example like: -//WaitToWrite(ActualAccount) than CallService(MS_YAMNWAITTOWRITE,ActualAccount,NULL)) - -//How to use YAMN functions: -//Create a structure containing pointer to functions you want to use in your plugin -//This structure can look something like this: -// -// struct -// { -// YAMN_WAITTOWRITEFCN WaitToWriteFcn; -// YAMN_WRITEDONEFCN WriteDoneFcn; -// } *pYAMNFcn; -// -//then you have to fill this structure with pointers... -//you have to use YAMN service to get pointer, like this (I wrote here all functions you may need, -//you can copy to your sources only those you need): -// -// pYAMNFcn->WaitToWriteFcn=(YAMN_WAITTOWRITEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOWRITEID,0); -// pYAMNFcn->WriteDoneFcn=(YAMN_WRITEDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WRITEDONEID,0); -// pYAMNFcn->WaitToReadFcn=(YAMN_WAITTOREADFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOREADID,0); -// pYAMNFcn->ReadDoneFcn=(YAMN_READDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_READDONEID,0); -// pYAMNFcn->SCGetNumberFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCGETNUMBERID,0); -// pYAMNFcn->SCIncFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCINCID,0); -// pYAMNFcn->SCDecFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCDECID,0); -// -//and in your plugin just simply use e.g.: -// -// MsgsWriteDone(ActualAccount); //this command leaves write access to account mails -// - -#define YAMN_WAITTOWRITEID "YAMN/WaitToWrite" -#define YAMN_WRITEDONEID "YAMN/WriteDone" -#define YAMN_WAITTOREADID "YAMN/WaitToRead" -#define YAMN_READDONEID "YAMN/ReadDone" -#define YAMN_SCGETNUMBERID "YAMN/SCGetNumber" -#define YAMN_SCINCID "YAMN/SCInc" -#define YAMN_SCDECID "YAMN/SCDec" - -#define WaitToWrite(x) pYAMNFcn->WaitToWriteFcn(x->AccountAccessSO,0) -#define WaitToWriteEx(x,y) pYAMNFcn->WaitToWriteFcn(x->AccountAccessSO,y) -#define WriteDone(x) pYAMNFcn->WriteDoneFcn(x->AccountAccessSO,0) -#define WaitToRead(x) pYAMNFcn->WaitToReadFcn(x->AccountAccessSO) -#define WaitToReadEx(x,y) pYAMNFcn->WaitToReadFcn(x->AccountAccessSO,y) -#define ReadDone(x) pYAMNFcn->ReadDoneFcn(x->AccountAccessSO) - -#define MsgsWaitToWrite(x) pYAMNFcn->WaitToWriteFcn(x->MessagesAccessSO,0) -#define MsgsWaitToWriteEx(x,y) pYAMNFcn->WaitToWriteFcn(x->MessagesAccessSO,y) -#define MsgsWriteDone(x) pYAMNFcn->WriteDoneFcn(x->MessagesAccessSO,0) -#define MsgsWaitToRead(x) pYAMNFcn->WaitToReadFcn(x->MessagesAccessSO) -#define MsgsWaitToReadEx(x) pYAMNFcn->WaitToReadFcn(x->MessagesAccessSO,y) -#define MsgsReadDone(x) pYAMNFcn->ReadDoneFcn(x->MessagesAccessSO) - -#define WaitToWriteSO(x) pYAMNFcn->WaitToWriteFcn(x,0) -#define WaitToWriteSOEx(x,y) pYAMNFcn->WaitToWriteFcn(x,y) -#define WriteDoneSO(x) pYAMNFcn->WriteDoneFcn(x,0) -#define WaitToReadSO(x) pYAMNFcn->WaitToReadFcn(x) -#define WaitToReadSOEx(x,y) pYAMNFcn->WaitToReadFcn(x,y) -#define ReadDoneSO(x) pYAMNFcn->ReadDoneFcn(x) - -#define SCGetNumber(x) pYAMNFcn->SCGetNumberFcn(x) -#define SCInc(x) pYAMNFcn->SCIncFcn(x) -#define SCDec(x) pYAMNFcn->SCDecFcn(x) - -#endif diff --git a/plugins/ExternalAPI/m_yamn.h b/plugins/ExternalAPI/m_yamn.h index 3ba9b07cd1..10b4f94513 100644 --- a/plugins/ExternalAPI/m_yamn.h +++ b/plugins/ExternalAPI/m_yamn.h @@ -7,13 +7,13 @@ //================================== VARIABLES STRUCT ======================================== // -typedef struct CYAMNVariables +struct YAMN_VARIABLES { #define YAMN_VARIABLESVERSION 3 MWindowList MessageWnds; MWindowList NewMailAccountWnd; int Shutdown; -} YAMN_VARIABLES, *PYAMN_VARIABLES; +}; // //================================== EXPORTED FUNCTIONS STRUCT =============================== @@ -68,13 +68,6 @@ struct CExportedServices //returns pointer to YAMN function or NULL when functions does not exist #define MS_YAMN_GETFCNPTR "YAMN/Service/GetFcn" -//GetVariables Service -//Ask YAMN for pointer to CYAMNVariables structure. -//WPARAM- YAMN_VARIABLESVERSION -//LPARAM- any value -//returns pointer to YAMN_VARIABLES or NULL when version of structure does not match -#define MS_YAMN_GETVARIABLES "YAMN/Service/GetVar" - //ForceCheck Service //Check mail on accounts //WPARAM- not used -- cgit v1.2.3