diff options
author | George Hazan <george.hazan@gmail.com> | 2023-10-06 14:03:42 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2023-10-06 14:03:42 +0300 |
commit | 4f7cb79f7c8d1b46260f135e3ab7ba615cf8ea29 (patch) | |
tree | 70bab49f49e7f4989445ba9a8bff94c90e1acf60 /plugins | |
parent | 4549087d4f7044dbf51a75d1af605ac93f6fbd6b (diff) |
fixes #3704 (YAMN: Миранда зависает если изменить настройки YAMN во время прилёта письма)
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/ExternalAPI/m_account.h | 200 | ||||
-rw-r--r-- | plugins/ExternalAPI/m_protoplugin.h | 28 | ||||
-rw-r--r-- | plugins/ExternalAPI/m_synchro.h | 160 | ||||
-rw-r--r-- | plugins/ExternalAPI/m_yamn.h | 11 |
4 files changed, 167 insertions, 232 deletions
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 <windows.h>
#include <tchar.h>
-#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 <windows.h>
-
-//
-//================================== 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
|