Exemplo n.º 1
0
static __inline int GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs,int isStatic)
{
	struct DBContact *dbc;
	DWORD ofsModuleName,ofsContact,ofsSettingsGroup,ofsBlobPtr;
	int settingNameLen,moduleNameLen;
	int bytesRemaining;
	PBYTE pBlob;
	char* szCachedSettingName;

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

	EnterCriticalSection(&csDbAccess);

	log3("get [%08p] %s/%s",hContact,dbcgs->szModule,dbcgs->szSetting);

	szCachedSettingName = GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,moduleNameLen,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=(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL);
	if(dbc->signature!=DBCONTACT_SIGNATURE) {
		LeaveCriticalSection(&csDbAccess);
		return 1;
	}
	ofsSettingsGroup=GetSettingsGroupOfsByModuleNameOfs(dbc,ofsModuleName);
	if(ofsSettingsGroup) {
		ofsBlobPtr=ofsSettingsGroup+offsetof(struct DBContactSettings,blob);
		pBlob = DBRead(ofsBlobPtr,sizeof(struct DBContactSettings),&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: DecodeCopyMemory(&(dbcgs->pValue->wVal), (PWORD)(pBlob+1), 2); break;
					case DBVT_DWORD: DecodeCopyMemory(&(dbcgs->pValue->dVal), (PDWORD)(pBlob+1), 4); 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);
							DecodeCopyMemory(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));
							DecodeCopyMemory(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);
							DecodeCopyMemory(dbcgs->pValue->pbVal,pBlob+3,dbcgs->pValue->cpbVal);
						}
						else {
							dbcgs->pValue->pbVal=(char*)mir_alloc(*(PWORD)(pBlob+1));
							DecodeCopyMemory(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);
	}	}

	/**** nullbie: query info from preset **********************/
	if (!hContact && DBPreset_QuerySetting(dbcgs->szModule, dbcgs->szSetting, dbcgs->pValue, isStatic))
	{
		/**** add to cache **********************/
		if ( dbcgs->pValue->type != DBVT_BLOB )
		{
			DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 1 );
			if ( pCachedValue != NULL )
				SetCachedVariant(dbcgs->pValue,pCachedValue);
		}
		return 0;
	}

	/**** 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;
}
Exemplo n.º 2
0
int CDb3Mmap::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic)
{
	if (szSetting == NULL || szModule == NULL)
		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(szSetting);
	int moduleNameLen = (int)mir_strlen(szModule);
	if (settingNameLen > 0xFE) {
#ifdef _DEBUG
		OutputDebugStringA("GetContactSettingWorker() got a > 255 setting name length. \n");
#endif
		return 1;
	}
	if (moduleNameLen > 0xFE) {
#ifdef _DEBUG
		OutputDebugStringA("GetContactSettingWorker() got a > 255 module name length. \n");
#endif
		return 1;
	}

	mir_cslock lck(m_csDbAccess);

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

	DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 0);
	if (pCachedValue != NULL) {
		if (pCachedValue->type == DBVT_ASCIIZ || pCachedValue->type == DBVT_UTF8) {
			int cbOrigLen = dbv->cchVal;
			char *cbOrigPtr = dbv->pszVal;
			memcpy(dbv, pCachedValue, sizeof(DBVARIANT));
			if (isStatic) {
				int cbLen = 0;
				if (pCachedValue->pszVal != NULL)
					cbLen = (int)mir_strlen(pCachedValue->pszVal);

				cbOrigLen--;
				dbv->pszVal = cbOrigPtr;
				if (cbLen < cbOrigLen)
					cbOrigLen = cbLen;
				memcpy(dbv->pszVal, pCachedValue->pszVal, cbOrigLen);
				dbv->pszVal[cbOrigLen] = 0;
				dbv->cchVal = cbLen;
			}
			else {
				dbv->pszVal = (char*)mir_alloc(mir_strlen(pCachedValue->pszVal) + 1);
				mir_strcpy(dbv->pszVal, pCachedValue->pszVal);
			}
		}
		else memcpy(dbv, pCachedValue, sizeof(DBVARIANT));

		log2("get cached %s (%p)", printVariant(dbv), pCachedValue);
		return (pCachedValue->type == DBVT_DELETED) ? 1 : 0;
	}

	// never look db for the resident variable
	if (szCachedSettingName[-1] != 0)
		return 1;

	DBCachedContact *cc;
	DWORD ofsContact = GetContactOffset(contactID, &cc);

	DWORD ofsModuleName = GetModuleNameOfs(szModule);

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

	DWORD ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc, ofsModuleName);
	if (ofsSettingsGroup) {
		int bytesRemaining;
		unsigned varLen;
		DWORD ofsBlobPtr = ofsSettingsGroup + offsetof(DBContactSettings, blob);
		PBYTE pBlob = DBRead(ofsBlobPtr, &bytesRemaining);
		while (pBlob[0]) {
			NeedBytes(1 + settingNameLen);
			if (pBlob[0] == settingNameLen && !memcmp(pBlob + 1, szSetting, settingNameLen)) {
				MoveAlong(1 + settingNameLen);
				NeedBytes(5);
				if (isStatic && (pBlob[0] & DBVTF_VARIABLELENGTH) && VLT(dbv->type) != VLT(pBlob[0]))
					return 1;

				BYTE iType = dbv->type = pBlob[0];
				switch (iType) {
				case DBVT_DELETED: /* this setting is deleted */
					dbv->type = DBVT_DELETED;
					return 2;

				case DBVT_BYTE:  dbv->bVal = pBlob[1]; break;
				case DBVT_WORD:  memmove(&(dbv->wVal), (PWORD)(pBlob + 1), 2); break;
				case DBVT_DWORD: memmove(&(dbv->dVal), (PDWORD)(pBlob + 1), 4); break;

				case DBVT_UTF8:
				case DBVT_ASCIIZ:
					varLen = *(PWORD)(pBlob + 1);
					NeedBytes(int(3 + varLen));
					if (isStatic) {
						dbv->cchVal--;
						if (varLen < dbv->cchVal)
							dbv->cchVal = varLen;
						memmove(dbv->pszVal, pBlob + 3, dbv->cchVal); // decode
						dbv->pszVal[dbv->cchVal] = 0;
						dbv->cchVal = varLen;
					}
					else {
						dbv->pszVal = (char*)mir_alloc(1 + varLen);
						memmove(dbv->pszVal, pBlob + 3, varLen);
						dbv->pszVal[varLen] = 0;
					}
					break;

				case DBVT_BLOB:
					varLen = *(PWORD)(pBlob + 1);
					NeedBytes(int(3 + varLen));
					if (isStatic) {
						if (varLen < dbv->cpbVal)
							dbv->cpbVal = varLen;
						memmove(dbv->pbVal, pBlob + 3, dbv->cpbVal);
					}
					else {
						dbv->pbVal = (BYTE *)mir_alloc(varLen);
						memmove(dbv->pbVal, pBlob + 3, varLen);
					}
					dbv->cpbVal = varLen;
					break;

				case DBVT_ENCRYPTED:
					if (m_crypto == NULL)
						return 1;
					else {
						varLen = *(PWORD)(pBlob + 1);
						NeedBytes(int(3 + varLen));
						size_t realLen;
						ptrA decoded(m_crypto->decodeString(pBlob + 3, varLen, &realLen));
						if (decoded == NULL)
							return 1;

						varLen = (WORD)realLen;
						dbv->type = DBVT_UTF8;
						if (isStatic) {
							dbv->cchVal--;
							if (varLen < dbv->cchVal)
								dbv->cchVal = varLen;
							memmove(dbv->pszVal, decoded, dbv->cchVal);
							dbv->pszVal[dbv->cchVal] = 0;
							dbv->cchVal = varLen;
						}
						else {
							dbv->pszVal = (char*)mir_alloc(1 + varLen);
							memmove(dbv->pszVal, decoded, varLen);
							dbv->pszVal[varLen] = 0;
						}
					}
					break;
				}

				/**** add to cache **********************/
				if (iType != DBVT_BLOB && iType != DBVT_ENCRYPTED) {
					DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1);
					if (pCachedValue != NULL) {
						m_cache->SetCachedVariant(dbv, pCachedValue);
						log3("set cached [%08p] %s (%p)", hContact, szCachedSettingName, pCachedValue);
					}
				}

				return 0;
			}
			NeedBytes(1);
			MoveAlong(pBlob[0] + 1);
			NeedBytes(3);
			MoveAlong(1 + GetSettingValueLength(pBlob));
			NeedBytes(1);
		}
	}

	// try to get the missing mc setting from the active sub
	if (cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) {
		if (contactID = db_mc_getDefault(contactID)) {
			if (szModule = GetContactProto(contactID)) {
				moduleNameLen = (int)mir_strlen(szModule);
				goto LBL_Seek;
			}
		}
	}

	logg();
	return 1;
}
Exemplo n.º 3
0
static __inline int GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs,int isStatic)
{
	struct 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=*(struct DBContact*)DBRead(ofsContact,sizeof(struct 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=(char*)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;
}
Exemplo n.º 4
0
int CDbxKV::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic)
{
	if (szSetting == NULL || szModule == NULL)
		return 1;

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

	mir_cslock lck(m_csDbAccess);

LBL_Seek:
	char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen);

	DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 0);
	if (pCachedValue != NULL) {
		if (pCachedValue->type == DBVT_ASCIIZ || pCachedValue->type == DBVT_UTF8) {
			int cbOrigLen = dbv->cchVal;
			char *cbOrigPtr = dbv->pszVal;
			memcpy(dbv, pCachedValue, sizeof(DBVARIANT));
			if (isStatic) {
				int cbLen = 0;
				if (pCachedValue->pszVal != NULL)
					cbLen = (int)strlen(pCachedValue->pszVal);

				cbOrigLen--;
				dbv->pszVal = cbOrigPtr;
				if (cbLen < cbOrigLen)
					cbOrigLen = cbLen;
				memcpy(dbv->pszVal, pCachedValue->pszVal, cbOrigLen);
				dbv->pszVal[cbOrigLen] = 0;
				dbv->cchVal = cbLen;
			}
			else {
				dbv->pszVal = (char*)mir_alloc(strlen(pCachedValue->pszVal) + 1);
				strcpy(dbv->pszVal, pCachedValue->pszVal);
			}
		}
		else memcpy(dbv, pCachedValue, sizeof(DBVARIANT));

		return (pCachedValue->type == DBVT_DELETED) ? 1 : 0;
	}

	// never look db for the resident variable
	if (szCachedSettingName[-1] != 0)
		return 1;

	DBCachedContact *cc = (contactID) ? m_cache->GetCachedContact(contactID) : NULL;

	DBSettingSortingKey keySearch;
	keySearch.dwContactID = contactID;
	keySearch.dwOfsModule = GetModuleNameOfs(szModule);
	strncpy_s(keySearch.szSettingName, szSetting, _TRUNCATE);

	ham_key_t key = { 2 * sizeof(DWORD) + settingNameLen, &keySearch };
	ham_record_t rec = { 0 };
	if (ham_db_find(m_dbSettings, NULL, &key, &rec, 0)) {
		// try to get the missing mc setting from the active sub
		if (cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) {
			if (contactID = db_mc_getDefault(contactID)) {
				if (szModule = GetContactProto(contactID)) {
					moduleNameLen = (int)strlen(szModule);
					goto LBL_Seek;
				}
			}
		}
		return 1;
	}

	BYTE *pBlob = (BYTE*)rec.data;
	if (isStatic && (pBlob[0] & DBVTF_VARIABLELENGTH) && VLT(dbv->type) != VLT(pBlob[0]))
		return 1;

	int varLen;
	BYTE iType = dbv->type = pBlob[0]; pBlob++;
	switch (iType) {
	case DBVT_DELETED: /* this setting is deleted */
		dbv->type = DBVT_DELETED;
		return 2;

	case DBVT_BYTE:  dbv->bVal = *pBlob; break;
	case DBVT_WORD:  dbv->wVal = *(WORD*)pBlob; break;
	case DBVT_DWORD: dbv->dVal = *(DWORD*)pBlob; break;

	case DBVT_UTF8:
	case DBVT_ASCIIZ:
		varLen = *(WORD*)pBlob;
		pBlob += 2;
		if (isStatic) {
			dbv->cchVal--;
			if (varLen < dbv->cchVal)
				dbv->cchVal = varLen;
			memmove(dbv->pszVal, pBlob, dbv->cchVal); // decode
			dbv->pszVal[dbv->cchVal] = 0;
			dbv->cchVal = varLen;
		}
		else {
			dbv->pszVal = (char*)mir_alloc(1 + varLen);
			memmove(dbv->pszVal, pBlob, varLen);
			dbv->pszVal[varLen] = 0;
		}
		break;

	case DBVT_BLOB:
		varLen = *(WORD*)pBlob;
		pBlob += 2;
		if (isStatic) {
			if (varLen < dbv->cpbVal)
				dbv->cpbVal = varLen;
			memmove(dbv->pbVal, pBlob, dbv->cpbVal);
		}
		else {
			dbv->pbVal = (BYTE *)mir_alloc(varLen);
			memmove(dbv->pbVal, pBlob, varLen);
		}
		dbv->cpbVal = varLen;
		break;

	case DBVT_ENCRYPTED:
		if (m_crypto == NULL)
			return 1;

		varLen = *(WORD*)pBlob;
		pBlob += 2;
		
		size_t realLen;
		ptrA decoded(m_crypto->decodeString(pBlob, varLen, &realLen));
		if (decoded == NULL)
			return 1;

		varLen = (WORD)realLen;
		dbv->type = DBVT_UTF8;
		if (isStatic) {
			dbv->cchVal--;
			if (varLen < dbv->cchVal)
				dbv->cchVal = varLen;
			memmove(dbv->pszVal, decoded, dbv->cchVal);
			dbv->pszVal[dbv->cchVal] = 0;
			dbv->cchVal = varLen;
		}
		else {
			dbv->pszVal = (char*)mir_alloc(1 + varLen);
			memmove(dbv->pszVal, decoded, varLen);
			dbv->pszVal[varLen] = 0;
		}
		break;
	}

	/**** add to cache **********************/
	if (iType != DBVT_BLOB && iType != DBVT_ENCRYPTED) {
		DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1);
		if (pCachedValue != NULL)
			m_cache->SetCachedVariant(dbv, pCachedValue);
	}

	return 0;
}