From 75115d35a7477110938f056a18edbbd43ac9a840 Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Mon, 23 Jul 2012 21:15:40 +0000
Subject: db3x, finally

git-svn-id: http://svn.miranda-ng.org/main/trunk@1144 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 plugins/Db3x/db3x_10.vcxproj         |  21 +-
 plugins/Db3x/db3x_10.vcxproj.filters |  42 +-
 plugins/Db3x/src/commonheaders.h     |  12 +-
 plugins/Db3x/src/database.cpp        | 153 ------
 plugins/Db3x/src/database.h          | 217 --------
 plugins/Db3x/src/dbcache.cpp         | 222 --------
 plugins/Db3x/src/dbcache3x.cpp       | 198 +++++++
 plugins/Db3x/src/dbcontacts.cpp      | 276 ----------
 plugins/Db3x/src/dbevents.cpp        | 407 ---------------
 plugins/Db3x/src/dbheaders.cpp       |  74 ---
 plugins/Db3x/src/dbintf.cpp          |  38 --
 plugins/Db3x/src/dbintf.h            |  68 ---
 plugins/Db3x/src/dbintf3x.cpp        |  77 +++
 plugins/Db3x/src/dbintf3x.h          |  74 +++
 plugins/Db3x/src/dbmodulechain.cpp   | 128 -----
 plugins/Db3x/src/dbsettings.cpp      | 971 -----------------------------------
 plugins/Db3x/src/init.cpp            | 156 +++---
 17 files changed, 459 insertions(+), 2675 deletions(-)
 delete mode 100644 plugins/Db3x/src/database.cpp
 delete mode 100644 plugins/Db3x/src/database.h
 delete mode 100644 plugins/Db3x/src/dbcache.cpp
 create mode 100644 plugins/Db3x/src/dbcache3x.cpp
 delete mode 100644 plugins/Db3x/src/dbcontacts.cpp
 delete mode 100644 plugins/Db3x/src/dbevents.cpp
 delete mode 100644 plugins/Db3x/src/dbheaders.cpp
 delete mode 100644 plugins/Db3x/src/dbintf.cpp
 delete mode 100644 plugins/Db3x/src/dbintf.h
 create mode 100644 plugins/Db3x/src/dbintf3x.cpp
 create mode 100644 plugins/Db3x/src/dbintf3x.h
 delete mode 100644 plugins/Db3x/src/dbmodulechain.cpp
 delete mode 100644 plugins/Db3x/src/dbsettings.cpp

(limited to 'plugins/Db3x')

diff --git a/plugins/Db3x/db3x_10.vcxproj b/plugins/Db3x/db3x_10.vcxproj
index 441e103858..68f34fdd90 100644
--- a/plugins/Db3x/db3x_10.vcxproj
+++ b/plugins/Db3x/db3x_10.vcxproj
@@ -199,22 +199,23 @@
     </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include="src\database.cpp" />
-    <ClCompile Include="src\dbcache.cpp" />
-    <ClCompile Include="src\dbcontacts.cpp" />
-    <ClCompile Include="src\dbevents.cpp" />
-    <ClCompile Include="src\dbheaders.cpp" />
-    <ClCompile Include="src\dbintf.cpp" />
-    <ClCompile Include="src\dbmodulechain.cpp" />
-    <ClCompile Include="src\dbsettings.cpp" />
+    <ClCompile Include="..\db3x_mmap\src\database.cpp" />
+    <ClCompile Include="..\db3x_mmap\src\dbcontacts.cpp" />
+    <ClCompile Include="..\db3x_mmap\src\dbevents.cpp" />
+    <ClCompile Include="..\db3x_mmap\src\dbheaders.cpp" />
+    <ClCompile Include="..\db3x_mmap\src\dbintf.cpp" />
+    <ClCompile Include="..\db3x_mmap\src\dbmodulechain.cpp" />
+    <ClCompile Include="..\db3x_mmap\src\dbsettings.cpp" />
+    <ClCompile Include="src\dbcache3x.cpp" />
+    <ClCompile Include="src\dbintf3x.cpp" />
     <ClCompile Include="src\init.cpp">
       <PrecompiledHeader>Create</PrecompiledHeader>
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\db3x_mmap\dbintf.h" />
     <ClInclude Include="src\commonheaders.h" />
-    <ClInclude Include="src\database.h" />
-    <ClInclude Include="src\dbintf.h" />
+    <ClInclude Include="src\dbintf3x.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="res\resource.rc" />
diff --git a/plugins/Db3x/db3x_10.vcxproj.filters b/plugins/Db3x/db3x_10.vcxproj.filters
index 682ea4edc7..a5829dde98 100644
--- a/plugins/Db3x/db3x_10.vcxproj.filters
+++ b/plugins/Db3x/db3x_10.vcxproj.filters
@@ -13,45 +13,51 @@
       <UniqueIdentifier>{fbaceae7-3e4a-4853-96f3-eec77981b2c9}</UniqueIdentifier>
       <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
     </Filter>
+    <Filter Include="Mmap">
+      <UniqueIdentifier>{640c5715-0e22-4240-8520-f7dedfc9fb87}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="src\database.cpp">
+    <ClCompile Include="src\init.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="src\dbcache.cpp">
+    <ClCompile Include="src\dbintf3x.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="src\dbcontacts.cpp">
-      <Filter>Source Files</Filter>
+    <ClCompile Include="..\db3x_mmap\src\database.cpp">
+      <Filter>Mmap</Filter>
     </ClCompile>
-    <ClCompile Include="src\dbevents.cpp">
+    <ClCompile Include="src\dbcache3x.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="src\dbheaders.cpp">
-      <Filter>Source Files</Filter>
+    <ClCompile Include="..\db3x_mmap\src\dbcontacts.cpp">
+      <Filter>Mmap</Filter>
     </ClCompile>
-    <ClCompile Include="src\dbmodulechain.cpp">
-      <Filter>Source Files</Filter>
+    <ClCompile Include="..\db3x_mmap\src\dbevents.cpp">
+      <Filter>Mmap</Filter>
     </ClCompile>
-    <ClCompile Include="src\dbsettings.cpp">
-      <Filter>Source Files</Filter>
+    <ClCompile Include="..\db3x_mmap\src\dbheaders.cpp">
+      <Filter>Mmap</Filter>
     </ClCompile>
-    <ClCompile Include="src\init.cpp">
-      <Filter>Source Files</Filter>
+    <ClCompile Include="..\db3x_mmap\src\dbintf.cpp">
+      <Filter>Mmap</Filter>
     </ClCompile>
-    <ClCompile Include="src\dbintf.cpp">
-      <Filter>Source Files</Filter>
+    <ClCompile Include="..\db3x_mmap\src\dbmodulechain.cpp">
+      <Filter>Mmap</Filter>
+    </ClCompile>
+    <ClCompile Include="..\db3x_mmap\src\dbsettings.cpp">
+      <Filter>Mmap</Filter>
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\commonheaders.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="src\database.h">
+    <ClInclude Include="src\dbintf3x.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="src\dbintf.h">
-      <Filter>Header Files</Filter>
+    <ClInclude Include="..\db3x_mmap\dbintf.h">
+      <Filter>Mmap</Filter>
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
diff --git a/plugins/Db3x/src/commonheaders.h b/plugins/Db3x/src/commonheaders.h
index 52734be2d0..5175ad67b9 100644
--- a/plugins/Db3x/src/commonheaders.h
+++ b/plugins/Db3x/src/commonheaders.h
@@ -49,17 +49,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include <m_langpack.h>
 
 #include "version.h"
-#include "database.h"
-#include "dbintf.h"
+#include "dbintf3x.h"
 #include "resource.h"
 
-extern HANDLE hDbFile;
-extern CRITICAL_SECTION csDbAccess;
-extern struct DBHeader dbHeader;
-extern HANDLE hCacheHeap;
-extern SortedList lContacts;
-extern TCHAR szDbPath[MAX_PATH];
-
 #ifdef __GNUC__
 #define mir_i64(x) (x##LL)
 #else
@@ -69,3 +61,5 @@ extern TCHAR szDbPath[MAX_PATH];
 #ifndef MODULAR
 void Encrypt(char*msg,BOOL up);
 #endif
+
+extern LIST<CDb3x> g_Dbs;
diff --git a/plugins/Db3x/src/database.cpp b/plugins/Db3x/src/database.cpp
deleted file mode 100644
index 50d51dde81..0000000000
--- a/plugins/Db3x/src/database.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-
-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"
-
-int ProfileManager(char *szDbDest,int cbDbDest);
-int ShouldAutoCreate(void);
-int CreateDbHeaders(HANDLE hFile);
-int InitialiseDbHeaders(void);
-int InitSettings(void);
-void UninitSettings(void);
-int InitContacts(void);
-void UninitContacts(void);
-int InitEvents(void);
-int InitModuleNames(void);
-void UninitModuleNames(void);
-int InitCache(void);
-void UninitCache(void);
-int InitIni(void);
-void UninitIni(void);
-
-HANDLE hDbFile = INVALID_HANDLE_VALUE;
-CRITICAL_SECTION csDbAccess;
-struct DBHeader dbHeader;
-TCHAR szDbPath[MAX_PATH];
-
-static void UnloadDatabase(void)
-{
-	CloseHandle(hDbFile);
-}
-
-DWORD CreateNewSpace(int bytes)
-{
-	DWORD ofsNew;
-
-	ofsNew = dbHeader.ofsFileEnd;
-	dbHeader.ofsFileEnd += bytes;
-	DBWrite(0,&dbHeader,sizeof(dbHeader));
-	log2("newspace %d@%08x",bytes,ofsNew);
-	return ofsNew;
-}
-
-void DeleteSpace(DWORD ofs,int bytes)
-{
-	PBYTE buf;
-	log2("deletespace %d@%08x",bytes,ofs);
-	dbHeader.slackSpace += bytes;
-	DBWrite(0,&dbHeader,sizeof(dbHeader));
-	buf = (PBYTE)mir_alloc(bytes);
-	memset(buf,0,bytes);
-	DBWrite(ofs,buf,bytes);
-	mir_free(buf);
-}
-
-void UnloadDatabaseModule(void)
-{
-	UninitSettings();
-	UninitContacts();
-	UninitModuleNames();
-	UninitCache();
-	UnloadDatabase();
-	DeleteCriticalSection(&csDbAccess);
-}
-
-int LoadDatabaseModule(void)
-{
-	InitializeCriticalSection(&csDbAccess);
-	log0("DB logging running");
-	{
-		DWORD dummy = 0;
-		hDbFile = CreateFile(szDbPath,GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
-		if ( hDbFile == INVALID_HANDLE_VALUE ) {
-			return 1;
-		}
-		if ( !ReadFile(hDbFile,&dbHeader,sizeof(dbHeader),&dummy,NULL)) {
-			CloseHandle(hDbFile);
-			return 1;
-		}
-	}
-	//if (ParseCommandLine()) return 1;
-	if (InitCache()) return 1;
-	if (InitModuleNames()) return 1;
-	if (InitContacts()) return 1;
-	if (InitSettings()) return 1;
-	if (InitEvents()) return 1;
-	return 0;
-}
-
-static DWORD DatabaseCorrupted = 0;
-
-void __cdecl dbpanic(void *arg)
-{
-	MessageBox(0,TranslateT("Miranda has detected corruption in your database. This corruption maybe fixed by DBTool.  Please download it from http://nightly.miranda.im/. Miranda will now shutdown."),TranslateT("Database Panic"),MB_SETFOREGROUND|MB_TOPMOST|MB_APPLMODAL|MB_ICONWARNING|MB_OK);
-	TerminateProcess(GetCurrentProcess(),255);
-	return;
-}
-
-void DatabaseCorruption(void)
-{
-	int kill = 0;
-
-	EnterCriticalSection(&csDbAccess);
-	if (DatabaseCorrupted == 0) {
-		DatabaseCorrupted++;
-		kill++;
-	} else {
-		/* db is already corrupted, someone else is dealing with it, wait here
-		so that we don't do any more damage */
-		LeaveCriticalSection(&csDbAccess);
-		Sleep(INFINITE);
-		return;
-	}
-	LeaveCriticalSection(&csDbAccess);
-	if (kill) {
-		_beginthread(dbpanic,0,NULL);
-		Sleep(INFINITE);
-	}
-}
-
-#ifdef DBLOGGING
-void DBLog(const char *file,int line,const char *fmt,...)
-{
-	FILE *fp;
-	va_list vararg;
-	char str[1024];
-
-	va_start(vararg,fmt);
-	mir_vsnprintf(str,sizeof(str),fmt,vararg);
-	va_end(vararg);
-	fp = fopen("c:\\mirandadatabase.log.txt","at");
-	fprintf(fp,"%u: %s %d: %s\n",GetTickCount(),file,line,str);
-	fclose(fp);
-}
-#endif
diff --git a/plugins/Db3x/src/database.h b/plugins/Db3x/src/database.h
deleted file mode 100644
index 2394655e73..0000000000
--- a/plugins/Db3x/src/database.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
-
-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.
-*/
-
-
-//all offsets are relative to the start of the file
-//offsets are 0 if there is nothing in the chain or this is the last in the
-//chain
-
-/* tree diagram
-
-DBHeader
- |-->end of file (plain offset)
- |-->first contact (DBContact)
- |   |-->next contact (DBContact)
- |   |   \--> ...
- |   |-->first settings (DBContactSettings)
- |   |	 |-->next settings (DBContactSettings)
- |   |   |   \--> ...
- |   |   \-->module name (DBModuleName)
- |   \-->first/last/firstunread event
- |-->user contact (DBContact)
- |   |-->next contact = NULL
- |   |-->first settings	as above
- |   \-->first/last/firstunread event as above
- \-->first module name (DBModuleName)
-     \-->next module name (DBModuleName)
-	     \--> ...
-*/
-
-#define DB_RESIZE_GRANULARITY    16384
-#define DB_THIS_VERSION          0x00000700u
-#define DB_SETTINGS_RESIZE_GRANULARITY  128
-
-#include <pshpack1.h>
-struct DBHeader {
-  BYTE signature[16];      // 'Miranda ICQ DB',0,26
-  DWORD version;		   //as 4 bytes, ie 1.2.3.10 = 0x0102030a
-                           //this version is 0x00000700
-  DWORD ofsFileEnd;		   //offset of the end of the database - place to write
-                           //new structures
-  DWORD slackSpace;		   //a counter of the number of bytes that have been
-                           //wasted so far due to deleting structures and/or
-						   //re-making them at the end. We should compact when
-						   //this gets above a threshold
-  DWORD contactCount;	   //number of contacts in the chain,excluding the user
-  DWORD ofsFirstContact;   //offset to first DBContact in the chain
-  DWORD ofsUser;		   //offset to DBContact representing the user
-  DWORD ofsFirstModuleName;	//offset to first struct DBModuleName in the chain
-};
-
-#define DBCONTACT_SIGNATURE   0x43DECADEu
-struct DBContact {
-  DWORD signature;
-  DWORD ofsNext;			 //offset to the next contact in the chain. zero if
-                             //this is the 'user' contact or the last contact
-							 //in the chain
-  DWORD ofsFirstSettings;	 //offset to the first DBContactSettings in the
-                             //chain for this contact.
-  DWORD eventCount;			 //number of events in the chain for this contact
-  DWORD ofsFirstEvent,ofsLastEvent;	 //offsets to the first and last DBEvent in
-                                     //the chain for this contact
-  DWORD ofsFirstUnreadEvent; //offset to the first (chronological) unread event
-							 //in the chain, 0 if all are read
-  DWORD timestampFirstUnread; //timestamp of the event at ofsFirstUnreadEvent
-};
-
-#define DBMODULENAME_SIGNATURE  0x4DDECADEu
-struct DBModuleName {
-  DWORD signature;
-  DWORD ofsNext;		//offset to the next module name in the chain
-  BYTE cbName;			//number of characters in this module name
-  char name[1];			//name, no nul terminator
-};
-
-#define DBCONTACTSETTINGS_SIGNATURE  0x53DECADEu
-struct DBContactSettings {
-  DWORD signature;
-  DWORD ofsNext;		 //offset to the next contactsettings in the chain
-  DWORD ofsModuleName;	 //offset to the DBModuleName of the owner of these
-                         //settings
-  DWORD cbBlob;			 //size of the blob in bytes. May be larger than the
-                         //actual size for reducing the number of moves
-						 //required using granularity in resizing
-  BYTE blob[1];			 //the blob. a back-to-back sequence of DBSetting
-                         //structs, the last has cbName = 0
-};
-
-/*	not a valid structure, content is figured out on the fly
-struct DBSetting {
-  BYTE cbName;			//number of bytes in the name of this setting
-                        //this  = 0 marks the end
-  char szName[...];		//setting name, excluding nul
-  BYTE dataType;		//type of data. see m_database.h, db/contact/getsetting
-  union {			   //a load of types of data, length is defined by dataType
-    BYTE bVal; WORD wVal; DWORD dVal;
-	struct {
-	  WORD cbString;
-	  char szVal[...];	  //excludes nul terminator
-	};
-	struct {
-	  WORD cbBlob;
-	  BYTE blobVal[...];
-	};
-  };
-};
-*/
-
-#define DBEVENT_SIGNATURE  0x45DECADEu
-struct DBEvent {
-  DWORD signature;
-  DWORD ofsPrev,ofsNext;	 //offset to the previous and next events in the
-                             //chain. Chain is sorted chronologically
-  DWORD ofsModuleName;		 //offset to a DBModuleName struct of the name of
-                             //the owner of this event
-  DWORD timestamp;			 //seconds since 00:00:00 01/01/1970
-  DWORD flags;				 //see m_database.h, db/event/add
-  WORD eventType;			 //module-defined event type
-  DWORD cbBlob;				 //number of bytes in the blob
-  BYTE blob[1];				 //the blob. module-defined formatting
-};
-#include <poppack.h>
-
-typedef struct
-{
-	BYTE bIsResident;
-	char name[1];
-}
-	DBCachedSettingName;
-
-typedef struct
-{
-	char* name;
-	DBVARIANT value;
-}
-	DBCachedGlobalValue;
-
-typedef struct DBCachedContactValue_tag
-{
-	char* name;
-	DBVARIANT value;
-	struct DBCachedContactValue_tag* next;
-}
-	DBCachedContactValue;
-
-typedef struct
-{
-	HANDLE hContact;
-	HANDLE hNext;
-	DBCachedContactValue* first;
-}
-	DBCachedContactValueList;
-
-
-//databasecorruption: called if any signatures are broken. very very fatal
-void DatabaseCorruption(void);
-PBYTE DBRead(DWORD ofs,int bytesRequired,int *bytesAvail);	//any preview result could be invalidated by the next call
-__forceinline PBYTE DBRead(HANDLE hContact,int bytesRequired,int *bytesAvail)
-{	return DBRead((DWORD)hContact, bytesRequired, bytesAvail);
-}
-void DBWrite(DWORD ofs,PVOID pData,int count);
-void DBFlush(int setting);
-void DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes);
-DWORD CreateNewSpace(int bytes);
-void DeleteSpace(DWORD ofs,int bytes);
-void GetProfileDirectory(char *szPath,int cbPath);
-int GetDefaultProfilePath(char *szPath,int cbPath,int *specified);
-int ShouldShowProfileManager(void);
-int CheckDbHeaders(struct DBHeader * hdr);
-int CreateDbHeaders(HANDLE hFile);
-int LoadDatabaseModule(void);
-void UnloadDatabaseModule(void);
-
-#ifdef _DEBUG
-#define MAXCACHEDREADSIZE     512
-#else
-#define MAXCACHEDREADSIZE     2048	 //push it to 1K  //technically 4096 would work, but I'm not going to push it
-#endif
-
-#ifdef _DEBUG
-//#define DBLOGGING
-#endif
-#ifdef DBLOGGING
-void DBLog(const char *file,int line,const char *fmt,...);
-#define logg()  DBLog(__FILE__,__LINE__,"")
-#define log0(s)  DBLog(__FILE__,__LINE__,s)
-#define log1(s,a)  DBLog(__FILE__,__LINE__,s,a)
-#define log2(s,a,b)  DBLog(__FILE__,__LINE__,s,a,b)
-#define log3(s,a,b,c)  DBLog(__FILE__,__LINE__,s,a,b,c)
-#define log4(s,a,b,c,d)  DBLog(__FILE__,__LINE__,s,a,b,c,d)
-#else
-#define logg()
-#define log0(s)
-#define log1(s,a)
-#define log2(s,a,b)
-#define log3(s,a,b,c)
-#define log4(s,a,b,c,d)
-#endif
diff --git a/plugins/Db3x/src/dbcache.cpp b/plugins/Db3x/src/dbcache.cpp
deleted file mode 100644
index c68db53a0a..0000000000
--- a/plugins/Db3x/src/dbcache.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-
-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"
-
-#define CACHESECTIONSIZE   4096
-#define CACHESECTIONCOUNT  32
-
-static BOOL safetyMode = TRUE;
-static PBYTE pDbCache;
-static DWORD lastUseCounter;
-struct DBCacheSectionInfo {
-	DWORD ofsBase;
-	DWORD lastUsed;
-} static cacheSectionInfo[CACHESECTIONCOUNT];
-
-static __inline int FindSectionForOffset(const DWORD ofs)
-{
-	int i;
-	for(i = 0;i<CACHESECTIONCOUNT;i++)
-		if (ofs >= cacheSectionInfo[i].ofsBase && ofs<cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE)
-			return i;
-	return -1;
-}
-
-static __inline int FindLRUSection(void)
-{
-	int i,lru = 0;
-	DWORD lowestLastUse = cacheSectionInfo[0].lastUsed;
-	for(i = 1;i<CACHESECTIONCOUNT;i++) if (cacheSectionInfo[i].lastUsed<lowestLastUse) {lru = i; lowestLastUse = cacheSectionInfo[i].lastUsed;}
-	return lru;
-}
-
-static __inline void LoadSection(const int i,DWORD ofs)
-{
-	cacheSectionInfo[i].ofsBase = ofs-ofs%CACHESECTIONSIZE;
-	log1("readsect %08x",ofs);
-	SetFilePointer(hDbFile,cacheSectionInfo[i].ofsBase,NULL,FILE_BEGIN);
-	ReadFile(hDbFile,pDbCache+i*CACHESECTIONSIZE,CACHESECTIONSIZE,&ofs,NULL);
-}
-
-static __inline void MoveSection(int *sectId,int dest)
-{
-	CopyMemory(pDbCache+dest*CACHESECTIONSIZE,pDbCache+(*sectId)*CACHESECTIONSIZE,CACHESECTIONSIZE);
-	cacheSectionInfo[dest].ofsBase = cacheSectionInfo[*sectId].ofsBase;
-	*sectId = dest;
-}
-
-
-
-//we are assumed to be in a mutex here
-PBYTE DBRead(DWORD ofs,int bytesRequired,int *bytesAvail)
-{
-
-	int part1sect;
-	int part2sect;
-
-
-	part1sect = FindSectionForOffset(ofs);
-	if (ofs%CACHESECTIONSIZE+bytesRequired<CACHESECTIONSIZE) {
-		//only one section required
-		if (part1sect == -1) {
-			part1sect = FindLRUSection();
-			LoadSection(part1sect,ofs);
-		}
-		cacheSectionInfo[part1sect].lastUsed = ++lastUseCounter;
-		if (bytesAvail!= NULL) *bytesAvail = cacheSectionInfo[part1sect].ofsBase+CACHESECTIONSIZE-ofs;
-		return pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
-	}
-	//two sections are required
-	part2sect = FindSectionForOffset(ofs+CACHESECTIONSIZE);
-	if (part1sect!= -1) {
-		if (part2sect == -1) {  //first part in cache, but not second part
-			if (part1sect == CACHESECTIONCOUNT-1) MoveSection(&part1sect,0);
-			LoadSection(part1sect+1,ofs+CACHESECTIONSIZE);
-		}
-		else if (part2sect!= part1sect+1) {   //both parts are in cache, but not already consecutive
-			if (part1sect == CACHESECTIONCOUNT-1) {
-				//first part is at end, move to before second part
-				if (part2sect == 0) //second part is at start: need to move both
-					MoveSection(&part2sect,1);
-				MoveSection(&part1sect,part2sect-1);
-			}
-			else  //move second part to after first part
-				MoveSection(&part2sect,part1sect+1);
-		}
-	}
-	else {
-		if (part2sect == -1) {  //neither section is in cache
-			part1sect = 0; part2sect = 1;
-			LoadSection(part1sect,ofs); LoadSection(part2sect,ofs+CACHESECTIONSIZE);
-		}
-		else {    //part 2 is in cache, but not part 1
-			if (part2sect == 0) MoveSection(&part2sect,1);
-			part1sect = part2sect-1;
-			LoadSection(part1sect,ofs);
-		}
-	}
-	//both sections are now consecutive, starting at part1sect
-	cacheSectionInfo[part1sect].lastUsed = ++lastUseCounter;
-	cacheSectionInfo[part1sect+1].lastUsed = ++lastUseCounter;
-	if (bytesAvail!= NULL) *bytesAvail = cacheSectionInfo[part1sect+1].ofsBase+CACHESECTIONSIZE-ofs;
-	return pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
-}
-
-
-
-//we are assumed to be in a mutex here
-void DBWrite(DWORD ofs,PVOID pData,int bytes)
-{
-	//write direct, and rely on Windows' write caching
-	DWORD bytesWritten;
-	int i;
-
-	log2("write %d@%08x",bytes,ofs);
-	SetFilePointer(hDbFile,ofs,NULL,FILE_BEGIN);
-	if (WriteFile(hDbFile,pData,bytes,&bytesWritten,NULL) == 0)
-	{
-		DatabaseCorruption();
-	}
-	logg();
-	//check if any of the cache sections contain this bit
-	for(i = 0;i<CACHESECTIONCOUNT;i++) {
-		if (ofs+bytes >= cacheSectionInfo[i].ofsBase && ofs<cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) {
-			if (ofs<cacheSectionInfo[i].ofsBase) {  //don't start at beginning
-				if (ofs+bytes >= cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE)   //don't finish at end
-					CopyMemory(pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,CACHESECTIONSIZE);
-				else CopyMemory(pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,bytes-(cacheSectionInfo[i].ofsBase-ofs));
-			}
-			else {	  //start at beginning
-				if (ofs+bytes >= cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE)   //don't finish at end
-					CopyMemory(pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE-ofs);
-				else CopyMemory(pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,bytes);
-			}
-		}
-	}
-}
-
-void DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes)
-{
-	DWORD bytesRead;
-	PBYTE buf;
-
-	log3("move %d %08x->%08x",bytes,ofsSource,ofsDest);
-	buf = (PBYTE)mir_alloc(bytes);
-	SetFilePointer(hDbFile,ofsSource,NULL,FILE_BEGIN);
-	ReadFile(hDbFile,buf,bytes,&bytesRead,NULL);
-	DBWrite(ofsDest,buf,bytes);
-	mir_free(buf);
-	logg();
-}
-
-static UINT_PTR flushBuffersTimerId;
-static VOID CALLBACK DoBufferFlushTimerProc(HWND hwnd,UINT message,UINT_PTR idEvent,DWORD dwTime)
-{
-	KillTimer(NULL,flushBuffersTimerId);
-	log0("tflush1");
-	FlushFileBuffers(hDbFile);
-	log0("tflush2");
-}
-
-void DBFlush(int setting)
-{
-	if (!setting) {
-		log0("nflush1");
-		if (safetyMode) FlushFileBuffers(hDbFile);
-		log0("nflush2");
-		return;
-	}
-	KillTimer(NULL,flushBuffersTimerId);
-	flushBuffersTimerId = SetTimer(NULL,flushBuffersTimerId,50,DoBufferFlushTimerProc);
-}
-
-static INT_PTR CacheSetSafetyMode(WPARAM wParam,LPARAM lParam)
-{
-	EnterCriticalSection(&csDbAccess);
-	safetyMode = wParam;
-	LeaveCriticalSection(&csDbAccess);
-	if (safetyMode) FlushFileBuffers(hDbFile);
-	return 0;
-}
-
-int InitCache(void)
-{
-	pDbCache = (PBYTE)mir_alloc(CACHESECTIONSIZE*CACHESECTIONCOUNT);
-	lastUseCounter = CACHESECTIONCOUNT;
-	for(int i = 0; i < CACHESECTIONCOUNT; i++) {
-		cacheSectionInfo[i].ofsBase = 0;
-		cacheSectionInfo[i].lastUsed = i;
-		SetFilePointer(hDbFile,cacheSectionInfo[i].ofsBase,NULL,FILE_BEGIN);
-
-		DWORD bytesRead;
-		ReadFile(hDbFile,pDbCache+i*CACHESECTIONSIZE,CACHESECTIONSIZE,&bytesRead,NULL);
-	}
-	return 0;
-}
-
-void UninitCache(void)
-{
-	mir_free(pDbCache);
-	KillTimer(NULL,flushBuffersTimerId);
-}
diff --git a/plugins/Db3x/src/dbcache3x.cpp b/plugins/Db3x/src/dbcache3x.cpp
new file mode 100644
index 0000000000..5688ce0a53
--- /dev/null
+++ b/plugins/Db3x/src/dbcache3x.cpp
@@ -0,0 +1,198 @@
+/*
+
+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"
+
+int CDb3x::FindSectionForOffset(const DWORD ofs)
+{
+	for (int i = 0; i < CACHESECTIONCOUNT; i++)
+		if (ofs >= cacheSectionInfo[i].ofsBase && ofs<cacheSectionInfo[i].ofsBase + CACHESECTIONSIZE)
+			return i;
+	return -1;
+}
+
+int CDb3x::FindLRUSection(void)
+{
+	int lru = 0;
+	DWORD lowestLastUse = cacheSectionInfo[0].lastUsed;
+	for (int i = 1; i < CACHESECTIONCOUNT; i++)
+		if (cacheSectionInfo[i].lastUsed < lowestLastUse) {
+			lru = i; 
+			lowestLastUse = cacheSectionInfo[i].lastUsed;
+		}
+	return lru;
+}
+
+void CDb3x::LoadSection(const int i,DWORD ofs)
+{
+	cacheSectionInfo[i].ofsBase = ofs - ofs%CACHESECTIONSIZE;
+	log1("readsect %08x",ofs);
+	SetFilePointer(m_hDbFile,cacheSectionInfo[i].ofsBase,NULL,FILE_BEGIN);
+	ReadFile(m_hDbFile,m_pDbCache+i*CACHESECTIONSIZE,CACHESECTIONSIZE,&ofs,NULL);
+}
+
+void CDb3x::MoveSection(int *sectId,int dest)
+{
+	CopyMemory(m_pDbCache+dest*CACHESECTIONSIZE,m_pDbCache+(*sectId)*CACHESECTIONSIZE,CACHESECTIONSIZE);
+	cacheSectionInfo[dest].ofsBase = cacheSectionInfo[*sectId].ofsBase;
+	*sectId = dest;
+}
+
+//we are assumed to be in a mutex here
+PBYTE CDb3x::DBRead(DWORD ofs,int bytesRequired,int *bytesAvail)
+{
+	int part1sect = FindSectionForOffset(ofs);
+	if (ofs%CACHESECTIONSIZE+bytesRequired<CACHESECTIONSIZE) {
+		//only one section required
+		if (part1sect == -1) {
+			part1sect = FindLRUSection();
+			LoadSection(part1sect,ofs);
+		}
+		cacheSectionInfo[part1sect].lastUsed = ++m_lastUseCounter;
+		if (bytesAvail!= NULL) *bytesAvail = cacheSectionInfo[part1sect].ofsBase+CACHESECTIONSIZE-ofs;
+		return m_pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
+	}
+	//two sections are required
+	int part2sect = FindSectionForOffset(ofs+CACHESECTIONSIZE);
+	if (part1sect != -1) {
+		if (part2sect == -1) {  //first part in cache, but not second part
+			if (part1sect == CACHESECTIONCOUNT-1) MoveSection(&part1sect,0);
+			LoadSection(part1sect+1,ofs+CACHESECTIONSIZE);
+		}
+		else if (part2sect!= part1sect+1) {   //both parts are in cache, but not already consecutive
+			if (part1sect == CACHESECTIONCOUNT-1) {
+				//first part is at end, move to before second part
+				if (part2sect == 0) //second part is at start: need to move both
+					MoveSection(&part2sect,1);
+				MoveSection(&part1sect,part2sect-1);
+			}
+			else  //move second part to after first part
+				MoveSection(&part2sect,part1sect+1);
+		}
+	}
+	else {
+		if (part2sect == -1) {  //neither section is in cache
+			part1sect = 0; part2sect = 1;
+			LoadSection(part1sect,ofs); LoadSection(part2sect,ofs+CACHESECTIONSIZE);
+		}
+		else {    //part 2 is in cache, but not part 1
+			if (part2sect == 0) MoveSection(&part2sect,1);
+			part1sect = part2sect-1;
+			LoadSection(part1sect,ofs);
+		}
+	}
+
+	//both sections are now consecutive, starting at part1sect
+	cacheSectionInfo[part1sect].lastUsed = ++m_lastUseCounter;
+	cacheSectionInfo[part1sect+1].lastUsed = ++m_lastUseCounter;
+	if (bytesAvail!= NULL)
+		*bytesAvail = cacheSectionInfo[part1sect+1].ofsBase+CACHESECTIONSIZE-ofs;
+	return m_pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
+}
+
+//we are assumed to be in a mutex here
+void CDb3x::DBWrite(DWORD ofs,PVOID pData,int bytes)
+{
+	//write direct, and rely on Windows' write caching
+	log2("write %d@%08x", bytes, ofs);
+	SetFilePointer(m_hDbFile, ofs, NULL, FILE_BEGIN);
+
+	DWORD bytesWritten;
+	if ( WriteFile(m_hDbFile, pData, bytes, &bytesWritten, NULL) == 0)
+		DatabaseCorruption( _T("%s (Write error)"));
+
+	logg();
+
+	//check if any of the cache sections contain this bit
+	for(int i = 0; i < CACHESECTIONCOUNT; i++) {
+		if (ofs+bytes >= cacheSectionInfo[i].ofsBase && ofs<cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) {
+			if (ofs<cacheSectionInfo[i].ofsBase) {  //don't start at beginning
+				if (ofs+bytes >= cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE)   //don't finish at end
+					CopyMemory(m_pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,CACHESECTIONSIZE);
+				else CopyMemory(m_pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,bytes-(cacheSectionInfo[i].ofsBase-ofs));
+			}
+			else {	  //start at beginning
+				if (ofs+bytes >= cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE)   //don't finish at end
+					CopyMemory(m_pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE-ofs);
+				else CopyMemory(m_pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,bytes);
+			}
+		}
+	}
+}
+
+void CDb3x::DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes)
+{
+	DWORD bytesRead;
+	PBYTE buf;
+
+	log3("move %d %08x->%08x",bytes,ofsSource,ofsDest);
+	buf = (PBYTE)mir_alloc(bytes);
+	SetFilePointer(m_hDbFile,ofsSource,NULL,FILE_BEGIN);
+	ReadFile(m_hDbFile,buf,bytes,&bytesRead,NULL);
+	DBWrite(ofsDest,buf,bytes);
+	mir_free(buf);
+	logg();
+}
+
+static VOID CALLBACK DoBufferFlushTimerProc(HWND hwnd,UINT message,UINT_PTR idEvent,DWORD dwTime)
+{
+	for (int i=0; i < g_Dbs.getCount(); i++) {
+		CDb3x* db = g_Dbs[i];
+
+		KillTimer(NULL, db->m_flushBuffersTimerId);
+		log0("tflush1");
+		FlushFileBuffers(db->getFile());
+		log0("tflush2");
+	}
+}
+
+void CDb3x::DBFlush(int setting)
+{
+	if (!setting) {
+		log0("nflush1");
+		if (m_safetyMode) FlushFileBuffers(m_hDbFile);
+		log0("nflush2");
+		return;
+	}
+	KillTimer(NULL,m_flushBuffersTimerId);
+	m_flushBuffersTimerId = SetTimer(NULL,m_flushBuffersTimerId,50,DoBufferFlushTimerProc);
+}
+
+void CDb3x::DBFill(DWORD ofs,int bytes)
+{
+}
+
+int CDb3x::InitCache(void)
+{
+	m_pDbCache = (PBYTE)mir_alloc(CACHESECTIONSIZE*CACHESECTIONCOUNT);
+	m_lastUseCounter = CACHESECTIONCOUNT;
+	for(int i = 0; i < CACHESECTIONCOUNT; i++) {
+		cacheSectionInfo[i].ofsBase = 0;
+		cacheSectionInfo[i].lastUsed = i;
+		SetFilePointer(m_hDbFile,cacheSectionInfo[i].ofsBase,NULL,FILE_BEGIN);
+
+		DWORD bytesRead;
+		ReadFile(m_hDbFile,m_pDbCache+i*CACHESECTIONSIZE,CACHESECTIONSIZE,&bytesRead,NULL);
+	}
+	return 0;
+}
diff --git a/plugins/Db3x/src/dbcontacts.cpp b/plugins/Db3x/src/dbcontacts.cpp
deleted file mode 100644
index d0fb0bbc97..0000000000
--- a/plugins/Db3x/src/dbcontacts.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
-
-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"
-
-static HANDLE hContactDeletedEvent,hContactAddedEvent;
-
-int InitContacts(void)
-{
-	hContactDeletedEvent = CreateHookableEvent(ME_DB_CONTACT_DELETED);
-	hContactAddedEvent = CreateHookableEvent(ME_DB_CONTACT_ADDED);
-	return 0;
-}
-
-void UninitContacts(void)
-{
-}
-
-INT_PTR GetContactSettingStatic(WPARAM wParam,LPARAM lParam);
-
-STDMETHODIMP_(LONG) CDdxMmap::GetContactCount(void)
-{
-	mir_cslock lck(csDbAccess);
-	return dbHeader.contactCount;
-}
-
-#define proto_module  "Protocol"
-#define proto_setting "p"
-
-int CDdxMmap::CheckProto(HANDLE hContact, const char *proto)
-{
-	char protobuf[MAX_PATH] = {0};
-	DBVARIANT dbv;
-	DBCONTACTGETSETTING sVal = {proto_module,proto_setting,&dbv};
-
- 	dbv.type = DBVT_ASCIIZ;
-	dbv.pszVal = protobuf;
-	dbv.cchVal = sizeof(protobuf);
-
-	if (GetContactSettingStatic(hContact, &sVal) != 0 || dbv.type != DBVT_ASCIIZ)
-		return 0;
-
-	return !strcmp(protobuf,proto);
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::FindFirstContact(const char* szProto)
-{
-	mir_cslock lck(csDbAccess);
-
-	HANDLE ret = (HANDLE)dbHeader.ofsFirstContact;
-	if (szProto && !CheckProto(ret, szProto))
-		ret = FindNextContact(ret, szProto);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::FindNextContact(HANDLE hContact, const char* szProto)
-{
-	DBCachedContactValueList VLtemp, *VL = NULL;
-	VLtemp.hContact = hContact;
-
-	mir_cslock lck(csDbAccess);
-	
-	while ( VLtemp.hContact ) {
-		int index;
-		if ( List_GetIndex(&lContacts, &VLtemp, &index)) {
-			VL = ( DBCachedContactValueList* )lContacts.items[index];
-			if (VL->hNext != NULL) {
-				if ( !szProto || CheckProto(VL->hNext, szProto))
-					return VL->hNext;
-
-				VLtemp.hContact = VL->hNext;
-				continue;
-		}	}
-
-		DBContact *dbc = (DBContact*)DBRead(VLtemp.hContact,sizeof(DBContact),NULL);
-		if (dbc->signature != DBCONTACT_SIGNATURE)
-			break;
-
-		if ( VL == NULL ) {
-			VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList));
-			VL->hContact = VLtemp.hContact;
-			List_Insert(&lContacts,VL,index);
-		}
-		VL->hNext = (HANDLE)dbc->ofsNext;
-		if (VL->hNext != NULL && (!szProto || CheckProto(VL->hNext, szProto)))
-			return VL->hNext;
-
-		VLtemp.hContact = VL->hNext;
-	}
-	return 0;
-}
-
-STDMETHODIMP_(LONG) CDdxMmap::DeleteContact(HANDLE hContact)
-{
-	DBContact *dbcPrev;
-	DWORD ofsThis,ofsNext,ofsFirstEvent;
-	DBContactSettings *dbcs;
-	DBEvent *dbe;
-	int index;
-
-	if (hContact == NULL) return 1;
-	{
-		mir_cslock lck(csDbAccess);
-
-		DBContact *dbc = (DBContact*)DBRead(hContact, sizeof(DBContact), NULL);
-		if (dbc->signature != DBCONTACT_SIGNATURE)
-			return 1;
-
-		if ((DWORD)hContact == dbHeader.ofsUser ) {
-			log0("FATAL: del of user chain attempted.");
-			return 1;
-		}
-
-		log0("del contact");
-	}
-
-	//call notifier while outside mutex
-	NotifyEventHooks(hContactDeletedEvent, (WPARAM)hContact, 0);
-	
-	//get back in
-	mir_cslock lck(csDbAccess);
-
-	DBCachedContactValueList VLtemp;
-	VLtemp.hContact = hContact;
-	if ( List_GetIndex(&lContacts,&VLtemp,&index))
-	{
-		DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index];
-		DBCachedContactValue* V = VL->first;
-		while ( V != NULL ) {
-			DBCachedContactValue* V1 = V->next;
-			if ( V->value.type == DBVT_ASCIIZ )
-				HeapFree( hCacheHeap, 0, V->value.pszVal );
-			HeapFree( hCacheHeap, 0, V );
-			V = V1;
-		}
-		HeapFree( hCacheHeap, 0, VL );
-
-		List_Remove(&lContacts,index);
-	}
-
-	DBContact *dbc = (DBContact*)DBRead(hContact, sizeof(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 = (DBEvent*)DBRead(ofsThis,sizeof(DBEvent),NULL);
-		ofsNext = dbe->ofsNext;
-		DeleteSpace(ofsThis,offsetof(DBEvent,blob)+dbe->cbBlob);
-		ofsThis = ofsNext;
-	}
-	//find previous contact in chain and change ofsNext
-	dbc = (DBContact*)DBRead(hContact, sizeof(DBContact), NULL);
-	if (dbHeader.ofsFirstContact == (DWORD)hContact) {
-		dbHeader.ofsFirstContact = dbc->ofsNext;
-		DBWrite(0,&dbHeader,sizeof(dbHeader));
-	}
-	else {
-		ofsNext = dbc->ofsNext;
-		ofsThis = dbHeader.ofsFirstContact;
-		dbcPrev = (DBContact*)DBRead(ofsThis,sizeof(DBContact),NULL);
-		while(dbcPrev->ofsNext!= (DWORD)hContact) {
-			if (dbcPrev->ofsNext == 0) DatabaseCorruption();
-			ofsThis = dbcPrev->ofsNext;
-			dbcPrev = (DBContact*)DBRead(ofsThis,sizeof(DBContact),NULL);
-		}
-		dbcPrev->ofsNext = ofsNext;
-		DBWrite(ofsThis,dbcPrev,sizeof(DBContact));
-		{
-			DBCachedContactValueList VLtemp;
-			VLtemp.hContact = (HANDLE)ofsThis;
-			if ( List_GetIndex(&lContacts,&VLtemp,&index))
-			{
-				DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index];
-				VL->hNext = ( HANDLE )ofsNext;
-		}	}
-	}
-	//delete contact
-	DeleteSpace((DWORD)hContact,sizeof(DBContact));
-	//decrement contact count
-	dbHeader.contactCount--;
-	DBWrite(0,&dbHeader,sizeof(dbHeader));
-	DBFlush(0);
-
-	//quit
-	return 0;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::AddContact(void)
-{
-	DBContact dbc;
-	DWORD ofsNew;
-
-	log0("add contact");
-	EnterCriticalSection(&csDbAccess);
-	ofsNew = CreateNewSpace(sizeof(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(DBContact));
-	DBWrite(0,&dbHeader,sizeof(dbHeader));
-	DBFlush(0);
-
-	{	int index;
-
-		DBCachedContactValueList *VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList));
-		VL->hContact = (HANDLE)ofsNew;
-
-		List_GetIndex(&lContacts,VL,&index);
-		List_Insert(&lContacts,VL,index);
-	}
-
-	LeaveCriticalSection(&csDbAccess);
-	NotifyEventHooks(hContactAddedEvent,(WPARAM)ofsNew,0);
-	return (HANDLE)ofsNew;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::IsDbContact(HANDLE hContact)
-{
-	DBContact dbc;
-	DWORD ofsContact = (DWORD)hContact;
-	INT_PTR ret;
-
-	EnterCriticalSection(&csDbAccess);
-	{
-		int index;
-		DBCachedContactValueList VLtemp,*VL;
-		VLtemp.hContact = hContact;
-		if ( List_GetIndex(&lContacts,&VLtemp,&index))
-			ret = TRUE;
-		else {
-			dbc = *(DBContact*)DBRead(ofsContact,sizeof(DBContact),NULL);
-			ret = dbc.signature == DBCONTACT_SIGNATURE;
-
-			if (ret) {
-				VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList));
-				VL->hContact = hContact;
-				List_Insert(&lContacts,VL,index);
-	}	}	}
-
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
diff --git a/plugins/Db3x/src/dbevents.cpp b/plugins/Db3x/src/dbevents.cpp
deleted file mode 100644
index 2deb70c647..0000000000
--- a/plugins/Db3x/src/dbevents.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
-
-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"
-
-DWORD GetModuleNameOfs(const char *szName);
-char *GetModuleNameByOfs(DWORD ofs);
-
-static HANDLE hEventDeletedEvent,hEventAddedEvent,hEventFilterAddedEvent;
-
-STDMETHODIMP_(LONG) CDdxMmap::GetEventCount(HANDLE hContact)
-{
-	INT_PTR ret;
-	DBContact *dbc;
-
-	EnterCriticalSection(&csDbAccess);
-	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-	dbc = (DBContact*)DBRead(hContact, sizeof(DBContact),NULL);
-	if (dbc->signature!= DBCONTACT_SIGNATURE) ret = -1;
-	else ret = dbc->eventCount;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::AddEvent(HANDLE hContact, DBEVENTINFO *dbei)
-{
-	DBContact dbc;
-	DBEvent dbe,*dbeTest;
-	DWORD ofsNew,ofsModuleName,ofsContact,ofsThis;
-
-	if (dbei == NULL||dbei->cbSize!= sizeof(DBEVENTINFO)) return 0;
-	if (dbei->timestamp == 0) return 0;
-	if (NotifyEventHooks(hEventFilterAddedEvent, (WPARAM)hContact, (LPARAM)dbei))
-		return 0;
-
-	EnterCriticalSection(&csDbAccess);
-	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-	else
-		ofsContact = (DWORD)hContact;
-	dbc = *(DBContact*)DBRead(ofsContact,sizeof(DBContact),NULL);
-	if (dbc.signature!= DBCONTACT_SIGNATURE) {
-		LeaveCriticalSection(&csDbAccess);
-	  	return 0;
-	}
-	ofsNew = CreateNewSpace(offsetof(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 = (DWORD)hContact;
-		dbe.ofsNext = 0;
-		dbe.flags |= DBEF_FIRST;
-		dbc.ofsFirstEvent = dbc.ofsLastEvent = ofsNew;
-	}
-	else {
-		dbeTest = (DBEvent*)DBRead(dbc.ofsFirstEvent,sizeof(DBEvent),NULL);
-		// Should new event be placed before first event in chain?
-		if (dbei->timestamp < dbeTest->timestamp) {
-			dbe.ofsPrev = (DWORD)hContact;
-			dbe.ofsNext = dbc.ofsFirstEvent;
-			dbe.flags |= DBEF_FIRST;
-			dbc.ofsFirstEvent = ofsNew;
-			dbeTest = (DBEvent*)DBRead(dbe.ofsNext,sizeof(DBEvent),NULL);
-			dbeTest->flags &= ~DBEF_FIRST;
-			dbeTest->ofsPrev = ofsNew;
-			DBWrite(dbe.ofsNext,dbeTest,sizeof(DBEvent));
-		}
-		else {
-			// Loop through the chain, starting at the end
-			ofsThis = dbc.ofsLastEvent;
-			dbeTest = (DBEvent*)DBRead(ofsThis, sizeof(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(DBEvent));
-					if (dbe.ofsNext == 0)
-						dbc.ofsLastEvent = ofsNew;
-					else {
-						dbeTest = (DBEvent*)DBRead(dbe.ofsNext, sizeof(DBEvent), NULL);
-						dbeTest->ofsPrev = ofsNew;
-						DBWrite(dbe.ofsNext, dbeTest, sizeof(DBEvent));
-					}
-					break;
-				}
-				ofsThis = dbeTest->ofsPrev;
-				dbeTest = (DBEvent*)DBRead(ofsThis, sizeof(DBEvent), NULL);
-			}
-		}
-	}
-	dbc.eventCount++;
-	if (!(dbe.flags&(DBEF_READ|DBEF_SENT))) {
-		if (dbe.timestamp<dbc.timestampFirstUnread || dbc.timestampFirstUnread == 0) {
-			dbc.timestampFirstUnread = dbe.timestamp;
-			dbc.ofsFirstUnreadEvent = ofsNew;
-		}
-	}
-	DBWrite(ofsContact,&dbc,sizeof(DBContact));
-	DBWrite(ofsNew,&dbe,offsetof(DBEvent,blob));
-	DBWrite(ofsNew+offsetof(DBEvent,blob),dbei->pBlob,dbei->cbBlob);
-	DBFlush(0);
-	LeaveCriticalSection(&csDbAccess);
-	log1("add event @ %08x",ofsNew);
-	NotifyEventHooks(hEventAddedEvent,(WPARAM)hContact,(LPARAM)ofsNew);
-	return (HANDLE)ofsNew;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::DeleteEvent(HANDLE hContact, HANDLE hDbEvent)
-{
-	DBContact dbc;
-	DWORD ofsContact,ofsThis;
-	DBEvent dbe,*dbeNext,*dbePrev;
-
-	EnterCriticalSection(&csDbAccess);
-	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-	else
-		ofsContact = (DWORD)hContact;
-	dbc = *(DBContact*)DBRead(ofsContact,sizeof(DBContact),NULL);
-	dbe = *(DBEvent*)DBRead(hDbEvent,sizeof(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)hContact, (LPARAM)hDbEvent);
-
-	//get back in
-	EnterCriticalSection(&csDbAccess);
-	dbc = *(DBContact*)DBRead(ofsContact,sizeof(DBContact),NULL);
-	dbe = *(DBEvent*)DBRead(hDbEvent,sizeof(DBEvent),NULL);
-	//check if this was the first unread, if so, recalc the first unread
-	if (dbc.ofsFirstUnreadEvent == (DWORD)hDbEvent) {
-		dbeNext = &dbe;
-		for (;;) {
-			if (dbeNext->ofsNext == 0) {
-				dbc.ofsFirstUnreadEvent = 0;
-				dbc.timestampFirstUnread = 0;
-				break;
-			}
-			ofsThis = dbeNext->ofsNext;
-			dbeNext = (DBEvent*)DBRead(ofsThis,sizeof(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 = (DBEvent*)DBRead(dbe.ofsNext,sizeof(DBEvent),NULL);
-			dbeNext->flags |= DBEF_FIRST;
-			dbeNext->ofsPrev = dbe.ofsPrev;
-			DBWrite(dbe.ofsNext,dbeNext,sizeof(DBEvent));
-			dbc.ofsFirstEvent = dbe.ofsNext;
-		}
-	}
-	else {
-		if (dbe.ofsNext == 0) {
-			dbePrev = (DBEvent*)DBRead(dbe.ofsPrev,sizeof(DBEvent),NULL);
-			dbePrev->ofsNext = 0;
-			DBWrite(dbe.ofsPrev,dbePrev,sizeof(DBEvent));
-			dbc.ofsLastEvent = dbe.ofsPrev;
-		}
-		else {
-			dbePrev = (DBEvent*)DBRead(dbe.ofsPrev,sizeof(DBEvent),NULL);
-			dbePrev->ofsNext = dbe.ofsNext;
-			DBWrite(dbe.ofsPrev,dbePrev,sizeof(DBEvent));
-			dbeNext = (DBEvent*)DBRead(dbe.ofsNext,sizeof(DBEvent),NULL);
-			dbeNext->ofsPrev = dbe.ofsPrev;
-			DBWrite(dbe.ofsNext,dbeNext,sizeof(DBEvent));
-		}
-	}
-	//delete event
-	DeleteSpace((DWORD)hDbEvent,offsetof(DBEvent,blob)+dbe.cbBlob);
-	//decrement event count
-	dbc.eventCount--;
-	DBWrite(ofsContact,&dbc,sizeof(DBContact));
-	DBFlush(0);
-	//quit
-	LeaveCriticalSection(&csDbAccess);
-	return 0;
-}
-
-STDMETHODIMP_(LONG) CDdxMmap::GetBlobSize(HANDLE hDbEvent)
-{
-	INT_PTR ret;
-
-	EnterCriticalSection(&csDbAccess);
-	DBEvent *dbe = (DBEvent*)DBRead(hDbEvent,sizeof(DBEvent),NULL);
-	if (dbe->signature!= DBEVENT_SIGNATURE) ret = -1;
-	else ret = dbe->cbBlob;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::GetEvent(HANDLE hDbEvent, DBEVENTINFO *dbei)
-{
-	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);
-	DBEvent *dbe = (DBEvent*)DBRead(hDbEvent,sizeof(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->cbBlob<dbe->cbBlob) bytesToCopy = dbei->cbBlob;
-	else bytesToCopy = dbe->cbBlob;
-	dbei->cbBlob = dbe->cbBlob;
-	for(i = 0;;i += MAXCACHEDREADSIZE) {
-		if (bytesToCopy-i <= MAXCACHEDREADSIZE) {
-			CopyMemory(dbei->pBlob+i,DBRead(DWORD(hDbEvent)+offsetof(DBEvent,blob)+i,bytesToCopy-i,NULL),bytesToCopy-i);
-			break;
-		}
-		CopyMemory(dbei->pBlob+i,DBRead(DWORD(hDbEvent)+offsetof(DBEvent,blob)+i,MAXCACHEDREADSIZE,NULL),MAXCACHEDREADSIZE);
-	}
-	LeaveCriticalSection(&csDbAccess);
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::MarkEventRead(HANDLE hContact, HANDLE hDbEvent)
-{
-	INT_PTR ret;
-	DWORD ofsThis;
-
-	EnterCriticalSection(&csDbAccess);
-	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-	DBContact dbc = *(DBContact*)DBRead(hContact,sizeof(DBContact),NULL);
-	DBEvent *dbe = (DBEvent*)DBRead(hDbEvent,sizeof(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((DWORD)hDbEvent, dbe, sizeof(DBEvent));
-	ret = (INT_PTR)dbe->flags;
-	if (dbc.ofsFirstUnreadEvent == (DWORD)hDbEvent) {
-		for (;;) {
-			if (dbe->ofsNext == 0) {
-				dbc.ofsFirstUnreadEvent = 0;
-				dbc.timestampFirstUnread = 0;
-				break;
-			}
-			ofsThis = dbe->ofsNext;
-			dbe = (DBEvent*)DBRead(ofsThis,sizeof(DBEvent),NULL);
-			if (!(dbe->flags&(DBEF_READ|DBEF_SENT))) {
-				dbc.ofsFirstUnreadEvent = ofsThis;
-				dbc.timestampFirstUnread = dbe->timestamp;
-				break;
-			}
-		}
-	}
-	DBWrite((DWORD)hContact,&dbc,sizeof(DBContact));
-	DBFlush(0);
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::GetEventContact(HANDLE hDbEvent)
-{
-	HANDLE ret;
-
-	EnterCriticalSection(&csDbAccess);
-	DBEvent *dbe = (DBEvent*)DBRead(hDbEvent,sizeof(DBEvent),NULL);
-	if (dbe->signature!= DBEVENT_SIGNATURE) {
-		LeaveCriticalSection(&csDbAccess);
-	  	return (HANDLE)-1;
-	}
-	while(!(dbe->flags & DBEF_FIRST))
-		dbe = (DBEvent*)DBRead(dbe->ofsPrev,sizeof(DBEvent),NULL);
-	ret = (HANDLE)dbe->ofsPrev;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::FindFirstEvent(HANDLE hContact)
-{
-	HANDLE ret;
-
-	EnterCriticalSection(&csDbAccess);
-	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-	DBContact *dbc = (DBContact*)DBRead(hContact,sizeof(DBContact),NULL);
-	if (dbc->signature!= DBCONTACT_SIGNATURE)
-		ret = 0;
-	else 
-		ret = (HANDLE)dbc->ofsFirstEvent;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::FindFirstUnreadEvent(HANDLE hContact)
-{
-	HANDLE ret;
-
-	EnterCriticalSection(&csDbAccess);
-	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-	DBContact *dbc = (DBContact*)DBRead(hContact,sizeof(DBContact),NULL);
-	if (dbc->signature!= DBCONTACT_SIGNATURE) ret = 0;
-	else ret = (HANDLE)dbc->ofsFirstUnreadEvent;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::FindLastEvent(HANDLE hContact)
-{
-	HANDLE ret;
-
-	EnterCriticalSection(&csDbAccess);
-	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-	DBContact *dbc = (DBContact*)DBRead(hContact,sizeof(DBContact),NULL);
-	if (dbc->signature!= DBCONTACT_SIGNATURE) ret = 0;
-	else ret = (HANDLE)dbc->ofsLastEvent;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::FindNextEvent(HANDLE hDbEvent)
-{
-	HANDLE ret;
-
-	EnterCriticalSection(&csDbAccess);
-	DBEvent *dbe = (DBEvent*)DBRead(hDbEvent,sizeof(DBEvent),NULL);
-	if (dbe->signature!= DBEVENT_SIGNATURE) ret = 0;
-	else ret = (HANDLE)dbe->ofsNext;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-STDMETHODIMP_(HANDLE) CDdxMmap::FindPrevEvent(HANDLE hDbEvent)
-{
-	HANDLE ret;
-
-	EnterCriticalSection(&csDbAccess);
-	DBEvent *dbe = (DBEvent*)DBRead(hDbEvent,sizeof(DBEvent),NULL);
-	if (dbe->signature!= DBEVENT_SIGNATURE) ret = 0;
-	else if (dbe->flags&DBEF_FIRST) ret = 0;
-	else ret = (HANDLE)dbe->ofsPrev;
-	LeaveCriticalSection(&csDbAccess);
-	return ret;
-}
-
-int InitEvents(void)
-{
-	hEventDeletedEvent = CreateHookableEvent(ME_DB_EVENT_DELETED);
-	hEventAddedEvent = CreateHookableEvent(ME_DB_EVENT_ADDED);
-	hEventFilterAddedEvent = CreateHookableEvent(ME_DB_EVENT_FILTER_ADD);
-	return 0;
-}
diff --git a/plugins/Db3x/src/dbheaders.cpp b/plugins/Db3x/src/dbheaders.cpp
deleted file mode 100644
index 7092dc4630..0000000000
--- a/plugins/Db3x/src/dbheaders.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-
-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"
-
-struct DBSignature {
-  char name[15];
-  BYTE eof;
-};
-static struct DBSignature dbSignature = {"Miranda ICQ DB",0x1A};
-
-//the cache has not been loaded when these functions are used
-
-int CreateDbHeaders(HANDLE hFile)
-{
-	DBContact user;
-	DWORD bytesWritten;
-
-	CopyMemory(dbHeader.signature,&dbSignature,sizeof(dbHeader.signature));
-	dbHeader.version = DB_THIS_VERSION;
-	dbHeader.ofsFileEnd = sizeof(struct DBHeader);
-	dbHeader.slackSpace = 0;
-	dbHeader.contactCount = 0;
-	dbHeader.ofsFirstContact = 0;
-	dbHeader.ofsFirstModuleName = 0;
-	dbHeader.ofsUser = 0;
-	//create user
-	dbHeader.ofsUser = dbHeader.ofsFileEnd;
-	dbHeader.ofsFileEnd += sizeof(DBContact);
-	SetFilePointer(hFile,0,NULL,FILE_BEGIN);
-	WriteFile(hFile,&dbHeader,sizeof(dbHeader),&bytesWritten,NULL);
-	user.signature = DBCONTACT_SIGNATURE;
-	user.ofsNext = 0;
-	user.ofsFirstSettings = 0;
-	user.eventCount = 0;
-	user.ofsFirstEvent = user.ofsLastEvent = 0;
-	SetFilePointer(hFile,dbHeader.ofsUser,NULL,FILE_BEGIN);
-	WriteFile(hFile,&user,sizeof(DBContact),&bytesWritten,NULL);
-	FlushFileBuffers(hFile);
-	return 0;
-}
-
-int CheckDbHeaders(struct DBHeader * hdr)
-{
-	if (memcmp(hdr->signature,&dbSignature,sizeof(hdr->signature))) return 1;
-	if (hdr->version!= DB_THIS_VERSION) return 2;
-	if (hdr->ofsUser == 0) return 3;
-	return 0;
-}
-
-int InitialiseDbHeaders(void)
-{
-	return 0;
-}
diff --git a/plugins/Db3x/src/dbintf.cpp b/plugins/Db3x/src/dbintf.cpp
deleted file mode 100644
index c30d8206cc..0000000000
--- a/plugins/Db3x/src/dbintf.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright 2012 Miranda NG 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;
-
-CDdxMmap::CDdxMmap(const TCHAR* tszFileName)
-{
-}
-
-STDMETHODIMP_(void) CDdxMmap::SetCacheSafetyMode(BOOL bIsSet)
-{
-	{	mir_cslock lck(csDbAccess);
-		safetyMode = bIsSet;
-	}
-	DBFlush(1);
-}
diff --git a/plugins/Db3x/src/dbintf.h b/plugins/Db3x/src/dbintf.h
deleted file mode 100644
index 6e9714640b..0000000000
--- a/plugins/Db3x/src/dbintf.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright 2012 Miranda NG 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 <m_db_int.h>
-
-struct CDdxMmap : public MIDatabase
-{
-	CDdxMmap(const TCHAR* tszFileName);
-
-	STDMETHODIMP_(void)   SetCacheSafetyMode(BOOL);
-
-	STDMETHODIMP_(LONG)   GetContactCount(void);
-	STDMETHODIMP_(HANDLE) FindFirstContact(const char* szProto = NULL);
-	STDMETHODIMP_(HANDLE) FindNextContact(HANDLE hContact, const char* szProto = NULL);
-	STDMETHODIMP_(LONG)   DeleteContact(HANDLE hContact);
-	STDMETHODIMP_(HANDLE) AddContact(void);
-	STDMETHODIMP_(BOOL)   IsDbContact(HANDLE hContact);
-
-	STDMETHODIMP_(LONG)   GetEventCount(HANDLE hContact);
-	STDMETHODIMP_(HANDLE) AddEvent(HANDLE hContact, DBEVENTINFO *dbei);
-	STDMETHODIMP_(BOOL)   DeleteEvent(HANDLE hContact, HANDLE hDbEvent);
-	STDMETHODIMP_(LONG)   GetBlobSize(HANDLE hDbEvent);
-	STDMETHODIMP_(BOOL)   GetEvent(HANDLE hDbEvent, DBEVENTINFO *dbei);
-	STDMETHODIMP_(BOOL)   MarkEventRead(HANDLE hContact, HANDLE hDbEvent);
-	STDMETHODIMP_(HANDLE) GetEventContact(HANDLE hDbEvent);
-	STDMETHODIMP_(HANDLE) FindFirstEvent(HANDLE hContact);
-	STDMETHODIMP_(HANDLE) FindFirstUnreadEvent(HANDLE hContact);
-	STDMETHODIMP_(HANDLE) FindLastEvent(HANDLE hContact);
-	STDMETHODIMP_(HANDLE) FindNextEvent(HANDLE hDbEvent);
-	STDMETHODIMP_(HANDLE) FindPrevEvent(HANDLE hDbEvent);
-
-	STDMETHODIMP_(BOOL)   EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam);
-
-	STDMETHODIMP_(BOOL)   GetContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs);
-	STDMETHODIMP_(BOOL)   GetContactSettingStr(HANDLE hContact, DBCONTACTGETSETTING *dbcgs);
-	STDMETHODIMP_(BOOL)   GetContactSettingStatic(HANDLE hContact, DBCONTACTGETSETTING *dbcgs);
-	STDMETHODIMP_(BOOL)   FreeVariant(DBVARIANT *dbv);
-	STDMETHODIMP_(BOOL)   WriteContactSetting(HANDLE hContact, DBCONTACTWRITESETTING *dbcws);
-	STDMETHODIMP_(BOOL)   DeleteContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs);
-	STDMETHODIMP_(BOOL)   EnumContactSettings(HANDLE hContact, DBCONTACTENUMSETTINGS* dbces);
-	STDMETHODIMP_(BOOL)   SetSettingResident(BOOL bIsResident, const char *pszSettingName);
-	STDMETHODIMP_(BOOL)   EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam);
-
-private:
-	int CheckProto(HANDLE hContact, const char *proto);
-
-	BOOL safetyMode;
-};
diff --git a/plugins/Db3x/src/dbintf3x.cpp b/plugins/Db3x/src/dbintf3x.cpp
new file mode 100644
index 0000000000..fcbfc8ce67
--- /dev/null
+++ b/plugins/Db3x/src/dbintf3x.cpp
@@ -0,0 +1,77 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright 2012 Miranda NG 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;
+
+CDb3x::CDb3x(const TCHAR* tszFileName) :
+	CDb3Base(tszFileName)
+{
+}
+
+CDb3x::~CDb3x()
+{
+	if (m_pDbCache) {
+		mir_free(m_pDbCache);
+		KillTimer(NULL,m_flushBuffersTimerId);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+//this function caches results
+DWORD CDb3x::GetSettingsGroupOfsByModuleNameOfs(DBContact *dbc,DWORD ofsContact,DWORD ofsModuleName)
+{
+	DBContactSettings *dbcs;
+	DWORD ofsThis;
+
+	for ( int i=0; i < SETTINGSGROUPOFSCOUNT; i++)
+		if(settingsGroupOfsCache[i].ofsContact == ofsContact && settingsGroupOfsCache[i].ofsModuleName == ofsModuleName)
+			return settingsGroupOfsCache[i].ofsSettingsGroup;
+
+	ofsThis = dbc->ofsFirstSettings;
+	while(ofsThis) {
+		dbcs = (struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL);
+		if (dbcs->signature != DBCONTACTSETTINGS_SIGNATURE) DatabaseCorruption( _T("Invalid database module"));
+		if (dbcs->ofsModuleName == ofsModuleName) {
+			settingsGroupOfsCache[nextSGOCacheEntry].ofsContact = ofsContact;
+			settingsGroupOfsCache[nextSGOCacheEntry].ofsModuleName = ofsModuleName;
+			settingsGroupOfsCache[nextSGOCacheEntry].ofsSettingsGroup = ofsThis;
+			if(++nextSGOCacheEntry==SETTINGSGROUPOFSCOUNT) nextSGOCacheEntry = 0;
+			return ofsThis;
+		}
+		ofsThis = dbcs->ofsNext;
+	}
+	return 0;
+}
+
+void CDb3x::InvalidateSettingsGroupOfsCacheEntry(DWORD ofsSettingsGroup)
+{
+	for (int i=0; i < SETTINGSGROUPOFSCOUNT; i++) {
+		if (settingsGroupOfsCache[i].ofsSettingsGroup == ofsSettingsGroup) {
+			settingsGroupOfsCache[i].ofsContact = 0;
+			settingsGroupOfsCache[i].ofsModuleName = 0;
+			settingsGroupOfsCache[i].ofsSettingsGroup = 0;
+			break;
+}	}	}
diff --git a/plugins/Db3x/src/dbintf3x.h b/plugins/Db3x/src/dbintf3x.h
new file mode 100644
index 0000000000..74dad4c4a8
--- /dev/null
+++ b/plugins/Db3x/src/dbintf3x.h
@@ -0,0 +1,74 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright 2012 Miranda NG 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 <m_db_int.h>
+
+#include "..\..\Db3x_mmap\src\database.h"
+#include "..\..\Db3x_mmap\src\dbintf.h"
+
+#define CACHESECTIONSIZE   4096
+#define CACHESECTIONCOUNT  32
+
+#define SETTINGSGROUPOFSCOUNT    32
+
+struct CDb3x : public CDb3Base
+{
+	CDb3x(const TCHAR* tszFileName);
+	~CDb3x();
+
+	__inline HANDLE getFile() const { return m_hDbFile; }
+
+protected:
+	virtual	DWORD GetSettingsGroupOfsByModuleNameOfs(DBContact *dbc,DWORD ofsContact,DWORD ofsModuleName);
+	virtual	void  DBMoveChunk(DWORD ofsDest, DWORD ofsSource, int bytes);
+	virtual	PBYTE DBRead(DWORD ofs, int bytesRequired, int *bytesAvail);
+	virtual	void  DBWrite(DWORD ofs, PVOID pData, int bytes);
+	virtual	void  DBFill(DWORD ofs, int bytes);
+	virtual	void  DBFlush(int setting);
+	virtual	int   InitCache(void);
+
+	PBYTE m_pDbCache;
+	DWORD m_lastUseCounter;
+
+	struct DBCacheSectionInfo
+	{
+		DWORD ofsBase;
+		DWORD lastUsed;
+	} 
+	cacheSectionInfo[CACHESECTIONCOUNT];
+
+	int nextSGOCacheEntry;
+	struct SettingsGroupOfsCacheEntry {
+		DWORD ofsContact;
+		DWORD ofsModuleName;
+		DWORD ofsSettingsGroup;
+	}
+	settingsGroupOfsCache[SETTINGSGROUPOFSCOUNT];
+
+	int  FindSectionForOffset(const DWORD ofs);
+	int  FindLRUSection(void);
+	void LoadSection(const int i,DWORD ofs);
+	void MoveSection(int *sectId,int dest);
+
+	void InvalidateSettingsGroupOfsCacheEntry(DWORD ofsSettingsGroup);
+};
diff --git a/plugins/Db3x/src/dbmodulechain.cpp b/plugins/Db3x/src/dbmodulechain.cpp
deleted file mode 100644
index fb7c6e4ce3..0000000000
--- a/plugins/Db3x/src/dbmodulechain.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-
-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"
-
-static INT_PTR EnumModuleNames(WPARAM wParam,LPARAM lParam);
-
-struct ModuleName {
-	char *name;
-	DWORD hash;
-	DWORD ofs;
-};
-static struct ModuleName *moduleName;
-static int moduleNameCount;
-
-int InitModuleNames(void)
-{
-	struct DBModuleName *dbmn;
-	DWORD ofsThis,ofsNext;
-	int nameLen;
-
-	moduleNameCount = 0;
-	moduleName = NULL;
-	ofsThis = dbHeader.ofsFirstModuleName;
-	dbmn = (struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL);
-	while(ofsThis) {
-		if (dbmn->signature!= DBMODULENAME_SIGNATURE) DatabaseCorruption();
-		moduleName = (struct ModuleName*)mir_realloc(moduleName,sizeof(struct ModuleName)*(moduleNameCount+1));
-		moduleName[moduleNameCount].ofs = ofsThis;
-		moduleName[moduleNameCount].hash = dbmn->cbName;    //very very simple hash so far
-		moduleName[moduleNameCount].name = (char*)mir_alloc(dbmn->cbName+1);
-		ofsNext = dbmn->ofsNext;
-		nameLen = dbmn->cbName;
-		CopyMemory(moduleName[moduleNameCount].name,DBRead(ofsThis+offsetof(struct DBModuleName,name),nameLen,NULL),nameLen);
-		moduleName[moduleNameCount].name[nameLen] = 0;
-		moduleNameCount++;
-		ofsThis = ofsNext;
-		dbmn = (struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL);
-	}
-	return 0;
-}
-
-void UninitModuleNames(void)
-{
-	int i;
-	for(i = 0;i<moduleNameCount;i++) mir_free(moduleName[i].name);
-	if (moduleNameCount) mir_free(moduleName);
-}
-
-static DWORD FindExistingModuleNameOfs(const char *szName,int nameLen)
-{
-	int i;
-	for(i = 0;i<moduleNameCount;i++)
-		if (moduleName[i].hash == (DWORD)nameLen && !strcmp(moduleName[i].name,szName)) return moduleName[i].ofs;
-	return 0;
-}
-
-//will create the offset if it needs to
-DWORD GetModuleNameOfs(const char *szName)
-{
-	struct DBModuleName dbmn;
-	int nameLen = (int)strlen(szName);
-	DWORD ofsNew,ofsExisting;
-
-	ofsExisting = FindExistingModuleNameOfs(szName,nameLen);
-	if (ofsExisting) return ofsExisting;
-	//need to create the module name
-	ofsNew = CreateNewSpace(nameLen+offsetof(struct DBModuleName,name));
-	dbmn.signature = DBMODULENAME_SIGNATURE;
-	dbmn.cbName = nameLen;
-	dbmn.ofsNext = dbHeader.ofsFirstModuleName;
-	dbHeader.ofsFirstModuleName = ofsNew;
-	DBWrite(0,&dbHeader,sizeof(dbHeader));
-	DBWrite(ofsNew,&dbmn,offsetof(struct DBModuleName,name));
-	DBWrite(ofsNew+offsetof(struct DBModuleName,name),(PVOID)szName,nameLen);
-	DBFlush(0);
-	//add to cache
-	moduleName = (struct ModuleName*)mir_realloc(moduleName,sizeof(struct ModuleName)*(moduleNameCount+1));
-	moduleName[moduleNameCount].ofs = ofsNew;
-	moduleName[moduleNameCount].hash = nameLen;    //very very simple hash so far
-	moduleName[moduleNameCount].name = (char*)mir_alloc(nameLen+1);
-	strcpy(moduleName[moduleNameCount].name,szName);
-	moduleNameCount++;
-	//quit
-	return ofsNew;
-}
-
-//it's OK that this is a bit slow - it's rarely used
-char *GetModuleNameByOfs(DWORD ofs)
-{
-	int i;
-
-	for(i = 0;i<moduleNameCount;i++)
-		if (moduleName[i].ofs == ofs) return moduleName[i].name;
-	DatabaseCorruption();
-	return NULL;
-} 
-
-STDMETHODIMP_(BOOL) CDdxMmap::EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam)
-{
-	int i;
-	INT_PTR ret;
-	for(i = 0;i<moduleNameCount;i++) {
-		ret = pFunc(moduleName[i].name,moduleName[i].ofs, (LPARAM)pParam);
-		if (ret) return ret;
-	}
-	return 0;
-}
diff --git a/plugins/Db3x/src/dbsettings.cpp b/plugins/Db3x/src/dbsettings.cpp
deleted file mode 100644
index db21b64db8..0000000000
--- a/plugins/Db3x/src/dbsettings.cpp
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
-
-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"
-
-DWORD GetModuleNameOfs(const char *szName);
-
-HANDLE hCacheHeap = NULL;
-SortedList lContacts;
-
-static SortedList lSettings, lGlobalSettings;
-static HANDLE hSettingChangeEvent = NULL;
-
-#define SETTINGSGROUPOFSCOUNT    32
-struct SettingsGroupOfsCacheEntry {
-	DWORD ofsContact;
-	DWORD ofsModuleName;
-	DWORD ofsSettingsGroup;
-};
-static struct SettingsGroupOfsCacheEntry settingsGroupOfsCache[SETTINGSGROUPOFSCOUNT];
-static int nextSGOCacheEntry;
-static int mirCp = CP_ACP;
-
-//this function caches results
-static DWORD GetSettingsGroupOfsByModuleNameOfs(DBContact *dbc,DWORD ofsContact,DWORD ofsModuleName)
-{
-	struct DBContactSettings *dbcs;
-	DWORD ofsThis;
-	int i;
-
-	for(i = 0;i<SETTINGSGROUPOFSCOUNT;i++) {
-		if (settingsGroupOfsCache[i].ofsContact == ofsContact && settingsGroupOfsCache[i].ofsModuleName == ofsModuleName)
-			return settingsGroupOfsCache[i].ofsSettingsGroup;
-	}
-	ofsThis = dbc->ofsFirstSettings;
-	while(ofsThis) {
-		dbcs = (struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL);
-		if (dbcs->signature!= DBCONTACTSETTINGS_SIGNATURE) DatabaseCorruption();
-		if (dbcs->ofsModuleName == ofsModuleName) {
-			settingsGroupOfsCache[nextSGOCacheEntry].ofsContact = ofsContact;
-			settingsGroupOfsCache[nextSGOCacheEntry].ofsModuleName = ofsModuleName;
-			settingsGroupOfsCache[nextSGOCacheEntry].ofsSettingsGroup = ofsThis;
-			if (++nextSGOCacheEntry == SETTINGSGROUPOFSCOUNT) nextSGOCacheEntry = 0;
-			return ofsThis;
-		}
-		ofsThis = dbcs->ofsNext;
-	}
-	return 0;
-}
-
-static void InvalidateSettingsGroupOfsCacheEntry(DWORD ofsSettingsGroup)
-{
-	for(int i = 0;i<SETTINGSGROUPOFSCOUNT;i++) {
-		if (settingsGroupOfsCache[i].ofsSettingsGroup == ofsSettingsGroup) {
-			settingsGroupOfsCache[i].ofsContact = 0;
-			settingsGroupOfsCache[i].ofsModuleName = 0;
-			settingsGroupOfsCache[i].ofsSettingsGroup = 0;
-			break;
-}	}	}
-
-static DWORD __inline GetSettingValueLength(PBYTE pSetting)
-{
-	if (pSetting[0]&DBVTF_VARIABLELENGTH) return 2+*(PWORD)(pSetting+1);
-	return pSetting[0];
-}
-
-static char* InsertCachedSetting( const char* szName, size_t cbNameLen, int index )
-{
-	char* newValue = (char*)HeapAlloc( hCacheHeap, 0, cbNameLen );
-	*newValue = 0;
-	strcpy(newValue+1,szName+1);
-	List_Insert(&lSettings,newValue,index);
-	return newValue;
-}
-
-static char* GetCachedSetting(const char *szModuleName,const char *szSettingName,int settingNameLen)
-{
-	static char *lastsetting = NULL;
-	int moduleNameLen = (int)strlen(szModuleName),index;
-	char *szFullName = (char*)alloca(moduleNameLen+settingNameLen+3);
-
-	strcpy(szFullName+1,szModuleName);
-	szFullName[moduleNameLen+1] = '/';
-	strcpy(szFullName+moduleNameLen+2,szSettingName);
-
-	if (lastsetting && strcmp(szFullName+1,lastsetting) == 0)
-		return lastsetting;
-
-	if ( List_GetIndex(&lSettings, szFullName, &index))
-		lastsetting = (char*)lSettings.items[index] + 1;
-	else
-		lastsetting = InsertCachedSetting( szFullName, moduleNameLen+settingNameLen+3, index )+1;
-	return lastsetting;
-}
-
-static void SetCachedVariant( DBVARIANT* s /* new */, DBVARIANT* d /* cached */ )
-{
-	char* szSave = ( d->type == DBVT_UTF8 || d->type == DBVT_ASCIIZ ) ? d->pszVal : NULL;
-
-	memcpy( d, s, sizeof( DBVARIANT ));
-	if (( s->type == DBVT_UTF8 || s->type == DBVT_ASCIIZ ) && s->pszVal != NULL ) {
-		if ( szSave != NULL )
-			d->pszVal = (char*)HeapReAlloc(hCacheHeap,0,szSave,strlen(s->pszVal)+1);
-		else
-			d->pszVal = (char*)HeapAlloc(hCacheHeap,0,strlen(s->pszVal)+1);
-		strcpy(d->pszVal,s->pszVal);
-	}
-
-	switch( d->type ) {
-		case DBVT_BYTE:	log1( "set cached byte: %d", d->bVal ); break;
-		case DBVT_WORD:	log1( "set cached word: %d", d->wVal ); break;
-		case DBVT_DWORD:	log1( "set cached dword: %d", d->dVal ); break;
-		case DBVT_UTF8:
-		case DBVT_ASCIIZ: log1( "set cached string: '%s'", d->pszVal ); break;
-		default:				log1( "set cached crap: %d", d->type ); break;
-}	}
-
-static void FreeCachedVariant( DBVARIANT* V )
-{
-	if (( V->type == DBVT_ASCIIZ || V->type == DBVT_UTF8 ) && V->pszVal != NULL )
-		HeapFree(hCacheHeap,0,V->pszVal);
-}
-
-static DBVARIANT* GetCachedValuePtr( HANDLE hContact, char* szSetting, int bAllocate )
-{
-	int index;
-
-	if ( hContact == 0 ) {
-		DBCachedGlobalValue Vtemp, *V;
-		Vtemp.name = szSetting;
-		if ( List_GetIndex(&lGlobalSettings,&Vtemp,&index)) {
-			V = (DBCachedGlobalValue*)lGlobalSettings.items[index];
-			if ( bAllocate == -1 ) {
-				FreeCachedVariant( &V->value );
-				List_Remove(&lGlobalSettings,index);
-				HeapFree(hCacheHeap,0,V);
-				return NULL;
-		}	}
-		else {
-			if ( bAllocate != 1 )
-				return NULL;
-
-			V = (DBCachedGlobalValue*)HeapAlloc(hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedGlobalValue));
-			V->name = szSetting;
-			List_Insert(&lGlobalSettings,V,index);
-		}
-
-		return &V->value;
-	}
-	else {
-		DBCachedContactValue *V, *V1;
-		DBCachedContactValueList VLtemp,*VL;
-
-		VLtemp.hContact = hContact;
-		if ( List_GetIndex(&lContacts,&VLtemp,&index)) {
-			VL = (DBCachedContactValueList*)lContacts.items[index];
-		}
-		else {
-			if ( bAllocate != 1 )
-				return NULL;
-
-			VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList));
-			VL->hContact = hContact;
-			List_Insert(&lContacts,VL,index);
-		}
-
-		for ( V = VL->first; V != NULL; V = V->next)
-			if (strcmp(V->name,szSetting) == 0)
-				break;
-
-		if ( V == NULL ) {
-			if ( bAllocate != 1 )
-				return NULL;
-
-			V = (DBCachedContactValue *)HeapAlloc(hCacheHeap, HEAP_ZERO_MEMORY, sizeof(DBCachedContactValue));
-			V->next = VL->first;
-			VL->first = V;
-			V->name = szSetting;
-		}
-		else if ( bAllocate == -1 ) {
-			FreeCachedVariant(&V->value);
-			if ( VL->first == V )
-				VL->first = V->next;
-			for ( V1 = VL->first; V1 != NULL; V1 = V1->next )
-				if ( V1->next == V ) {
-					V1->next = V->next;
-					break;
-				}
-			HeapFree(hCacheHeap,0,V);
-			return NULL;
-		}
-
-		return &V->value;
-}	}
-
-#define NeedBytes(n)   if (bytesRemaining<(n)) pBlob = (PBYTE)DBRead(ofsBlobPtr,(n),&bytesRemaining)
-#define MoveAlong(n)   {int x = n; pBlob += (x); ofsBlobPtr += (x); bytesRemaining -= (x);}
-#define VLT(n) ((n == DBVT_UTF8)?DBVT_ASCIIZ:n)
-static __inline int GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs,int isStatic)
-{
-	DBContact dbc;
-	struct DBContactSettings dbcs;
-	DWORD ofsModuleName,ofsContact,ofsSettingsGroup,ofsBlobPtr;
-	int settingNameLen;
-	int bytesRemaining;
-	PBYTE pBlob;
-	char* szCachedSettingName;
-
-	if ((!dbcgs->szSetting) || (!dbcgs->szModule))
-		return 1;
-	settingNameLen = (int)strlen(dbcgs->szSetting);
-
-	EnterCriticalSection(&csDbAccess);
-
-	log3("get [%08p] %s/%s",hContact,dbcgs->szModule,dbcgs->szSetting);
-
-	szCachedSettingName = GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,settingNameLen);
-	{
-		DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 0 );
-		if ( pCachedValue != NULL ) {
-			if ( pCachedValue->type == DBVT_ASCIIZ || pCachedValue->type == DBVT_UTF8 ) {
-				int   cbOrigLen = dbcgs->pValue->cchVal;
-				char* cbOrigPtr = dbcgs->pValue->pszVal;
-				memcpy( dbcgs->pValue, pCachedValue, sizeof( DBVARIANT ));
-				if ( isStatic ) {
-					int cbLen = 0;
-					if ( pCachedValue->pszVal != NULL )
-						cbLen = (int)strlen( pCachedValue->pszVal );
-
-					cbOrigLen--;
-					dbcgs->pValue->pszVal = cbOrigPtr;
-					if (cbLen<cbOrigLen) cbOrigLen = cbLen;
-					CopyMemory(dbcgs->pValue->pszVal,pCachedValue->pszVal,cbOrigLen);
-					dbcgs->pValue->pszVal[cbOrigLen] = 0;
-					dbcgs->pValue->cchVal = cbLen;
-				}
-				else {
-					dbcgs->pValue->pszVal = (char*)mir_alloc(strlen(pCachedValue->pszVal)+1);
-					strcpy(dbcgs->pValue->pszVal,pCachedValue->pszVal);
-				}
-			}
-			else
-				memcpy( dbcgs->pValue, pCachedValue, sizeof( DBVARIANT ));
-
-			switch( dbcgs->pValue->type ) {
-				case DBVT_BYTE:	log1( "get cached byte: %d", dbcgs->pValue->bVal ); break;
-				case DBVT_WORD:	log1( "get cached word: %d", dbcgs->pValue->wVal ); break;
-				case DBVT_DWORD:	log1( "get cached dword: %d", dbcgs->pValue->dVal ); break;
-				case DBVT_UTF8:
-				case DBVT_ASCIIZ: log1( "get cached string: '%s'", dbcgs->pValue->pszVal); break;
-				default:				log1( "get cached crap: %d", dbcgs->pValue->type ); break;
-			}
-
-			LeaveCriticalSection(&csDbAccess);
-			return ( pCachedValue->type == DBVT_DELETED ) ? 1 : 0;
-	}	}
-
-	ofsModuleName = GetModuleNameOfs(dbcgs->szModule);
-	if (hContact == NULL) ofsContact = dbHeader.ofsUser;
-	else ofsContact = (DWORD)hContact;
-	dbc = *(DBContact*)DBRead(ofsContact,sizeof(DBContact),NULL);
-	if (dbc.signature!= DBCONTACT_SIGNATURE) {
-		LeaveCriticalSection(&csDbAccess);
-		return 1;
-	}
-	ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc,ofsContact,ofsModuleName);
-	if (ofsSettingsGroup) {
-		dbcs = *(struct DBContactSettings*)DBRead(ofsSettingsGroup,sizeof(struct DBContactSettings),&bytesRemaining);
-		ofsBlobPtr = ofsSettingsGroup+offsetof(struct DBContactSettings,blob);
-		pBlob = (PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining);
-		while(pBlob[0]) {
-			NeedBytes(1+settingNameLen);
-			if (pBlob[0] == settingNameLen && !memcmp(pBlob+1,dbcgs->szSetting,settingNameLen)) {
-				MoveAlong(1+settingNameLen);
-				NeedBytes(5);
-				if (isStatic && pBlob[0]&DBVTF_VARIABLELENGTH && VLT(dbcgs->pValue->type) != VLT(pBlob[0])) {
-					LeaveCriticalSection(&csDbAccess);
-					return 1;
-				}
-				dbcgs->pValue->type = pBlob[0];
-				switch(pBlob[0]) {
-					case DBVT_DELETED: { /* this setting is deleted */
-						dbcgs->pValue->type = DBVT_DELETED;
-						LeaveCriticalSection(&csDbAccess);
-						return 2;
-					}
-					case DBVT_BYTE: dbcgs->pValue->bVal = pBlob[1]; break;
-					case DBVT_WORD: dbcgs->pValue->wVal = *(PWORD)(pBlob+1); break;
-					case DBVT_DWORD: dbcgs->pValue->dVal = *(PDWORD)(pBlob+1); break;
-					case DBVT_UTF8:
-					case DBVT_ASCIIZ:
-						NeedBytes(3+*(PWORD)(pBlob+1));
-						if (isStatic) {
-							dbcgs->pValue->cchVal--;
-							if (*(PWORD)(pBlob+1)<dbcgs->pValue->cchVal) dbcgs->pValue->cchVal = *(PWORD)(pBlob+1);
-							CopyMemory(dbcgs->pValue->pszVal,pBlob+3,dbcgs->pValue->cchVal);
-							dbcgs->pValue->pszVal[dbcgs->pValue->cchVal] = 0;
-							dbcgs->pValue->cchVal = *(PWORD)(pBlob+1);
-						}
-						else {
-							dbcgs->pValue->pszVal = (char*)mir_alloc(1+*(PWORD)(pBlob+1));
-							CopyMemory(dbcgs->pValue->pszVal,pBlob+3,*(PWORD)(pBlob+1));
-							dbcgs->pValue->pszVal[*(PWORD)(pBlob+1)] = 0;
-						}
-						break;
-					case DBVT_BLOB:
-						NeedBytes(3+*(PWORD)(pBlob+1));
-						if (isStatic) {
-							if (*(PWORD)(pBlob+1)<dbcgs->pValue->cpbVal) dbcgs->pValue->cpbVal = *(PWORD)(pBlob+1);
-							CopyMemory(dbcgs->pValue->pbVal,pBlob+3,dbcgs->pValue->cpbVal);
-						}
-						else {
-							dbcgs->pValue->pbVal = (BYTE *)mir_alloc(*(PWORD)(pBlob + 1));
-							CopyMemory(dbcgs->pValue->pbVal,pBlob+3,*(PWORD)(pBlob+1));
-						}
-						dbcgs->pValue->cpbVal = *(PWORD)(pBlob+1);
-						break;
-				}
-
-				/**** add to cache **********************/
-				if ( dbcgs->pValue->type != DBVT_BLOB )
-				{
-					DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 1 );
-					if ( pCachedValue != NULL )
-						SetCachedVariant(dbcgs->pValue,pCachedValue);
-				}
-
-				LeaveCriticalSection(&csDbAccess);
-				logg();
-				return 0;
-			}
-			NeedBytes(1);
-			MoveAlong(pBlob[0]+1);
-			NeedBytes(3);
-			MoveAlong(1+GetSettingValueLength(pBlob));
-			NeedBytes(1);
-	}	}
-
-	/**** add missing setting to cache **********************/
-	if ( dbcgs->pValue->type != DBVT_BLOB )
-	{
-		DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 1 );
-		if ( pCachedValue != NULL )
-			pCachedValue->type = DBVT_DELETED;
-	}
-
-	LeaveCriticalSection(&csDbAccess);
-	logg();
-	return 1;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::GetContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dgs)
-{
-	dgs->pValue->type = 0;
-	if ( GetContactSettingWorker(hContact, dgs, 0))
-		return 1;
-
-	if ( dgs->pValue->type == DBVT_UTF8 ) {
-		WCHAR* tmp = NULL;
-		char*  p = NEWSTR_ALLOCA(dgs->pValue->pszVal);
-		if ( mir_utf8decode( p, &tmp ) != NULL ) {
-			BOOL bUsed = FALSE;
-			int  result = WideCharToMultiByte( mirCp, WC_NO_BEST_FIT_CHARS, tmp, -1, NULL, 0, NULL, &bUsed );
-
-			mir_free( dgs->pValue->pszVal );
-
-			if ( bUsed || result == 0 ) {
-				dgs->pValue->type = DBVT_WCHAR;
-				dgs->pValue->pwszVal = tmp;
-			}
-			else {
-				dgs->pValue->type = DBVT_ASCIIZ;
-				dgs->pValue->pszVal = (char *)mir_alloc(result);
-				WideCharToMultiByte( mirCp, WC_NO_BEST_FIT_CHARS, tmp, -1, dgs->pValue->pszVal, result, NULL, NULL );
-				mir_free( tmp );
-			}
-		}
-		else {
-			dgs->pValue->type = DBVT_ASCIIZ;
-			mir_free( tmp );
-	}	}
-
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::GetContactSettingStr(HANDLE hContact, DBCONTACTGETSETTING *dgs)
-{
-	int iSaveType = dgs->pValue->type;
-
-	if ( GetContactSettingWorker(hContact, dgs, 0))
-		return 1;
-
-	if ( iSaveType == 0 || iSaveType == dgs->pValue->type )
-		return 0;
-
-	if ( dgs->pValue->type != DBVT_ASCIIZ && dgs->pValue->type != DBVT_UTF8 )
-		return 1;
-
-	if ( iSaveType == DBVT_WCHAR ) {
-		if ( dgs->pValue->type != DBVT_UTF8 ) {
-			int len = MultiByteToWideChar( CP_ACP, 0, dgs->pValue->pszVal, -1, NULL, 0 );
-			wchar_t* wszResult = ( wchar_t* )mir_alloc(( len+1 )*sizeof( wchar_t ));
-			if ( wszResult == NULL )
-				return 1;
-
-			MultiByteToWideChar( CP_ACP, 0, dgs->pValue->pszVal, -1, wszResult, len );
-			wszResult[ len ] = 0;
-			mir_free( dgs->pValue->pszVal );
-			dgs->pValue->pwszVal = wszResult;
-		}
-		else {
-			char* savePtr = NEWSTR_ALLOCA(dgs->pValue->pszVal);
-			mir_free( dgs->pValue->pszVal );
-			if ( !mir_utf8decode( savePtr, &dgs->pValue->pwszVal ))
-				return 1;
-		}
-	}
-	else if ( iSaveType == DBVT_UTF8 ) {
-		char* tmpBuf = mir_utf8encode( dgs->pValue->pszVal );
-		if ( tmpBuf == NULL )
-			return 1;
-
-		mir_free( dgs->pValue->pszVal );
-		dgs->pValue->pszVal = tmpBuf;
-	}
-	else if ( iSaveType == DBVT_ASCIIZ )
-		mir_utf8decode( dgs->pValue->pszVal, NULL );
-
-	dgs->pValue->type = iSaveType;
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::GetContactSettingStatic(HANDLE hContact, DBCONTACTGETSETTING *dgs)
-{
-	if ( GetContactSettingWorker(hContact, dgs, 1))
-		return 1;
-
-	if ( dgs->pValue->type == DBVT_UTF8 ) {
-		mir_utf8decode( dgs->pValue->pszVal, NULL );
-		dgs->pValue->type = DBVT_ASCIIZ;
-	}
-
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::FreeVariant(DBVARIANT *dbv)
-{
-	if ( dbv == 0 ) return 1;
-	switch ( dbv->type ) {
-		case DBVT_ASCIIZ:
-		case DBVT_UTF8:
-		case DBVT_WCHAR:
-		{
-			if ( dbv->pszVal ) mir_free(dbv->pszVal);
-			dbv->pszVal = 0;
-			break;
-		}
-		case DBVT_BLOB:
-		{
-			if ( dbv->pbVal ) mir_free(dbv->pbVal);
-			dbv->pbVal = 0;
-			break;
-		}
-	}
-	dbv->type = 0;
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::SetSettingResident(BOOL bIsResident, const char *pszSettingName)
-{
-	char*  szSetting;
-	size_t cbSettingNameLen = strlen(pszSettingName);
-	int    idx;
-	char*  szTemp = (char*)alloca( cbSettingNameLen+2 );
-	strcpy( szTemp+1, pszSettingName);
-
-	EnterCriticalSection(&csDbAccess);
-	if ( !List_GetIndex( &lSettings, szTemp, &idx ))
-		szSetting = InsertCachedSetting( szTemp, cbSettingNameLen+2, idx );
-	else
-		szSetting = (char *)lSettings.items[idx];
-
-   *szSetting = (char)bIsResident;
-
-	LeaveCriticalSection(&csDbAccess);
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::WriteContactSetting(HANDLE hContact, DBCONTACTWRITESETTING *dbcws)
-{
-	DBCONTACTWRITESETTING tmp;
-	DBContact dbc;
-	DWORD ofsModuleName;
-	struct DBContactSettings dbcs;
-	PBYTE pBlob;
-	int settingNameLen = 0;
-	int moduleNameLen = 0;
-	int settingDataLen = 0;
-	int bytesRequired,bytesRemaining;
-	DWORD ofsContact,ofsSettingsGroup,ofsBlobPtr;
-
-	if (dbcws == NULL || dbcws->szSetting == NULL || dbcws->szModule == NULL )
-		return 1;
-
-	tmp = *dbcws;
-	if (tmp.value.type == DBVT_WCHAR) {
-		if (tmp.value.pszVal != NULL) {
-			char* val = mir_utf8encodeW(tmp.value.pwszVal);
-			if ( val == NULL )
-				return 1;
-
-			tmp.value.pszVal = ( char* )alloca( strlen( val )+1 );
-			strcpy( tmp.value.pszVal, val );
-			mir_free(val);
-			tmp.value.type = DBVT_UTF8;
-		}
-		else return 1;
-	}
-
-	if (tmp.value.type!= DBVT_BYTE && tmp.value.type!= DBVT_WORD && tmp.value.type!= DBVT_DWORD && tmp.value.type!= DBVT_ASCIIZ && tmp.value.type!= DBVT_UTF8 && tmp.value.type!= DBVT_BLOB)
-		return 1;
-	if ((!tmp.szModule) || (!tmp.szSetting) || ((tmp.value.type == DBVT_ASCIIZ || tmp.value.type == DBVT_UTF8 )&& tmp.value.pszVal == NULL) || (tmp.value.type == DBVT_BLOB && tmp.value.pbVal == NULL))
-		return 1;
-	// the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name
-	settingNameLen = (int)strlen(tmp.szSetting);
-	moduleNameLen = (int)strlen(tmp.szModule);
-	if ( settingNameLen > 0xFE )
-	{
-		#ifdef _DEBUG
-			OutputDebugString(_T("WriteContactSetting() got a > 255 setting name length. \n"));
-		#endif
-		return 1;
-	}
-	if ( moduleNameLen > 0xFE )
-	{
-		#ifdef _DEBUG
-			OutputDebugString(_T("WriteContactSetting() got a > 255 module name length. \n"));
-		#endif
-		return 1;
-	}
-
-	// the db can not tolerate strings/blobs longer than 0xFFFF since the format writes 2 lengths
-	switch( tmp.value.type ) {
-	case DBVT_ASCIIZ:		case DBVT_BLOB:	case DBVT_UTF8:
-		{	int len = ( tmp.value.type != DBVT_BLOB ) ? (int)strlen(tmp.value.pszVal) : tmp.value.cpbVal;
-			if ( len  >=  0xFFFF ) {
-				#ifdef _DEBUG
-					OutputDebugString(_T("WriteContactSetting() writing huge string/blob, rejecting (  >=  0xFFFF ) \n"));
-				#endif
-				return 1;
-			}
-		}
-	}
-
-	EnterCriticalSection(&csDbAccess);
-	{
-		char* szCachedSettingName = GetCachedSetting(tmp.szModule, tmp.szSetting, settingNameLen);
-		if ( tmp.value.type != DBVT_BLOB ) {
-			DBVARIANT* pCachedValue = GetCachedValuePtr(hContact, szCachedSettingName, 1);
-			if ( pCachedValue != NULL ) {
-				BOOL bIsIdentical = FALSE;
-				if ( pCachedValue->type == tmp.value.type ) {
-					switch(tmp.value.type) {
-						case DBVT_BYTE:   bIsIdentical = pCachedValue->bVal == tmp.value.bVal;  break;
-						case DBVT_WORD:   bIsIdentical = pCachedValue->wVal == tmp.value.wVal;  break;
-						case DBVT_DWORD:  bIsIdentical = pCachedValue->dVal == tmp.value.dVal;  break;
-						case DBVT_UTF8:
-						case DBVT_ASCIIZ: bIsIdentical = strcmp( pCachedValue->pszVal, tmp.value.pszVal ) == 0; break;
-					}
-					if ( bIsIdentical ) {
-						LeaveCriticalSection(&csDbAccess);
-						return 0;
-					}
-				}
-				SetCachedVariant(&tmp.value, pCachedValue);
-			}
-			if ( szCachedSettingName[-1] != 0 ) {
-				LeaveCriticalSection(&csDbAccess);
-				NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)&tmp);
-				return 0;
-			}
-		}
-		else GetCachedValuePtr(hContact, szCachedSettingName, -1);
-	}
-
-	ofsModuleName = GetModuleNameOfs(tmp.szModule);
- 	if (hContact == 0)
-		ofsContact = dbHeader.ofsUser;
-	else
-		ofsContact = (DWORD)hContact;
-
-	dbc = *(DBContact*)DBRead(ofsContact,sizeof(DBContact),NULL);
-	if (dbc.signature!= DBCONTACT_SIGNATURE) {
-		LeaveCriticalSection(&csDbAccess);
-		return 1;
-	}
-	log0("write setting");
-	//make sure the module group exists
-	ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc,ofsContact,ofsModuleName);
-	if (ofsSettingsGroup == 0) {  //module group didn't exist - make it
-		if (tmp.value.type&DBVTF_VARIABLELENGTH) {
-		  if (tmp.value.type == DBVT_ASCIIZ || tmp.value.type == DBVT_UTF8) bytesRequired = (int)strlen(tmp.value.pszVal)+2;
-		  else if (tmp.value.type == DBVT_BLOB) bytesRequired = tmp.value.cpbVal+2;
-		}
-		else bytesRequired = tmp.value.type;
-		bytesRequired += 2+settingNameLen;
-		bytesRequired += (DB_SETTINGS_RESIZE_GRANULARITY-(bytesRequired%DB_SETTINGS_RESIZE_GRANULARITY))%DB_SETTINGS_RESIZE_GRANULARITY;
-		ofsSettingsGroup = CreateNewSpace(bytesRequired+offsetof(struct DBContactSettings,blob));
-		dbcs.signature = DBCONTACTSETTINGS_SIGNATURE;
-		dbcs.ofsNext = dbc.ofsFirstSettings;
-		dbcs.ofsModuleName = ofsModuleName;
-		dbcs.cbBlob = bytesRequired;
-		dbcs.blob[0] = 0;
-		dbc.ofsFirstSettings = ofsSettingsGroup;
-		DBWrite(ofsContact,&dbc,sizeof(DBContact));
-		DBWrite(ofsSettingsGroup,&dbcs,sizeof(struct DBContactSettings));
-		ofsBlobPtr = ofsSettingsGroup+offsetof(struct DBContactSettings,blob);
-		pBlob = (PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining);
-	}
-	else {
-		dbcs = *(struct DBContactSettings*)DBRead(ofsSettingsGroup,sizeof(struct DBContactSettings),&bytesRemaining);
-		//find if the setting exists
-		ofsBlobPtr = ofsSettingsGroup+offsetof(struct DBContactSettings,blob);
-		pBlob = (PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining);
-		while(pBlob[0]) {
-			NeedBytes(settingNameLen+1);
-			if (pBlob[0] == settingNameLen && !memcmp(pBlob+1,tmp.szSetting,settingNameLen))
-				break;
-			NeedBytes(1);
-			MoveAlong(pBlob[0]+1);
-			NeedBytes(3);
-			MoveAlong(1+GetSettingValueLength(pBlob));
-			NeedBytes(1);
-		}
-		if (pBlob[0]) {	 //setting already existed, and up to end of name is in cache
-			MoveAlong(1+settingNameLen);
-			//if different type or variable length and length is different
-			NeedBytes(3);
-			if (pBlob[0]!= tmp.value.type || ((pBlob[0] == DBVT_ASCIIZ || pBlob[0] == DBVT_UTF8) && *(PWORD)(pBlob+1)!= strlen(tmp.value.pszVal)) || (pBlob[0] == DBVT_BLOB && *(PWORD)(pBlob+1)!= tmp.value.cpbVal)) {
-				//bin it
-				int nameLen,valLen;
-				DWORD ofsSettingToCut;
-				NeedBytes(3);
-				nameLen = 1+settingNameLen;
-				valLen = 1+GetSettingValueLength(pBlob);
-				ofsSettingToCut = ofsBlobPtr-nameLen;
-				MoveAlong(valLen);
-				NeedBytes(1);
-				while(pBlob[0]) {
-					MoveAlong(pBlob[0]+1);
-					NeedBytes(3);
-					MoveAlong(1+GetSettingValueLength(pBlob));
-					NeedBytes(1);
-				}
-				DBMoveChunk(ofsSettingToCut,ofsSettingToCut+nameLen+valLen,ofsBlobPtr+1-ofsSettingToCut);
-				ofsBlobPtr -= nameLen+valLen;
-				pBlob = (PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining);
-			}
-			else {
-				//replace existing setting at pBlob
-				MoveAlong(1);	//skip data type
-				switch(tmp.value.type) {
-					case DBVT_BYTE: DBWrite(ofsBlobPtr,&tmp.value.bVal,1); break;
-					case DBVT_WORD: DBWrite(ofsBlobPtr,&tmp.value.wVal,2); break;
-					case DBVT_DWORD: DBWrite(ofsBlobPtr,&tmp.value.dVal,4); break;
-					case DBVT_UTF8:
-					case DBVT_ASCIIZ: DBWrite(ofsBlobPtr+2,tmp.value.pszVal,(int)strlen(tmp.value.pszVal)); break;
-					case DBVT_BLOB: DBWrite(ofsBlobPtr+2,tmp.value.pbVal,tmp.value.cpbVal); break;
-				}
-				//quit
-				DBFlush(1);
-				LeaveCriticalSection(&csDbAccess);
-				//notify
-				NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)&tmp);
-				return 0;
-			}
-		}
-	}
-	//cannot do a simple replace, add setting to end of list
-	//pBlob already points to end of list
-	//see if it fits
-	if (tmp.value.type&DBVTF_VARIABLELENGTH) {
-	  if (tmp.value.type == DBVT_ASCIIZ || tmp.value.type == DBVT_UTF8) bytesRequired = (int)strlen(tmp.value.pszVal)+2;
-	  else if (tmp.value.type == DBVT_BLOB) bytesRequired = tmp.value.cpbVal+2;
-	}
-	else bytesRequired = tmp.value.type;
-	bytesRequired += 2+settingNameLen;
-	bytesRequired += ofsBlobPtr+1-(ofsSettingsGroup+offsetof(struct DBContactSettings,blob));
-	if ((DWORD)bytesRequired>dbcs.cbBlob) {
-		//doesn't fit: move entire group
-		struct DBContactSettings *dbcsPrev;
-		DWORD ofsDbcsPrev,oldSize,ofsNew;
-
-		InvalidateSettingsGroupOfsCacheEntry(ofsSettingsGroup);
-		bytesRequired += (DB_SETTINGS_RESIZE_GRANULARITY-(bytesRequired%DB_SETTINGS_RESIZE_GRANULARITY))%DB_SETTINGS_RESIZE_GRANULARITY;
-		//find previous group to change its offset
-		ofsDbcsPrev = dbc.ofsFirstSettings;
-		if (ofsDbcsPrev == ofsSettingsGroup) ofsDbcsPrev = 0;
-		else {
-			dbcsPrev = (struct DBContactSettings*)DBRead(ofsDbcsPrev,sizeof(struct DBContactSettings),NULL);
-			while(dbcsPrev->ofsNext!= ofsSettingsGroup) {
-				if (dbcsPrev->ofsNext == 0) DatabaseCorruption();
-				ofsDbcsPrev = dbcsPrev->ofsNext;
-				dbcsPrev = (struct DBContactSettings*)DBRead(ofsDbcsPrev,sizeof(struct DBContactSettings),NULL);
-			}
-		}
-		//create the new one
-		ofsNew = CreateNewSpace(bytesRequired+offsetof(struct DBContactSettings,blob));
-		//copy across
-		DBMoveChunk(ofsNew,ofsSettingsGroup,bytesRequired+offsetof(struct DBContactSettings,blob));
-		oldSize = dbcs.cbBlob;
-		dbcs.cbBlob = bytesRequired;
-		DBWrite(ofsNew,&dbcs,offsetof(struct DBContactSettings,blob));
-		if (ofsDbcsPrev == 0) {
-			dbc.ofsFirstSettings = ofsNew;
-			DBWrite(ofsContact,&dbc,sizeof(DBContact));
-		}
-		else {
-			dbcsPrev = (struct DBContactSettings*)DBRead(ofsDbcsPrev,sizeof(struct DBContactSettings),NULL);
-			dbcsPrev->ofsNext = ofsNew;
-			DBWrite(ofsDbcsPrev,dbcsPrev,offsetof(struct DBContactSettings,blob));
-		}
-		DeleteSpace(ofsSettingsGroup,oldSize+offsetof(struct DBContactSettings,blob));
-		ofsBlobPtr += ofsNew-ofsSettingsGroup;
-		ofsSettingsGroup = ofsNew;
-		pBlob = (PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining);
-	}
-	//we now have a place to put it and enough space: make it
-	DBWrite(ofsBlobPtr,&settingNameLen,1);
-	DBWrite(ofsBlobPtr+1,(PVOID)tmp.szSetting,settingNameLen);
-	MoveAlong(1+settingNameLen);
-	DBWrite(ofsBlobPtr,&tmp.value.type,1);
-	MoveAlong(1);
-	switch(tmp.value.type) {
-		case DBVT_BYTE: DBWrite(ofsBlobPtr,&tmp.value.bVal,1); MoveAlong(1); break;
-		case DBVT_WORD: DBWrite(ofsBlobPtr,&tmp.value.wVal,2); MoveAlong(2); break;
-		case DBVT_DWORD: DBWrite(ofsBlobPtr,&tmp.value.dVal,4); MoveAlong(4); break;
-		case DBVT_UTF8:
-		case DBVT_ASCIIZ:
-			{	int len = (int)strlen(tmp.value.pszVal);
-				DBWrite(ofsBlobPtr,&len,2);
-				DBWrite(ofsBlobPtr+2,tmp.value.pszVal,len);
-				MoveAlong(2+len);
-			}
-			break;
-		case DBVT_BLOB:
-			DBWrite(ofsBlobPtr,&tmp.value.cpbVal,2);
-			DBWrite(ofsBlobPtr+2,tmp.value.pbVal,tmp.value.cpbVal);
-			MoveAlong(2+tmp.value.cpbVal);
-			break;
-	}
-	{	BYTE zero = 0;
-		DBWrite(ofsBlobPtr,&zero,1);
-	}
-	//quit
-	DBFlush(1);
-	LeaveCriticalSection(&csDbAccess);
-	//notify
-	NotifyEventHooks(hSettingChangeEvent, (WPARAM)hContact, (LPARAM)&tmp);
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::DeleteContactSetting(HANDLE hContact, DBCONTACTGETSETTING *dbcgs)
-{
-	DBContact *dbc;
-	DWORD ofsModuleName,ofsSettingsGroup,ofsBlobPtr;
-	struct DBContactSettings dbcs;
-	PBYTE pBlob;
-	int settingNameLen = (int)strlen(dbcgs->szSetting),bytesRemaining;
-	char* szCachedSettingName;
-	HANDLE saveContact = hContact;
-
-	if ((!dbcgs->szModule) || (!dbcgs->szSetting))
-		return 1;
-
-	EnterCriticalSection(&csDbAccess);
-	ofsModuleName = GetModuleNameOfs(dbcgs->szModule);
- 	if (hContact == 0)
-		hContact = (HANDLE)dbHeader.ofsUser;
-
-	dbc = (DBContact*)DBRead(hContact,sizeof(DBContact),NULL);
-	if (dbc->signature!= DBCONTACT_SIGNATURE) {
-		LeaveCriticalSection(&csDbAccess);
-		return 1;
-	}
-	//make sure the module group exists
-	ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(dbc, (DWORD)hContact,ofsModuleName);
-	if (ofsSettingsGroup == 0) {
-		LeaveCriticalSection(&csDbAccess);
-		return 1;
-	}
-	dbc = (DBContact*)DBRead(hContact,sizeof(DBContact),NULL);
-	if (dbc->signature!= DBCONTACT_SIGNATURE) {
-		LeaveCriticalSection(&csDbAccess);
-		return 1;
-	}
-	ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(dbc,(DWORD)hContact,ofsModuleName);
-	if (ofsSettingsGroup == 0) {
-		LeaveCriticalSection(&csDbAccess);
-		return 1;
-	}
-	dbcs = *(struct DBContactSettings*)DBRead(ofsSettingsGroup,sizeof(struct DBContactSettings),NULL);
-	//find if the setting exists
-	ofsBlobPtr = ofsSettingsGroup+offsetof(struct DBContactSettings,blob);
-	pBlob = (PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining);
-	while(pBlob[0]) {
-		NeedBytes(settingNameLen+1);
-		if (pBlob[0] == settingNameLen && !memcmp(pBlob+1,dbcgs->szSetting,settingNameLen))
-			break;
-		NeedBytes(1);
-		MoveAlong(pBlob[0]+1);
-		NeedBytes(3);
-		MoveAlong(1+GetSettingValueLength(pBlob));
-		NeedBytes(1);
-	}
-	if (!pBlob[0]) {     //setting didn't exist
-		LeaveCriticalSection(&csDbAccess);
-		return 1;
-	}
-	{	//bin it
-		int nameLen,valLen;
-		DWORD ofsSettingToCut;
-		MoveAlong(1+settingNameLen);
-		NeedBytes(3);
-		nameLen = 1+settingNameLen;
-		valLen = 1+GetSettingValueLength(pBlob);
-		ofsSettingToCut = ofsBlobPtr-nameLen;
-		MoveAlong(valLen);
-		NeedBytes(1);
-		while(pBlob[0]) {
-			MoveAlong(pBlob[0]+1);
-			NeedBytes(3);
-			MoveAlong(1+GetSettingValueLength(pBlob));
-			NeedBytes(1);
-		}
-		DBMoveChunk(ofsSettingToCut,ofsSettingToCut+nameLen+valLen,ofsBlobPtr+1-ofsSettingToCut);
-	}
-
-	szCachedSettingName = GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,settingNameLen);
-	GetCachedValuePtr(saveContact, szCachedSettingName, -1 );
-
-	//quit
-	DBFlush(1);
-	LeaveCriticalSection(&csDbAccess);
-	{	//notify
-		DBCONTACTWRITESETTING dbcws;
-		dbcws.szModule = dbcgs->szModule;
-		dbcws.szSetting = dbcgs->szSetting;
-		dbcws.value.type = DBVT_DELETED;
-		NotifyEventHooks(hSettingChangeEvent,(WPARAM)saveContact,(LPARAM)&dbcws);
-	}
-	return 0;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::EnumContactSettings(HANDLE hContact, DBCONTACTENUMSETTINGS* dbces)
-{
-	DBContact dbc;
-	struct DBContactSettings dbcs;
-	DWORD ofsModuleName,ofsContact,ofsBlobPtr;
-	int bytesRemaining, result;
-	PBYTE pBlob;
-	char szSetting[256];
-
-	if (!dbces->szModule)
-		return -1;
-
-	EnterCriticalSection(&csDbAccess);
-
-	ofsModuleName = GetModuleNameOfs(dbces->szModule);
-	if (hContact == 0)
-		ofsContact = dbHeader.ofsUser;
-	else
-		ofsContact = (DWORD)hContact;
-	dbc = *(DBContact*)DBRead(ofsContact,sizeof(DBContact),NULL);
-	if (dbc.signature!= DBCONTACT_SIGNATURE) {
-		LeaveCriticalSection(&csDbAccess);
-		return -1;
-	}
-	dbces->ofsSettings = GetSettingsGroupOfsByModuleNameOfs(&dbc,ofsContact,ofsModuleName);
-	if (!dbces->ofsSettings) {
-		LeaveCriticalSection(&csDbAccess);
-		return -1;
-	}
-	dbcs = *(struct DBContactSettings*)DBRead(dbces->ofsSettings,sizeof(struct DBContactSettings),&bytesRemaining);
-	ofsBlobPtr = dbces->ofsSettings+offsetof(struct DBContactSettings,blob);
-	pBlob = (PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining);
-	if (pBlob[0] == 0) {
-		LeaveCriticalSection(&csDbAccess);
-		return -1;
-	}
-	result = 0;
-	while(pBlob[0]) {
-		NeedBytes(1);
-		NeedBytes(1+pBlob[0]);
-		CopyMemory(szSetting,pBlob+1,pBlob[0]); szSetting[pBlob[0]] = 0;
-		result = (dbces->pfnEnumProc)(szSetting,dbces->lParam);
-		MoveAlong(1+pBlob[0]);
-		NeedBytes(3);
-		MoveAlong(1+GetSettingValueLength(pBlob));
-		NeedBytes(1);
-	}
-	LeaveCriticalSection(&csDbAccess);
-	return result;
-}
-
-STDMETHODIMP_(BOOL) CDdxMmap::EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam)
-{
-	for(int i = 0; i < lSettings.realCount; i++) {
-		int ret = pFunc((char *)lSettings.items[i], 0, (LPARAM)pParam);
-		if (ret) return ret;
-	}
-	return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-//
-//   Module initialization procedure
-
-static int stringCompare( DBCachedSettingName* p1, DBCachedSettingName* p2 )
-{
-	return strcmp( p1->name, p2->name );
-}
-
-static int stringCompare2( DBCachedGlobalValue* p1, DBCachedGlobalValue* p2 )
-{
-	return strcmp( p1->name, p2->name );
-}
-
-int InitSettings(void)
-{
-	hSettingChangeEvent = CreateHookableEvent(ME_DB_CONTACT_SETTINGCHANGED);
-
-	mirCp = CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 );
-
-	hCacheHeap = HeapCreate(0, 0, 0);
-	lSettings.sortFunc = (FSortFunc)stringCompare;
-	lSettings.increment = 50;
-	lContacts.sortFunc = HandleKeySort;
-	lContacts.increment = 100;
-	lGlobalSettings.sortFunc = (FSortFunc)stringCompare2;
-	lGlobalSettings.increment = 100;
-	return 0;
-}
-
-void UninitSettings(void)
-{
-	HeapDestroy(hCacheHeap);
-	List_Destroy(&lContacts);
-	List_Destroy(&lSettings);
-	List_Destroy(&lGlobalSettings);
-}
diff --git a/plugins/Db3x/src/init.cpp b/plugins/Db3x/src/init.cpp
index ab0e6b4357..406db891a6 100644
--- a/plugins/Db3x/src/init.cpp
+++ b/plugins/Db3x/src/init.cpp
@@ -1,8 +1,8 @@
 /*
 
-Miranda IM: the free IM client for Microsoft* Windows*
+Miranda NG: the free IM client for Microsoft* Windows*
 
-Copyright 2000-2003 Miranda ICQ/IM project,
+Copyright 2012 Miranda NG project,
 all portions of this codebase are copyrighted to the people
 listed in contributors.txt.
 
@@ -25,135 +25,116 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 int hLangpack;
 
-HINSTANCE g_hInst = NULL;
-
-static PLUGININFOEX pluginInfo = {
+static PLUGININFOEX pluginInfo =
+{
 	sizeof(PLUGININFOEX),
-	"Miranda database driver",
+	"Miranda NG database driver",
 	__VERSION_DWORD,
 	"Provides Miranda database support: global settings, contacts, history, settings per contact.",
-	"Miranda-IM project",
-	"ghazan@miranda-im.org",
-	"Copyright 2000-2011 Miranda IM project",
+	"Miranda NG project",
+	"ghazan@miranda.im",
+	"Copyright 2012 Miranda NG project",
 	"",
 	UNICODE_AWARE,
     {0x1394a3ab, 0x2585, 0x4196, { 0x8f, 0x72, 0xe, 0xae, 0xc2, 0x45, 0xe, 0x11 }} //{1394A3AB-2585-4196-8F72-0EAEC2450E11}
 };
 
-CDdxMmap* g_Db = NULL;
+HINSTANCE g_hInst = NULL;
+
+LIST<CDb3x> g_Dbs(1, (LIST<CDb3x>::FTSortFunc)HandleKeySort);
 
 /////////////////////////////////////////////////////////////////////////////////////////
 
 // returns 0 if the profile is created, EMKPRF*
-static int makeDatabase(const TCHAR *profile, int * error)
+static int makeDatabase(const TCHAR *profile, int *error)
 {
-	HANDLE hFile = CreateFile(profile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
-	if ( hFile != INVALID_HANDLE_VALUE ) {
-		CreateDbHeaders(hFile);
-		CloseHandle(hFile);
+	CDb3x *tmp = new CDb3x(profile);
+	if (tmp->Create() == ERROR_SUCCESS) {
+		tmp->CreateDbHeaders();
+		delete tmp;
 		return 0;
 	}
-	if ( error != NULL ) *error = EMKPRF_CREATEFAILED;
+	delete tmp;
+	if (error != NULL) *error = EMKPRF_CREATEFAILED;
 	return 1;
 }
 
 // returns 0 if the given profile has a valid header
-static int grokHeader(const TCHAR *profile, int * error )
+static int grokHeader(const TCHAR *profile, int *error)
 {
-	int rc = 1;
-	int chk = 0;
-	struct DBHeader hdr;
-	HANDLE hFile = INVALID_HANDLE_VALUE;
-	DWORD dummy = 0;
-
-	hFile = CreateFile(profile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
-	if ( hFile == INVALID_HANDLE_VALUE ) {
-		if ( error != NULL ) *error = EGROKPRF_CANTREAD;
-		return 1;
-	}
-	// read the header, which can fail (for various reasons)
-	if ( !ReadFile(hFile, &hdr, sizeof(struct DBHeader), &dummy, NULL)) {
-		if ( error != NULL) *error = EGROKPRF_CANTREAD;
-		CloseHandle(hFile);
+	CDb3x *tmp = new CDb3x(profile);
+	if (tmp->Load(true) != ERROR_SUCCESS) {
+		delete tmp;
+		if (error != NULL) *error = EGROKPRF_CANTREAD;
 		return 1;
 	}
-	chk = CheckDbHeaders(&hdr);
+
+	int chk = tmp->CheckDbHeaders();
+	delete tmp;
 	if ( chk == 0 ) {
 		// all the internal tests passed, hurrah
-		rc = 0;
-		if ( error != NULL ) *error = 0;
-	} else {
-		// didn't pass at all, or some did.
-		switch ( chk ) {
-			case 1:
-			{
-				// "Miranda ICQ DB" wasn't present
-				if ( error != NULL ) *error = EGROKPRF_UNKHEADER;
-				break;
-			}
-			case 2:
-			{
-				// header was present, but version information newer
-				if ( error != NULL ) *error =  EGROKPRF_VERNEWER;
-				break;
-			}
-			case 3:
-			{
-				// header/version OK, internal data missing
-				if ( error != NULL ) *error = EGROKPRF_DAMAGED;
-				break;
-			}
-		} // switch
-	} //if
-	CloseHandle(hFile);
-	return rc;
+		if (error != NULL) *error = 0;
+		return 0;
+	}
+	
+	// didn't pass at all, or some did.
+	switch ( chk ) {
+	case 1:
+		// "Miranda ICQ DB" wasn't present
+		if (error != NULL) *error = EGROKPRF_UNKHEADER;
+		break;
+
+	case 2:
+		// header was present, but version information newer
+		if (error != NULL) *error =  EGROKPRF_VERNEWER;
+		break;
+
+	case 3:
+		// header/version OK, internal data missing
+		if (error != NULL) *error = EGROKPRF_DAMAGED;
+		break;
+	}
+
+	return 1;
 }
 
 // returns 0 if all the APIs are injected otherwise, 1
 static MIDatabase* LoadDatabase(const TCHAR *profile)
 {
-	if (g_Db) delete g_Db;
-	g_Db = new CDdxMmap(profile);
-
-	// don't need thread notifications
-	_tcsncpy(szDbPath, profile, SIZEOF(szDbPath));
+	// set the memory, lists & UTF8 manager
+	mir_getLP( &pluginInfo );
 
-	mir_getLP(&pluginInfo);
-
-	// inject all APIs and hooks into the core
-	LoadDatabaseModule();
+	CDb3x* db = new CDb3x(profile);
+	if (db->Load(false) != ERROR_SUCCESS) {
+		delete db;
+		return NULL;
+	}
 
-	return g_Db;
+	g_Dbs.insert(db);
+	return db;
 }
 
 static int UnloadDatabase(MIDatabase* db)
 {
-	UnloadDatabaseModule();
+	g_Dbs.remove((CDb3x*)db);
+	delete (CDb3x*)db;
 	return 0;
 }
 
-static DATABASELINK dblink = {
+static DATABASELINK dblink =
+{
 	sizeof(DATABASELINK),
 	"db3x driver",
 	_T("db3x database support"),
 	makeDatabase,
 	grokHeader,
 	LoadDatabase,
-	UnloadDatabase,
+	UnloadDatabase
 };
 
-BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved)
-{
-	g_hInst = hInstDLL;
-	return TRUE;
-}
-
-extern "C" __declspec(dllexport) DATABASELINK* DatabasePluginInfo(void * reserved)
-{
-	return &dblink;
-}
+/////////////////////////////////////////////////////////////////////////////////////////
 
-extern "C" __declspec(dllexport) PLUGININFOEX * MirandaPluginInfoEx(DWORD mirandaVersion)
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
 {
 	return &pluginInfo;
 }
@@ -168,5 +149,12 @@ extern "C" __declspec(dllexport) int Load(void)
 
 extern "C" __declspec(dllexport) int Unload(void)
 {
+	g_Dbs.destroy();
 	return 0;
 }
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved)
+{
+	g_hInst = hInstDLL;
+	return TRUE;
+}
-- 
cgit v1.2.3