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/proto/pop3/pop3comm.cpp | 417 ++++++++++++----------------- protocols/YAMN/src/proto/pop3/pop3comm.h | 64 ++--- protocols/YAMN/src/proto/pop3/pop3opt.cpp | 389 +++++++++++++-------------- 3 files changed, 379 insertions(+), 491 deletions(-) (limited to 'protocols/YAMN/src/proto') 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; -- cgit v1.2.3