summaryrefslogtreecommitdiff
path: root/plugins/Dbx_mmap_SA/dbcontacts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Dbx_mmap_SA/dbcontacts.cpp')
-rw-r--r--plugins/Dbx_mmap_SA/dbcontacts.cpp299
1 files changed, 299 insertions, 0 deletions
diff --git a/plugins/Dbx_mmap_SA/dbcontacts.cpp b/plugins/Dbx_mmap_SA/dbcontacts.cpp
new file mode 100644
index 0000000000..51e533266d
--- /dev/null
+++ b/plugins/Dbx_mmap_SA/dbcontacts.cpp
@@ -0,0 +1,299 @@
+/*
+
+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 HANDLE hCacheHeap;
+extern SortedList lContacts;
+extern HANDLE hLastCachedContact;
+
+INT_PTR GetContactSettingStatic(WPARAM wParam,LPARAM lParam);
+void FreeCachedVariant( DBVARIANT* V );
+
+static INT_PTR GetContactCount(WPARAM wParam,LPARAM lParam);
+static INT_PTR FindFirstContact(WPARAM wParam,LPARAM lParam);
+static INT_PTR FindNextContact(WPARAM wParam,LPARAM lParam);
+static INT_PTR DeleteContact(WPARAM wParam,LPARAM lParam);
+static INT_PTR AddContact(WPARAM wParam,LPARAM lParam);
+static INT_PTR IsDbContact(WPARAM wParam,LPARAM lParam);
+
+static HANDLE hContactDeletedEvent,hContactAddedEvent;
+
+
+int InitContacts(void)
+{
+ CreateServiceFunction(MS_DB_CONTACT_GETCOUNT,GetContactCount);
+ CreateServiceFunction(MS_DB_CONTACT_FINDFIRST,FindFirstContact);
+ CreateServiceFunction(MS_DB_CONTACT_FINDNEXT,FindNextContact);
+ CreateServiceFunction(MS_DB_CONTACT_DELETE,DeleteContact);
+ CreateServiceFunction(MS_DB_CONTACT_ADD,AddContact);
+ CreateServiceFunction(MS_DB_CONTACT_IS,IsDbContact);
+ hContactDeletedEvent=CreateHookableEvent(ME_DB_CONTACT_DELETED);
+ hContactAddedEvent=CreateHookableEvent(ME_DB_CONTACT_ADDED);
+ return 0;
+}
+
+void UninitContacts(void)
+{
+}
+
+DBCachedContactValueList* AddToCachedContactList(HANDLE hContact, int index)
+{
+ DBCachedContactValueList* VL;
+ VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList));
+ VL->hContact = hContact;
+ if (index == -1) li.List_GetIndex(&lContacts,VL,&index);
+ li.List_Insert(&lContacts,VL,index);
+ return VL;
+}
+
+static INT_PTR GetContactCount(WPARAM wParam,LPARAM lParam)
+{
+ int ret;
+
+ EnterCriticalSection(&csDbAccess);
+ ret=dbHeader.contactCount;
+ LeaveCriticalSection(&csDbAccess);
+ return ret;
+}
+
+#define proto_module "Protocol"
+#define proto_setting "p"
+
+static int CheckProto(HANDLE hContact, const char *proto)
+{
+ static char protobuf[MAX_PATH] = {0};
+ static DBVARIANT dbv;
+ static DBCONTACTGETSETTING sVal = {proto_module,proto_setting,&dbv};
+
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = protobuf;
+ dbv.cchVal = sizeof(protobuf);
+
+ if (GetContactSettingStatic((WPARAM)hContact, (LPARAM )&sVal) != 0
+ || (dbv.type != DBVT_ASCIIZ)) return 0;
+
+ return !strcmp(protobuf,proto);
+}
+
+static INT_PTR FindFirstContact(WPARAM wParam,LPARAM lParam)
+{
+ INT_PTR ret = 0;
+ EnterCriticalSection(&csDbAccess);
+ ret = (INT_PTR)dbHeader.ofsFirstContact;
+ if (lParam && !CheckProto((HANDLE)ret,(const char*)lParam))
+ ret = FindNextContact((WPARAM)ret,lParam);
+ LeaveCriticalSection(&csDbAccess);
+ return ret;
+}
+
+static INT_PTR FindNextContact(WPARAM wParam,LPARAM lParam)
+{
+ int index;
+ struct DBContact *dbc;
+ DBCachedContactValueList VLtemp, *VL = NULL;
+ VLtemp.hContact = (HANDLE)wParam;
+ EnterCriticalSection(&csDbAccess);
+ while(VLtemp.hContact) {
+ if ( li.List_GetIndex(&lContacts,&VLtemp,&index)) {
+ VL = ( DBCachedContactValueList* )lContacts.items[index];
+ if (VL->hNext != NULL) {
+ if (!lParam || CheckProto(VL->hNext,(const char*)lParam)) {
+ LeaveCriticalSection(&csDbAccess);
+ return (INT_PTR)VL->hNext;
+ }
+ else {
+ VLtemp.hContact = VL->hNext;
+ continue;
+ } } }
+
+ dbc=(struct DBContact*)DBRead((DWORD)VLtemp.hContact,sizeof(struct DBContact),NULL);
+ if (dbc->signature!=DBCONTACT_SIGNATURE)
+ break;
+ else {
+ if ( VL == NULL )
+ VL = AddToCachedContactList(VLtemp.hContact,index);
+
+ VL->hNext = (HANDLE)dbc->ofsNext;
+ if (VL->hNext != NULL && (!lParam || CheckProto(VL->hNext,(const char*)lParam))) {
+ LeaveCriticalSection(&csDbAccess);
+ return (INT_PTR)VL->hNext;
+ }
+ VLtemp.hContact = VL->hNext;
+ } }
+ LeaveCriticalSection(&csDbAccess);
+ return 0;
+}
+
+static INT_PTR DeleteContact(WPARAM wParam,LPARAM lParam)
+{
+ struct DBContact *dbc,*dbcPrev;
+ DWORD ofsThis,ofsNext,ofsFirstEvent;
+ struct DBContactSettings *dbcs;
+ struct DBEvent *dbe;
+ int index;
+
+ if ((HANDLE)wParam==NULL) return 1;
+ EnterCriticalSection(&csDbAccess);
+ dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL);
+ if(dbc->signature!=DBCONTACT_SIGNATURE) {
+ LeaveCriticalSection(&csDbAccess);
+ return 1;
+ }
+ if ( (HANDLE)wParam == (HANDLE)dbHeader.ofsUser ) {
+ LeaveCriticalSection(&csDbAccess);
+ log0("FATAL: del of user chain attempted.");
+ return 1;
+ }
+ log0("del contact");
+ LeaveCriticalSection(&csDbAccess);
+ //call notifier while outside mutex
+ NotifyEventHooks(hContactDeletedEvent,wParam,0);
+ //get back in
+ EnterCriticalSection(&csDbAccess);
+
+ { DBCachedContactValueList VLtemp;
+ VLtemp.hContact = (HANDLE)wParam;
+ if ( li.List_GetIndex(&lContacts,&VLtemp,&index))
+ {
+ DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index];
+ DBCachedContactValue* V = VL->first;
+ while ( V != NULL ) {
+ DBCachedContactValue* V1 = V->next;
+ FreeCachedVariant(&V->value);
+ HeapFree( hCacheHeap, 0, V );
+ V = V1;
+ }
+ HeapFree( hCacheHeap, 0, VL );
+
+ if (VLtemp.hContact == hLastCachedContact)
+ hLastCachedContact = NULL;
+ li.List_Remove(&lContacts,index);
+ } }
+
+ dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL);
+ //delete settings chain
+ ofsThis=dbc->ofsFirstSettings;
+ ofsFirstEvent=dbc->ofsFirstEvent;
+ while(ofsThis) {
+ dbcs=(struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL);
+ ofsNext=dbcs->ofsNext;
+ DeleteSpace(ofsThis,offsetof(struct DBContactSettings,blob)+dbcs->cbBlob);
+ ofsThis=ofsNext;
+ }
+ //delete event chain
+ ofsThis=ofsFirstEvent;
+ while(ofsThis) {
+ dbe=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL);
+ ofsNext=dbe->ofsNext;
+ DeleteSpace(ofsThis,offsetof(struct DBEvent,blob)+dbe->cbBlob);
+ ofsThis=ofsNext;
+ }
+ //find previous contact in chain and change ofsNext
+ dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL);
+ if(dbHeader.ofsFirstContact==wParam) {
+ dbHeader.ofsFirstContact=dbc->ofsNext;
+ DBWrite(0,&dbHeader,sizeof(dbHeader));
+ }
+ else {
+ ofsNext=dbc->ofsNext;
+ ofsThis=dbHeader.ofsFirstContact;
+ dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL);
+ while(dbcPrev->ofsNext!=wParam) {
+ if(dbcPrev->ofsNext==0) DatabaseCorruption(NULL);
+ ofsThis=dbcPrev->ofsNext;
+ dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL);
+ }
+ dbcPrev->ofsNext=ofsNext;
+ DBWrite(ofsThis,dbcPrev,sizeof(struct DBContact));
+ {
+ DBCachedContactValueList VLtemp;
+ VLtemp.hContact = (HANDLE)ofsThis;
+ if ( li.List_GetIndex(&lContacts,&VLtemp,&index))
+ {
+ DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index];
+ VL->hNext = ( HANDLE )ofsNext;
+ } }
+ }
+ //delete contact
+ DeleteSpace(wParam,sizeof(struct DBContact));
+ //decrement contact count
+ dbHeader.contactCount--;
+ DBWrite(0,&dbHeader,sizeof(dbHeader));
+ DBFlush(0);
+ //quit
+ LeaveCriticalSection(&csDbAccess);
+ return 0;
+}
+
+static INT_PTR AddContact(WPARAM wParam,LPARAM lParam)
+{
+ struct DBContact dbc;
+ DWORD ofsNew;
+
+ log0("add contact");
+ EnterCriticalSection(&csDbAccess);
+ ofsNew=CreateNewSpace(sizeof(struct DBContact));
+ dbc.signature=DBCONTACT_SIGNATURE;
+ dbc.eventCount=0;
+ dbc.ofsFirstEvent=dbc.ofsLastEvent=0;
+ dbc.ofsFirstSettings=0;
+ dbc.ofsNext=dbHeader.ofsFirstContact;
+ dbc.ofsFirstUnreadEvent=0;
+ dbc.timestampFirstUnread=0;
+ dbHeader.ofsFirstContact=ofsNew;
+ dbHeader.contactCount++;
+ DBWrite(ofsNew,&dbc,sizeof(struct DBContact));
+ DBWrite(0,&dbHeader,sizeof(dbHeader));
+ DBFlush(0);
+
+ AddToCachedContactList((HANDLE)ofsNew, -1);
+
+ LeaveCriticalSection(&csDbAccess);
+ NotifyEventHooks(hContactAddedEvent,(WPARAM)ofsNew,0);
+ return (INT_PTR)ofsNew;
+}
+
+static INT_PTR IsDbContact(WPARAM wParam,LPARAM lParam)
+{
+ struct DBContact *dbc;
+ DWORD ofsContact=(DWORD)wParam;
+ int ret;
+
+ EnterCriticalSection(&csDbAccess);
+ {
+ int index;
+ DBCachedContactValueList VLtemp;
+ VLtemp.hContact = (HANDLE)wParam;
+ if ( li.List_GetIndex(&lContacts,&VLtemp,&index))
+ ret = TRUE;
+ else {
+ dbc=(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL);
+ ret=dbc->signature==DBCONTACT_SIGNATURE;
+ if (ret)
+ AddToCachedContactList((HANDLE)wParam, index);
+ } }
+
+ LeaveCriticalSection(&csDbAccess);
+ return ret;
+}