Example #1
0
void Map()
{
	hMap = CreateFileMapping(hDbFile, NULL, PAGE_READWRITE, 0, dwFileSize, NULL);

	if (hMap)
		pDbCache = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS/*FILE_MAP_WRITE*/, 0, 0 ,0);
	else
		DatabaseCorruption( _T("%s (CreateFileMapping failed. Code: %d)"));

	if (!pDbCache)
		DatabaseCorruption( _T("%s (MapViewOfFile failed. Code: %d)"));
}
Example #2
0
void CDbxKV::AddToList(char *name, DWORD ofs)
{
	ModuleName *mn = (ModuleName*)HeapAlloc(m_hModHeap, 0, sizeof(ModuleName));
	mn->name = name;
	mn->ofs = ofs;

	if (m_lMods.getIndex(mn) != -1)
		DatabaseCorruption(_T("%s (Module Name not unique)"));
	m_lMods.insert(mn);

	if (m_lOfs.getIndex(mn) != -1)
		DatabaseCorruption(_T("%s (Module Offset not unique)"));
	m_lOfs.insert(mn);
}
Example #3
0
void ReMap(DWORD needed)
{
	KillTimer(NULL,flushBuffersTimerId);

	log3("remapping %d + %d (file end: %d)",dwFileSize,needed,dbHeader.ofsFileEnd);

	if (needed > ChunkSize)
	{
		if ((needed + dwFileSize) - dbHeader.ofsFileEnd > ChunkSize)
			DatabaseCorruption( _T("%s (Too large increment)"));
		else
		{
			DWORD x = dbHeader.ofsFileEnd/ChunkSize;
			dwFileSize = (x+1)*ChunkSize;
		}
	}
	else
		dwFileSize += ChunkSize;

//	FlushViewOfFile(pDbCache, 0);
	UnmapViewOfFile(pDbCache);
	pDbCache = NULL;
	CloseHandle(hMap);

	Map();
}
Example #4
0
//this function caches results
static DWORD GetSettingsGroupOfsByModuleNameOfs(struct 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;
}
//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);
            }
        }
    }
}
Example #6
0
int InitModuleNames(void)
{
	struct DBModuleName *dbmn;
	DWORD ofsThis;
	int nameLen;
	char *mod;

	hModHeap=HeapCreate(0,0,0);
	lMods.sortFunc=ModCompare;
	lMods.increment=50;
	lOfs.sortFunc=OfsCompare;
	lOfs.increment=50;

	ofsThis=dbHeader.ofsFirstModuleName;
	dbmn=(struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL);
	while(ofsThis) {
		if(dbmn->signature!=DBMODULENAME_SIGNATURE) DatabaseCorruption(NULL);

		nameLen=dbmn->cbName;

		mod = (char*)HeapAlloc(hModHeap,0,nameLen+1);
		CopyMemory(mod,DBRead(ofsThis+offsetof(struct DBModuleName,name),nameLen,NULL),nameLen);
		mod[nameLen] = 0;

		AddToList(mod, nameLen, ofsThis);

		ofsThis=dbmn->ofsNext;
		dbmn=(struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL);
	}
	CreateServiceFunction(MS_DB_MODULES_ENUM,EnumModuleNames);
	return 0;
}
Example #7
0
int CDbxKV::InitModuleNames(void)
{
	m_maxModuleID = 0;

	ham_key_t key = { 0 };
	ham_record_t rec = { 0 };
	cursor_ptr cursor(m_dbModules);
	if (ham_cursor_move(cursor, &key, &rec, HAM_CURSOR_FIRST) != HAM_SUCCESS)
		return 0;

	do {
		DBModuleName *pmod = (DBModuleName*)rec.data;
		if (pmod->dwSignature != DBMODULENAME_SIGNATURE)
			DatabaseCorruption(NULL);

		char *pVal = (char*)HeapAlloc(m_hModHeap, 0, pmod->cbName+1);
		memcpy(pVal, pmod->name, pmod->cbName);
		pVal[pmod->cbName] = 0;

		int moduleId = *(int*)key.data;
		AddToList(pVal, moduleId);

		if (moduleId > m_maxModuleID)
			m_maxModuleID = moduleId;
	} while (ham_cursor_move(cursor, &key, &rec, HAM_CURSOR_NEXT) == 0);

	return 0;
}
Example #8
0
int CDbxMdb::Load(bool bSkipInit)
{
	if (!Remap())
		return EGROKPRF_CANTREAD;

	if (!bSkipInit) {
		txn_ptr trnlck(m_pMdbEnv);
		mdb_open(trnlck, "global", MDB_CREATE | MDB_INTEGERKEY, &m_dbGlobal);
		mdb_open(trnlck, "contacts", MDB_CREATE | MDB_INTEGERKEY, &m_dbContacts);
		mdb_open(trnlck, "modules", MDB_CREATE | MDB_INTEGERKEY, &m_dbModules);
		mdb_open(trnlck, "events", MDB_CREATE | MDB_INTEGERKEY, &m_dbEvents);
		mdb_open(trnlck, "eventsrt", MDB_CREATE | MDB_INTEGERKEY, &m_dbEventsSort);
		mdb_open(trnlck, "settings", MDB_CREATE, &m_dbSettings);

		DWORD keyVal = 1;
		MDB_val key = { sizeof(DWORD), &keyVal }, data;
		if (mdb_get(trnlck, m_dbGlobal, &key, &data) == MDB_SUCCESS) {
			DBHeader *hdr = (DBHeader*)data.mv_data;
			if (hdr->dwSignature != DBHEADER_SIGNATURE)
				DatabaseCorruption(NULL);

			memcpy(&m_header, data.mv_data, sizeof(m_header));
		}
		else {
			m_header.dwSignature = DBHEADER_SIGNATURE;
			m_header.dwVersion = 1;
			data.mv_data = &m_header; data.mv_size = sizeof(m_header);
			mdb_put(trnlck, m_dbGlobal, &key, &data, 0);

			keyVal = 0;
			DBContact dbc = { DBCONTACT_SIGNATURE, 0, 0, 0 };
			data.mv_data = &dbc; data.mv_size = sizeof(dbc);
			mdb_put(trnlck, m_dbContacts, &key, &data, 0);
		}
		trnlck.commit();

		if (InitModuleNames()) return EGROKPRF_CANTREAD;
		if (InitCrypt())       return EGROKPRF_CANTREAD;

		// everything is ok, go on
		if (!m_bReadOnly) {
			// we don't need events in the service mode
			if (ServiceExists(MS_DB_SETSAFETYMODE)) {
				hContactDeletedEvent = CreateHookableEvent(ME_DB_CONTACT_DELETED);
				hContactAddedEvent = CreateHookableEvent(ME_DB_CONTACT_ADDED);
				hSettingChangeEvent = CreateHookableEvent(ME_DB_CONTACT_SETTINGCHANGED);
				hEventMarkedRead = CreateHookableEvent(ME_DB_EVENT_MARKED_READ);

				hEventAddedEvent = CreateHookableEvent(ME_DB_EVENT_ADDED);
				hEventDeletedEvent = CreateHookableEvent(ME_DB_EVENT_DELETED);
				hEventFilterAddedEvent = CreateHookableEvent(ME_DB_EVENT_FILTER_ADD);
			}
		}

		FillContacts();
	}

	return ERROR_SUCCESS;
}
Example #9
0
void AddToList(char *name, DWORD len, DWORD ofs)
{
	int index;
	ModuleName *mn = (ModuleName*)HeapAlloc(hModHeap,0,sizeof(ModuleName));
	mn->name = name;
	mn->ofs = ofs;

	if (li.List_GetIndex(&lMods,mn,&index))
		DatabaseCorruption( _T("%s (Module Name not unique)"));

	li.List_Insert(&lMods,mn,index);

	if (li.List_GetIndex(&lOfs,mn,&index))
		DatabaseCorruption( _T("%s (Module Offset not unique)"));

	li.List_Insert(&lOfs,mn,index);
}
Example #10
0
static VOID CALLBACK DoBufferFlushTimerProc(HWND hwnd,UINT message,UINT idEvent,DWORD dwTime)
{
    if (!pDbCache) return;

	KillTimer(NULL,flushBuffersTimerId);
	log0("tflush1");
	if (FlushViewOfFile(pDbCache, 0) == 0)
		DatabaseCorruption(NULL);
	log0("tflush2");
}
Example #11
0
void DBFlush(int setting)
{
	if(!setting) {
		log0("nflush1");
		if(safetyMode && pDbCache) {
			if (FlushViewOfFile(pDbCache, 0) == 0)
				DatabaseCorruption(NULL);
		}
		log0("nflush2");
		return;
	}
	KillTimer(NULL,flushBuffersTimerId);
	flushBuffersTimerId=SetTimer(NULL,flushBuffersTimerId,50,DoBufferFlushTimerProc);
}
Example #12
0
static DWORD GetSettingsGroupOfsByModuleNameOfs(struct DBContact *dbc,DWORD ofsModuleName)
{
	struct DBContactSettings *dbcs;
	DWORD ofsThis;

	ofsThis=dbc->ofsFirstSettings;
	while(ofsThis) {
		dbcs=(struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL);
		if(dbcs->signature!=DBCONTACTSETTINGS_SIGNATURE) DatabaseCorruption(NULL);
		if(dbcs->ofsModuleName==ofsModuleName)
			return ofsThis;

		ofsThis=dbcs->ofsNext;
	}
	return 0;
}
Example #13
0
char* CDb3Mmap::GetModuleNameByOfs(DWORD ofs)
{
	if (m_lastmn && m_lastmn->ofs == ofs)
		return m_lastmn->name;

	ModuleName mn = {NULL, ofs};
	int index = m_lOfs.getIndex(&mn);
	if (index != -1) {
		ModuleName *pmn = m_lOfs[index];
		m_lastmn = pmn;
		return pmn->name;
	}

	DatabaseCorruption(NULL);
	return NULL;
}
Example #14
0
static VOID CALLBACK DoBufferFlushTimerProc(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime)
{
    if (!pDbCache) return;

	KillTimer(NULL,flushBuffersTimerId);
	log0("tflush1");
	if (FlushViewOfFile(pDbCache, 0) == 0) {
		if (flushFailTick == 0)
			flushFailTick = GetTickCount();
		else if (GetTickCount() - flushFailTick > 5000) 
			DatabaseCorruption(NULL);
	}
	else
		flushFailTick = 0;
	log0("tflush2");
}
Example #15
0
void DBFlush(int setting)
{
	if(!setting) {
		log0("nflush1");
		if(safetyMode && pDbCache) {
			if (FlushViewOfFile(pDbCache, 0) == 0) {
				if (flushFailTick == 0)
					flushFailTick = GetTickCount();
				else if (GetTickCount() - flushFailTick > 5000) 
					DatabaseCorruption(NULL);
			}
			else
				flushFailTick = 0;
		}
		log0("nflush2");
		return;
	}
	KillTimer(NULL,flushBuffersTimerId);
	flushBuffersTimerId=SetTimer(NULL,flushBuffersTimerId,50,DoBufferFlushTimerProc);
}
Example #16
0
int CDb3Mmap::InitModuleNames(void)
{
	DWORD ofsThis = m_dbHeader.ofsModuleNames;
	DBModuleName *dbmn = (struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL);
	while (ofsThis) {
		if (dbmn->signature != DBMODULENAME_SIGNATURE)
			DatabaseCorruption(NULL);

		int nameLen = dbmn->cbName;

		char *mod = (char*)HeapAlloc(m_hModHeap,0,nameLen+1);
		CopyMemory(mod,DBRead(ofsThis + offsetof(struct DBModuleName,name),nameLen,NULL),nameLen);
		mod[nameLen] = 0;

		AddToList(mod, nameLen, ofsThis);

		ofsThis = dbmn->ofsNext;
		dbmn = (struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL);
	}
	return 0;
}
Example #17
0
char *GetModuleNameByOfs(DWORD ofs)
{
	static ModuleName *lastmn = NULL;
	ModuleName mn, *pmn;
	int index;

	if (lastmn && lastmn->ofs == ofs)
		return lastmn->name;

	mn.name = NULL;
	mn.ofs = ofs;

	if (li.List_GetIndex(&lOfs,&mn,&index)) {
		pmn = (ModuleName*)lOfs.items[index];
		lastmn = pmn;
		return pmn->name;
	}

	DatabaseCorruption(NULL);
	return NULL;
}
Example #18
0
void CDbxKV::FillContacts()
{
	m_contactCount = 0;

	ham_key_t key = { 0 };
	ham_record_t rec = { 0 };
	cursor_ptr cursor(m_dbContacts);
	if (ham_cursor_move(cursor, &key, &rec, HAM_CURSOR_FIRST) != HAM_SUCCESS) // empty table?
		return;

	do {
		DBContact *dbc = (DBContact*)rec.data;
		if (dbc->dwSignature != DBCONTACT_SIGNATURE)
			DatabaseCorruption(NULL);

		DBCachedContact *cc = m_cache->AddContactToCache(*(DWORD*)key.data);
		cc->dbc.dwSignature = DBCONTACT_SIGNATURE;
		cc->dbc.dwEventCount = dbc->dwEventCount;
		cc->dbc.dwFirstUnread = dbc->dwFirstUnread;
		cc->dbc.tsFirstUnread = dbc->tsFirstUnread;

		CheckProto(cc, "");

		m_dwMaxContactId = cc->contactID+1;
		m_contactCount++;

		DBVARIANT dbv; dbv.type = DBVT_DWORD;
		cc->nSubs = (0 != GetContactSetting(cc->contactID, META_PROTO, "NumContacts", &dbv)) ? -1 : dbv.dVal;
		if (cc->nSubs != -1) {
			cc->pSubs = (MCONTACT*)mir_alloc(cc->nSubs*sizeof(MCONTACT));
			for (int i = 0; i < cc->nSubs; i++) {
				char setting[100];
				mir_snprintf(setting, SIZEOF(setting), "Handle%d", i);
				cc->pSubs[i] = (0 != GetContactSetting(cc->contactID, META_PROTO, setting, &dbv)) ? NULL : dbv.dVal;
			}
		}
		cc->nDefault = (0 != GetContactSetting(cc->contactID, META_PROTO, "Default", &dbv)) ? -1 : dbv.dVal;
		cc->parentID = (0 != GetContactSetting(cc->contactID, META_PROTO, "ParentMeta", &dbv)) ? NULL : dbv.dVal;
	} while (ham_cursor_move(cursor, &key, &rec, HAM_CURSOR_NEXT) == HAM_SUCCESS);
}
Example #19
0
void CDbxKyoto::FillContacts()
{
	m_contactCount = 0;

	size_t size;
	cursor_ptr cursor(m_dbContacts);
	for (cursor->jump(); cursor->step();) {
		const char *pRec, *pKey = cursor->get(&size, &pRec, &size);
		DBContact *dbc = (DBContact*)pRec;
		if (dbc->dwSignature != DBCONTACT_SIGNATURE)
			DatabaseCorruption(NULL);

		DBCachedContact *cc = m_cache->AddContactToCache(*(DWORD*)pKey);
		cc->dbc.dwSignature = DBCONTACT_SIGNATURE;
		cc->dbc.dwEventCount = dbc->dwEventCount;
		cc->dbc.dwFirstUnread = dbc->dwFirstUnread;
		cc->dbc.tsFirstUnread = dbc->tsFirstUnread;

		CheckProto(cc, "");

		m_dwMaxContactId = cc->contactID+1;
		m_contactCount++;

		DBVARIANT dbv; dbv.type = DBVT_DWORD;
		cc->nSubs = (0 != GetContactSetting(cc->contactID, META_PROTO, "NumContacts", &dbv)) ? -1 : dbv.dVal;
		if (cc->nSubs != -1) {
			cc->pSubs = (MCONTACT*)mir_alloc(cc->nSubs*sizeof(MCONTACT));
			for (int i = 0; i < cc->nSubs; i++) {
				char setting[100];
				mir_snprintf(setting, SIZEOF(setting), "Handle%d", i);
				cc->pSubs[i] = (0 != GetContactSetting(cc->contactID, META_PROTO, setting, &dbv)) ? NULL : dbv.dVal;
			}
		}
		cc->nDefault = (0 != GetContactSetting(cc->contactID, META_PROTO, "Default", &dbv)) ? -1 : dbv.dVal;
		cc->parentID = (0 != GetContactSetting(cc->contactID, META_PROTO, "ParentMeta", &dbv)) ? NULL : dbv.dVal;

		delete[] pKey;
	}
}
Example #20
0
STDMETHODIMP_(LONG) CDb3Mmap::DeleteContact(MCONTACT contactID)
{
	if (contactID == 0) // global contact cannot be removed
		return 1;

	mir_cslockfull lck(m_csDbAccess);
	DWORD ofsContact = GetContactOffset(contactID);

	DBContact *dbc = (DBContact*)DBRead(ofsContact, NULL);
	if (dbc->signature != DBCONTACT_SIGNATURE)
		return 1;

	if (ofsContact == m_dbHeader.ofsUser) {
		log0("FATAL: del of user chain attempted.");
		return 1;
	}

	lck.unlock();
	log0("del contact");

	// call notifier while outside mutex
	NotifyEventHooks(hContactDeletedEvent, contactID, 0);

	// get back in
	lck.lock();

	// delete settings chain
	DWORD ofsThis = dbc->ofsFirstSettings;
	DWORD ofsFirstEvent = dbc->ofsFirstEvent;
	while (ofsThis) {
		DBContactSettings *dbcs = (DBContactSettings*)DBRead(ofsThis, NULL);
		DWORD ofsNext = dbcs->ofsNext;
		DeleteSpace(ofsThis, offsetof(DBContactSettings, blob) + dbcs->cbBlob);
		ofsThis = ofsNext;
	}

	// delete event chain
	ofsThis = ofsFirstEvent;
	while (ofsThis) {
		DBEvent *dbe = (DBEvent*)DBRead(ofsThis, NULL);
		DWORD ofsNext = dbe->ofsNext;
		DeleteSpace(ofsThis, offsetof(DBEvent, blob) + dbe->cbBlob);
		ofsThis = ofsNext;
	}

	// find previous contact in chain and change ofsNext
	if (m_dbHeader.ofsFirstContact == ofsContact) {
		m_dbHeader.ofsFirstContact = dbc->ofsNext;
		DBWrite(0, &m_dbHeader, sizeof(m_dbHeader));
	}
	else {
		DWORD ofsNext = dbc->ofsNext;
		ofsThis = m_dbHeader.ofsFirstContact;
		DBContact *dbcPrev = (DBContact*)DBRead(ofsThis, NULL);
		while (dbcPrev->ofsNext != ofsContact) {
			if (dbcPrev->ofsNext == 0) DatabaseCorruption(NULL);
			ofsThis = dbcPrev->ofsNext;
			dbcPrev = (DBContact*)DBRead(ofsThis, NULL);
		}
		dbcPrev->ofsNext = ofsNext;
		DBWrite(ofsThis, dbcPrev, sizeof(DBContact));
	}

	// delete contact
	DeleteSpace(ofsContact, sizeof(DBContact));

	// decrement contact count
	m_dbHeader.contactCount--;
	DBWrite(0, &m_dbHeader, sizeof(m_dbHeader));
	DBFlush(0);

	// free cache item
	m_cache->FreeCachedContact(contactID);
	if (contactID == m_hLastCachedContact)
		m_hLastCachedContact = NULL;
	return 0;
}
Example #21
0
STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws)
{
	if (dbcws == NULL || dbcws->szSetting == NULL || dbcws->szModule == NULL || m_bReadOnly)
		return 1;

	// the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name
	int settingNameLen = (int)mir_strlen(dbcws->szSetting);
	int moduleNameLen = (int)mir_strlen(dbcws->szModule);
	if (settingNameLen > 0xFE) {
#ifdef _DEBUG
		OutputDebugStringA("WriteContactSetting() got a > 255 setting name length. \n");
#endif
		return 1;
	}
	if (moduleNameLen > 0xFE) {
#ifdef _DEBUG
		OutputDebugStringA("WriteContactSetting() got a > 255 module name length. \n");
#endif
		return 1;
	}

	// used for notifications
	DBCONTACTWRITESETTING dbcwNotif = *dbcws;
	if (dbcwNotif.value.type == DBVT_WCHAR) {
		if (dbcwNotif.value.pszVal != NULL) {
			char* val = mir_utf8encodeW(dbcwNotif.value.pwszVal);
			if (val == NULL)
				return 1;

			dbcwNotif.value.pszVal = (char*)alloca(mir_strlen(val) + 1);
			mir_strcpy(dbcwNotif.value.pszVal, val);
			mir_free(val);
			dbcwNotif.value.type = DBVT_UTF8;
		}
		else return 1;
	}

	if (dbcwNotif.szModule == NULL || dbcwNotif.szSetting == NULL)
		return 1;

	DBCONTACTWRITESETTING dbcwWork = dbcwNotif;

	mir_ptr<BYTE> pEncoded(NULL);
	bool bIsEncrypted = false;
	switch (dbcwWork.value.type) {
	case DBVT_BYTE: case DBVT_WORD: case DBVT_DWORD:
		break;

	case DBVT_ASCIIZ: case DBVT_UTF8:
		bIsEncrypted = m_bEncrypted || IsSettingEncrypted(dbcws->szModule, dbcws->szSetting);
	LBL_WriteString:
		if (dbcwWork.value.pszVal == NULL)
			return 1;
		dbcwWork.value.cchVal = (WORD)mir_strlen(dbcwWork.value.pszVal);
		if (bIsEncrypted) {
			size_t len;
			BYTE *pResult = m_crypto->encodeString(dbcwWork.value.pszVal, &len);
			if (pResult != NULL) {
				pEncoded = dbcwWork.value.pbVal = pResult;
				dbcwWork.value.cpbVal = (WORD)len;
				dbcwWork.value.type = DBVT_ENCRYPTED;
			}
		}
		break;

	case DBVT_UNENCRYPTED:
		dbcwNotif.value.type = dbcwWork.value.type = DBVT_UTF8;
		goto LBL_WriteString;

	case DBVT_BLOB: case DBVT_ENCRYPTED:
		if (dbcwWork.value.pbVal == NULL)
			return 1;
		break;
	default:
		return 1;
	}

	mir_cslockfull lck(m_csDbAccess);

	DWORD ofsBlobPtr, ofsContact = GetContactOffset(contactID);
	if (ofsContact == 0) {
		_ASSERT(false); // contact doesn't exist?
		return 2;
	}

	char *szCachedSettingName = m_cache->GetCachedSetting(dbcwWork.szModule, dbcwWork.szSetting, moduleNameLen, settingNameLen);
	log3("set [%08p] %s (%p)", hContact, szCachedSettingName, szCachedSettingName);

	// we don't cache blobs and passwords
	if (dbcwWork.value.type != DBVT_BLOB && dbcwWork.value.type != DBVT_ENCRYPTED && !bIsEncrypted) {
		DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1);
		if (pCachedValue != NULL) {
			bool bIsIdentical = false;
			if (pCachedValue->type == dbcwWork.value.type) {
				switch (dbcwWork.value.type) {
				case DBVT_BYTE:   bIsIdentical = pCachedValue->bVal == dbcwWork.value.bVal;  break;
				case DBVT_WORD:   bIsIdentical = pCachedValue->wVal == dbcwWork.value.wVal;  break;
				case DBVT_DWORD:  bIsIdentical = pCachedValue->dVal == dbcwWork.value.dVal;  break;
				case DBVT_UTF8:
				case DBVT_ASCIIZ: bIsIdentical = mir_strcmp(pCachedValue->pszVal, dbcwWork.value.pszVal) == 0; break;
				}
				if (bIsIdentical)
					return 0;
			}
			m_cache->SetCachedVariant(&dbcwWork.value, pCachedValue);
		}
		if (szCachedSettingName[-1] != 0) {
			lck.unlock();
			log2(" set resident as %s (%p)", printVariant(&dbcwWork.value), pCachedValue);
			NotifyEventHooks(hSettingChangeEvent, contactID, (LPARAM)&dbcwWork);
			return 0;
		}
	}
	else m_cache->GetCachedValuePtr(contactID, szCachedSettingName, -1);

	log1(" write database as %s", printVariant(&dbcwWork.value));

	DWORD ofsModuleName = GetModuleNameOfs(dbcwWork.szModule);
	DBContact dbc = *(DBContact*)DBRead(ofsContact, NULL);
	if (dbc.signature != DBCONTACT_SIGNATURE)
		return 1;

	// make sure the module group exists
	PBYTE pBlob;
	int bytesRequired, bytesRemaining;
	DBContactSettings dbcs;
	DWORD ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc, ofsModuleName);
	if (ofsSettingsGroup == 0) {  //module group didn't exist - make it
		switch (dbcwWork.value.type) {
		case DBVT_ASCIIZ: case DBVT_UTF8:
			bytesRequired = dbcwWork.value.cchVal + 2;
			break;
		case DBVT_BLOB: case DBVT_ENCRYPTED:
			bytesRequired = dbcwWork.value.cpbVal + 2;
			break;
		default:
			bytesRequired = dbcwWork.value.type;
		}
		bytesRequired += 2 + settingNameLen;
		bytesRequired += (DB_SETTINGS_RESIZE_GRANULARITY - (bytesRequired % DB_SETTINGS_RESIZE_GRANULARITY)) % DB_SETTINGS_RESIZE_GRANULARITY;
		ofsSettingsGroup = CreateNewSpace(bytesRequired + offsetof(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(DBContactSettings));
		ofsBlobPtr = ofsSettingsGroup + offsetof(DBContactSettings, blob);
		pBlob = (PBYTE)DBRead(ofsBlobPtr, &bytesRemaining);
	}
	else {
		dbcs = *(DBContactSettings*)DBRead(ofsSettingsGroup, &bytesRemaining);

		// find if the setting exists
		ofsBlobPtr = ofsSettingsGroup + offsetof(DBContactSettings, blob);
		pBlob = (PBYTE)DBRead(ofsBlobPtr, &bytesRemaining);
		while (pBlob[0]) {
			NeedBytes(settingNameLen + 1);
			if (pBlob[0] == settingNameLen && !memcmp(pBlob + 1, dbcwWork.szSetting, settingNameLen))
				break;
			NeedBytes(1);
			MoveAlong(pBlob[0] + 1);
			NeedBytes(3);
			MoveAlong(1 + GetSettingValueLength(pBlob));
			NeedBytes(1);
		}

		// setting already existed, and up to end of name is in cache
		if (pBlob[0]) {
			MoveAlong(1 + settingNameLen);
			// if different type or variable length and length is different
			NeedBytes(3);
			if (pBlob[0] != dbcwWork.value.type ||
				((pBlob[0] == DBVT_ASCIIZ || pBlob[0] == DBVT_UTF8) && *(PWORD)(pBlob + 1) != dbcwWork.value.cchVal) ||
				((pBlob[0] == DBVT_BLOB || pBlob[0] == DBVT_ENCRYPTED) && *(PWORD)(pBlob + 1) != dbcwWork.value.cpbVal))
			{
				// bin it
				NeedBytes(3);
				int nameLen = 1 + settingNameLen;
				int valLen = 1 + GetSettingValueLength(pBlob);
				DWORD 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, &bytesRemaining);
			}
			else {
				// replace existing setting at pBlob
				MoveAlong(1);	// skip data type
				switch (dbcwWork.value.type) {
				case DBVT_BYTE:  DBWrite(ofsBlobPtr, &dbcwWork.value.bVal, 1); break;
				case DBVT_WORD:  DBWrite(ofsBlobPtr, &dbcwWork.value.wVal, 2); break;
				case DBVT_DWORD: DBWrite(ofsBlobPtr, &dbcwWork.value.dVal, 4); break;
				case DBVT_BLOB:
					DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal);
					break;
				case DBVT_ENCRYPTED:
					DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal);
					break;
				case DBVT_UTF8:
				case DBVT_ASCIIZ:
					DBWrite(ofsBlobPtr + 2, dbcwWork.value.pszVal, dbcwWork.value.cchVal);
					break;
				}
				// quit
				DBFlush(1);
				lck.unlock();
				// notify
				NotifyEventHooks(hSettingChangeEvent, contactID, (LPARAM)&dbcwNotif);
				return 0;
			}
		}
	}

	// cannot do a simple replace, add setting to end of list
	// pBlob already points to end of list
	// see if it fits
	switch (dbcwWork.value.type) {
	case DBVT_ASCIIZ: case DBVT_UTF8:
		bytesRequired = dbcwWork.value.cchVal + 2;
		break;
	case DBVT_BLOB: case DBVT_ENCRYPTED:
		bytesRequired = dbcwWork.value.cpbVal + 2;
		break;
	default:
		bytesRequired = dbcwWork.value.type;
	}

	bytesRequired += 2 + settingNameLen;
	bytesRequired += ofsBlobPtr + 1 - (ofsSettingsGroup + offsetof(DBContactSettings, blob));

	if ((DWORD)bytesRequired > dbcs.cbBlob) {
		// doesn't fit: move entire group
		DBContactSettings *dbcsPrev;
		DWORD ofsDbcsPrev, 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 = (DBContactSettings*)DBRead(ofsDbcsPrev, NULL);
			while (dbcsPrev->ofsNext != ofsSettingsGroup) {
				if (dbcsPrev->ofsNext == 0) DatabaseCorruption(NULL);
				ofsDbcsPrev = dbcsPrev->ofsNext;
				dbcsPrev = (DBContactSettings*)DBRead(ofsDbcsPrev, NULL);
			}
		}

		// create the new one
		ofsNew = ReallocSpace(ofsSettingsGroup, dbcs.cbBlob + offsetof(DBContactSettings, blob), bytesRequired + offsetof(DBContactSettings, blob));

		dbcs.cbBlob = bytesRequired;

		DBWrite(ofsNew, &dbcs, offsetof(DBContactSettings, blob));
		if (ofsDbcsPrev == 0) {
			dbc.ofsFirstSettings = ofsNew;
			DBWrite(ofsContact, &dbc, sizeof(DBContact));
		}
		else {
			dbcsPrev = (DBContactSettings*)DBRead(ofsDbcsPrev, NULL);
			dbcsPrev->ofsNext = ofsNew;
			DBWrite(ofsDbcsPrev, dbcsPrev, offsetof(DBContactSettings, blob));
		}
		ofsBlobPtr += ofsNew - ofsSettingsGroup;
		ofsSettingsGroup = ofsNew;
		pBlob = (PBYTE)DBRead(ofsBlobPtr, &bytesRemaining);
	}

	// we now have a place to put it and enough space: make it
	DBWrite(ofsBlobPtr, &settingNameLen, 1);
	DBWrite(ofsBlobPtr + 1, (PVOID)dbcwWork.szSetting, settingNameLen);
	MoveAlong(1 + settingNameLen);
	DBWrite(ofsBlobPtr, &dbcwWork.value.type, 1);
	MoveAlong(1);
	switch (dbcwWork.value.type) {
	case DBVT_BYTE: DBWrite(ofsBlobPtr, &dbcwWork.value.bVal, 1); MoveAlong(1); break;
	case DBVT_WORD: DBWrite(ofsBlobPtr, &dbcwWork.value.wVal, 2); MoveAlong(2); break;
	case DBVT_DWORD: DBWrite(ofsBlobPtr, &dbcwWork.value.dVal, 4); MoveAlong(4); break;

	case DBVT_BLOB:
		DBWrite(ofsBlobPtr, &dbcwWork.value.cpbVal, 2);
		DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal);
		MoveAlong(2 + dbcwWork.value.cpbVal);
		break;

	case DBVT_ENCRYPTED:
		DBWrite(ofsBlobPtr, &dbcwWork.value.cpbVal, 2);
		DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal);
		MoveAlong(2 + dbcwWork.value.cpbVal);
		break;

	case DBVT_UTF8: case DBVT_ASCIIZ:
		DBWrite(ofsBlobPtr, &dbcwWork.value.cchVal, 2);
		DBWrite(ofsBlobPtr + 2, dbcwWork.value.pszVal, dbcwWork.value.cchVal);
		MoveAlong(2 + dbcwWork.value.cchVal);
		break;
	}

	BYTE zero = 0;
	DBWrite(ofsBlobPtr, &zero, 1);

	// quit
	DBFlush(1);
	lck.unlock();

	// notify
	NotifyEventHooks(hSettingChangeEvent, contactID, (LPARAM)&dbcwNotif);
	return 0;
}
Example #22
0
static INT_PTR DeleteContact(WPARAM wParam,LPARAM lParam)
{
	struct DBContact *dbc,*dbcPrev;
	DWORD ofsThis,ofsNext,ofsFirstEvent;
	struct DBContactSettings *dbcs;
	struct DBEvent *dbe;
	int index;

	if((HANDLE)wParam==NULL) return 1;
	EnterCriticalSection(&csDbAccess);
	dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL);
	if(dbc->signature!=DBCONTACT_SIGNATURE) {
		LeaveCriticalSection(&csDbAccess);
		return 1;
	}
	if ( (HANDLE)wParam == (HANDLE)dbHeader.ofsUser ) {
		LeaveCriticalSection(&csDbAccess);
		log0("FATAL: del of user chain attempted.");
		return 1;
	}
	log0("del contact");
	LeaveCriticalSection(&csDbAccess);
	//call notifier while outside mutex
	NotifyEventHooks(hContactDeletedEvent,wParam,0);
	//get back in
	EnterCriticalSection(&csDbAccess);

	{	DBCachedContactValueList VLtemp;
		VLtemp.hContact = (HANDLE)wParam;
		if ( li.List_GetIndex(&lContacts,&VLtemp,&index))
		{
			DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index];
			DBCachedContactValue* V = VL->first;
			while ( V != NULL ) {
				DBCachedContactValue* V1 = V->next;
				FreeCachedVariant(&V->value);
				HeapFree( hCacheHeap, 0, V );
				V = V1;
			}
			HeapFree( hCacheHeap, 0, VL );

			if (VLtemp.hContact == hLastCachedContact)
				hLastCachedContact = NULL;
			li.List_Remove(&lContacts,index);
	}	}

	dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL);
	//delete settings chain
	ofsThis=dbc->ofsFirstSettings;
	ofsFirstEvent=dbc->ofsFirstEvent;
	while(ofsThis) {
		dbcs=(struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL);
		ofsNext=dbcs->ofsNext;
		DeleteSpace(ofsThis,offsetof(struct DBContactSettings,blob)+dbcs->cbBlob);
		ofsThis=ofsNext;
	}
	//delete event chain
	ofsThis=ofsFirstEvent;
	while(ofsThis) {
		dbe=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL);
		ofsNext=dbe->ofsNext;
		DeleteSpace(ofsThis,offsetof(struct DBEvent,blob)+dbe->cbBlob);
		ofsThis=ofsNext;
	}
	//find previous contact in chain and change ofsNext
	dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL);
	if(dbHeader.ofsFirstContact==wParam) {
		dbHeader.ofsFirstContact=dbc->ofsNext;
		DBWrite(0,&dbHeader,sizeof(dbHeader));
	}
	else {
		ofsNext=dbc->ofsNext;
		ofsThis=dbHeader.ofsFirstContact;
		dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL);
		while(dbcPrev->ofsNext!=wParam) {
			if(dbcPrev->ofsNext==0) DatabaseCorruption(NULL);
			ofsThis=dbcPrev->ofsNext;
			dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL);
		}
		dbcPrev->ofsNext=ofsNext;
		DBWrite(ofsThis,dbcPrev,sizeof(struct DBContact));
		{
			DBCachedContactValueList VLtemp;
			VLtemp.hContact = (HANDLE)ofsThis;
			if ( li.List_GetIndex(&lContacts,&VLtemp,&index))
			{
				DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index];
				VL->hNext = ( HANDLE )ofsNext;
		}	}
	}
	//delete contact
	DeleteSpace(wParam,sizeof(struct DBContact));
	//decrement contact count
	dbHeader.contactCount--;
	DBWrite(0,&dbHeader,sizeof(dbHeader));
	DBFlush(0);
	//quit
	LeaveCriticalSection(&csDbAccess);
	return 0;
}