From 6310a02bfe505209f20aeb96af7515555986dc91 Mon Sep 17 00:00:00 2001 From: Rozhuk Ivan Date: Thu, 27 Nov 2014 19:30:15 +0000 Subject: YAMN: code cleanup git-svn-id: http://svn.miranda-ng.org/main/trunk@11123 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/YAMN/src/account.cpp | 2601 +++++++++++++++++++++--------------------- 1 file changed, 1301 insertions(+), 1300 deletions(-) (limited to 'plugins/YAMN/src/account.cpp') diff --git a/plugins/YAMN/src/account.cpp b/plugins/YAMN/src/account.cpp index 376389eddb..7470a1b969 100644 --- a/plugins/YAMN/src/account.cpp +++ b/plugins/YAMN/src/account.cpp @@ -1,1300 +1,1301 @@ -/* - * This code implements manipulation with accounts - * such as reading accounts from file, writing them to file, - * finding account by name etc. - * - * (c) majvan 2002-2004 - */ - -#include "yamn.h" - -//Account status CS -//When we check some account, thread should change status of account to idle, connecting etc. -//So if we want to read status, we have to successfully write and then read. -CRITICAL_SECTION AccountStatusCS; - -//File Writing CS -//When 2 threads want to write to file... -CRITICAL_SECTION FileWritingCS; - -struct CExportedFunctions AccountExportedFcn[]= -{ - {YAMN_GETSTATUSID,(void *)GetStatusFcn}, - {YAMN_SETSTATUSID,(void *)SetStatusFcn}, -}; - -struct CExportedServices AccountExportedSvc[]= -{ - {MS_YAMN_CREATEPLUGINACCOUNT,CreatePluginAccountSvc}, - {MS_YAMN_DELETEPLUGINACCOUNT,DeletePluginAccountSvc}, - {MS_YAMN_FINDACCOUNTBYNAME,FindAccountByNameSvc}, - {MS_YAMN_GETNEXTFREEACCOUNT,GetNextFreeAccountSvc}, - {MS_YAMN_DELETEACCOUNT,DeletePluginAccountSvc}, - {MS_YAMN_READACCOUNTS,AddAccountsFromFileSvc}, - {MS_YAMN_WRITEACCOUNTS,WriteAccountsToFileSvc}, -}; - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - -INT_PTR CreatePluginAccountSvc(WPARAM wParam,LPARAM lParam) -{ - HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; - DWORD AccountVersion=(DWORD)lParam; - HACCOUNT NewAccount; - -//test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match) - if (AccountVersion != YAMN_ACCOUNTVERSION) - return NULL; - - if (Plugin != NULL) - { - if (Plugin->Fcn->NewAccountFcnPtr != NULL) - { -//Let plugin create its own structure, which can be derived from CAccount structure - NewAccount=Plugin->Fcn->NewAccountFcnPtr(Plugin,YAMN_ACCOUNTVERSION); - NewAccount->Plugin=Plugin; - } - else - { -//We suggest plugin uses standard CAccount structure, so we create it - NewAccount=new struct CAccount; - NewAccount->Plugin=Plugin; - } -//If not created successfully - if (NewAccount==NULL) - return NULL; -//Init every members of structure, used by YAMN - InitAccount(NewAccount); - - return (INT_PTR)NewAccount; - } - return NULL; -} - -INT_PTR DeletePluginAccountSvc(WPARAM wParam,LPARAM) -{ - HACCOUNT OldAccount=(HACCOUNT)wParam; - - if (OldAccount->Plugin->Fcn != NULL) - { -//Deinit every members and allocated fields of structure used by YAMN - DeInitAccount(OldAccount); - if (OldAccount->Plugin->Fcn->DeleteAccountFcnPtr != NULL) - { -//Let plugin delete its own CAccount derived structure - OldAccount->Plugin->Fcn->DeleteAccountFcnPtr(OldAccount); - } - else - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeletePluginAccountSvc:delete OldAccount\n"); -#endif - delete OldAccount; //consider account as standard YAMN HACCOUNT and use its own destructor - } - return 1; - } - delete OldAccount; //consider account as standard YAMN HACCOUNT, not initialized before and use its own destructor - return 1; -} - -int InitAccount(HACCOUNT Which) -{ -//initialize synchronizing objects - Which->AccountAccessSO=new SWMRG; - SWMRGInitialize(Which->AccountAccessSO,NULL); - Which->MessagesAccessSO=new SWMRG; - SWMRGInitialize(Which->MessagesAccessSO,NULL); - Which->UsingThreads=new SCOUNTER; - SWMRGInitialize(Which->MessagesAccessSO,NULL); - -//zero memory, where timestamps are stored - ZeroMemory(&Which->LastChecked,sizeof(Which->LastChecked)); - ZeroMemory(&Which->LastSChecked,sizeof(Which->LastSChecked)); - ZeroMemory(&Which->LastSynchronised,sizeof(Which->LastSynchronised)); - ZeroMemory(&Which->LastMail,sizeof(Which->LastMail)); - - Which->Name=NULL; - Which->Mails=NULL; - Which->Interval=0; - Which->Flags=0; - Which->StatusFlags=0; - Which->Next=NULL; - - Which->Server=new struct CServer; - Which->AbleToWork=TRUE; - - return 1; -} - -void DeInitAccount(HACCOUNT Which) -{ -//delete YAMN allocated fields - if (Which->Name != NULL) - delete[] Which->Name; - if (Which->Server->Name != NULL) - delete[] Which->Server->Name; - if (Which->Server->Login != NULL) - delete[] Which->Server->Login; - if (Which->Server->Passwd != NULL) - delete[] Which->Server->Passwd; - if (Which->Server != NULL) - delete[] Which->Server; - - SWMRGDelete(Which->AccountAccessSO); - delete Which->AccountAccessSO; - SWMRGDelete(Which->MessagesAccessSO); - delete Which->MessagesAccessSO; - delete Which->UsingThreads; - DeleteMessagesToEndFcn(Which,(HYAMNMAIL)Which->Mails); -} - -void StopSignalFcn(HACCOUNT Which) -//set event that we are going to delete account -{ -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"\tStopSignalFcn:stop account: %x\n",Which); -#endif - 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); -} - -void CodeDecodeString(char *Dest,BOOL Encrypt) -{ - TCHAR Code=STARTCODEPSW; - - if (Dest==NULL) - return; - - for (;*Dest != (TCHAR)0;Dest++) - { - if (Encrypt) - *Dest=*Dest+Code; - else - *Dest=*Dest-Code; - Code+=(TCHAR)ADDCODEPSW; - } -} - -static DWORD PostFileToMemory(HANDLE File,char **MemFile,char **End) -{ - DWORD FileSize,ReadBytes; - if (!(FileSize=GetFileSize(File,NULL))) { - CloseHandle(File); - return EACC_FILESIZE; - } - - //allocate space in memory, where we copy the whole file - if (NULL==(*MemFile = new char[FileSize])) - { - CloseHandle(File); - return EACC_ALLOC; - } - - //copy file to memory - if (!ReadFile(File,(LPVOID)*MemFile,FileSize,&ReadBytes,NULL)) - { - CloseHandle(File); - delete[] *MemFile; - return EACC_SYSTEM; - } - CloseHandle(File); - *End = *MemFile + FileSize; - return 0; -} - -DWORD FileToMemory(TCHAR *FileName,char **MemFile,char **End) -{ - HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return EACC_SYSTEM; - - return PostFileToMemory(hFile, MemFile, End); -} - -#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES) -DWORD ReadStringFromMemory(char **Parser,TCHAR *End,char **StoreTo,TCHAR *DebugString) -{ -//This is the debug version of ReadStringFromMemory function. This version shows MessageBox where -//read string is displayed - TCHAR *Dest,*Finder; - DWORD Size; - TCHAR Debug[65536]; - - Finder=*Parser; - while((*Finder != (TCHAR)0) && (Finder<=End)) Finder++; - mir_sntprintf(Debug, SIZEOF(Debug), _T("%s: %s,length is %d, remaining %d chars"), DebugString, *Parser, Finder-*Parser, End-Finder); - MessageBox(NULL,Debug,_T("debug"),MB_OK); - if (Finder>=End) - return EACC_FILECOMPATIBILITY; - if (Size=Finder-*Parser) - { - if (NULL==(Dest=*StoreTo=new TCHAR[Size+1])) - return EACC_ALLOC; - for (;*Parser<=Finder;(*Parser)++,Dest++) - *Dest=**Parser; - } - else - { - *StoreTo=NULL; - (*Parser)++; - } - return 0; -} -#endif - -DWORD ReadStringFromMemory(char **Parser,char *End,char **StoreTo) -{ - char *Dest,*Finder; - DWORD Size; - - Finder=*Parser; - while((*Finder != (TCHAR)0) && (Finder<=End)) Finder++; - if (Finder>=End) - return EACC_FILECOMPATIBILITY; - if (Size=Finder-*Parser) - { - if (NULL==(Dest=*StoreTo=new char[Size+1])) - return EACC_ALLOC; - for (;*Parser<=Finder;(*Parser)++,Dest++) - *Dest=**Parser; - } - else - { - *StoreTo=NULL; - (*Parser)++; - } - return 0; -} - - #if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES) -DWORD ReadStringFromMemoryW(WCHAR **Parser,TCHAR *End,WCHAR **StoreTo,WCHAR *DebugString) -{ -//This is the debug version of ReadStringFromMemoryW function. This version shows MessageBox where -//read string is displayed - WCHAR *Dest,*Finder; - DWORD Size; - WCHAR Debug[65536]; - - Finder=*Parser; - while((*Finder != (WCHAR)0) && (Finder<=(WCHAR *)End)) Finder++; - mir_sntprintf(Debug, SIZEOF(Debug), L"%s: %s,length is %d, remaining %d chars", DebugString, *Parser, Finder-*Parser, (WCHAR *)End-Finder); - MessageBoxW(NULL,Debug,L"debug",MB_OK); - if (Finder>=(WCHAR *)End) - return EACC_FILECOMPATIBILITY; - if (Size=Finder-*Parser) - { - if (NULL==(Dest=*StoreTo=new WCHAR[Size+1])) - return EACC_ALLOC; - for (;*Parser<=Finder;(*Parser)++,Dest++) - *Dest=**Parser; - } - else - { - *StoreTo=NULL; - (*Parser)++; - } - return 0; -} - #endif //if defined(DEBUG...) - -DWORD ReadStringFromMemoryW(WCHAR **Parser,WCHAR *End,WCHAR **StoreTo) -{ - WCHAR *Dest,*Finder; - DWORD Size; - - Finder=*Parser; - while((*Finder != (WCHAR)0) && (Finder<=(WCHAR *)End)) Finder++; - if (Finder>=(WCHAR *)End) - return EACC_FILECOMPATIBILITY; - if (Size=Finder-*Parser) - { - if (NULL==(Dest=*StoreTo=new WCHAR[Size+1])) - return EACC_ALLOC; - for (;*Parser<=Finder;(*Parser)++,Dest++) - *Dest=**Parser; - } - else - { - *StoreTo=NULL; - (*Parser)++; - } - return 0; -} - -static DWORD ReadNotificationFromMemory(char **Parser,char *End,YAMN_NOTIFICATION *Which) -{ - DWORD Stat; -#ifdef DEBUG_FILEREAD - TCHAR Debug[65536]; -#endif - - Which->Flags=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("NFlags: %04x, remaining %d chars"), Which->Flags, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - - Which->PopupB=*(COLORREF *)(*Parser); - (*Parser)+=sizeof(COLORREF); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("PopupB: %04x, remaining %d chars"), Which->PopupB, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - Which->PopupT=*(COLORREF *)(*Parser); - (*Parser)+=sizeof(COLORREF); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("PopupT: %04x, remaining %d chars"), Which->PopupT, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - Which->PopupTime=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("PopupTime: %04x, remaining %d chars"), Which->PopupTime, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - -#ifdef DEBUG_FILEREAD - if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->App,L"App")) -#else - if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->App)) -#endif - return Stat; -#ifdef DEBUG_FILEREAD - if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->AppParam,L"AppParam")) -#else - if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->AppParam)) -#endif - return Stat; - return 0; -} - -DWORD ReadMessagesFromMemory(HACCOUNT Which,char **Parser,char *End) -{ - char *Finder; - DWORD Size,Stat; - HYAMNMAIL ActualMail=NULL; - struct CMimeItem *items; - char *ReadString; - -#ifdef DEBUG_FILEREAD - MessageBox(NULL,_T("going to read messages, if any..."),_T("debug"),MB_OK); -#endif - do - { - Finder=*Parser; - while((*Finder != (TCHAR)0) && (Finder<=End)) Finder++; - if (Finder>=End) - return EACC_FILECOMPATIBILITY; - if (Size=Finder-*Parser) - { - if (Which->Mails==NULL) //First message in queue - { - if (NULL==(Which->Mails=ActualMail=CreateAccountMail(Which))) - return EACC_ALLOC; - } - else - { - if (NULL==(ActualMail->Next=CreateAccountMail(Which))) { - return EACC_ALLOC; - } - ActualMail=ActualMail->Next; - } - items=NULL; -#ifdef DEBUG_FILEREADMESSAGES - if (Stat=ReadStringFromMemory(Parser,End,&ActualMail->ID,_T("ID"))) -#else - if (Stat=ReadStringFromMemory(Parser,End,&ActualMail->ID)) -#endif - return Stat; -// ActualMail->MailData=new MAILDATA; !!! mem leake !!! this is alloc by CreateAccountMail, no need for doubble alloc !!!! - - ActualMail->MailData->Size=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; - ActualMail->Flags=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; - ActualMail->Number=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; - - if ((NULL != Which->Plugin->MailFcn) && (NULL != Which->Plugin->MailFcn->ReadMailOptsFcnPtr)) - Which->Plugin->MailFcn->ReadMailOptsFcnPtr(ActualMail,Parser,End); //read plugin mail settings from file - - do - { -#if defined(DEBUG_FILEREADMESSAGES) || defined(DEBUG_FILEREAD) - if (Stat=ReadStringFromMemory(Parser,End,&ReadString,_T("Name"))) -#else - if (Stat=ReadStringFromMemory(Parser,End,&ReadString)) -#endif - return Stat; - if (ReadString==NULL) - break; - -#ifdef DEBUG_DECODE - DebugLog(DecodeFile,"%s",ReadString); -#endif - - if (items==NULL) - items=ActualMail->MailData->TranslatedHeader=new struct CMimeItem; - else - { - items->Next=new struct CMimeItem; - items=items->Next; - } - if (items==NULL) - return EACC_ALLOC; - items->name=ReadString; - -#ifdef DEBUG_FILEREADMESSAGES - if (Stat=ReadStringFromMemory(Parser,End,&ReadString,_T("Value"))) -#else - if (Stat=ReadStringFromMemory(Parser,End,&ReadString)) -#endif - return Stat; - items->value=ReadString; -#ifdef DEBUG_DECODE - DebugLog(DecodeFile,"%s\n",ReadString); -#endif - }while(1); - } - else - break; //no next messages, new account! - - }while(1); - (*Parser)++; - return 0; -} - -DWORD ReadAccountFromMemory(HACCOUNT Which,char **Parser,char *End) -{ - DWORD Stat; -#ifdef DEBUG_FILEREAD - TCHAR Debug[65536]; -#endif - //Read name of account - -#ifdef DEBUG_FILEREAD - if (Stat=ReadStringFromMemory(Parser,End,&Which->Name,_T("Name"))) -#else - if (Stat=ReadStringFromMemory(Parser,End,&Which->Name)) -#endif - return Stat; - if (Which->Name==NULL) - return EACC_FILECOMPATIBILITY; - - //Read server parameters -#ifdef DEBUG_FILEREAD - if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Name,_T("Server"))) -#else - if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Name)) -#endif - return Stat; - Which->Server->Port=*(WORD *)(*Parser); - (*Parser)+=sizeof(WORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("Port: %d, remaining %d chars"), Which->Server->Port, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif -#ifdef DEBUG_FILEREAD - if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Login,_T("Login"))) -#else - if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Login)) -#endif - return Stat; -#ifdef DEBUG_FILEREAD - if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Passwd,_T("Password"))) -#else - if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Passwd)) -#endif - return Stat; - CodeDecodeString(Which->Server->Passwd,FALSE); - - //Read account flags - Which->Flags=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("Flags: %04x, remaining %d chars"), Which->Flags, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - Which->StatusFlags=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("STFlags: %04x, remaining %d chars"), Which->StatusFlags, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - Which->PluginFlags=*(DWORD *)(*Parser); - (*Parser)+=sizeof(DWORD); -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("PFlags: %04x, remaining %d chars"), Which->PluginFlags, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - - //Read account miscellaneous parameters - Which->Interval=*(WORD *)(*Parser); - Which->TimeLeft=Which->Interval; //check on loading - (*Parser)+=sizeof(WORD); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("Interval: %d, remaining %d chars"), Which->Interval, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - - //Read notification parameters - if (Stat=ReadNotificationFromMemory(Parser,End,&Which->NewMailN)) - return Stat; - if (Stat=ReadNotificationFromMemory(Parser,End,&Which->NoNewMailN)) - return Stat; - if (Stat=ReadNotificationFromMemory(Parser,End,&Which->BadConnectN)) - return Stat; - - //Let plugin read its own data stored in file - if (Which->Plugin->Fcn != NULL && Which->Plugin->Fcn->ReadPluginOptsFcnPtr != NULL) - if (Stat=Which->Plugin->Fcn->ReadPluginOptsFcnPtr(Which,Parser,End)) - return Stat; - //Read mails -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write wait\n"); -#endif - WaitToWriteFcn(Which->MessagesAccessSO); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write enter\n"); -#endif - if (Stat=ReadMessagesFromMemory(Which,Parser,End)) - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write done\n"); -#endif - WriteDoneFcn(Which->MessagesAccessSO); - return Stat; - } -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write done\n"); -#endif - WriteDoneFcn(Which->MessagesAccessSO); - - //Read timestamps - Which->LastChecked=*(SYSTEMTIME *)(*Parser); - (*Parser)+=sizeof(SYSTEMTIME); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("LastChecked: %04x, remaining %d chars"), Which->LastChecked, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - Which->LastSChecked=*(SYSTEMTIME *)(*Parser); - (*Parser)+=sizeof(SYSTEMTIME); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("LastSChecked: %04x, remaining %d chars"), Which->LastSChecked, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - Which->LastSynchronised=*(SYSTEMTIME *)(*Parser); - (*Parser)+=sizeof(SYSTEMTIME); - if (*Parser>=End) - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("LastSynchronised: %04x, remaining %d chars"), Which->LastSynchronised, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - Which->LastMail=*(SYSTEMTIME *)(*Parser); - (*Parser)+=sizeof(SYSTEMTIME); - if (*Parser>End) //WARNING! There's only > at the end of testing - return EACC_FILECOMPATIBILITY; -#ifdef DEBUG_FILEREAD - mir_sntprintf(Debug, SIZEOF(Debug), _T("LastMail: %04x, remaining %d chars"), Which->LastMail, End-*Parser); - MessageBox(NULL,Debug,_T("debug"),MB_OK); -#endif - if (*Parser==End) - return EACC_ENDOFFILE; - return 0; - -} - -static INT_PTR PerformAccountReading(HYAMNPROTOPLUGIN Plugin,char *MemFile,char *End) -{ - //Retrieve info for account from memory - char *Parser; - DWORD Ver,Stat; - - HACCOUNT ActualAccount,FirstAllocatedAccount; - - Ver=*(DWORD *)MemFile; - if (Ver>YAMN_ACCOUNTFILEVERSION) - { - delete[] MemFile; - return EACC_FILEVERSION; - } - Parser=MemFile+sizeof(Ver); - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write wait\n"); -#endif - SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write enter\n"); -#endif - if (NULL==(ActualAccount=(HACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT,(WPARAM)Plugin,(LPARAM)YAMN_ACCOUNTVERSION))) - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write done\n"); -#endif - SWMRGDoneWriting(Plugin->AccountBrowserSO); - delete[] MemFile; - return EACC_ALLOC; - } - FirstAllocatedAccount=ActualAccount; - - do - { - HACCOUNT Temp; - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write wait\n"); -#endif - WaitToWriteFcn(ActualAccount->AccountAccessSO); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write enter\n"); -#endif - Stat=ReadAccountFromMemory(ActualAccount,&Parser,End); - - if (ActualAccount->StatusFlags & (YAMN_ACC_STARTA | YAMN_ACC_STARTS)) - ActualAccount->TimeLeft=1; //check on loading - - if (Stat && (Stat != EACC_ENDOFFILE)) - { - for (ActualAccount=FirstAllocatedAccount;ActualAccount != NULL;ActualAccount=Temp) - { - Temp=ActualAccount->Next; - delete ActualAccount; - } - delete[] MemFile; - if (Plugin->FirstAccount==FirstAllocatedAccount) - Plugin->FirstAccount=NULL; -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write done\n"); -#endif - SWMRGDoneWriting(Plugin->AccountBrowserSO); - return (INT_PTR)Stat; - } - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write done\n"); -#endif - WriteDoneFcn(ActualAccount->AccountAccessSO); - - if ((Stat != EACC_ENDOFFILE) && (NULL==(ActualAccount=(HACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT,(WPARAM)Plugin,(LPARAM)YAMN_ACCOUNTVERSION)))) - { - for (ActualAccount=FirstAllocatedAccount;ActualAccount != NULL;ActualAccount=Temp) - { - Temp=ActualAccount->Next; - delete ActualAccount; - } - delete[] MemFile; - if (Plugin->FirstAccount==FirstAllocatedAccount) - Plugin->FirstAccount=NULL; -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write done\n"); -#endif - SWMRGDoneWriting(Plugin->AccountBrowserSO); - return EACC_ALLOC; - } - }while(Stat != EACC_ENDOFFILE); - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write done\n"); -#endif - SWMRGDoneWriting(Plugin->AccountBrowserSO); - delete[] MemFile; - - return 0; -} - -// Add accounts from file to memory -INT_PTR AddAccountsFromFileSvc(WPARAM wParam,LPARAM lParam) -{ - char *MemFile,*End; - DWORD Stat = FileToMemory(( TCHAR* )lParam, &MemFile, &End); - if ( Stat != NO_ERROR ) - return (INT_PTR)Stat; - - return PerformAccountReading((HYAMNPROTOPLUGIN)wParam,MemFile,End); -} - -DWORD WriteStringToFile(HANDLE File,char *Source) -{ - DWORD Length,WrittenBytes; - char null = 0; - - if ((Source==NULL) || !(Length=(DWORD)strlen(Source))) { - if (!WriteFile(File,&null,1,&WrittenBytes,NULL)) { - CloseHandle(File); - return EACC_SYSTEM; - } - } - else if (!WriteFile(File,Source,(Length+1),&WrittenBytes,NULL)) { - CloseHandle(File); - return EACC_SYSTEM; - } - return 0; -} - -DWORD WriteStringToFileW(HANDLE File,WCHAR *Source) -{ - DWORD Length,WrittenBytes; - WCHAR null=(WCHAR)0; - - if ((Source==NULL) || !(Length=(DWORD)wcslen(Source))) - { - if (!WriteFile(File,&null,sizeof(WCHAR),&WrittenBytes,NULL)) - { - CloseHandle(File); - return EACC_SYSTEM; - } - } - else if (!WriteFile(File,Source,(Length+1)*sizeof(WCHAR),&WrittenBytes,NULL)) - return EACC_SYSTEM; - return 0; -} - -DWORD WriteMessagesToFile(HANDLE File,HACCOUNT Which) -{ - DWORD WrittenBytes,Stat; - HYAMNMAIL ActualMail=(HYAMNMAIL)Which->Mails; - struct CMimeItem *items; - - while(ActualMail != NULL) - { - if (Stat=WriteStringToFile(File,ActualMail->ID)) - return Stat; - if (!WriteFile(File,(char *)&ActualMail->MailData->Size,sizeof(ActualMail->MailData->Size),&WrittenBytes,NULL) || - !WriteFile(File,(char *)&ActualMail->Flags,sizeof(ActualMail->Flags),&WrittenBytes,NULL) || - !WriteFile(File,(char *)&ActualMail->Number,sizeof(ActualMail->Number),&WrittenBytes,NULL)) - return EACC_SYSTEM; - if ((NULL != Which->Plugin->MailFcn) && (NULL != Which->Plugin->MailFcn->WriteMailOptsFcnPtr)) - Which->Plugin->MailFcn->WriteMailOptsFcnPtr(File,ActualMail); //write plugin mail options to file - for (items=ActualMail->MailData->TranslatedHeader;items != NULL;items=items->Next) - { - if (Stat=WriteStringToFile(File,items->name)) - return Stat; - if (Stat=WriteStringToFile(File,items->value)) - return Stat; - } - if (Stat=WriteStringToFile(File,"")) - return Stat; - ActualMail=ActualMail->Next; - } - if (Stat=WriteStringToFile(File,"")) - return Stat; - return 0; -} - -static INT_PTR PerformAccountWriting(HYAMNPROTOPLUGIN Plugin,HANDLE File) -{ - DWORD WrittenBytes,Stat; - HACCOUNT ActualAccount; - DWORD Ver=YAMN_ACCOUNTFILEVERSION; - BOOL Writed=FALSE; - DWORD ReturnValue=0,EnterCode; - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:AccountBrowserSO-read wait\n"); -#endif - SWMRGWaitToRead(Plugin->AccountBrowserSO,INFINITE); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:AccountBrowserSO-read enter\n"); -#endif - try - { - for (ActualAccount=Plugin->FirstAccount;ActualAccount != NULL;ActualAccount=ActualAccount->Next) - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read wait\n"); -#endif - EnterCode=WaitToReadFcn(ActualAccount->AccountAccessSO); - if (EnterCode==WAIT_FINISH) //account is about to delete - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read wait failed\n"); -#endif - ActualAccount=ActualAccount->Next; - continue; - } - if (EnterCode==WAIT_FAILED) //account is deleted - break; -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read enter\n"); -#endif - if ((ActualAccount->Name==NULL) || (*ActualAccount->Name==(TCHAR)0)) - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read done\n"); -#endif - ReadDoneFcn(ActualAccount->AccountAccessSO); - continue; - } - - if (!Writed && !WriteFile(File,&Ver,sizeof(Ver),&WrittenBytes,NULL)) - throw (DWORD)EACC_SYSTEM; - Writed=TRUE; - - if (Stat=WriteStringToFile(File,ActualAccount->Name)) - throw (DWORD)Stat; - - if (Stat=WriteStringToFile(File,ActualAccount->Server->Name)) - throw (DWORD)Stat; - - if (!WriteFile(File,(char *)&ActualAccount->Server->Port,2,&WrittenBytes,NULL)) - throw (DWORD)EACC_SYSTEM; - - if ((Stat=WriteStringToFile(File,ActualAccount->Server->Login))) - throw (DWORD)Stat; - - CodeDecodeString(ActualAccount->Server->Passwd,TRUE); - - if (Stat=WriteStringToFile(File,ActualAccount->Server->Passwd)) - { - CodeDecodeString(ActualAccount->Server->Passwd,FALSE); - throw (DWORD)Stat; - } - CodeDecodeString(ActualAccount->Server->Passwd,FALSE); - - if ((!WriteFile(File,(char *)&ActualAccount->Flags,sizeof(DWORD),&WrittenBytes,NULL) || - (!WriteFile(File,(char *)&ActualAccount->StatusFlags,sizeof(DWORD),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->PluginFlags,sizeof(DWORD),&WrittenBytes,NULL)))) - throw (DWORD)EACC_SYSTEM; - - if (!WriteFile(File,(char *)&ActualAccount->Interval,sizeof(WORD),&WrittenBytes,NULL)) - throw (DWORD)EACC_SYSTEM; - - if ((!WriteFile(File,(char *)&ActualAccount->NewMailN.Flags,sizeof(DWORD),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->NewMailN.PopupB,sizeof(COLORREF),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->NewMailN.PopupT,sizeof(COLORREF),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->NewMailN.PopupTime,sizeof(DWORD),&WrittenBytes,NULL))) - throw (DWORD)EACC_SYSTEM; - - if ((Stat=WriteStringToFileW(File,ActualAccount->NewMailN.App)) || - (Stat=WriteStringToFileW(File,ActualAccount->NewMailN.AppParam))) - throw (DWORD)Stat; - - if ((!WriteFile(File,(char *)&ActualAccount->NoNewMailN.Flags,sizeof(DWORD),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->NoNewMailN.PopupB,sizeof(COLORREF),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->NoNewMailN.PopupT,sizeof(COLORREF),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->NoNewMailN.PopupTime,sizeof(DWORD),&WrittenBytes,NULL))) - throw (DWORD)EACC_SYSTEM; - - if ((Stat=WriteStringToFileW(File,ActualAccount->NoNewMailN.App)) || - (Stat=WriteStringToFileW(File,ActualAccount->NoNewMailN.AppParam))) - throw (DWORD)Stat; - - if ((!WriteFile(File,(char *)&ActualAccount->BadConnectN.Flags,sizeof(DWORD),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->BadConnectN.PopupB,sizeof(COLORREF),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->BadConnectN.PopupT,sizeof(COLORREF),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->BadConnectN.PopupTime,sizeof(DWORD),&WrittenBytes,NULL))) - throw (DWORD)EACC_SYSTEM; - - if ((Stat=WriteStringToFileW(File,ActualAccount->BadConnectN.App)) || - (Stat=WriteStringToFileW(File,ActualAccount->BadConnectN.AppParam))) - throw (DWORD)Stat; - -//Let plugin write its own values into file - if (ActualAccount->Plugin->Fcn != NULL && ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr != NULL) - if (Stat=ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr(File,ActualAccount)) - throw (DWORD)Stat; -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read wait\n"); -#endif - WaitToReadFcn(ActualAccount->MessagesAccessSO); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read enter\n"); -#endif - if (Stat=WriteMessagesToFile(File,ActualAccount)) - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read done\n"); -#endif - ReadDoneFcn(ActualAccount->MessagesAccessSO); - throw (DWORD)Stat; - } -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read done\n"); -#endif - ReadDoneFcn(ActualAccount->MessagesAccessSO); - - if ((!WriteFile(File,(char *)&ActualAccount->LastChecked,sizeof(SYSTEMTIME),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->LastSChecked,sizeof(SYSTEMTIME),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->LastSynchronised,sizeof(SYSTEMTIME),&WrittenBytes,NULL)) || - (!WriteFile(File,(char *)&ActualAccount->LastMail,sizeof(SYSTEMTIME),&WrittenBytes,NULL))) - throw (DWORD)Stat; - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read done\n"); -#endif - ReadDoneFcn(ActualAccount->AccountAccessSO); - } - } - catch(DWORD ErrorCode) - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read done\n"); -#endif - ReadDoneFcn(ActualAccount->AccountAccessSO); - ReturnValue=ErrorCode; - } -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WriteAccountsToFile:AccountBrowserSO-read done\n"); -#endif - SWMRGDoneReading(Plugin->AccountBrowserSO); - CloseHandle(File); - return 0; -} - -//Writes accounts to file -INT_PTR WriteAccountsToFileSvc(WPARAM wParam,LPARAM lParam) -{ - HYAMNPROTOPLUGIN Plugin = ( HYAMNPROTOPLUGIN )wParam; - TCHAR* tszFileName = ( TCHAR* )lParam; - - EnterCriticalSection( &FileWritingCS ); - HANDLE hFile = CreateFile(tszFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); - if ( hFile == INVALID_HANDLE_VALUE ) { - LeaveCriticalSection(&FileWritingCS); - return EACC_SYSTEM; - } - - INT_PTR rv = PerformAccountWriting(Plugin, hFile); - LeaveCriticalSection(&FileWritingCS); - - return rv; -} - -INT_PTR FindAccountByNameSvc(WPARAM wParam,LPARAM lParam) -{ - HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; - char *SearchedAccount=(char *)lParam; - HACCOUNT Finder; - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"FindAccountByName:AccountBrowserSO-read wait\n"); -#endif - SWMRGWaitToRead(Plugin->AccountBrowserSO,INFINITE); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"FindAccountByName:AccountBrowserSO-read enter\n"); -#endif - for (Finder=Plugin->FirstAccount;Finder != NULL;Finder=Finder->Next) - if ((Finder->Name != NULL) && (0 == strcmp(SearchedAccount,Finder->Name))) - break; -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"FindAccountByName:AccountBrowserSO-read done\n"); -#endif - SWMRGDoneReading(Plugin->AccountBrowserSO); - return (INT_PTR)Finder; -} - -INT_PTR GetNextFreeAccountSvc(WPARAM wParam,LPARAM lParam) -{ - HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; - HACCOUNT Finder; - - if (Plugin->FirstAccount==NULL) - { - Plugin->FirstAccount=(HACCOUNT)CallService(MS_YAMN_CREATEPLUGINACCOUNT,wParam,lParam); - return (INT_PTR)Plugin->FirstAccount; - } - for (Finder=Plugin->FirstAccount;Finder->Next != NULL;Finder=Finder->Next); - Finder->Next=(HACCOUNT)CallService(MS_YAMN_CREATEPLUGINACCOUNT,wParam,lParam); - return (INT_PTR)Finder->Next; -} - -/* -int FindPluginAccount(WPARAM wParam,LPARAM lParam) -{ - HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; - HACCOUNT Finder=(HACCOUNT)lParam; - - if (Finder=NULL) Finder=Plugin->FirstAccount; - -// for (;Finder != NULL && Finder->PluginID != Plugin->PluginInfo->PluginID;Finder=(HACCOUNT)Finder->Next); - return (int)Finder; -} -*/ -INT_PTR DeleteAccountSvc(WPARAM wParam,LPARAM lParam) -{ -//Deleting account works on these steps: -//1. set signal that account should stop activity (set event) -// setting this event we achieve, that any access to account is failed, -// so threads do not start any work with accounts (better saying threads of plugins should not start) -//2. wait to get write access to chained list of accounts -//3. we can write to chained list, so we change chain not to show to actual account -// now, any thread browsing list of accounts does not browse through actual account -// actual account seems to be hidden (it exists, but it is not in accounts chained list (chained list=queue)) -//Now, we should delete account from memory, BUT!!! -// Any thread can still be waked up and start asking account synchronizing object -// If account is deleted, asking about access to read account can throw memory exception (reading for -// a synchronizing object from memory, that was deleted) -//So, we cannot now delete account. We have to wait until we are sure no thread will be using account anymore -// (or to the end of Miranda, but problem is in allocated memory- it is allocated and Miranda is SMALLER, faster, easier, isn't it?) -// This deleting is achieved in 2 ways: -// We have event in UsingThreads synchronization objects. This event signals that no thread will use actual account -// 1. Any thread using account first increment UsingThread, so we know that account is used -// 2. If thread is about to close, it should decrement UsingThread -// 3. If thread creates another thread, that will use account, caller has to wait until the new thread does not -// increment UsingThreads (imagine that caller ends before the new thread set it: if no other thread is using -// account, account is automaticaly (decreasing UsingThreads) signaled as "not used" and we delete it. But then -// new thread is going to read account...). -//4. wait until UsingThread Event is signaled -//5. delete account from memory - - HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; - HACCOUNT Which=(HACCOUNT)lParam; - HACCOUNT Finder; - DWORD tid; - -//1. set stop signal - StopSignalFcn(Which); - WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_STOPACCOUNT,(WPARAM)Which,0); - if (Plugin->Fcn->StopAccountFcnPtr != NULL) - Plugin->Fcn->StopAccountFcnPtr(Which); - -//2. wait to get write access -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write wait\n"); -#endif - SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write enter\n"); -#endif - -//3. remove from queue (chained list) - if (Plugin->FirstAccount==NULL) - { -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write done\n"); -#endif - 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; - } -//leave write access -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write done\n"); -#endif - 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? -// No, of course not. We will create new thread, that will wait and additionally remove our thread in background. -//5. So, the last point (deleting from memory) is performed in new DeleteAccountInBackground thread - - if ((Plugin->Fcn != NULL) && (Plugin->Fcn->WriteAccountsFcnPtr != NULL)) - Plugin->Fcn->WriteAccountsFcnPtr(); - CloseHandle(CreateThread(NULL,0,DeleteAccountInBackground,(LPVOID)Which,0,&tid)); - -//Now, plugin can consider account as deleted, but plugin really can achieve deleting this account from memory when using -//event UsingThreads. - return 1; -} - -DWORD WINAPI DeleteAccountInBackground(LPVOID Value) -{ - HACCOUNT Which=(HACCOUNT)Value; - WaitForSingleObject(Which->UsingThreads->Event,INFINITE); - CallService(MS_YAMN_DELETEPLUGINACCOUNT,(WPARAM)Which,0); - return 0; -} - -int StopAccounts(HYAMNPROTOPLUGIN Plugin) -{ - HACCOUNT Finder; - -//1. wait to get write access -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"StopAccounts:AccountBrowserSO-write wait\n"); -#endif - SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"StopAccounts:AccountBrowserSO-write enter\n"); -#endif - for (Finder=Plugin->FirstAccount;Finder != NULL;Finder=Finder->Next) - { -//2. set stop signal - StopSignalFcn(Finder); - WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_STOPACCOUNT,(WPARAM)Finder,0); - if (Plugin->Fcn->StopAccountFcnPtr != NULL) - Plugin->Fcn->StopAccountFcnPtr(Finder); - } - -//leave write access -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"StopAccounts:AccountBrowserSO-write done\n"); -#endif - SWMRGDoneWriting(Plugin->AccountBrowserSO); - -//Now, account is stopped. It can be removed from memory... - return 1; -} - -int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin,BOOL GetAccountBrowserAccess) -{ - HACCOUNT Finder; - - if (GetAccountBrowserAccess) - { -//1. wait to get write access -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WaitForAllAccounts:AccountBrowserSO-write wait\n"); -#endif - SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WaitForAllAccounts:AccountBrowserSO-write enter\n"); -#endif - } - for (Finder=Plugin->FirstAccount;Finder != NULL;Finder=Finder->Next) - { -//2. wait for signal that account is not in use -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WaitForAllAccounts:waiting for UsingThreadEV %x (account %x)\n",Finder->UsingThreads,Finder); -#endif - WaitForSingleObject(Finder->UsingThreads->Event,INFINITE); - SetEvent(Finder->UsingThreads->Event); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WaitForAllAccounts:UsingThreadEV signaled\n"); -#endif - } - if (GetAccountBrowserAccess) - { -//leave write access -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"WaitForAllAccounts:AccountBrowserSO-write done\n"); -#endif - SWMRGDoneWriting(Plugin->AccountBrowserSO); - } - - return 1; -} - -int DeleteAccounts(HYAMNPROTOPLUGIN Plugin) -{ - HACCOUNT Finder; - - //1. wait to get write access - #ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeleteAccounts:AccountBrowserSO-write wait\n"); - #endif - SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); - #ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeleteAccounts:AccountBrowserSO-write enter\n"); - #endif - - WaitForAllAccounts(Plugin,FALSE); - - for (Finder=Plugin->FirstAccount;Finder != NULL;) - { - HACCOUNT Next = Finder->Next; - DeletePluginAccountSvc((WPARAM)Finder,0); - Finder = Next; - } - - //leave write access - #ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"DeleteAccounts:AccountBrowserSO-write done\n"); - #endif - SWMRGDoneWriting(Plugin->AccountBrowserSO); - - return 1; -} - -void WINAPI GetStatusFcn(HACCOUNT Which,TCHAR *Value) -{ - if (Which==NULL) - return; - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"\tGetStatus:AccountStatusCS-cs wait\n"); -#endif - EnterCriticalSection(&AccountStatusCS); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"\tGetStatus:AccountStatusCS-cs enter\n"); -#endif - lstrcpy(Value,Which->Status); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"\tGetStatus:AccountStatusCS-cs done\n"); -#endif - LeaveCriticalSection(&AccountStatusCS); - return; -} - -void WINAPI SetStatusFcn(HACCOUNT Which,TCHAR *Value) -{ - if (Which==NULL) - return; - -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"\tSetStatus:AccountStatusCS-cs wait\n"); -#endif - EnterCriticalSection(&AccountStatusCS); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"\tSetStatus:AccountStatusCS-cs enter\n"); -#endif - lstrcpy(Which->Status,Value); - WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_CHANGESTATUS,(WPARAM)Which,0); -#ifdef DEBUG_SYNCHRO - DebugLog(SynchroFile,"\tSetStatus:AccountStatusCS-cs done\n"); -#endif - LeaveCriticalSection(&AccountStatusCS); -} - -/* -#ifdef DEBUG_ACCOUNTS -int GetAccounts() -{ - HACCOUNT Finder; - int cnt=0; - - for (Finder=Account;Finder != NULL;Finder=Finder->Next) - cnt++; - return cnt; -} - -void WriteAccounts() -{ - HACCOUNT Finder; - - for (Finder=Account;Finder != NULL;Finder=Finder->Next) - MessageBoxA(NULL,Finder->Name,"Browsing account",MB_OK); -} -#endif -*/ +/* + * This code implements manipulation with accounts + * such as reading accounts from file, writing them to file, + * finding account by name etc. + * + * (c) majvan 2002-2004 + */ + +#include "yamn.h" + +//Account status CS +//When we check some account, thread should change status of account to idle, connecting etc. +//So if we want to read status, we have to successfully write and then read. +CRITICAL_SECTION AccountStatusCS; + +//File Writing CS +//When 2 threads want to write to file... +CRITICAL_SECTION FileWritingCS; + +struct CExportedFunctions AccountExportedFcn[]= +{ + {YAMN_GETSTATUSID,(void *)GetStatusFcn}, + {YAMN_SETSTATUSID,(void *)SetStatusFcn}, +}; + +struct CExportedServices AccountExportedSvc[]= +{ + {MS_YAMN_CREATEPLUGINACCOUNT,CreatePluginAccountSvc}, + {MS_YAMN_DELETEPLUGINACCOUNT,DeletePluginAccountSvc}, + {MS_YAMN_FINDACCOUNTBYNAME,FindAccountByNameSvc}, + {MS_YAMN_GETNEXTFREEACCOUNT,GetNextFreeAccountSvc}, + {MS_YAMN_DELETEACCOUNT,DeletePluginAccountSvc}, + {MS_YAMN_READACCOUNTS,AddAccountsFromFileSvc}, + {MS_YAMN_WRITEACCOUNTS,WriteAccountsToFileSvc}, +}; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +INT_PTR CreatePluginAccountSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; + DWORD AccountVersion=(DWORD)lParam; + HACCOUNT NewAccount; + +//test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match) + if (AccountVersion != YAMN_ACCOUNTVERSION) + return NULL; + + if (Plugin != NULL) + { + if (Plugin->Fcn->NewAccountFcnPtr != NULL) + { +//Let plugin create its own structure, which can be derived from CAccount structure + NewAccount=Plugin->Fcn->NewAccountFcnPtr(Plugin,YAMN_ACCOUNTVERSION); + NewAccount->Plugin=Plugin; + } + else + { +//We suggest plugin uses standard CAccount structure, so we create it + NewAccount=new struct CAccount; + NewAccount->Plugin=Plugin; + } +//If not created successfully + if (NewAccount==NULL) + return NULL; +//Init every members of structure, used by YAMN + InitAccount(NewAccount); + + return (INT_PTR)NewAccount; + } + return NULL; +} + +INT_PTR DeletePluginAccountSvc(WPARAM wParam,LPARAM) +{ + HACCOUNT OldAccount=(HACCOUNT)wParam; + + if (OldAccount->Plugin->Fcn != NULL) + { +//Deinit every members and allocated fields of structure used by YAMN + DeInitAccount(OldAccount); + if (OldAccount->Plugin->Fcn->DeleteAccountFcnPtr != NULL) + { +//Let plugin delete its own CAccount derived structure + OldAccount->Plugin->Fcn->DeleteAccountFcnPtr(OldAccount); + } + else + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeletePluginAccountSvc:delete OldAccount\n"); +#endif + delete OldAccount; //consider account as standard YAMN HACCOUNT and use its own destructor + } + return 1; + } + delete OldAccount; //consider account as standard YAMN HACCOUNT, not initialized before and use its own destructor + return 1; +} + +int InitAccount(HACCOUNT Which) +{ +//initialize synchronizing objects + Which->AccountAccessSO=new SWMRG; + SWMRGInitialize(Which->AccountAccessSO,NULL); + Which->MessagesAccessSO=new SWMRG; + SWMRGInitialize(Which->MessagesAccessSO,NULL); + Which->UsingThreads=new SCOUNTER; + SWMRGInitialize(Which->MessagesAccessSO,NULL); + +//zero memory, where timestamps are stored + ZeroMemory(&Which->LastChecked,sizeof(Which->LastChecked)); + ZeroMemory(&Which->LastSChecked,sizeof(Which->LastSChecked)); + ZeroMemory(&Which->LastSynchronised,sizeof(Which->LastSynchronised)); + ZeroMemory(&Which->LastMail,sizeof(Which->LastMail)); + + Which->Name=NULL; + Which->Mails=NULL; + Which->Interval=0; + Which->Flags=0; + Which->StatusFlags=0; + Which->Next=NULL; + + Which->Server=new struct CServer; + Which->AbleToWork=TRUE; + + return 1; +} + +void DeInitAccount(HACCOUNT Which) +{ +//delete YAMN allocated fields + if (Which->Name != NULL) + delete[] Which->Name; + if (Which->Server != NULL) { + if (Which->Server->Name != NULL) + delete[] Which->Server->Name; + if (Which->Server->Login != NULL) + delete[] Which->Server->Login; + if (Which->Server->Passwd != NULL) + delete[] Which->Server->Passwd; + delete[] Which->Server; + } + + SWMRGDelete(Which->AccountAccessSO); + delete Which->AccountAccessSO; + SWMRGDelete(Which->MessagesAccessSO); + delete Which->MessagesAccessSO; + delete Which->UsingThreads; + DeleteMessagesToEndFcn(Which,(HYAMNMAIL)Which->Mails); +} + +void StopSignalFcn(HACCOUNT Which) +//set event that we are going to delete account +{ +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tStopSignalFcn:stop account: %x\n",Which); +#endif + 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); +} + +void CodeDecodeString(char *Dest,BOOL Encrypt) +{ + TCHAR Code=STARTCODEPSW; + + if (Dest==NULL) + return; + + for (;*Dest != (TCHAR)0;Dest++) + { + if (Encrypt) + *Dest=*Dest+Code; + else + *Dest=*Dest-Code; + Code+=(TCHAR)ADDCODEPSW; + } +} + +static DWORD PostFileToMemory(HANDLE File,char **MemFile,char **End) +{ + DWORD FileSize,ReadBytes; + if (!(FileSize=GetFileSize(File,NULL))) { + CloseHandle(File); + return EACC_FILESIZE; + } + + //allocate space in memory, where we copy the whole file + if (NULL==(*MemFile = new char[FileSize])) + { + CloseHandle(File); + return EACC_ALLOC; + } + + //copy file to memory + if (!ReadFile(File,(LPVOID)*MemFile,FileSize,&ReadBytes,NULL)) + { + CloseHandle(File); + delete[] *MemFile; + return EACC_SYSTEM; + } + CloseHandle(File); + *End = *MemFile + FileSize; + return 0; +} + +DWORD FileToMemory(TCHAR *FileName,char **MemFile,char **End) +{ + HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return EACC_SYSTEM; + + return PostFileToMemory(hFile, MemFile, End); +} + +#if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES) +DWORD ReadStringFromMemory(char **Parser,TCHAR *End,char **StoreTo,TCHAR *DebugString) +{ +//This is the debug version of ReadStringFromMemory function. This version shows MessageBox where +//read string is displayed + TCHAR *Dest,*Finder; + DWORD Size; + TCHAR Debug[65536]; + + Finder=*Parser; + while((*Finder != (TCHAR)0) && (Finder<=End)) Finder++; + mir_sntprintf(Debug, SIZEOF(Debug), _T("%s: %s,length is %d, remaining %d chars"), DebugString, *Parser, Finder-*Parser, End-Finder); + MessageBox(NULL,Debug,_T("debug"),MB_OK); + if (Finder>=End) + return EACC_FILECOMPATIBILITY; + if (Size=Finder-*Parser) + { + if (NULL==(Dest=*StoreTo=new TCHAR[Size+1])) + return EACC_ALLOC; + for (;*Parser<=Finder;(*Parser)++,Dest++) + *Dest=**Parser; + } + else + { + *StoreTo=NULL; + (*Parser)++; + } + return 0; +} +#endif + +DWORD ReadStringFromMemory(char **Parser,char *End,char **StoreTo) +{ + char *Dest,*Finder; + DWORD Size; + + Finder=*Parser; + while((*Finder != (TCHAR)0) && (Finder<=End)) Finder++; + if (Finder>=End) + return EACC_FILECOMPATIBILITY; + if (Size=Finder-*Parser) + { + if (NULL==(Dest=*StoreTo=new char[Size+1])) + return EACC_ALLOC; + for (;*Parser<=Finder;(*Parser)++,Dest++) + *Dest=**Parser; + } + else + { + *StoreTo=NULL; + (*Parser)++; + } + return 0; +} + + #if defined(DEBUG_FILEREAD) || defined(DEBUG_FILEREADMESSAGES) +DWORD ReadStringFromMemoryW(WCHAR **Parser,TCHAR *End,WCHAR **StoreTo,WCHAR *DebugString) +{ +//This is the debug version of ReadStringFromMemoryW function. This version shows MessageBox where +//read string is displayed + WCHAR *Dest,*Finder; + DWORD Size; + WCHAR Debug[65536]; + + Finder=*Parser; + while((*Finder != (WCHAR)0) && (Finder<=(WCHAR *)End)) Finder++; + mir_sntprintf(Debug, SIZEOF(Debug), L"%s: %s,length is %d, remaining %d chars", DebugString, *Parser, Finder-*Parser, (WCHAR *)End-Finder); + MessageBoxW(NULL,Debug,L"debug",MB_OK); + if (Finder>=(WCHAR *)End) + return EACC_FILECOMPATIBILITY; + if (Size=Finder-*Parser) + { + if (NULL==(Dest=*StoreTo=new WCHAR[Size+1])) + return EACC_ALLOC; + for (;*Parser<=Finder;(*Parser)++,Dest++) + *Dest=**Parser; + } + else + { + *StoreTo=NULL; + (*Parser)++; + } + return 0; +} + #endif //if defined(DEBUG...) + +DWORD ReadStringFromMemoryW(WCHAR **Parser,WCHAR *End,WCHAR **StoreTo) +{ + WCHAR *Dest,*Finder; + DWORD Size; + + Finder=*Parser; + while((*Finder != (WCHAR)0) && (Finder<=(WCHAR *)End)) Finder++; + if (Finder>=(WCHAR *)End) + return EACC_FILECOMPATIBILITY; + if (Size=Finder-*Parser) + { + if (NULL==(Dest=*StoreTo=new WCHAR[Size+1])) + return EACC_ALLOC; + for (;*Parser<=Finder;(*Parser)++,Dest++) + *Dest=**Parser; + } + else + { + *StoreTo=NULL; + (*Parser)++; + } + return 0; +} + +static DWORD ReadNotificationFromMemory(char **Parser,char *End,YAMN_NOTIFICATION *Which) +{ + DWORD Stat; +#ifdef DEBUG_FILEREAD + TCHAR Debug[65536]; +#endif + + Which->Flags=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("NFlags: %04x, remaining %d chars"), Which->Flags, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + + Which->PopupB=*(COLORREF *)(*Parser); + (*Parser)+=sizeof(COLORREF); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("PopupB: %04x, remaining %d chars"), Which->PopupB, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + Which->PopupT=*(COLORREF *)(*Parser); + (*Parser)+=sizeof(COLORREF); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("PopupT: %04x, remaining %d chars"), Which->PopupT, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + Which->PopupTime=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("PopupTime: %04x, remaining %d chars"), Which->PopupTime, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + +#ifdef DEBUG_FILEREAD + if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->App,L"App")) +#else + if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->App)) +#endif + return Stat; +#ifdef DEBUG_FILEREAD + if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->AppParam,L"AppParam")) +#else + if (Stat=ReadStringFromMemoryW((WCHAR **)Parser,(WCHAR*)End,&Which->AppParam)) +#endif + return Stat; + return 0; +} + +DWORD ReadMessagesFromMemory(HACCOUNT Which,char **Parser,char *End) +{ + char *Finder; + DWORD Size,Stat; + HYAMNMAIL ActualMail=NULL; + struct CMimeItem *items; + char *ReadString; + +#ifdef DEBUG_FILEREAD + MessageBox(NULL,_T("going to read messages, if any..."),_T("debug"),MB_OK); +#endif + do + { + Finder=*Parser; + while((*Finder != (TCHAR)0) && (Finder<=End)) Finder++; + if (Finder>=End) + return EACC_FILECOMPATIBILITY; + if (Size=Finder-*Parser) + { + if (Which->Mails==NULL) //First message in queue + { + if (NULL==(Which->Mails=ActualMail=CreateAccountMail(Which))) + return EACC_ALLOC; + } + else + { + if (NULL==(ActualMail->Next=CreateAccountMail(Which))) { + return EACC_ALLOC; + } + ActualMail=ActualMail->Next; + } + items=NULL; +#ifdef DEBUG_FILEREADMESSAGES + if (Stat=ReadStringFromMemory(Parser,End,&ActualMail->ID,_T("ID"))) +#else + if (Stat=ReadStringFromMemory(Parser,End,&ActualMail->ID)) +#endif + return Stat; +// ActualMail->MailData=new MAILDATA; !!! mem leake !!! this is alloc by CreateAccountMail, no need for doubble alloc !!!! + + ActualMail->MailData->Size=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; + ActualMail->Flags=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; + ActualMail->Number=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; + + if ((NULL != Which->Plugin->MailFcn) && (NULL != Which->Plugin->MailFcn->ReadMailOptsFcnPtr)) + Which->Plugin->MailFcn->ReadMailOptsFcnPtr(ActualMail,Parser,End); //read plugin mail settings from file + + do + { +#if defined(DEBUG_FILEREADMESSAGES) || defined(DEBUG_FILEREAD) + if (Stat=ReadStringFromMemory(Parser,End,&ReadString,_T("Name"))) +#else + if (Stat=ReadStringFromMemory(Parser,End,&ReadString)) +#endif + return Stat; + if (ReadString==NULL) + break; + +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%s",ReadString); +#endif + + if (items==NULL) + items=ActualMail->MailData->TranslatedHeader=new struct CMimeItem; + else + { + items->Next=new struct CMimeItem; + items=items->Next; + } + if (items==NULL) + return EACC_ALLOC; + items->name=ReadString; + +#ifdef DEBUG_FILEREADMESSAGES + if (Stat=ReadStringFromMemory(Parser,End,&ReadString,_T("Value"))) +#else + if (Stat=ReadStringFromMemory(Parser,End,&ReadString)) +#endif + return Stat; + items->value=ReadString; +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%s\n",ReadString); +#endif + }while(1); + } + else + break; //no next messages, new account! + + }while(1); + (*Parser)++; + return 0; +} + +DWORD ReadAccountFromMemory(HACCOUNT Which,char **Parser,char *End) +{ + DWORD Stat; +#ifdef DEBUG_FILEREAD + TCHAR Debug[65536]; +#endif + //Read name of account + +#ifdef DEBUG_FILEREAD + if (Stat=ReadStringFromMemory(Parser,End,&Which->Name,_T("Name"))) +#else + if (Stat=ReadStringFromMemory(Parser,End,&Which->Name)) +#endif + return Stat; + if (Which->Name==NULL) + return EACC_FILECOMPATIBILITY; + + //Read server parameters +#ifdef DEBUG_FILEREAD + if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Name,_T("Server"))) +#else + if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Name)) +#endif + return Stat; + Which->Server->Port=*(WORD *)(*Parser); + (*Parser)+=sizeof(WORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("Port: %d, remaining %d chars"), Which->Server->Port, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif +#ifdef DEBUG_FILEREAD + if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Login,_T("Login"))) +#else + if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Login)) +#endif + return Stat; +#ifdef DEBUG_FILEREAD + if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Passwd,_T("Password"))) +#else + if (Stat=ReadStringFromMemory(Parser,End,&Which->Server->Passwd)) +#endif + return Stat; + CodeDecodeString(Which->Server->Passwd,FALSE); + + //Read account flags + Which->Flags=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("Flags: %04x, remaining %d chars"), Which->Flags, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + Which->StatusFlags=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("STFlags: %04x, remaining %d chars"), Which->StatusFlags, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + Which->PluginFlags=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD); +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("PFlags: %04x, remaining %d chars"), Which->PluginFlags, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + + //Read account miscellaneous parameters + Which->Interval=*(WORD *)(*Parser); + Which->TimeLeft=Which->Interval; //check on loading + (*Parser)+=sizeof(WORD); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("Interval: %d, remaining %d chars"), Which->Interval, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + + //Read notification parameters + if (Stat=ReadNotificationFromMemory(Parser,End,&Which->NewMailN)) + return Stat; + if (Stat=ReadNotificationFromMemory(Parser,End,&Which->NoNewMailN)) + return Stat; + if (Stat=ReadNotificationFromMemory(Parser,End,&Which->BadConnectN)) + return Stat; + + //Let plugin read its own data stored in file + if (Which->Plugin->Fcn != NULL && Which->Plugin->Fcn->ReadPluginOptsFcnPtr != NULL) + if (Stat=Which->Plugin->Fcn->ReadPluginOptsFcnPtr(Which,Parser,End)) + return Stat; + //Read mails +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write wait\n"); +#endif + WaitToWriteFcn(Which->MessagesAccessSO); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write enter\n"); +#endif + if (Stat=ReadMessagesFromMemory(Which,Parser,End)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write done\n"); +#endif + WriteDoneFcn(Which->MessagesAccessSO); + return Stat; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ReadAccountFromMemory:ActualAccountMsgsSO-write done\n"); +#endif + WriteDoneFcn(Which->MessagesAccessSO); + + //Read timestamps + Which->LastChecked=*(SYSTEMTIME *)(*Parser); + (*Parser)+=sizeof(SYSTEMTIME); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("LastChecked: %04x, remaining %d chars"), Which->LastChecked, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + Which->LastSChecked=*(SYSTEMTIME *)(*Parser); + (*Parser)+=sizeof(SYSTEMTIME); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("LastSChecked: %04x, remaining %d chars"), Which->LastSChecked, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + Which->LastSynchronised=*(SYSTEMTIME *)(*Parser); + (*Parser)+=sizeof(SYSTEMTIME); + if (*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("LastSynchronised: %04x, remaining %d chars"), Which->LastSynchronised, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + Which->LastMail=*(SYSTEMTIME *)(*Parser); + (*Parser)+=sizeof(SYSTEMTIME); + if (*Parser>End) //WARNING! There's only > at the end of testing + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + mir_sntprintf(Debug, SIZEOF(Debug), _T("LastMail: %04x, remaining %d chars"), Which->LastMail, End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + if (*Parser==End) + return EACC_ENDOFFILE; + return 0; + +} + +static INT_PTR PerformAccountReading(HYAMNPROTOPLUGIN Plugin,char *MemFile,char *End) +{ + //Retrieve info for account from memory + char *Parser; + DWORD Ver,Stat; + + HACCOUNT ActualAccount,FirstAllocatedAccount; + + Ver=*(DWORD *)MemFile; + if (Ver>YAMN_ACCOUNTFILEVERSION) + { + delete[] MemFile; + return EACC_FILEVERSION; + } + Parser=MemFile+sizeof(Ver); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write wait\n"); +#endif + SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write enter\n"); +#endif + if (NULL==(ActualAccount=(HACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT,(WPARAM)Plugin,(LPARAM)YAMN_ACCOUNTVERSION))) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write done\n"); +#endif + SWMRGDoneWriting(Plugin->AccountBrowserSO); + delete[] MemFile; + return EACC_ALLOC; + } + FirstAllocatedAccount=ActualAccount; + + do + { + HACCOUNT Temp; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write wait\n"); +#endif + WaitToWriteFcn(ActualAccount->AccountAccessSO); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write enter\n"); +#endif + Stat=ReadAccountFromMemory(ActualAccount,&Parser,End); + + if (ActualAccount->StatusFlags & (YAMN_ACC_STARTA | YAMN_ACC_STARTS)) + ActualAccount->TimeLeft=1; //check on loading + + if (Stat && (Stat != EACC_ENDOFFILE)) + { + for (ActualAccount=FirstAllocatedAccount;ActualAccount != NULL;ActualAccount=Temp) + { + Temp=ActualAccount->Next; + delete ActualAccount; + } + delete[] MemFile; + if (Plugin->FirstAccount==FirstAllocatedAccount) + Plugin->FirstAccount=NULL; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write done\n"); +#endif + SWMRGDoneWriting(Plugin->AccountBrowserSO); + return (INT_PTR)Stat; + } + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:ActualAccountSO-write done\n"); +#endif + WriteDoneFcn(ActualAccount->AccountAccessSO); + + if ((Stat != EACC_ENDOFFILE) && (NULL==(ActualAccount=(HACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT,(WPARAM)Plugin,(LPARAM)YAMN_ACCOUNTVERSION)))) + { + for (ActualAccount=FirstAllocatedAccount;ActualAccount != NULL;ActualAccount=Temp) + { + Temp=ActualAccount->Next; + delete ActualAccount; + } + delete[] MemFile; + if (Plugin->FirstAccount==FirstAllocatedAccount) + Plugin->FirstAccount=NULL; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write done\n"); +#endif + SWMRGDoneWriting(Plugin->AccountBrowserSO); + return EACC_ALLOC; + } + }while(Stat != EACC_ENDOFFILE); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AddAccountsFromFile:AccountBrowserSO-write done\n"); +#endif + SWMRGDoneWriting(Plugin->AccountBrowserSO); + delete[] MemFile; + + return 0; +} + +// Add accounts from file to memory +INT_PTR AddAccountsFromFileSvc(WPARAM wParam,LPARAM lParam) +{ + char *MemFile,*End; + DWORD Stat = FileToMemory(( TCHAR* )lParam, &MemFile, &End); + if ( Stat != NO_ERROR ) + return (INT_PTR)Stat; + + return PerformAccountReading((HYAMNPROTOPLUGIN)wParam,MemFile,End); +} + +DWORD WriteStringToFile(HANDLE File,char *Source) +{ + DWORD Length,WrittenBytes; + char null = 0; + + if ((Source==NULL) || !(Length=(DWORD)strlen(Source))) { + if (!WriteFile(File,&null,1,&WrittenBytes,NULL)) { + CloseHandle(File); + return EACC_SYSTEM; + } + } + else if (!WriteFile(File,Source,(Length+1),&WrittenBytes,NULL)) { + CloseHandle(File); + return EACC_SYSTEM; + } + return 0; +} + +DWORD WriteStringToFileW(HANDLE File,WCHAR *Source) +{ + DWORD Length,WrittenBytes; + WCHAR null=(WCHAR)0; + + if ((Source==NULL) || !(Length=(DWORD)wcslen(Source))) + { + if (!WriteFile(File,&null,sizeof(WCHAR),&WrittenBytes,NULL)) + { + CloseHandle(File); + return EACC_SYSTEM; + } + } + else if (!WriteFile(File,Source,(Length+1)*sizeof(WCHAR),&WrittenBytes,NULL)) + return EACC_SYSTEM; + return 0; +} + +DWORD WriteMessagesToFile(HANDLE File,HACCOUNT Which) +{ + DWORD WrittenBytes,Stat; + HYAMNMAIL ActualMail=(HYAMNMAIL)Which->Mails; + struct CMimeItem *items; + + while(ActualMail != NULL) + { + if (Stat=WriteStringToFile(File,ActualMail->ID)) + return Stat; + if (!WriteFile(File,(char *)&ActualMail->MailData->Size,sizeof(ActualMail->MailData->Size),&WrittenBytes,NULL) || + !WriteFile(File,(char *)&ActualMail->Flags,sizeof(ActualMail->Flags),&WrittenBytes,NULL) || + !WriteFile(File,(char *)&ActualMail->Number,sizeof(ActualMail->Number),&WrittenBytes,NULL)) + return EACC_SYSTEM; + if ((NULL != Which->Plugin->MailFcn) && (NULL != Which->Plugin->MailFcn->WriteMailOptsFcnPtr)) + Which->Plugin->MailFcn->WriteMailOptsFcnPtr(File,ActualMail); //write plugin mail options to file + for (items=ActualMail->MailData->TranslatedHeader;items != NULL;items=items->Next) + { + if (Stat=WriteStringToFile(File,items->name)) + return Stat; + if (Stat=WriteStringToFile(File,items->value)) + return Stat; + } + if (Stat=WriteStringToFile(File,"")) + return Stat; + ActualMail=ActualMail->Next; + } + if (Stat=WriteStringToFile(File,"")) + return Stat; + return 0; +} + +static INT_PTR PerformAccountWriting(HYAMNPROTOPLUGIN Plugin,HANDLE File) +{ + DWORD WrittenBytes,Stat; + HACCOUNT ActualAccount; + DWORD Ver=YAMN_ACCOUNTFILEVERSION; + BOOL Writed=FALSE; + DWORD ReturnValue=0,EnterCode; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:AccountBrowserSO-read wait\n"); +#endif + SWMRGWaitToRead(Plugin->AccountBrowserSO,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:AccountBrowserSO-read enter\n"); +#endif + try + { + for (ActualAccount=Plugin->FirstAccount;ActualAccount != NULL;ActualAccount=ActualAccount->Next) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read wait\n"); +#endif + EnterCode=WaitToReadFcn(ActualAccount->AccountAccessSO); + if (EnterCode==WAIT_FINISH) //account is about to delete + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read wait failed\n"); +#endif + ActualAccount=ActualAccount->Next; + continue; + } + if (EnterCode==WAIT_FAILED) //account is deleted + break; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read enter\n"); +#endif + if ((ActualAccount->Name==NULL) || (*ActualAccount->Name==(TCHAR)0)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + continue; + } + + if (!Writed && !WriteFile(File,&Ver,sizeof(Ver),&WrittenBytes,NULL)) + throw (DWORD)EACC_SYSTEM; + Writed=TRUE; + + if (Stat=WriteStringToFile(File,ActualAccount->Name)) + throw (DWORD)Stat; + + if (Stat=WriteStringToFile(File,ActualAccount->Server->Name)) + throw (DWORD)Stat; + + if (!WriteFile(File,(char *)&ActualAccount->Server->Port,2,&WrittenBytes,NULL)) + throw (DWORD)EACC_SYSTEM; + + if ((Stat=WriteStringToFile(File,ActualAccount->Server->Login))) + throw (DWORD)Stat; + + CodeDecodeString(ActualAccount->Server->Passwd,TRUE); + + if (Stat=WriteStringToFile(File,ActualAccount->Server->Passwd)) + { + CodeDecodeString(ActualAccount->Server->Passwd,FALSE); + throw (DWORD)Stat; + } + CodeDecodeString(ActualAccount->Server->Passwd,FALSE); + + if ((!WriteFile(File,(char *)&ActualAccount->Flags,sizeof(DWORD),&WrittenBytes,NULL) || + (!WriteFile(File,(char *)&ActualAccount->StatusFlags,sizeof(DWORD),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->PluginFlags,sizeof(DWORD),&WrittenBytes,NULL)))) + throw (DWORD)EACC_SYSTEM; + + if (!WriteFile(File,(char *)&ActualAccount->Interval,sizeof(WORD),&WrittenBytes,NULL)) + throw (DWORD)EACC_SYSTEM; + + if ((!WriteFile(File,(char *)&ActualAccount->NewMailN.Flags,sizeof(DWORD),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->NewMailN.PopupB,sizeof(COLORREF),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->NewMailN.PopupT,sizeof(COLORREF),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->NewMailN.PopupTime,sizeof(DWORD),&WrittenBytes,NULL))) + throw (DWORD)EACC_SYSTEM; + + if ((Stat=WriteStringToFileW(File,ActualAccount->NewMailN.App)) || + (Stat=WriteStringToFileW(File,ActualAccount->NewMailN.AppParam))) + throw (DWORD)Stat; + + if ((!WriteFile(File,(char *)&ActualAccount->NoNewMailN.Flags,sizeof(DWORD),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->NoNewMailN.PopupB,sizeof(COLORREF),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->NoNewMailN.PopupT,sizeof(COLORREF),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->NoNewMailN.PopupTime,sizeof(DWORD),&WrittenBytes,NULL))) + throw (DWORD)EACC_SYSTEM; + + if ((Stat=WriteStringToFileW(File,ActualAccount->NoNewMailN.App)) || + (Stat=WriteStringToFileW(File,ActualAccount->NoNewMailN.AppParam))) + throw (DWORD)Stat; + + if ((!WriteFile(File,(char *)&ActualAccount->BadConnectN.Flags,sizeof(DWORD),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->BadConnectN.PopupB,sizeof(COLORREF),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->BadConnectN.PopupT,sizeof(COLORREF),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->BadConnectN.PopupTime,sizeof(DWORD),&WrittenBytes,NULL))) + throw (DWORD)EACC_SYSTEM; + + if ((Stat=WriteStringToFileW(File,ActualAccount->BadConnectN.App)) || + (Stat=WriteStringToFileW(File,ActualAccount->BadConnectN.AppParam))) + throw (DWORD)Stat; + +//Let plugin write its own values into file + if (ActualAccount->Plugin->Fcn != NULL && ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr != NULL) + if (Stat=ActualAccount->Plugin->Fcn->WritePluginOptsFcnPtr(File,ActualAccount)) + throw (DWORD)Stat; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read wait\n"); +#endif + WaitToReadFcn(ActualAccount->MessagesAccessSO); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read enter\n"); +#endif + if (Stat=WriteMessagesToFile(File,ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->MessagesAccessSO); + throw (DWORD)Stat; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountMsgsSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->MessagesAccessSO); + + if ((!WriteFile(File,(char *)&ActualAccount->LastChecked,sizeof(SYSTEMTIME),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->LastSChecked,sizeof(SYSTEMTIME),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->LastSynchronised,sizeof(SYSTEMTIME),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&ActualAccount->LastMail,sizeof(SYSTEMTIME),&WrittenBytes,NULL))) + throw (DWORD)Stat; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + } + catch(DWORD ErrorCode) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + ReturnValue=ErrorCode; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WriteAccountsToFile:AccountBrowserSO-read done\n"); +#endif + SWMRGDoneReading(Plugin->AccountBrowserSO); + CloseHandle(File); + return 0; +} + +//Writes accounts to file +INT_PTR WriteAccountsToFileSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNPROTOPLUGIN Plugin = ( HYAMNPROTOPLUGIN )wParam; + TCHAR* tszFileName = ( TCHAR* )lParam; + + EnterCriticalSection( &FileWritingCS ); + HANDLE hFile = CreateFile(tszFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + if ( hFile == INVALID_HANDLE_VALUE ) { + LeaveCriticalSection(&FileWritingCS); + return EACC_SYSTEM; + } + + INT_PTR rv = PerformAccountWriting(Plugin, hFile); + LeaveCriticalSection(&FileWritingCS); + + return rv; +} + +INT_PTR FindAccountByNameSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; + char *SearchedAccount=(char *)lParam; + HACCOUNT Finder; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"FindAccountByName:AccountBrowserSO-read wait\n"); +#endif + SWMRGWaitToRead(Plugin->AccountBrowserSO,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"FindAccountByName:AccountBrowserSO-read enter\n"); +#endif + for (Finder=Plugin->FirstAccount;Finder != NULL;Finder=Finder->Next) + if ((Finder->Name != NULL) && (0 == strcmp(SearchedAccount,Finder->Name))) + break; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"FindAccountByName:AccountBrowserSO-read done\n"); +#endif + SWMRGDoneReading(Plugin->AccountBrowserSO); + return (INT_PTR)Finder; +} + +INT_PTR GetNextFreeAccountSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; + HACCOUNT Finder; + + if (Plugin->FirstAccount==NULL) + { + Plugin->FirstAccount=(HACCOUNT)CallService(MS_YAMN_CREATEPLUGINACCOUNT,wParam,lParam); + return (INT_PTR)Plugin->FirstAccount; + } + for (Finder=Plugin->FirstAccount;Finder->Next != NULL;Finder=Finder->Next); + Finder->Next=(HACCOUNT)CallService(MS_YAMN_CREATEPLUGINACCOUNT,wParam,lParam); + return (INT_PTR)Finder->Next; +} + +/* +int FindPluginAccount(WPARAM wParam,LPARAM lParam) +{ + HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; + HACCOUNT Finder=(HACCOUNT)lParam; + + if (Finder=NULL) Finder=Plugin->FirstAccount; + +// for (;Finder != NULL && Finder->PluginID != Plugin->PluginInfo->PluginID;Finder=(HACCOUNT)Finder->Next); + return (int)Finder; +} +*/ +INT_PTR DeleteAccountSvc(WPARAM wParam,LPARAM lParam) +{ +//Deleting account works on these steps: +//1. set signal that account should stop activity (set event) +// setting this event we achieve, that any access to account is failed, +// so threads do not start any work with accounts (better saying threads of plugins should not start) +//2. wait to get write access to chained list of accounts +//3. we can write to chained list, so we change chain not to show to actual account +// now, any thread browsing list of accounts does not browse through actual account +// actual account seems to be hidden (it exists, but it is not in accounts chained list (chained list=queue)) +//Now, we should delete account from memory, BUT!!! +// Any thread can still be waked up and start asking account synchronizing object +// If account is deleted, asking about access to read account can throw memory exception (reading for +// a synchronizing object from memory, that was deleted) +//So, we cannot now delete account. We have to wait until we are sure no thread will be using account anymore +// (or to the end of Miranda, but problem is in allocated memory- it is allocated and Miranda is SMALLER, faster, easier, isn't it?) +// This deleting is achieved in 2 ways: +// We have event in UsingThreads synchronization objects. This event signals that no thread will use actual account +// 1. Any thread using account first increment UsingThread, so we know that account is used +// 2. If thread is about to close, it should decrement UsingThread +// 3. If thread creates another thread, that will use account, caller has to wait until the new thread does not +// increment UsingThreads (imagine that caller ends before the new thread set it: if no other thread is using +// account, account is automaticaly (decreasing UsingThreads) signaled as "not used" and we delete it. But then +// new thread is going to read account...). +//4. wait until UsingThread Event is signaled +//5. delete account from memory + + HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; + HACCOUNT Which=(HACCOUNT)lParam; + HACCOUNT Finder; + DWORD tid; + +//1. set stop signal + StopSignalFcn(Which); + WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_STOPACCOUNT,(WPARAM)Which,0); + if (Plugin->Fcn->StopAccountFcnPtr != NULL) + Plugin->Fcn->StopAccountFcnPtr(Which); + +//2. wait to get write access +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write wait\n"); +#endif + SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write enter\n"); +#endif + +//3. remove from queue (chained list) + if (Plugin->FirstAccount==NULL) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write done\n"); +#endif + 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; + } +//leave write access +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteAccount:AccountBrowserSO-write done\n"); +#endif + 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? +// No, of course not. We will create new thread, that will wait and additionally remove our thread in background. +//5. So, the last point (deleting from memory) is performed in new DeleteAccountInBackground thread + + if ((Plugin->Fcn != NULL) && (Plugin->Fcn->WriteAccountsFcnPtr != NULL)) + Plugin->Fcn->WriteAccountsFcnPtr(); + CloseHandle(CreateThread(NULL,0,DeleteAccountInBackground,(LPVOID)Which,0,&tid)); + +//Now, plugin can consider account as deleted, but plugin really can achieve deleting this account from memory when using +//event UsingThreads. + return 1; +} + +DWORD WINAPI DeleteAccountInBackground(LPVOID Value) +{ + HACCOUNT Which=(HACCOUNT)Value; + WaitForSingleObject(Which->UsingThreads->Event,INFINITE); + CallService(MS_YAMN_DELETEPLUGINACCOUNT,(WPARAM)Which,0); + return 0; +} + +int StopAccounts(HYAMNPROTOPLUGIN Plugin) +{ + HACCOUNT Finder; + +//1. wait to get write access +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"StopAccounts:AccountBrowserSO-write wait\n"); +#endif + SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"StopAccounts:AccountBrowserSO-write enter\n"); +#endif + for (Finder=Plugin->FirstAccount;Finder != NULL;Finder=Finder->Next) + { +//2. set stop signal + StopSignalFcn(Finder); + WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_STOPACCOUNT,(WPARAM)Finder,0); + if (Plugin->Fcn->StopAccountFcnPtr != NULL) + Plugin->Fcn->StopAccountFcnPtr(Finder); + } + +//leave write access +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"StopAccounts:AccountBrowserSO-write done\n"); +#endif + SWMRGDoneWriting(Plugin->AccountBrowserSO); + +//Now, account is stopped. It can be removed from memory... + return 1; +} + +int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin,BOOL GetAccountBrowserAccess) +{ + HACCOUNT Finder; + + if (GetAccountBrowserAccess) + { +//1. wait to get write access +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WaitForAllAccounts:AccountBrowserSO-write wait\n"); +#endif + SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WaitForAllAccounts:AccountBrowserSO-write enter\n"); +#endif + } + for (Finder=Plugin->FirstAccount;Finder != NULL;Finder=Finder->Next) + { +//2. wait for signal that account is not in use +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WaitForAllAccounts:waiting for UsingThreadEV %x (account %x)\n",Finder->UsingThreads,Finder); +#endif + WaitForSingleObject(Finder->UsingThreads->Event,INFINITE); + SetEvent(Finder->UsingThreads->Event); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WaitForAllAccounts:UsingThreadEV signaled\n"); +#endif + } + if (GetAccountBrowserAccess) + { +//leave write access +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"WaitForAllAccounts:AccountBrowserSO-write done\n"); +#endif + SWMRGDoneWriting(Plugin->AccountBrowserSO); + } + + return 1; +} + +int DeleteAccounts(HYAMNPROTOPLUGIN Plugin) +{ + HACCOUNT Finder; + + //1. wait to get write access + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteAccounts:AccountBrowserSO-write wait\n"); + #endif + SWMRGWaitToWrite(Plugin->AccountBrowserSO,INFINITE); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteAccounts:AccountBrowserSO-write enter\n"); + #endif + + WaitForAllAccounts(Plugin,FALSE); + + for (Finder=Plugin->FirstAccount;Finder != NULL;) + { + HACCOUNT Next = Finder->Next; + DeletePluginAccountSvc((WPARAM)Finder,0); + Finder = Next; + } + + //leave write access + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteAccounts:AccountBrowserSO-write done\n"); + #endif + SWMRGDoneWriting(Plugin->AccountBrowserSO); + + return 1; +} + +void WINAPI GetStatusFcn(HACCOUNT Which,TCHAR *Value) +{ + if (Which==NULL) + return; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tGetStatus:AccountStatusCS-cs wait\n"); +#endif + EnterCriticalSection(&AccountStatusCS); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tGetStatus:AccountStatusCS-cs enter\n"); +#endif + lstrcpy(Value,Which->Status); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tGetStatus:AccountStatusCS-cs done\n"); +#endif + LeaveCriticalSection(&AccountStatusCS); + return; +} + +void WINAPI SetStatusFcn(HACCOUNT Which,TCHAR *Value) +{ + if (Which==NULL) + return; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tSetStatus:AccountStatusCS-cs wait\n"); +#endif + EnterCriticalSection(&AccountStatusCS); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tSetStatus:AccountStatusCS-cs enter\n"); +#endif + lstrcpy(Which->Status,Value); + WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_CHANGESTATUS,(WPARAM)Which,0); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tSetStatus:AccountStatusCS-cs done\n"); +#endif + LeaveCriticalSection(&AccountStatusCS); +} + +/* +#ifdef DEBUG_ACCOUNTS +int GetAccounts() +{ + HACCOUNT Finder; + int cnt=0; + + for (Finder=Account;Finder != NULL;Finder=Finder->Next) + cnt++; + return cnt; +} + +void WriteAccounts() +{ + HACCOUNT Finder; + + for (Finder=Account;Finder != NULL;Finder=Finder->Next) + MessageBoxA(NULL,Finder->Name,"Browsing account",MB_OK); +} +#endif +*/ -- cgit v1.2.3