From 1204c8ca267a83f1df6b8087bbfc5335ffb5090d Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sat, 23 Jun 2012 17:30:56 +0000 Subject: Db3x_mmap: renamed to .cpp git-svn-id: http://svn.miranda-ng.org/main/trunk@575 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Db3x_mmap/dbevents.cpp | 449 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 449 insertions(+) create mode 100644 plugins/Db3x_mmap/dbevents.cpp (limited to 'plugins/Db3x_mmap/dbevents.cpp') diff --git a/plugins/Db3x_mmap/dbevents.cpp b/plugins/Db3x_mmap/dbevents.cpp new file mode 100644 index 0000000000..5576455daf --- /dev/null +++ b/plugins/Db3x_mmap/dbevents.cpp @@ -0,0 +1,449 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + +extern BOOL safetyMode; + +DWORD GetModuleNameOfs(const char *szName); +char *GetModuleNameByOfs(DWORD ofs); + +static INT_PTR GetEventCount(WPARAM wParam,LPARAM lParam); +static INT_PTR AddEvent(WPARAM wParam,LPARAM lParam); +static INT_PTR DeleteEvent(WPARAM wParam,LPARAM lParam); +static INT_PTR GetBlobSize(WPARAM wParam,LPARAM lParam); +static INT_PTR GetEvent(WPARAM wParam,LPARAM lParam); +static INT_PTR MarkEventRead(WPARAM wParam,LPARAM lParam); +static INT_PTR GetEventContact(WPARAM wParam,LPARAM lParam); +static INT_PTR FindFirstEvent(WPARAM wParam,LPARAM lParam); +static INT_PTR FindFirstUnreadEvent(WPARAM wParam,LPARAM lParam); +static INT_PTR FindLastEvent(WPARAM wParam,LPARAM lParam); +static INT_PTR FindNextEvent(WPARAM wParam,LPARAM lParam); +static INT_PTR FindPrevEvent(WPARAM wParam,LPARAM lParam); + +static HANDLE hEventDeletedEvent,hEventAddedEvent,hEventFilterAddedEvent; + +int InitEvents(void) +{ + CreateServiceFunction(MS_DB_EVENT_GETCOUNT,GetEventCount); + CreateServiceFunction(MS_DB_EVENT_ADD,AddEvent); + CreateServiceFunction(MS_DB_EVENT_DELETE,DeleteEvent); + CreateServiceFunction(MS_DB_EVENT_GETBLOBSIZE,GetBlobSize); + CreateServiceFunction(MS_DB_EVENT_GET,GetEvent); + CreateServiceFunction(MS_DB_EVENT_MARKREAD,MarkEventRead); + CreateServiceFunction(MS_DB_EVENT_GETCONTACT,GetEventContact); + CreateServiceFunction(MS_DB_EVENT_FINDFIRST,FindFirstEvent); + CreateServiceFunction(MS_DB_EVENT_FINDFIRSTUNREAD,FindFirstUnreadEvent); + CreateServiceFunction(MS_DB_EVENT_FINDLAST,FindLastEvent); + CreateServiceFunction(MS_DB_EVENT_FINDNEXT,FindNextEvent); + CreateServiceFunction(MS_DB_EVENT_FINDPREV,FindPrevEvent); + hEventDeletedEvent=CreateHookableEvent(ME_DB_EVENT_DELETED); + hEventAddedEvent=CreateHookableEvent(ME_DB_EVENT_ADDED); + hEventFilterAddedEvent=CreateHookableEvent(ME_DB_EVENT_FILTER_ADD); + return 0; +} + +void UninitEvents(void) +{ +} + +static INT_PTR GetEventCount(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=-1; + else ret=dbc->eventCount; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR AddEvent(WPARAM wParam,LPARAM lParam) +{ + DBEVENTINFO *dbei=(DBEVENTINFO*)lParam; + struct DBContact dbc; + struct DBEvent dbe,*dbeTest; + DWORD ofsNew,ofsModuleName,ofsContact,ofsThis; + BOOL neednotify; + + if(dbei==NULL||dbei->cbSize!=sizeof(DBEVENTINFO)) return 0; + if(dbei->timestamp==0) return 0; + if (NotifyEventHooks(hEventFilterAddedEvent,wParam,lParam)) { + return 0; + } + EnterCriticalSection(&csDbAccess); + if(wParam==0) ofsContact=dbHeader.ofsUser; + else ofsContact=(DWORD)wParam; + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + if(dbc.signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 0; + } + ofsNew=CreateNewSpace(offsetof(struct DBEvent,blob)+dbei->cbBlob); + ofsModuleName=GetModuleNameOfs(dbei->szModule); + + dbe.signature=DBEVENT_SIGNATURE; + dbe.ofsModuleName=ofsModuleName; + dbe.timestamp=dbei->timestamp; + dbe.flags=dbei->flags; + dbe.eventType=dbei->eventType; + dbe.cbBlob=dbei->cbBlob; + //find where to put it - sort by timestamp + if(dbc.eventCount==0) { + dbe.ofsPrev=wParam; + dbe.ofsNext=0; + dbe.flags|=DBEF_FIRST; + dbc.ofsFirstEvent=dbc.ofsLastEvent=ofsNew; + } + else { + dbeTest=(struct DBEvent*)DBRead(dbc.ofsFirstEvent,sizeof(struct DBEvent),NULL); + // Should new event be placed before first event in chain? + if (dbei->timestamp < dbeTest->timestamp) { + dbe.ofsPrev=wParam; + dbe.ofsNext=dbc.ofsFirstEvent; + dbe.flags|=DBEF_FIRST; + dbc.ofsFirstEvent=ofsNew; + dbeTest=(struct DBEvent*)DBRead(dbe.ofsNext,sizeof(struct DBEvent),NULL); + dbeTest->flags&=~DBEF_FIRST; + dbeTest->ofsPrev=ofsNew; + DBWrite(dbe.ofsNext,dbeTest,sizeof(struct DBEvent)); + } + else { + // Loop through the chain, starting at the end + ofsThis = dbc.ofsLastEvent; + dbeTest = (struct DBEvent*)DBRead(ofsThis, sizeof(struct DBEvent), NULL); + for (;;) { + // If the new event's timesstamp is equal to or greater than the + // current dbevent, it will be inserted after. If not, continue + // with the previous dbevent in chain. + if (dbe.timestamp >= dbeTest->timestamp) { + dbe.ofsPrev = ofsThis; + dbe.ofsNext = dbeTest->ofsNext; + dbeTest->ofsNext = ofsNew; + DBWrite(ofsThis, dbeTest, sizeof(struct DBEvent)); + if (dbe.ofsNext == 0) + dbc.ofsLastEvent = ofsNew; + else { + dbeTest = (struct DBEvent*)DBRead(dbe.ofsNext, sizeof(struct DBEvent), NULL); + dbeTest->ofsPrev = ofsNew; + DBWrite(dbe.ofsNext, dbeTest, sizeof(struct DBEvent)); + } + break; + } + ofsThis = dbeTest->ofsPrev; + dbeTest = (struct DBEvent*)DBRead(ofsThis, sizeof(struct DBEvent), NULL); + } + } + } + dbc.eventCount++; + if (!(dbe.flags&(DBEF_READ|DBEF_SENT))) { + if(dbe.timestamppBlob,dbei->cbBlob); + DBFlush(0); + + LeaveCriticalSection(&csDbAccess); + log1("add event @ %08x",ofsNew); + + // Notify only in safe mode or on really new events + if (neednotify) + NotifyEventHooks(hEventAddedEvent,wParam,(LPARAM)ofsNew); + + return (INT_PTR)ofsNew; +} + +static INT_PTR DeleteEvent(WPARAM wParam,LPARAM lParam) +{ + struct DBContact dbc; + DWORD ofsContact,ofsThis; + struct DBEvent dbe,*dbeNext,*dbePrev; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) ofsContact=dbHeader.ofsUser; + else ofsContact=wParam; + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + dbe=*(struct DBEvent*)DBRead(lParam,sizeof(struct DBEvent),NULL); + if(dbc.signature!=DBCONTACT_SIGNATURE || dbe.signature!=DBEVENT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + log1("delete event @ %08x",wParam); + LeaveCriticalSection(&csDbAccess); + //call notifier while outside mutex + NotifyEventHooks(hEventDeletedEvent,wParam,lParam); + //get back in + EnterCriticalSection(&csDbAccess); + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + dbe=*(struct DBEvent*)DBRead(lParam,sizeof(struct DBEvent),NULL); + //check if this was the first unread, if so, recalc the first unread + if(dbc.ofsFirstUnreadEvent==(DWORD)lParam) { + dbeNext=&dbe; + for (;;) { + if(dbeNext->ofsNext==0) { + dbc.ofsFirstUnreadEvent=0; + dbc.timestampFirstUnread=0; + break; + } + ofsThis=dbeNext->ofsNext; + dbeNext=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL); + if (!(dbeNext->flags&(DBEF_READ|DBEF_SENT))) { + dbc.ofsFirstUnreadEvent=ofsThis; + dbc.timestampFirstUnread=dbeNext->timestamp; + break; + } + } + } + //get previous and next events in chain and change offsets + if(dbe.flags&DBEF_FIRST) { + if(dbe.ofsNext==0) { + dbc.ofsFirstEvent=dbc.ofsLastEvent=0; + } + else { + dbeNext=(struct DBEvent*)DBRead(dbe.ofsNext,sizeof(struct DBEvent),NULL); + dbeNext->flags|=DBEF_FIRST; + dbeNext->ofsPrev=dbe.ofsPrev; + DBWrite(dbe.ofsNext,dbeNext,sizeof(struct DBEvent)); + dbc.ofsFirstEvent=dbe.ofsNext; + } + } + else { + if(dbe.ofsNext==0) { + dbePrev=(struct DBEvent*)DBRead(dbe.ofsPrev,sizeof(struct DBEvent),NULL); + dbePrev->ofsNext=0; + DBWrite(dbe.ofsPrev,dbePrev,sizeof(struct DBEvent)); + dbc.ofsLastEvent=dbe.ofsPrev; + } + else { + dbePrev=(struct DBEvent*)DBRead(dbe.ofsPrev,sizeof(struct DBEvent),NULL); + dbePrev->ofsNext=dbe.ofsNext; + DBWrite(dbe.ofsPrev,dbePrev,sizeof(struct DBEvent)); + dbeNext=(struct DBEvent*)DBRead(dbe.ofsNext,sizeof(struct DBEvent),NULL); + dbeNext->ofsPrev=dbe.ofsPrev; + DBWrite(dbe.ofsNext,dbeNext,sizeof(struct DBEvent)); + } + } + //delete event + DeleteSpace(lParam,offsetof(struct DBEvent,blob)+dbe.cbBlob); + //decrement event count + dbc.eventCount--; + DBWrite(ofsContact,&dbc,sizeof(struct DBContact)); + DBFlush(0); + //quit + LeaveCriticalSection(&csDbAccess); + return 0; +} + +static INT_PTR GetBlobSize(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) ret=-1; + else ret=dbe->cbBlob; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR GetEvent(WPARAM wParam,LPARAM lParam) +{ + struct DBEvent *dbe; + DBEVENTINFO *dbei=(DBEVENTINFO*)lParam; + int bytesToCopy,i; + + if(dbei==NULL||dbei->cbSize!=sizeof(DBEVENTINFO)) return 1; + if(dbei->cbBlob>0 && dbei->pBlob==NULL) { + dbei->cbBlob = 0; + return 1; + } + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + dbei->szModule=GetModuleNameByOfs(dbe->ofsModuleName); + dbei->timestamp=dbe->timestamp; + dbei->flags=dbe->flags; + dbei->eventType=dbe->eventType; + if(dbei->cbBlobcbBlob) bytesToCopy=dbei->cbBlob; + else bytesToCopy=dbe->cbBlob; + dbei->cbBlob=dbe->cbBlob; + if (bytesToCopy && dbei->pBlob) + { + for(i=0;;i+=MAXCACHEDREADSIZE) { + if(bytesToCopy-i<=MAXCACHEDREADSIZE) { + CopyMemory(dbei->pBlob+i,DBRead(wParam+offsetof(struct DBEvent,blob)+i,bytesToCopy-i,NULL),bytesToCopy-i); + break; + } + CopyMemory(dbei->pBlob+i,DBRead(wParam+offsetof(struct DBEvent,blob)+i,MAXCACHEDREADSIZE,NULL),MAXCACHEDREADSIZE); + } + } + LeaveCriticalSection(&csDbAccess); + return 0; +} + +static INT_PTR MarkEventRead(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBEvent *dbe; + struct DBContact dbc; + DWORD ofsThis; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=*(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + dbe=(struct DBEvent*)DBRead(lParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE || dbc.signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return -1; + } + if(dbe->flags&DBEF_READ || dbe->flags&DBEF_SENT) { + ret=(INT_PTR)dbe->flags; + LeaveCriticalSection(&csDbAccess); + return ret; + } + log1("mark read @ %08x",wParam); + dbe->flags|=DBEF_READ; + DBWrite(lParam,dbe,sizeof(struct DBEvent)); + ret=(int)dbe->flags; + if(dbc.ofsFirstUnreadEvent==(DWORD)lParam) { + for (;;) { + if(dbe->ofsNext==0) { + dbc.ofsFirstUnreadEvent=0; + dbc.timestampFirstUnread=0; + break; + } + ofsThis=dbe->ofsNext; + dbe=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL); + if (!(dbe->flags&(DBEF_READ|DBEF_SENT))) { + dbc.ofsFirstUnreadEvent=ofsThis; + dbc.timestampFirstUnread=dbe->timestamp; + break; + } + } + } + DBWrite(wParam,&dbc,sizeof(struct DBContact)); + DBFlush(0); + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR GetEventContact(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return -1; + } + while(!(dbe->flags&DBEF_FIRST)) + dbe=(struct DBEvent*)DBRead(dbe->ofsPrev,sizeof(struct DBEvent),NULL); + ret=(INT_PTR)dbe->ofsPrev; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR FindFirstEvent(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=0; + else ret=(INT_PTR)dbc->ofsFirstEvent; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR FindFirstUnreadEvent(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=0; + else ret=(INT_PTR)dbc->ofsFirstUnreadEvent; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR FindLastEvent(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=0; + else ret=(INT_PTR)dbc->ofsLastEvent; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR FindNextEvent(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) ret=0; + else ret=(INT_PTR)dbe->ofsNext; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static INT_PTR FindPrevEvent(WPARAM wParam,LPARAM lParam) +{ + INT_PTR ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) ret=0; + else if(dbe->flags&DBEF_FIRST) ret=0; + else ret=(INT_PTR)dbe->ofsPrev; + LeaveCriticalSection(&csDbAccess); + return ret; +} -- cgit v1.2.3