diff options
-rw-r--r-- | plugins/YAMN/src/account.cpp | 2601 | ||||
-rw-r--r-- | plugins/YAMN/src/browser/mailbrowser.cpp | 5162 | ||||
-rw-r--r-- | plugins/YAMN/src/main.cpp | 792 |
3 files changed, 4279 insertions, 4276 deletions
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,"<read name>%s</read name>",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,"<read value>%s</read value>\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,"<read name>%s</read name>",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,"<read value>%s</read value>\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 +*/ diff --git a/plugins/YAMN/src/browser/mailbrowser.cpp b/plugins/YAMN/src/browser/mailbrowser.cpp index 0d60cd6e18..cda180d5ac 100644 --- a/plugins/YAMN/src/browser/mailbrowser.cpp +++ b/plugins/YAMN/src/browser/mailbrowser.cpp @@ -1,2580 +1,2582 @@ -/*
- * This code implements window handling (new mail)
- *
- * (c) majvan 2002-2004
- */
-/* There can be problems when compiling this file, because in this file
- * we are using both unicode and no-unicode functions and compiler does not
- * like it in one file
- * When you got errors, try to comment the #define <stdio.h> and compile, then
- * put it back to uncommented and compile again :)
- */
-
-#include "../yamn.h"
-
-#define TIMER_FLASHING 0x09061979
-#define MAILBROWSER_MINXSIZE 200 //min size of mail browser window
-#define MAILBROWSER_MINYSIZE 130
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-char* s_MonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-bool bDate = false,bSub=false,bSize=false,bFrom=false;
-int PosX=0,PosY=0,SizeX=460,SizeY=100;
-int HeadSizeX = 0x2b2, HeadSizeY = 0x0b5, HeadPosX = 100, HeadPosY = 100;
-int HeadSplitPos=250; // per-mils of the size
-static int FromWidth=250,SubjectWidth=280,SizeWidth=50,SizeDate=205;
-unsigned char optDateTime = (SHOWDATELONG | SHOWDATENOTODAY);
-
-struct CMailNumbersSub
-{
- int Total; //any mail
- int New; //uses YAMN_MSG_NEW flag
- int UnSeen; //uses YAMN_MSG_UNSEEN flag
-// int Browser; //uses YAMN_MSG_BROWSER flag
- int BrowserUC; //uses YAMN_MSG_BROWSER flag and YAMN_MSG_UNSEEN flag
- int Display; //uses YAMN_MSG_DISPLAY flag
- int DisplayTC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag
- int DisplayUC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag and YAMN_MSG_UNSEEN flag
- int Popup; //uses YAMN_MSG_POPUP flag
- int PopupTC; //uses YAMN_MSG_POPUPC flag
- int PopupNC; //uses YAMN_MSG_POPUPC flag and YAMN_MSG_NEW flag
- int PopupRun; //uses YAMN_MSG_POPUP flag and YAMN_MSG_NEW flag
- int PopupSL2NC; //uses YAMN_MSG_SPAML2 flag and YAMN_MSG_NEW flag
- int PopupSL3NC; //uses YAMN_MSG_SPAML3 flag and YAMN_MSG_NEW flag
-// int SysTray; //uses YAMN_MSG_SYSTRAY flag
- int SysTrayUC; //uses YAMN_MSG_SYSTRAY flag and YAMN_MSG_UNSEEN flag
-// int Sound; //uses YAMN_MSG_SOUND flag
- int SoundNC; //uses YAMN_MSG_SOUND flag and YAMN_MSG_NEW flag
-// int App; //uses YAMN_MSG_APP flag
- int AppNC; //uses YAMN_MSG_APP flag and YAMN_MSG_NEW flag
- int EventNC; //uses YAMN_MSG_NEVENT flag and YAMN_MSG_NEW flag
-};
-
-struct CMailNumbers
-{
- struct CMailNumbersSub Real;
- struct CMailNumbersSub Virtual;
-};
-
-struct CMailWinUserInfo
-{
- HACCOUNT Account;
- int TrayIconState;
- BOOL UpdateMailsMessagesAccess;
- BOOL Seen;
- BOOL RunFirstTime;
-};
-
-struct CChangeContent
-{
- DWORD nflags;
- DWORD nnflags;
-};
-
-struct CUpdateMails
-{
- struct CChangeContent *Flags;
- BOOL Waiting;
- HANDLE Copied;
-};
-struct CSortList
-{
- HWND hDlg;
- int iSubItem;
-};
-
-//Retrieves HACCOUNT, whose mails are displayed in ListMails
-// hLM- handle of dialog window
-// returns handle of account
-inline HACCOUNT GetWindowAccount(HWND hDialog);
-
-//Looks to mail flags and increment mail counter (e.g. if mail is new, increments the new mail counter
-// msgq- mail, which increments the counters
-// MN- counnters structure
-void IncrementMailCounters(HYAMNMAIL msgq,struct CMailNumbers *MN);
-
-enum
-{
- UPDATE_FAIL=0, //function failed
- UPDATE_NONE, //none update has been performed
- UPDATE_OK, //some changes occured, update performed
-};
-//Just looks for mail changes in account and update the mail browser window
-// hDlg- dialog handle
-// ActualAccount- account handle
-// nflags- flags what to do when new mail arrives
-// nnflags- flags what to do when no new mail arrives
-// returns one of UPDATE_XXX value(not implemented yet)
-int UpdateMails(HWND hDlg,HACCOUNT ActualAccount,DWORD nflags,DWORD nnflags);
-
-//When new mail occurs, shows window, plays sound, runs application...
-// hDlg- dialog handle. Dialog of mailbrowser is already created and actions are performed over this window
-// ActualAccount- handle of account, whose mails are to be notified
-// MN- statistics of mails in account
-// nflags- what to do or not to do (e.g. to show mailbrowser window or prohibit to show)
-// nflags- flags what to do when new mail arrives
-// nnflags- flags what to do when no new mail arrives
-void DoMailActions(HWND hDlg,HACCOUNT ActualAccount,struct CMailNumbers *MN,DWORD nflags,DWORD nnflags);
-
-//Looks for items in mailbrowser and if they were deleted, delete them from browser window
-// hListView- handle of listview window
-// ActualAccount- handle of account, whose mails are show
-// MailNumbers- pointer to structure, in which function stores numbers of mails with some property
-// returns one of UPDATE_XXX value (not implemented yet)
-int ChangeExistingMailStatus(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MN);
-
-//Adds new mails to ListView and if any new, shows multi popup (every new message is new popup window created by popup plugin)
-// hListView- handle of listview window
-// ActualAccount- handle of account, whose mails are show
-// NewMailPopup- pointer to prepared structure for popup plugin, can be NULL if no popup show
-// MailNumbers- pointer to structure, in which function stores numbers of mails with some property
-// nflags- flags what to do when new mail arrives
-// returns one of UPDATE_XXX value (not implemented yet)
-int AddNewMailsToListView(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MailNumbers,DWORD nflags);
-
-//Window callback procedure for popup window (created by popup plugin)
-LRESULT CALLBACK NewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
-
-//Window callback procedure for popup window (created by popup plugin)
-LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
-
-//Dialog callback procedure for mail browser
-INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam);
-
-//MailBrowser thread function creates window if needed, tray icon and plays sound
-DWORD WINAPI MailBrowser(LPVOID Param);
-
-LRESULT CALLBACK ListViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
-//Runs mail browser in new thread
-INT_PTR RunMailBrowserSvc(WPARAM,LPARAM);
-
-#define YAMN_BROWSER_SHOWPOPUP 0x01
-
- // list view items' order criteria
- #define LVORDER_NOORDER -1
- #define LVORDER_STRING 0
- #define LVORDER_NUMERIC 1
- #define LVORDER_DATETIME 2
-
- // list view order direction
- #define LVORDER_ASCENDING 1
- #define LVORDER_NONE 0
- #define LVORDER_DESCENDING -1
-
- // list view sort type
- #define LVSORTPRIORITY_NONE -1
-
- // List view column info.
- typedef struct _SAMPLELISTVIEWCOLUMN
- {
- UINT uCXCol; // index
- int nSortType; // sorting type (STRING = 0, NUMERIC, DATE, DATETIME)
- int nSortOrder; // sorting order (ASCENDING = -1, NONE, DESCENDING)
- int nPriority; // sort priority (-1 for none, 0, 1, ..., nColumns - 1 maximum)
- TCHAR lpszName[128]; // column name
- } SAMPLELISTVIEWCOLUMN;
-
- // Compare priority
- typedef struct _LVCOMPAREINFO
- {
- int iIdx; // Index
- int iPriority; // Priority
- } LVCOMPAREINFO, *LPLVCOMPAREINFO;
-
-//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-LPARAM readItemLParam(HWND hwnd,DWORD iItem)
-{
- LVITEM item;
-
- item.mask = LVIF_PARAM;
- item.iItem = iItem;
- item.iSubItem = 0;
- SendMessage(hwnd,LVM_GETITEM,0,(LPARAM)&item);
- return item.lParam;
-}
-
-inline HACCOUNT GetWindowAccount(HWND hDlg)
-{
- struct CMailWinUserInfo *mwui;
-
- if (NULL==(mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER)))
- return NULL;
- return mwui->Account;
-}
-
-void IncrementMailCounters(HYAMNMAIL msgq,struct CMailNumbers *MN)
-{
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Total++;
- else
- MN->Real.Total++;
-
- if (msgq->Flags & YAMN_MSG_NEW)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.New++;
- else
- MN->Real.New++;
- if (msgq->Flags & YAMN_MSG_UNSEEN)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.UnSeen++;
- else
- MN->Real.UnSeen++;
- if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER)) == (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.BrowserUC++;
- else
- MN->Real.BrowserUC++;
- if (msgq->Flags & YAMN_MSG_DISPLAY)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Display++;
- else
- MN->Real.Display++;
- if ((msgq->Flags & (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.DisplayTC++;
- else
- MN->Real.DisplayTC++;
- if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.DisplayUC++;
- else
- MN->Real.DisplayUC++;
- if (msgq->Flags & YAMN_MSG_POPUP)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Popup++;
- else
- MN->Real.Popup++;
- if ((msgq->Flags & YAMN_MSG_POPUPC) == YAMN_MSG_POPUPC)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupTC++;
- else
- MN->Real.PopupTC++;
- if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUPC)) == (YAMN_MSG_NEW | YAMN_MSG_POPUPC))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupNC++;
- else
- MN->Real.PopupNC++;
- if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUP)) == (YAMN_MSG_NEW | YAMN_MSG_POPUP))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupRun++;
- else
- MN->Real.PopupRun++;
- if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags,YAMN_MSG_SPAML2))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupSL2NC++;
- else
- MN->Real.PopupSL2NC++;
- if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags,YAMN_MSG_SPAML3))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.PopupSL3NC++;
- else
- MN->Real.PopupSL3NC++;
-/* if (msgq->MailData->Flags & YAMN_MSG_SYSTRAY)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.SysTray++;
- else
- MN->Real.SysTray++;
-*/ if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_SYSTRAY)) == (YAMN_MSG_UNSEEN|YAMN_MSG_SYSTRAY))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.SysTrayUC++;
- else
- MN->Real.SysTrayUC++;
-/* if (msgq->MailData->Flags & YAMN_MSG_SOUND)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.Sound++;
- else
- MN->Real.Sound++;
-*/ if ((msgq->Flags & (YAMN_MSG_NEW|YAMN_MSG_SOUND)) == (YAMN_MSG_NEW|YAMN_MSG_SOUND))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.SoundNC++;
- else
- MN->Real.SoundNC++;
-/* if (msgq->MailData->Flags & YAMN_MSG_APP)
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.App++;
- else
- MN->Real.App++;
-*/ if ((msgq->Flags & (YAMN_MSG_NEW|YAMN_MSG_APP)) == (YAMN_MSG_NEW|YAMN_MSG_APP))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.AppNC++;
- else
- MN->Real.AppNC++;
- if ((msgq->Flags & (YAMN_MSG_NEW|YAMN_MSG_NEVENT)) == (YAMN_MSG_NEW|YAMN_MSG_NEVENT))
- if (msgq->Flags & YAMN_MSG_VIRTUAL)
- MN->Virtual.EventNC++;
- else
- MN->Real.EventNC++;
-}
-
-int UpdateMails(HWND hDlg,HACCOUNT ActualAccount,DWORD nflags,DWORD nnflags)
-{
-#define MAILBROWSERTITLE LPGEN("%s - %d new mail messages, %d total")
-
- struct CMailWinUserInfo *mwui;
- struct CMailNumbers MN;
-
- HYAMNMAIL msgq;
- BOOL Loaded;
- BOOL RunMailBrowser,RunPopups;
-
- mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER);
- //now we ensure read access for account and write access for its mails
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read wait\n");
- #endif
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- {
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read wait failed\n");
- #endif
- PostMessage(hDlg,WM_DESTROY,0,0);
-
- return UPDATE_FAIL;
- }
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read enter\n");
- #endif
-
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write wait\n");
- #endif
- if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO))
- {
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write wait failed\n");
- DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read done\n");
- #endif
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- PostMessage(hDlg,WM_DESTROY,0,0);
- return UPDATE_FAIL;
- }
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write enter\n");
- #endif
-
- ZeroMemory(&MN,sizeof(MN));
-
- for (msgq=(HYAMNMAIL)ActualAccount->Mails;msgq != NULL;msgq=msgq->Next)
- {
- if (!LoadedMailData(msgq)) //check if mail is already in memory
- {
- Loaded=false;
- if (NULL==LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it
- continue;
- }
- else
- Loaded=true;
-
- IncrementMailCounters(msgq,&MN);
-
- if (!Loaded)
- UnloadMailData(msgq); //do not keep data for mail in memory
- }
-
- if (mwui != NULL)
- mwui->UpdateMailsMessagesAccess=TRUE;
-
- //Now we are going to check if extracting data from mail headers are needed.
- //If popups will be displayed or mailbrowser window
- if ((((mwui != NULL) && !(mwui->RunFirstTime)) &&
- (
- ((nnflags & YAMN_ACC_MSGP) && !(MN.Real.BrowserUC+MN.Virtual.BrowserUC)) ||
- ((nflags & YAMN_ACC_MSGP) && (MN.Real.BrowserUC+MN.Virtual.BrowserUC))
- )
- ) || //if mail window was displayed before and flag YAMN_ACC_MSGP is set
- ((nnflags & YAMN_ACC_MSG) && !(MN.Real.BrowserUC+MN.Virtual.BrowserUC)) || //if needed to run mailbrowser when no unseen and no unseen mail found
- ((nflags & YAMN_ACC_MSG) && (MN.Real.BrowserUC+MN.Virtual.BrowserUC)) || //if unseen mails found, we sure run mailbrowser
- ((nflags & YAMN_ACC_ICO) && (MN.Real.SysTrayUC+MN.Virtual.SysTrayUC))
- ) //if needed to run systray
- RunMailBrowser=TRUE;
- else RunMailBrowser=FALSE;
-
- if ( (nflags & YAMN_ACC_POP) &&
- (ActualAccount->Flags & YAMN_ACC_POPN) &&
- (MN.Real.PopupNC+MN.Virtual.PopupNC)) //if some popups with mails are needed to show
- RunPopups=TRUE;
- else RunPopups=FALSE;
-
- if (RunMailBrowser)
- ChangeExistingMailStatus(GetDlgItem(hDlg,IDC_LISTMAILS),ActualAccount,&MN);
- if (RunMailBrowser || RunPopups)
- AddNewMailsToListView(hDlg==NULL ? NULL : GetDlgItem(hDlg,IDC_LISTMAILS),ActualAccount,&MN,nflags);
-
- if (RunMailBrowser)
- {
- size_t len = strlen(ActualAccount->Name)+strlen(Translate(MAILBROWSERTITLE))+10; //+10 chars for numbers
- char *TitleStrA=new char[len];
- WCHAR *TitleStrW=new WCHAR[len];
-
- mir_snprintf(TitleStrA, len, Translate(MAILBROWSERTITLE), ActualAccount->Name, MN.Real.DisplayUC + MN.Virtual.DisplayUC, MN.Real.Display + MN.Virtual.Display);
- MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,TitleStrA,-1,TitleStrW,(int)strlen(TitleStrA)+1);
- SendMessageW(hDlg,WM_SETTEXT,0,(LPARAM)TitleStrW);
- delete[] TitleStrA;
- delete[] TitleStrW;
- }
-
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:Do mail actions\n");
- #endif
-
- DoMailActions(hDlg,ActualAccount,&MN,nflags,nnflags);
-
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:Do mail actions done\n");
- #endif
-
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_NEW,0,YAMN_MSG_NEW,YAMN_FLAG_REMOVE); //rempve the new flag
- if (!RunMailBrowser)
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_UNSEEN,YAMN_MSG_STAYUNSEEN,YAMN_MSG_UNSEEN,YAMN_FLAG_REMOVE); //remove the unseen flag when it was not displayed and it has not "stay unseen" flag set
-
- if (mwui != NULL)
- {
- mwui->UpdateMailsMessagesAccess=FALSE;
- mwui->RunFirstTime=FALSE;
- }
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write done\n");
- DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read done\n");
- #endif
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- if (RunMailBrowser)
- UpdateWindow(GetDlgItem(hDlg,IDC_LISTMAILS));
- else if (hDlg != NULL)
- DestroyWindow(hDlg);
-
- return 1;
-}
-
-int ChangeExistingMailStatus(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MN)
-{
- int i,in;
- LVITEMW item;
- HYAMNMAIL mail,msgq;
-
- in=ListView_GetItemCount(hListView);
- item.mask=LVIF_PARAM;
-
- for (i=0;i<in;i++)
- {
- item.iItem=i;
- item.iSubItem=0;
- if (TRUE==ListView_GetItem(hListView,&item))
- mail=(HYAMNMAIL)item.lParam;
- else
- continue;
- for (msgq=(HYAMNMAIL)ActualAccount->Mails;(msgq != NULL)&&(msgq != mail);msgq=msgq->Next); //found the same mail in account queue
- if (msgq==NULL) //if mail was not found
- if (TRUE==ListView_DeleteItem(hListView,i))
- {
- in--;i--;
- continue;
- }
- }
-
- return TRUE;
-}
-
-void MimeDateToLocalizedDateTime(char *datein, WCHAR *dateout, int lendateout);
-int AddNewMailsToListView(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MN,DWORD nflags)
-{
- HYAMNMAIL msgq;
- POPUPDATAT NewMailPopup = {0};
-
- WCHAR *FromStr;
- WCHAR SizeStr[20];
- WCHAR LocalDateStr[128];
-
- LVITEMW item;
- LVFINDINFO fi;
-
- int foundi,lfoundi;
- struct CHeader UnicodeHeader;
- BOOL Loaded,Extracted,FromStrNew=FALSE;
-
- ZeroMemory(&item,sizeof(item));
- ZeroMemory(&UnicodeHeader,sizeof(UnicodeHeader));
-
- if (hListView != NULL)
- {
- item.mask=LVIF_TEXT | LVIF_PARAM;
- item.iItem=0;
- ZeroMemory(&fi,sizeof(fi));
- fi.flags=LVFI_PARAM; //let's go search item by lParam number
- lfoundi=0;
- }
-
- NewMailPopup.lchContact=(ActualAccount->hContact != NULL) ? ActualAccount->hContact : (MCONTACT)ActualAccount;
- NewMailPopup.lchIcon=g_LoadIconEx(2);
- NewMailPopup.colorBack=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupB : GetSysColor(COLOR_BTNFACE);
- NewMailPopup.colorText=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupT : GetSysColor(COLOR_WINDOWTEXT);
- NewMailPopup.iSeconds=ActualAccount->NewMailN.PopupTime;
-
- NewMailPopup.PluginWindowProc=NewMailPopupProc;
- NewMailPopup.PluginData=(void *)0; //it's new mail popup
-
- for (msgq=(HYAMNMAIL)ActualAccount->Mails;msgq != NULL;msgq=msgq->Next,lfoundi++)
- {
-// now we hide mail pointer to item's lParam member. We can later use it to retrieve mail datas
-
- Extracted=FALSE;FromStr=NULL;FromStrNew=FALSE;
-
- if (hListView != NULL)
- {
- fi.lParam=(LPARAM)msgq;
- if (-1 != (foundi=ListView_FindItem(hListView,-1,&fi))) //if mail is already in window
- {
- lfoundi=foundi;
- continue; //do not insert any item
- }
-
- item.iItem=lfoundi; //insert after last found item
- item.lParam=(LPARAM)msgq;
- }
-
- if (!LoadedMailData(msgq)) //check if mail is already in memory
- {
- Loaded=false;
- if (NULL==LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it
- continue;
- }
- else
- Loaded=true;
-
- if (((hListView != NULL) && (msgq->Flags & YAMN_MSG_DISPLAY)) ||
- ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW)))
- {
-
- if (!Extracted) ExtractHeader(msgq->MailData->TranslatedHeader,msgq->MailData->CP,&UnicodeHeader);
- Extracted=TRUE;
-
- if ((UnicodeHeader.From != NULL) && (UnicodeHeader.FromNick != NULL)) {
- size_t size = wcslen(UnicodeHeader.From) + wcslen(UnicodeHeader.FromNick) + 4;
- FromStr = new WCHAR[size];
- mir_sntprintf(FromStr, size, L"%s <%s>", UnicodeHeader.FromNick, UnicodeHeader.From);
- FromStrNew = TRUE;
- }
- else if (UnicodeHeader.From != NULL)
- FromStr=UnicodeHeader.From;
- else if (UnicodeHeader.FromNick != NULL)
- FromStr=UnicodeHeader.FromNick;
- else if (UnicodeHeader.ReturnPath != NULL)
- FromStr=UnicodeHeader.ReturnPath;
-
- if (NULL==FromStr) {
- FromStr = L"";
- FromStrNew = FALSE;
- }
- }
-
- if ((hListView != NULL) && (msgq->Flags & YAMN_MSG_DISPLAY)) {
- item.iSubItem = 0;
- item.pszText = FromStr;
- item.iItem = SendMessageW(hListView,LVM_INSERTITEMW,0,(LPARAM)&item);
-
- item.iSubItem = 1;
- item.pszText = (NULL != UnicodeHeader.Subject ? UnicodeHeader.Subject : (WCHAR*)L"");
- SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item);
-
- item.iSubItem = 2;
- mir_sntprintf(SizeStr, SIZEOF(SizeStr), L"%d kB", msgq->MailData->Size / 1024);
- item.pszText = SizeStr;
- SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item);
-
- item.iSubItem = 3;
- item.pszText = L"";
-
- for (CMimeItem *heads = msgq->MailData->TranslatedHeader; heads != NULL; heads = heads->Next) {
- if ( !_stricmp(heads->name, "Date")) {
- MimeDateToLocalizedDateTime(heads->value, LocalDateStr, 128);
- item.pszText = LocalDateStr;
- break;
- }
- }
- SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item);
- }
-
- if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW)) {
- lstrcpyn(NewMailPopup.lptzContactName, FromStr, SIZEOF(NewMailPopup.lptzContactName));
- lstrcpyn(NewMailPopup.lptzText, UnicodeHeader.Subject, SIZEOF(NewMailPopup.lptzText));
-
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)malloc(sizeof(YAMN_MAILSHOWPARAM));
- if (MailParam) {
- MailParam->account = ActualAccount;
- MailParam->mail = msgq;
- MailParam->ThreadRunningEV = 0;
- NewMailPopup.PluginData = MailParam;
- PUAddPopupT(&NewMailPopup);
- }
- }
-
- if ((msgq->Flags & YAMN_MSG_UNSEEN) && (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN))
- CallService(MS_KBDNOTIFY_EVENTSOPENED,1,NULL);
-
- if (FromStrNew)
- delete[] FromStr;
-
- if (Extracted)
- {
- DeleteHeaderContent(&UnicodeHeader);
- ZeroMemory(&UnicodeHeader,sizeof(UnicodeHeader));
- }
-
- if (!Loaded)
- {
- SaveMailData(msgq);
- UnloadMailData(msgq); //do not keep data for mail in memory
- }
- }
-
- return TRUE;
-}
-
-void DoMailActions(HWND hDlg,HACCOUNT ActualAccount,struct CMailNumbers *MN,DWORD nflags,DWORD nnflags)
-{
- char *NotIconText = Translate("- new mail message(s)");
- NOTIFYICONDATA nid;
-
- ZeroMemory(&nid,sizeof(nid));
-
- if (MN->Real.EventNC+MN->Virtual.EventNC)
- NotifyEventHooks(hNewMailHook,0,0);
-
- if ((nflags & YAMN_ACC_KBN) && (MN->Real.PopupRun+MN->Virtual.PopupRun))
- {
- CallService(MS_KBDNOTIFY_STARTBLINK,(WPARAM)MN->Real.PopupNC+MN->Virtual.PopupNC,NULL);
- }
-
- if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun+MN->Virtual.PopupRun))
- {
- char sMsg[250];
- mir_snprintf(sMsg, 249, Translate("%s : %d new mail message(s), %d total"), ActualAccount->Name, MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
- if (!(nflags & YAMN_ACC_CONTNOEVENT)) {
- CLISTEVENT cEvent;
- cEvent.cbSize = sizeof(CLISTEVENT);
- cEvent.hContact = ActualAccount->hContact;
- cEvent.hIcon = g_LoadIconEx(2);
- cEvent.hDbEvent = (HANDLE)ActualAccount->hContact;
- cEvent.lParam = (LPARAM) ActualAccount->hContact;
- cEvent.pszService = MS_YAMN_CLISTDBLCLICK;
- cEvent.pszTooltip = sMsg;
- cEvent.flags = 0;
- CallServiceSync(MS_CLIST_ADDEVENT, 0,(LPARAM)&cEvent);
- }
- db_set_s(ActualAccount->hContact, "CList", "StatusMsg", sMsg);
-
- if (nflags & YAMN_ACC_CONTNICK)
- {
- db_set_s(ActualAccount->hContact, YAMN_DBMODULE, "Nick",sMsg);
- }
- }
-
- if ((nflags & YAMN_ACC_POP) &&
- !(ActualAccount->Flags & YAMN_ACC_POPN) &&
- (MN->Real.PopupRun+MN->Virtual.PopupRun))
- {
- POPUPDATAT NewMailPopup ={0};
-
- NewMailPopup.lchContact=(ActualAccount->hContact != NULL) ? ActualAccount->hContact : (MCONTACT)ActualAccount;
- NewMailPopup.lchIcon=g_LoadIconEx(2);
- NewMailPopup.colorBack=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupB : GetSysColor(COLOR_BTNFACE);
- NewMailPopup.colorText=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupT : GetSysColor(COLOR_WINDOWTEXT);
- NewMailPopup.iSeconds=ActualAccount->NewMailN.PopupTime;
-
- NewMailPopup.PluginWindowProc = NewMailPopupProc;
- NewMailPopup.PluginData = (void *)0; //multiple popups
-
- lstrcpyn(NewMailPopup.lptzContactName, _A2T(ActualAccount->Name), SIZEOF(NewMailPopup.lptzContactName));
- mir_sntprintf(NewMailPopup.lptzText, SIZEOF(NewMailPopup.lptzText), TranslateT("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
- PUAddPopupT(&NewMailPopup);
- }
-
- //destroy tray icon if no new mail
- if ((MN->Real.SysTrayUC+MN->Virtual.SysTrayUC==0) && (hDlg != NULL))
- {
- nid.hWnd=hDlg;
- nid.uID=0;
- Shell_NotifyIcon(NIM_DELETE,&nid);
- }
-
- //and remove the event
- if ((nflags & YAMN_ACC_CONT) && (!(nflags & YAMN_ACC_CONTNOEVENT)) && (MN->Real.UnSeen + MN->Virtual.UnSeen==0)) {
- CallService(MS_CLIST_REMOVEEVENT,(WPARAM)ActualAccount->hContact,(LPARAM)ActualAccount->hContact);
- }
-
- if ((MN->Real.BrowserUC+MN->Virtual.BrowserUC==0) && (hDlg != NULL))
- {
- if (!IsWindowVisible(hDlg) && !(nflags & YAMN_ACC_MSG))
- PostMessage(hDlg,WM_DESTROY,0,0); //destroy window if no new mail and window is not visible
- if (nnflags & YAMN_ACC_MSG) //if no new mail and msg should be executed
- {
- SetForegroundWindow(hDlg);
- ShowWindow(hDlg,SW_SHOWNORMAL);
- }
- }
- else
- if (hDlg != NULL) //else insert icon and set window if new mails
- {
- SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_SCROLL,0,(LPARAM)0x7ffffff);
-
- if ((nflags & YAMN_ACC_ICO) && (MN->Real.SysTrayUC+MN->Virtual.SysTrayUC))
- {
- char* src;
- TCHAR *dest;
- int i;
-
- for (src=ActualAccount->Name,dest=nid.szTip,i=0;(*src != (TCHAR)0) && (i+1<sizeof(nid.szTip));*dest++=*src++);
- for (src=NotIconText;(*src != (TCHAR)0) && (i+1<sizeof(nid.szTip));*dest++=*src++);
- *dest=(TCHAR)0;
- nid.cbSize=sizeof(NOTIFYICONDATA);
- nid.hWnd=hDlg;
- nid.hIcon=g_LoadIconEx(2);
- nid.uID=0;
- nid.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;
- nid.uCallbackMessage=WM_YAMN_NOTIFYICON;
- Shell_NotifyIcon(NIM_ADD,&nid);
- SetTimer(hDlg,TIMER_FLASHING,500,NULL);
- }
- if (nflags & YAMN_ACC_MSG) //if no new mail and msg should be executed
- ShowWindow(hDlg,SW_SHOWNORMAL);
- }
-
- if (MN->Real.AppNC+MN->Virtual.AppNC != 0)
- {
- if (nflags & YAMN_ACC_APP)
- {
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
- ZeroMemory(&si,sizeof(si));
- si.cb=sizeof(si);
-
- if (ActualAccount->NewMailN.App != NULL)
- {
- WCHAR *Command;
- if (ActualAccount->NewMailN.AppParam != NULL)
- Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+wcslen(ActualAccount->NewMailN.AppParam)+6];
- else
- Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+6];
-
- if (Command != NULL)
- {
- lstrcpyW(Command,L"\"");
- lstrcatW(Command,ActualAccount->NewMailN.App);
- lstrcatW(Command,L"\" ");
- if (ActualAccount->NewMailN.AppParam != NULL)
- lstrcatW(Command,ActualAccount->NewMailN.AppParam);
- CreateProcessW(NULL,Command,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
- delete[] Command;
- }
- }
- }
- }
-
- if (MN->Real.SoundNC+MN->Virtual.SoundNC != 0)
- if (nflags & YAMN_ACC_SND)
- CallService(MS_SKIN_PLAYSOUND,0,(LPARAM)YAMN_NEWMAILSOUND);
-
- if ((nnflags & YAMN_ACC_POP) && (MN->Real.PopupRun+MN->Virtual.PopupRun==0))
- {
- POPUPDATAT NoNewMailPopup;
-
- NoNewMailPopup.lchContact=(ActualAccount->hContact != NULL) ? ActualAccount->hContact : (MCONTACT)ActualAccount;
- NoNewMailPopup.lchIcon=g_LoadIconEx(1);
- NoNewMailPopup.colorBack=ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? ActualAccount->NoNewMailN.PopupB : GetSysColor(COLOR_BTNFACE);
- NoNewMailPopup.colorText=ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? ActualAccount->NoNewMailN.PopupT : GetSysColor(COLOR_WINDOWTEXT);
- NoNewMailPopup.iSeconds=ActualAccount->NoNewMailN.PopupTime;
-
- NoNewMailPopup.PluginWindowProc=NoNewMailPopupProc;
- NoNewMailPopup.PluginData=(void *)0; //it's not new mail popup
-
- lstrcpyn(NoNewMailPopup.lptzContactName,_A2T(ActualAccount->Name),SIZEOF(NoNewMailPopup.lptzContactName));
- if (MN->Real.PopupSL2NC+MN->Virtual.PopupSL2NC)
- mir_sntprintf(NoNewMailPopup.lptzText, SIZEOF(NoNewMailPopup.lptzText), TranslateT("No new mail message, %d spam(s)"), MN->Real.PopupSL2NC + MN->Virtual.PopupSL2NC);
- else
- lstrcpyn(NoNewMailPopup.lptzText,TranslateT("No new mail message"),SIZEOF(NoNewMailPopup.lptzText));
- PUAddPopupT(&NoNewMailPopup);
- }
-
- if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun+MN->Virtual.PopupRun==0))
- {
- if (ActualAccount->hContact != NULL)
- {
- if (MN->Real.PopupTC+MN->Virtual.PopupTC)
- {
- char tmp[255];
- mir_snprintf(tmp, SIZEOF(tmp), Translate("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC);
- db_set_s(ActualAccount->hContact, "CList", "StatusMsg", tmp);
- }
- else db_set_s(ActualAccount->hContact, "CList", "StatusMsg", Translate("No new mail message"));
-
- if (nflags & YAMN_ACC_CONTNICK)
- db_set_s(ActualAccount->hContact, YAMN_DBMODULE, "Nick", ActualAccount->Name);
- }
- }
- return;
-}
-
-DWORD WINAPI ShowEmailThread(LPVOID Param);
-LRESULT CALLBACK NewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
-{
- INT_PTR PluginParam=0;
- switch(msg)
- {
- case WM_COMMAND:
- //if clicked and it's new mail popup window
- if ((HIWORD(wParam)==STN_CLICKED) && (-1 != (PluginParam=CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hWnd,(LPARAM)&PluginParam))))
- {
- MCONTACT hContact = 0;
- HACCOUNT Account;
- if (PluginParam) {
- PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM;
- memcpy(MailParam,(PINT_PTR)PluginParam,sizeof(YAMN_MAILSHOWPARAM));
- hContact = MailParam->account->hContact;
- Account = MailParam->account;
- if (NULL != (MailParam->ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) {
- HANDLE NewThread;
- if (NULL != (NewThread=CreateThread(NULL,0,ShowEmailThread,(LPVOID)MailParam,0,NULL)))
- {
- CloseHandle(NewThread);
- }
- CloseHandle(MailParam->ThreadRunningEV);
- }
- //delete MailParam;
- } else {
- DBVARIANT dbv;
-
- hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0);
-
- if (!db_get((MCONTACT)hContact,YAMN_DBMODULE,"Id",&dbv))
- {
- Account=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else
- Account = (HACCOUNT)hContact; //????
-
-
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read wait\n");
- #endif
- if (WAIT_OBJECT_0==WaitToReadFcn(Account->AccountAccessSO))
- {
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter\n");
- #endif
- switch(msg)
- {
- case WM_COMMAND:
- {
- YAMN_MAILBROWSERPARAM Param={(HANDLE)0,Account,
- (Account->NewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG,
- (Account->NoNewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG};
-
- RunMailBrowserSvc((WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION);
- }
- break;
- }
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read done\n");
- #endif
- ReadDoneFcn(Account->AccountAccessSO);
- }
- #ifdef DEBUG_SYNCHRO
- else
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter failed\n");
- #endif
- }
- if ((Account->NewMailN.Flags & YAMN_ACC_CONT) && !(Account->NewMailN.Flags & YAMN_ACC_CONTNOEVENT)) {
- CallService(MS_CLIST_REMOVEEVENT, hContact, hContact);
- }
- }
- // fall through
- case WM_CONTEXTMENU:
- SendMessageW(hWnd,UM_DESTROYPOPUP,0,0);
- break;
- case UM_FREEPLUGINDATA:{
- PYAMN_MAILSHOWPARAM mpd = (PYAMN_MAILSHOWPARAM)PUGetPluginData(hWnd);
- MCONTACT hContact = 0;
- if ((mpd) && (INT_PTR)mpd != -1)free(mpd);
- return FALSE;
- }
- case UM_INITPOPUP:
- //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
- WindowList_Add(YAMNVar.MessageWnds,hWnd,NULL);
- break;
- case UM_DESTROYPOPUP:
- WindowList_Remove(YAMNVar.MessageWnds,hWnd);
- break;
- case WM_YAMN_STOPACCOUNT:
- {
- HACCOUNT ActualAccount;
- MCONTACT hContact;
- DBVARIANT dbv;
-
- hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0);
-
- if (!db_get((MCONTACT) hContact,YAMN_DBMODULE,"Id",&dbv))
- {
- ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else
- ActualAccount = (HACCOUNT) hContact;
-
- if ((HACCOUNT)wParam != ActualAccount)
- break;
- DestroyWindow(hWnd);
- return 0;
- }
- case WM_NOTIFY:
- default:
- break;
- }
- return DefWindowProc(hWnd,msg,wParam,lParam);
-}
-
-LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
-{
- switch(msg)
- {
- case WM_COMMAND:
- if ((HIWORD(wParam)==STN_CLICKED) && (msg==WM_COMMAND))
- {
- HACCOUNT ActualAccount;
- MCONTACT hContact;
- DBVARIANT dbv;
-
- hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0);
-
- if (!db_get((MCONTACT)hContact,YAMN_DBMODULE,"Id",&dbv))
- {
- ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else
- ActualAccount = (HACCOUNT) hContact;
-
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read wait\n");
- #endif
- if (WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO))
- {
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter\n");
- #endif
- switch(msg)
- {
- case WM_COMMAND:
- {
- YAMN_MAILBROWSERPARAM Param={(HANDLE)0,ActualAccount,ActualAccount->NewMailN.Flags,ActualAccount->NoNewMailN.Flags,0};
-
- Param.nnflags=Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
- Param.nnflags=Param.nnflags & ~YAMN_ACC_POP;
-
- Param.nflags=Param.nflags | YAMN_ACC_MSG; //show mails in account even no new mail in account
- Param.nflags=Param.nflags & ~YAMN_ACC_POP;
-
- RunMailBrowserSvc((WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION);
- }
- break;
- }
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read done\n");
- #endif
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- #ifdef DEBUG_SYNCHRO
- else
- DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter failed\n");
- #endif
- SendMessageW(hWnd,UM_DESTROYPOPUP,0,0);
- }
- break;
-
- case WM_CONTEXTMENU:
- SendMessageW(hWnd,UM_DESTROYPOPUP,0,0);
- break;
-
- case UM_FREEPLUGINDATA:
- //Here we'd free our own data, if we had it.
- return FALSE;
- case UM_INITPOPUP:
- //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups.
- WindowList_Add(YAMNVar.MessageWnds,hWnd,NULL);
- break;
- case UM_DESTROYPOPUP:
- WindowList_Remove(YAMNVar.MessageWnds,hWnd);
- break;
- case WM_YAMN_STOPACCOUNT:
- {
- HACCOUNT ActualAccount;
- MCONTACT hContact;
- DBVARIANT dbv;
-
- hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0);
-
- if (!db_get((MCONTACT) hContact,YAMN_DBMODULE,"Id",&dbv))
- {
- ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal);
- db_free(&dbv);
- }
- else
- ActualAccount = (HACCOUNT) hContact;
-
- if ((HACCOUNT)wParam != ActualAccount)
- break;
-
- DestroyWindow(hWnd);
- return 0;
- }
- case WM_NOTIFY:
-/* switch(((LPNMHDR)lParam)->code)
- {
- case NM_CLICK:
- {
- }
- }
- break;
-*/ default:
- break;
- }
- return DefWindowProc(hWnd,msg,wParam,lParam);
-}
-
-#ifdef __GNUC__
-//number of 100 ns periods between FILETIME 0 (1601/01/01 00:00:00.0000000) and TIMESTAMP 0 (1970/01/01 00:00:00)
-#define NUM100NANOSEC 116444736000000000ULL
-//The biggest time Get[Date|Time]Format can handle (Fri, 31 Dec 30827 23:59:59.9999999)
-#define MAXFILETIME 0x7FFF35F4F06C7FFFULL
-#else
-#define NUM100NANOSEC 116444736000000000
-#define MAXFILETIME 0x7FFF35F4F06C7FFF
-#endif
-
-ULONGLONG MimeDateToFileTime(char *datein)
-{
- char *day=0, *month=0, *year=0, *time=0, *shift=0;
- SYSTEMTIME st;
- ULONGLONG res=0;
- int wShiftSeconds = CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,0,0);
- GetLocalTime(&st);
- //datein = "Xxx, 1 Jan 2060 5:29:1 +0530 XXX";
- //datein = "Xxx, 1 Jan 2060 05:29:10 ";
- //datein = " ManySpaces 1.5 Jan 2060 05::";
- //datein = "Xxx, 35 February 20 :29:10 ";
- //datein = "01.12.2007 (22:38:17)"; //
- if (datein) {
- char tmp [64];
- while ( datein[0]==' ') datein++; // eat leading spaces
- strncpy(tmp,datein,63); tmp [63]=0;
- if (atoi(tmp)) { // Parseable integer on DayOfWeek field? Buggy mime date.
- day = tmp;
- } else {
- int i = 0;
- while (tmp[i]==' ')i++; if (day = strchr(&tmp[i],' ')) {day[0]=0; day++;}
- }
- if (day) {while ( day[0]==' ') day++;if (month= strchr(day, ' ')) {month[0]=0; month++;}}
- if (month) {while (month[0]==' ')month++;if (year = strchr(month,' ')) { year[0]=0; year++;}}
- if (year) {while ( year[0]==' ') year++;if (time = strchr(year, ' ')) { time[0]=0; time++;}}
- if (time) {while ( time[0]==' ') time++;if (shift= strchr(time, ' ')) {shift[0]=0; shift++;shift[5]=0;}}
-
- if (year) {
- st.wYear = atoi(year);
- if (strlen(year)<4) if (st.wYear<70)st.wYear += 2000; else st.wYear += 1900;
- };
- if (month) for (int i=0;i<12;i++) if (strncmp(month,s_MonthNames[i],3)==0) {st.wMonth = i + 1; break;}
- if (day) st.wDay = atoi(day);
- if (time) {
- char *h, *m, *s;
- h = time;
- if (m = strchr(h,':')) {
- m[0]=0; m++;
- if (s = strchr(m,':')) {s[0] = 0; s++;}
- } else s=0;
- st.wHour = atoi(h);
- st.wMinute = m?atoi(m):0;
- st.wSecond = s?atoi(s):0;
- } else {st.wHour=st.wMinute=st.wSecond=0;}
-
- if (shift) {
- if (strlen(shift)<4) {
- //has only hour
- wShiftSeconds = (atoi(shift))*3600;
- } else {
- char *smin = shift + strlen(shift)-2;
- int ismin = atoi(smin);
- smin[0] = 0;
- int ishour = atoi(shift);
- wShiftSeconds = (ishour*60+(ishour<0?-1:1)*ismin)*60;
- }
- }
- } // if (datein)
- FILETIME ft;
- if (SystemTimeToFileTime(&st,&ft)) {
- res = ((ULONGLONG)ft.dwHighDateTime<<32)|((ULONGLONG)ft.dwLowDateTime);
- LONGLONG w100nano = Int32x32To64((DWORD)wShiftSeconds,10000000);
- res -= w100nano;
- }else{
- res=0;
- }
- return res;
-}
-
-void FileTimeToLocalizedDateTime(LONGLONG filetime, WCHAR *dateout, int lendateout)
-{
- int localeID = CallService(MS_LANGPACK_GETLOCALE,0,0);
- //int localeID = MAKELCID(LANG_URDU, SORT_DEFAULT);
- if (localeID==CALLSERVICE_NOTFOUND) localeID=LOCALE_USER_DEFAULT;
- if (filetime>MAXFILETIME) filetime = MAXFILETIME;
- else if (filetime<=0) {
- wcsncpy(dateout,TranslateW(L"Invalid"),lendateout);
- return;
- }
- SYSTEMTIME st;
- WORD wTodayYear, wTodayMonth, wTodayDay;
- FILETIME ft;
- BOOL willShowDate = !(optDateTime&SHOWDATENOTODAY);
- if (!willShowDate) {
- GetLocalTime(&st);
- wTodayYear = st.wYear;
- wTodayMonth = st.wMonth;
- wTodayDay = st.wDay;
- }
- ft.dwLowDateTime = (DWORD)filetime;
- ft.dwHighDateTime = (DWORD)(filetime >> 32);
- FILETIME localft;
- if (!FileTimeToLocalFileTime(&ft,&localft)) {
- // this should never happen
- wcsncpy(dateout,L"Incorrect FileTime",lendateout);
- } else {
- if (!FileTimeToSystemTime(&localft,&st)) {
- // this should never happen
- wcsncpy(dateout,L"Incorrect LocalFileTime",lendateout);
- } else {
- dateout[lendateout-1]=0;
- int templen = 0;
- if (!willShowDate) willShowDate = (wTodayYear != st.wYear)||(wTodayMonth != st.wMonth)||(wTodayDay != st.wDay);
- if (willShowDate) {
- templen = GetDateFormatW(localeID,(optDateTime&SHOWDATELONG)?DATE_LONGDATE:DATE_SHORTDATE,&st,NULL,dateout,lendateout-2);
- dateout[templen-1] = ' ';
- }
- if (templen<(lendateout-1)) {
- GetTimeFormatW(localeID,(optDateTime&SHOWDATENOSECONDS)?TIME_NOSECONDS:0,&st,NULL,&dateout[templen],lendateout-templen-1);
- }
- }
- }
-}
-
-void MimeDateToLocalizedDateTime(char *datein, WCHAR *dateout, int lendateout)
-{
- ULONGLONG ft = MimeDateToFileTime(datein);
- FileTimeToLocalizedDateTime(ft,dateout,lendateout);
-}
-
-int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2,LPARAM lParamSort ) {
- if (lParam1 == NULL || lParam2 == NULL)
- return 0;
-
- int nResult = 0;
- char *str1;
- char *str2;
- HYAMNMAIL email1 = (HYAMNMAIL)lParam1;
- HYAMNMAIL email2 = (HYAMNMAIL)lParam2;
- struct CShortHeader Header1;
- struct CShortHeader Header2;
- ZeroMemory(&Header1,sizeof(Header1));
- ZeroMemory(&Header2,sizeof(Header2));
-
- try {
- ExtractShortHeader(email1->MailData->TranslatedHeader,&Header1);
- ExtractShortHeader(email2->MailData->TranslatedHeader,&Header2);
-
- switch((int)lParamSort)
- {
- case 0: //From
- if (Header1.FromNick == NULL)
- str1 = Header1.From;
- else str1 = Header1.FromNick;
-
- if (Header2.FromNick == NULL)
- str2 = Header2.From;
- else str2 = Header2.FromNick;
-
- nResult = strcmp(str1, str2);
-
- if (bFrom) nResult = -nResult;
- break;
- case 1: //Subject
- if (Header1.Subject == NULL)
- str1 = " ";
- else str1 = Header1.Subject;
-
- if (Header2.Subject == NULL)
- str2 = " ";
- else str2 = Header2.Subject;
-
- nResult = strcmp(str1, str2);
-
- if (bSub) nResult = -nResult;
- break;
- case 2: //Size
- if (email1->MailData->Size == email2->MailData->Size) nResult = 0;
- if (email1->MailData->Size > email2->MailData->Size) nResult = 1;
- if (email1->MailData->Size < email2->MailData->Size) nResult = -1;
-
- if (bSize) nResult = -nResult;
- break;
-
- case 3: //Date
- {
- ULONGLONG ts1 = 0, ts2 = 0;
- ts1 = MimeDateToFileTime(Header1.Date);
- ts2 = MimeDateToFileTime(Header2.Date);
- if (ts1 > ts2) nResult = 1;
- else if (ts1 < ts2) nResult = -1;
- else nResult = 0;
- }
- if (bDate) nResult = -nResult;
- break;
-
- default:
- if (Header1.Subject == NULL) str1 = " ";
- else str1 = Header1.Subject;
-
- if (Header2.Subject == NULL) str2 = " ";
- else str2 = Header2.Subject;
-
- nResult = strcmp(str1, str2);
- break;
- }
- //MessageBox(NULL,str1,str2,0);
- }
- catch( ... )
- {
- }
-
- //free mem
- DeleteShortHeaderContent(&Header1);
- DeleteShortHeaderContent(&Header2);
- return nResult;
-
-}
-
-HCURSOR hCurSplitNS, hCurSplitWE;
-#define DM_SPLITTERMOVED (WM_USER+15)
-
-static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_NCHITTEST:
- return HTCLIENT;
-
- case WM_SETCURSOR:
- SetCursor(hCurSplitNS);
- return TRUE;
-
- case WM_LBUTTONDOWN:
- SetCapture(hwnd);
- return 0;
-
- case WM_MOUSEMOVE:
- if (GetCapture() == hwnd) {
- RECT rc;
- GetClientRect(hwnd, &rc);
- SendMessage(GetParent(hwnd), DM_SPLITTERMOVED, (short) HIWORD(GetMessagePos()) + rc.bottom / 2, (LPARAM) hwnd);
- }
- return 0;
-
- case WM_LBUTTONUP:
- ReleaseCapture();
- return 0;
- }
- return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam);
-}
-
-void ConvertCodedStringToUnicode(char *stream,WCHAR **storeto,DWORD cp,int mode);
-int ConvertStringToUnicode(char *stream,unsigned int cp,WCHAR **out);
-
-INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
-{
- switch(msg) {
- case WM_INITDIALOG:
- {
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)lParam;
- WCHAR *iHeaderW=NULL;
- WCHAR *iValueW=NULL;
- int StrLen;
- HWND hListView = GetDlgItem(hDlg,IDC_LISTHEADERS);
- mir_subclassWindow(GetDlgItem(hDlg, IDC_SPLITTER), SplitterSubclassProc);
- SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)MailParam);
- SendMessageW(hDlg,WM_SETICON,(WPARAM)ICON_BIG,(LPARAM)g_LoadIconEx(2, true));
- SendMessageW(hDlg,WM_SETICON,(WPARAM)ICON_SMALL,(LPARAM)g_LoadIconEx(2));
-
- ListView_SetUnicodeFormat(hListView,TRUE);
- ListView_SetExtendedListViewStyle(hListView,LVS_EX_FULLROWSELECT);
-
- StrLen=MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Header"),-1,NULL,0);
- iHeaderW=new WCHAR[StrLen+1];
- MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Header"),-1,iHeaderW,StrLen);
-
- StrLen=MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Value"),-1,NULL,0);
- iValueW=new WCHAR[StrLen+1];
- MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Value"),-1,iValueW,StrLen);
-
- LVCOLUMNW lvc0={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,130,iHeaderW,0,0};
- LVCOLUMNW lvc1={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,400,iValueW,0,0};
- SendMessageW(hListView,LVM_INSERTCOLUMNW,0,(LPARAM)&lvc0);
- SendMessageW(hListView,LVM_INSERTCOLUMNW,1,(LPARAM)&lvc1);
- if (NULL != iHeaderW)
- delete[] iHeaderW;
- if (NULL != iValueW)
- delete[] iValueW;
-
- //WindowList_Add(YAMNVar.MessageWnds,hDlg,NULL);
- //WindowList_Add(YAMNVar.NewMailAccountWnd,hDlg,ActualAccount);
- SendMessage(hDlg,WM_YAMN_CHANGECONTENT,0,(LPARAM)MailParam);
- MoveWindow(hDlg,HeadPosX,HeadPosY,HeadSizeX,HeadSizeY,0);
- ShowWindow(hDlg,SW_SHOWNORMAL);
- }
- break;
-
- case WM_YAMN_CHANGECONTENT:
- {
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)
- (lParam?lParam:GetWindowLongPtr(hDlg,DWLP_USER));
- HWND hListView = GetDlgItem(hDlg,IDC_LISTHEADERS);
- HWND hEdit = GetDlgItem(hDlg,IDC_EDITBODY);
- //do not redraw
- SendMessage(hListView, WM_SETREDRAW, 0, 0);
- ListView_DeleteAllItems(hListView);
- struct CMimeItem *Header;
- LVITEMW item;
- item.mask=LVIF_TEXT | LVIF_PARAM;
- WCHAR *From=0,*Subj=0;
- char *contentType=0, *transEncoding=0, *body=0; //should not be delete[]-ed
- for (Header=MailParam->mail->MailData->TranslatedHeader;Header != NULL;Header=Header->Next)
- {
- WCHAR *str1 = 0;
- WCHAR *str2 = 0;
- if (!body) if (!_stricmp(Header->name,"Body")) {body = Header->value; continue;}
- if (!contentType) if (!_stricmp(Header->name,"Content-Type")) contentType = Header->value;
- if (!transEncoding) if (!_stricmp(Header->name,"Content-Transfer-Encoding")) transEncoding = Header->value;
- //ConvertCodedStringToUnicode(Header->name,&str1,MailParam->mail->MailData->CP,1);
- {
- int streamsize = MultiByteToWideChar(20127,0,Header->name,-1,NULL,0);
- str1 = new WCHAR[streamsize+1];
- MultiByteToWideChar(20127,0,Header->name,-1,str1,streamsize);//US-ASCII
- }
- ConvertCodedStringToUnicode(Header->value,&str2,MailParam->mail->MailData->CP,1);
- if (!str2) { str2 = (WCHAR *)malloc(2); str2[0] = 0; }// the header value may be NULL
- if (!From) if (!_stricmp(Header->name,"From")) {
- From =new WCHAR[wcslen(str2)+1];
- wcscpy(From,str2);
- }
- if (!Subj) if (!_stricmp(Header->name,"Subject")) {
- Subj =new WCHAR[wcslen(str2)+1];
- wcscpy(Subj,str2);
- }
- //if (!hasBody) if (!strcmp(Header->name,"Body")) hasBody = true;
- int count = 0; WCHAR **split=0;
- if (str2) {
- int ofs = 0;
- while (str2[ofs]) {
- if ((str2[ofs]==0x266A)||(str2[ofs]==0x25D9)||(str2[ofs]==0x25CB)||
- (str2[ofs]==0x09)||(str2[ofs]==0x0A)||(str2[ofs]==0x0D))count++;
- ofs++;
- }
- split=new WCHAR*[count+1];
- count=0; ofs=0;
- split[0]=str2;
- while (str2[ofs]) {
- if ((str2[ofs]==0x266A)||(str2[ofs]==0x25D9)||(str2[ofs]==0x25CB)||
- (str2[ofs]==0x09)||(str2[ofs]==0x0A)||(str2[ofs]==0x0D)) {
- if (str2[ofs-1]) {
- count++;
- }
- split[count]=(WCHAR *)(str2+ofs+1);
- str2[ofs]=0;
- }
- ofs++;
- };
- }
- if (!_stricmp(Header->name,"From")||!_stricmp(Header->name,"To")||!_stricmp(Header->name,"Date")||!_stricmp(Header->name,"Subject"))
- item.iItem = 0;
- else
- item.iItem = 999;
- for (int i=0;i<=count;i++) {
- item.iSubItem=0;
- if (i==0)
- item.pszText=str1;
- else {
- item.iItem++;
- item.pszText=0;
- }
- item.iItem=SendMessageW(hListView,LVM_INSERTITEMW,0,(LPARAM)&item);
- item.iSubItem=1;
- item.pszText=str2?split[i]:0;
- SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item);
- }
- if (split)delete[] split;
-
- if (str1) free(str1);
- if (str2) free(str2);
- }
- if (body) {
- WCHAR *bodyDecoded = 0;
- char *localBody=0;
- if (contentType) {
- if (!_strnicmp(contentType,"text",4)) {
- if (transEncoding) {
- if (!_stricmp(transEncoding,"base64")) {
- int size = (int)strlen(body)*3/4+5;
- localBody = new char[size+1];
- DecodeBase64(body,localBody,size);
- } else if (!_stricmp(transEncoding,"quoted-printable")) {
- int size = (int)strlen(body)+2;
- localBody = new char[size+1];
- DecodeQuotedPrintable(body,localBody,size,FALSE);
- }
- }
- } else if (!_strnicmp(contentType,"multipart/",10)) {
- char *bondary=NULL;
- if (NULL != (bondary=ExtractFromContentType(contentType,"boundary=")))
- {
- bodyDecoded = ParseMultipartBody(body,bondary);
- delete[] bondary;
- }
- }
- }
- if (!bodyDecoded)ConvertStringToUnicode(localBody?localBody:body,MailParam->mail->MailData->CP,&bodyDecoded);
- SendMessageW(hEdit,WM_SETTEXT,0,(LPARAM)bodyDecoded);
- delete[] bodyDecoded;
- if (localBody) delete[] localBody;
- SetFocus(hEdit);
- }
- if (!(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)) {
- MailParam->mail->Flags |= YAMN_MSG_BODYREQUESTED;
- CallService(MS_YAMN_ACCOUNTCHECK,(WPARAM)MailParam->account,0);
- } else {
- if (MailParam->mail->Flags & YAMN_MSG_UNSEEN) {
- MailParam->mail->Flags&=~YAMN_MSG_UNSEEN; //mark the message as seen
- HWND hMailBrowser;
- if (hMailBrowser=WindowList_Find(YAMNVar.NewMailAccountWnd, (MCONTACT)MailParam->account)) {
- struct CChangeContent Params={MailParam->account->NewMailN.Flags|YAMN_ACC_MSGP,MailParam->account->NoNewMailN.Flags|YAMN_ACC_MSGP};
- SendMessageW(hMailBrowser,WM_YAMN_CHANGECONTENT,(WPARAM)MailParam->account,(LPARAM)&Params);
- }
- else UpdateMails(NULL,MailParam->account,MailParam->account->NewMailN.Flags,MailParam->account->NoNewMailN.Flags);
- }
- }
- ShowWindow(GetDlgItem(hDlg, IDC_SPLITTER),(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)?SW_SHOW:SW_HIDE);
- ShowWindow(hEdit,(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)?SW_SHOW:SW_HIDE);
- WCHAR *title=0;
- size_t size = (From ? wcslen(From) : 0) + (Subj ? wcslen(Subj) : 0) + 4;
- title = new WCHAR[size];
- if (From&&Subj)
- mir_sntprintf(title, size, L"%s (%s)", Subj, From);
- else if (From)
- mir_sntprintf(title, size, L"%s", From);
- else if (Subj)
- mir_sntprintf(title, size, L"%s", Subj);
- else
- mir_sntprintf(title, size, L"none");
- if (Subj) delete[] Subj;
- if (From) delete[] From;
- SendMessageW(hDlg,WM_SETTEXT,0,(LPARAM)title);
- delete[] title;
- // turn on redrawing
- SendMessage(hListView, WM_SETREDRAW, 1, 0);
- SendMessage(hDlg, WM_SIZE, 0, HeadSizeY<<16|HeadSizeX);
- } break;
-
- case WM_YAMN_STOPACCOUNT:
- {
- PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)
- (lParam?lParam:GetWindowLongPtr(hDlg,DWLP_USER));
-
- if (NULL==MailParam)
- break;
- if ((HACCOUNT)wParam != MailParam->account)
- break;
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"ShowMessage:STOPACCOUNT:sending destroy msg\n");
-#endif
- DestroyWindow(hDlg);
- }
- return 1;
-
- case WM_CTLCOLORSTATIC:
- //here should be check if this is our edittext control.
- //but we have only one static control (for now);
- SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
- SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT));
- return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
-
- case WM_DESTROY:
- {
- RECT coord;
- if (GetWindowRect(hDlg,&coord)) {
- HeadPosX=coord.left;
- HeadSizeX=coord.right-coord.left;
- HeadPosY=coord.top;
- HeadSizeY=coord.bottom-coord.top;
- }
-
- PostQuitMessage(1);
- }
- break;
-
- case WM_SYSCOMMAND:
- switch(wParam) {
- case SC_CLOSE:
- DestroyWindow(hDlg);
- break;
- }
- break;
-
- case WM_MOVE:
- HeadPosX=LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
- HeadPosY=HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
- return 0;
-
- case DM_SPLITTERMOVED:
- if ((HWND) lParam == GetDlgItem(hDlg, IDC_SPLITTER)) {
- POINT pt;
- pt.x = 0;
- pt.y = wParam;
- ScreenToClient(hDlg, &pt);
- HeadSplitPos = (pt.y*1000)/HeadSizeY;//+rc.bottom-rc.top;
- if (HeadSplitPos>=1000) HeadSplitPos = 999;
- else if (HeadSplitPos<=0) HeadSplitPos = 1;
- else SendMessage(hDlg, WM_SIZE, 0, HeadSizeY<<16|HeadSizeX);
- }
- return 0;
-
- case WM_SIZE:
- if (wParam == SIZE_RESTORED) {
- HWND hList = GetDlgItem(hDlg,IDC_LISTHEADERS);
- HWND hEdit = GetDlgItem(hDlg,IDC_EDITBODY);
- BOOL changeX = LOWORD(lParam) != HeadSizeX;
- BOOL isBodyShown = ((PYAMN_MAILSHOWPARAM)(GetWindowLongPtr(hDlg,DWLP_USER)))->mail->Flags & YAMN_MSG_BODYRECEIVED;
- HeadSizeX=LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
- HeadSizeY=HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
- int localSplitPos = (HeadSplitPos*HeadSizeY)/1000;
- int localSizeX;
- RECT coord;
- MoveWindow(GetDlgItem(hDlg,IDC_SPLITTER),5,localSplitPos,HeadSizeX-10,2,TRUE);
- MoveWindow(hEdit,5,localSplitPos+6,HeadSizeX-10,HeadSizeY-localSplitPos-11,TRUE); //where to put text window while resizing
- MoveWindow(hList, 5 ,5 ,HeadSizeX-10 ,(isBodyShown?localSplitPos:HeadSizeY)-10,TRUE); //where to put headers list window while resizing
- //if (changeX) {
- if (GetClientRect(hList,&coord)) {
- localSizeX=coord.right-coord.left;
- } else localSizeX=HeadSizeX;
- LONG iNameWidth = ListView_GetColumnWidth(hList,0);
- ListView_SetColumnWidth(hList,1,(localSizeX<=iNameWidth)?0:(localSizeX-iNameWidth));
- //}
- }
- return 0;
-
- case WM_CONTEXTMENU:
- if ( GetWindowLongPtr(( HWND )wParam, GWLP_ID ) == IDC_LISTHEADERS) {
- //MessageBox(0,"LISTHEADERS","Debug",0);
- HWND hList = GetDlgItem( hDlg, IDC_LISTHEADERS );
- POINT pt = { (signed short)LOWORD( lParam ), (signed short)HIWORD( lParam ) };
- HTREEITEM hItem = 0;
- if (pt.x==-1) pt.x = 0;
- if (pt.y==-1) pt.y = 0;
- if (int numRows = ListView_GetItemCount(hList)) {
- HMENU hMenu = CreatePopupMenu();
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected"));
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All"));
- AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel"));
- int nReturnCmd = TrackPopupMenu( hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, NULL );
- DestroyMenu( hMenu );
- if (nReturnCmd>0) {
- int courRow=0;
- size_t sizeNeeded = 0;
- TCHAR headname[64]={0}, headvalue[256]={0};
- for (courRow=0; courRow < numRows; courRow++) {
- if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue;
- ListView_GetItemText(hList, courRow, 0, headname, SIZEOF(headname));
- ListView_GetItemText(hList, courRow, 1, headvalue, SIZEOF(headvalue));
- size_t headnamelen = _tcslen(headname);
- if (headnamelen) sizeNeeded += 1 + headnamelen;
- sizeNeeded += 3 + _tcslen(headvalue);
- }
- if (sizeNeeded && OpenClipboard(hDlg)) {
- EmptyClipboard();
- HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE,(sizeNeeded+1)*sizeof(TCHAR));
- TCHAR *buff = ( TCHAR* )GlobalLock(hData);
- int courPos = 0;
- for (courRow=0;courRow<numRows;courRow++) {
- if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue;
- ListView_GetItemText(hList, courRow, 0, headname, SIZEOF(headname));
- ListView_GetItemText(hList, courRow, 1, headvalue, SIZEOF(headvalue));
- if ( _tcslen(headname)) courPos += mir_sntprintf(&buff[courPos], sizeNeeded + 1, _T("%s:\t%s\r\n"), headname, headvalue);
- else courPos += mir_sntprintf(&buff[courPos], sizeNeeded + 1, _T("\t%s\r\n"), headvalue);
- }
- GlobalUnlock(hData);
-
- SetClipboardData(CF_UNICODETEXT,hData);
-
- CloseClipboard();
- }
- }
- }
- }
- break; // just in case
- }
- return 0;
-}
-
-DWORD WINAPI ShowEmailThread(LPVOID Param) {
- struct MailShowMsgWinParam MyParam;
- MyParam=*(struct MailShowMsgWinParam *)Param;
-
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"ShowMessage:Incrementing \"using threads\" %x (account %x)\n",MyParam.account->UsingThreads,MyParam.account);
- #endif
- SCIncFcn(MyParam.account->UsingThreads);
- SetEvent(MyParam.ThreadRunningEV);
- if (MyParam.mail->MsgWindow) {
- //if (!BringWindowToTop(MyParam.mail->MsgWindow)) {
- if (!SetForegroundWindow(MyParam.mail->MsgWindow)) {
- SendMessage(MyParam.mail->MsgWindow,WM_DESTROY,0,0);
- MyParam.mail->MsgWindow = 0;
- goto CREADTEVIEWMESSAGEWINDOW;
- }else{
- if (IsIconic(MyParam.mail->MsgWindow)) {
- OpenIcon(MyParam.mail->MsgWindow);
- }
- }
- } else {
-CREADTEVIEWMESSAGEWINDOW:
- MyParam.mail->MsgWindow = CreateDialogParamW(YAMNVar.hInst,MAKEINTRESOURCEW(IDD_DLGSHOWMESSAGE),NULL,DlgProcYAMNShowMessage,(LPARAM)&MyParam);
- WindowList_Add(YAMNVar.MessageWnds,MyParam.mail->MsgWindow,NULL);
- MSG msg;
- while(GetMessage(&msg,NULL,0,0)) {
- if (!IsDialogMessage(MyParam.mail->MsgWindow, &msg)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- } }
- WindowList_Remove(YAMNVar.MessageWnds,MyParam.mail->MsgWindow);
- MyParam.mail->MsgWindow = NULL;
- }
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"ShowMessage:Decrementing \"using threads\" %x (account %x)\n",MyParam.account->UsingThreads,MyParam.account);
- #endif
- SCDecFcn(MyParam.account->UsingThreads);
- delete Param;
- return 1;
-}
-
-INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
-{
- switch(msg) {
- case WM_INITDIALOG:
- {
- HACCOUNT ActualAccount;
- struct MailBrowserWinParam *MyParam=(struct MailBrowserWinParam *)lParam;
- struct CMailWinUserInfo *mwui;
-
- ListView_SetUnicodeFormat(GetDlgItem(hDlg,IDC_LISTMAILS),TRUE);
- ListView_SetExtendedListViewStyle(GetDlgItem(hDlg,IDC_LISTMAILS),LVS_EX_FULLROWSELECT);
-
- ActualAccount=MyParam->account;
- mwui=new struct CMailWinUserInfo;
- mwui->Account=ActualAccount;
- mwui->TrayIconState=0;
- mwui->UpdateMailsMessagesAccess=FALSE;
- mwui->Seen=FALSE;
- mwui->RunFirstTime=TRUE;
-
- SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)mwui);
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read wait\n");
-#endif
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read enter failed\n");
-#endif
- DestroyWindow(hDlg);
- return FALSE;
- }
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read enter\n");
-#endif
-
- SendMessageW(GetDlgItem(hDlg,IDC_BTNAPP),WM_SETTEXT,0,(LPARAM)TranslateW(L"Run application"));
- SendMessageW(GetDlgItem(hDlg,IDC_BTNDEL),WM_SETTEXT,0,(LPARAM)TranslateW(L"Delete selected"));
- SendMessageW(GetDlgItem(hDlg,IDC_BTNCHECKALL),WM_SETTEXT,0,(LPARAM)TranslateW(L"Select All"));
- SendMessageW(GetDlgItem(hDlg,IDC_BTNOK),WM_SETTEXT,0,(LPARAM)TranslateW(L"OK"));
-
- LVCOLUMNW lvc0={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,FromWidth,TranslateW(L"From"),0,0};
- LVCOLUMNW lvc1={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,SubjectWidth,TranslateW(L"Subject"),0,0};
- LVCOLUMNW lvc2={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,SizeWidth,TranslateW(L"Size"),0,0};
- LVCOLUMNW lvc3={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,SizeDate,TranslateW(L"Date"),0,0};
- SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,0,(LPARAM)&lvc0);
- SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,1,(LPARAM)&lvc1);
- SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,(WPARAM)2,(LPARAM)&lvc2);
- SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,(WPARAM)3,(LPARAM)&lvc3);
-
- if ((ActualAccount->NewMailN.App != NULL) && (wcslen(ActualAccount->NewMailN.App)))
- EnableWindow(GetDlgItem(hDlg,IDC_BTNAPP),TRUE);
- else
- EnableWindow(GetDlgItem(hDlg,IDC_BTNAPP),FALSE);
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read done\n");
-#endif
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- WindowList_Add(YAMNVar.MessageWnds,hDlg,NULL);
- WindowList_Add(YAMNVar.NewMailAccountWnd,hDlg, (MCONTACT)ActualAccount);
-
- {
- TCHAR accstatus[512];
- GetStatusFcn(ActualAccount,accstatus);
- SetDlgItemText(hDlg,IDC_STSTATUS,accstatus);
- }
- SetTimer(hDlg,TIMER_FLASHING,500,NULL);
-
- if (ActualAccount->hContact != NULL)
- CallService(MS_CLIST_REMOVEEVENT,(WPARAM)ActualAccount->hContact,(LPARAM)"yamn new mail message");
-
- mir_subclassWindow( GetDlgItem(hDlg, IDC_LISTMAILS), ListViewSubclassProc);
- }
- break;
-
- case WM_DESTROY:
- {
- HACCOUNT ActualAccount;
- RECT coord;
- LVCOLUMNW ColInfo;
- NOTIFYICONDATA nid;
- HYAMNMAIL Parser;
- struct CMailWinUserInfo *mwui;
-
- mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER);
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- break;
- ColInfo.mask=LVCF_WIDTH;
- if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),0,&ColInfo))
- FromWidth=ColInfo.cx;
- if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),1,&ColInfo))
- SubjectWidth=ColInfo.cx;
- if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),2,&ColInfo))
- SizeWidth=ColInfo.cx;
- if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),3,&ColInfo))
- SizeDate=ColInfo.cx;
-
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DESTROY:save window position\n");
-#endif
- if (!YAMNVar.Shutdown && GetWindowRect(hDlg,&coord)) //the YAMNVar.Shutdown testing is because M<iranda strange functionality at shutdown phase, when call to DBWriteContactSetting freezes calling thread
- {
- PosX=coord.left;
- SizeX=coord.right-coord.left;
- PosY=coord.top;
- SizeY=coord.bottom-coord.top;
- db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBPOSX,PosX);
- db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBPOSY,PosY);
- db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBSIZEX,SizeX);
- db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBSIZEY,SizeY);
- }
- KillTimer(hDlg,TIMER_FLASHING);
-
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DESTROY:remove window from list\n");
-#endif
- WindowList_Remove(YAMNVar.NewMailAccountWnd,hDlg);
- WindowList_Remove(YAMNVar.MessageWnds,hDlg);
-
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write wait\n");
-#endif
- if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write wait failed\n");
-#endif
- break;
- }
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write enter\n");
-#endif
- //delete mails from queue, which are deleted from server (spam level 3 mails e.g.)
- for (Parser=(HYAMNMAIL)ActualAccount->Mails;Parser != NULL;Parser=Parser->Next)
- {
- if ((Parser->Flags & YAMN_MSG_DELETED) && YAMN_MSG_SPAML(Parser->Flags,YAMN_MSG_SPAML3) && mwui->Seen) //if spaml3 was already deleted and user knows about it
- {
- DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails,Parser,1);
- CallService(MS_YAMN_DELETEACCOUNTMAIL,(WPARAM)ActualAccount->Plugin,(LPARAM)Parser);
- }
- }
-
- //mark mails as read (remove "new" and "unseen" flags)
- if (mwui->Seen)
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_DISPLAY,0,YAMN_MSG_NEW | YAMN_MSG_UNSEEN,0);
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write done\n");
-#endif
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
-
- ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
-
- delete mwui;
- SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)NULL);
-
- nid.cbSize=sizeof(NOTIFYICONDATA);
- nid.hWnd=hDlg;
- nid.uID=0;
- Shell_NotifyIcon(NIM_DELETE,&nid);
- PostQuitMessage(0);
- }
- break;
- case WM_SHOWWINDOW:
- {
- struct CMailWinUserInfo *mwui;
-
- if (NULL==(mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER)))
- return 0;
- mwui->Seen=TRUE;
- }
- case WM_YAMN_CHANGESTATUS:
- {
- HACCOUNT ActualAccount;
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- break;
-
- if ((HACCOUNT)wParam != ActualAccount)
- break;
-
- TCHAR accstatus[512];
- GetStatusFcn(ActualAccount,accstatus);
- SetDlgItemText(hDlg,IDC_STSTATUS,accstatus);
- }
- return 1;
- case WM_YAMN_CHANGECONTENT:
- {
- struct CUpdateMails UpdateParams;
- BOOL ThisThreadWindow=(GetCurrentThreadId()==GetWindowThreadProcessId(hDlg,NULL));
-
- if (NULL==(UpdateParams.Copied=CreateEvent(NULL,FALSE,FALSE,NULL)))
- {
- DestroyWindow(hDlg);
- return 0;
- }
- UpdateParams.Flags=(struct CChangeContent *)lParam;
- UpdateParams.Waiting=!ThisThreadWindow;
-
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:CHANGECONTENT:posting UPDATEMAILS\n");
-#endif
- if (ThisThreadWindow)
- {
- if (!UpdateMails(hDlg,(HACCOUNT)wParam,UpdateParams.Flags->nflags,UpdateParams.Flags->nnflags))
- DestroyWindow(hDlg);
- }
- else if (PostMessage(hDlg,WM_YAMN_UPDATEMAILS,wParam,(LPARAM)&UpdateParams)) //this ensures UpdateMails will execute the thread who created the browser window
- {
- if (!ThisThreadWindow)
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:CHANGECONTENT:waiting for event\n");
-#endif
- WaitForSingleObject(UpdateParams.Copied,INFINITE);
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:CHANGECONTENT:event signaled\n");
-#endif
- }
- }
-
- CloseHandle(UpdateParams.Copied);
- }
- return 1;
- case WM_YAMN_UPDATEMAILS:
- {
- HACCOUNT ActualAccount;
-
- struct CUpdateMails *um=(struct CUpdateMails *)lParam;
- DWORD nflags,nnflags;
-
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:UPDATEMAILS\n");
-#endif
-
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- return 0;
- if ((HACCOUNT)wParam != ActualAccount)
- return 0;
-
- nflags=um->Flags->nflags;
- nnflags=um->Flags->nnflags;
-
- if (um->Waiting)
- SetEvent(um->Copied);
-
- if (!UpdateMails(hDlg,ActualAccount,nflags,nnflags))
- DestroyWindow(hDlg);
- }
- return 1;
- case WM_YAMN_STOPACCOUNT:
- {
- HACCOUNT ActualAccount;
-
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- break;
- if ((HACCOUNT)wParam != ActualAccount)
- break;
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:STOPACCOUNT:sending destroy msg\n");
-#endif
- PostQuitMessage(0);
- }
- return 1;
- case WM_YAMN_NOTIFYICON:
- {
- HACCOUNT ActualAccount;
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- break;
-
- switch(lParam)
- {
- case WM_LBUTTONDBLCLK:
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read wait\n");
-#endif
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read wait failed\n");
-#endif
- return 0;
- }
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read enter\n");
-#endif
- if (ActualAccount->AbilityFlags & YAMN_ACC_BROWSE)
- {
- ShowWindow(hDlg,SW_SHOWNORMAL);
- SetForegroundWindow(hDlg);
- }
- else
- DestroyWindow(hDlg);
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read done\n");
-#endif
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- break;
- }
- break;
- }
- case WM_YAMN_SHOWSELECTED:
- {
- int iSelect;
- iSelect=SendMessage(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_GETNEXTITEM,-1,MAKELPARAM((UINT)LVNI_FOCUSED,0)); // return item selected
-
- if (iSelect != -1)
- {
- LV_ITEMW item;
- HYAMNMAIL ActualMail;
-
- item.iItem=iSelect;
- item.iSubItem=0;
- item.mask=LVIF_PARAM | LVIF_STATE;
- item.stateMask=0xFFFFFFFF;
- ListView_GetItem(GetDlgItem(hDlg,IDC_LISTMAILS),&item);
- ActualMail=(HYAMNMAIL)item.lParam;
- if (NULL != ActualMail)
- {
- //ShowEmailThread
- PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM;
- MailParam->account = GetWindowAccount(hDlg);
- MailParam->mail = ActualMail;
- if (NULL != (MailParam->ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) {
- HANDLE NewThread;
- if (NULL != (NewThread=CreateThread(NULL,0,ShowEmailThread,MailParam,0,NULL)))
- {
- //WaitForSingleObject(MailParam->ThreadRunningEV,INFINITE);
- CloseHandle(NewThread);
- }
- CloseHandle(MailParam->ThreadRunningEV);
- }
- //delete MailParam;
- }
- }
- } break;
- case WM_SYSCOMMAND:
- {
- HACCOUNT ActualAccount;
-
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- break;
- switch(wParam)
- {
- case SC_CLOSE:
- DestroyWindow(hDlg);
- break;
- }
- }
- break;
-
- case WM_COMMAND:
- {
- HACCOUNT ActualAccount;
- int Items;
-
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- break;
-
- switch(LOWORD(wParam))
- {
- case IDC_BTNCHECKALL:
- ListView_SetItemState(GetDlgItem(hDlg,IDC_LISTMAILS), -1, 0, LVIS_SELECTED); // deselect all items
- ListView_SetItemState(GetDlgItem(hDlg,IDC_LISTMAILS),-1, LVIS_SELECTED ,LVIS_SELECTED);
- Items = ListView_GetItemCount(GetDlgItem(hDlg,IDC_LISTMAILS));
- ListView_RedrawItems(GetDlgItem(hDlg,IDC_LISTMAILS), 0, Items);
- UpdateWindow(GetDlgItem(hDlg,IDC_LISTMAILS));
- SetFocus(GetDlgItem(hDlg,IDC_LISTMAILS));
- break;
-
- case IDC_BTNOK:
- DestroyWindow(hDlg);
- break;
-
- case IDC_BTNAPP:
- {
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
-
- ZeroMemory(&si,sizeof(si));
- si.cb=sizeof(si);
-
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read wait\n");
-#endif
- if (WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read enter\n");
-#endif
- if (ActualAccount->NewMailN.App != NULL)
- {
- WCHAR *Command;
- if (ActualAccount->NewMailN.AppParam != NULL)
- Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+wcslen(ActualAccount->NewMailN.AppParam)+6];
- else
- Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+6];
-
- if (Command != NULL)
- {
- lstrcpyW(Command,L"\"");
- lstrcatW(Command,ActualAccount->NewMailN.App);
- lstrcatW(Command,L"\" ");
- if (ActualAccount->NewMailN.AppParam != NULL)
- lstrcatW(Command,ActualAccount->NewMailN.AppParam);
- CreateProcessW(NULL,Command,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
- delete[] Command;
- }
- }
-
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read done\n");
-#endif
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
-#ifdef DEBUG_SYNCHRO
- else
- DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read enter failed\n");
-#endif
- if (!(GetKeyState(VK_SHIFT) & 0x8000) && !(GetKeyState(VK_CONTROL) & 0x8000))
- DestroyWindow(hDlg);
-
- }
- break;
- case IDC_BTNDEL:
- {
- LVITEMW item;
- HYAMNMAIL FirstMail=NULL,ActualMail;
- HANDLE ThreadRunningEV;
- DWORD tid,Total=0;
-
- // we use event to signal, that running thread has all needed stack parameters copied
- if (NULL==(ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL)))
- break;
- int Items=ListView_GetItemCount(GetDlgItem(hDlg,IDC_LISTMAILS));
-
- item.stateMask=0xFFFFFFFF;
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write wait\n");
-#endif
- if (WAIT_OBJECT_0==WaitToWriteFcn(ActualAccount->MessagesAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write enter\n");
-#endif
- for (int i=0;i<Items;i++)
- {
- item.iItem=i;
- item.iSubItem=0;
- item.mask=LVIF_PARAM | LVIF_STATE;
- item.stateMask=0xFFFFFFFF;
- ListView_GetItem(GetDlgItem(hDlg,IDC_LISTMAILS),&item);
- ActualMail=(HYAMNMAIL)item.lParam;
- if (NULL==ActualMail)
- break;
- if (item.state & LVIS_SELECTED)
- {
- ActualMail->Flags|=YAMN_MSG_USERDELETE; //set to mail we are going to delete it
- Total++;
- }
- }
-
- // Enable write-access to mails
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write done\n");
-#endif
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
-
- if (Total)
- {
- TCHAR DeleteMsg[1024];
-
- mir_sntprintf(DeleteMsg, SIZEOF(DeleteMsg), TranslateT("Do you really want to delete %d selected mails?"),Total);
- if (IDOK==MessageBox(hDlg,DeleteMsg,TranslateT("Delete confirmation"),MB_OKCANCEL | MB_ICONWARNING))
- {
- struct DeleteParam ParamToDeleteMails={YAMN_DELETEVERSION,ThreadRunningEV,ActualAccount,NULL};
-
- // Find if there's mail marked to delete, which was deleted before
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write wait\n");
-#endif
- if (WAIT_OBJECT_0==WaitToWriteFcn(ActualAccount->MessagesAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write enter\n");
-#endif
- for (ActualMail=(HYAMNMAIL)ActualAccount->Mails;ActualMail != NULL;ActualMail=ActualMail->Next)
- {
- if ((ActualMail->Flags & YAMN_MSG_DELETED) && ((ActualMail->Flags & YAMN_MSG_USERDELETE))) //if selected mail was already deleted
- {
- DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails,ActualMail,1);
- CallService(MS_YAMN_DELETEACCOUNTMAIL,(WPARAM)ActualAccount->Plugin,(LPARAM)ActualMail); //delete it from memory
- continue;
- }
- }
- // Set flag to marked mails that they can be deleted
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE,0,YAMN_MSG_DELETEOK,1);
- // Create new thread which deletes marked mails.
- HANDLE NewThread;
-
- if (NULL != (NewThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ActualAccount->Plugin->Fcn->DeleteMailsFcnPtr,(LPVOID)&ParamToDeleteMails,0,&tid)))
- {
- WaitForSingleObject(ThreadRunningEV,INFINITE);
- CloseHandle(NewThread);
- }
- // Enable write-access to mails
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write done\n");
-#endif
- WriteDoneFcn(ActualAccount->MessagesAccessSO);
- }
- }
- else
- //else mark messages that they are not to be deleted
- SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE,0,YAMN_MSG_USERDELETE,0);
- }
- }
- CloseHandle(ThreadRunningEV);
- if (db_get_b(NULL, YAMN_DBMODULE, YAMN_CLOSEDELETE, 0))
- DestroyWindow(hDlg);
-
- }
- break;
- }
- }
- break;
- case WM_SIZE:
- if (wParam==SIZE_RESTORED)
- {
- LONG x=LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left;
- LONG y=HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top;
- MoveWindow(GetDlgItem(hDlg,IDC_BTNDEL), 5 ,y-5-25,(x-20)/3,25,TRUE); //where to put DELETE button while resizing
- MoveWindow(GetDlgItem(hDlg,IDC_BTNCHECKALL),10+ (x-20)/3,y-5-25,(x-20)/6,25,TRUE); //where to put CHECK ALL button while resizing
- MoveWindow(GetDlgItem(hDlg,IDC_BTNAPP), 15+ (x-20)/3 + (x-20)/6,y-5-25,(x-20)/3,25,TRUE); //where to put RUN APP button while resizing
- MoveWindow(GetDlgItem(hDlg,IDC_BTNOK), 20+2*(x-20)/3 + (x-20)/6 ,y-5-25,(x-20)/6,25,TRUE); //where to put OK button while resizing
- MoveWindow(GetDlgItem(hDlg,IDC_LISTMAILS), 5 ,5 ,x-10 ,y-55,TRUE); //where to put list mail window while resizing
- MoveWindow(GetDlgItem(hDlg,IDC_STSTATUS), 5 ,y-5-45 ,x-10 ,15,TRUE); //where to put account status text while resizing
- }
- // break;
- return 0;
- case WM_GETMINMAXINFO:
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.x=MAILBROWSER_MINXSIZE;
- ((LPMINMAXINFO)lParam)->ptMinTrackSize.y=MAILBROWSER_MINYSIZE;
- return 0;
- case WM_TIMER:
- {
- NOTIFYICONDATA nid;
- struct CMailWinUserInfo *mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER);
-
- ZeroMemory(&nid,sizeof(nid));
- nid.cbSize=sizeof(NOTIFYICONDATA);
- nid.hWnd=hDlg;
- nid.uID=0;
- nid.uFlags=NIF_ICON;
- if (mwui->TrayIconState==0)
- nid.hIcon=g_LoadIconEx(0);
- else
- nid.hIcon=g_LoadIconEx(2);
- Shell_NotifyIcon(NIM_MODIFY,&nid);
- mwui->TrayIconState=!mwui->TrayIconState;
- // UpdateWindow(hDlg);
- }
- break;
-
- case WM_NOTIFY:
- switch(((LPNMHDR)lParam)->idFrom) {
- case IDC_LISTMAILS:
- switch(((LPNMHDR)lParam)->code) {
- case NM_DBLCLK:
- SendMessage(hDlg,WM_YAMN_SHOWSELECTED,0,0);
- break;
- case LVN_COLUMNCLICK:
- HACCOUNT ActualAccount;
- if (NULL != (ActualAccount=GetWindowAccount(hDlg))) {
- NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
- if (WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:COLUMNCLICK:ActualAccountSO-read enter\n");
-#endif
- switch((int)pNMListView->iSubItem)
- {
- case 0:
- bFrom = !bFrom;
- break;
- case 1:
- bSub = !bSub;
- break;
- case 2:
- bSize = !bSize;
- break;
- case 3:
- bDate = !bDate;
- break;
- default:
- break;
- }
- ListView_SortItems(pNMListView->hdr.hwndFrom,ListViewCompareProc,pNMListView->iSubItem);
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read done\n");
-#endif
- ReadDoneFcn(ActualAccount->AccountAccessSO);
- }
- }
- break;
-
- case NM_CUSTOMDRAW:
- {
- HACCOUNT ActualAccount;
- LPNMLVCUSTOMDRAW cd=(LPNMLVCUSTOMDRAW)lParam;
- LONG_PTR PaintCode;
-
- if (NULL==(ActualAccount=GetWindowAccount(hDlg)))
- break;
-
- switch(cd->nmcd.dwDrawStage) {
- case CDDS_PREPAINT:
- PaintCode=CDRF_NOTIFYITEMDRAW;
- break;
- case CDDS_ITEMPREPAINT:
- PaintCode=CDRF_NOTIFYSUBITEMDRAW;
- break;
- case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
- {
- // COLORREF crText, crBkgnd;
- // crText= RGB(128,128,255);
- HYAMNMAIL ActualMail;
- BOOL umma;
-
- {
- struct CMailWinUserInfo *mwui;
- mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER);
- umma= mwui->UpdateMailsMessagesAccess;
- }
- ActualMail=(HYAMNMAIL)cd->nmcd.lItemlParam;
- if (!ActualMail)
- ActualMail=(HYAMNMAIL)readItemLParam(cd->nmcd.hdr.hwndFrom,cd->nmcd.dwItemSpec);
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read wait\n");
-#endif
- if (!umma)
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->MessagesAccessSO))
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read wait failed\n");
-#endif
- return 0;
- }
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read enter\n");
-#endif
- switch(ActualMail->Flags & YAMN_MSG_SPAMMASK)
- {
- case YAMN_MSG_SPAML1:
- case YAMN_MSG_SPAML2:
- cd->clrText=RGB(150,150,150);
- break;
- case YAMN_MSG_SPAML3:
- cd->clrText=RGB(200,200,200);
- cd->clrTextBk=RGB(160,160,160);
- break;
- case 0:
- if (cd->nmcd.dwItemSpec & 1)
- cd->clrTextBk=RGB(230,230,230);
- break;
- default:
- break;
- }
- if (ActualMail->Flags & YAMN_MSG_UNSEEN)
- cd->clrTextBk=RGB(220,235,250);
- PaintCode=CDRF_DODEFAULT;
-
- if (!umma)
- {
-#ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read done\n");
-#endif
- ReadDoneFcn(ActualAccount->MessagesAccessSO);
- }
-
- break;
- }
- }
- SetWindowLongPtr(hDlg,DWLP_MSGRESULT,PaintCode);
- return 1;
- }
- }
- }
- break;
-
- case WM_CONTEXTMENU:
- if ( GetWindowLongPtr(( HWND )wParam, GWLP_ID ) == IDC_LISTMAILS) {
- //MessageBox(0,"LISTHEADERS","Debug",0);
- HWND hList = GetDlgItem( hDlg, IDC_LISTMAILS );
- POINT pt = { (signed short)LOWORD( lParam ), (signed short)HIWORD( lParam ) };
- HTREEITEM hItem = 0;
- if (pt.x==-1) pt.x = 0;
- if (pt.y==-1) pt.y = 0;
- if (int numRows = ListView_GetItemCount(hList)) {
- HMENU hMenu = CreatePopupMenu();
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected"));
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All"));
- AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
- AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel"));
- int nReturnCmd = TrackPopupMenu( hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, NULL );
- DestroyMenu( hMenu );
- if (nReturnCmd>0) {
- int courRow=0;
- size_t sizeNeeded = 0;
- TCHAR from[128]={0}, subject[256]={0}, size[16]={0}, date[64]={0};
- for (courRow=0;courRow<numRows;courRow++) {
- if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue;
- ListView_GetItemText(hList, courRow, 0, from, SIZEOF(from));
- ListView_GetItemText(hList, courRow, 1, subject, SIZEOF(subject));
- ListView_GetItemText(hList, courRow, 2, size, SIZEOF(size));
- ListView_GetItemText(hList, courRow, 3, date, SIZEOF(date));
- sizeNeeded += 5+_tcslen(from)+_tcslen(subject)+_tcslen(size)+_tcslen(date);
- }
- if (sizeNeeded && OpenClipboard(hDlg)) {
- EmptyClipboard();
- HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE,(sizeNeeded+1)*sizeof(TCHAR));
- TCHAR *buff = (TCHAR *)GlobalLock(hData);
- int courPos = 0;
- for (courRow=0; courRow < numRows; courRow++) {
- if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue;
- ListView_GetItemText(hList, courRow, 0, from, SIZEOF(from));
- ListView_GetItemText(hList, courRow, 1, subject, SIZEOF(subject));
- ListView_GetItemText(hList, courRow, 2, size, SIZEOF(size));
- ListView_GetItemText(hList, courRow, 3, date, SIZEOF(date));
- courPos += mir_sntprintf(&buff[courPos], sizeNeeded + 1, _T("%s\t%s\t%s\t%s\r\n"), from, subject, size, date);
- }
- GlobalUnlock(hData);
-
- SetClipboardData(CF_UNICODETEXT,hData);
-
- CloseClipboard();
- }
- }
- }
- }
- break; // just in case
- }
- return 0;
-}
-
-LRESULT CALLBACK ListViewSubclassProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- HWND hwndParent = GetParent(hDlg);
-
- switch(msg) {
- case WM_GETDLGCODE :
- {
- LPMSG lpmsg;
- if ( ( lpmsg = (LPMSG)lParam ) != NULL ) {
- if ( lpmsg->message == WM_KEYDOWN
- && lpmsg->wParam == VK_RETURN)
- return DLGC_WANTALLKEYS;
- }
- break;
- }
- case WM_KEYDOWN:
- {
-
- BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000;
- BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000;
- BOOL isAlt = GetKeyState(VK_MENU) & 0x8000;
-
- switch (wParam)
- {
- case 'A': // ctrl-a
- if (!isAlt && !isShift && isCtrl) SendMessage(hwndParent,WM_COMMAND,IDC_BTNCHECKALL,0);
- break;
- case VK_RETURN:
- case VK_SPACE:
- if (!isAlt && !isShift && !isCtrl) SendMessage(hwndParent,WM_YAMN_SHOWSELECTED,0,0);
- break;
- case VK_DELETE:
- SendMessage(hwndParent,WM_COMMAND,IDC_BTNDEL,0);
- break;
- }
-
- break;
-
- }
- }
- return mir_callNextSubclass(hDlg, ListViewSubclassProc, msg, wParam, lParam);
-}
-
-DWORD WINAPI MailBrowser(LPVOID Param)
-{
- MSG msg;
-
- HWND hMailBrowser;
- BOOL WndFound=FALSE;
- HACCOUNT ActualAccount;
- struct MailBrowserWinParam MyParam;
-
- MyParam=*(struct MailBrowserWinParam *)Param;
- ActualAccount=MyParam.account;
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:Incrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount);
- #endif
- SCIncFcn(ActualAccount->UsingThreads);
-
-// we will not use params in stack anymore
- SetEvent(MyParam.ThreadRunningEV);
-
- __try
- {
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read wait\n");
- #endif
- if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO))
- {
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read wait failed\n");
- #endif
- return 0;
- }
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read enter\n");
- #endif
- if (!(ActualAccount->AbilityFlags & YAMN_ACC_BROWSE))
- {
- MyParam.nflags=MyParam.nflags & ~YAMN_ACC_MSG;
- MyParam.nnflags=MyParam.nnflags & ~YAMN_ACC_MSG;
- }
- if (!(ActualAccount->AbilityFlags & YAMN_ACC_POPUP))
- MyParam.nflags=MyParam.nflags & ~YAMN_ACC_POP;
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read done\n");
- #endif
- ReadDoneFcn(ActualAccount->AccountAccessSO);
-
- if (NULL != (hMailBrowser=WindowList_Find(YAMNVar.NewMailAccountWnd, (MCONTACT)ActualAccount)))
- WndFound=TRUE;
- if ((hMailBrowser==NULL) && ((MyParam.nflags & YAMN_ACC_MSG) || (MyParam.nflags & YAMN_ACC_ICO) || (MyParam.nnflags & YAMN_ACC_MSG)))
- {
- hMailBrowser=CreateDialogParamW(YAMNVar.hInst,MAKEINTRESOURCEW(IDD_DLGVIEWMESSAGES),NULL,DlgProcYAMNMailBrowser,(LPARAM)&MyParam);
- SendMessageW(hMailBrowser,WM_SETICON,(WPARAM)ICON_BIG,(LPARAM)g_LoadIconEx(2,true));
- SendMessageW(hMailBrowser,WM_SETICON,(WPARAM)ICON_SMALL,(LPARAM)g_LoadIconEx(2));
- MoveWindow(hMailBrowser,PosX,PosY,SizeX,SizeY,TRUE);
- }
-
- if (hMailBrowser != NULL)
- {
- struct CChangeContent Params={MyParam.nflags,MyParam.nnflags}; //if this thread created window, just post message to update mails
-
- SendMessageW(hMailBrowser,WM_YAMN_CHANGECONTENT,(WPARAM)ActualAccount,(LPARAM)&Params); //we ensure this will do the thread who created the browser window
- }
- else
- UpdateMails(NULL,ActualAccount,MyParam.nflags,MyParam.nnflags); //update mails without displaying or refreshing any window
-
- if ((hMailBrowser != NULL) && !WndFound) //we process message loop only for thread that created window
- {
- while(GetMessage(&msg,NULL,0,0))
- {
- if (!IsDialogMessage(hMailBrowser, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- }
-
- if ((!WndFound) && (ActualAccount->Plugin->Fcn != NULL) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != NULL) && ActualAccount->AbleToWork)
- ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr();
- }
- __finally
- {
- #ifdef DEBUG_SYNCHRO
- DebugLog(SynchroFile,"MailBrowser:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount);
- #endif
- SCDecFcn(ActualAccount->UsingThreads);
- }
- return 1;
-}
-
-INT_PTR RunMailBrowserSvc(WPARAM wParam,LPARAM lParam)
-{
- DWORD tid;
- //an event for successfull copy parameters to which point a pointer in stack for new thread
- HANDLE ThreadRunningEV;
- PYAMN_MAILBROWSERPARAM Param=(PYAMN_MAILBROWSERPARAM)wParam;
-
- if ((DWORD)lParam != YAMN_MAILBROWSERVERSION)
- return 0;
-
- if (NULL != (ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL)))
- {
- HANDLE NewThread;
-
- Param->ThreadRunningEV=ThreadRunningEV;
- if (NULL != (NewThread=CreateThread(NULL,0,MailBrowser,Param,0,&tid)))
- {
- WaitForSingleObject(ThreadRunningEV,INFINITE);
- CloseHandle(NewThread);
- }
- CloseHandle(ThreadRunningEV);
- return 1;
- }
- return 0;
-}
+/* + * This code implements window handling (new mail) + * + * (c) majvan 2002-2004 + */ +/* There can be problems when compiling this file, because in this file + * we are using both unicode and no-unicode functions and compiler does not + * like it in one file + * When you got errors, try to comment the #define <stdio.h> and compile, then + * put it back to uncommented and compile again :) + */ + +#include "../yamn.h" + +#define TIMER_FLASHING 0x09061979 +#define MAILBROWSER_MINXSIZE 200 //min size of mail browser window +#define MAILBROWSER_MINYSIZE 130 + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +char* s_MonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +bool bDate = false,bSub=false,bSize=false,bFrom=false; +int PosX=0,PosY=0,SizeX=460,SizeY=100; +int HeadSizeX = 0x2b2, HeadSizeY = 0x0b5, HeadPosX = 100, HeadPosY = 100; +int HeadSplitPos=250; // per-mils of the size +static int FromWidth=250,SubjectWidth=280,SizeWidth=50,SizeDate=205; +unsigned char optDateTime = (SHOWDATELONG | SHOWDATENOTODAY); + +struct CMailNumbersSub +{ + int Total; //any mail + int New; //uses YAMN_MSG_NEW flag + int UnSeen; //uses YAMN_MSG_UNSEEN flag +// int Browser; //uses YAMN_MSG_BROWSER flag + int BrowserUC; //uses YAMN_MSG_BROWSER flag and YAMN_MSG_UNSEEN flag + int Display; //uses YAMN_MSG_DISPLAY flag + int DisplayTC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag + int DisplayUC; //uses YAMN_MSG_DISPLAY flag and YAMN_MSG_DISPLAYC flag and YAMN_MSG_UNSEEN flag + int Popup; //uses YAMN_MSG_POPUP flag + int PopupTC; //uses YAMN_MSG_POPUPC flag + int PopupNC; //uses YAMN_MSG_POPUPC flag and YAMN_MSG_NEW flag + int PopupRun; //uses YAMN_MSG_POPUP flag and YAMN_MSG_NEW flag + int PopupSL2NC; //uses YAMN_MSG_SPAML2 flag and YAMN_MSG_NEW flag + int PopupSL3NC; //uses YAMN_MSG_SPAML3 flag and YAMN_MSG_NEW flag +// int SysTray; //uses YAMN_MSG_SYSTRAY flag + int SysTrayUC; //uses YAMN_MSG_SYSTRAY flag and YAMN_MSG_UNSEEN flag +// int Sound; //uses YAMN_MSG_SOUND flag + int SoundNC; //uses YAMN_MSG_SOUND flag and YAMN_MSG_NEW flag +// int App; //uses YAMN_MSG_APP flag + int AppNC; //uses YAMN_MSG_APP flag and YAMN_MSG_NEW flag + int EventNC; //uses YAMN_MSG_NEVENT flag and YAMN_MSG_NEW flag +}; + +struct CMailNumbers +{ + struct CMailNumbersSub Real; + struct CMailNumbersSub Virtual; +}; + +struct CMailWinUserInfo +{ + HACCOUNT Account; + int TrayIconState; + BOOL UpdateMailsMessagesAccess; + BOOL Seen; + BOOL RunFirstTime; +}; + +struct CChangeContent +{ + DWORD nflags; + DWORD nnflags; +}; + +struct CUpdateMails +{ + struct CChangeContent *Flags; + BOOL Waiting; + HANDLE Copied; +}; +struct CSortList +{ + HWND hDlg; + int iSubItem; +}; + +//Retrieves HACCOUNT, whose mails are displayed in ListMails +// hLM- handle of dialog window +// returns handle of account +inline HACCOUNT GetWindowAccount(HWND hDialog); + +//Looks to mail flags and increment mail counter (e.g. if mail is new, increments the new mail counter +// msgq- mail, which increments the counters +// MN- counnters structure +void IncrementMailCounters(HYAMNMAIL msgq,struct CMailNumbers *MN); + +enum +{ + UPDATE_FAIL=0, //function failed + UPDATE_NONE, //none update has been performed + UPDATE_OK, //some changes occured, update performed +}; +//Just looks for mail changes in account and update the mail browser window +// hDlg- dialog handle +// ActualAccount- account handle +// nflags- flags what to do when new mail arrives +// nnflags- flags what to do when no new mail arrives +// returns one of UPDATE_XXX value(not implemented yet) +int UpdateMails(HWND hDlg,HACCOUNT ActualAccount,DWORD nflags,DWORD nnflags); + +//When new mail occurs, shows window, plays sound, runs application... +// hDlg- dialog handle. Dialog of mailbrowser is already created and actions are performed over this window +// ActualAccount- handle of account, whose mails are to be notified +// MN- statistics of mails in account +// nflags- what to do or not to do (e.g. to show mailbrowser window or prohibit to show) +// nflags- flags what to do when new mail arrives +// nnflags- flags what to do when no new mail arrives +void DoMailActions(HWND hDlg,HACCOUNT ActualAccount,struct CMailNumbers *MN,DWORD nflags,DWORD nnflags); + +//Looks for items in mailbrowser and if they were deleted, delete them from browser window +// hListView- handle of listview window +// ActualAccount- handle of account, whose mails are show +// MailNumbers- pointer to structure, in which function stores numbers of mails with some property +// returns one of UPDATE_XXX value (not implemented yet) +int ChangeExistingMailStatus(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MN); + +//Adds new mails to ListView and if any new, shows multi popup (every new message is new popup window created by popup plugin) +// hListView- handle of listview window +// ActualAccount- handle of account, whose mails are show +// NewMailPopup- pointer to prepared structure for popup plugin, can be NULL if no popup show +// MailNumbers- pointer to structure, in which function stores numbers of mails with some property +// nflags- flags what to do when new mail arrives +// returns one of UPDATE_XXX value (not implemented yet) +int AddNewMailsToListView(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MailNumbers,DWORD nflags); + +//Window callback procedure for popup window (created by popup plugin) +LRESULT CALLBACK NewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam); + +//Window callback procedure for popup window (created by popup plugin) +LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam); + +//Dialog callback procedure for mail browser +INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam); + +//MailBrowser thread function creates window if needed, tray icon and plays sound +DWORD WINAPI MailBrowser(LPVOID Param); + +LRESULT CALLBACK ListViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +//Runs mail browser in new thread +INT_PTR RunMailBrowserSvc(WPARAM,LPARAM); + +#define YAMN_BROWSER_SHOWPOPUP 0x01 + + // list view items' order criteria + #define LVORDER_NOORDER -1 + #define LVORDER_STRING 0 + #define LVORDER_NUMERIC 1 + #define LVORDER_DATETIME 2 + + // list view order direction + #define LVORDER_ASCENDING 1 + #define LVORDER_NONE 0 + #define LVORDER_DESCENDING -1 + + // list view sort type + #define LVSORTPRIORITY_NONE -1 + + // List view column info. + typedef struct _SAMPLELISTVIEWCOLUMN + { + UINT uCXCol; // index + int nSortType; // sorting type (STRING = 0, NUMERIC, DATE, DATETIME) + int nSortOrder; // sorting order (ASCENDING = -1, NONE, DESCENDING) + int nPriority; // sort priority (-1 for none, 0, 1, ..., nColumns - 1 maximum) + TCHAR lpszName[128]; // column name + } SAMPLELISTVIEWCOLUMN; + + // Compare priority + typedef struct _LVCOMPAREINFO + { + int iIdx; // Index + int iPriority; // Priority + } LVCOMPAREINFO, *LPLVCOMPAREINFO; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +LPARAM readItemLParam(HWND hwnd,DWORD iItem) +{ + LVITEM item; + + item.mask = LVIF_PARAM; + item.iItem = iItem; + item.iSubItem = 0; + SendMessage(hwnd,LVM_GETITEM,0,(LPARAM)&item); + return item.lParam; +} + +inline HACCOUNT GetWindowAccount(HWND hDlg) +{ + struct CMailWinUserInfo *mwui; + + if (NULL==(mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER))) + return NULL; + return mwui->Account; +} + +void IncrementMailCounters(HYAMNMAIL msgq,struct CMailNumbers *MN) +{ + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.Total++; + else + MN->Real.Total++; + + if (msgq->Flags & YAMN_MSG_NEW) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.New++; + else + MN->Real.New++; + if (msgq->Flags & YAMN_MSG_UNSEEN) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.UnSeen++; + else + MN->Real.UnSeen++; + if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER)) == (YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.BrowserUC++; + else + MN->Real.BrowserUC++; + if (msgq->Flags & YAMN_MSG_DISPLAY) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.Display++; + else + MN->Real.Display++; + if ((msgq->Flags & (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.DisplayTC++; + else + MN->Real.DisplayTC++; + if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) == (YAMN_MSG_UNSEEN | YAMN_MSG_DISPLAYC | YAMN_MSG_DISPLAY)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.DisplayUC++; + else + MN->Real.DisplayUC++; + if (msgq->Flags & YAMN_MSG_POPUP) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.Popup++; + else + MN->Real.Popup++; + if ((msgq->Flags & YAMN_MSG_POPUPC) == YAMN_MSG_POPUPC) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.PopupTC++; + else + MN->Real.PopupTC++; + if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUPC)) == (YAMN_MSG_NEW | YAMN_MSG_POPUPC)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.PopupNC++; + else + MN->Real.PopupNC++; + if ((msgq->Flags & (YAMN_MSG_NEW | YAMN_MSG_POPUP)) == (YAMN_MSG_NEW | YAMN_MSG_POPUP)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.PopupRun++; + else + MN->Real.PopupRun++; + if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags,YAMN_MSG_SPAML2)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.PopupSL2NC++; + else + MN->Real.PopupSL2NC++; + if ((msgq->Flags & YAMN_MSG_NEW) && YAMN_MSG_SPAML(msgq->Flags,YAMN_MSG_SPAML3)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.PopupSL3NC++; + else + MN->Real.PopupSL3NC++; +/* if (msgq->MailData->Flags & YAMN_MSG_SYSTRAY) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.SysTray++; + else + MN->Real.SysTray++; +*/ if ((msgq->Flags & (YAMN_MSG_UNSEEN | YAMN_MSG_SYSTRAY)) == (YAMN_MSG_UNSEEN|YAMN_MSG_SYSTRAY)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.SysTrayUC++; + else + MN->Real.SysTrayUC++; +/* if (msgq->MailData->Flags & YAMN_MSG_SOUND) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.Sound++; + else + MN->Real.Sound++; +*/ if ((msgq->Flags & (YAMN_MSG_NEW|YAMN_MSG_SOUND)) == (YAMN_MSG_NEW|YAMN_MSG_SOUND)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.SoundNC++; + else + MN->Real.SoundNC++; +/* if (msgq->MailData->Flags & YAMN_MSG_APP) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.App++; + else + MN->Real.App++; +*/ if ((msgq->Flags & (YAMN_MSG_NEW|YAMN_MSG_APP)) == (YAMN_MSG_NEW|YAMN_MSG_APP)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.AppNC++; + else + MN->Real.AppNC++; + if ((msgq->Flags & (YAMN_MSG_NEW|YAMN_MSG_NEVENT)) == (YAMN_MSG_NEW|YAMN_MSG_NEVENT)) + if (msgq->Flags & YAMN_MSG_VIRTUAL) + MN->Virtual.EventNC++; + else + MN->Real.EventNC++; +} + +int UpdateMails(HWND hDlg,HACCOUNT ActualAccount,DWORD nflags,DWORD nnflags) +{ +#define MAILBROWSERTITLE LPGEN("%s - %d new mail messages, %d total") + + struct CMailWinUserInfo *mwui; + struct CMailNumbers MN; + + HYAMNMAIL msgq; + BOOL Loaded; + BOOL RunMailBrowser,RunPopups; + + mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER); + //now we ensure read access for account and write access for its mails + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read wait\n"); + #endif + if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read wait failed\n"); + #endif + PostMessage(hDlg,WM_DESTROY,0,0); + + return UPDATE_FAIL; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read enter\n"); + #endif + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write wait\n"); + #endif + if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write wait failed\n"); + DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read done\n"); + #endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + + PostMessage(hDlg,WM_DESTROY,0,0); + return UPDATE_FAIL; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write enter\n"); + #endif + + ZeroMemory(&MN,sizeof(MN)); + + for (msgq=(HYAMNMAIL)ActualAccount->Mails;msgq != NULL;msgq=msgq->Next) + { + if (!LoadedMailData(msgq)) //check if mail is already in memory + { + Loaded=false; + if (NULL==LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it + continue; + } + else + Loaded=true; + + IncrementMailCounters(msgq,&MN); + + if (!Loaded) + UnloadMailData(msgq); //do not keep data for mail in memory + } + + if (mwui != NULL) + mwui->UpdateMailsMessagesAccess=TRUE; + + //Now we are going to check if extracting data from mail headers are needed. + //If popups will be displayed or mailbrowser window + if ((((mwui != NULL) && !(mwui->RunFirstTime)) && + ( + ((nnflags & YAMN_ACC_MSGP) && !(MN.Real.BrowserUC+MN.Virtual.BrowserUC)) || + ((nflags & YAMN_ACC_MSGP) && (MN.Real.BrowserUC+MN.Virtual.BrowserUC)) + ) + ) || //if mail window was displayed before and flag YAMN_ACC_MSGP is set + ((nnflags & YAMN_ACC_MSG) && !(MN.Real.BrowserUC+MN.Virtual.BrowserUC)) || //if needed to run mailbrowser when no unseen and no unseen mail found + ((nflags & YAMN_ACC_MSG) && (MN.Real.BrowserUC+MN.Virtual.BrowserUC)) || //if unseen mails found, we sure run mailbrowser + ((nflags & YAMN_ACC_ICO) && (MN.Real.SysTrayUC+MN.Virtual.SysTrayUC)) + ) //if needed to run systray + RunMailBrowser=TRUE; + else RunMailBrowser=FALSE; + + if ( (nflags & YAMN_ACC_POP) && + (ActualAccount->Flags & YAMN_ACC_POPN) && + (MN.Real.PopupNC+MN.Virtual.PopupNC)) //if some popups with mails are needed to show + RunPopups=TRUE; + else RunPopups=FALSE; + + if (RunMailBrowser) + ChangeExistingMailStatus(GetDlgItem(hDlg,IDC_LISTMAILS),ActualAccount,&MN); + if (RunMailBrowser || RunPopups) + AddNewMailsToListView(hDlg==NULL ? NULL : GetDlgItem(hDlg,IDC_LISTMAILS),ActualAccount,&MN,nflags); + + if (RunMailBrowser) + { + size_t len = strlen(ActualAccount->Name)+strlen(Translate(MAILBROWSERTITLE))+10; //+10 chars for numbers + char *TitleStrA=new char[len]; + WCHAR *TitleStrW=new WCHAR[len]; + + mir_snprintf(TitleStrA, len, Translate(MAILBROWSERTITLE), ActualAccount->Name, MN.Real.DisplayUC + MN.Virtual.DisplayUC, MN.Real.Display + MN.Virtual.Display); + MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,TitleStrA,-1,TitleStrW,(int)strlen(TitleStrA)+1); + SendMessageW(hDlg,WM_SETTEXT,0,(LPARAM)TitleStrW); + delete[] TitleStrA; + delete[] TitleStrW; + } + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:Do mail actions\n"); + #endif + + DoMailActions(hDlg,ActualAccount,&MN,nflags,nnflags); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:Do mail actions done\n"); + #endif + + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_NEW,0,YAMN_MSG_NEW,YAMN_FLAG_REMOVE); //rempve the new flag + if (!RunMailBrowser) + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_UNSEEN,YAMN_MSG_STAYUNSEEN,YAMN_MSG_UNSEEN,YAMN_FLAG_REMOVE); //remove the unseen flag when it was not displayed and it has not "stay unseen" flag set + + if (mwui != NULL) + { + mwui->UpdateMailsMessagesAccess=FALSE; + mwui->RunFirstTime=FALSE; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UpdateMails:ActualAccountMsgsSO-write done\n"); + DebugLog(SynchroFile,"UpdateMails:ActualAccountSO-read done\n"); + #endif + WriteDoneFcn(ActualAccount->MessagesAccessSO); + ReadDoneFcn(ActualAccount->AccountAccessSO); + + if (RunMailBrowser) + UpdateWindow(GetDlgItem(hDlg,IDC_LISTMAILS)); + else if (hDlg != NULL) + DestroyWindow(hDlg); + + return 1; +} + +int ChangeExistingMailStatus(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MN) +{ + int i,in; + LVITEMW item; + HYAMNMAIL mail,msgq; + + in=ListView_GetItemCount(hListView); + item.mask=LVIF_PARAM; + + for (i=0;i<in;i++) + { + item.iItem=i; + item.iSubItem=0; + if (TRUE==ListView_GetItem(hListView,&item)) + mail=(HYAMNMAIL)item.lParam; + else + continue; + for (msgq=(HYAMNMAIL)ActualAccount->Mails;(msgq != NULL)&&(msgq != mail);msgq=msgq->Next); //found the same mail in account queue + if (msgq==NULL) //if mail was not found + if (TRUE==ListView_DeleteItem(hListView,i)) + { + in--;i--; + continue; + } + } + + return TRUE; +} + +void MimeDateToLocalizedDateTime(char *datein, WCHAR *dateout, int lendateout); +int AddNewMailsToListView(HWND hListView,HACCOUNT ActualAccount,struct CMailNumbers *MN,DWORD nflags) +{ + HYAMNMAIL msgq; + POPUPDATAT NewMailPopup = {0}; + + WCHAR *FromStr; + WCHAR SizeStr[20]; + WCHAR LocalDateStr[128]; + + LVITEMW item; + LVFINDINFO fi; + + int foundi,lfoundi; + struct CHeader UnicodeHeader; + BOOL Loaded,Extracted,FromStrNew=FALSE; + + ZeroMemory(&item,sizeof(item)); + ZeroMemory(&UnicodeHeader,sizeof(UnicodeHeader)); + + if (hListView != NULL) + { + item.mask=LVIF_TEXT | LVIF_PARAM; + item.iItem=0; + ZeroMemory(&fi,sizeof(fi)); + fi.flags=LVFI_PARAM; //let's go search item by lParam number + lfoundi=0; + } + + NewMailPopup.lchContact=(ActualAccount->hContact != NULL) ? ActualAccount->hContact : (MCONTACT)ActualAccount; + NewMailPopup.lchIcon=g_LoadIconEx(2); + NewMailPopup.colorBack=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupB : GetSysColor(COLOR_BTNFACE); + NewMailPopup.colorText=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupT : GetSysColor(COLOR_WINDOWTEXT); + NewMailPopup.iSeconds=ActualAccount->NewMailN.PopupTime; + + NewMailPopup.PluginWindowProc=NewMailPopupProc; + NewMailPopup.PluginData=(void *)0; //it's new mail popup + + for (msgq=(HYAMNMAIL)ActualAccount->Mails;msgq != NULL;msgq=msgq->Next,lfoundi++) + { +// now we hide mail pointer to item's lParam member. We can later use it to retrieve mail datas + + Extracted=FALSE;FromStr=NULL;FromStrNew=FALSE; + + if (hListView != NULL) + { + fi.lParam=(LPARAM)msgq; + if (-1 != (foundi=ListView_FindItem(hListView,-1,&fi))) //if mail is already in window + { + lfoundi=foundi; + continue; //do not insert any item + } + + item.iItem=lfoundi; //insert after last found item + item.lParam=(LPARAM)msgq; + } + + if (!LoadedMailData(msgq)) //check if mail is already in memory + { + Loaded=false; + if (NULL==LoadMailData(msgq)) //if we could not load mail to memory, consider this mail deleted and do not display it + continue; + } + else + Loaded=true; + + if (((hListView != NULL) && (msgq->Flags & YAMN_MSG_DISPLAY)) || + ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW))) + { + + if (!Extracted) ExtractHeader(msgq->MailData->TranslatedHeader,msgq->MailData->CP,&UnicodeHeader); + Extracted=TRUE; + + if ((UnicodeHeader.From != NULL) && (UnicodeHeader.FromNick != NULL)) { + size_t size = wcslen(UnicodeHeader.From) + wcslen(UnicodeHeader.FromNick) + 4; + FromStr = new WCHAR[size]; + mir_sntprintf(FromStr, size, L"%s <%s>", UnicodeHeader.FromNick, UnicodeHeader.From); + FromStrNew = TRUE; + } + else if (UnicodeHeader.From != NULL) + FromStr=UnicodeHeader.From; + else if (UnicodeHeader.FromNick != NULL) + FromStr=UnicodeHeader.FromNick; + else if (UnicodeHeader.ReturnPath != NULL) + FromStr=UnicodeHeader.ReturnPath; + + if (NULL==FromStr) { + FromStr = L""; + FromStrNew = FALSE; + } + } + + if ((hListView != NULL) && (msgq->Flags & YAMN_MSG_DISPLAY)) { + item.iSubItem = 0; + item.pszText = FromStr; + item.iItem = SendMessageW(hListView,LVM_INSERTITEMW,0,(LPARAM)&item); + + item.iSubItem = 1; + item.pszText = (NULL != UnicodeHeader.Subject ? UnicodeHeader.Subject : (WCHAR*)L""); + SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item); + + item.iSubItem = 2; + mir_sntprintf(SizeStr, SIZEOF(SizeStr), L"%d kB", msgq->MailData->Size / 1024); + item.pszText = SizeStr; + SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item); + + item.iSubItem = 3; + item.pszText = L""; + + for (CMimeItem *heads = msgq->MailData->TranslatedHeader; heads != NULL; heads = heads->Next) { + if ( !_stricmp(heads->name, "Date")) { + MimeDateToLocalizedDateTime(heads->value, LocalDateStr, 128); + item.pszText = LocalDateStr; + break; + } + } + SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item); + } + + if ((nflags & YAMN_ACC_POP) && (ActualAccount->Flags & YAMN_ACC_POPN) && (msgq->Flags & YAMN_MSG_POPUP) && (msgq->Flags & YAMN_MSG_NEW)) { + lstrcpyn(NewMailPopup.lptzContactName, FromStr, SIZEOF(NewMailPopup.lptzContactName)); + lstrcpyn(NewMailPopup.lptzText, UnicodeHeader.Subject, SIZEOF(NewMailPopup.lptzText)); + + PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)malloc(sizeof(YAMN_MAILSHOWPARAM)); + if (MailParam) { + MailParam->account = ActualAccount; + MailParam->mail = msgq; + MailParam->ThreadRunningEV = 0; + NewMailPopup.PluginData = MailParam; + PUAddPopupT(&NewMailPopup); + } + } + + if ((msgq->Flags & YAMN_MSG_UNSEEN) && (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN)) + CallService(MS_KBDNOTIFY_EVENTSOPENED,1,NULL); + + if (FromStrNew) + delete[] FromStr; + + if (Extracted) + { + DeleteHeaderContent(&UnicodeHeader); + ZeroMemory(&UnicodeHeader,sizeof(UnicodeHeader)); + } + + if (!Loaded) + { + SaveMailData(msgq); + UnloadMailData(msgq); //do not keep data for mail in memory + } + } + + return TRUE; +} + +void DoMailActions(HWND hDlg,HACCOUNT ActualAccount,struct CMailNumbers *MN,DWORD nflags,DWORD nnflags) +{ + char *NotIconText = Translate("- new mail message(s)"); + NOTIFYICONDATA nid; + + ZeroMemory(&nid,sizeof(nid)); + + if (MN->Real.EventNC+MN->Virtual.EventNC) + NotifyEventHooks(hNewMailHook,0,0); + + if ((nflags & YAMN_ACC_KBN) && (MN->Real.PopupRun+MN->Virtual.PopupRun)) + { + CallService(MS_KBDNOTIFY_STARTBLINK,(WPARAM)MN->Real.PopupNC+MN->Virtual.PopupNC,NULL); + } + + if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun+MN->Virtual.PopupRun)) + { + char sMsg[250]; + mir_snprintf(sMsg, 249, Translate("%s : %d new mail message(s), %d total"), ActualAccount->Name, MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC); + if (!(nflags & YAMN_ACC_CONTNOEVENT)) { + CLISTEVENT cEvent; + cEvent.cbSize = sizeof(CLISTEVENT); + cEvent.hContact = ActualAccount->hContact; + cEvent.hIcon = g_LoadIconEx(2); + cEvent.hDbEvent = (HANDLE)ActualAccount->hContact; + cEvent.lParam = (LPARAM) ActualAccount->hContact; + cEvent.pszService = MS_YAMN_CLISTDBLCLICK; + cEvent.pszTooltip = sMsg; + cEvent.flags = 0; + CallServiceSync(MS_CLIST_ADDEVENT, 0,(LPARAM)&cEvent); + } + db_set_s(ActualAccount->hContact, "CList", "StatusMsg", sMsg); + + if (nflags & YAMN_ACC_CONTNICK) + { + db_set_s(ActualAccount->hContact, YAMN_DBMODULE, "Nick",sMsg); + } + } + + if ((nflags & YAMN_ACC_POP) && + !(ActualAccount->Flags & YAMN_ACC_POPN) && + (MN->Real.PopupRun+MN->Virtual.PopupRun)) + { + POPUPDATAT NewMailPopup ={0}; + + NewMailPopup.lchContact=(ActualAccount->hContact != NULL) ? ActualAccount->hContact : (MCONTACT)ActualAccount; + NewMailPopup.lchIcon=g_LoadIconEx(2); + NewMailPopup.colorBack=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupB : GetSysColor(COLOR_BTNFACE); + NewMailPopup.colorText=nflags & YAMN_ACC_POPC ? ActualAccount->NewMailN.PopupT : GetSysColor(COLOR_WINDOWTEXT); + NewMailPopup.iSeconds=ActualAccount->NewMailN.PopupTime; + + NewMailPopup.PluginWindowProc = NewMailPopupProc; + NewMailPopup.PluginData = (void *)0; //multiple popups + + lstrcpyn(NewMailPopup.lptzContactName, _A2T(ActualAccount->Name), SIZEOF(NewMailPopup.lptzContactName)); + mir_sntprintf(NewMailPopup.lptzText, SIZEOF(NewMailPopup.lptzText), TranslateT("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC); + PUAddPopupT(&NewMailPopup); + } + + //destroy tray icon if no new mail + if ((MN->Real.SysTrayUC+MN->Virtual.SysTrayUC==0) && (hDlg != NULL)) + { + nid.hWnd=hDlg; + nid.uID=0; + Shell_NotifyIcon(NIM_DELETE,&nid); + } + + //and remove the event + if ((nflags & YAMN_ACC_CONT) && (!(nflags & YAMN_ACC_CONTNOEVENT)) && (MN->Real.UnSeen + MN->Virtual.UnSeen==0)) { + CallService(MS_CLIST_REMOVEEVENT,(WPARAM)ActualAccount->hContact,(LPARAM)ActualAccount->hContact); + } + + if ((MN->Real.BrowserUC+MN->Virtual.BrowserUC==0) && (hDlg != NULL)) + { + if (!IsWindowVisible(hDlg) && !(nflags & YAMN_ACC_MSG)) + PostMessage(hDlg,WM_DESTROY,0,0); //destroy window if no new mail and window is not visible + if (nnflags & YAMN_ACC_MSG) //if no new mail and msg should be executed + { + SetForegroundWindow(hDlg); + ShowWindow(hDlg,SW_SHOWNORMAL); + } + } + else + if (hDlg != NULL) //else insert icon and set window if new mails + { + SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_SCROLL,0,(LPARAM)0x7ffffff); + + if ((nflags & YAMN_ACC_ICO) && (MN->Real.SysTrayUC+MN->Virtual.SysTrayUC)) + { + char* src; + TCHAR *dest; + int i; + + for (src=ActualAccount->Name,dest=nid.szTip,i=0;(*src != (TCHAR)0) && (i+1<sizeof(nid.szTip));*dest++=*src++); + for (src=NotIconText;(*src != (TCHAR)0) && (i+1<sizeof(nid.szTip));*dest++=*src++); + *dest=(TCHAR)0; + nid.cbSize=sizeof(NOTIFYICONDATA); + nid.hWnd=hDlg; + nid.hIcon=g_LoadIconEx(2); + nid.uID=0; + nid.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP; + nid.uCallbackMessage=WM_YAMN_NOTIFYICON; + Shell_NotifyIcon(NIM_ADD,&nid); + SetTimer(hDlg,TIMER_FLASHING,500,NULL); + } + if (nflags & YAMN_ACC_MSG) //if no new mail and msg should be executed + ShowWindow(hDlg,SW_SHOWNORMAL); + } + + if (MN->Real.AppNC+MN->Virtual.AppNC != 0) + { + if (nflags & YAMN_ACC_APP) + { + PROCESS_INFORMATION pi; + STARTUPINFOW si; + ZeroMemory(&si,sizeof(si)); + si.cb=sizeof(si); + + if (ActualAccount->NewMailN.App != NULL) + { + WCHAR *Command; + if (ActualAccount->NewMailN.AppParam != NULL) + Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+wcslen(ActualAccount->NewMailN.AppParam)+6]; + else + Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+6]; + + if (Command != NULL) + { + lstrcpyW(Command,L"\""); + lstrcatW(Command,ActualAccount->NewMailN.App); + lstrcatW(Command,L"\" "); + if (ActualAccount->NewMailN.AppParam != NULL) + lstrcatW(Command,ActualAccount->NewMailN.AppParam); + CreateProcessW(NULL,Command,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi); + delete[] Command; + } + } + } + } + + if (MN->Real.SoundNC+MN->Virtual.SoundNC != 0) + if (nflags & YAMN_ACC_SND) + CallService(MS_SKIN_PLAYSOUND,0,(LPARAM)YAMN_NEWMAILSOUND); + + if ((nnflags & YAMN_ACC_POP) && (MN->Real.PopupRun+MN->Virtual.PopupRun==0)) + { + POPUPDATAT NoNewMailPopup; + + NoNewMailPopup.lchContact=(ActualAccount->hContact != NULL) ? ActualAccount->hContact : (MCONTACT)ActualAccount; + NoNewMailPopup.lchIcon=g_LoadIconEx(1); + NoNewMailPopup.colorBack=ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? ActualAccount->NoNewMailN.PopupB : GetSysColor(COLOR_BTNFACE); + NoNewMailPopup.colorText=ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? ActualAccount->NoNewMailN.PopupT : GetSysColor(COLOR_WINDOWTEXT); + NoNewMailPopup.iSeconds=ActualAccount->NoNewMailN.PopupTime; + + NoNewMailPopup.PluginWindowProc=NoNewMailPopupProc; + NoNewMailPopup.PluginData=(void *)0; //it's not new mail popup + + lstrcpyn(NoNewMailPopup.lptzContactName,_A2T(ActualAccount->Name),SIZEOF(NoNewMailPopup.lptzContactName)); + if (MN->Real.PopupSL2NC+MN->Virtual.PopupSL2NC) + mir_sntprintf(NoNewMailPopup.lptzText, SIZEOF(NoNewMailPopup.lptzText), TranslateT("No new mail message, %d spam(s)"), MN->Real.PopupSL2NC + MN->Virtual.PopupSL2NC); + else + lstrcpyn(NoNewMailPopup.lptzText,TranslateT("No new mail message"),SIZEOF(NoNewMailPopup.lptzText)); + PUAddPopupT(&NoNewMailPopup); + } + + if ((nflags & YAMN_ACC_CONT) && (MN->Real.PopupRun+MN->Virtual.PopupRun==0)) + { + if (ActualAccount->hContact != NULL) + { + if (MN->Real.PopupTC+MN->Virtual.PopupTC) + { + char tmp[255]; + mir_snprintf(tmp, SIZEOF(tmp), Translate("%d new mail message(s), %d total"), MN->Real.PopupNC + MN->Virtual.PopupNC, MN->Real.PopupTC + MN->Virtual.PopupTC); + db_set_s(ActualAccount->hContact, "CList", "StatusMsg", tmp); + } + else db_set_s(ActualAccount->hContact, "CList", "StatusMsg", Translate("No new mail message")); + + if (nflags & YAMN_ACC_CONTNICK) + db_set_s(ActualAccount->hContact, YAMN_DBMODULE, "Nick", ActualAccount->Name); + } + } + return; +} + +DWORD WINAPI ShowEmailThread(LPVOID Param); +LRESULT CALLBACK NewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ + INT_PTR PluginParam=0; + switch(msg) + { + case WM_COMMAND: + //if clicked and it's new mail popup window + if ((HIWORD(wParam)==STN_CLICKED) && (-1 != (PluginParam=CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hWnd,(LPARAM)&PluginParam)))) + { + MCONTACT hContact = 0; + HACCOUNT Account; + if (PluginParam) { + PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM; + memcpy(MailParam,(PINT_PTR)PluginParam,sizeof(YAMN_MAILSHOWPARAM)); + hContact = MailParam->account->hContact; + Account = MailParam->account; + if (NULL != (MailParam->ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) { + HANDLE NewThread; + if (NULL != (NewThread=CreateThread(NULL,0,ShowEmailThread,(LPVOID)MailParam,0,NULL))) + { + CloseHandle(NewThread); + } + CloseHandle(MailParam->ThreadRunningEV); + } + //delete MailParam; + } else { + DBVARIANT dbv; + + hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0); + + if (!db_get((MCONTACT)hContact,YAMN_DBMODULE,"Id",&dbv)) + { + Account=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal); + db_free(&dbv); + } + else + Account = (HACCOUNT)hContact; //???? + + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read wait\n"); + #endif + if (WAIT_OBJECT_0==WaitToReadFcn(Account->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter\n"); + #endif + switch(msg) + { + case WM_COMMAND: + { + YAMN_MAILBROWSERPARAM Param={(HANDLE)0,Account, + (Account->NewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG, + (Account->NoNewMailN.Flags & ~YAMN_ACC_POP) | YAMN_ACC_MSGP | YAMN_ACC_MSG}; + + RunMailBrowserSvc((WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION); + } + break; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read done\n"); + #endif + ReadDoneFcn(Account->AccountAccessSO); + } + #ifdef DEBUG_SYNCHRO + else + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter failed\n"); + #endif + } + if ((Account->NewMailN.Flags & YAMN_ACC_CONT) && !(Account->NewMailN.Flags & YAMN_ACC_CONTNOEVENT)) { + CallService(MS_CLIST_REMOVEEVENT, hContact, hContact); + } + } + // fall through + case WM_CONTEXTMENU: + SendMessageW(hWnd,UM_DESTROYPOPUP,0,0); + break; + case UM_FREEPLUGINDATA:{ + PYAMN_MAILSHOWPARAM mpd = (PYAMN_MAILSHOWPARAM)PUGetPluginData(hWnd); + MCONTACT hContact = 0; + if ((mpd) && (INT_PTR)mpd != -1)free(mpd); + return FALSE; + } + case UM_INITPOPUP: + //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups. + WindowList_Add(YAMNVar.MessageWnds,hWnd,NULL); + break; + case UM_DESTROYPOPUP: + WindowList_Remove(YAMNVar.MessageWnds,hWnd); + break; + case WM_YAMN_STOPACCOUNT: + { + HACCOUNT ActualAccount; + MCONTACT hContact; + DBVARIANT dbv; + + hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0); + + if (!db_get((MCONTACT) hContact,YAMN_DBMODULE,"Id",&dbv)) + { + ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal); + db_free(&dbv); + } + else + ActualAccount = (HACCOUNT) hContact; + + if ((HACCOUNT)wParam != ActualAccount) + break; + DestroyWindow(hWnd); + return 0; + } + case WM_NOTIFY: + default: + break; + } + return DefWindowProc(hWnd,msg,wParam,lParam); +} + +LRESULT CALLBACK NoNewMailPopupProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) + { + case WM_COMMAND: + if ((HIWORD(wParam)==STN_CLICKED) && (msg==WM_COMMAND)) + { + HACCOUNT ActualAccount; + MCONTACT hContact; + DBVARIANT dbv; + + hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0); + + if (!db_get((MCONTACT)hContact,YAMN_DBMODULE,"Id",&dbv)) + { + ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal); + db_free(&dbv); + } + else + ActualAccount = (HACCOUNT) hContact; + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read wait\n"); + #endif + if (WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter\n"); + #endif + switch(msg) + { + case WM_COMMAND: + { + YAMN_MAILBROWSERPARAM Param={(HANDLE)0,ActualAccount,ActualAccount->NewMailN.Flags,ActualAccount->NoNewMailN.Flags,0}; + + Param.nnflags=Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account + Param.nnflags=Param.nnflags & ~YAMN_ACC_POP; + + Param.nflags=Param.nflags | YAMN_ACC_MSG; //show mails in account even no new mail in account + Param.nflags=Param.nflags & ~YAMN_ACC_POP; + + RunMailBrowserSvc((WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION); + } + break; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read done\n"); + #endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + #ifdef DEBUG_SYNCHRO + else + DebugLog(SynchroFile,"PopupProc:LEFTCLICK:ActualAccountSO-read enter failed\n"); + #endif + SendMessageW(hWnd,UM_DESTROYPOPUP,0,0); + } + break; + + case WM_CONTEXTMENU: + SendMessageW(hWnd,UM_DESTROYPOPUP,0,0); + break; + + case UM_FREEPLUGINDATA: + //Here we'd free our own data, if we had it. + return FALSE; + case UM_INITPOPUP: + //This is the equivalent to WM_INITDIALOG you'd get if you were the maker of dialog popups. + WindowList_Add(YAMNVar.MessageWnds,hWnd,NULL); + break; + case UM_DESTROYPOPUP: + WindowList_Remove(YAMNVar.MessageWnds,hWnd); + break; + case WM_YAMN_STOPACCOUNT: + { + HACCOUNT ActualAccount; + MCONTACT hContact; + DBVARIANT dbv; + + hContact=(MCONTACT)CallService(MS_POPUP_GETCONTACT,(WPARAM)hWnd,0); + + if (!db_get((MCONTACT) hContact,YAMN_DBMODULE,"Id",&dbv)) + { + ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal); + db_free(&dbv); + } + else + ActualAccount = (HACCOUNT) hContact; + + if ((HACCOUNT)wParam != ActualAccount) + break; + + DestroyWindow(hWnd); + return 0; + } + case WM_NOTIFY: +/* switch(((LPNMHDR)lParam)->code) + { + case NM_CLICK: + { + } + } + break; +*/ default: + break; + } + return DefWindowProc(hWnd,msg,wParam,lParam); +} + +#ifdef __GNUC__ +//number of 100 ns periods between FILETIME 0 (1601/01/01 00:00:00.0000000) and TIMESTAMP 0 (1970/01/01 00:00:00) +#define NUM100NANOSEC 116444736000000000ULL +//The biggest time Get[Date|Time]Format can handle (Fri, 31 Dec 30827 23:59:59.9999999) +#define MAXFILETIME 0x7FFF35F4F06C7FFFULL +#else +#define NUM100NANOSEC 116444736000000000 +#define MAXFILETIME 0x7FFF35F4F06C7FFF +#endif + +ULONGLONG MimeDateToFileTime(char *datein) +{ + char *day=0, *month=0, *year=0, *time=0, *shift=0; + SYSTEMTIME st; + ULONGLONG res=0; + int wShiftSeconds = CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,0,0); + GetLocalTime(&st); + //datein = "Xxx, 1 Jan 2060 5:29:1 +0530 XXX"; + //datein = "Xxx, 1 Jan 2060 05:29:10 "; + //datein = " ManySpaces 1.5 Jan 2060 05::"; + //datein = "Xxx, 35 February 20 :29:10 "; + //datein = "01.12.2007 (22:38:17)"; // + if (datein) { + char tmp [64]; + while ( datein[0]==' ') datein++; // eat leading spaces + strncpy(tmp,datein,63); tmp [63]=0; + if (atoi(tmp)) { // Parseable integer on DayOfWeek field? Buggy mime date. + day = tmp; + } else { + int i = 0; + while (tmp[i]==' ')i++; if (day = strchr(&tmp[i],' ')) {day[0]=0; day++;} + } + if (day) {while ( day[0]==' ') day++;if (month= strchr(day, ' ')) {month[0]=0; month++;}} + if (month) {while (month[0]==' ')month++;if (year = strchr(month,' ')) { year[0]=0; year++;}} + if (year) {while ( year[0]==' ') year++;if (time = strchr(year, ' ')) { time[0]=0; time++;}} + if (time) {while ( time[0]==' ') time++;if (shift= strchr(time, ' ')) {shift[0]=0; shift++;shift[5]=0;}} + + if (year) { + st.wYear = atoi(year); + if (strlen(year)<4) if (st.wYear<70)st.wYear += 2000; else st.wYear += 1900; + }; + if (month) for (int i=0;i<12;i++) if (strncmp(month,s_MonthNames[i],3)==0) {st.wMonth = i + 1; break;} + if (day) st.wDay = atoi(day); + if (time) { + char *h, *m, *s; + h = time; + if (m = strchr(h,':')) { + m[0]=0; m++; + if (s = strchr(m,':')) {s[0] = 0; s++;} + } else s=0; + st.wHour = atoi(h); + st.wMinute = m?atoi(m):0; + st.wSecond = s?atoi(s):0; + } else {st.wHour=st.wMinute=st.wSecond=0;} + + if (shift) { + if (strlen(shift)<4) { + //has only hour + wShiftSeconds = (atoi(shift))*3600; + } else { + char *smin = shift + strlen(shift)-2; + int ismin = atoi(smin); + smin[0] = 0; + int ishour = atoi(shift); + wShiftSeconds = (ishour*60+(ishour<0?-1:1)*ismin)*60; + } + } + } // if (datein) + FILETIME ft; + if (SystemTimeToFileTime(&st,&ft)) { + res = ((ULONGLONG)ft.dwHighDateTime<<32)|((ULONGLONG)ft.dwLowDateTime); + LONGLONG w100nano = Int32x32To64((DWORD)wShiftSeconds,10000000); + res -= w100nano; + }else{ + res=0; + } + return res; +} + +void FileTimeToLocalizedDateTime(LONGLONG filetime, WCHAR *dateout, int lendateout) +{ + int localeID = CallService(MS_LANGPACK_GETLOCALE,0,0); + //int localeID = MAKELCID(LANG_URDU, SORT_DEFAULT); + if (localeID==CALLSERVICE_NOTFOUND) localeID=LOCALE_USER_DEFAULT; + if (filetime>MAXFILETIME) filetime = MAXFILETIME; + else if (filetime<=0) { + wcsncpy(dateout,TranslateW(L"Invalid"),lendateout); + return; + } + SYSTEMTIME st; + WORD wTodayYear, wTodayMonth, wTodayDay; + FILETIME ft; + BOOL willShowDate = !(optDateTime&SHOWDATENOTODAY); + if (!willShowDate) { + GetLocalTime(&st); + wTodayYear = st.wYear; + wTodayMonth = st.wMonth; + wTodayDay = st.wDay; + } + ft.dwLowDateTime = (DWORD)filetime; + ft.dwHighDateTime = (DWORD)(filetime >> 32); + FILETIME localft; + if (!FileTimeToLocalFileTime(&ft,&localft)) { + // this should never happen + wcsncpy(dateout,L"Incorrect FileTime",lendateout); + } else { + if (!FileTimeToSystemTime(&localft,&st)) { + // this should never happen + wcsncpy(dateout,L"Incorrect LocalFileTime",lendateout); + } else { + dateout[lendateout-1]=0; + int templen = 0; + if (!willShowDate) willShowDate = (wTodayYear != st.wYear)||(wTodayMonth != st.wMonth)||(wTodayDay != st.wDay); + if (willShowDate) { + templen = GetDateFormatW(localeID,(optDateTime&SHOWDATELONG)?DATE_LONGDATE:DATE_SHORTDATE,&st,NULL,dateout,lendateout-2); + dateout[templen-1] = ' '; + } + if (templen<(lendateout-1)) { + GetTimeFormatW(localeID,(optDateTime&SHOWDATENOSECONDS)?TIME_NOSECONDS:0,&st,NULL,&dateout[templen],lendateout-templen-1); + } + } + } +} + +void MimeDateToLocalizedDateTime(char *datein, WCHAR *dateout, int lendateout) +{ + ULONGLONG ft = MimeDateToFileTime(datein); + FileTimeToLocalizedDateTime(ft,dateout,lendateout); +} + +int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2,LPARAM lParamSort ) { + if (lParam1 == NULL || lParam2 == NULL) + return 0; + + int nResult = 0; + char *str1; + char *str2; + HYAMNMAIL email1 = (HYAMNMAIL)lParam1; + HYAMNMAIL email2 = (HYAMNMAIL)lParam2; + struct CShortHeader Header1; + struct CShortHeader Header2; + ZeroMemory(&Header1,sizeof(Header1)); + ZeroMemory(&Header2,sizeof(Header2)); + + try { + ExtractShortHeader(email1->MailData->TranslatedHeader,&Header1); + ExtractShortHeader(email2->MailData->TranslatedHeader,&Header2); + + switch((int)lParamSort) + { + case 0: //From + if (Header1.FromNick == NULL) + str1 = Header1.From; + else str1 = Header1.FromNick; + + if (Header2.FromNick == NULL) + str2 = Header2.From; + else str2 = Header2.FromNick; + + nResult = strcmp(str1, str2); + + if (bFrom) nResult = -nResult; + break; + case 1: //Subject + if (Header1.Subject == NULL) + str1 = " "; + else str1 = Header1.Subject; + + if (Header2.Subject == NULL) + str2 = " "; + else str2 = Header2.Subject; + + nResult = strcmp(str1, str2); + + if (bSub) nResult = -nResult; + break; + case 2: //Size + if (email1->MailData->Size == email2->MailData->Size) nResult = 0; + if (email1->MailData->Size > email2->MailData->Size) nResult = 1; + if (email1->MailData->Size < email2->MailData->Size) nResult = -1; + + if (bSize) nResult = -nResult; + break; + + case 3: //Date + { + ULONGLONG ts1 = 0, ts2 = 0; + ts1 = MimeDateToFileTime(Header1.Date); + ts2 = MimeDateToFileTime(Header2.Date); + if (ts1 > ts2) nResult = 1; + else if (ts1 < ts2) nResult = -1; + else nResult = 0; + } + if (bDate) nResult = -nResult; + break; + + default: + if (Header1.Subject == NULL) str1 = " "; + else str1 = Header1.Subject; + + if (Header2.Subject == NULL) str2 = " "; + else str2 = Header2.Subject; + + nResult = strcmp(str1, str2); + break; + } + //MessageBox(NULL,str1,str2,0); + } + catch( ... ) + { + } + + //free mem + DeleteShortHeaderContent(&Header1); + DeleteShortHeaderContent(&Header2); + return nResult; + +} + +HCURSOR hCurSplitNS, hCurSplitWE; +#define DM_SPLITTERMOVED (WM_USER+15) + +static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_NCHITTEST: + return HTCLIENT; + + case WM_SETCURSOR: + SetCursor(hCurSplitNS); + return TRUE; + + case WM_LBUTTONDOWN: + SetCapture(hwnd); + return 0; + + case WM_MOUSEMOVE: + if (GetCapture() == hwnd) { + RECT rc; + GetClientRect(hwnd, &rc); + SendMessage(GetParent(hwnd), DM_SPLITTERMOVED, (short) HIWORD(GetMessagePos()) + rc.bottom / 2, (LPARAM) hwnd); + } + return 0; + + case WM_LBUTTONUP: + ReleaseCapture(); + return 0; + } + return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam); +} + +void ConvertCodedStringToUnicode(char *stream,WCHAR **storeto,DWORD cp,int mode); +int ConvertStringToUnicode(char *stream,unsigned int cp,WCHAR **out); + +INT_PTR CALLBACK DlgProcYAMNShowMessage(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + { + PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM)lParam; + WCHAR *iHeaderW=NULL; + WCHAR *iValueW=NULL; + int StrLen; + HWND hListView = GetDlgItem(hDlg,IDC_LISTHEADERS); + mir_subclassWindow(GetDlgItem(hDlg, IDC_SPLITTER), SplitterSubclassProc); + SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)MailParam); + SendMessageW(hDlg,WM_SETICON,(WPARAM)ICON_BIG,(LPARAM)g_LoadIconEx(2, true)); + SendMessageW(hDlg,WM_SETICON,(WPARAM)ICON_SMALL,(LPARAM)g_LoadIconEx(2)); + + ListView_SetUnicodeFormat(hListView,TRUE); + ListView_SetExtendedListViewStyle(hListView,LVS_EX_FULLROWSELECT); + + StrLen=MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Header"),-1,NULL,0); + iHeaderW=new WCHAR[StrLen+1]; + MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Header"),-1,iHeaderW,StrLen); + + StrLen=MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Value"),-1,NULL,0); + iValueW=new WCHAR[StrLen+1]; + MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,Translate("Value"),-1,iValueW,StrLen); + + LVCOLUMNW lvc0={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,130,iHeaderW,0,0}; + LVCOLUMNW lvc1={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,400,iValueW,0,0}; + SendMessageW(hListView,LVM_INSERTCOLUMNW,0,(LPARAM)&lvc0); + SendMessageW(hListView,LVM_INSERTCOLUMNW,1,(LPARAM)&lvc1); + if (NULL != iHeaderW) + delete[] iHeaderW; + if (NULL != iValueW) + delete[] iValueW; + + //WindowList_Add(YAMNVar.MessageWnds,hDlg,NULL); + //WindowList_Add(YAMNVar.NewMailAccountWnd,hDlg,ActualAccount); + SendMessage(hDlg,WM_YAMN_CHANGECONTENT,0,(LPARAM)MailParam); + MoveWindow(hDlg,HeadPosX,HeadPosY,HeadSizeX,HeadSizeY,0); + ShowWindow(hDlg,SW_SHOWNORMAL); + } + break; + + case WM_YAMN_CHANGECONTENT: + { + PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM) + (lParam?lParam:GetWindowLongPtr(hDlg,DWLP_USER)); + HWND hListView = GetDlgItem(hDlg,IDC_LISTHEADERS); + HWND hEdit = GetDlgItem(hDlg,IDC_EDITBODY); + //do not redraw + SendMessage(hListView, WM_SETREDRAW, 0, 0); + ListView_DeleteAllItems(hListView); + struct CMimeItem *Header; + LVITEMW item; + item.mask=LVIF_TEXT | LVIF_PARAM; + WCHAR *From=0,*Subj=0; + char *contentType=0, *transEncoding=0, *body=0; //should not be delete[]-ed + for (Header=MailParam->mail->MailData->TranslatedHeader;Header != NULL;Header=Header->Next) + { + WCHAR *str1 = 0; + WCHAR *str2 = 0; + WCHAR str_nul[2] = {0}; + if (!body) if (!_stricmp(Header->name,"Body")) {body = Header->value; continue;} + if (!contentType) if (!_stricmp(Header->name,"Content-Type")) contentType = Header->value; + if (!transEncoding) if (!_stricmp(Header->name,"Content-Transfer-Encoding")) transEncoding = Header->value; + //ConvertCodedStringToUnicode(Header->name,&str1,MailParam->mail->MailData->CP,1); + { + int streamsize = MultiByteToWideChar(20127,0,Header->name,-1,NULL,0); + str1 = (WCHAR *)malloc(sizeof(WCHAR) * (streamsize + 1)); + MultiByteToWideChar(20127,0,Header->name,-1,str1,streamsize);//US-ASCII + } + ConvertCodedStringToUnicode(Header->value,&str2,MailParam->mail->MailData->CP,1); + if (!str2) { str2 = (WCHAR *)str_nul; }// the header value may be NULL + if (!From) if (!_stricmp(Header->name,"From")) { + From =new WCHAR[wcslen(str2)+1]; + wcscpy(From,str2); + } + if (!Subj) if (!_stricmp(Header->name,"Subject")) { + Subj =new WCHAR[wcslen(str2)+1]; + wcscpy(Subj,str2); + } + //if (!hasBody) if (!strcmp(Header->name,"Body")) hasBody = true; + int count = 0; WCHAR **split=0; + int ofs = 0; + while (str2[ofs]) { + if ((str2[ofs]==0x266A)||(str2[ofs]==0x25D9)||(str2[ofs]==0x25CB)|| + (str2[ofs]==0x09)||(str2[ofs]==0x0A)||(str2[ofs]==0x0D))count++; + ofs++; + } + split=new WCHAR*[count+1]; + count=0; ofs=0; + split[0]=str2; + while (str2[ofs]) { + if ((str2[ofs]==0x266A)||(str2[ofs]==0x25D9)||(str2[ofs]==0x25CB)|| + (str2[ofs]==0x09)||(str2[ofs]==0x0A)||(str2[ofs]==0x0D)) { + if (str2[ofs-1]) { + count++; + } + split[count]=(WCHAR *)(str2+ofs+1); + str2[ofs]=0; + } + ofs++; + }; + + if (!_stricmp(Header->name,"From")||!_stricmp(Header->name,"To")||!_stricmp(Header->name,"Date")||!_stricmp(Header->name,"Subject")) + item.iItem = 0; + else + item.iItem = 999; + for (int i=0;i<=count;i++) { + item.iSubItem=0; + if (i==0) + item.pszText=str1; + else { + item.iItem++; + item.pszText=0; + } + item.iItem=SendMessageW(hListView,LVM_INSERTITEMW,0,(LPARAM)&item); + item.iSubItem=1; + item.pszText=str2?split[i]:0; + SendMessageW(hListView,LVM_SETITEMTEXTW,(WPARAM)item.iItem,(LPARAM)&item); + } + delete[] split; + + if (str1) + free(str1); + if (str2 != (WCHAR *)str_nul) + free(str2); + } + if (body) { + WCHAR *bodyDecoded = 0; + char *localBody=0; + if (contentType) { + if (!_strnicmp(contentType,"text",4)) { + if (transEncoding) { + if (!_stricmp(transEncoding,"base64")) { + int size = (int)strlen(body)*3/4+5; + localBody = new char[size+1]; + DecodeBase64(body,localBody,size); + } else if (!_stricmp(transEncoding,"quoted-printable")) { + int size = (int)strlen(body)+2; + localBody = new char[size+1]; + DecodeQuotedPrintable(body,localBody,size,FALSE); + } + } + } else if (!_strnicmp(contentType,"multipart/",10)) { + char *bondary=NULL; + if (NULL != (bondary=ExtractFromContentType(contentType,"boundary="))) + { + bodyDecoded = ParseMultipartBody(body,bondary); + delete[] bondary; + } + } + } + if (!bodyDecoded)ConvertStringToUnicode(localBody?localBody:body,MailParam->mail->MailData->CP,&bodyDecoded); + SendMessageW(hEdit,WM_SETTEXT,0,(LPARAM)bodyDecoded); + delete[] bodyDecoded; + if (localBody) delete[] localBody; + SetFocus(hEdit); + } + if (!(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)) { + MailParam->mail->Flags |= YAMN_MSG_BODYREQUESTED; + CallService(MS_YAMN_ACCOUNTCHECK,(WPARAM)MailParam->account,0); + } else { + if (MailParam->mail->Flags & YAMN_MSG_UNSEEN) { + MailParam->mail->Flags&=~YAMN_MSG_UNSEEN; //mark the message as seen + HWND hMailBrowser; + if (hMailBrowser=WindowList_Find(YAMNVar.NewMailAccountWnd, (MCONTACT)MailParam->account)) { + struct CChangeContent Params={MailParam->account->NewMailN.Flags|YAMN_ACC_MSGP,MailParam->account->NoNewMailN.Flags|YAMN_ACC_MSGP}; + SendMessageW(hMailBrowser,WM_YAMN_CHANGECONTENT,(WPARAM)MailParam->account,(LPARAM)&Params); + } + else UpdateMails(NULL,MailParam->account,MailParam->account->NewMailN.Flags,MailParam->account->NoNewMailN.Flags); + } + } + ShowWindow(GetDlgItem(hDlg, IDC_SPLITTER),(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)?SW_SHOW:SW_HIDE); + ShowWindow(hEdit,(MailParam->mail->Flags & YAMN_MSG_BODYRECEIVED)?SW_SHOW:SW_HIDE); + WCHAR *title=0; + size_t size = (From ? wcslen(From) : 0) + (Subj ? wcslen(Subj) : 0) + 4; + title = new WCHAR[size]; + if (From&&Subj) + mir_sntprintf(title, size, L"%s (%s)", Subj, From); + else if (From) + mir_sntprintf(title, size, L"%s", From); + else if (Subj) + mir_sntprintf(title, size, L"%s", Subj); + else + mir_sntprintf(title, size, L"none"); + if (Subj) delete[] Subj; + if (From) delete[] From; + SendMessageW(hDlg,WM_SETTEXT,0,(LPARAM)title); + delete[] title; + // turn on redrawing + SendMessage(hListView, WM_SETREDRAW, 1, 0); + SendMessage(hDlg, WM_SIZE, 0, HeadSizeY<<16|HeadSizeX); + } break; + + case WM_YAMN_STOPACCOUNT: + { + PYAMN_MAILSHOWPARAM MailParam = (PYAMN_MAILSHOWPARAM) + (lParam?lParam:GetWindowLongPtr(hDlg,DWLP_USER)); + + if (NULL==MailParam) + break; + if ((HACCOUNT)wParam != MailParam->account) + break; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ShowMessage:STOPACCOUNT:sending destroy msg\n"); +#endif + DestroyWindow(hDlg); + } + return 1; + + case WM_CTLCOLORSTATIC: + //here should be check if this is our edittext control. + //but we have only one static control (for now); + SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); + SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); + return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); + + case WM_DESTROY: + { + RECT coord; + if (GetWindowRect(hDlg,&coord)) { + HeadPosX=coord.left; + HeadSizeX=coord.right-coord.left; + HeadPosY=coord.top; + HeadSizeY=coord.bottom-coord.top; + } + + PostQuitMessage(1); + } + break; + + case WM_SYSCOMMAND: + switch(wParam) { + case SC_CLOSE: + DestroyWindow(hDlg); + break; + } + break; + + case WM_MOVE: + HeadPosX=LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left; + HeadPosY=HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top; + return 0; + + case DM_SPLITTERMOVED: + if ((HWND) lParam == GetDlgItem(hDlg, IDC_SPLITTER)) { + POINT pt; + pt.x = 0; + pt.y = wParam; + ScreenToClient(hDlg, &pt); + HeadSplitPos = (pt.y*1000)/HeadSizeY;//+rc.bottom-rc.top; + if (HeadSplitPos>=1000) HeadSplitPos = 999; + else if (HeadSplitPos<=0) HeadSplitPos = 1; + else SendMessage(hDlg, WM_SIZE, 0, HeadSizeY<<16|HeadSizeX); + } + return 0; + + case WM_SIZE: + if (wParam == SIZE_RESTORED) { + HWND hList = GetDlgItem(hDlg,IDC_LISTHEADERS); + HWND hEdit = GetDlgItem(hDlg,IDC_EDITBODY); + BOOL changeX = LOWORD(lParam) != HeadSizeX; + BOOL isBodyShown = ((PYAMN_MAILSHOWPARAM)(GetWindowLongPtr(hDlg,DWLP_USER)))->mail->Flags & YAMN_MSG_BODYRECEIVED; + HeadSizeX=LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left; + HeadSizeY=HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top; + int localSplitPos = (HeadSplitPos*HeadSizeY)/1000; + int localSizeX; + RECT coord; + MoveWindow(GetDlgItem(hDlg,IDC_SPLITTER),5,localSplitPos,HeadSizeX-10,2,TRUE); + MoveWindow(hEdit,5,localSplitPos+6,HeadSizeX-10,HeadSizeY-localSplitPos-11,TRUE); //where to put text window while resizing + MoveWindow(hList, 5 ,5 ,HeadSizeX-10 ,(isBodyShown?localSplitPos:HeadSizeY)-10,TRUE); //where to put headers list window while resizing + //if (changeX) { + if (GetClientRect(hList,&coord)) { + localSizeX=coord.right-coord.left; + } else localSizeX=HeadSizeX; + LONG iNameWidth = ListView_GetColumnWidth(hList,0); + ListView_SetColumnWidth(hList,1,(localSizeX<=iNameWidth)?0:(localSizeX-iNameWidth)); + //} + } + return 0; + + case WM_CONTEXTMENU: + if ( GetWindowLongPtr(( HWND )wParam, GWLP_ID ) == IDC_LISTHEADERS) { + //MessageBox(0,"LISTHEADERS","Debug",0); + HWND hList = GetDlgItem( hDlg, IDC_LISTHEADERS ); + POINT pt = { (signed short)LOWORD( lParam ), (signed short)HIWORD( lParam ) }; + HTREEITEM hItem = 0; + if (pt.x==-1) pt.x = 0; + if (pt.y==-1) pt.y = 0; + if (int numRows = ListView_GetItemCount(hList)) { + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected")); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All")); + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel")); + int nReturnCmd = TrackPopupMenu( hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, NULL ); + DestroyMenu( hMenu ); + if (nReturnCmd>0) { + int courRow=0; + size_t sizeNeeded = 0; + TCHAR headname[64]={0}, headvalue[256]={0}; + for (courRow=0; courRow < numRows; courRow++) { + if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue; + ListView_GetItemText(hList, courRow, 0, headname, SIZEOF(headname)); + ListView_GetItemText(hList, courRow, 1, headvalue, SIZEOF(headvalue)); + size_t headnamelen = _tcslen(headname); + if (headnamelen) sizeNeeded += 1 + headnamelen; + sizeNeeded += 3 + _tcslen(headvalue); + } + if (sizeNeeded && OpenClipboard(hDlg)) { + EmptyClipboard(); + HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE,(sizeNeeded+1)*sizeof(TCHAR)); + TCHAR *buff = ( TCHAR* )GlobalLock(hData); + int courPos = 0; + for (courRow=0;courRow<numRows;courRow++) { + if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue; + ListView_GetItemText(hList, courRow, 0, headname, SIZEOF(headname)); + ListView_GetItemText(hList, courRow, 1, headvalue, SIZEOF(headvalue)); + if ( _tcslen(headname)) courPos += mir_sntprintf(&buff[courPos], sizeNeeded + 1, _T("%s:\t%s\r\n"), headname, headvalue); + else courPos += mir_sntprintf(&buff[courPos], sizeNeeded + 1, _T("\t%s\r\n"), headvalue); + } + GlobalUnlock(hData); + + SetClipboardData(CF_UNICODETEXT,hData); + + CloseClipboard(); + } + } + } + } + break; // just in case + } + return 0; +} + +DWORD WINAPI ShowEmailThread(LPVOID Param) { + struct MailShowMsgWinParam MyParam; + MyParam=*(struct MailShowMsgWinParam *)Param; + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ShowMessage:Incrementing \"using threads\" %x (account %x)\n",MyParam.account->UsingThreads,MyParam.account); + #endif + SCIncFcn(MyParam.account->UsingThreads); + SetEvent(MyParam.ThreadRunningEV); + if (MyParam.mail->MsgWindow) { + //if (!BringWindowToTop(MyParam.mail->MsgWindow)) { + if (!SetForegroundWindow(MyParam.mail->MsgWindow)) { + SendMessage(MyParam.mail->MsgWindow,WM_DESTROY,0,0); + MyParam.mail->MsgWindow = 0; + goto CREADTEVIEWMESSAGEWINDOW; + }else{ + if (IsIconic(MyParam.mail->MsgWindow)) { + OpenIcon(MyParam.mail->MsgWindow); + } + } + } else { +CREADTEVIEWMESSAGEWINDOW: + MyParam.mail->MsgWindow = CreateDialogParamW(YAMNVar.hInst,MAKEINTRESOURCEW(IDD_DLGSHOWMESSAGE),NULL,DlgProcYAMNShowMessage,(LPARAM)&MyParam); + WindowList_Add(YAMNVar.MessageWnds,MyParam.mail->MsgWindow,NULL); + MSG msg; + while(GetMessage(&msg,NULL,0,0)) { + if (!IsDialogMessage(MyParam.mail->MsgWindow, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } + WindowList_Remove(YAMNVar.MessageWnds,MyParam.mail->MsgWindow); + MyParam.mail->MsgWindow = NULL; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ShowMessage:Decrementing \"using threads\" %x (account %x)\n",MyParam.account->UsingThreads,MyParam.account); + #endif + SCDecFcn(MyParam.account->UsingThreads); + delete Param; + return 1; +} + +INT_PTR CALLBACK DlgProcYAMNMailBrowser(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + { + HACCOUNT ActualAccount; + struct MailBrowserWinParam *MyParam=(struct MailBrowserWinParam *)lParam; + struct CMailWinUserInfo *mwui; + + ListView_SetUnicodeFormat(GetDlgItem(hDlg,IDC_LISTMAILS),TRUE); + ListView_SetExtendedListViewStyle(GetDlgItem(hDlg,IDC_LISTMAILS),LVS_EX_FULLROWSELECT); + + ActualAccount=MyParam->account; + mwui=new struct CMailWinUserInfo; + mwui->Account=ActualAccount; + mwui->TrayIconState=0; + mwui->UpdateMailsMessagesAccess=FALSE; + mwui->Seen=FALSE; + mwui->RunFirstTime=TRUE; + + SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)mwui); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read wait\n"); +#endif + if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read enter failed\n"); +#endif + DestroyWindow(hDlg); + return FALSE; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read enter\n"); +#endif + + SendMessageW(GetDlgItem(hDlg,IDC_BTNAPP),WM_SETTEXT,0,(LPARAM)TranslateW(L"Run application")); + SendMessageW(GetDlgItem(hDlg,IDC_BTNDEL),WM_SETTEXT,0,(LPARAM)TranslateW(L"Delete selected")); + SendMessageW(GetDlgItem(hDlg,IDC_BTNCHECKALL),WM_SETTEXT,0,(LPARAM)TranslateW(L"Select All")); + SendMessageW(GetDlgItem(hDlg,IDC_BTNOK),WM_SETTEXT,0,(LPARAM)TranslateW(L"OK")); + + LVCOLUMNW lvc0={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,FromWidth,TranslateW(L"From"),0,0}; + LVCOLUMNW lvc1={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,SubjectWidth,TranslateW(L"Subject"),0,0}; + LVCOLUMNW lvc2={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,SizeWidth,TranslateW(L"Size"),0,0}; + LVCOLUMNW lvc3={LVCF_FMT | LVCF_TEXT | LVCF_WIDTH,LVCFMT_LEFT,SizeDate,TranslateW(L"Date"),0,0}; + SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,0,(LPARAM)&lvc0); + SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,1,(LPARAM)&lvc1); + SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,(WPARAM)2,(LPARAM)&lvc2); + SendMessageW(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_INSERTCOLUMNW,(WPARAM)3,(LPARAM)&lvc3); + + if ((ActualAccount->NewMailN.App != NULL) && (wcslen(ActualAccount->NewMailN.App))) + EnableWindow(GetDlgItem(hDlg,IDC_BTNAPP),TRUE); + else + EnableWindow(GetDlgItem(hDlg,IDC_BTNAPP),FALSE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:INIT:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + + WindowList_Add(YAMNVar.MessageWnds,hDlg,NULL); + WindowList_Add(YAMNVar.NewMailAccountWnd,hDlg, (MCONTACT)ActualAccount); + + { + TCHAR accstatus[512]; + GetStatusFcn(ActualAccount,accstatus); + SetDlgItemText(hDlg,IDC_STSTATUS,accstatus); + } + SetTimer(hDlg,TIMER_FLASHING,500,NULL); + + if (ActualAccount->hContact != NULL) + CallService(MS_CLIST_REMOVEEVENT,(WPARAM)ActualAccount->hContact,(LPARAM)"yamn new mail message"); + + mir_subclassWindow( GetDlgItem(hDlg, IDC_LISTMAILS), ListViewSubclassProc); + } + break; + + case WM_DESTROY: + { + HACCOUNT ActualAccount; + RECT coord; + LVCOLUMNW ColInfo; + NOTIFYICONDATA nid; + HYAMNMAIL Parser; + struct CMailWinUserInfo *mwui; + + mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER); + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + break; + ColInfo.mask=LVCF_WIDTH; + if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),0,&ColInfo)) + FromWidth=ColInfo.cx; + if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),1,&ColInfo)) + SubjectWidth=ColInfo.cx; + if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),2,&ColInfo)) + SizeWidth=ColInfo.cx; + if (ListView_GetColumn(GetDlgItem(hDlg,IDC_LISTMAILS),3,&ColInfo)) + SizeDate=ColInfo.cx; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DESTROY:save window position\n"); +#endif + if (!YAMNVar.Shutdown && GetWindowRect(hDlg,&coord)) //the YAMNVar.Shutdown testing is because M<iranda strange functionality at shutdown phase, when call to DBWriteContactSetting freezes calling thread + { + PosX=coord.left; + SizeX=coord.right-coord.left; + PosY=coord.top; + SizeY=coord.bottom-coord.top; + db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBPOSX,PosX); + db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBPOSY,PosY); + db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBSIZEX,SizeX); + db_set_dw(NULL,YAMN_DBMODULE,YAMN_DBSIZEY,SizeY); + } + KillTimer(hDlg,TIMER_FLASHING); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DESTROY:remove window from list\n"); +#endif + WindowList_Remove(YAMNVar.NewMailAccountWnd,hDlg); + WindowList_Remove(YAMNVar.MessageWnds,hDlg); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write wait\n"); +#endif + if (WAIT_OBJECT_0 != WaitToWriteFcn(ActualAccount->MessagesAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write wait failed\n"); +#endif + break; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write enter\n"); +#endif + //delete mails from queue, which are deleted from server (spam level 3 mails e.g.) + for (Parser=(HYAMNMAIL)ActualAccount->Mails;Parser != NULL;Parser=Parser->Next) + { + if ((Parser->Flags & YAMN_MSG_DELETED) && YAMN_MSG_SPAML(Parser->Flags,YAMN_MSG_SPAML3) && mwui->Seen) //if spaml3 was already deleted and user knows about it + { + DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails,Parser,1); + CallService(MS_YAMN_DELETEACCOUNTMAIL,(WPARAM)ActualAccount->Plugin,(LPARAM)Parser); + } + } + + //mark mails as read (remove "new" and "unseen" flags) + if (mwui->Seen) + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_DISPLAY,0,YAMN_MSG_NEW | YAMN_MSG_UNSEEN,0); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DESTROY:ActualAccountMsgsSO-write done\n"); +#endif + WriteDoneFcn(ActualAccount->MessagesAccessSO); + + ZeroMemory(&nid,sizeof(NOTIFYICONDATA)); + + delete mwui; + SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)NULL); + + nid.cbSize=sizeof(NOTIFYICONDATA); + nid.hWnd=hDlg; + nid.uID=0; + Shell_NotifyIcon(NIM_DELETE,&nid); + PostQuitMessage(0); + } + break; + case WM_SHOWWINDOW: + { + struct CMailWinUserInfo *mwui; + + if (NULL==(mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER))) + return 0; + mwui->Seen=TRUE; + } + case WM_YAMN_CHANGESTATUS: + { + HACCOUNT ActualAccount; + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + break; + + if ((HACCOUNT)wParam != ActualAccount) + break; + + TCHAR accstatus[512]; + GetStatusFcn(ActualAccount,accstatus); + SetDlgItemText(hDlg,IDC_STSTATUS,accstatus); + } + return 1; + case WM_YAMN_CHANGECONTENT: + { + struct CUpdateMails UpdateParams; + BOOL ThisThreadWindow=(GetCurrentThreadId()==GetWindowThreadProcessId(hDlg,NULL)); + + if (NULL==(UpdateParams.Copied=CreateEvent(NULL,FALSE,FALSE,NULL))) + { + DestroyWindow(hDlg); + return 0; + } + UpdateParams.Flags=(struct CChangeContent *)lParam; + UpdateParams.Waiting=!ThisThreadWindow; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:CHANGECONTENT:posting UPDATEMAILS\n"); +#endif + if (ThisThreadWindow) + { + if (!UpdateMails(hDlg,(HACCOUNT)wParam,UpdateParams.Flags->nflags,UpdateParams.Flags->nnflags)) + DestroyWindow(hDlg); + } + else if (PostMessage(hDlg,WM_YAMN_UPDATEMAILS,wParam,(LPARAM)&UpdateParams)) //this ensures UpdateMails will execute the thread who created the browser window + { + if (!ThisThreadWindow) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:CHANGECONTENT:waiting for event\n"); +#endif + WaitForSingleObject(UpdateParams.Copied,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:CHANGECONTENT:event signaled\n"); +#endif + } + } + + CloseHandle(UpdateParams.Copied); + } + return 1; + case WM_YAMN_UPDATEMAILS: + { + HACCOUNT ActualAccount; + + struct CUpdateMails *um=(struct CUpdateMails *)lParam; + DWORD nflags,nnflags; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:UPDATEMAILS\n"); +#endif + + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + return 0; + if ((HACCOUNT)wParam != ActualAccount) + return 0; + + nflags=um->Flags->nflags; + nnflags=um->Flags->nnflags; + + if (um->Waiting) + SetEvent(um->Copied); + + if (!UpdateMails(hDlg,ActualAccount,nflags,nnflags)) + DestroyWindow(hDlg); + } + return 1; + case WM_YAMN_STOPACCOUNT: + { + HACCOUNT ActualAccount; + + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + break; + if ((HACCOUNT)wParam != ActualAccount) + break; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:STOPACCOUNT:sending destroy msg\n"); +#endif + PostQuitMessage(0); + } + return 1; + case WM_YAMN_NOTIFYICON: + { + HACCOUNT ActualAccount; + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + break; + + switch(lParam) + { + case WM_LBUTTONDBLCLK: +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read wait\n"); +#endif + if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read wait failed\n"); +#endif + return 0; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read enter\n"); +#endif + if (ActualAccount->AbilityFlags & YAMN_ACC_BROWSE) + { + ShowWindow(hDlg,SW_SHOWNORMAL); + SetForegroundWindow(hDlg); + } + else + DestroyWindow(hDlg); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DBLCLICKICON:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + break; + } + break; + } + case WM_YAMN_SHOWSELECTED: + { + int iSelect; + iSelect=SendMessage(GetDlgItem(hDlg,IDC_LISTMAILS),LVM_GETNEXTITEM,-1,MAKELPARAM((UINT)LVNI_FOCUSED,0)); // return item selected + + if (iSelect != -1) + { + LV_ITEMW item; + HYAMNMAIL ActualMail; + + item.iItem=iSelect; + item.iSubItem=0; + item.mask=LVIF_PARAM | LVIF_STATE; + item.stateMask=0xFFFFFFFF; + ListView_GetItem(GetDlgItem(hDlg,IDC_LISTMAILS),&item); + ActualMail=(HYAMNMAIL)item.lParam; + if (NULL != ActualMail) + { + //ShowEmailThread + PYAMN_MAILSHOWPARAM MailParam = new YAMN_MAILSHOWPARAM; + MailParam->account = GetWindowAccount(hDlg); + MailParam->mail = ActualMail; + if (NULL != (MailParam->ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) { + HANDLE NewThread; + if (NULL != (NewThread=CreateThread(NULL,0,ShowEmailThread,MailParam,0,NULL))) + { + //WaitForSingleObject(MailParam->ThreadRunningEV,INFINITE); + CloseHandle(NewThread); + } + CloseHandle(MailParam->ThreadRunningEV); + } + //delete MailParam; + } + } + } break; + case WM_SYSCOMMAND: + { + HACCOUNT ActualAccount; + + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + break; + switch(wParam) + { + case SC_CLOSE: + DestroyWindow(hDlg); + break; + } + } + break; + + case WM_COMMAND: + { + HACCOUNT ActualAccount; + int Items; + + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + break; + + switch(LOWORD(wParam)) + { + case IDC_BTNCHECKALL: + ListView_SetItemState(GetDlgItem(hDlg,IDC_LISTMAILS), -1, 0, LVIS_SELECTED); // deselect all items + ListView_SetItemState(GetDlgItem(hDlg,IDC_LISTMAILS),-1, LVIS_SELECTED ,LVIS_SELECTED); + Items = ListView_GetItemCount(GetDlgItem(hDlg,IDC_LISTMAILS)); + ListView_RedrawItems(GetDlgItem(hDlg,IDC_LISTMAILS), 0, Items); + UpdateWindow(GetDlgItem(hDlg,IDC_LISTMAILS)); + SetFocus(GetDlgItem(hDlg,IDC_LISTMAILS)); + break; + + case IDC_BTNOK: + DestroyWindow(hDlg); + break; + + case IDC_BTNAPP: + { + PROCESS_INFORMATION pi; + STARTUPINFOW si; + + ZeroMemory(&si,sizeof(si)); + si.cb=sizeof(si); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read wait\n"); +#endif + if (WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read enter\n"); +#endif + if (ActualAccount->NewMailN.App != NULL) + { + WCHAR *Command; + if (ActualAccount->NewMailN.AppParam != NULL) + Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+wcslen(ActualAccount->NewMailN.AppParam)+6]; + else + Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+6]; + + if (Command != NULL) + { + lstrcpyW(Command,L"\""); + lstrcatW(Command,ActualAccount->NewMailN.App); + lstrcatW(Command,L"\" "); + if (ActualAccount->NewMailN.AppParam != NULL) + lstrcatW(Command,ActualAccount->NewMailN.AppParam); + CreateProcessW(NULL,Command,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi); + delete[] Command; + } + } + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + } +#ifdef DEBUG_SYNCHRO + else + DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read enter failed\n"); +#endif + if (!(GetKeyState(VK_SHIFT) & 0x8000) && !(GetKeyState(VK_CONTROL) & 0x8000)) + DestroyWindow(hDlg); + + } + break; + case IDC_BTNDEL: + { + LVITEMW item; + HYAMNMAIL FirstMail=NULL,ActualMail; + HANDLE ThreadRunningEV; + DWORD tid,Total=0; + + // we use event to signal, that running thread has all needed stack parameters copied + if (NULL==(ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) + break; + int Items=ListView_GetItemCount(GetDlgItem(hDlg,IDC_LISTMAILS)); + + item.stateMask=0xFFFFFFFF; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write wait\n"); +#endif + if (WAIT_OBJECT_0==WaitToWriteFcn(ActualAccount->MessagesAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write enter\n"); +#endif + for (int i=0;i<Items;i++) + { + item.iItem=i; + item.iSubItem=0; + item.mask=LVIF_PARAM | LVIF_STATE; + item.stateMask=0xFFFFFFFF; + ListView_GetItem(GetDlgItem(hDlg,IDC_LISTMAILS),&item); + ActualMail=(HYAMNMAIL)item.lParam; + if (NULL==ActualMail) + break; + if (item.state & LVIS_SELECTED) + { + ActualMail->Flags|=YAMN_MSG_USERDELETE; //set to mail we are going to delete it + Total++; + } + } + + // Enable write-access to mails +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write done\n"); +#endif + WriteDoneFcn(ActualAccount->MessagesAccessSO); + + if (Total) + { + TCHAR DeleteMsg[1024]; + + mir_sntprintf(DeleteMsg, SIZEOF(DeleteMsg), TranslateT("Do you really want to delete %d selected mails?"),Total); + if (IDOK==MessageBox(hDlg,DeleteMsg,TranslateT("Delete confirmation"),MB_OKCANCEL | MB_ICONWARNING)) + { + struct DeleteParam ParamToDeleteMails={YAMN_DELETEVERSION,ThreadRunningEV,ActualAccount,NULL}; + + // Find if there's mail marked to delete, which was deleted before +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write wait\n"); +#endif + if (WAIT_OBJECT_0==WaitToWriteFcn(ActualAccount->MessagesAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write enter\n"); +#endif + for (ActualMail=(HYAMNMAIL)ActualAccount->Mails;ActualMail != NULL;ActualMail=ActualMail->Next) + { + if ((ActualMail->Flags & YAMN_MSG_DELETED) && ((ActualMail->Flags & YAMN_MSG_USERDELETE))) //if selected mail was already deleted + { + DeleteMessageFromQueueFcn((HYAMNMAIL *)&ActualAccount->Mails,ActualMail,1); + CallService(MS_YAMN_DELETEACCOUNTMAIL,(WPARAM)ActualAccount->Plugin,(LPARAM)ActualMail); //delete it from memory + continue; + } + } + // Set flag to marked mails that they can be deleted + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE,0,YAMN_MSG_DELETEOK,1); + // Create new thread which deletes marked mails. + HANDLE NewThread; + + if (NULL != (NewThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ActualAccount->Plugin->Fcn->DeleteMailsFcnPtr,(LPVOID)&ParamToDeleteMails,0,&tid))) + { + WaitForSingleObject(ThreadRunningEV,INFINITE); + CloseHandle(NewThread); + } + // Enable write-access to mails +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNDEL:ActualAccountMsgsSO-write done\n"); +#endif + WriteDoneFcn(ActualAccount->MessagesAccessSO); + } + } + else + //else mark messages that they are not to be deleted + SetRemoveFlagsInQueueFcn((HYAMNMAIL)ActualAccount->Mails,YAMN_MSG_DISPLAY | YAMN_MSG_USERDELETE,0,YAMN_MSG_USERDELETE,0); + } + } + CloseHandle(ThreadRunningEV); + if (db_get_b(NULL, YAMN_DBMODULE, YAMN_CLOSEDELETE, 0)) + DestroyWindow(hDlg); + + } + break; + } + } + break; + case WM_SIZE: + if (wParam==SIZE_RESTORED) + { + LONG x=LOWORD(lParam); //((LPRECT)lParam)->right-((LPRECT)lParam)->left; + LONG y=HIWORD(lParam); //((LPRECT)lParam)->bottom-((LPRECT)lParam)->top; + MoveWindow(GetDlgItem(hDlg,IDC_BTNDEL), 5 ,y-5-25,(x-20)/3,25,TRUE); //where to put DELETE button while resizing + MoveWindow(GetDlgItem(hDlg,IDC_BTNCHECKALL),10+ (x-20)/3,y-5-25,(x-20)/6,25,TRUE); //where to put CHECK ALL button while resizing + MoveWindow(GetDlgItem(hDlg,IDC_BTNAPP), 15+ (x-20)/3 + (x-20)/6,y-5-25,(x-20)/3,25,TRUE); //where to put RUN APP button while resizing + MoveWindow(GetDlgItem(hDlg,IDC_BTNOK), 20+2*(x-20)/3 + (x-20)/6 ,y-5-25,(x-20)/6,25,TRUE); //where to put OK button while resizing + MoveWindow(GetDlgItem(hDlg,IDC_LISTMAILS), 5 ,5 ,x-10 ,y-55,TRUE); //where to put list mail window while resizing + MoveWindow(GetDlgItem(hDlg,IDC_STSTATUS), 5 ,y-5-45 ,x-10 ,15,TRUE); //where to put account status text while resizing + } + // break; + return 0; + case WM_GETMINMAXINFO: + ((LPMINMAXINFO)lParam)->ptMinTrackSize.x=MAILBROWSER_MINXSIZE; + ((LPMINMAXINFO)lParam)->ptMinTrackSize.y=MAILBROWSER_MINYSIZE; + return 0; + case WM_TIMER: + { + NOTIFYICONDATA nid; + struct CMailWinUserInfo *mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER); + + ZeroMemory(&nid,sizeof(nid)); + nid.cbSize=sizeof(NOTIFYICONDATA); + nid.hWnd=hDlg; + nid.uID=0; + nid.uFlags=NIF_ICON; + if (mwui->TrayIconState==0) + nid.hIcon=g_LoadIconEx(0); + else + nid.hIcon=g_LoadIconEx(2); + Shell_NotifyIcon(NIM_MODIFY,&nid); + mwui->TrayIconState=!mwui->TrayIconState; + // UpdateWindow(hDlg); + } + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case IDC_LISTMAILS: + switch(((LPNMHDR)lParam)->code) { + case NM_DBLCLK: + SendMessage(hDlg,WM_YAMN_SHOWSELECTED,0,0); + break; + case LVN_COLUMNCLICK: + HACCOUNT ActualAccount; + if (NULL != (ActualAccount=GetWindowAccount(hDlg))) { + NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam; + if (WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:COLUMNCLICK:ActualAccountSO-read enter\n"); +#endif + switch((int)pNMListView->iSubItem) + { + case 0: + bFrom = !bFrom; + break; + case 1: + bSub = !bSub; + break; + case 2: + bSize = !bSize; + break; + case 3: + bDate = !bDate; + break; + default: + break; + } + ListView_SortItems(pNMListView->hdr.hwndFrom,ListViewCompareProc,pNMListView->iSubItem); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:BTNAPP:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + } + break; + + case NM_CUSTOMDRAW: + { + HACCOUNT ActualAccount; + LPNMLVCUSTOMDRAW cd=(LPNMLVCUSTOMDRAW)lParam; + LONG_PTR PaintCode; + + if (NULL==(ActualAccount=GetWindowAccount(hDlg))) + break; + + switch(cd->nmcd.dwDrawStage) { + case CDDS_PREPAINT: + PaintCode=CDRF_NOTIFYITEMDRAW; + break; + case CDDS_ITEMPREPAINT: + PaintCode=CDRF_NOTIFYSUBITEMDRAW; + break; + case CDDS_ITEMPREPAINT | CDDS_SUBITEM: + { + // COLORREF crText, crBkgnd; + // crText= RGB(128,128,255); + HYAMNMAIL ActualMail; + BOOL umma; + + { + struct CMailWinUserInfo *mwui; + mwui=(struct CMailWinUserInfo *)GetWindowLongPtr(hDlg,DWLP_USER); + umma= mwui->UpdateMailsMessagesAccess; + } + ActualMail=(HYAMNMAIL)cd->nmcd.lItemlParam; + if (!ActualMail) + ActualMail=(HYAMNMAIL)readItemLParam(cd->nmcd.hdr.hwndFrom,cd->nmcd.dwItemSpec); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read wait\n"); +#endif + if (!umma) + if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->MessagesAccessSO)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read wait failed\n"); +#endif + return 0; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read enter\n"); +#endif + switch(ActualMail->Flags & YAMN_MSG_SPAMMASK) + { + case YAMN_MSG_SPAML1: + case YAMN_MSG_SPAML2: + cd->clrText=RGB(150,150,150); + break; + case YAMN_MSG_SPAML3: + cd->clrText=RGB(200,200,200); + cd->clrTextBk=RGB(160,160,160); + break; + case 0: + if (cd->nmcd.dwItemSpec & 1) + cd->clrTextBk=RGB(230,230,230); + break; + default: + break; + } + if (ActualMail->Flags & YAMN_MSG_UNSEEN) + cd->clrTextBk=RGB(220,235,250); + PaintCode=CDRF_DODEFAULT; + + if (!umma) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:DRAWITEM:ActualAccountMsgsSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->MessagesAccessSO); + } + + break; + } + } + SetWindowLongPtr(hDlg,DWLP_MSGRESULT,PaintCode); + return 1; + } + } + } + break; + + case WM_CONTEXTMENU: + if ( GetWindowLongPtr(( HWND )wParam, GWLP_ID ) == IDC_LISTMAILS) { + //MessageBox(0,"LISTHEADERS","Debug",0); + HWND hList = GetDlgItem( hDlg, IDC_LISTMAILS ); + POINT pt = { (signed short)LOWORD( lParam ), (signed short)HIWORD( lParam ) }; + HTREEITEM hItem = 0; + if (pt.x==-1) pt.x = 0; + if (pt.y==-1) pt.y = 0; + if (int numRows = ListView_GetItemCount(hList)) { + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)1, TranslateT("Copy Selected")); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)2, TranslateT("Copy All")); + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + AppendMenu(hMenu, MF_STRING, (UINT_PTR)0, TranslateT("Cancel")); + int nReturnCmd = TrackPopupMenu( hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, NULL ); + DestroyMenu( hMenu ); + if (nReturnCmd>0) { + int courRow=0; + size_t sizeNeeded = 0; + TCHAR from[128]={0}, subject[256]={0}, size[16]={0}, date[64]={0}; + for (courRow=0;courRow<numRows;courRow++) { + if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue; + ListView_GetItemText(hList, courRow, 0, from, SIZEOF(from)); + ListView_GetItemText(hList, courRow, 1, subject, SIZEOF(subject)); + ListView_GetItemText(hList, courRow, 2, size, SIZEOF(size)); + ListView_GetItemText(hList, courRow, 3, date, SIZEOF(date)); + sizeNeeded += 5+_tcslen(from)+_tcslen(subject)+_tcslen(size)+_tcslen(date); + } + if (sizeNeeded && OpenClipboard(hDlg)) { + EmptyClipboard(); + HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE,(sizeNeeded+1)*sizeof(TCHAR)); + TCHAR *buff = (TCHAR *)GlobalLock(hData); + int courPos = 0; + for (courRow=0; courRow < numRows; courRow++) { + if ((nReturnCmd==1) && (ListView_GetItemState(hList, courRow, LVIS_SELECTED)==0)) continue; + ListView_GetItemText(hList, courRow, 0, from, SIZEOF(from)); + ListView_GetItemText(hList, courRow, 1, subject, SIZEOF(subject)); + ListView_GetItemText(hList, courRow, 2, size, SIZEOF(size)); + ListView_GetItemText(hList, courRow, 3, date, SIZEOF(date)); + courPos += mir_sntprintf(&buff[courPos], sizeNeeded + 1, _T("%s\t%s\t%s\t%s\r\n"), from, subject, size, date); + } + GlobalUnlock(hData); + + SetClipboardData(CF_UNICODETEXT,hData); + + CloseClipboard(); + } + } + } + } + break; // just in case + } + return 0; +} + +LRESULT CALLBACK ListViewSubclassProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndParent = GetParent(hDlg); + + switch(msg) { + case WM_GETDLGCODE : + { + LPMSG lpmsg; + if ( ( lpmsg = (LPMSG)lParam ) != NULL ) { + if ( lpmsg->message == WM_KEYDOWN + && lpmsg->wParam == VK_RETURN) + return DLGC_WANTALLKEYS; + } + break; + } + case WM_KEYDOWN: + { + + BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; + BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000; + BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; + + switch (wParam) + { + case 'A': // ctrl-a + if (!isAlt && !isShift && isCtrl) SendMessage(hwndParent,WM_COMMAND,IDC_BTNCHECKALL,0); + break; + case VK_RETURN: + case VK_SPACE: + if (!isAlt && !isShift && !isCtrl) SendMessage(hwndParent,WM_YAMN_SHOWSELECTED,0,0); + break; + case VK_DELETE: + SendMessage(hwndParent,WM_COMMAND,IDC_BTNDEL,0); + break; + } + + break; + + } + } + return mir_callNextSubclass(hDlg, ListViewSubclassProc, msg, wParam, lParam); +} + +DWORD WINAPI MailBrowser(LPVOID Param) +{ + MSG msg; + + HWND hMailBrowser; + BOOL WndFound=FALSE; + HACCOUNT ActualAccount; + struct MailBrowserWinParam MyParam; + + MyParam=*(struct MailBrowserWinParam *)Param; + ActualAccount=MyParam.account; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:Incrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); + #endif + SCIncFcn(ActualAccount->UsingThreads); + +// we will not use params in stack anymore + SetEvent(MyParam.ThreadRunningEV); + + __try + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read wait\n"); + #endif + if (WAIT_OBJECT_0 != WaitToReadFcn(ActualAccount->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read wait failed\n"); + #endif + return 0; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read enter\n"); + #endif + if (!(ActualAccount->AbilityFlags & YAMN_ACC_BROWSE)) + { + MyParam.nflags=MyParam.nflags & ~YAMN_ACC_MSG; + MyParam.nnflags=MyParam.nnflags & ~YAMN_ACC_MSG; + } + if (!(ActualAccount->AbilityFlags & YAMN_ACC_POPUP)) + MyParam.nflags=MyParam.nflags & ~YAMN_ACC_POP; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:ActualAccountSO-read done\n"); + #endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + + if (NULL != (hMailBrowser=WindowList_Find(YAMNVar.NewMailAccountWnd, (MCONTACT)ActualAccount))) + WndFound=TRUE; + if ((hMailBrowser==NULL) && ((MyParam.nflags & YAMN_ACC_MSG) || (MyParam.nflags & YAMN_ACC_ICO) || (MyParam.nnflags & YAMN_ACC_MSG))) + { + hMailBrowser=CreateDialogParamW(YAMNVar.hInst,MAKEINTRESOURCEW(IDD_DLGVIEWMESSAGES),NULL,DlgProcYAMNMailBrowser,(LPARAM)&MyParam); + SendMessageW(hMailBrowser,WM_SETICON,(WPARAM)ICON_BIG,(LPARAM)g_LoadIconEx(2,true)); + SendMessageW(hMailBrowser,WM_SETICON,(WPARAM)ICON_SMALL,(LPARAM)g_LoadIconEx(2)); + MoveWindow(hMailBrowser,PosX,PosY,SizeX,SizeY,TRUE); + } + + if (hMailBrowser != NULL) + { + struct CChangeContent Params={MyParam.nflags,MyParam.nnflags}; //if this thread created window, just post message to update mails + + SendMessageW(hMailBrowser,WM_YAMN_CHANGECONTENT,(WPARAM)ActualAccount,(LPARAM)&Params); //we ensure this will do the thread who created the browser window + } + else + UpdateMails(NULL,ActualAccount,MyParam.nflags,MyParam.nnflags); //update mails without displaying or refreshing any window + + if ((hMailBrowser != NULL) && !WndFound) //we process message loop only for thread that created window + { + while(GetMessage(&msg,NULL,0,0)) + { + if (!IsDialogMessage(hMailBrowser, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + if ((!WndFound) && (ActualAccount->Plugin->Fcn != NULL) && (ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr != NULL) && ActualAccount->AbleToWork) + ActualAccount->Plugin->Fcn->WriteAccountsFcnPtr(); + } + __finally + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"MailBrowser:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); + #endif + SCDecFcn(ActualAccount->UsingThreads); + } + return 1; +} + +INT_PTR RunMailBrowserSvc(WPARAM wParam,LPARAM lParam) +{ + DWORD tid; + //an event for successfull copy parameters to which point a pointer in stack for new thread + HANDLE ThreadRunningEV; + PYAMN_MAILBROWSERPARAM Param=(PYAMN_MAILBROWSERPARAM)wParam; + + if ((DWORD)lParam != YAMN_MAILBROWSERVERSION) + return 0; + + if (NULL != (ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) + { + HANDLE NewThread; + + Param->ThreadRunningEV=ThreadRunningEV; + if (NULL != (NewThread=CreateThread(NULL,0,MailBrowser,Param,0,&tid))) + { + WaitForSingleObject(ThreadRunningEV,INFINITE); + CloseHandle(NewThread); + } + CloseHandle(ThreadRunningEV); + return 1; + } + return 0; +} diff --git a/plugins/YAMN/src/main.cpp b/plugins/YAMN/src/main.cpp index c26653813b..14b1a8af9c 100644 --- a/plugins/YAMN/src/main.cpp +++ b/plugins/YAMN/src/main.cpp @@ -1,396 +1,396 @@ -/*
- * YAMN plugin main file
- * Miranda homepage: http://miranda-icq.sourceforge.net/
- * YAMN homepage: http://www.majvan.host.sk/Projekty/YAMN
- *
- * initializes all variables for further work
- *
- * (c) majvan 2002-2004
- */
-
-#include "yamn.h"
-
-//--------------------------------------------------------------------------------------------------
-
-TCHAR ProfileName[MAX_PATH];
-TCHAR UserDirectory[MAX_PATH];
-
-TCHAR szMirandaDir[MAX_PATH];
-TCHAR szProfileDir[MAX_PATH];
-
-int YAMN_STATUS;
-
-BOOL UninstallPlugins;
-
-HANDLE hAccountFolder;
-
-HINSTANCE *hDllPlugins;
-static int iDllPlugins = 0;
-
-
-YAMN_VARIABLES YAMNVar;
-
-int hLangpack;
-
-PLUGININFOEX pluginInfo = {
- sizeof(PLUGININFOEX),
- __PLUGIN_NAME,
- PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
- __DESCRIPTION,
- __AUTHOR,
- __AUTHOREMAIL,
- __COPYRIGHT,
- __AUTHORWEB,
- UNICODE_AWARE,
- // {B047A7E5-027A-4CFC-8B18-EDA8345D2790}
- {0xb047a7e5, 0x27a, 0x4cfc, {0x8b, 0x18, 0xed, 0xa8, 0x34, 0x5d, 0x27, 0x90}}
-};
-
-HANDLE hNewMailHook;
-HANDLE NoWriterEV;
-HANDLE hTTButton;
-
-UINT SecTimer;
-
-HGENMENU hMenuItemMain = 0;
-HGENMENU hMenuItemCont = 0;
-HGENMENU hMenuItemContApp = 0;
-
-#define FIXED_TAB_SIZE 100 // default value for fixed width tabs
-
-static void GetProfileDirectory(TCHAR *szPath, int cbPath)
-//This is copied from Miranda's sources. In 0.2.1.0 it is needed, in newer vesions of Miranda use MS_DB_GETPROFILEPATH service
-{
- TCHAR tszOldPath[MAX_PATH];
- CallService(MS_DB_GETPROFILEPATHT, SIZEOF(tszOldPath), (LPARAM)tszOldPath);
- _tcscat(tszOldPath, _T("\\*.book"));
-
- VARST ptszNewPath( _T("%miranda_userdata%"));
-
- SHFILEOPSTRUCT file_op = {
- NULL,
- FO_MOVE,
- tszOldPath,
- ptszNewPath,
- FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT,
- false,
- 0,
- _T("") };
- SHFileOperation(&file_op);
-
- _tcsncpy(szPath, ptszNewPath, cbPath);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
- YAMNVar.hInst = hinstDLL;
- return TRUE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
-{
- return &pluginInfo;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef _DEBUG
-static TCHAR unknownCP[1500] = {0};
-#endif
-// The callback function
-BOOL CALLBACK EnumSystemCodePagesProc(LPTSTR cpStr)
-{
- //Convert code page string to number
- UINT cp = _ttoi(cpStr);
- if (!IsValidCodePage(cp))
- return TRUE;
-
- //Get Code Page name
- CPINFOEX info;
- if (GetCPInfoEx(cp, 0, &info)) {
- #ifdef _DEBUG
- BOOLEAN found = FALSE;
- #endif
- for (int i = 1;i<CPLENALL;i++) if (CodePageNamesAll[i].CP == cp) {
- CodePageNamesAll[i].isValid = TRUE;
- CPLENSUPP++;
- #ifdef _DEBUG
- found = TRUE;
- #endif
- break;
- }
- #ifdef _DEBUG
- if (!found) {
- _tcscat(unknownCP, info.CodePageName);
- _tcscat(unknownCP, _T("\n"));
- }
- #endif
- }
- return TRUE;
-}
-
-void CheckMenuItems()
-{
- Menu_ShowItem(hMenuItemMain, db_get_b(NULL, YAMN_DBMODULE, YAMN_SHOWMAINMENU, 1) != 0);
-}
-
-int SystemModulesLoaded(WPARAM, LPARAM)
-{
- //Insert "Check mail (YAMN)" item to Miranda's menu
- CLISTMENUITEM mi = { sizeof(mi) };
- mi.position = 0xb0000000;
- mi.icolibItem = g_GetIconHandle(0);
- mi.pszName = LPGEN("Check &mail (All Account)");
- mi.pszPopupName = NULL;//YAMN_DBMODULE;
- mi.pszService = MS_YAMN_FORCECHECK;
- hMenuItemMain = Menu_AddMainMenuItem(&mi);
-
- mi.pszName = LPGEN("Check &mail (This Account)");
- mi.pszContactOwner = YAMN_DBMODULE;
- mi.pszService = MS_YAMN_CLISTCONTEXT;
- hMenuItemCont = Menu_AddContactMenuItem(&mi);
-
- mi.icolibItem = g_GetIconHandle(1);
- mi.pszName = LPGEN("Launch application");
- mi.pszContactOwner = YAMN_DBMODULE;
- mi.pszService = MS_YAMN_CLISTCONTEXTAPP;
- hMenuItemContApp = Menu_AddContactMenuItem(&mi);
-
- CheckMenuItems();
-
- if (hAccountFolder = FoldersRegisterCustomPathT(LPGEN("YAMN"), LPGEN("YAMN Account Folder"), UserDirectory))
- FoldersGetCustomPathT(hAccountFolder, UserDirectory, MAX_PATH, UserDirectory);
-
- RegisterPOP3Plugin(0, 0);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static IconItem iconList[] =
-{
- { LPGEN("Check mail"), "YAMN_Check", IDI_CHECKMAIL },
- { LPGEN("Launch application"), "YAMN_Launch", IDI_LAUNCHAPP },
- { LPGEN("New Mail"), "YAMN_NewMail", IDI_NEWMAIL },
- { LPGEN("Connect Fail"), "YAMN_ConnectFail", IDI_BADCONNECT },
-};
-
-static void LoadIcons()
-{
- Icon_Register(YAMNVar.hInst, "YAMN", iconList, SIZEOF(iconList));
-}
-
-HANDLE WINAPI g_GetIconHandle( int idx )
-{
- if ( idx >= SIZEOF(iconList))
- return NULL;
- return iconList[idx].hIcolib;
-}
-
-HICON WINAPI g_LoadIconEx( int idx, bool big )
-{
- if ( idx >= SIZEOF(iconList))
- return NULL;
- return Skin_GetIcon(iconList[idx].szName, big);
-}
-
-void WINAPI g_ReleaseIcon( HICON hIcon )
-{
- if ( hIcon ) Skin_ReleaseIcon(hIcon);
-}
-
-static void LoadPlugins()
-{
- TCHAR szSearchPath[MAX_PATH];
- mir_sntprintf(szSearchPath, MAX_PATH, _T("%s\\Plugins\\YAMN\\*.dll"), szMirandaDir);
-
- hDllPlugins = NULL;
-
- WIN32_FIND_DATA fd;
- HANDLE hFind = FindFirstFile(szSearchPath, &fd);
- if (hFind != INVALID_HANDLE_VALUE) {
- do {
- //rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too
- TCHAR *dot = _tcsrchr(fd.cFileName, '.');
- if (dot == NULL )
- continue;
-
- // we have a dot
- int len = lstrlen(fd.cFileName); // find the length of the string
- TCHAR* end = fd.cFileName+len; // get a pointer to the NULL
- int safe = (end-dot)-1; // figure out how many chars after the dot are "safe", not including NULL
-
- if ((safe != 3) || (lstrcmpi(dot+1, _T("dll")) != 0)) //not bound, however the "dll" string should mean only 3 chars are compared
- continue;
-
- TCHAR szPluginPath[MAX_PATH];
- mir_sntprintf(szPluginPath, MAX_PATH,_T("%s\\Plugins\\YAMN\\%s"), szMirandaDir, fd.cFileName);
- HINSTANCE hDll = LoadLibrary(szPluginPath);
- if (hDll == NULL)
- continue;
-
- LOADFILTERFCN LoadFilter = (LOADFILTERFCN) GetProcAddress(hDll, "LoadFilter");
- if (NULL == LoadFilter) {
- FreeLibrary(hDll);
- hDll = NULL;
- continue;
- }
-
- if (!(*LoadFilter)(GetFcnPtrSvc)) {
- FreeLibrary(hDll);
- hDll = NULL;
- }
-
- if (hDll != NULL) {
- hDllPlugins = (HINSTANCE *)realloc((void *)hDllPlugins, (iDllPlugins+1)*sizeof(HINSTANCE));
- hDllPlugins[iDllPlugins++] = hDll;
- }
- }
- while(FindNextFile(hFind, &fd));
-
- FindClose(hFind);
- }
-}
-
-extern "C" int __declspec(dllexport) Load(void)
-{
- mir_getLP(&pluginInfo);
-
- YAMN_STATUS = ID_STATUS_OFFLINE;
-
- // we get the Miranda Root Path
- PathToAbsoluteT( _T("."), szMirandaDir);
-
- // retrieve the current profile name
- CallService(MS_DB_GETPROFILENAMET, (WPARAM)SIZEOF(ProfileName), (LPARAM)ProfileName); //not to pass entire array to fcn
- TCHAR *fc = _tcsrchr(ProfileName, '.');
- if ( fc != NULL ) *fc = 0;
-
- // we get the user path where our yamn-account.book.ini is stored from mirandaboot.ini file
- GetProfileDirectory(UserDirectory, SIZEOF(UserDirectory));
-
- // Enumerate all the code pages available for the System Locale
- EnumSystemCodePages(EnumSystemCodePagesProc, CP_INSTALLED);
- CodePageNamesSupp = new _tcptable[CPLENSUPP];
- for (int i = 0, k = 0; i < CPLENALL; i++) {
- if (CodePageNamesAll[i].isValid) {
- CodePageNamesSupp[k] = CodePageNamesAll[i];
- k++;
- } }
-
- // Registering YAMN as protocol
- PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE };
- pd.szName = YAMN_DBMODULE;
- pd.type = PROTOTYPE_VIRTUAL;
- CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
-
- InitializeCriticalSection(&AccountStatusCS);
- InitializeCriticalSection(&FileWritingCS);
- InitializeCriticalSection(&PluginRegCS);
-
- if (NULL == (NoWriterEV = CreateEvent(NULL, TRUE, TRUE, NULL)))
- return 1;
- if (NULL == (WriteToFileEV = CreateEvent(NULL, FALSE, FALSE, NULL)))
- return 1;
- if (NULL == (ExitEV = CreateEvent(NULL, TRUE, FALSE, NULL)))
- return 1;
-
- PosX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBPOSX, 0);
- PosY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBPOSY, 0);
- SizeX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBSIZEX, 800);
- SizeY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBSIZEY, 200);
-
- HeadPosX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSX, 0);
- HeadPosY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSY, 0);
- HeadSizeX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGSIZEX, 690);
- HeadSizeY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGSIZEY, 300);
- HeadSplitPos = db_get_w(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSSPLIT, 250);
-
- optDateTime = db_get_b(NULL, YAMN_DBMODULE, YAMN_DBTIMEOPTIONS, optDateTime);
-
- // Create new window queues for broadcast messages
- YAMNVar.MessageWnds = WindowList_Create();
- YAMNVar.NewMailAccountWnd = WindowList_Create();
- YAMNVar.Shutdown = FALSE;
-
- hCurSplitNS = LoadCursor(NULL, IDC_SIZENS);
- hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE);
-
-#ifdef _DEBUG
- InitDebug();
-#endif
-
- CreateServiceFunctions();
-
- SkinAddNewSoundEx(YAMN_NEWMAILSOUND, YAMN_DBMODULE, YAMN_NEWMAILSNDDESC);
- SkinAddNewSoundEx(YAMN_CONNECTFAILSOUND, YAMN_DBMODULE, YAMN_CONNECTFAILSNDDESC);
-
- HookEvents();
-
- LoadIcons();
- LoadPlugins();
-
- HOTKEYDESC hkd = {0};
- hkd.cbSize = sizeof(hkd);
- hkd.pszName = "YAMN_hotkey";
- hkd.pszService = MS_YAMN_FORCECHECK;
- hkd.pszSection = YAMN_DBMODULE;
- hkd.pszDescription = LPGEN("Check mail");
- hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, VK_F11);
- Hotkey_Register(&hkd);
-
- //Create thread that will be executed every second
- if (!(SecTimer = SetTimer(NULL, 0, 1000, TimerProc)))
- return 1;
-
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void UnloadPlugins()
-{
- for (int i = iDllPlugins-1;i>=0;i--) {
- if (FreeLibrary(hDllPlugins[i])) {
- hDllPlugins[i] = NULL; //for safety
- iDllPlugins --;
- }
- }
- if (hDllPlugins) {
- free((void *)hDllPlugins);
- hDllPlugins = NULL;
- }
-}
-
-extern "C" int __declspec(dllexport) Unload(void)
-{
-#ifdef _DEBUG
- UnInitDebug();
-#endif
-
- WindowList_Destroy(YAMNVar.MessageWnds);
- WindowList_Destroy(YAMNVar.NewMailAccountWnd);
-
- DestroyCursor(hCurSplitNS);
- DestroyCursor(hCurSplitWE);
-
- CloseHandle(NoWriterEV);
- CloseHandle(WriteToFileEV);
- CloseHandle(ExitEV);
-
- DeleteCriticalSection(&AccountStatusCS);
- DeleteCriticalSection(&FileWritingCS);
- DeleteCriticalSection(&PluginRegCS);
-
- UnhookEvents();
- DestroyServiceFunctions();
-
- UnloadPlugins();
-
- delete [] CodePageNamesSupp;
- return 0;
-}
+/* + * YAMN plugin main file + * Miranda homepage: http://miranda-icq.sourceforge.net/ + * YAMN homepage: http://www.majvan.host.sk/Projekty/YAMN + * + * initializes all variables for further work + * + * (c) majvan 2002-2004 + */ + +#include "yamn.h" + +//-------------------------------------------------------------------------------------------------- + +TCHAR ProfileName[MAX_PATH]; +TCHAR UserDirectory[MAX_PATH]; + +TCHAR szMirandaDir[MAX_PATH]; +TCHAR szProfileDir[MAX_PATH]; + +int YAMN_STATUS; + +BOOL UninstallPlugins; + +HANDLE hAccountFolder; + +HINSTANCE *hDllPlugins; +static int iDllPlugins = 0; + + +YAMN_VARIABLES YAMNVar; + +int hLangpack; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {B047A7E5-027A-4CFC-8B18-EDA8345D2790} + {0xb047a7e5, 0x27a, 0x4cfc, {0x8b, 0x18, 0xed, 0xa8, 0x34, 0x5d, 0x27, 0x90}} +}; + +HANDLE hNewMailHook; +HANDLE NoWriterEV; +HANDLE hTTButton; + +UINT SecTimer; + +HGENMENU hMenuItemMain = 0; +HGENMENU hMenuItemCont = 0; +HGENMENU hMenuItemContApp = 0; + +#define FIXED_TAB_SIZE 100 // default value for fixed width tabs + +static void GetProfileDirectory(TCHAR *szPath, int cbPath) +//This is copied from Miranda's sources. In 0.2.1.0 it is needed, in newer vesions of Miranda use MS_DB_GETPROFILEPATH service +{ + TCHAR tszOldPath[MAX_PATH]; + CallService(MS_DB_GETPROFILEPATHT, SIZEOF(tszOldPath), (LPARAM)tszOldPath); + _tcscat(tszOldPath, _T("\\*.book")); + + VARST ptszNewPath( _T("%miranda_userdata%")); + + SHFILEOPSTRUCT file_op = { + NULL, + FO_MOVE, + tszOldPath, + ptszNewPath, + FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT, + false, + 0, + _T("") }; + SHFileOperation(&file_op); + + _tcsncpy(szPath, ptszNewPath, cbPath); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + YAMNVar.hInst = hinstDLL; + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +#ifdef _DEBUG +static TCHAR unknownCP[1500] = {0}; +#endif +// The callback function +BOOL CALLBACK EnumSystemCodePagesProc(LPTSTR cpStr) +{ + //Convert code page string to number + UINT cp = _ttoi(cpStr); + if (!IsValidCodePage(cp)) + return TRUE; + + //Get Code Page name + CPINFOEX info; + if (GetCPInfoEx(cp, 0, &info)) { + #ifdef _DEBUG + BOOLEAN found = FALSE; + #endif + for (int i = 1;i<CPLENALL;i++) if (CodePageNamesAll[i].CP == cp) { + CodePageNamesAll[i].isValid = TRUE; + CPLENSUPP++; + #ifdef _DEBUG + found = TRUE; + #endif + break; + } + #ifdef _DEBUG + if (!found) { + _tcscat(unknownCP, info.CodePageName); + _tcscat(unknownCP, _T("\n")); + } + #endif + } + return TRUE; +} + +void CheckMenuItems() +{ + Menu_ShowItem(hMenuItemMain, db_get_b(NULL, YAMN_DBMODULE, YAMN_SHOWMAINMENU, 1) != 0); +} + +int SystemModulesLoaded(WPARAM, LPARAM) +{ + //Insert "Check mail (YAMN)" item to Miranda's menu + CLISTMENUITEM mi = { sizeof(mi) }; + mi.position = 0xb0000000; + mi.icolibItem = g_GetIconHandle(0); + mi.pszName = LPGEN("Check &mail (All Account)"); + mi.pszPopupName = NULL;//YAMN_DBMODULE; + mi.pszService = MS_YAMN_FORCECHECK; + hMenuItemMain = Menu_AddMainMenuItem(&mi); + + mi.pszName = LPGEN("Check &mail (This Account)"); + mi.pszContactOwner = YAMN_DBMODULE; + mi.pszService = MS_YAMN_CLISTCONTEXT; + hMenuItemCont = Menu_AddContactMenuItem(&mi); + + mi.icolibItem = g_GetIconHandle(1); + mi.pszName = LPGEN("Launch application"); + mi.pszContactOwner = YAMN_DBMODULE; + mi.pszService = MS_YAMN_CLISTCONTEXTAPP; + hMenuItemContApp = Menu_AddContactMenuItem(&mi); + + CheckMenuItems(); + + if (hAccountFolder = FoldersRegisterCustomPathT(LPGEN("YAMN"), LPGEN("YAMN Account Folder"), UserDirectory)) + FoldersGetCustomPathT(hAccountFolder, UserDirectory, MAX_PATH, UserDirectory); + + RegisterPOP3Plugin(0, 0); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static IconItem iconList[] = +{ + { LPGEN("Check mail"), "YAMN_Check", IDI_CHECKMAIL }, + { LPGEN("Launch application"), "YAMN_Launch", IDI_LAUNCHAPP }, + { LPGEN("New Mail"), "YAMN_NewMail", IDI_NEWMAIL }, + { LPGEN("Connect Fail"), "YAMN_ConnectFail", IDI_BADCONNECT }, +}; + +static void LoadIcons() +{ + Icon_Register(YAMNVar.hInst, "YAMN", iconList, SIZEOF(iconList)); +} + +HANDLE WINAPI g_GetIconHandle( int idx ) +{ + if ( idx >= SIZEOF(iconList)) + return NULL; + return iconList[idx].hIcolib; +} + +HICON WINAPI g_LoadIconEx( int idx, bool big ) +{ + if ( idx >= SIZEOF(iconList)) + return NULL; + return Skin_GetIcon(iconList[idx].szName, big); +} + +void WINAPI g_ReleaseIcon( HICON hIcon ) +{ + if ( hIcon ) Skin_ReleaseIcon(hIcon); +} + +static void LoadPlugins() +{ + TCHAR szSearchPath[MAX_PATH]; + mir_sntprintf(szSearchPath, MAX_PATH, _T("%s\\Plugins\\YAMN\\*.dll"), szMirandaDir); + + hDllPlugins = NULL; + + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(szSearchPath, &fd); + if (hFind != INVALID_HANDLE_VALUE) { + do { + //rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too + TCHAR *dot = _tcsrchr(fd.cFileName, '.'); + if (dot == NULL ) + continue; + + // we have a dot + int len = lstrlen(fd.cFileName); // find the length of the string + TCHAR* end = fd.cFileName+len; // get a pointer to the NULL + int safe = (end-dot)-1; // figure out how many chars after the dot are "safe", not including NULL + + if ((safe != 3) || (lstrcmpi(dot+1, _T("dll")) != 0)) //not bound, however the "dll" string should mean only 3 chars are compared + continue; + + TCHAR szPluginPath[MAX_PATH]; + mir_sntprintf(szPluginPath, MAX_PATH,_T("%s\\Plugins\\YAMN\\%s"), szMirandaDir, fd.cFileName); + HINSTANCE hDll = LoadLibrary(szPluginPath); + if (hDll == NULL) + continue; + + LOADFILTERFCN LoadFilter = (LOADFILTERFCN) GetProcAddress(hDll, "LoadFilter"); + if (NULL == LoadFilter) { + FreeLibrary(hDll); + hDll = NULL; + continue; + } + + if (!(*LoadFilter)(GetFcnPtrSvc)) { + FreeLibrary(hDll); + hDll = NULL; + } + + if (hDll != NULL) { + hDllPlugins = (HINSTANCE *)realloc((void *)hDllPlugins, (iDllPlugins+1)*sizeof(HINSTANCE)); + hDllPlugins[iDllPlugins++] = hDll; + } + } + while(FindNextFile(hFind, &fd)); + + FindClose(hFind); + } +} + +extern "C" int __declspec(dllexport) Load(void) +{ + mir_getLP(&pluginInfo); + + YAMN_STATUS = ID_STATUS_OFFLINE; + + // we get the Miranda Root Path + PathToAbsoluteT( _T("."), szMirandaDir); + + // retrieve the current profile name + CallService(MS_DB_GETPROFILENAMET, (WPARAM)SIZEOF(ProfileName), (LPARAM)ProfileName); //not to pass entire array to fcn + TCHAR *fc = _tcsrchr(ProfileName, '.'); + if ( fc != NULL ) *fc = 0; + + // we get the user path where our yamn-account.book.ini is stored from mirandaboot.ini file + GetProfileDirectory(UserDirectory, SIZEOF(UserDirectory)); + + // Enumerate all the code pages available for the System Locale + EnumSystemCodePages(EnumSystemCodePagesProc, CP_INSTALLED); + CodePageNamesSupp = new _tcptable[CPLENSUPP]; + for (int i = 0, k = 0; i < CPLENALL; i++) { + if (CodePageNamesAll[i].isValid) { + CodePageNamesSupp[k] = CodePageNamesAll[i]; + k++; + } } + + // Registering YAMN as protocol + PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE }; + pd.szName = YAMN_DBMODULE; + pd.type = PROTOTYPE_VIRTUAL; + CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); + + InitializeCriticalSection(&AccountStatusCS); + InitializeCriticalSection(&FileWritingCS); + InitializeCriticalSection(&PluginRegCS); + + if (NULL == (NoWriterEV = CreateEvent(NULL, TRUE, TRUE, NULL))) + return 1; + if (NULL == (WriteToFileEV = CreateEvent(NULL, FALSE, FALSE, NULL))) + return 1; + if (NULL == (ExitEV = CreateEvent(NULL, TRUE, FALSE, NULL))) + return 1; + + PosX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBPOSX, 0); + PosY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBPOSY, 0); + SizeX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBSIZEX, 800); + SizeY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBSIZEY, 200); + + HeadPosX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSX, 0); + HeadPosY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSY, 0); + HeadSizeX = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGSIZEX, 690); + HeadSizeY = db_get_dw(NULL, YAMN_DBMODULE, YAMN_DBMSGSIZEY, 300); + HeadSplitPos = db_get_w(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSSPLIT, 250); + + optDateTime = db_get_b(NULL, YAMN_DBMODULE, YAMN_DBTIMEOPTIONS, optDateTime); + + // Create new window queues for broadcast messages + YAMNVar.MessageWnds = WindowList_Create(); + YAMNVar.NewMailAccountWnd = WindowList_Create(); + YAMNVar.Shutdown = FALSE; + + hCurSplitNS = LoadCursor(NULL, IDC_SIZENS); + hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE); + +#ifdef _DEBUG + InitDebug(); +#endif + + CreateServiceFunctions(); + + SkinAddNewSoundEx(YAMN_NEWMAILSOUND, YAMN_DBMODULE, YAMN_NEWMAILSNDDESC); + SkinAddNewSoundEx(YAMN_CONNECTFAILSOUND, YAMN_DBMODULE, YAMN_CONNECTFAILSNDDESC); + + HookEvents(); + + LoadIcons(); + LoadPlugins(); + + HOTKEYDESC hkd = {0}; + hkd.cbSize = sizeof(hkd); + hkd.pszName = "YAMN_hotkey"; + hkd.pszService = MS_YAMN_FORCECHECK; + hkd.pszSection = YAMN_DBMODULE; + hkd.pszDescription = LPGEN("Check mail"); + hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, VK_F11); + Hotkey_Register(&hkd); + + //Create thread that will be executed every second + if (!(SecTimer = SetTimer(NULL, 0, 1000, TimerProc))) + return 1; + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static void UnloadPlugins() +{ + if (hDllPlugins == NULL) + return; + for (int i = iDllPlugins - 1; i >= 0; i --) { + if (FreeLibrary(hDllPlugins[i])) { + hDllPlugins[i] = NULL; //for safety + iDllPlugins --; + } + } + free((void *)hDllPlugins); + hDllPlugins = NULL; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ +#ifdef _DEBUG + UnInitDebug(); +#endif + + WindowList_Destroy(YAMNVar.MessageWnds); + WindowList_Destroy(YAMNVar.NewMailAccountWnd); + + DestroyCursor(hCurSplitNS); + DestroyCursor(hCurSplitWE); + + CloseHandle(NoWriterEV); + CloseHandle(WriteToFileEV); + CloseHandle(ExitEV); + + DeleteCriticalSection(&AccountStatusCS); + DeleteCriticalSection(&FileWritingCS); + DeleteCriticalSection(&PluginRegCS); + + UnhookEvents(); + DestroyServiceFunctions(); + + UnloadPlugins(); + + delete [] CodePageNamesSupp; + return 0; +} |