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 --- protocols/YAMN/src/account.cpp | 208 ++++------- protocols/YAMN/src/browser/badconnect.cpp | 140 ++++--- protocols/YAMN/src/browser/browser.h | 23 +- protocols/YAMN/src/browser/mailbrowser.cpp | 566 ++++++++++++++--------------- protocols/YAMN/src/filterplugin.cpp | 3 +- protocols/YAMN/src/mails/mails.cpp | 20 +- protocols/YAMN/src/main.cpp | 53 --- protocols/YAMN/src/main.h | 2 - protocols/YAMN/src/proto/pop3/pop3comm.cpp | 417 +++++++++------------ protocols/YAMN/src/proto/pop3/pop3comm.h | 64 +--- protocols/YAMN/src/proto/pop3/pop3opt.cpp | 389 ++++++++++---------- protocols/YAMN/src/protoplugin.cpp | 55 ++- protocols/YAMN/src/services.cpp | 39 +- protocols/YAMN/src/stdafx.h | 59 +-- protocols/YAMN/src/synchro.cpp | 289 ++++++--------- protocols/YAMN/src/version.h | 6 +- protocols/YAMN/src/yamn.cpp | 92 +---- 17 files changed, 992 insertions(+), 1433 deletions(-) (limited to 'protocols/YAMN/src') diff --git a/protocols/YAMN/src/account.cpp b/protocols/YAMN/src/account.cpp index 46b7782ab0..55c9dbb9a9 100644 --- a/protocols/YAMN/src/account.cpp +++ b/protocols/YAMN/src/account.cpp @@ -17,12 +17,6 @@ static mir_cs csAccountStatusCS; // When 2 threads want to write to file... static mir_cs csFileWritingCS; -struct CExportedFunctions AccountExportedFcn[] = -{ - {YAMN_GETSTATUSID, (void *)GetStatusFcn}, - {YAMN_SETSTATUSID, (void *)SetStatusFcn}, -}; - struct CExportedServices AccountExportedSvc[] = { {MS_YAMN_CREATEPLUGINACCOUNT, CreatePluginAccountSvc}, @@ -39,7 +33,7 @@ struct CExportedServices AccountExportedSvc[] = INT_PTR CreatePluginAccountSvc(WPARAM wParam, LPARAM lParam) { - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; + YAMN_PROTOPLUGIN *Plugin = (YAMN_PROTOPLUGIN *)wParam; uint32_t AccountVersion = (uint32_t)lParam; //test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match) @@ -53,7 +47,7 @@ INT_PTR CreatePluginAccountSvc(WPARAM wParam, LPARAM lParam) NewAccount = Plugin->Fcn->NewAccountFcnPtr(Plugin, YAMN_ACCOUNTVERSION); else //We suggest plugin uses standard CAccount structure, so we create it - NewAccount = new struct CAccount; + NewAccount = new CAccount(); //If not created successfully if (NewAccount == nullptr) @@ -90,15 +84,7 @@ INT_PTR DeletePluginAccountSvc(WPARAM wParam, LPARAM) int InitAccount(CAccount *Which) { - //initialize synchronizing objects - Which->AccountAccessSO = new SWMRG; - SWMRGInitialize(Which->AccountAccessSO, nullptr); - Which->MessagesAccessSO = new SWMRG; - SWMRGInitialize(Which->MessagesAccessSO, nullptr); - Which->UsingThreads = new SCOUNTER; - SWMRGInitialize(Which->MessagesAccessSO, nullptr); - - //zero memory, where timestamps are stored + // zero memory, where timestamps are stored memset(&Which->LastChecked, 0, sizeof(Which->LastChecked)); memset(&Which->LastSChecked, 0, sizeof(Which->LastSChecked)); memset(&Which->LastSynchronised, 0, sizeof(Which->LastSynchronised)); @@ -111,7 +97,7 @@ int InitAccount(CAccount *Which) Which->StatusFlags = YAMN_ACC_ST1 + YAMN_ACC_ST7; Which->Next = nullptr; - Which->Server = new struct CServer; + Which->Server = new CServer(); Which->AbleToWork = TRUE; return 1; @@ -132,11 +118,6 @@ void DeInitAccount(CAccount *Which) delete[] Which->Server; } - SWMRGDelete(Which->AccountAccessSO); - delete Which->AccountAccessSO; - SWMRGDelete(Which->MessagesAccessSO); - delete Which->MessagesAccessSO; - delete Which->UsingThreads; DeleteMessagesToEndFcn(Which, (HYAMNMAIL)Which->Mails); } @@ -144,10 +125,11 @@ void StopSignalFcn(CAccount *Which) //set event that we are going to delete account { Which->AbleToWork = FALSE; - //do not use synchronizing objects anymore - //any access to these objects then ends with WAIT_FAILED - SetEvent(Which->AccountAccessSO->hFinishEV); - SetEvent(Which->MessagesAccessSO->hFinishEV); + + // do not use synchronizing objects anymore + // any access to these objects then ends with WAIT_FAILED + Which->AccountAccessSO.Stop(); + Which->MessagesAccessSO.Stop(); } void CodeDecodeString(char *Dest, BOOL Encrypt) @@ -426,9 +408,9 @@ uint32_t ReadMessagesFromMemory(CAccount *Which, char **Parser, char *End) #endif if (items == nullptr) - items = ActualMail->MailData->TranslatedHeader = new struct CMimeItem; + items = ActualMail->MailData->TranslatedHeader = new CMimeItem(); else { - items->Next = new struct CMimeItem; + items->Next = new CMimeItem(); items = items->Next; } if (items == nullptr) @@ -548,15 +530,12 @@ uint32_t ReadAccountFromMemory(CAccount *Which, char **Parser, char *End) return Stat; // Read mails - WaitToWriteFcn(Which->MessagesAccessSO); - - if (Stat = ReadMessagesFromMemory(Which, Parser, End)) { - WriteDoneFcn(Which->MessagesAccessSO); - return Stat; + { + SWriteGuard sw(Which->MessagesAccessSO); + if (Stat = ReadMessagesFromMemory(Which, Parser, End)) + return Stat; } - WriteDoneFcn(Which->MessagesAccessSO); - // Read timestamps Which->LastChecked = *(SYSTEMTIME *)(*Parser); (*Parser) += sizeof(SYSTEMTIME); @@ -583,7 +562,7 @@ uint32_t ReadAccountFromMemory(CAccount *Which, char **Parser, char *End) return 0; } -static INT_PTR PerformAccountReading(HYAMNPROTOPLUGIN Plugin, char *MemFile, char *End) +static INT_PTR PerformAccountReading(YAMN_PROTOPLUGIN *Plugin, char *MemFile, char *End) { // Retrieve info for account from memory char *Parser; @@ -597,41 +576,38 @@ static INT_PTR PerformAccountReading(HYAMNPROTOPLUGIN Plugin, char *MemFile, cha return EACC_FILEVERSION; } Parser = MemFile + sizeof(Ver); - - SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE); - - if (nullptr == (ActualAccount = (CAccount *)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) { - SWMRGDoneWriting(Plugin->AccountBrowserSO); - delete[] MemFile; - return EACC_ALLOC; + { + SWriteGuard swb(Plugin->AccountBrowserSO); + if (nullptr == (ActualAccount = (CAccount *)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) { + delete[] MemFile; + return EACC_ALLOC; + } } FirstAllocatedAccount = ActualAccount; do { CAccount *Temp; + { + SWriteGuard swb(Plugin->AccountBrowserSO); + Stat = ReadAccountFromMemory(ActualAccount, &Parser, End); - WaitToWriteFcn(ActualAccount->AccountAccessSO); - Stat = ReadAccountFromMemory(ActualAccount, &Parser, End); + if (ActualAccount->StatusFlags & (YAMN_ACC_STARTA | YAMN_ACC_STARTS)) + ActualAccount->TimeLeft = 1; //check on loading - if (ActualAccount->StatusFlags & (YAMN_ACC_STARTA | YAMN_ACC_STARTS)) - ActualAccount->TimeLeft = 1; //check on loading + if (Stat && (Stat != EACC_ENDOFFILE)) { + for (ActualAccount = FirstAllocatedAccount; ActualAccount != nullptr; ActualAccount = Temp) { + Temp = ActualAccount->Next; + delete ActualAccount; + } + delete[] MemFile; + if (Plugin->FirstAccount == FirstAllocatedAccount) + Plugin->FirstAccount = nullptr; - if (Stat && (Stat != EACC_ENDOFFILE)) { - for (ActualAccount = FirstAllocatedAccount; ActualAccount != nullptr; ActualAccount = Temp) { - Temp = ActualAccount->Next; - delete ActualAccount; + return (INT_PTR)Stat; } - delete[] MemFile; - if (Plugin->FirstAccount == FirstAllocatedAccount) - Plugin->FirstAccount = nullptr; - - SWMRGDoneWriting(Plugin->AccountBrowserSO); - return (INT_PTR)Stat; } - WriteDoneFcn(ActualAccount->AccountAccessSO); - if ((Stat != EACC_ENDOFFILE) && (nullptr == (ActualAccount = (CAccount *)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)Plugin, (LPARAM)YAMN_ACCOUNTVERSION)))) { for (ActualAccount = FirstAllocatedAccount; ActualAccount != nullptr; ActualAccount = Temp) { Temp = ActualAccount->Next; @@ -641,12 +617,10 @@ static INT_PTR PerformAccountReading(HYAMNPROTOPLUGIN Plugin, char *MemFile, cha if (Plugin->FirstAccount == FirstAllocatedAccount) Plugin->FirstAccount = nullptr; - SWMRGDoneWriting(Plugin->AccountBrowserSO); return EACC_ALLOC; } } while (Stat != EACC_ENDOFFILE); - SWMRGDoneWriting(Plugin->AccountBrowserSO); delete[] MemFile; return 0; } @@ -659,7 +633,7 @@ INT_PTR AddAccountsFromFileSvc(WPARAM wParam, LPARAM lParam) if (Stat != NO_ERROR) return (INT_PTR)Stat; - return PerformAccountReading((HYAMNPROTOPLUGIN)wParam, MemFile, End); + return PerformAccountReading((YAMN_PROTOPLUGIN *)wParam, MemFile, End); } uint32_t WriteStringToFile(HANDLE File, char *Source) @@ -727,31 +701,29 @@ DWORD WriteMessagesToFile(HANDLE File, CAccount *Which) return 0; } -static INT_PTR PerformAccountWriting(HYAMNPROTOPLUGIN Plugin, HANDLE File) +static INT_PTR PerformAccountWriting(YAMN_PROTOPLUGIN *Plugin, HANDLE File) { DWORD WrittenBytes, Stat; CAccount *ActualAccount; uint32_t Ver = YAMN_ACCOUNTFILEVERSION; BOOL Writed = FALSE; - uint32_t ReturnValue = 0, EnterCode; + uint32_t ReturnValue = 0; - SWMRGWaitToRead(Plugin->AccountBrowserSO, INFINITE); + SReadGuard srb(Plugin->AccountBrowserSO); try { for (ActualAccount = Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) { - EnterCode = WaitToReadFcn(ActualAccount->AccountAccessSO); - if (EnterCode == WAIT_FINISH) //account is about to delete - { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra == WAIT_FINISH) { //account is about to delete ActualAccount = ActualAccount->Next; continue; } - if (EnterCode == WAIT_FAILED) //account is deleted + + if (sra == WAIT_FAILED) //account is deleted break; - if ((ActualAccount->Name == nullptr) || (*ActualAccount->Name == (wchar_t)0)) { - ReadDoneFcn(ActualAccount->AccountAccessSO); + if ((ActualAccount->Name == nullptr) || (*ActualAccount->Name == (wchar_t)0)) continue; - } if (!Writed && !WriteFile(File, &Ver, sizeof(Ver), &WrittenBytes, nullptr)) throw (uint32_t)EACC_SYSTEM; @@ -821,31 +793,20 @@ static INT_PTR PerformAccountWriting(HYAMNPROTOPLUGIN Plugin, HANDLE File) if (Stat = ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr(File, ActualAccount)) throw (uint32_t)Stat; - WaitToReadFcn(ActualAccount->MessagesAccessSO); - - if (Stat = WriteMessagesToFile(File, ActualAccount)) { - - ReadDoneFcn(ActualAccount->MessagesAccessSO); + if (Stat = WriteMessagesToFile(File, ActualAccount)) throw (uint32_t)Stat; - } - - ReadDoneFcn(ActualAccount->MessagesAccessSO); if ((!WriteFile(File, (char *)&ActualAccount->LastChecked, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) || (!WriteFile(File, (char *)&ActualAccount->LastSChecked, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) || (!WriteFile(File, (char *)&ActualAccount->LastSynchronised, sizeof(SYSTEMTIME), &WrittenBytes, nullptr)) || (!WriteFile(File, (char *)&ActualAccount->LastMail, sizeof(SYSTEMTIME), &WrittenBytes, nullptr))) throw (uint32_t)Stat; - - ReadDoneFcn(ActualAccount->AccountAccessSO); } } catch (uint32_t ErrorCode) { - ReadDoneFcn(ActualAccount->AccountAccessSO); ReturnValue = ErrorCode; } - SWMRGDoneReading(Plugin->AccountBrowserSO); CloseHandle(File); return 0; } @@ -853,7 +814,7 @@ static INT_PTR PerformAccountWriting(HYAMNPROTOPLUGIN Plugin, HANDLE File) // Writes accounts to file INT_PTR WriteAccountsToFileSvc(WPARAM wParam, LPARAM lParam) { - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; + YAMN_PROTOPLUGIN *Plugin = (YAMN_PROTOPLUGIN*)wParam; mir_cslock lck(csFileWritingCS); HANDLE hFile = CreateFile((wchar_t *)lParam, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); @@ -865,23 +826,21 @@ INT_PTR WriteAccountsToFileSvc(WPARAM wParam, LPARAM lParam) INT_PTR FindAccountByNameSvc(WPARAM wParam, LPARAM lParam) { - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; + YAMN_PROTOPLUGIN *Plugin = (YAMN_PROTOPLUGIN*)wParam; char *SearchedAccount = (char *)lParam; - CAccount *Finder; - SWMRGWaitToRead(Plugin->AccountBrowserSO, INFINITE); + SReadGuard srb(Plugin->AccountBrowserSO); - for (Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) + for (auto *Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) if ((Finder->Name != nullptr) && (0 == mir_strcmp(SearchedAccount, Finder->Name))) - break; + return (INT_PTR)Finder; - SWMRGDoneReading(Plugin->AccountBrowserSO); - return (INT_PTR)Finder; + return 0; } INT_PTR GetNextFreeAccountSvc(WPARAM wParam, LPARAM lParam) { - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; + YAMN_PROTOPLUGIN *Plugin = (YAMN_PROTOPLUGIN*)wParam; CAccount *Finder; if (Plugin->FirstAccount == nullptr) { @@ -920,7 +879,7 @@ INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM lParam) //4. wait until UsingThread Event is signaled //5. delete account from memory - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; + YAMN_PROTOPLUGIN *Plugin = (YAMN_PROTOPLUGIN*)wParam; CAccount *Which = (CAccount *)lParam; CAccount *Finder; @@ -930,26 +889,24 @@ INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM lParam) if (Plugin->Fcn->StopAccountFcnPtr != nullptr) Plugin->Fcn->StopAccountFcnPtr(Which); - //2. wait to get write access - SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE); + { + // 2. wait to get write access + SWriteGuard swb(Plugin->AccountBrowserSO); - //3. remove from queue (chained list) - if (Plugin->FirstAccount == nullptr) { - SWMRGDoneWriting(Plugin->AccountBrowserSO); - return 0; - } - if (Plugin->FirstAccount == Which) { - Finder = Plugin->FirstAccount->Next; - Plugin->FirstAccount = Finder; - } - else { - for (Finder = Plugin->FirstAccount; Which != Finder->Next; Finder = Finder->Next); - Finder->Next = Finder->Next->Next; + // 3. remove from queue (chained list) + if (Plugin->FirstAccount == nullptr) { + return 0; + } + if (Plugin->FirstAccount == Which) { + Finder = Plugin->FirstAccount->Next; + Plugin->FirstAccount = Finder; + } + else { + for (Finder = Plugin->FirstAccount; Which != Finder->Next; Finder = Finder->Next); + Finder->Next = Finder->Next->Next; + } } - //leave write access - SWMRGDoneWriting(Plugin->AccountBrowserSO); - //4. wait while event "UsingThread" is not signaled // And what to do, if this event will be signaled in 1 hour? (Although it's paranoia, because we have sent "delete signal", so // other threads do not start any new work with actual account) We will wait in blocked state? @@ -968,16 +925,16 @@ INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM lParam) void __cdecl DeleteAccountInBackground(void *Value) { CAccount *Which = (CAccount *)Value; - WaitForSingleObject(Which->UsingThreads->Event, INFINITE); + WaitForSingleObject(Which->UsingThreads.GetEvent(), INFINITE); CallService(MS_YAMN_DELETEPLUGINACCOUNT, (WPARAM)Which, 0); } -int StopAccounts(HYAMNPROTOPLUGIN Plugin) +int StopAccounts(YAMN_PROTOPLUGIN *Plugin) { CAccount *Finder; //1. wait to get write access - SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE); + SWriteGuard swb(Plugin->AccountBrowserSO); for (Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) { //2. set stop signal @@ -987,36 +944,32 @@ int StopAccounts(HYAMNPROTOPLUGIN Plugin) Plugin->Fcn->StopAccountFcnPtr(Finder); } - //leave write access - SWMRGDoneWriting(Plugin->AccountBrowserSO); - //Now, account is stopped. It can be removed from memory... return 1; } -int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin, BOOL GetAccountBrowserAccess) +int WaitForAllAccounts(YAMN_PROTOPLUGIN *Plugin, BOOL GetAccountBrowserAccess) { if (GetAccountBrowserAccess) { //1. wait to get write access - SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE); + Plugin->AccountBrowserSO.WaitToWrite(); } for (CAccount *Finder = Plugin->FirstAccount; Finder != nullptr; Finder = Finder->Next) { //2. wait for signal that account is not in use - WaitForSingleObject(Finder->UsingThreads->Event, INFINITE); - SetEvent(Finder->UsingThreads->Event); + WaitForSingleObject(Finder->UsingThreads.GetEvent(), INFINITE); + SetEvent(Finder->UsingThreads.GetEvent()); } if (GetAccountBrowserAccess) { //leave write access - SWMRGDoneWriting(Plugin->AccountBrowserSO); + Plugin->AccountBrowserSO.DoneWriting(); } return 1; } -int DeleteAccounts(HYAMNPROTOPLUGIN Plugin) +int DeleteAccounts(YAMN_PROTOPLUGIN *Plugin) { - //1. wait to get write access - SWMRGWaitToWrite(Plugin->AccountBrowserSO, INFINITE); + SWriteGuard swb(Plugin->AccountBrowserSO); WaitForAllAccounts(Plugin, FALSE); @@ -1025,9 +978,6 @@ int DeleteAccounts(HYAMNPROTOPLUGIN Plugin) DeletePluginAccountSvc((WPARAM)Finder, 0); Finder = Next; } - - //leave write access - SWMRGDoneWriting(Plugin->AccountBrowserSO); return 1; } diff --git a/protocols/YAMN/src/browser/badconnect.cpp b/protocols/YAMN/src/browser/badconnect.cpp index 6e023ccf84..c6a2179f90 100644 --- a/protocols/YAMN/src/browser/badconnect.cpp +++ b/protocols/YAMN/src/browser/badconnect.cpp @@ -23,7 +23,8 @@ LRESULT CALLBACK BadConnectPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM si.cb = sizeof(si); CAccount *ActualAccount = (CAccount *)PUGetPluginData(hWnd); - if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra == WAIT_OBJECT_0) { if (ActualAccount->BadConnectN.App != nullptr) { wchar_t *Command; if (ActualAccount->BadConnectN.AppParam != nullptr) @@ -41,8 +42,6 @@ LRESULT CALLBACK BadConnectPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM delete[] Command; } } - - ReadDoneFcn(ActualAccount->AccountAccessSO); } PUDeletePopup(hWnd); @@ -76,57 +75,57 @@ INT_PTR CALLBACK DlgProcYAMNBadConnection(HWND hDlg, UINT msg, WPARAM wParam, LP wchar_t *Message1W = nullptr; POPUPDATAW BadConnectPopup = {}; - ActualAccount = ((struct BadConnectionParam *)lParam)->account; - ErrorCode = ((struct BadConnectionParam *)lParam)->errcode; - - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) - return FALSE; - - int size = (int)(mir_strlen(ActualAccount->Name) + mir_strlen(Translate(BADCONNECTTITLE))); - TitleStrA = new char[size]; - mir_snprintf(TitleStrA, size, Translate(BADCONNECTTITLE), ActualAccount->Name); - - ShowPopup = ActualAccount->BadConnectN.Flags & YAMN_ACC_POP; - ShowMsg = ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG; - ShowIco = ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO; - - if (ShowPopup) { - BadConnectPopup.lchIcon = g_plugin.getIcon(IDI_BADCONNECT); - BadConnectPopup.colorBack = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupB : GetSysColor(COLOR_BTNFACE); - BadConnectPopup.colorText = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupT : GetSysColor(COLOR_WINDOWTEXT); - BadConnectPopup.iSeconds = ActualAccount->BadConnectN.PopupTime; + ActualAccount = ((BadConnectionParam *)lParam)->account; + ErrorCode = ((BadConnectionParam *)lParam)->errcode; + { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (WAIT_OBJECT_0 != sra) + return FALSE; + + int size = (int)(mir_strlen(ActualAccount->Name) + mir_strlen(Translate(BADCONNECTTITLE))); + TitleStrA = new char[size]; + mir_snprintf(TitleStrA, size, Translate(BADCONNECTTITLE), ActualAccount->Name); + + ShowPopup = ActualAccount->BadConnectN.Flags & YAMN_ACC_POP; + ShowMsg = ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG; + ShowIco = ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO; + + if (ShowPopup) { + BadConnectPopup.lchIcon = g_plugin.getIcon(IDI_BADCONNECT); + BadConnectPopup.colorBack = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupB : GetSysColor(COLOR_BTNFACE); + BadConnectPopup.colorText = ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? ActualAccount->BadConnectN.PopupT : GetSysColor(COLOR_WINDOWTEXT); + BadConnectPopup.iSeconds = ActualAccount->BadConnectN.PopupTime; + + BadConnectPopup.PluginWindowProc = BadConnectPopupProc; + BadConnectPopup.PluginData = ActualAccount; + mir_wstrncpy(BadConnectPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(BadConnectPopup.lpwzContactName)); + } - BadConnectPopup.PluginWindowProc = BadConnectPopupProc; - BadConnectPopup.PluginData = ActualAccount; - mir_wstrncpy(BadConnectPopup.lpwzContactName, _A2T(ActualAccount->Name), _countof(BadConnectPopup.lpwzContactName)); - } + if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr != nullptr) { + Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode); + SetDlgItemText(hDlg, IDC_STATICMSG, Message1W); + wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE); + if (ShowPopup) + PUAddPopupW(&BadConnectPopup); + } + else if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringAFcnPtr != nullptr) { + Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode); + SetDlgItemText(hDlg, IDC_STATICMSG, Message1W); + wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE); + if (ShowPopup) + PUAddPopupW(&BadConnectPopup); + } + else { + Message1W = TranslateT("Unknown error"); + SetDlgItemText(hDlg, IDC_STATICMSG, Message1W); + wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE); + if (ShowPopup) + PUAddPopupW(&BadConnectPopup); + } - if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr != nullptr) { - Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode); - SetDlgItemText(hDlg, IDC_STATICMSG, Message1W); - wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE); - if (ShowPopup) - PUAddPopupW(&BadConnectPopup); - } - else if (ActualAccount->Plugin->Fcn != nullptr && ActualAccount->Plugin->Fcn->GetErrorStringAFcnPtr != nullptr) { - Message1W = ActualAccount->Plugin->Fcn->GetErrorStringWFcnPtr(ErrorCode); - SetDlgItemText(hDlg, IDC_STATICMSG, Message1W); - wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE); - if (ShowPopup) - PUAddPopupW(&BadConnectPopup); + if (!ShowMsg && !ShowIco) + DestroyWindow(hDlg); } - else { - Message1W = TranslateT("Unknown error"); - SetDlgItemText(hDlg, IDC_STATICMSG, Message1W); - wcsncpy_s(BadConnectPopup.lpwzText, Message1W, _TRUNCATE); - if (ShowPopup) - PUAddPopupW(&BadConnectPopup); - } - - if (!ShowMsg && !ShowIco) - DestroyWindow(hDlg); - - ReadDoneFcn(ActualAccount->AccountAccessSO); SetWindowTextA(hDlg, TitleStrA); delete[] TitleStrA; @@ -141,7 +140,6 @@ INT_PTR CALLBACK DlgProcYAMNBadConnection(HWND hDlg, UINT msg, WPARAM wParam, LP case WM_DESTROY: { NOTIFYICONDATA nid; - memset(&nid, 0, sizeof(NOTIFYICONDATA)); nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hDlg; @@ -182,27 +180,22 @@ INT_PTR CALLBACK DlgProcYAMNBadConnection(HWND hDlg, UINT msg, WPARAM wParam, LP return 0; } -void __cdecl BadConnection(void *Param) +static void __cdecl BadConnection(void *Param) { MSG msg; HWND hBadConnect; CAccount *ActualAccount; - struct BadConnectionParam MyParam = *(struct BadConnectionParam *)Param; - ActualAccount = MyParam.account; - - SCIncFcn(ActualAccount->UsingThreads); - - // we will not use params in stack anymore - SetEvent(MyParam.ThreadRunningEV); + auto *MyParam = (BadConnectionParam *)Param; + ActualAccount = MyParam->account; - __try { - hBadConnect = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_DLGBADCONNECT), nullptr, DlgProcYAMNBadConnection, (LPARAM)&MyParam); - Window_SetIcon_IcoLib(hBadConnect, g_plugin.getIconHandle(IDI_BADCONNECT)); + SCGuard sc(ActualAccount->UsingThreads); - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) - __leave; + hBadConnect = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_DLGBADCONNECT), nullptr, DlgProcYAMNBadConnection, (LPARAM)&MyParam); + Window_SetIcon_IcoLib(hBadConnect, g_plugin.getIconHandle(IDI_BADCONNECT)); + SReadGuard sra(ActualAccount->AccountAccessSO); + if (WAIT_OBJECT_0 == sra) { Skin_PlaySound(YAMN_CONNECTFAILSOUND); if (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) @@ -218,8 +211,7 @@ void __cdecl BadConnection(void *Param) mir_snwprintf(nid.szTip, L"%S%s", ActualAccount->Name, TranslateT(" - connection error")); Shell_NotifyIcon(NIM_ADD, &nid); } - - ReadDoneFcn(ActualAccount->AccountAccessSO); + sra.Uninit(); UpdateWindow(hBadConnect); while (GetMessage(&msg, nullptr, 0, 0)) { @@ -231,20 +223,12 @@ void __cdecl BadConnection(void *Param) if ((ActualAccount->Plugin->Fcn != nullptr) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != nullptr) && ActualAccount->AbleToWork) ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr(); } - __finally { - SCDecFcn(ActualAccount->UsingThreads); - } + delete MyParam; } int RunBadConnection(CAccount *acc, UINT_PTR iErrorCode, void *pUserInfo) { - BadConnectionParam param = {CreateEvent(nullptr, FALSE, FALSE, nullptr), acc, iErrorCode, pUserInfo}; - - HANDLE NewThread = mir_forkthread(BadConnection, ¶m); - if (nullptr == NewThread) - return 0; - - WaitForSingleObject(param.ThreadRunningEV, INFINITE); - CloseHandle(param.ThreadRunningEV); + BadConnectionParam param = { acc, iErrorCode, pUserInfo }; + mir_forkthread(BadConnection, new BadConnectionParam(param)); return 1; } diff --git a/protocols/YAMN/src/browser/browser.h b/protocols/YAMN/src/browser/browser.h index 0cb3f1a248..4cf0b55ed4 100644 --- a/protocols/YAMN/src/browser/browser.h +++ b/protocols/YAMN/src/browser/browser.h @@ -1,35 +1,24 @@ #ifndef __MAILBROWSER_H #define __MAILBROWSER_H -typedef struct MailBrowserWinParam -{ #define YAMN_MAILBROWSERVERSION 1 - HANDLE ThreadRunningEV; + +struct YAMN_MAILBROWSERPARAM +{ CAccount *account; uint32_t nflags; //flags YAMN_ACC_??? when new mails uint32_t nnflags; //flags YAMN_ACC_??? when no new mails void *Param; -} YAMN_MAILBROWSERPARAM,*PYAMN_MAILBROWSERPARAM; +}; -typedef struct MailShowMsgWinParam +struct YAMN_MAILSHOWPARAM { - HANDLE ThreadRunningEV; CAccount *account; HYAMNMAIL mail; -} YAMN_MAILSHOWPARAM, *PYAMN_MAILSHOWPARAM; - -typedef struct NoNewMailParam -{ -#define YAMN_NONEWMAILVERSION 1 - HANDLE ThreadRunningEV; - CAccount *account; - uint32_t flags; - void *Param; -} YAMN_NONEWMAILPARAM,*PYAMN_NONEWMAILPARAM; +}; struct BadConnectionParam { - HANDLE ThreadRunningEV; CAccount *account; UINT_PTR errcode; void *Param; diff --git a/protocols/YAMN/src/browser/mailbrowser.cpp b/protocols/YAMN/src/browser/mailbrowser.cpp index 18710224ee..1a320322ec 100644 --- a/protocols/YAMN/src/browser/mailbrowser.cpp +++ b/protocols/YAMN/src/browser/mailbrowser.cpp @@ -151,11 +151,6 @@ LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l // Dialog callback procedure for mail browser INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -// MailBrowser thread function creates window if needed, tray icon and plays sound -void __cdecl MailBrowser(void *Param); - -LRESULT CALLBACK ListViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - // Runs mail browser in new thread INT_PTR RunMailBrowserSvc(WPARAM, LPARAM); @@ -323,91 +318,92 @@ int UpdateMails(HWND hDlg, CAccount *ActualAccount, uint32_t nflags, uint32_t nn BOOL RunMailBrowser, RunPopups; struct CMailWinUserInfo *mwui = (struct CMailWinUserInfo *)GetWindowLongPtr(hDlg, DWLP_USER); - //now we ensure read access for account and write access for its mails - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) { - PostMessage(hDlg, WM_DESTROY, 0, 0); - return UPDATE_FAIL; - } - - if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO)) { - ReadDoneFcn(ActualAccount->AccountAccessSO); - PostMessage(hDlg, WM_DESTROY, 0, 0); - return UPDATE_FAIL; - } - memset(&MN, 0, sizeof(MN)); + //now we ensure read access for account and write access for its mails + { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (!sra.Succeeded()) { + PostMessage(hDlg, WM_DESTROY, 0, 0); + return UPDATE_FAIL; + } - for (HYAMNMAIL msgq = (HYAMNMAIL)ActualAccount->Mails; msgq != nullptr; msgq = msgq->Next) { - if (!LoadedMailData(msgq)) //check if mail is already in memory - { - Loaded = false; - if (nullptr == LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it - continue; + SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (!swm.Succeeded()) { + PostMessage(hDlg, WM_DESTROY, 0, 0); + return UPDATE_FAIL; } - else - Loaded = true; - IncrementMailCounters(msgq, &MN); + memset(&MN, 0, sizeof(MN)); - if (!Loaded) - UnloadMailData(msgq); //do not keep data for mail in memory - } + for (HYAMNMAIL msgq = (HYAMNMAIL)ActualAccount->Mails; msgq != nullptr; msgq = msgq->Next) { + if (!LoadedMailData(msgq)) //check if mail is already in memory + { + Loaded = false; + if (nullptr == LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it + continue; + } + else + Loaded = true; - if (mwui != nullptr) - mwui->UpdateMailsMessagesAccess = TRUE; - - //Now we are going to check if extracting data from mail headers are needed. - //If popups will be displayed or mailbrowser window - if ((((mwui != nullptr) && !(mwui->RunFirstTime)) && - ( - ((nnflags & YAMN_ACC_MSGP) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || - ((nflags & YAMN_ACC_MSGP) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC)) - ) - ) || //if mail window was displayed before and flag YAMN_ACC_MSGP is set - ((nnflags & YAMN_ACC_MSG) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if needed to run mailbrowser when no unseen and no unseen mail found - ((nflags & YAMN_ACC_MSG) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if unseen mails found, we sure run mailbrowser - ((nflags & YAMN_ACC_ICO) && (MN.Real.SysTrayUC + MN.Virtual.SysTrayUC)) - ) //if needed to run systray - RunMailBrowser = TRUE; - else - RunMailBrowser = FALSE; + IncrementMailCounters(msgq, &MN); - // if some popups with mails are needed to show - if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (MN.Real.PopupNC + MN.Virtual.PopupNC)) - RunPopups = TRUE; - else RunPopups = FALSE; + if (!Loaded) + UnloadMailData(msgq); //do not keep data for mail in memory + } - if (RunMailBrowser) - ChangeExistingMailStatus(GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount); - if (RunMailBrowser || RunPopups) - AddNewMailsToListView(hDlg == nullptr ? nullptr : GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount, nflags); - - if (RunMailBrowser) { - size_t len = mir_strlen(ActualAccount->Name) + mir_strlen(Translate(MAILBROWSERTITLE)) + 10; //+10 chars for numbers - char *TitleStrA = new char[len]; - wchar_t *TitleStrW = new wchar_t[len]; - - mir_snprintf(TitleStrA, len, Translate(MAILBROWSERTITLE), ActualAccount->Name, MN.Real.DisplayUC + MN.Virtual.DisplayUC, MN.Real.Display + MN.Virtual.Display); - MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, TitleStrA, -1, TitleStrW, (int)mir_strlen(TitleStrA) + 1); - SetWindowTextW(hDlg, TitleStrW); - delete[] TitleStrA; - delete[] TitleStrW; - } + if (mwui != nullptr) + mwui->UpdateMailsMessagesAccess = TRUE; + + //Now we are going to check if extracting data from mail headers are needed. + //If popups will be displayed or mailbrowser window + if ((((mwui != nullptr) && !(mwui->RunFirstTime)) && + ( + ((nnflags & YAMN_ACC_MSGP) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || + ((nflags & YAMN_ACC_MSGP) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC)) + ) + ) || //if mail window was displayed before and flag YAMN_ACC_MSGP is set + ((nnflags & YAMN_ACC_MSG) && !(MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if needed to run mailbrowser when no unseen and no unseen mail found + ((nflags & YAMN_ACC_MSG) && (MN.Real.BrowserUC + MN.Virtual.BrowserUC)) || //if unseen mails found, we sure run mailbrowser + ((nflags & YAMN_ACC_ICO) && (MN.Real.SysTrayUC + MN.Virtual.SysTrayUC)) + ) //if needed to run systray + RunMailBrowser = TRUE; + else + RunMailBrowser = FALSE; + + // if some popups with mails are needed to show + if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (MN.Real.PopupNC + MN.Virtual.PopupNC)) + RunPopups = TRUE; + else RunPopups = FALSE; + + if (RunMailBrowser) + ChangeExistingMailStatus(GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount); + if (RunMailBrowser || RunPopups) + AddNewMailsToListView(hDlg == nullptr ? nullptr : GetDlgItem(hDlg, IDC_LISTMAILS), ActualAccount, nflags); + + if (RunMailBrowser) { + size_t len = mir_strlen(ActualAccount->Name) + mir_strlen(Translate(MAILBROWSERTITLE)) + 10; //+10 chars for numbers + char *TitleStrA = new char[len]; + wchar_t *TitleStrW = new wchar_t[len]; + + mir_snprintf(TitleStrA, len, Translate(MAILBROWSERTITLE), ActualAccount->Name, MN.Real.DisplayUC + MN.Virtual.DisplayUC, MN.Real.Display + MN.Virtual.Display); + MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, TitleStrA, -1, TitleStrW, (int)mir_strlen(TitleStrA) + 1); + SetWindowTextW(hDlg, TitleStrW); + delete[] TitleStrA; + delete[] TitleStrW; + } - DoMailActions(hDlg, ActualAccount, &MN, nflags, nnflags); + DoMailActions(hDlg, ActualAccount, &MN, nflags, nnflags); - SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_NEW, 0, YAMN_MSG_NEW, YAMN_FLAG_REMOVE); //rempve the new flag - if (!RunMailBrowser) - SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_UNSEEN, YAMN_MSG_STAYUNSEEN, YAMN_MSG_UNSEEN, YAMN_FLAG_REMOVE); //remove the unseen flag when it was not displayed and it has not "stay unseen" flag set + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_NEW, 0, YAMN_MSG_NEW, YAMN_FLAG_REMOVE); //rempve the new flag + if (!RunMailBrowser) + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_UNSEEN, YAMN_MSG_STAYUNSEEN, YAMN_MSG_UNSEEN, YAMN_FLAG_REMOVE); //remove the unseen flag when it was not displayed and it has not "stay unseen" flag set - if (mwui != nullptr) { - mwui->UpdateMailsMessagesAccess = FALSE; - mwui->RunFirstTime = FALSE; + if (mwui != nullptr) { + mwui->UpdateMailsMessagesAccess = FALSE; + mwui->RunFirstTime = FALSE; + } } - WriteDoneFcn(ActualAccount->MessagesAccessSO); - ReadDoneFcn(ActualAccount->AccountAccessSO); - if (RunMailBrowser) UpdateWindow(GetDlgItem(hDlg, IDC_LISTMAILS)); else if (hDlg != nullptr) @@ -562,14 +558,11 @@ int AddNewMailsToListView(HWND hListView, CAccount *ActualAccount, uint32_t nfla mir_wstrncpy(NewMailPopup.lpwzContactName, FromStr, _countof(NewMailPopup.lpwzContactName)); mir_wstrncpy(NewMailPopup.lpwzText, UnicodeHeader.Subject, _countof(NewMailPopup.lpwzText)); - PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)malloc(sizeof(YAMN_MAILSHOWPARAM)); - if (MailParam) { - MailParam->account = ActualAccount; - MailParam->mail = msgq; - MailParam->ThreadRunningEV = nullptr; - NewMailPopup.PluginData = MailParam; - PUAddPopupW(&NewMailPopup); - } + auto *MailParam = new YAMN_MAILSHOWPARAM; + MailParam->account = ActualAccount; + MailParam->mail = msgq; + NewMailPopup.PluginData = MailParam; + PUAddPopupW(&NewMailPopup); } if ((msgq->Flags & YAMN_MSG_UNSEEN) && (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN)) @@ -765,7 +758,7 @@ LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa MCONTACT hContact = 0; CAccount *Account; if (PluginParam) { - PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM; + YAMN_MAILSHOWPARAM *MailParam = new YAMN_MAILSHOWPARAM; memcpy(MailParam, (PINT_PTR)PluginParam, sizeof(YAMN_MAILSHOWPARAM)); hContact = MailParam->account->hContact; Account = MailParam->account; @@ -782,11 +775,12 @@ LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa } else Account = (CAccount *)hContact; //???? - if (WAIT_OBJECT_0 == WaitToReadFcn(Account->AccountAccessSO)) { + SReadGuard sra(Account->AccountAccessSO); + if (sra.Succeeded()) { switch (msg) { case WM_COMMAND: { - YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, Account, + YAMN_MAILBROWSERPARAM Param = { Account, (Account->NewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG, (Account->NoNewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG}; @@ -794,7 +788,6 @@ LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa } break; } - ReadDoneFcn(Account->AccountAccessSO); } } if ((Account->NewMailN.Flags & YAMN_ACC_CONT) && !(Account->NewMailN.Flags & YAMN_ACC_CONTNOEVENT)) @@ -807,8 +800,8 @@ LRESULT CALLBACK NewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa break; case UM_FREEPLUGINDATA: { - PYAMN_MAILSHOWPARAM mpd = (PYAMN_MAILSHOWPARAM)PUGetPluginData(hWnd); - if ((mpd) && (INT_PTR)mpd != -1)free(mpd); + auto *mpd = (YAMN_MAILSHOWPARAM*)PUGetPluginData(hWnd); + delete mpd; return FALSE; } case UM_INITPOPUP: @@ -858,11 +851,12 @@ LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l } else ActualAccount = (CAccount *)hContact; - if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra.Succeeded()) { switch (msg) { case WM_COMMAND: { - YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr}; + YAMN_MAILBROWSERPARAM Param = { ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr}; Param.nnflags = Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account Param.nnflags = Param.nnflags & ~YAMN_ACC_POP; @@ -874,7 +868,6 @@ LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l } break; } - ReadDoneFcn(ActualAccount->AccountAccessSO); } PUDeletePopup(hWnd); } @@ -1183,7 +1176,7 @@ INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPAR switch (msg) { case WM_INITDIALOG: { - PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)lParam; + YAMN_MAILSHOWPARAM *MailParam = (YAMN_MAILSHOWPARAM*)lParam; wchar_t *iHeaderW = nullptr; wchar_t *iValueW = nullptr; int StrLen; @@ -1220,8 +1213,7 @@ INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPAR case WM_YAMN_CHANGECONTENT: { - PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM) - (lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER)); + auto *MailParam = (YAMN_MAILSHOWPARAM*)(lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER)); HWND hListView = GetDlgItem(hDlg, IDC_LISTHEADERS); HWND hEdit = GetDlgItem(hDlg, IDC_EDITBODY); //do not redraw @@ -1373,11 +1365,10 @@ INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPAR case WM_YAMN_STOPACCOUNT: { - PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM) - (lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER)); - + auto *MailParam = (YAMN_MAILSHOWPARAM*)(lParam ? lParam : GetWindowLongPtr(hDlg, DWLP_USER)); if (nullptr == MailParam) break; + if ((CAccount *)wParam != MailParam->account) break; @@ -1437,7 +1428,7 @@ INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPAR if (wParam == SIZE_RESTORED) { HWND hList = GetDlgItem(hDlg, IDC_LISTHEADERS); HWND hEdit = GetDlgItem(hDlg, IDC_EDITBODY); - BOOL isBodyShown = ((PYAMN_MAILSHOWPARAM)(GetWindowLongPtr(hDlg, DWLP_USER)))->mail->Flags & YAMN_MSG_BODYRECEIVED; + BOOL isBodyShown = ((YAMN_MAILSHOWPARAM*)(GetWindowLongPtr(hDlg, DWLP_USER)))->mail->Flags & YAMN_MSG_BODYRECEIVED; HeadSizeX = LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left; HeadSizeY = HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top; int localSplitPos = (HeadSplitPos * HeadSizeY) / 1000; @@ -1512,38 +1503,76 @@ INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg, UINT msg, WPARAM wParam, LPAR void __cdecl ShowEmailThread(void *Param) { - struct MailShowMsgWinParam MyParam = *(struct MailShowMsgWinParam *)Param; + auto *MyParam = (YAMN_MAILSHOWPARAM *)Param; - SCIncFcn(MyParam.account->UsingThreads); + SCGuard sc(MyParam->account->UsingThreads); - if (MyParam.mail->MsgWindow) { - //if (!BringWindowToTop(MyParam.mail->MsgWindow)) { - if (!SetForegroundWindow(MyParam.mail->MsgWindow)) { - SendMessage(MyParam.mail->MsgWindow, WM_DESTROY, 0, 0); - MyParam.mail->MsgWindow = nullptr; + if (MyParam->mail->MsgWindow) { + if (!SetForegroundWindow(MyParam->mail->MsgWindow)) { + SendMessage(MyParam->mail->MsgWindow, WM_DESTROY, 0, 0); + MyParam->mail->MsgWindow = nullptr; goto CREADTEVIEWMESSAGEWINDOW; } - if (IsIconic(MyParam.mail->MsgWindow)) - OpenIcon(MyParam.mail->MsgWindow); + if (IsIconic(MyParam->mail->MsgWindow)) + OpenIcon(MyParam->mail->MsgWindow); } else { CREADTEVIEWMESSAGEWINDOW: - MyParam.mail->MsgWindow = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGSHOWMESSAGE), nullptr, DlgProcYAMNShowMessage, (LPARAM)&MyParam); - WindowList_Add(YAMNVar.MessageWnds, MyParam.mail->MsgWindow); + MyParam->mail->MsgWindow = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGSHOWMESSAGE), nullptr, DlgProcYAMNShowMessage, (LPARAM)MyParam); + WindowList_Add(YAMNVar.MessageWnds, MyParam->mail->MsgWindow); MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { - if (MyParam.mail->MsgWindow == nullptr || !IsDialogMessage(MyParam.mail->MsgWindow, &msg)) { /* Wine fix. */ + if (MyParam->mail->MsgWindow == nullptr || !IsDialogMessage(MyParam->mail->MsgWindow, &msg)) { /* Wine fix. */ TranslateMessage(&msg); DispatchMessage(&msg); } } - WindowList_Remove(YAMNVar.MessageWnds, MyParam.mail->MsgWindow); - MyParam.mail->MsgWindow = nullptr; + WindowList_Remove(YAMNVar.MessageWnds, MyParam->mail->MsgWindow); + MyParam->mail->MsgWindow = nullptr; } - SCDecFcn(MyParam.account->UsingThreads); - delete (struct MailShowMsgWinParam *)Param; + delete MyParam; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Mail browser window + +static LRESULT CALLBACK ListViewSubclassProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndParent = GetParent(hDlg); + + switch (msg) { + case WM_GETDLGCODE: + { + LPMSG lpmsg = (LPMSG)lParam; + if (lpmsg != nullptr && lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_RETURN) + return DLGC_WANTALLKEYS; + } + break; + + case WM_KEYDOWN: + { + BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; + BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000; + BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; + + switch (wParam) { + case 'A': // ctrl-a + if (!isAlt && !isShift && isCtrl) SendMessage(hwndParent, WM_COMMAND, IDC_BTNCHECKALL, 0); + break; + case VK_RETURN: + case VK_SPACE: + if (!isAlt && !isShift && !isCtrl) SendMessage(hwndParent, WM_YAMN_SHOWSELECTED, 0, 0); + break; + case VK_DELETE: + SendMessage(hwndParent, WM_COMMAND, IDC_BTNDEL, 0); + break; + } + } + break; + } + return mir_callNextSubclass(hDlg, ListViewSubclassProc, msg, wParam, lParam); } INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -1555,13 +1584,13 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR switch (msg) { case WM_INITDIALOG: { - struct MailBrowserWinParam *MyParam = (struct MailBrowserWinParam *)lParam; + auto *MyParam = (YAMN_MAILBROWSERPARAM *)lParam; ListView_SetUnicodeFormat(GetDlgItem(hDlg, IDC_LISTMAILS), TRUE); ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_LISTMAILS), LVS_EX_FULLROWSELECT); ActualAccount = MyParam->account; - mwui = new struct CMailWinUserInfo; + mwui = new CMailWinUserInfo(); mwui->Account = ActualAccount; mwui->TrayIconState = 0; mwui->UpdateMailsMessagesAccess = FALSE; @@ -1569,7 +1598,9 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR mwui->RunFirstTime = TRUE; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)mwui); - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) { + + SReadGuard sra(ActualAccount->AccountAccessSO); + if (!sra.Succeeded()) { DestroyWindow(hDlg); return FALSE; } @@ -1604,16 +1635,15 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR else EnableWindow(GetDlgItem(hDlg, IDC_BTNAPP), FALSE); - ReadDoneFcn(ActualAccount->AccountAccessSO); + sra.Uninit(); WindowList_Add(YAMNVar.MessageWnds, hDlg); WindowList_Add(YAMNVar.NewMailAccountWnd, hDlg, (UINT_PTR)ActualAccount); - { - wchar_t accstatus[512]; - GetStatusFcn(ActualAccount, accstatus); - SetDlgItemText(hDlg, IDC_STSTATUS, accstatus); - } + wchar_t accstatus[512]; + GetStatusFcn(ActualAccount, accstatus); + SetDlgItemText(hDlg, IDC_STSTATUS, accstatus); + SetTimer(hDlg, TIMER_FLASHING, 500, nullptr); if (ActualAccount->hContact != NULL) @@ -1657,31 +1687,29 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR WindowList_Remove(YAMNVar.NewMailAccountWnd, hDlg); WindowList_Remove(YAMNVar.MessageWnds, hDlg); + { + SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (!swm.Succeeded()) + break; - if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO)) - break; - - //delete mails from queue, which are deleted from server (spam level 3 mails e.g.) - for (HYAMNMAIL Parser = (HYAMNMAIL)ActualAccount->Mails; Parser != nullptr; Parser = Parser->Next) { - if ((Parser->Flags & YAMN_MSG_DELETED) && YAMN_MSG_SPAML(Parser->Flags, YAMN_MSG_SPAML3) && mwui->Seen) //if spaml3 was already deleted and user knows about it - { - DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, Parser, 1); - CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)Parser); + // delete mails from queue, which are deleted from server (spam level 3 mails e.g.) + for (HYAMNMAIL Parser = (HYAMNMAIL)ActualAccount->Mails; Parser != nullptr; Parser = Parser->Next) { + if ((Parser->Flags & YAMN_MSG_DELETED) && YAMN_MSG_SPAML(Parser->Flags, YAMN_MSG_SPAML3) && mwui->Seen) //if spaml3 was already deleted and user knows about it + { + DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, Parser, 1); + CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)Parser); + } } - } - - //mark mails as read (remove "new" and "unseen" flags) - if (mwui->Seen) - SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY, 0, YAMN_MSG_NEW | YAMN_MSG_UNSEEN, 0); - - WriteDoneFcn(ActualAccount->MessagesAccessSO); - NOTIFYICONDATA nid; - memset(&nid, 0, sizeof(NOTIFYICONDATA)); + // mark mails as read (remove "new" and "unseen" flags) + if (mwui->Seen) + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY, 0, YAMN_MSG_NEW | YAMN_MSG_UNSEEN, 0); + } delete mwui; SetWindowLongPtr(hDlg, DWLP_USER, NULL); + NOTIFYICONDATA nid = {}; nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hDlg; nid.uID = 0; @@ -1769,17 +1797,17 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR switch (lParam) { case WM_LBUTTONDBLCLK: - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) { - return 0; - } + { + SReadGuard sra(ActualAccount->AccountAccessSO, 0); + if (!sra.Succeeded()) + return 0; - if (ActualAccount->AbilityFlags & YAMN_ACC_BROWSE) { - ShowWindow(hDlg, SW_SHOWNORMAL); - SetForegroundWindow(hDlg); + if (ActualAccount->AbilityFlags & YAMN_ACC_BROWSE) { + ShowWindow(hDlg, SW_SHOWNORMAL); + SetForegroundWindow(hDlg); + } + else DestroyWindow(hDlg); } - else DestroyWindow(hDlg); - - ReadDoneFcn(ActualAccount->AccountAccessSO); break; } break; @@ -1797,7 +1825,7 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR ListView_GetItem(GetDlgItem(hDlg, IDC_LISTMAILS), &item); HYAMNMAIL ActualMail = (HYAMNMAIL)item.lParam; if (nullptr != ActualMail) { - PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM; + auto *MailParam = new YAMN_MAILSHOWPARAM; MailParam->account = GetWindowAccount(hDlg); MailParam->mail = ActualMail; mir_forkthread(ShowEmailThread, MailParam); @@ -1842,7 +1870,8 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR memset(&si, 0, sizeof(si)); si.cb = sizeof(si); - if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra.Succeeded()) { if (ActualAccount->NewMailN.App != nullptr) { wchar_t *Command; if (ActualAccount->NewMailN.AppParam != nullptr) @@ -1860,8 +1889,6 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR delete[] Command; } } - - ReadDoneFcn(ActualAccount->AccountAccessSO); } if (!(GetKeyState(VK_SHIFT) & 0x8000) && !(GetKeyState(VK_CONTROL) & 0x8000)) @@ -1883,58 +1910,56 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR LVITEM item; item.stateMask = 0xFFFFFFFF; - - if (WAIT_OBJECT_0 == WaitToWriteFcn(ActualAccount->MessagesAccessSO)) { - for (int i = 0; i < Items; i++) { - item.iItem = i; - item.iSubItem = 0; - item.mask = LVIF_PARAM | LVIF_STATE; - item.stateMask = 0xFFFFFFFF; - ListView_GetItem(GetDlgItem(hDlg, IDC_LISTMAILS), &item); - ActualMail = (HYAMNMAIL)item.lParam; - if (nullptr == ActualMail) - break; - if (item.state & LVIS_SELECTED) { - ActualMail->Flags |= YAMN_MSG_USERDELETE; //set to mail we are going to delete it - Total++; + { + SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (swm.Succeeded()) { + for (int i = 0; i < Items; i++) { + item.iItem = i; + item.iSubItem = 0; + item.mask = LVIF_PARAM | LVIF_STATE; + item.stateMask = 0xFFFFFFFF; + ListView_GetItem(GetDlgItem(hDlg, IDC_LISTMAILS), &item); + ActualMail = (HYAMNMAIL)item.lParam; + if (nullptr == ActualMail) + break; + if (item.state & LVIS_SELECTED) { + ActualMail->Flags |= YAMN_MSG_USERDELETE; //set to mail we are going to delete it + Total++; + } } } + } - // Enable write-access to mails - WriteDoneFcn(ActualAccount->MessagesAccessSO); - - if (Total) { - wchar_t DeleteMsg[1024]; - - mir_snwprintf(DeleteMsg, TranslateT("Do you really want to delete %d selected mails?"), Total); - if (IDOK == MessageBox(hDlg, DeleteMsg, TranslateT("Delete confirmation"), MB_OKCANCEL | MB_ICONWARNING)) { - struct DeleteParam ParamToDeleteMails = {YAMN_DELETEVERSION, ThreadRunningEV, ActualAccount, nullptr}; - - // Find if there's mail marked to delete, which was deleted before - if (WAIT_OBJECT_0 == WaitToWriteFcn(ActualAccount->MessagesAccessSO)) { - for (ActualMail = (HYAMNMAIL)ActualAccount->Mails; ActualMail != nullptr; ActualMail = ActualMail->Next) { - if ((ActualMail->Flags & YAMN_MSG_DELETED) && ((ActualMail->Flags & YAMN_MSG_USERDELETE))) //if selected mail was already deleted - { - DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, ActualMail, 1); - CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)ActualMail); //delete it from memory - continue; - } + if (Total) { + wchar_t DeleteMsg[1024]; + + mir_snwprintf(DeleteMsg, TranslateT("Do you really want to delete %d selected mails?"), Total); + if (IDOK == MessageBox(hDlg, DeleteMsg, TranslateT("Delete confirmation"), MB_OKCANCEL | MB_ICONWARNING)) { + struct DeleteParam ParamToDeleteMails = {YAMN_DELETEVERSION, ThreadRunningEV, ActualAccount, nullptr}; + + // Find if there's mail marked to delete, which was deleted before + SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (swm.Succeeded()) { + for (ActualMail = (HYAMNMAIL)ActualAccount->Mails; ActualMail != nullptr; ActualMail = ActualMail->Next) { + if ((ActualMail->Flags & YAMN_MSG_DELETED) && ((ActualMail->Flags & YAMN_MSG_USERDELETE))) //if selected mail was already deleted + { + DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, ActualMail, 1); + CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)ActualAccount->Plugin, (LPARAM)ActualMail); //delete it from memory + continue; } - // Set flag to marked mails that they can be deleted - SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_DELETEOK, 1); - // Create new thread which deletes marked mails. - HANDLE NewThread = mir_forkthread(ActualAccount->Plugin->Fcn->DeleteMailsFcnPtr, &ParamToDeleteMails); - if (NewThread != nullptr) - WaitForSingleObject(ThreadRunningEV, INFINITE); - - // Enable write-access to mails - WriteDoneFcn(ActualAccount->MessagesAccessSO); } + // Set flag to marked mails that they can be deleted + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_DELETEOK, 1); + // Create new thread which deletes marked mails. + HANDLE NewThread = mir_forkthread(ActualAccount->Plugin->Fcn->DeleteMailsFcnPtr, &ParamToDeleteMails); + if (NewThread != nullptr) + WaitForSingleObject(ThreadRunningEV, INFINITE); } - else //else mark messages that they are not to be deleted - SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_USERDELETE, 0); } + else //else mark messages that they are not to be deleted + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails, YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE, 0, YAMN_MSG_USERDELETE, 0); } + CloseHandle(ThreadRunningEV); if (g_plugin.getByte(YAMN_CLOSEDELETE, 0)) DestroyWindow(hDlg); @@ -1990,7 +2015,8 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR case LVN_COLUMNCLICK: if (nullptr != (ActualAccount = GetWindowAccount(hDlg))) { NM_LISTVIEW *pNMListView = (NM_LISTVIEW *)lParam; - if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra.Succeeded()) { switch ((int)pNMListView->iSubItem) { case 0: bFrom = !bFrom; @@ -2008,7 +2034,6 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR break; } ListView_SortItems(pNMListView->hdr.hwndFrom, ListViewCompareProc, pNMListView->iSubItem); - ReadDoneFcn(ActualAccount->AccountAccessSO); } } break; @@ -2036,7 +2061,7 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR ActualMail = (HYAMNMAIL)readItemLParam(cd->nmcd.hdr.hwndFrom, cd->nmcd.dwItemSpec); if (!umma) - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->MessagesAccessSO)) + if (WAIT_OBJECT_0 != ActualAccount->MessagesAccessSO.WaitToRead()) return 0; switch (ActualMail->Flags & YAMN_MSG_SPAMMASK) { @@ -2060,7 +2085,7 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR PaintCode = CDRF_DODEFAULT; if (!umma) - ReadDoneFcn(ActualAccount->MessagesAccessSO); + ActualAccount->MessagesAccessSO.DoneReading(); } break; default: @@ -2127,105 +2152,59 @@ INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg, UINT msg, WPARAM wParam, LPAR return 0; } -LRESULT CALLBACK ListViewSubclassProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndParent = GetParent(hDlg); - - switch (msg) { - case WM_GETDLGCODE: - { - LPMSG lpmsg = (LPMSG)lParam; - if (lpmsg != nullptr) { - if (lpmsg->message == WM_KEYDOWN - && lpmsg->wParam == VK_RETURN) - return DLGC_WANTALLKEYS; - } - } - break; - - case WM_KEYDOWN: - { - BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; - BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000; - BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; - - switch (wParam) { - case 'A': // ctrl-a - if (!isAlt && !isShift && isCtrl) SendMessage(hwndParent, WM_COMMAND, IDC_BTNCHECKALL, 0); - break; - case VK_RETURN: - case VK_SPACE: - if (!isAlt && !isShift && !isCtrl) SendMessage(hwndParent, WM_YAMN_SHOWSELECTED, 0, 0); - break; - case VK_DELETE: - SendMessage(hwndParent, WM_COMMAND, IDC_BTNDEL, 0); - break; - } - } - break; - } - return mir_callNextSubclass(hDlg, ListViewSubclassProc, msg, wParam, lParam); -} - -void __cdecl MailBrowser(void *Param) +static void __cdecl MailBrowser(void *Param) { MSG msg; HWND hMailBrowser; BOOL WndFound = FALSE; - struct MailBrowserWinParam MyParam = *(struct MailBrowserWinParam *)Param; - CAccount *ActualAccount = MyParam.account; - SCIncFcn(ActualAccount->UsingThreads); - - // we will not use params in stack anymore - SetEvent(MyParam.ThreadRunningEV); - - __try { - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) - __leave; + auto *MyParam = (YAMN_MAILBROWSERPARAM *)Param; + CAccount *ActualAccount = MyParam->account; + SCGuard sc(ActualAccount->UsingThreads); + { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (!sra.Succeeded()) + return; if (!(ActualAccount->AbilityFlags & YAMN_ACC_BROWSE)) { - MyParam.nflags = MyParam.nflags & ~YAMN_ACC_MSG; - MyParam.nnflags = MyParam.nnflags & ~YAMN_ACC_MSG; + MyParam->nflags = MyParam->nflags & ~YAMN_ACC_MSG; + MyParam->nnflags = MyParam->nnflags & ~YAMN_ACC_MSG; } if (!(ActualAccount->AbilityFlags & YAMN_ACC_POPUP)) - MyParam.nflags = MyParam.nflags & ~YAMN_ACC_POP; - - ReadDoneFcn(ActualAccount->AccountAccessSO); - - if (nullptr != (hMailBrowser = WindowList_Find(YAMNVar.NewMailAccountWnd, (UINT_PTR)ActualAccount))) - WndFound = TRUE; - - if ((hMailBrowser == nullptr) && ((MyParam.nflags & YAMN_ACC_MSG) || (MyParam.nflags & YAMN_ACC_ICO) || (MyParam.nnflags & YAMN_ACC_MSG))) { - hMailBrowser = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGVIEWMESSAGES), nullptr, DlgProcYAMNMailBrowser, (LPARAM)&MyParam); - Window_SetIcon_IcoLib(hMailBrowser, g_plugin.getIconHandle(IDI_NEWMAIL)); - MoveWindow(hMailBrowser, PosX, PosY, SizeX, SizeY, TRUE); - } + MyParam->nflags = MyParam->nflags & ~YAMN_ACC_POP; + } - if (hMailBrowser != nullptr) { - struct CChangeContent Params = {MyParam.nflags, MyParam.nnflags}; //if this thread created window, just post message to update mails + if (nullptr != (hMailBrowser = WindowList_Find(YAMNVar.NewMailAccountWnd, (UINT_PTR)ActualAccount))) + WndFound = TRUE; - SendMessage(hMailBrowser, WM_YAMN_CHANGECONTENT, (WPARAM)ActualAccount, (LPARAM)&Params); //we ensure this will do the thread who created the browser window - } - else UpdateMails(nullptr, ActualAccount, MyParam.nflags, MyParam.nnflags); //update mails without displaying or refreshing any window + if ((hMailBrowser == nullptr) && ((MyParam->nflags & YAMN_ACC_MSG) || (MyParam->nflags & YAMN_ACC_ICO ) || (MyParam->nnflags & YAMN_ACC_MSG))) { + hMailBrowser = CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCEW(IDD_DLGVIEWMESSAGES), nullptr, DlgProcYAMNMailBrowser, (LPARAM)MyParam); + Window_SetIcon_IcoLib(hMailBrowser, g_plugin.getIconHandle(IDI_NEWMAIL)); + MoveWindow(hMailBrowser, PosX, PosY, SizeX, SizeY, TRUE); + } - if ((hMailBrowser != nullptr) && !WndFound) { //we process message loop only for thread that created window - while (GetMessage(&msg, nullptr, 0, 0)) { - if (hMailBrowser == nullptr || !IsDialogMessage(hMailBrowser, &msg)) { /* Wine fix. */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } + if (hMailBrowser != nullptr) { + // if this thread created window, just post message to update mails + struct CChangeContent Params = { MyParam->nflags, MyParam->nnflags }; + SendMessage(hMailBrowser, WM_YAMN_CHANGECONTENT, (WPARAM)ActualAccount, (LPARAM)&Params); //we ensure this will do the thread who created the browser window + } + else UpdateMails(nullptr, ActualAccount, MyParam->nflags, MyParam->nnflags); //update mails without displaying or refreshing any window + + if ((hMailBrowser != nullptr) && !WndFound) { //we process message loop only for thread that created window + while (GetMessage(&msg, nullptr, 0, 0)) { + if (hMailBrowser == nullptr || !IsDialogMessage(hMailBrowser, &msg)) { /* Wine fix. */ + TranslateMessage(&msg); + DispatchMessage(&msg); } } - - if ((!WndFound) && (ActualAccount->Plugin->Fcn != nullptr) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != nullptr) && ActualAccount->AbleToWork) - ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr(); - } - __finally { - SCDecFcn(ActualAccount->UsingThreads); } + + if ((!WndFound) && (ActualAccount->Plugin->Fcn != nullptr) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != nullptr) && ActualAccount->AbleToWork) + ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr(); + + delete MyParam; } INT_PTR RunMailBrowserSvc(WPARAM wParam, LPARAM lParam) @@ -2233,16 +2212,7 @@ INT_PTR RunMailBrowserSvc(WPARAM wParam, LPARAM lParam) if ((uint32_t)lParam != YAMN_MAILBROWSERVERSION) return 0; - PYAMN_MAILBROWSERPARAM Param = (PYAMN_MAILBROWSERPARAM)wParam; - - //an event for successfull copy parameters to which point a pointer in stack for new thread - HANDLE ThreadRunningEV = CreateEvent(nullptr, FALSE, FALSE, nullptr); - Param->ThreadRunningEV = ThreadRunningEV; - - HANDLE NewThread = mir_forkthread(MailBrowser, Param); - if (NewThread != nullptr) - WaitForSingleObject(ThreadRunningEV, INFINITE); - - CloseHandle(ThreadRunningEV); + auto *Param = (YAMN_MAILBROWSERPARAM*)wParam; + mir_forkthread(MailBrowser, new YAMN_MAILBROWSERPARAM(*Param)); return 1; } diff --git a/protocols/YAMN/src/filterplugin.cpp b/protocols/YAMN/src/filterplugin.cpp index 451ea155aa..9d22962b8f 100644 --- a/protocols/YAMN/src/filterplugin.cpp +++ b/protocols/YAMN/src/filterplugin.cpp @@ -148,7 +148,7 @@ INT_PTR FilterMailSvc(WPARAM wParam, LPARAM lParam) PYAMN_FILTERPLUGINQUEUE ActualPlugin; mir_cslock lck(PluginRegCS); - WaitToWriteFcn(Account->MessagesAccessSO); + SWriteGuard swa(Account->MessagesAccessSO); for (ActualPlugin = FirstFilterPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) if (ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr != nullptr) @@ -164,6 +164,5 @@ INT_PTR FilterMailSvc(WPARAM wParam, LPARAM lParam) if (YAMN_MSG_SPAML(Mail->Flags, YAMN_MSG_SPAML3)) Mail->Flags = Mail->Flags & ~(YAMN_MSG_MEMDELETE); //set message not to delete it immidiatelly from memory - WriteDoneFcn(Account->MessagesAccessSO); return 1; } diff --git a/protocols/YAMN/src/mails/mails.cpp b/protocols/YAMN/src/mails/mails.cpp index 1385cb649d..87a4faaf42 100644 --- a/protocols/YAMN/src/mails/mails.cpp +++ b/protocols/YAMN/src/mails/mails.cpp @@ -91,18 +91,6 @@ HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From); // mode- nonzero to set, else remove void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSetRemove, int mode); -struct CExportedFunctions MailExportedFcn[] = -{ - {YAMN_SYNCHROMIMEMSGSID, (void *)SynchroMessagesFcn}, - {YAMN_TRANSLATEHEADERID, (void *)TranslateHeaderFcn}, - {YAMN_APPENDQUEUEID, (void *)AppendQueueFcn}, - {YAMN_DELETEMIMEQUEUEID, (void *)DeleteMessagesToEndFcn}, - {YAMN_DELETEMIMEMESSAGEID, (void *)DeleteMessageFromQueueFcn}, - {YAMN_FINDMIMEMESSAGEID, (void *)FindMessageByIDFcn}, - {YAMN_CREATENEWDELETEQUEUEID, (void *)CreateNewDeleteQueueFcn}, - {YAMN_SETREMOVEQUEUEFLAGSID, (void *)SetRemoveFlagsInQueueFcn}, -}; - struct CExportedServices MailExportedSvc[] = { {MS_YAMN_CREATEACCOUNTMAIL, CreateAccountMailSvc}, @@ -147,7 +135,7 @@ INT_PTR CreateAccountMailSvc(WPARAM wParam, LPARAM lParam) INT_PTR DeleteAccountMailSvc(WPARAM wParam, LPARAM lParam) { - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; + YAMN_PROTOPLUGIN *Plugin = (YAMN_PROTOPLUGIN*)wParam; HYAMNMAIL OldMail = (HYAMNMAIL)lParam; struct CMimeItem *TH; @@ -315,7 +303,7 @@ void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From) } } -void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0) +void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode) { uint32_t Number = Which->Number; HYAMNMAIL Parser; @@ -388,7 +376,7 @@ void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head) } while (ENDLINEWS(finder)); if (Item != nullptr) { - if (nullptr == (Item->Next = new struct CMimeItem)) + if (nullptr == (Item->Next = new CMimeItem())) break; Item = Item->Next; } @@ -417,7 +405,7 @@ void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head) if (ENDLINE(finder))finder--; prev2 = finder; if (prev2 > prev1) { // yes, we have body - if (nullptr == (Item->Next = new struct CMimeItem)) break; // Cant create new item?! + Item->Next = new CMimeItem(); Item = Item->Next; Item->Next = nullptr;//just in case; Item->name = new char[5]; strncpy(Item->name, "Body", 5); diff --git a/protocols/YAMN/src/main.cpp b/protocols/YAMN/src/main.cpp index c4979af1fb..3094e2a283 100644 --- a/protocols/YAMN/src/main.cpp +++ b/protocols/YAMN/src/main.cpp @@ -153,58 +153,6 @@ void LoadIcons() g_plugin.registerIcon("YAMN", iconList); } -static void LoadPlugins() -{ - wchar_t szSearchPath[MAX_PATH]; - mir_snwprintf(szSearchPath, L"%s\\Plugins\\YAMN\\*.dll", szMirandaDir); - - hDllPlugins = nullptr; - - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile(szSearchPath, &fd); - if (hFind != INVALID_HANDLE_VALUE) { - do { - //rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too - wchar_t *dot = wcsrchr(fd.cFileName, '.'); - if (dot == nullptr) - continue; - - // we have a dot - int len = (int)mir_wstrlen(fd.cFileName); // find the length of the string - wchar_t *end = fd.cFileName + len; // get a pointer to the NULL - int safe = (end - dot) - 1; // figure out how many chars after the dot are "safe", not including NULL - - if ((safe != 3) || (mir_wstrcmpi(dot + 1, L"dll") != 0)) //not bound, however the "dll" string should mean only 3 chars are compared - continue; - - wchar_t szPluginPath[MAX_PATH]; - mir_snwprintf(szPluginPath, L"%s\\Plugins\\YAMN\\%s", szMirandaDir, fd.cFileName); - HINSTANCE hDll = LoadLibrary(szPluginPath); - if (hDll == nullptr) - continue; - - LOADFILTERFCN LoadFilter = (LOADFILTERFCN)GetProcAddress(hDll, "LoadFilter"); - if (nullptr == LoadFilter) { - FreeLibrary(hDll); - hDll = nullptr; - continue; - } - - if (!LoadFilter(GetFcnPtrSvc)) { - FreeLibrary(hDll); - hDll = nullptr; - } - - if (hDll != nullptr) { - hDllPlugins = (HINSTANCE *)realloc(hDllPlugins, (iDllPlugins + 1) * sizeof(HINSTANCE)); - hDllPlugins[iDllPlugins++] = hDll; - } - } while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } -} - int CMPlugin::Load() { // we get the Miranda Root Path @@ -267,7 +215,6 @@ int CMPlugin::Load() HookEvents(); LoadIcons(); - LoadPlugins(); HOTKEYDESC hkd = {}; hkd.pszName = "YAMN_hotkey"; diff --git a/protocols/YAMN/src/main.h b/protocols/YAMN/src/main.h index 971ba43c9f..79c56fefe0 100644 --- a/protocols/YAMN/src/main.h +++ b/protocols/YAMN/src/main.h @@ -31,7 +31,5 @@ extern unsigned char optDateTime; // Loading Icon and checking for icolib void LoadIcons(); -typedef INT_PTR (*LOADFILTERFCN)(MIRANDASERVICE GetYAMNFcn); - #endif diff --git a/protocols/YAMN/src/proto/pop3/pop3comm.cpp b/protocols/YAMN/src/proto/pop3/pop3comm.cpp index fc0f5819bb..ba793cd9d3 100644 --- a/protocols/YAMN/src/proto/pop3/pop3comm.cpp +++ b/protocols/YAMN/src/proto/pop3/pop3comm.cpp @@ -14,13 +14,15 @@ #define ERRORSTR_MAXLEN 1024 //in wide-chars +int WINAPI SetProtocolPluginFcnImportFcn(YAMN_PROTOPLUGIN *Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer); + //-------------------------------------------------------------------------------------------------- HANDLE hNetLib = nullptr; -PSCOUNTER CPOP3Account::AccountWriterSO = nullptr; +SCOUNTER CPOP3Account::AccountWriterSO; //Creates new CPOP3Account structure -CAccount *WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN Plugin, DWORD CAccountVersion); +CAccount *WINAPI CreatePOP3Account(YAMN_PROTOPLUGIN *Plugin, DWORD CAccountVersion); //Deletes CPOP3Account structure void WINAPI DeletePOP3Account(CAccount *Which); @@ -48,7 +50,7 @@ HYAMNMAIL WINAPI CreatePOP3Mail(CAccount *Account, DWORD CMimeMailVersion); //Function does all needed work when connection failed or any error occured //Creates structure containing error code, closes internet session, runs "bad connect" function -static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnect, uint32_t POP3PluginParam, BOOL UseSSL); +static void PostErrorProc(CPOP3Account *ActualAccount, void *ParamToBadConnect, uint32_t POP3PluginParam, BOOL UseSSL); //Checks POP3 account and stores all info to account. It deletes old mails=> synchro // WhichTemp- pointer to strucure containing needed information @@ -87,9 +89,6 @@ void ExtractList(char *stream, int len, HYAMNMAIL queue); void ExtractMail(char *stream, int len, HYAMNMAIL queue); -YAMNExportedFcns *pYAMNFcn = nullptr; -MailExportedFcns *pYAMNMailFcn = nullptr; - YAMN_PROTOIMPORTFCN POP3ProtocolFunctions = { CreatePOP3Account, @@ -117,8 +116,7 @@ YAMN_MAILIMPORTFCN POP3MailFunctions = nullptr, }; -PYAMN_VARIABLES pYAMNVar = nullptr; -HYAMNPROTOPLUGIN POP3Plugin = nullptr; +YAMN_PROTOPLUGIN *POP3Plugin = nullptr; YAMN_PROTOREGISTRATION POP3ProtocolRegistration = { @@ -138,24 +136,21 @@ HANDLE RegisterNLClient(char *name); CPOP3Account::CPOP3Account() { - //NOTE! This constructor constructs CAccount structure. If your plugin is not internal, - //you will need these constructors. All you need is in Account.cpp. Just copy to your source code - //constructor and destructor of CAccount. + // NOTE! This constructor constructs CAccount structure. If your plugin is not internal, + // you will need these constructors. All you need is in Account.cpp. Just copy to your source code + // constructor and destructor of CAccount. UseInternetFree = CreateEvent(nullptr, FALSE, TRUE, nullptr); - InternetQueries = new SCOUNTER; AbilityFlags = YAMN_ACC_BROWSE | YAMN_ACC_POPUP; - SetAccountStatus((CAccount *)this, TranslateT("Disconnected")); + SetStatusFcn(this, TranslateT("Disconnected")); } CPOP3Account::~CPOP3Account() { CloseHandle(UseInternetFree); - if (InternetQueries != nullptr) - delete InternetQueries; } -CAccount *WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN, DWORD) +CAccount* WINAPI CreatePOP3Account(YAMN_PROTOPLUGIN*, DWORD) { //First, we should check whether CAccountVersion matches. //But this is internal plugin, so YAMN's CAccount structure and our CAccount structure are @@ -164,75 +159,39 @@ CAccount *WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN, DWORD) // if (CAccountVersion != YAMN_ACCOUNTVERSION) return NULL; //Now it is needed to construct our POP3 account and return its handle - return (CAccount *)new struct CPOP3Account(); + return new CPOP3Account(); } void WINAPI DeletePOP3Account(CAccount *Which) { - delete (HPOP3ACCOUNT)Which; + delete (CPOP3Account*)Which; } void WINAPI StopPOP3Account(CAccount *Which) { - ((HPOP3ACCOUNT)Which)->Client.Stopped = TRUE; - if (((HPOP3ACCOUNT)Which)->Client.NetClient != nullptr) //we should inform also network client. Usefull only when network client implements this feature - ((HPOP3ACCOUNT)Which)->Client.NetClient->Stopped = TRUE; + ((CPOP3Account*)Which)->Client.Stopped = TRUE; + if (((CPOP3Account*)Which)->Client.NetClient != nullptr) //we should inform also network client. Usefull only when network client implements this feature + ((CPOP3Account*)Which)->Client.NetClient->Stopped = TRUE; } //This function is like main function for POP3 internal protocol int RegisterPOP3Plugin(WPARAM, LPARAM) { - // Get YAMN variables we can use - if (nullptr == (pYAMNVar = (PYAMN_VARIABLES)CallService(MS_YAMN_GETVARIABLES, YAMN_VARIABLESVERSION, 0))) - return 0; - - // We have to get pointers to YAMN exported functions: allocate structure and fill it - if (nullptr == (pYAMNFcn = new struct YAMNExportedFcns)) { -LBL_Error: + // Register new pop3 user in netlib + if (nullptr == (hNetLib = RegisterNLClient("YAMN (POP3)"))) { UnLoadPOP3(nullptr); return 0; } - // Register new pop3 user in netlib - if (nullptr == (hNetLib = RegisterNLClient("YAMN (POP3)"))) - goto LBL_Error; - - pYAMNFcn->SetProtocolPluginFcnImportFcn = (YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SETPROTOCOLPLUGINFCNIMPORTID, 0); - 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); - pYAMNFcn->SetStatusFcn = (YAMN_SETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SETSTATUSID, 0); - pYAMNFcn->GetStatusFcn = (YAMN_GETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_GETSTATUSID, 0); - - if (nullptr == (pYAMNMailFcn = new struct MailExportedFcns)) - goto LBL_Error; - - pYAMNMailFcn->SynchroMessagesFcn = (YAMN_SYNCHROMIMEMSGSFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_SYNCHROMIMEMSGSID, 0); - pYAMNMailFcn->TranslateHeaderFcn = (YAMN_TRANSLATEHEADERFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_TRANSLATEHEADERID, 0); - pYAMNMailFcn->AppendQueueFcn = (YAMN_APPENDQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_APPENDQUEUEID, 0); - pYAMNMailFcn->DeleteMessagesToEndFcn = (YAMN_DELETEMIMEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_DELETEMIMEQUEUEID, 0); - pYAMNMailFcn->DeleteMessageFromQueueFcn = (YAMN_DELETEMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_DELETEMIMEMESSAGEID, 0); - pYAMNMailFcn->FindMessageByIDFcn = (YAMN_FINDMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_FINDMIMEMESSAGEID, 0); - pYAMNMailFcn->CreateNewDeleteQueueFcn = (YAMN_CREATENEWDELETEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR, (WPARAM)YAMN_CREATENEWDELETEQUEUEID, 0); - - //set static variable - if (CPOP3Account::AccountWriterSO == nullptr) - if (nullptr == (CPOP3Account::AccountWriterSO = new SCOUNTER)) - goto LBL_Error; - - //First, we register this plugin - //it is quite impossible this function returns zero (failure) as YAMN and internal plugin structre versions are the same + // First, we register this plugin + // it is quite impossible this function returns zero (failure) as YAMN and internal plugin structre versions are the same POP3ProtocolRegistration.Name = Translate("POP3 protocol (internal)"); POP3ProtocolRegistration.Description = Translate(__DESCRIPTION); - if (nullptr == (POP3Plugin = (HYAMNPROTOPLUGIN)CallService(MS_YAMN_REGISTERPROTOPLUGIN, (WPARAM)&POP3ProtocolRegistration, (LPARAM)YAMN_PROTOREGISTRATIONVERSION))) + if (nullptr == (POP3Plugin = (YAMN_PROTOPLUGIN*)CallService(MS_YAMN_REGISTERPROTOPLUGIN, (WPARAM)&POP3ProtocolRegistration, (LPARAM)YAMN_PROTOREGISTRATIONVERSION))) return 0; //Next we set our imported functions for YAMN - if (!SetProtocolPluginFcnImport(POP3Plugin, &POP3ProtocolFunctions, YAMN_PROTOIMPORTFCNVERSION, &POP3MailFunctions, YAMN_MAILIMPORTFCNVERSION)) + if (!SetProtocolPluginFcnImportFcn(POP3Plugin, &POP3ProtocolFunctions, YAMN_PROTOIMPORTFCNVERSION, &POP3MailFunctions, YAMN_MAILIMPORTFCNVERSION)) return 0; //Then, we read all mails for accounts. @@ -303,19 +262,9 @@ LBL_Error: DWORD WINAPI UnLoadPOP3(void *) { - //pYAMNVar is only a pointr, no need delete or free if (hNetLib) { Netlib_CloseHandle(hNetLib); hNetLib = nullptr; } - if (CPOP3Account::AccountWriterSO) { - delete CPOP3Account::AccountWriterSO; CPOP3Account::AccountWriterSO = nullptr; - } - if (pYAMNMailFcn) { - delete pYAMNMailFcn; pYAMNMailFcn = nullptr; - } - if (pYAMNFcn) { - delete pYAMNFcn; pYAMNFcn = nullptr; - } if (FileName) { CallService(MS_YAMN_DELETEFILENAME, (WPARAM)FileName, 0); FileName = nullptr; } @@ -341,7 +290,7 @@ DWORD WINAPI WritePOP3Options(HANDLE File, CAccount *Which) uint32_t Ver = POP3_FILEVERSION; if ((!WriteFile(File, (char *)&Ver, sizeof(uint32_t), &WrittenBytes, nullptr)) || - (!WriteFile(File, (char *)&((HPOP3ACCOUNT)Which)->CP, sizeof(uint16_t), &WrittenBytes, nullptr))) + (!WriteFile(File, (char *)&((CPOP3Account*)Which)->CP, sizeof(uint16_t), &WrittenBytes, nullptr))) return EACC_SYSTEM; return 0; } @@ -359,12 +308,12 @@ DWORD WINAPI ReadPOP3Options(CAccount *Which, char **Parser, char *End) if (Ver != POP3_FILEVERSION) return EACC_FILECOMPATIBILITY; - ((HPOP3ACCOUNT)Which)->CP = *(uint16_t *)(*Parser); + ((CPOP3Account*)Which)->CP = *(uint16_t *)(*Parser); (*Parser) += sizeof(uint16_t); if (*Parser >= End) return EACC_FILECOMPATIBILITY; #ifdef DEBUG_FILEREAD - mir_snwprintf(Debug, L"CodePage: %d, remaining %d chars", ((HPOP3ACCOUNT)Which)->CP, End - *Parser); + mir_snwprintf(Debug, L"CodePage: %d, remaining %d chars", ((CPOP3Account*)Which)->CP, End - *Parser); MessageBox(NULL, Debug, L"debug", MB_OK); #endif return 0; @@ -387,7 +336,7 @@ HYAMNMAIL WINAPI CreatePOP3Mail(CAccount *Account, DWORD) delete NewMail; return nullptr; } - NewMail->MailData->CP = ((HPOP3ACCOUNT)Account)->CP; + NewMail->MailData->CP = ((CPOP3Account*)Account)->CP; return (HYAMNMAIL)NewMail; } @@ -397,7 +346,7 @@ static void SetContactStatus(CAccount *account, int status) g_plugin.setWord(account->hContact, "Status", status); } -static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnection, uint32_t POP3PluginParam, BOOL UseSSL) +static void PostErrorProc(CPOP3Account* ActualAccount, void *ParamToBadConnection, uint32_t POP3PluginParam, BOOL UseSSL) { char *DataRX; @@ -431,7 +380,7 @@ static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnection catch (...) { } - SetAccountStatus(ActualAccount, TranslateT("Disconnected")); + SetStatusFcn(ActualAccount, TranslateT("Disconnected")); //If we cannot allocate memory, do nothing if (ErrorCode == nullptr) { @@ -453,7 +402,7 @@ static void PostErrorProc(HPOP3ACCOUNT ActualAccount, void *ParamToBadConnection //Checks POP3 account and synchronizes it DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) { - HPOP3ACCOUNT ActualAccount; + CPOP3Account* ActualAccount; CPop3Client *MyClient; HYAMNMAIL NewMails = nullptr, MsgQueuePtr = nullptr; char *DataRX = nullptr, *Temp; @@ -484,19 +433,18 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN". // } - ActualAccount = (HPOP3ACCOUNT)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread + ActualAccount = (CPOP3Account*)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread YAMNParam = WhichTemp->BrowserParam; CheckFlags = WhichTemp->Flags; - SCInc(ActualAccount->UsingThreads); + SCGuard sc(ActualAccount->UsingThreads); //Unblock YAMN, signal that we have copied all parameters from YAMN thread stack if (INVALID_HANDLE_VALUE != WhichTemp->ThreadRunningEV) SetEvent(WhichTemp->ThreadRunningEV); - if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) { - SCDec(ActualAccount->UsingThreads); + SReadGuard sra(ActualAccount->AccountAccessSO); + if (!sra.Succeeded()) return 0; - } MyClient = &ActualAccount->Client; //Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes. @@ -507,19 +455,16 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) ActualCopied.ServerPasswd = _strdup(ActualAccount->Server->Passwd); ActualCopied.NFlags = ActualAccount->NewMailN.Flags; ActualCopied.NNFlags = ActualAccount->NoNewMailN.Flags; - - ReadDone(ActualAccount); - SCInc(ActualAccount->InternetQueries); //increment counter, that there is one more thread waiting for connection - - WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); //wait until we can use connection - SCDec(ActualAccount->InternetQueries); - + sra.Uninit(); + { + SCGuard scq(ActualAccount->InternetQueries); // increment counter, that there is one more thread waiting for connection + WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); // wait until we can use connection + } //OK, we enter the "use internet" section. But after we start communication, we can test if we did not enter the "use internet" section only for the reason, //that previous thread release the internet section because this account has stop signal (we stop account and there are 2 threads: one communicating, //the second one waiting for network access- the first one ends because we want to stop account, this one is released, but should be stopped as well). if (!ActualAccount->AbleToWork) { SetEvent(ActualAccount->UseInternetFree); - SCDec(ActualAccount->UsingThreads); return 0; } UsingInternet = TRUE; @@ -532,7 +477,7 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) // if we are already connected, we have open session (another thread left us open session), so we don't need to login // note that connected state without logging cannot occur, because if we close session, we always close socket too (we must close socket is the right word :)) if ((MyClient->NetClient == nullptr) || !MyClient->NetClient->Connected()) { - SetAccountStatus(ActualAccount, TranslateT("Connecting to server")); + SetStatusFcn(ActualAccount, TranslateT("Connecting to server")); DataRX = MyClient->Connect(ActualCopied.ServerName, ActualCopied.ServerPort, ActualCopied.Flags & YAMN_ACC_SSL23, ActualCopied.Flags & YAMN_ACC_NOTLS); char *timestamp = nullptr; @@ -552,7 +497,7 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) DataRX = nullptr; } - SetAccountStatus(ActualAccount, TranslateT("Entering POP3 account")); + SetStatusFcn(ActualAccount, TranslateT("Entering POP3 account")); if (ActualCopied.Flags & YAMN_ACC_APOP) { DataRX = MyClient->APOP(ActualCopied.ServerLogin, ActualCopied.ServerPasswd, timestamp); @@ -572,7 +517,7 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) DataRX = nullptr; } } - SetAccountStatus(ActualAccount, TranslateT("Searching for new mail message")); + SetStatusFcn(ActualAccount, TranslateT("Searching for new mail message")); DataRX = MyClient->Stat(); @@ -607,58 +552,59 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) free(DataRX); DataRX = nullptr; } + { + SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (!swm.Succeeded()) + throw (uint32_t)(ActualAccount->SystemError = EACC_STOPPED); - if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount)) - throw (uint32_t)(ActualAccount->SystemError = EACC_STOPPED); - - ActualAccount->LastChecked = now; - for (MsgQueuePtr = (HYAMNMAIL)ActualAccount->Mails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next) { - if (MsgQueuePtr->Flags & YAMN_MSG_BODYREQUESTED) { - HYAMNMAIL NewMsgsPtr = nullptr; - for (NewMsgsPtr = (HYAMNMAIL)NewMails; NewMsgsPtr != nullptr; NewMsgsPtr = NewMsgsPtr->Next) { - if (!mir_strcmp(MsgQueuePtr->ID, NewMsgsPtr->ID)) { - wchar_t accstatus[512]; - mir_snwprintf(accstatus, TranslateT("Reading body %s"), NewMsgsPtr->ID); - SetAccountStatus(ActualAccount, accstatus); - DataRX = MyClient->Top(MsgQueuePtr->Number, 100); - if (DataRX != nullptr) { - Temp = DataRX; - while ((Temp < DataRX + MyClient->NetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++; - - if (OKLINE(DataRX)) - for (Temp = DataRX; (Temp < DataRX + MyClient->NetClient->Rcv) && (!ENDLINE(Temp)); Temp++); - while ((Temp < DataRX + MyClient->NetClient->Rcv) && ENDLINE(Temp)) Temp++; - } - else - continue; - //delete all the headers of the old mail MsgQueuePtr->MailData->TranslatedHeader - struct CMimeItem *TH = MsgQueuePtr->MailData->TranslatedHeader; - if (TH) for (; MsgQueuePtr->MailData->TranslatedHeader != nullptr;) { - TH = TH->Next; - if (MsgQueuePtr->MailData->TranslatedHeader->name != nullptr) - delete[] MsgQueuePtr->MailData->TranslatedHeader->name; - if (MsgQueuePtr->MailData->TranslatedHeader->value != nullptr) - delete[] MsgQueuePtr->MailData->TranslatedHeader->value; - delete MsgQueuePtr->MailData->TranslatedHeader; - MsgQueuePtr->MailData->TranslatedHeader = TH; - } + ActualAccount->LastChecked = now; + for (MsgQueuePtr = (HYAMNMAIL)ActualAccount->Mails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next) { + if (MsgQueuePtr->Flags & YAMN_MSG_BODYREQUESTED) { + HYAMNMAIL NewMsgsPtr = nullptr; + for (NewMsgsPtr = (HYAMNMAIL)NewMails; NewMsgsPtr != nullptr; NewMsgsPtr = NewMsgsPtr->Next) { + if (!mir_strcmp(MsgQueuePtr->ID, NewMsgsPtr->ID)) { + wchar_t accstatus[512]; + mir_snwprintf(accstatus, TranslateT("Reading body %s"), NewMsgsPtr->ID); + SetStatusFcn(ActualAccount, accstatus); + DataRX = MyClient->Top(MsgQueuePtr->Number, 100); + if (DataRX != nullptr) { + Temp = DataRX; + while ((Temp < DataRX + MyClient->NetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++; + + if (OKLINE(DataRX)) + for (Temp = DataRX; (Temp < DataRX + MyClient->NetClient->Rcv) && (!ENDLINE(Temp)); Temp++); + while ((Temp < DataRX + MyClient->NetClient->Rcv) && ENDLINE(Temp)) Temp++; + } + else + continue; + //delete all the headers of the old mail MsgQueuePtr->MailData->TranslatedHeader + struct CMimeItem *TH = MsgQueuePtr->MailData->TranslatedHeader; + if (TH) for (; MsgQueuePtr->MailData->TranslatedHeader != nullptr;) { + TH = TH->Next; + if (MsgQueuePtr->MailData->TranslatedHeader->name != nullptr) + delete[] MsgQueuePtr->MailData->TranslatedHeader->name; + if (MsgQueuePtr->MailData->TranslatedHeader->value != nullptr) + delete[] MsgQueuePtr->MailData->TranslatedHeader->value; + delete MsgQueuePtr->MailData->TranslatedHeader; + MsgQueuePtr->MailData->TranslatedHeader = TH; + } - TranslateHeader(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader); + TranslateHeaderFcn(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader); - MsgQueuePtr->Flags |= YAMN_MSG_BODYRECEIVED; + MsgQueuePtr->Flags |= YAMN_MSG_BODYRECEIVED; - if (DataRX != nullptr) - free(DataRX); - DataRX = nullptr; - break; + if (DataRX != nullptr) + free(DataRX); + DataRX = nullptr; + break; + } } } } - } - - SynchroMessages(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); //we get only new mails on server! - MsgsWriteDone(ActualAccount); + SynchroMessagesFcn(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); //we get only new mails on server! + } + for (MsgQueuePtr = (HYAMNMAIL)ActualAccount->Mails; MsgQueuePtr != nullptr; MsgQueuePtr = MsgQueuePtr->Next) { if ((MsgQueuePtr->Flags & YAMN_MSG_BODYREQUESTED) && (MsgQueuePtr->Flags & YAMN_MSG_BODYRECEIVED)) { MsgQueuePtr->Flags &= ~YAMN_MSG_BODYREQUESTED; @@ -676,7 +622,7 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) BOOL autoretr = (ActualAccount->Flags & YAMN_ACC_BODY) != 0; DataRX = MyClient->Top(MsgQueuePtr->Number, autoretr ? 100 : 0); mir_snwprintf(accstatus, TranslateT("Reading new mail messages (%d%% done)"), 100 * i / msgs); - SetAccountStatus(ActualAccount, accstatus); + SetStatusFcn(ActualAccount, accstatus); if (DataRX != nullptr) { Temp = DataRX; @@ -689,7 +635,7 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) else continue; - TranslateHeader(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader); + TranslateHeaderFcn(Temp, MyClient->NetClient->Rcv - (Temp - DataRX), &MsgQueuePtr->MailData->TranslatedHeader); #ifdef DEBUG_DECODE @@ -713,19 +659,19 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) MsgQueuePtr = MsgQueuePtr->Next; } + + { SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (!swm.Succeeded()) + throw (uint32_t)ActualAccount->SystemError == EACC_STOPPED; - if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount)) - throw (uint32_t)ActualAccount->SystemError == EACC_STOPPED; - - if (ActualAccount->Mails == nullptr) - ActualAccount->Mails = NewMails; - else { - ActualAccount->LastMail = ActualAccount->LastChecked; - AppendQueue((HYAMNMAIL)ActualAccount->Mails, NewMails); + if (ActualAccount->Mails == nullptr) + ActualAccount->Mails = NewMails; + else { + ActualAccount->LastMail = ActualAccount->LastChecked; + AppendQueueFcn((HYAMNMAIL)ActualAccount->Mails, NewMails); + } } - MsgsWriteDone(ActualAccount); - // we are going to delete mails having SPAM flag level3 and 4 (see m_mails.h) set { struct DeleteParam ParamToDeleteMails = {YAMN_DELETEVERSION, INVALID_HANDLE_VALUE, ActualAccount, YAMNParam, (void *)POP3_DELETEFROMCHECK}; @@ -736,14 +682,14 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) // if there is no waiting thread for internet connection close it // else leave connection open - if (0 == SCGetNumber(ActualAccount->InternetQueries)) { + if (0 == ActualAccount->InternetQueries.GetNumber()) { DataRX = MyClient->Quit(); if (DataRX != nullptr) free(DataRX); DataRX = nullptr; MyClient->NetClient->Disconnect(); - SetAccountStatus(ActualAccount, TranslateT("Disconnected")); + SetStatusFcn(ActualAccount, TranslateT("Disconnected")); } UsingInternet = FALSE; @@ -756,14 +702,12 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) throw; //go to the main exception handling } - { - YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualCopied.NFlags, ActualCopied.NNFlags, YAMNParam}; + YAMN_MAILBROWSERPARAM Param = { ActualAccount, ActualCopied.NFlags, ActualCopied.NNFlags, YAMNParam}; + if (CheckFlags & YAMN_FORCECHECK) + Param.nnflags |= YAMN_ACC_POP; // if force check, show popup anyway and if mailbrowser was opened, do not close + Param.nnflags |= YAMN_ACC_MSGP; // do not close browser if already open + CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, YAMN_MAILBROWSERVERSION); - if (CheckFlags & YAMN_FORCECHECK) - Param.nnflags |= YAMN_ACC_POP; //if force check, show popup anyway and if mailbrowser was opened, do not close - Param.nnflags |= YAMN_ACC_MSGP; //do not close browser if already open - CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION); - } SetContactStatus(ActualAccount, ActualAccount->isCounting ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE); } #ifdef DEBUG_COMM @@ -777,12 +721,13 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) #ifdef DEBUG_COMM DebugLog(CommFile, "ERROR: %x\n", ErrorCode); #endif - if (WAIT_OBJECT_0 == MsgsWaitToWrite(ActualAccount)) { - ActualAccount->LastChecked = now; - MsgsWriteDone(ActualAccount); + { + SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (swm.Succeeded()) + ActualAccount->LastChecked = now; } - DeleteMIMEQueue(ActualAccount, NewMails); + DeleteMessagesToEndFcn(ActualAccount, NewMails); if (DataRX != nullptr) free(DataRX); @@ -809,7 +754,6 @@ DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp) #endif // WriteAccounts(); - SCDec(ActualAccount->UsingThreads); return 0; } @@ -844,49 +788,46 @@ void __cdecl DeleteMailsPOP3(void *param) // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN". // } - HPOP3ACCOUNT ActualAccount = (HPOP3ACCOUNT)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread + CPOP3Account* ActualAccount = (CPOP3Account*)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread LPVOID YAMNParam = WhichTemp->BrowserParam; UINT_PTR POP3PluginParam = (UINT_PTR)((struct DeleteParam *)WhichTemp)->CustomParam; - SCInc(ActualAccount->UsingThreads); + SCGuard sc(ActualAccount->UsingThreads); if (INVALID_HANDLE_VALUE != WhichTemp->ThreadRunningEV) SetEvent(WhichTemp->ThreadRunningEV); + + { SReadGuard sra(ActualAccount->AccountAccessSO); + if (!sra.Succeeded()) + return; - if (WAIT_OBJECT_0 != WaitToRead(ActualAccount)) { - SCDec(ActualAccount->UsingThreads); - return; - } - - if (nullptr == (DeleteMails = (HYAMNMAIL)CreateNewDeleteQueue((HYAMNMAIL)ActualAccount->Mails))) //if there's no mail for deleting, return - { - if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked - { - YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, YAMN_ACC_MSGP, YAMN_ACC_MSGP, YAMNParam}; //Just update the window - CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION); + // if there's no mail for deleting, return + if (nullptr == (DeleteMails = CreateNewDeleteQueueFcn((HYAMNMAIL)ActualAccount->Mails))) { + // We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked + if (POP3_DELETEFROMCHECK != POP3PluginParam) { + YAMN_MAILBROWSERPARAM Param = { ActualAccount, YAMN_ACC_MSGP, YAMN_ACC_MSGP, YAMNParam }; //Just update the window + CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, YAMN_MAILBROWSERVERSION); + } + return; } - SCDec(ActualAccount->UsingThreads); - return; - } + MyClient = &ActualAccount->Client; - MyClient = &(ActualAccount->Client); - - //Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes. - ActualCopied.ServerName = _strdup(ActualAccount->Server->Name); - ActualCopied.ServerPort = ActualAccount->Server->Port; - ActualCopied.Flags = ActualAccount->Flags; - ActualCopied.ServerLogin = _strdup(ActualAccount->Server->Login); - ActualCopied.ServerPasswd = _strdup(ActualAccount->Server->Passwd); - ActualCopied.NFlags = ActualAccount->NewMailN.Flags; - ActualCopied.NNFlags = ActualAccount->NoNewMailN.Flags; - - ReadDone(ActualAccount); - - SCInc(ActualAccount->InternetQueries); //This is POP3-internal SCOUNTER, we set another thread wait for this account to be connected to inet - if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked - WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); + // Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes. + ActualCopied.ServerName = _strdup(ActualAccount->Server->Name); + ActualCopied.ServerPort = ActualAccount->Server->Port; + ActualCopied.Flags = ActualAccount->Flags; + ActualCopied.ServerLogin = _strdup(ActualAccount->Server->Login); + ActualCopied.ServerPasswd = _strdup(ActualAccount->Server->Passwd); + ActualCopied.NFlags = ActualAccount->NewMailN.Flags; + ActualCopied.NNFlags = ActualAccount->NoNewMailN.Flags; + } + + { + SCGuard scq(ActualAccount->InternetQueries); // This is POP3-internal SCOUNTER, we set another thread wait for this account to be connected to inet + if (POP3_DELETEFROMCHECK != POP3PluginParam) // We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked + WaitForSingleObject(ActualAccount->UseInternetFree, INFINITE); + } - SCDec(ActualAccount->InternetQueries); UsingInternet = TRUE; try { @@ -895,7 +836,7 @@ void __cdecl DeleteMailsPOP3(void *param) DebugLog(CommFile, "<--------Communication-------->\n"); #endif if ((MyClient->NetClient == nullptr) || !MyClient->NetClient->Connected()) { - SetAccountStatus(ActualAccount, TranslateT("Connecting to server")); + SetStatusFcn(ActualAccount, TranslateT("Connecting to server")); DataRX = MyClient->Connect(ActualCopied.ServerName, ActualCopied.ServerPort, ActualCopied.Flags & YAMN_ACC_SSL23, ActualCopied.Flags & YAMN_ACC_NOTLS); @@ -914,7 +855,7 @@ void __cdecl DeleteMailsPOP3(void *param) free(DataRX); DataRX = nullptr; } - SetAccountStatus(ActualAccount, TranslateT("Entering POP3 account")); + SetStatusFcn(ActualAccount, TranslateT("Entering POP3 account")); if (ActualAccount->Flags & YAMN_ACC_APOP) { DataRX = MyClient->APOP(ActualCopied.ServerLogin, ActualCopied.ServerPasswd, timestamp); @@ -940,7 +881,7 @@ void __cdecl DeleteMailsPOP3(void *param) #endif if (POP3_DELETEFROMCHECK != POP3PluginParam) //We do not need to get mails on server as we have already it from check function { - SetAccountStatus(ActualAccount, TranslateT("Deleting requested mails")); + SetStatusFcn(ActualAccount, TranslateT("Deleting requested mails")); DataRX = MyClient->Stat(); @@ -983,16 +924,16 @@ void __cdecl DeleteMailsPOP3(void *param) DataRX = nullptr; // we get "new mails" on server (NewMails will contain all mails on server not found in DeleteMails) // but also in DeleteMails we get only those, which are still on server with their responsable numbers - SynchroMessages(ActualAccount, (HYAMNMAIL *)&DeleteMails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); + SynchroMessagesFcn(ActualAccount, (HYAMNMAIL *)&DeleteMails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); } } - else SetAccountStatus(ActualAccount, TranslateT("Deleting spam")); + else SetStatusFcn(ActualAccount, TranslateT("Deleting spam")); - if (WAIT_OBJECT_0 != MsgsWaitToWrite(ActualAccount)) - throw (uint32_t)EACC_STOPPED; + { SWriteGuard swm(ActualAccount->MessagesAccessSO); + if (!swm.Succeeded()) + throw (uint32_t)EACC_STOPPED; - if (msgs || POP3_DELETEFROMCHECK == POP3PluginParam) { - try { + if (msgs || POP3_DELETEFROMCHECK == POP3PluginParam) { HYAMNMAIL Temp; for (i = 0, MsgQueuePtr = DeleteMails; MsgQueuePtr != nullptr; i++) { @@ -1002,11 +943,11 @@ void __cdecl DeleteMailsPOP3(void *param) Temp = MsgQueuePtr->Next; if (POP3_FOK == MyClient->AckFlag) //if server answers that mail was deleted { - DeleteMIMEMessage((HYAMNMAIL *)&DeleteMails, MsgQueuePtr); - HYAMNMAIL DeletedMail = FindMIMEMessageByID((HYAMNMAIL)ActualAccount->Mails, MsgQueuePtr->ID); + DeleteMessageFromQueueFcn((HYAMNMAIL *)&DeleteMails, MsgQueuePtr); + HYAMNMAIL DeletedMail = FindMessageByIDFcn((HYAMNMAIL)ActualAccount->Mails, MsgQueuePtr->ID); if ((MsgQueuePtr->Flags & YAMN_MSG_MEMDELETE)) //if mail should be deleted from memory (or disk) { - DeleteMIMEMessage((HYAMNMAIL *)&ActualAccount->Mails, DeletedMail); //remove from queue + DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails, DeletedMail); //remove from queue CallService(MS_YAMN_DELETEACCOUNTMAIL, (WPARAM)POP3Plugin, (LPARAM)DeletedMail); } else //else mark it only as "deleted mail" @@ -1027,33 +968,27 @@ void __cdecl DeleteMailsPOP3(void *param) else MsgQueuePtr = MsgQueuePtr->Next; } - } - catch (...) //if any exception in the code where we have write-access to account occured, don't forget to leave write-access - { - MsgsWriteDone(ActualAccount); - throw; //and go to the main exception handling - } - if (NewMails != nullptr) - // in ActualAccount->Mails we have all mails stored before calling this function - // in NewMails we have all mails not found in DeleteMails (in other words: we performed new ID checking and we - // stored all mails found on server, then we deleted the ones we wanted to delete in this function - // and NewMails queue now contains actual state of mails on server). But we will not use NewMails as actual state, because NewMails does not contain header data (subject, from...) - // We perform deleting from ActualAccount->Mails: we remove from original queue (ActualAccount->Mails) all deleted mails - SynchroMessages(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); - // Now ActualAccount->Mails contains all mails when calling this function except the ones, we wanted to delete (these are in DeleteMails) - // And in NewMails we have new mails (if any) - else if (POP3_DELETEFROMCHECK != POP3PluginParam) { - DeleteMIMEQueue(ActualAccount, (HYAMNMAIL)ActualAccount->Mails); + if (NewMails != nullptr) + // in ActualAccount->Mails we have all mails stored before calling this function + // in NewMails we have all mails not found in DeleteMails (in other words: we performed new ID checking and we + // stored all mails found on server, then we deleted the ones we wanted to delete in this function + // and NewMails queue now contains actual state of mails on server). But we will not use NewMails as actual state, because NewMails does not contain header data (subject, from...) + // We perform deleting from ActualAccount->Mails: we remove from original queue (ActualAccount->Mails) all deleted mails + SynchroMessagesFcn(ActualAccount, (HYAMNMAIL *)&ActualAccount->Mails, nullptr, (HYAMNMAIL *)&NewMails, nullptr); + // Now ActualAccount->Mails contains all mails when calling this function except the ones, we wanted to delete (these are in DeleteMails) + // And in NewMails we have new mails (if any) + else if (POP3_DELETEFROMCHECK != POP3PluginParam) { + DeleteMessagesToEndFcn(ActualAccount, (HYAMNMAIL)ActualAccount->Mails); + ActualAccount->Mails = nullptr; + } + } + else { + DeleteMessagesToEndFcn(ActualAccount, (HYAMNMAIL)ActualAccount->Mails); ActualAccount->Mails = nullptr; } } - else { - DeleteMIMEQueue(ActualAccount, (HYAMNMAIL)ActualAccount->Mails); - ActualAccount->Mails = nullptr; - } - - MsgsWriteDone(ActualAccount); + #ifdef DEBUG_DECODE DebugLog(DecodeFile, "\n"); #endif @@ -1065,18 +1000,17 @@ void __cdecl DeleteMailsPOP3(void *param) // else leave connection open // if this functin was called from SynchroPOP3, then do not try to disconnect if (POP3_DELETEFROMCHECK != POP3PluginParam) { - YAMN_MAILBROWSERPARAM Param = {(HANDLE)nullptr, ActualAccount, ActualCopied.NFlags, YAMN_ACC_MSGP, YAMNParam}; - - CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, (LPARAM)YAMN_MAILBROWSERVERSION); + YAMN_MAILBROWSERPARAM Param = { ActualAccount, ActualCopied.NFlags, YAMN_ACC_MSGP, YAMNParam}; + CallService(MS_YAMN_MAILBROWSER, (WPARAM)&Param, YAMN_MAILBROWSERVERSION); - if (0 == SCGetNumber(ActualAccount->InternetQueries)) { + if (0 == ActualAccount->InternetQueries.GetNumber()) { DataRX = MyClient->Quit(); if (DataRX != nullptr) free(DataRX); DataRX = nullptr; MyClient->NetClient->Disconnect(); - SetAccountStatus(ActualAccount, TranslateT("Disconnected")); + SetStatusFcn(ActualAccount, TranslateT("Disconnected")); } UsingInternet = FALSE; @@ -1114,15 +1048,14 @@ void __cdecl DeleteMailsPOP3(void *param) free(ActualCopied.ServerLogin); free(ActualCopied.ServerPasswd); - DeleteMIMEQueue(ActualAccount, NewMails); - DeleteMIMEQueue(ActualAccount, DeleteMails); + DeleteMessagesToEndFcn(ActualAccount, NewMails); + DeleteMessagesToEndFcn(ActualAccount, DeleteMails); #ifdef DEBUG_COMM DebugLog(CommFile, "\n"); #endif // WriteAccounts(); - SCDec(ActualAccount->UsingThreads); return; } diff --git a/protocols/YAMN/src/proto/pop3/pop3comm.h b/protocols/YAMN/src/proto/pop3/pop3comm.h index f8edceb731..7a6d339d8d 100644 --- a/protocols/YAMN/src/proto/pop3/pop3comm.h +++ b/protocols/YAMN/src/proto/pop3/pop3comm.h @@ -3,38 +3,37 @@ #define POP3_FILEVERSION 1 //Version of aditional information stored in book file -typedef struct CPOP3Account: public CAccount +struct CPOP3Account : public CAccount { -// We can use SCOUNTER structure, because this is internal plugin. -// This SO is used to determine if any POP3 account is in "write access" mode - static PSCOUNTER AccountWriterSO; + // We can use SCOUNTER structure, because this is internal plugin. + // This SO is used to determine if any POP3 account is in "write access" mode + static SCOUNTER AccountWriterSO; -// It is usefull to have client structure in account. With this structure we have access to account's socket. -// This is related to InternetQueries and UseInternetFree -// This member should be synchronized with UseInternetFree + // It is usefull to have client structure in account. With this structure we have access to account's socket. + // This is related to InternetQueries and UseInternetFree + // This member should be synchronized with UseInternetFree class CPop3Client Client; -// This member is usefull for MIME headers. It is default codepage, if no other codepage found + // This member is usefull for MIME headers. It is default codepage, if no other codepage found uint16_t CP; //access only through AccountAccessSO -// In this memeber last error code is stored + // In this memeber last error code is stored uint32_t SystemError; //access through UseInternetFree -// We use only counter from this object and it is # of threads waiting to work on internet. -// We use event UseInternet to access critical sections. -// It is usefull in 2 ways: we have mutual exclusion that only one thread works with account on internet. -// Thread, which has done its work with account on internet can close socket, but it is not needed, when any other -// thread wants to work (e.g. we have deleted mails, but when deleting, another thread wants to check new mail, so -// we delete all needed mails and check if there's thread that wants to work. If yes, we do not need to quit session, -// we leave socket open, and leave internet. Another thread then start checking and does not connect, does not send -// user and password... because socket is open- it continues) - PSCOUNTER InternetQueries; + // We use only counter from this object and it is # of threads waiting to work on internet. + // We use event UseInternet to access critical sections. + // It is usefull in 2 ways: we have mutual exclusion that only one thread works with account on internet. + // Thread, which has done its work with account on internet can close socket, but it is not needed, when any other + // thread wants to work (e.g. we have deleted mails, but when deleting, another thread wants to check new mail, so + // we delete all needed mails and check if there's thread that wants to work. If yes, we do not need to quit session, + // we leave socket open, and leave internet. Another thread then start checking and does not connect, does not send + // user and password... because socket is open- it continues) + SCOUNTER InternetQueries; HANDLE UseInternetFree; CPOP3Account(); ~CPOP3Account(); - -} POP3ACCOUNT,*HPOP3ACCOUNT; +}; typedef struct POP3LayeredError { @@ -45,31 +44,6 @@ typedef struct POP3LayeredError uint32_t SystemError; } POP3_ERRORCODE,*PPOP3_ERRORCODE; -struct YAMNExportedFcns -{ - YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN SetProtocolPluginFcnImportFcn; - YAMN_WAITTOWRITEFCN WaitToWriteFcn; - YAMN_WRITEDONEFCN WriteDoneFcn; - YAMN_WAITTOREADFCN WaitToReadFcn; - YAMN_READDONEFCN ReadDoneFcn; - YAMN_SCMANAGEFCN SCGetNumberFcn; - YAMN_SCMANAGEFCN SCIncFcn; - YAMN_SCMANAGEFCN SCDecFcn; - YAMN_SETSTATUSFCN SetStatusFcn; - YAMN_GETSTATUSFCN GetStatusFcn; -}; - -struct MailExportedFcns -{ - YAMN_SYNCHROMIMEMSGSFCN SynchroMessagesFcn; - YAMN_TRANSLATEHEADERFCN TranslateHeaderFcn; - YAMN_APPENDQUEUEFCN AppendQueueFcn; - YAMN_DELETEMIMEQUEUEFCN DeleteMessagesToEndFcn; - YAMN_DELETEMIMEMESSAGEFCN DeleteMessageFromQueueFcn; - YAMN_FINDMIMEMESSAGEFCN FindMessageByIDFcn; - YAMN_CREATENEWDELETEQUEUEFCN CreateNewDeleteQueueFcn; -}; - enum { EACC_QUEUEALLOC=1, //memory allocation diff --git a/protocols/YAMN/src/proto/pop3/pop3opt.cpp b/protocols/YAMN/src/proto/pop3/pop3opt.cpp index 7cf85e5b76..25937acbbb 100644 --- a/protocols/YAMN/src/proto/pop3/pop3opt.cpp +++ b/protocols/YAMN/src/proto/pop3/pop3opt.cpp @@ -34,13 +34,13 @@ struct CBaseOptionsDlg : public CDlgBase CDlgBase(g_plugin, iDlgId) {} - void DlgShowAccount(HPOP3ACCOUNT pAccount) + void DlgShowAccount(CPOP3Account* pAccount) { int i; if (pAccount) { // we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread - WaitToRead(pAccount); + SReadGuard sra(pAccount->AccountAccessSO); DlgSetItemText(m_hwnd, IDC_EDITSERVER, pAccount->Server->Name); DlgSetItemText(m_hwnd, IDC_EDITNAME, pAccount->Name); @@ -89,9 +89,8 @@ struct CBaseOptionsDlg : public CDlgBase CheckDlgButton(m_hwnd, IDC_CHECKCONTACTNOEVENT, pAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT ? BST_CHECKED : BST_UNCHECKED); wchar_t accstatus[256]; - GetAccountStatus(pAccount, accstatus); + GetStatusFcn(pAccount, accstatus); SetDlgItemText(m_hwnd, IDC_STSTATUS, accstatus); - ReadDone(pAccount); } else { DlgSetItemText(m_hwnd, IDC_EDITSERVER, nullptr); @@ -172,11 +171,10 @@ struct CGeneralOptDlg : public CBaseOptionsDlg static int g_iStatusControls[] = {IDC_CHECKST0, IDC_CHECKST1, IDC_CHECKST2, IDC_CHECKST3, IDC_CHECKST4, IDC_CHECKST5, IDC_CHECKST6, IDC_CHECKST7}; -static BOOL DlgShowAccountStatus(HWND hDlg, HPOP3ACCOUNT ActualAccount) +static BOOL DlgShowAccountStatus(HWND hDlg, CPOP3Account* ActualAccount) { if (ActualAccount) { - WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread - + SReadGuard sra(ActualAccount->AccountAccessSO); CheckDlgButton(hDlg, IDC_CHECKST0, ActualAccount->StatusFlags & YAMN_ACC_ST0 ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_CHECKST1, ActualAccount->StatusFlags & YAMN_ACC_ST1 ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_CHECKST2, ActualAccount->StatusFlags & YAMN_ACC_ST2 ? BST_CHECKED : BST_UNCHECKED); @@ -185,8 +183,6 @@ static BOOL DlgShowAccountStatus(HWND hDlg, HPOP3ACCOUNT ActualAccount) CheckDlgButton(hDlg, IDC_CHECKST5, ActualAccount->StatusFlags & YAMN_ACC_ST5 ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_CHECKST6, ActualAccount->StatusFlags & YAMN_ACC_ST6 ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_CHECKST7, ActualAccount->StatusFlags & YAMN_ACC_ST7 ? BST_CHECKED : BST_UNCHECKED); - - ReadDone(ActualAccount); } else { CheckDlgButton(hDlg, IDC_CHECKST0, BST_UNCHECKED); @@ -203,10 +199,10 @@ static BOOL DlgShowAccountStatus(HWND hDlg, HPOP3ACCOUNT ActualAccount) static INT_PTR CALLBACK DlgProcPOP3AccStatusOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM) { - static HPOP3ACCOUNT ActualAccount; + static CPOP3Account* ActualAccount; switch (msg) { case WM_INITDIALOG: - ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput); + ActualAccount = (CPOP3Account*)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput); if (ActualAccount != nullptr) { DlgShowAccountStatus(hDlg, ActualAccount); for (auto &it : g_iStatusControls) @@ -252,7 +248,7 @@ class CAccOptDlg : public CBaseOptionsDlg { INT_PTR Result; UCHAR ActualStatus; - HPOP3ACCOUNT ActualAccount = nullptr; + CPOP3Account* ActualAccount = nullptr; CCtrlCheck chkContact, chkSsl, chkApp; CCtrlCombo cmbAccount, cmbCP; @@ -338,15 +334,13 @@ public: DlgShowAccount(0); // Fill accounts - WaitToReadSO(POP3Plugin->AccountBrowserSO); - - for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next) - if (ActualAccount->Name != nullptr) - cmbAccount.AddStringA(ActualAccount->Name); + { SReadGuard srb(POP3Plugin->AccountBrowserSO); + for (ActualAccount = (CPOP3Account *)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (CPOP3Account *)ActualAccount->Next) + if (ActualAccount->Name != nullptr) + cmbAccount.AddStringA(ActualAccount->Name); + } cmbAccount.SetCurSel(0); - ReadDoneSO(POP3Plugin->AccountBrowserSO); - // Fill code pages cmbCP.AddString(TranslateT("Default")); for (int i = 1; i < CPLENSUPP; i++) { @@ -360,22 +354,22 @@ public: ActualAccount = nullptr; SendMessage(GetParent(m_hwnd), PSM_UNCHANGED, (WPARAM)m_hwnd, 0); - WindowList_Add(pYAMNVar->MessageWnds, m_hwnd); + WindowList_Add(YAMNVar.MessageWnds, m_hwnd); return true; } void OnDestroy() override { - WindowList_Remove(pYAMNVar->MessageWnds, m_hwnd); + WindowList_Remove(YAMNVar.MessageWnds, m_hwnd); } INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override { switch (msg) { case WM_YAMN_CHANGESTATUS: - if ((HPOP3ACCOUNT)wParam == ActualAccount) { + if ((CPOP3Account*)wParam == ActualAccount) { wchar_t accstatus[256]; - GetAccountStatus(ActualAccount, accstatus); + GetStatusFcn(ActualAccount, accstatus); SetDlgItemText(m_hwnd, IDC_STSTATUS, accstatus); return TRUE; } @@ -386,7 +380,7 @@ public: return TRUE; case WM_YAMN_CHANGETIME: - if ((HPOP3ACCOUNT)wParam == ActualAccount) { + if ((CPOP3Account*)wParam == ActualAccount) { wchar_t Text[256]; mir_snwprintf(Text, TranslateT("Time left to next check [s]: %d"), (uint32_t)lParam); SetDlgItemText(m_hwnd, IDC_STTIMELEFT, Text); @@ -406,7 +400,7 @@ public: void onKillFocus_Account(CCtrlCombo *) { GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)); - if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) { + if (nullptr == (ActualAccount = (CPOP3Account*)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) { DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr); EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE); DlgEnableAccount(mir_strlen(DlgInput) > 0); @@ -423,7 +417,7 @@ public: if (CB_ERR != (Result = cmbAccount.GetCurSel())) SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput); - if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) { + if ((Result == CB_ERR) || (nullptr == (ActualAccount = (CPOP3Account*)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) { DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr); EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE); } @@ -515,7 +509,7 @@ public: GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)); EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), FALSE); if ((CB_ERR == (Result = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0))) - || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) + || (nullptr == (ActualAccount = (CPOP3Account*)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) return; if (IDOK != MessageBox(m_hwnd, TranslateT("Do you really want to delete this account?"), TranslateT("Delete account confirmation"), MB_OKCANCEL | MB_ICONWARNING)) @@ -546,7 +540,8 @@ public: char Text[MAX_PATH]; wchar_t TextW[MAX_PATH]; BOOL Translated, NewAcc = FALSE; - size_t Length, index; + size_t Length; + int index; if (!GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, Text, _countof(Text))) return false; @@ -600,129 +595,121 @@ public: DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use.")); - if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)Text))) { + if (nullptr == (ActualAccount = (CPOP3Account*)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)Text))) { NewAcc = TRUE; - WaitToWriteSO(POP3Plugin->AccountBrowserSO); - if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)POP3Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) { - WriteDoneSO(POP3Plugin->AccountBrowserSO); + SWriteGuard swb(POP3Plugin->AccountBrowserSO); + if (nullptr == (ActualAccount = (CPOP3Account*)CallService(MS_YAMN_GETNEXTFREEACCOUNT, (WPARAM)POP3Plugin, (LPARAM)YAMN_ACCOUNTVERSION))) { + swb.Uninit(); MessageBox(m_hwnd, TranslateT("Cannot allocate memory space for new account"), TranslateT("Memory error"), MB_OK); return false; } DlgEnableAccount(true); } - else { // We have to get full access to AccountBrowser, so other iterating thrads cannot get new account until new account is right set - WaitToWriteSO(POP3Plugin->AccountBrowserSO); - } - - if (WAIT_OBJECT_0 != WaitToWrite(ActualAccount)) - WriteDoneSO(POP3Plugin->AccountBrowserSO); - - GetDlgItemTextA(m_hwnd, IDC_EDITNAME, Text, _countof(Text)); - if (!(Length = mir_strlen(Text))) - return false; - if (nullptr != ActualAccount->Name) - delete[] ActualAccount->Name; - ActualAccount->Name = new char[mir_strlen(Text) + 1]; - mir_strcpy(ActualAccount->Name, Text); - - GetDlgItemTextA(m_hwnd, IDC_EDITSERVER, Text, _countof(Text)); - if (nullptr != ActualAccount->Server->Name) - delete[] ActualAccount->Server->Name; - ActualAccount->Server->Name = new char[mir_strlen(Text) + 1]; - mir_strcpy(ActualAccount->Server->Name, Text); - - GetDlgItemTextA(m_hwnd, IDC_EDITLOGIN, Text, _countof(Text)); - if (nullptr != ActualAccount->Server->Login) - delete[] ActualAccount->Server->Login; - ActualAccount->Server->Login = new char[mir_strlen(Text) + 1]; - mir_strcpy(ActualAccount->Server->Login, Text); - - GetDlgItemTextA(m_hwnd, IDC_EDITPASS, Text, _countof(Text)); - if (nullptr != ActualAccount->Server->Passwd) - delete[] ActualAccount->Server->Passwd; - ActualAccount->Server->Passwd = new char[mir_strlen(Text) + 1]; - mir_strcpy(ActualAccount->Server->Passwd, Text); - - GetDlgItemTextW(m_hwnd, IDC_EDITAPP, TextW, _countof(TextW)); - if (nullptr != ActualAccount->NewMailN.App) - delete[] ActualAccount->NewMailN.App; - ActualAccount->NewMailN.App = new wchar_t[mir_wstrlen(TextW) + 1]; - mir_wstrcpy(ActualAccount->NewMailN.App, TextW); - - GetDlgItemTextW(m_hwnd, IDC_EDITAPPPARAM, TextW, _countof(TextW)); - if (nullptr != ActualAccount->NewMailN.AppParam) - delete[] ActualAccount->NewMailN.AppParam; - ActualAccount->NewMailN.AppParam = new wchar_t[mir_wstrlen(TextW) + 1]; - mir_wstrcpy(ActualAccount->NewMailN.AppParam, TextW); - - ActualAccount->Server->Port = Port; - ActualAccount->Interval = Interval * 60; - - if (CB_ERR == (index = SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_GETCURSEL, 0, 0))) - index = CPDEFINDEX; - ActualAccount->CP = CodePageNamesSupp[index].CP; - - if (NewAcc) - ActualAccount->TimeLeft = Interval * 60; - - BOOL CheckStart = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSTART) == BST_CHECKED); - BOOL CheckForce = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFORCE) == BST_CHECKED); - - ActualAccount->Flags = - (Check ? YAMN_ACC_ENA : 0) | - (CheckSSL ? YAMN_ACC_SSL23 : 0) | - (CheckNoTLS ? YAMN_ACC_NOTLS : 0) | - (CheckAPOP ? YAMN_ACC_APOP : 0) | - (CheckABody ? YAMN_ACC_BODY : 0) | - (ActualAccount->Flags & YAMN_ACC_POPN); - - ActualAccount->StatusFlags &= 0xFFFF; - ActualAccount->StatusFlags |= - (CheckStart ? YAMN_ACC_STARTS : 0) | - (CheckForce ? YAMN_ACC_FORCE : 0); - - ActualAccount->NewMailN.Flags = - (CheckMsg ? YAMN_ACC_MSG : 0) | - (CheckIco ? YAMN_ACC_ICO : 0) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_POP) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) | - (CheckApp ? YAMN_ACC_APP : 0) | - (CheckKBN ? YAMN_ACC_KBN : 0) | - (CheckContact ? YAMN_ACC_CONT : 0) | - (CheckContactNick ? YAMN_ACC_CONTNICK : 0) | - (CheckContactNoEvent ? YAMN_ACC_CONTNOEVENT : 0) | - YAMN_ACC_MSGP; //this is default: when new mail arrives and window was displayed, leave it displayed. - - ActualAccount->NoNewMailN.Flags = - (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP) | - (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) | - (CheckNMsgP ? YAMN_ACC_MSGP : 0); - - ActualAccount->BadConnectN.Flags = - (CheckFMsg ? YAMN_ACC_MSG : 0) | - (CheckFIco ? YAMN_ACC_ICO : 0) | - (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP) | - (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC); - - WriteDone(ActualAccount); - WriteDoneSO(POP3Plugin->AccountBrowserSO); + { + SWriteGuard swa(ActualAccount->AccountAccessSO); + if (swa.Succeeded()) { + GetDlgItemTextA(m_hwnd, IDC_EDITNAME, Text, _countof(Text)); + if (!(Length = mir_strlen(Text))) + return false; + if (nullptr != ActualAccount->Name) + delete[] ActualAccount->Name; + ActualAccount->Name = new char[mir_strlen(Text) + 1]; + mir_strcpy(ActualAccount->Name, Text); + + GetDlgItemTextA(m_hwnd, IDC_EDITSERVER, Text, _countof(Text)); + if (nullptr != ActualAccount->Server->Name) + delete[] ActualAccount->Server->Name; + ActualAccount->Server->Name = new char[mir_strlen(Text) + 1]; + mir_strcpy(ActualAccount->Server->Name, Text); + + GetDlgItemTextA(m_hwnd, IDC_EDITLOGIN, Text, _countof(Text)); + if (nullptr != ActualAccount->Server->Login) + delete[] ActualAccount->Server->Login; + ActualAccount->Server->Login = new char[mir_strlen(Text) + 1]; + mir_strcpy(ActualAccount->Server->Login, Text); + + GetDlgItemTextA(m_hwnd, IDC_EDITPASS, Text, _countof(Text)); + if (nullptr != ActualAccount->Server->Passwd) + delete[] ActualAccount->Server->Passwd; + ActualAccount->Server->Passwd = new char[mir_strlen(Text) + 1]; + mir_strcpy(ActualAccount->Server->Passwd, Text); + + GetDlgItemTextW(m_hwnd, IDC_EDITAPP, TextW, _countof(TextW)); + if (nullptr != ActualAccount->NewMailN.App) + delete[] ActualAccount->NewMailN.App; + ActualAccount->NewMailN.App = new wchar_t[mir_wstrlen(TextW) + 1]; + mir_wstrcpy(ActualAccount->NewMailN.App, TextW); + + GetDlgItemTextW(m_hwnd, IDC_EDITAPPPARAM, TextW, _countof(TextW)); + if (nullptr != ActualAccount->NewMailN.AppParam) + delete[] ActualAccount->NewMailN.AppParam; + ActualAccount->NewMailN.AppParam = new wchar_t[mir_wstrlen(TextW) + 1]; + mir_wstrcpy(ActualAccount->NewMailN.AppParam, TextW); + + ActualAccount->Server->Port = Port; + ActualAccount->Interval = Interval * 60; + + if (CB_ERR == (index = SendDlgItemMessage(m_hwnd, IDC_COMBOCP, CB_GETCURSEL, 0, 0))) + index = CPDEFINDEX; + ActualAccount->CP = CodePageNamesSupp[index].CP; + + if (NewAcc) + ActualAccount->TimeLeft = Interval * 60; + + BOOL CheckStart = (IsDlgButtonChecked(m_hwnd, IDC_CHECKSTART) == BST_CHECKED); + BOOL CheckForce = (IsDlgButtonChecked(m_hwnd, IDC_CHECKFORCE) == BST_CHECKED); + + ActualAccount->Flags = + (Check ? YAMN_ACC_ENA : 0) | + (CheckSSL ? YAMN_ACC_SSL23 : 0) | + (CheckNoTLS ? YAMN_ACC_NOTLS : 0) | + (CheckAPOP ? YAMN_ACC_APOP : 0) | + (CheckABody ? YAMN_ACC_BODY : 0) | + (ActualAccount->Flags & YAMN_ACC_POPN); + + ActualAccount->StatusFlags &= 0xFFFF; + ActualAccount->StatusFlags |= + (CheckStart ? YAMN_ACC_STARTS : 0) | + (CheckForce ? YAMN_ACC_FORCE : 0); + + ActualAccount->NewMailN.Flags = + (CheckMsg ? YAMN_ACC_MSG : 0) | + (CheckIco ? YAMN_ACC_ICO : 0) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_POP) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) | + (CheckApp ? YAMN_ACC_APP : 0) | + (CheckKBN ? YAMN_ACC_KBN : 0) | + (CheckContact ? YAMN_ACC_CONT : 0) | + (CheckContactNick ? YAMN_ACC_CONTNICK : 0) | + (CheckContactNoEvent ? YAMN_ACC_CONTNOEVENT : 0) | + YAMN_ACC_MSGP; //this is default: when new mail arrives and window was displayed, leave it displayed. + + ActualAccount->NoNewMailN.Flags = + (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP) | + (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) | + (CheckNMsgP ? YAMN_ACC_MSGP : 0); + + ActualAccount->BadConnectN.Flags = + (CheckFMsg ? YAMN_ACC_MSG : 0) | + (CheckFIco ? YAMN_ACC_ICO : 0) | + (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP) | + (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC); + } + } EnableWindow(GetDlgItem(m_hwnd, IDC_BTNDEL), TRUE); DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr); - index = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0); + index = cmbAccount.GetCurSel(); + cmbAccount.ResetContent(); - HPOP3ACCOUNT temp = ActualAccount; - - SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_RESETCONTENT, 0, 0); if (POP3Plugin->FirstAccount != nullptr) - for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next) - if (ActualAccount->Name != nullptr) - SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_ADDSTRING, 0, (LPARAM)ActualAccount->Name); + for (auto *p = POP3Plugin->FirstAccount; p != nullptr; p = p->Next) + if (p->Name != nullptr) + cmbAccount.AddStringA(p->Name); - ActualAccount = temp; - SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_SETCURSEL, (WPARAM)index, (LPARAM)ActualAccount->Name); + index = cmbAccount.SetCurSel(index); WritePOP3Accounts(); RefreshContact(); @@ -735,7 +722,7 @@ public: class CPopupOptsDlg : public CBaseOptionsDlg { - HPOP3ACCOUNT ActualAccount = nullptr; + CPOP3Account* ActualAccount = nullptr; UCHAR ActualStatus; CCtrlCombo cmbAccount, cmbCP; @@ -745,7 +732,7 @@ class CPopupOptsDlg : public CBaseOptionsDlg void DlgShowAccountPopup() { if (ActualAccount) { - WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread + SReadGuard sra(ActualAccount->AccountAccessSO); SetDlgItemInt(m_hwnd, IDC_EDITPOPS, ActualAccount->NewMailN.PopupTime, FALSE); SetDlgItemInt(m_hwnd, IDC_EDITNPOPS, ActualAccount->NoNewMailN.PopupTime, FALSE); SetDlgItemInt(m_hwnd, IDC_EDITFPOPS, ActualAccount->BadConnectN.PopupTime, FALSE); @@ -758,7 +745,6 @@ class CPopupOptsDlg : public CBaseOptionsDlg chkFcol.SetState(ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC); CheckDlgButton(m_hwnd, IDC_RADIOPOPN, ActualAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(m_hwnd, IDC_RADIOPOP1, ActualAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED); - ReadDone(ActualAccount); } else { // default SetDlgItemInt(m_hwnd, IDC_EDITPOPS, 0, FALSE); @@ -801,7 +787,7 @@ class CPopupOptsDlg : public CBaseOptionsDlg void DlgShowAccountColors() { - WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread + SReadGuard sra(ActualAccount->AccountAccessSO); if (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) { SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_SETCOLOUR, 0, (LPARAM)ActualAccount->NewMailN.PopupB); @@ -827,8 +813,6 @@ class CPopupOptsDlg : public CBaseOptionsDlg SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE)); SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_SETCOLOUR, 0, (LPARAM)GetSysColor(COLOR_WINDOWTEXT)); } - - ReadDone(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread } public: @@ -859,19 +843,17 @@ public: bool OnInitDialog() override { - WindowList_Add(pYAMNVar->MessageWnds, m_hwnd); + WindowList_Add(YAMNVar.MessageWnds, m_hwnd); DlgEnableAccountPopup(false); DlgShowAccountPopup(); - - WaitToReadSO(POP3Plugin->AccountBrowserSO); - - if (POP3Plugin->FirstAccount != nullptr) - for (ActualAccount = (HPOP3ACCOUNT)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (HPOP3ACCOUNT)ActualAccount->Next) - if (ActualAccount->Name != nullptr) - cmbAccount.AddStringA(ActualAccount->Name); - - ReadDoneSO(POP3Plugin->AccountBrowserSO); + { + SReadGuard srb(POP3Plugin->AccountBrowserSO); + if (POP3Plugin->FirstAccount != nullptr) + for (ActualAccount = (CPOP3Account *)POP3Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = (CPOP3Account *)ActualAccount->Next) + if (ActualAccount->Name != nullptr) + cmbAccount.AddStringA(ActualAccount->Name); + } ActualAccount = nullptr; cmbAccount.SetCurSel(0); return true; @@ -879,13 +861,13 @@ public: void OnDestroy() override { - WindowList_Remove(pYAMNVar->MessageWnds, m_hwnd); + WindowList_Remove(YAMNVar.MessageWnds, m_hwnd); } void onKillFocus_Account(CCtrlCombo *) { GetDlgItemTextA(m_hwnd, IDC_COMBOACCOUNT, DlgInput, _countof(DlgInput)); - if (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) { + if (nullptr == (ActualAccount = (CPOP3Account*)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput))) { DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr); if (mir_strlen(DlgInput)) DlgEnableAccountPopup(true); @@ -901,10 +883,10 @@ public: void onSelChange_Account(CCtrlCombo *) { - int Result = SendDlgItemMessage(m_hwnd, IDC_COMBOACCOUNT, CB_GETCURSEL, 0, 0); + int Result = cmbAccount.GetCurSel(); if (CB_ERR != Result) SendDlgItemMessageA(m_hwnd, IDC_COMBOACCOUNT, CB_GETLBTEXT, (WPARAM)Result, (LPARAM)DlgInput); - if ((Result == CB_ERR) || (nullptr == (ActualAccount = (HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) { + if ((Result == CB_ERR) || (nullptr == (ActualAccount = (CPOP3Account*)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)DlgInput)))) { DlgSetItemText(m_hwnd, (WPARAM)IDC_STTIMELEFT, nullptr); } else { @@ -1049,53 +1031,52 @@ public: } DlgSetItemTextW(m_hwnd, IDC_STTIMELEFT, TranslateT("Please wait while no account is in use.")); - - ActualAccount->Flags = - (ActualAccount->Flags & YAMN_ACC_ENA) | - (ActualAccount->Flags & YAMN_ACC_SSL23) | - (ActualAccount->Flags & YAMN_ACC_NOTLS) | - (ActualAccount->Flags & YAMN_ACC_APOP) | - (ActualAccount->Flags & YAMN_ACC_BODY) | - (CheckPopN ? YAMN_ACC_POPN : 0); - - ActualAccount->NewMailN.Flags = - (ActualAccount->NewMailN.Flags & YAMN_ACC_MSG) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_ICO) | - (CheckPopup ? YAMN_ACC_POP : 0) | - (CheckPopupW ? YAMN_ACC_POPC : 0) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_APP) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_CONT) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNICK) | - (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT) | - YAMN_ACC_MSGP; - - ActualAccount->NoNewMailN.Flags = - (CheckNPopup ? YAMN_ACC_POP : 0) | - (CheckNPopupW ? YAMN_ACC_POPC : 0) | - (ActualAccount->NoNewMailN.Flags & YAMN_ACC_MSGP); - - ActualAccount->BadConnectN.Flags = - (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) | - (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) | - (CheckFPopup ? YAMN_ACC_POP : 0) | - (CheckFPopupW ? YAMN_ACC_POPC : 0); - - ActualAccount->NewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_GETCOLOUR, 0, 0); - ActualAccount->NewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_GETCOLOUR, 0, 0); - ActualAccount->NewMailN.PopupTime = Time; - - ActualAccount->NoNewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_GETCOLOUR, 0, 0); - ActualAccount->NoNewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_GETCOLOUR, 0, 0); - ActualAccount->NoNewMailN.PopupTime = TimeN; - - ActualAccount->BadConnectN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_GETCOLOUR, 0, 0); - ActualAccount->BadConnectN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_GETCOLOUR, 0, 0); - ActualAccount->BadConnectN.PopupTime = TimeF; - - WriteDone(ActualAccount); - WriteDoneSO(POP3Plugin->AccountBrowserSO); - + { + SWriteGuard swa(ActualAccount->AccountAccessSO); + + ActualAccount->Flags = + (ActualAccount->Flags & YAMN_ACC_ENA) | + (ActualAccount->Flags & YAMN_ACC_SSL23) | + (ActualAccount->Flags & YAMN_ACC_NOTLS) | + (ActualAccount->Flags & YAMN_ACC_APOP) | + (ActualAccount->Flags & YAMN_ACC_BODY) | + (CheckPopN ? YAMN_ACC_POPN : 0); + + ActualAccount->NewMailN.Flags = + (ActualAccount->NewMailN.Flags & YAMN_ACC_MSG) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_ICO) | + (CheckPopup ? YAMN_ACC_POP : 0) | + (CheckPopupW ? YAMN_ACC_POPC : 0) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_APP) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_CONT) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNICK) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT) | + YAMN_ACC_MSGP; + + ActualAccount->NoNewMailN.Flags = + (CheckNPopup ? YAMN_ACC_POP : 0) | + (CheckNPopupW ? YAMN_ACC_POPC : 0) | + (ActualAccount->NoNewMailN.Flags & YAMN_ACC_MSGP); + + ActualAccount->BadConnectN.Flags = + (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) | + (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) | + (CheckFPopup ? YAMN_ACC_POP : 0) | + (CheckFPopupW ? YAMN_ACC_POPC : 0); + + ActualAccount->NewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPB, CPM_GETCOLOUR, 0, 0); + ActualAccount->NewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPT, CPM_GETCOLOUR, 0, 0); + ActualAccount->NewMailN.PopupTime = Time; + + ActualAccount->NoNewMailN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPNB, CPM_GETCOLOUR, 0, 0); + ActualAccount->NoNewMailN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPNT, CPM_GETCOLOUR, 0, 0); + ActualAccount->NoNewMailN.PopupTime = TimeN; + + ActualAccount->BadConnectN.PopupB = SendDlgItemMessage(m_hwnd, IDC_CPFB, CPM_GETCOLOUR, 0, 0); + ActualAccount->BadConnectN.PopupT = SendDlgItemMessage(m_hwnd, IDC_CPFT, CPM_GETCOLOUR, 0, 0); + ActualAccount->BadConnectN.PopupTime = TimeF; + } WritePOP3Accounts(); RefreshContact(); return TRUE; diff --git a/protocols/YAMN/src/protoplugin.cpp b/protocols/YAMN/src/protoplugin.cpp index b192ac1f5f..7732640fcb 100644 --- a/protocols/YAMN/src/protoplugin.cpp +++ b/protocols/YAMN/src/protoplugin.cpp @@ -8,12 +8,12 @@ //-------------------------------------------------------------------------------------------------- -PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin = nullptr; +YAMN_PROTOPLUGINQUEUE *FirstProtoPlugin = nullptr; INT_PTR RegisterProtocolPluginSvc(WPARAM, LPARAM); //Removes plugin from queue and deletes registration structures -INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin); +INT_PTR UnregisterProtocolPlugin(YAMN_PROTOPLUGIN *Plugin); INT_PTR UnregisterProtocolPluginSvc(WPARAM, LPARAM); @@ -27,12 +27,7 @@ INT_PTR UnregisterProtoPlugins(); // YAMNMailFcn- pointer to imported functions with mails // YAMNMailFcnVer- version of YAMN_MAILIMPORTFCN, use YAMN_MAILIMPORTFCNVERSION // returns nonzero if success -int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer); - -struct CExportedFunctions ProtoPluginExportedFcn[] = -{ - {YAMN_SETPROTOCOLPLUGINFCNIMPORTID, (void *)SetProtocolPluginFcnImportFcn}, -}; +int WINAPI SetProtocolPluginFcnImportFcn(YAMN_PROTOPLUGIN *Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer); struct CExportedServices ProtoPluginExportedSvc[] = { @@ -48,7 +43,7 @@ struct CExportedServices ProtoPluginExportedSvc[] = INT_PTR RegisterProtocolPluginSvc(WPARAM wParam, LPARAM lParam) { PYAMN_PROTOREGISTRATION Registration = (PYAMN_PROTOREGISTRATION)wParam; - HYAMNPROTOPLUGIN Plugin; + YAMN_PROTOPLUGIN *Plugin; if (lParam != YAMN_PROTOREGISTRATIONVERSION) return 0; @@ -58,22 +53,15 @@ INT_PTR RegisterProtocolPluginSvc(WPARAM wParam, LPARAM lParam) return (INT_PTR)NULL; Plugin->PluginInfo = Registration; - Plugin->FirstAccount = nullptr; - - Plugin->AccountBrowserSO = new SWMRG; - SWMRGInitialize(Plugin->AccountBrowserSO, nullptr); - Plugin->Fcn = nullptr; Plugin->MailFcn = nullptr; return (INT_PTR)Plugin; } -int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer) +int WINAPI SetProtocolPluginFcnImportFcn(YAMN_PROTOPLUGIN *Plugin, PYAMN_PROTOIMPORTFCN YAMNFcn, uint32_t YAMNFcnVer, PYAMN_MAILIMPORTFCN YAMNMailFcn, uint32_t YAMNMailFcnVer) { - PYAMN_PROTOPLUGINQUEUE Parser; - if (YAMNFcnVer != YAMN_PROTOIMPORTFCNVERSION) return 0; if (YAMNMailFcnVer != YAMN_MAILIMPORTFCNVERSION) @@ -87,7 +75,9 @@ int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMP Plugin->MailFcn = YAMNMailFcn; mir_cslock lck(PluginRegCS); + // We add protocol to the protocol list + YAMN_PROTOPLUGINQUEUE *Parser; for (Parser = FirstProtoPlugin; Parser != nullptr && Parser->Next != nullptr; Parser = Parser->Next); if (Parser == nullptr) { FirstProtoPlugin = new YAMN_PROTOPLUGINQUEUE; @@ -103,9 +93,9 @@ int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin, PYAMN_PROTOIMP return 1; } -INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin) +INT_PTR UnregisterProtocolPlugin(YAMN_PROTOPLUGIN *Plugin) { - PYAMN_PROTOPLUGINQUEUE Parser, Found; + YAMN_PROTOPLUGINQUEUE *Parser, *Found; if (FirstProtoPlugin->Plugin == Plugin) { Found = FirstProtoPlugin; @@ -120,24 +110,23 @@ INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin) else Found = nullptr; } - if (Found != nullptr) { - StopAccounts(Plugin); - DeleteAccounts(Plugin); - if (Plugin->Fcn->UnLoadFcn != nullptr) - Plugin->Fcn->UnLoadFcn((void *)nullptr); - - delete Found->Plugin->AccountBrowserSO; - delete Found->Plugin; - delete Found; - } - else - return 0; - return 1; + + if (!Found) + return 1; + + StopAccounts(Plugin); + DeleteAccounts(Plugin); + if (Plugin->Fcn->UnLoadFcn != nullptr) + Plugin->Fcn->UnLoadFcn((void *)nullptr); + + delete Found->Plugin; + delete Found; + return 0; } INT_PTR UnregisterProtocolPluginSvc(WPARAM wParam, LPARAM) { - HYAMNPROTOPLUGIN Plugin = (HYAMNPROTOPLUGIN)wParam; + YAMN_PROTOPLUGIN *Plugin = (YAMN_PROTOPLUGIN*)wParam; mir_cslock lck(PluginRegCS); UnregisterProtocolPlugin(Plugin); diff --git a/protocols/YAMN/src/services.cpp b/protocols/YAMN/src/services.cpp index 361fb01636..180b035a06 100644 --- a/protocols/YAMN/src/services.cpp +++ b/protocols/YAMN/src/services.cpp @@ -58,7 +58,8 @@ static INT_PTR ContactApplication(WPARAM wParam, LPARAM) STARTUPINFOW si = {0}; si.cb = sizeof(si); - if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra.Succeeded()) { if (ActualAccount->NewMailN.App != nullptr) { wchar_t *Command; if (ActualAccount->NewMailN.AppParam != nullptr) @@ -78,15 +79,13 @@ static INT_PTR ContactApplication(WPARAM wParam, LPARAM) delete[] Command; } } - - ReadDoneFcn(ActualAccount->AccountAccessSO); } } db_free(&dbv); return 0; } -uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout); +uint32_t WINAPI SWMRGWaitToRead(SWMRG *pSWMRG, uint32_t dwTimeout); static INT_PTR AccountMailCheck(WPARAM wParam, LPARAM lParam) { //This service will check/sincronize the account pointed by wParam @@ -102,9 +101,8 @@ static INT_PTR AccountMailCheck(WPARAM wParam, LPARAM lParam) return 0; mir_cslock lck(PluginRegCS); - if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualAccount->AccountAccessSO, 0)) { - } - else { + SReadGuard sra(ActualAccount->AccountAccessSO, 0); + if (sra.Succeeded()) { if ((ActualAccount->Flags & YAMN_ACC_ENA) && ActualAccount->Plugin->Fcn->SynchroFcnPtr) { CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, lParam != 0 ? YAMN_FORCECHECK : YAMN_NORMALCHECK, nullptr, nullptr}; @@ -116,7 +114,6 @@ static INT_PTR AccountMailCheck(WPARAM wParam, LPARAM lParam) CloseHandle(NewThread); } } - ReadDoneFcn(ActualAccount->AccountAccessSO); } CloseHandle(ThreadRunningEV); } @@ -142,23 +139,17 @@ static INT_PTR ContactMailCheck(WPARAM hContact, LPARAM) //if we want to close miranda, we get event and do not run pop3 checking anymore if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0)) return 0; + mir_cslock lck(PluginRegCS); - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) { - } - else { + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra.Succeeded()) { if ((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) //account cannot be forced to check { - if (ActualAccount->Plugin->Fcn->ForceCheckFcnPtr == nullptr) - ReadDoneFcn(ActualAccount->AccountAccessSO); - DWORD tid; struct CheckParam ParamToPlugin = {YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_FORCECHECK, (void *)nullptr, nullptr}; - if (nullptr == CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid)) - ReadDoneFcn(ActualAccount->AccountAccessSO); - else + if (CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid)) WaitForSingleObject(ThreadRunningEV, INFINITE); } - ReadDoneFcn(ActualAccount->AccountAccessSO); } CloseHandle(ThreadRunningEV); } @@ -178,8 +169,9 @@ static INT_PTR ContactMailCheck(WPARAM hContact, LPARAM) CAccount *ActualAccount = (CAccount *)CallService(MS_YAMN_FINDACCOUNTBYNAME, (WPARAM)POP3Plugin, (LPARAM)dbv.pszVal); if (ActualAccount != nullptr) { - if (WAIT_OBJECT_0 == WaitToReadFcn(ActualAccount->AccountAccessSO)) { - YAMN_MAILBROWSERPARAM Param = {nullptr, ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr}; + SReadGuard sra(ActualAccount->AccountAccessSO); + if (sra.Succeeded()) { + YAMN_MAILBROWSERPARAM Param = { ActualAccount, ActualAccount->NewMailN.Flags, ActualAccount->NoNewMailN.Flags, nullptr}; Param.nnflags = Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account Param.nnflags = Param.nnflags & ~YAMN_ACC_POP; @@ -188,7 +180,6 @@ static INT_PTR ContactMailCheck(WPARAM hContact, LPARAM) Param.nflags = Param.nflags & ~YAMN_ACC_POP; RunMailBrowserSvc((WPARAM)&Param, YAMN_MAILBROWSERVERSION); - ReadDoneFcn(ActualAccount->AccountAccessSO); } } db_free(&dbv); @@ -285,12 +276,6 @@ void CreateServiceFunctions(void) CreateServiceFunction(YAMN_DBMODULE PS_GETNAME, Service_GetName); CreateServiceFunction(YAMN_DBMODULE PS_LOADICON, Service_LoadIcon); - // Function with which protocol plugin can register - CreateServiceFunction(MS_YAMN_GETFCNPTR, GetFcnPtrSvc); - - // Function returns pointer to YAMN variables - CreateServiceFunction(MS_YAMN_GETVARIABLES, GetVariablesSvc); - // Function with which protocol plugin can register CreateServiceFunction(MS_YAMN_REGISTERPROTOPLUGIN, RegisterProtocolPluginSvc); diff --git a/protocols/YAMN/src/stdafx.h b/protocols/YAMN/src/stdafx.h index 38f1c1b5fe..25dda0a5f5 100644 --- a/protocols/YAMN/src/stdafx.h +++ b/protocols/YAMN/src/stdafx.h @@ -69,12 +69,10 @@ void UnInitDebug(); // From yamn.cpp INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM lParam); -INT_PTR GetVariablesSvc(WPARAM, LPARAM); + void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD); INT_PTR ForceCheckSvc(WPARAM, LPARAM); -extern struct YAMNExportedFcns *pYAMNFcn; - // From account.cpp INT_PTR CreatePluginAccountSvc(WPARAM wParam, LPARAM lParam); INT_PTR DeletePluginAccountSvc(WPARAM wParam, LPARAM); @@ -104,9 +102,9 @@ INT_PTR GetNextFreeAccountSvc(WPARAM wParam, LPARAM lParam); INT_PTR DeleteAccountSvc(WPARAM wParam, LPARAM); void __cdecl DeleteAccountInBackground(void *Which); -int StopAccounts(HYAMNPROTOPLUGIN Plugin); -int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin, BOOL GetAccountBrowserAccess = FALSE); -int DeleteAccounts(HYAMNPROTOPLUGIN Plugin); +int StopAccounts(YAMN_PROTOPLUGIN *Plugin); +int WaitForAllAccounts(YAMN_PROTOPLUGIN *Plugin, BOOL GetAccountBrowserAccess = FALSE); +int DeleteAccounts(YAMN_PROTOPLUGIN *Plugin); void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value); void WINAPI SetStatusFcn(CAccount *Which, wchar_t *Value); @@ -177,26 +175,21 @@ extern HANDLE hTTButton; extern HCURSOR hCurSplitNS, hCurSplitWE; extern UINT SecTimer; -//From synchro.cpp +// From synchro.cpp void WINAPI DeleteMessagesToEndFcn(CAccount *Account, HYAMNMAIL From); -uint32_t WINAPI WaitToWriteFcn(PSWMRG SObject, PSCOUNTER SCounter = nullptr); -void WINAPI WriteDoneFcn(PSWMRG SObject, PSCOUNTER SCounter = nullptr); -uint32_t WINAPI WaitToReadFcn(PSWMRG SObject); -void WINAPI ReadDoneFcn(PSWMRG SObject); -uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter); -uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter); -BOOL WINAPI SWMRGInitialize(PSWMRG, wchar_t *); -void WINAPI SWMRGDelete(PSWMRG); -uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout); -void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG); -uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout); -void WINAPI SWMRGDoneReading(PSWMRG pSWMRG); - -//From mails.cpp + +// From mails.cpp void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode); void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From, uint32_t FlagsSet, uint32_t FlagsNotSet, uint32_t FlagsToSet, int mode); -//From mime.cpp +void WINAPI AppendQueueFcn(HYAMNMAIL first, HYAMNMAIL second); +HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From); +void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From, HYAMNMAIL Which, int mode = 0); +HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From, char *ID); +void WINAPI SynchroMessagesFcn(CAccount *Account, HYAMNMAIL *OldQueue, HYAMNMAIL *RemovedOld, HYAMNMAIL *NewQueue, HYAMNMAIL *RemovedNew); +void WINAPI TranslateHeaderFcn(char *stream, int len, struct CMimeItem **head); + +// From mime.cpp void ExtractHeader(struct CMimeItem *items, int &CP, struct CHeader *head); void ExtractShortHeader(struct CMimeItem *items, struct CShortHeader *head); void DeleteHeaderContent(struct CHeader *head); @@ -207,7 +200,7 @@ wchar_t *ParseMultipartBody(char *src, char *bond); //From account.cpp void WINAPI GetStatusFcn(CAccount *Which, wchar_t *Value); -extern HYAMNPROTOPLUGIN POP3Plugin; +extern YAMN_PROTOPLUGIN *POP3Plugin; //from decode.cpp int DecodeQuotedPrintable(char *Src, char *Dst, int DstLen, BOOL isQ); @@ -217,21 +210,7 @@ int DecodeBase64(char *Src, char *Dst, int DstLen); extern PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin; //From protoplugin.cpp -extern PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin; - -extern struct CExportedFunctions ProtoPluginExportedFcn[1]; -extern struct CExportedServices ProtoPluginExportedSvc[5]; -//From filterplugin.cpp -extern struct CExportedFunctions FilterPluginExportedFcn[1]; -extern struct CExportedServices FilterPluginExportedSvc[2]; -//From synchro.cpp -extern struct CExportedFunctions SynchroExportedFcn[7]; -//From account.cpp -extern struct CExportedFunctions AccountExportedFcn[2]; -extern struct CExportedServices AccountExportedSvc[9]; -//From mails.cpp (MIME) -extern struct CExportedFunctions MailExportedFcn[8]; -extern struct CExportedServices MailExportedSvc[5]; +extern YAMN_PROTOPLUGINQUEUE *FirstProtoPlugin; extern char *iconDescs[]; extern char *iconNames[]; @@ -243,11 +222,7 @@ extern struct WndHandles *MessageWnd; extern int GetCharsetFromString(char *input, size_t size); extern void ConvertCodedStringToUnicode(char *stream, wchar_t **storeto, uint32_t cp, int mode); -extern void __cdecl MailBrowser(void *Param); -extern void __cdecl BadConnection(void *Param); extern PVOID TLSCtx; extern PVOID SSLCtx; -extern PYAMN_VARIABLES pYAMNVar; - #endif diff --git a/protocols/YAMN/src/synchro.cpp b/protocols/YAMN/src/synchro.cpp index 184156787d..d239f95434 100644 --- a/protocols/YAMN/src/synchro.cpp +++ b/protocols/YAMN/src/synchro.cpp @@ -7,157 +7,85 @@ #include "stdafx.h" - // Initializes a SWMRG structure. This structure must be - // initialized before any writer or reader threads attempt - // to wait on it. - // The structure must be allocated by the application and - // the structure's address is passed as the first parameter. - // The lpszName parameter is the name of the object. Pass - // NULL if you do not want to share the object. -BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG, wchar_t *Name); - -// Deletes the system resources associated with a SWMRG -// structure. The structure must be deleted only when -// no writer or reader threads in the calling process -// will wait on it. -void WINAPI SWMRGDelete(PSWMRG pSWMRG); - -// A writer thread calls this function to know when -// it can successfully write to the shared data. -// returns WAIT_FINISH when we are in write-access or WAIT_FAILED -// when event about quick finishing is set (or when system returns fail when waiting for synchro object) -uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout); - -// A writer thread calls this function to let other threads -// know that it no longer needs to write to the shared data. -void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG); - -// A reader thread calls this function to know when -// it can successfully read the shared data. -// returns WAIT_FINISH when we are in read-access or WAIT_FAILED -// when event about quick finishing is set (or when system returns fail when waiting for synchro object) -uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout); - -// A reader thread calls this function to let other threads -// know when it no longer needs to read the shared data. -void WINAPI SWMRGDoneReading(PSWMRG pSWMRG); - -// WaitToReadFcn -// is used to wait for read access with SWMRG SO, but it also increments counter if successfull -// returns WAIT_FAILED or WAIT_FINISH -// when WAIT_FAILED, we should not begin to access datas, we are not in read-access mode -uint32_t WINAPI WaitToReadFcn(PSWMRG SObject); - -// WriteDoneFcn -// is used to release read access with SWMRG SO, but it also decrements counter if successfull -void WINAPI ReadDoneFcn(PSWMRG SObject); - -// This functions is for export purposes -// Plugin can call this function to manage SCOUNTER synchronization object - -// Gets number value stored in SCOUNTER SO -// Note you must not read the number from memory directly, because -// CPU can stop reading thread when it has read HI-Word, then another thread -// can change the value and then OS starts the previous thread, that reads the -// LO-uint16_t of uint32_t. And the return value HI+LO-uint16_t is corrupted -uint32_t WINAPI SCGetNumberFcn(PSCOUNTER SCounter); - -// Increments SCOUNTER and unsets event -// Returns Number after incrementing -uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter); - -// Decrements SCOUNTER and sets event if zero -// Returns Number after decrementing -uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter); - -struct CExportedFunctions SynchroExportedFcn[] = +///////////////////////////////////////////////////////////////////////////////////////// +// Initializes a SWMRG structure. This structure must be +// initialized before any writer or reader threads attempt +// to wait on it. +// The structure must be allocated by the application and +// the structure's address is passed as the first parameter. +// The lpszName parameter is the name of the object. Pass +// NULL if you do not want to share the object. + +SWMRG::SWMRG(wchar_t *Name) { - {YAMN_WAITTOWRITEID, (void *)WaitToWriteFcn}, - {YAMN_WRITEDONEID, (void *)WriteDoneFcn}, - {YAMN_WAITTOREADID, (void *)WaitToReadFcn}, - {YAMN_READDONEID, (void *)ReadDoneFcn}, - {YAMN_SCGETNUMBERID, (void *)SCGetNumberFcn}, - {YAMN_SCINCID, (void *)SCIncFcn}, - {YAMN_SCDECID, (void *)SCDecFcn}, -}; - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - -void WINAPI SWMRGDelete(PSWMRG pSWMRG) -{ - // Destroys any synchronization objects that were - // successfully created. - if (nullptr != pSWMRG->hEventNoWriter) - CloseHandle(pSWMRG->hEventNoWriter); - if (nullptr != pSWMRG->hEventNoReaders) - CloseHandle(pSWMRG->hEventNoReaders); - if (nullptr != pSWMRG->hSemNumReaders) - CloseHandle(pSWMRG->hSemNumReaders); - if (nullptr != pSWMRG->hFinishEV) - CloseHandle(pSWMRG->hFinishEV); -} - -BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG, wchar_t *Name) -{ - pSWMRG->hEventNoWriter = nullptr; - pSWMRG->hEventNoReaders = nullptr; - pSWMRG->hSemNumReaders = nullptr; - pSWMRG->hFinishEV = nullptr; - // Creates the automatic-reset event that is signalled when // no writer threads are writing. // Initially no reader threads are reading. if (Name != nullptr) Name[0] = (wchar_t)'W'; - pSWMRG->hEventNoWriter = CreateEvent(nullptr, FALSE, TRUE, Name); + hEventNoWriter = ::CreateEvent(nullptr, FALSE, TRUE, Name); // Creates the manual-reset event that is signalled when // no reader threads are reading. // Initially no reader threads are reading. if (Name != nullptr) Name[0] = (wchar_t)'R'; - pSWMRG->hEventNoReaders = CreateEvent(nullptr, TRUE, TRUE, Name); + hEventNoReaders = ::CreateEvent(nullptr, TRUE, TRUE, Name); // Initializes the variable that indicates the number of // reader threads that are reading. // Initially no reader threads are reading. if (Name != nullptr) Name[0] = (wchar_t)'C'; - pSWMRG->hSemNumReaders = CreateSemaphore(nullptr, 0, 0x7FFFFFFF, Name); + hSemNumReaders = ::CreateSemaphore(nullptr, 0, 0x7FFFFFFF, Name); if (Name != nullptr) Name[0] = (wchar_t)'F'; - pSWMRG->hFinishEV = CreateEvent(nullptr, TRUE, FALSE, Name); + hFinishEV = ::CreateEvent(nullptr, TRUE, FALSE, Name); +} - // If a synchronization object could not be created, - // destroys any created objects and return failure. - if ((nullptr == pSWMRG->hEventNoWriter) || (nullptr == pSWMRG->hEventNoReaders) || (nullptr == pSWMRG->hSemNumReaders) || (nullptr == pSWMRG->hFinishEV)) { - SWMRGDelete(pSWMRG); - return FALSE; - } - return TRUE; +// Destroys any synchronization objects that were +// successfully created. + +SWMRG::~SWMRG() +{ + if (nullptr != hEventNoWriter) + CloseHandle(hEventNoWriter); + if (nullptr != hEventNoReaders) + CloseHandle(hEventNoReaders); + if (nullptr != hSemNumReaders) + CloseHandle(hSemNumReaders); + if (nullptr != hFinishEV) + CloseHandle(hFinishEV); } -uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout) +///////////////////////////////////////////////////////////////////////////////////////// +// SWMRGWaitToWrite +// A writer thread calls this function to know when +// it can successfully write to the shared data. +// returns WAIT_FINISH when we are in write-access or WAIT_FAILED +// when event about quick finishing is set (or when system returns fail when waiting for synchro object) + +uint32_t SWMRG::WaitToWrite(uint32_t dwTimeout) { uint32_t dw; HANDLE aHandles[2]; + // SSL_DebugLog("SWMRGWaitToWrite %p", this); // We can write if the following are true: // 1. No other threads are writing. // 2. No threads are reading. // But first we have to know if SWMRG structure is not about to delete - aHandles[0] = pSWMRG->hEventNoWriter; - aHandles[1] = pSWMRG->hEventNoReaders; - if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(pSWMRG->hFinishEV, 0))) + aHandles[0] = hEventNoWriter; + aHandles[1] = hEventNoReaders; + if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(hFinishEV, 0))) return WAIT_FINISH; if (WAIT_FAILED == dw) return dw; dw = WaitForMultipleObjects(2, aHandles, TRUE, dwTimeout); // if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete - if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(pSWMRG->hFinishEV, 0)))) { - SetEvent(pSWMRG->hEventNoWriter); + if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(hFinishEV, 0)))) { + SetEvent(hEventNoWriter); return WAIT_FINISH; } @@ -170,32 +98,42 @@ uint32_t WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG, uint32_t dwTimeout) return dw; } -void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG) -// Presumably, a writer thread calling this function has -// successfully called WaitToWrite. This means that we -// do not have to wait on any synchronization objects -// here because the writer already owns the Event. +///////////////////////////////////////////////////////////////////////////////////////// +// SWMRGDoneWriting +// A writer thread calls this function to let other threads +// know that it no longer needs to write to the shared data. + +void SWMRG::DoneWriting() { + // SSL_DebugLog("SWMRGDoneWriting %p", this); + // Allow other writer/reader threads to use // the SWMRG synchronization object. - SetEvent(pSWMRG->hEventNoWriter); + SetEvent(hEventNoWriter); } -uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout) +///////////////////////////////////////////////////////////////////////////////////////// +// SWMRGWaitToRead +// is used to wait for read access with SWMRG SO, but it also increments counter if successfull +// returns WAIT_FAILED or WAIT_FINISH +// when WAIT_FAILED, we should not begin to access datas, we are not in read-access mode + +uint32_t SWMRG::WaitToRead(uint32_t dwTimeout) { uint32_t dw; LONG lPreviousCount; + // SSL_DebugLog("SWMRGWaitToRead %p", this); // We can read if no threads are writing. // And there's not request to delete structure - if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(pSWMRG->hFinishEV, 0))) + if (WAIT_OBJECT_0 == (dw = WaitForSingleObject(hFinishEV, 0))) return WAIT_FINISH; if (WAIT_FAILED == dw) return dw; - dw = WaitForSingleObject(pSWMRG->hEventNoWriter, dwTimeout); + dw = WaitForSingleObject(hEventNoWriter, dwTimeout); // if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete - if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(pSWMRG->hFinishEV, 0)))) { - SetEvent(pSWMRG->hEventNoWriter); + if ((dw != WAIT_FAILED) && (WAIT_OBJECT_0 == (WaitForSingleObject(hFinishEV, 0)))) { + SetEvent(hEventNoWriter); return WAIT_FINISH; } @@ -204,112 +142,123 @@ uint32_t WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, uint32_t dwTimeout) // Increment the number of reader threads. // But there can't be more than one thread incrementing readers, // so this is why we use semaphore. - ReleaseSemaphore(pSWMRG->hSemNumReaders, 1, &lPreviousCount); + ReleaseSemaphore(hSemNumReaders, 1, &lPreviousCount); if (lPreviousCount == 0) // If this is the first reader thread, // set event to reflect this. Other reader threads can read, no writer thread can write. - ResetEvent(pSWMRG->hEventNoReaders); + ResetEvent(hEventNoReaders); // Allow other writer/reader threads to use // the SWMRG synchronization object. hEventNoWrite is still non-signaled // (it looks like writer is processing thread, but it is not true) - SetEvent(pSWMRG->hEventNoWriter); + SetEvent(hEventNoWriter); } - return(dw); + return dw; } -void WINAPI SWMRGDoneReading(PSWMRG pSWMRG) +///////////////////////////////////////////////////////////////////////////////////////// +// SWMRGDoneReading +// A reader thread calls this function to let other threads +// know when it no longer needs to read the shared data. + +void SWMRG::DoneReading() { HANDLE aHandles[2]; LONG lNumReaders; + // SSL_DebugLog("SWMRGDoneReading %p", this); // We can stop reading if the events are available, // but when we stop reading we must also decrement the // number of reader threads. - aHandles[0] = pSWMRG->hEventNoWriter; - aHandles[1] = pSWMRG->hSemNumReaders; + aHandles[0] = hEventNoWriter; + aHandles[1] = hSemNumReaders; WaitForMultipleObjects(2, aHandles, TRUE, INFINITE); // Get the remaining number of readers by releasing the // semaphore and then restoring the count by immediately // performing a wait. - ReleaseSemaphore(pSWMRG->hSemNumReaders, 1, &lNumReaders); - WaitForSingleObject(pSWMRG->hSemNumReaders, INFINITE); + ReleaseSemaphore(hSemNumReaders, 1, &lNumReaders); + WaitForSingleObject(hSemNumReaders, INFINITE); // If there are no remaining readers, // set the event to relect this. if (lNumReaders == 0) // If there are no reader threads, // set our event to reflect this. - SetEvent(pSWMRG->hEventNoReaders); + SetEvent(hEventNoReaders); // Allow other writer/reader threads to use // the SWMRG synchronization object. // (it looks like writer is processing thread, but it is not true) - SetEvent(pSWMRG->hEventNoWriter); + SetEvent(hEventNoWriter); } -uint32_t WINAPI WaitToWriteFcn(PSWMRG SObject, PSCOUNTER SCounter) -{ - uint32_t EnterCode; - - if (WAIT_OBJECT_0 == (EnterCode = SWMRGWaitToWrite(SObject, INFINITE))) - if (SCounter != nullptr) - SCIncFcn(SCounter); - - return EnterCode; -} +///////////////////////////////////////////////////////////////////////////////////////// +// SCOUNTER -void WINAPI WriteDoneFcn(PSWMRG SObject, PSCOUNTER SCounter) +SCOUNTER::SCOUNTER() { - SWMRGDoneWriting(SObject); - if (SCounter != nullptr) - SCDecFcn(SCounter); + InitializeCriticalSection(&CounterCS); + Event = CreateEvent(nullptr, FALSE, TRUE, nullptr); + SetEvent(Event); } -uint32_t WINAPI WaitToReadFcn(PSWMRG SObject) +SCOUNTER::SCOUNTER(HANDLE InitializedEvent) { - uint32_t EnterCode = SWMRGWaitToRead(SObject, INFINITE); - return EnterCode; + InitializeCriticalSection(&CounterCS); + Event = InitializedEvent; + SetEvent(Event); } -void WINAPI ReadDoneFcn(PSWMRG SObject) +SCOUNTER::~SCOUNTER() { - SWMRGDoneReading(SObject); + DeleteCriticalSection(&CounterCS); + CloseHandle(Event); } -uint32_t WINAPI SCGetNumberFcn(PSCOUNTER SCounter) -{ +// Gets number value stored in SCOUNTER SO +// Note you must not read the number from memory directly, because +// CPU can stop reading thread when it has read HI-Word, then another thread +// can change the value and then OS starts the previous thread, that reads the +// LO-uint16_t of uint32_t. And the return value HI+LO-uint16_t is corrupted - EnterCriticalSection(&SCounter->CounterCS); +uint32_t SCOUNTER::GetNumber() +{ + EnterCriticalSection(&CounterCS); - uint32_t Temp = SCounter->Number; + uint32_t Temp = Number; - LeaveCriticalSection(&SCounter->CounterCS); + LeaveCriticalSection(&CounterCS); return Temp; } -uint32_t WINAPI SCIncFcn(PSCOUNTER SCounter) +// Increments SCOUNTER and unsets event +// Returns Number after incrementing + +uint32_t SCOUNTER::Inc() { - EnterCriticalSection(&SCounter->CounterCS); + EnterCriticalSection(&CounterCS); - uint32_t Temp = ++SCounter->Number; - ResetEvent(SCounter->Event); + uint32_t Temp = ++Number; + ResetEvent(Event); - LeaveCriticalSection(&SCounter->CounterCS); + LeaveCriticalSection(&CounterCS); return Temp; } -uint32_t WINAPI SCDecFcn(PSCOUNTER SCounter) +// Decrements SCOUNTER and sets event if zero +// Returns Number after decrementing + +uint32_t SCOUNTER::Dec() { uint32_t Temp; - EnterCriticalSection(&SCounter->CounterCS); + EnterCriticalSection(&CounterCS); - if (!(Temp = --SCounter->Number)) { - SetEvent(SCounter->Event); + if (!(Temp = --Number)) { + SetEvent(Event); } - LeaveCriticalSection(&SCounter->CounterCS); + LeaveCriticalSection(&CounterCS); return Temp; } diff --git a/protocols/YAMN/src/version.h b/protocols/YAMN/src/version.h index 72bda16cfe..cd1a59c725 100644 --- a/protocols/YAMN/src/version.h +++ b/protocols/YAMN/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 -#define __MINOR_VERSION 1 -#define __RELEASE_NUM 2 -#define __BUILD_NUM 7 +#define __MINOR_VERSION 2 +#define __RELEASE_NUM 1 +#define __BUILD_NUM 1 #include diff --git a/protocols/YAMN/src/yamn.cpp b/protocols/YAMN/src/yamn.cpp index 2af7efd74f..753f269d3a 100644 --- a/protocols/YAMN/src/yamn.cpp +++ b/protocols/YAMN/src/yamn.cpp @@ -26,12 +26,6 @@ HANDLE ExitEV; //If this is signaled, write accounts to file is performed. Set this event if you want to actualize your accounts and messages HANDLE WriteToFileEV; -//Returns pointer to YAMN exported function -INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM lParam); - -//Returns pointer to YAMN variables -INT_PTR GetVariablesSvc(WPARAM wParam, LPARAM); - // Function every seconds decrements account counter of seconds and checks if they are 0 // If yes, creates a POP3 thread to check account void CALLBACK TimerProc(HWND, UINT, UINT, uint32_t); @@ -55,45 +49,6 @@ INT_PTR ForceCheckSvc(WPARAM, LPARAM); //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- -INT_PTR GetFcnPtrSvc(WPARAM wParam, LPARAM) -{ - int i; - - for (i=0;iNext) { - if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO, 0)) // we want to access accounts immiadtelly + for (YAMN_PROTOPLUGINQUEUE *ActualPlugin = FirstProtoPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) { + SReadGuard srb(ActualPlugin->Plugin->AccountBrowserSO, 0); // we want to access accounts immiadtelly + if (!srb.Succeeded()) return; for (ActualAccount = ActualPlugin->Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) { if (ActualAccount->Plugin == nullptr || ActualAccount->Plugin->Fcn == nullptr) //account not inited continue; - if (WAIT_OBJECT_0 != SWMRGWaitToRead(ActualAccount->AccountAccessSO, 0)) + SReadGuard sra(ActualAccount->AccountAccessSO, 0); + if (!sra.Succeeded()) continue; BOOL isAccountCounting = 0; @@ -148,14 +105,11 @@ void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD) ActualAccount->TimeLeft = ActualAccount->Interval; HANDLE NewThread = CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->TimeoutFcnPtr, &ParamToPlugin, 0, &tid); - if (NewThread == nullptr) { - ReadDoneFcn(ActualAccount->AccountAccessSO); + if (NewThread == nullptr) continue; - } - else { - WaitForSingleObject(ThreadRunningEV, INFINITE); - CloseHandle(NewThread); - } + + WaitForSingleObject(ThreadRunningEV, INFINITE); + CloseHandle(NewThread); } } @@ -171,9 +125,7 @@ ChangeIsCountingStatusLabel: break; } } - ReadDoneFcn(ActualAccount->AccountAccessSO); } - SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO); } CloseHandle(ThreadRunningEV); } @@ -191,34 +143,30 @@ INT_PTR ForceCheckSvc(WPARAM, LPARAM) if (WAIT_OBJECT_0 == WaitForSingleObject(ExitEV, 0)) return 0; - { - mir_cslock lck(PluginRegCS); - for (PYAMN_PROTOPLUGINQUEUE ActualPlugin = FirstProtoPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) { - SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO, INFINITE); + { mir_cslock lck(PluginRegCS); + + for (YAMN_PROTOPLUGINQUEUE *ActualPlugin = FirstProtoPlugin; ActualPlugin != nullptr; ActualPlugin = ActualPlugin->Next) { + SReadGuard srb(ActualPlugin->Plugin->AccountBrowserSO); for (ActualAccount = ActualPlugin->Plugin->FirstAccount; ActualAccount != nullptr; ActualAccount = ActualAccount->Next) { if (ActualAccount->Plugin->Fcn == nullptr) //account not inited continue; - if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) + SReadGuard sra(ActualAccount->AccountAccessSO); + if (!sra.Succeeded()) continue; if ((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) { //account cannot be forced to check - if (ActualAccount->Plugin->Fcn->ForceCheckFcnPtr == nullptr) { - ReadDoneFcn(ActualAccount->AccountAccessSO); + if (ActualAccount->Plugin->Fcn->ForceCheckFcnPtr == nullptr) continue; - } + struct CheckParam ParamToPlugin = { YAMN_CHECKVERSION, ThreadRunningEV, ActualAccount, YAMN_FORCECHECK, (void *)nullptr, nullptr }; - if (nullptr == CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid)) { - ReadDoneFcn(ActualAccount->AccountAccessSO); + if (nullptr == CreateThread(nullptr, 0, (YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr, &ParamToPlugin, 0, &tid)) continue; - } - else - WaitForSingleObject(ThreadRunningEV, INFINITE); + + WaitForSingleObject(ThreadRunningEV, INFINITE); } - ReadDoneFcn(ActualAccount->AccountAccessSO); } - SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO); } } -- cgit v1.2.3