Beispiel #1
0
MEVENT CSkypeProto::GetMessageFromDb(MCONTACT hContact, const char *messageId, LONGLONG timestamp)
{
	if (messageId == NULL)
		return NULL;

	timestamp -= 600; // we check events written 10 minutes ago
	size_t messageIdLength = mir_strlen(messageId);

	mir_cslock lock(messageSyncLock);
	for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent))
	{
		DBEVENTINFO dbei = { sizeof(dbei) };
		dbei.cbBlob = db_event_getBlobSize(hDbEvent);

		if (dbei.cbBlob < messageIdLength)
			continue;

		mir_ptr<BYTE> blob((PBYTE)mir_alloc(dbei.cbBlob));
		dbei.pBlob = blob;
		db_event_get(hDbEvent, &dbei);

		size_t cbLen = mir_strlen((char*)dbei.pBlob);
		if (memcmp(&dbei.pBlob[cbLen + 1], messageId, messageIdLength) == 0)
			return hDbEvent;

		if (dbei.timestamp < timestamp)
			break;
	}

	return NULL;
}
Beispiel #2
0
BOOL checkMsgTimestamp(MCONTACT hContact, HANDLE hEventCurrent, DWORD timestampCurrent)
{
	if (!bFlashIfMsgOlder)
		return TRUE;

	for (HANDLE hEvent = db_event_prev(hContact, hEventCurrent); hEvent; hEvent = db_event_prev(hContact, hEvent)) {
		DBEVENTINFO einfo = { sizeof(einfo) };
		if(!db_event_get(hEvent, &einfo)) {
			if ((einfo.timestamp + wSecondsOlder) <= timestampCurrent)
				return TRUE;
			if (einfo.eventType == EVENTTYPE_MESSAGE)
				return FALSE;
		}
	}

	return TRUE;
}
Beispiel #3
0
DWORD INTSORT_GetLastMsgTime(MCONTACT hContact)
{
	for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) {
		DBEVENTINFO dbei = { sizeof(dbei) };
		db_event_get(hDbEvent, &dbei);
		if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
			return dbei.timestamp;
	}
	return 0;
}
//************************************************************************
// updates the message count for the specified contact
//************************************************************************
void CContactList::UpdateMessageCounter(CListEntry<CContactListEntry*,CContactListGroup*> *pContactEntry)
{
	CContactListEntry *pEntry = GetContactData(pContactEntry);
	if(!pEntry) {
		return;
	}
	int iOldMessages = pEntry->iMessages;

	bool bSort = false;
	HANDLE hEvent= NULL;

	hEvent = db_event_firstUnread(pEntry->hHandle);
	if(CAppletManager::IsMessageWindowOpen(pEntry->hHandle) || (hEvent == NULL && pEntry->iMessages > 0))
	{
		pEntry->iMessages = 0;
		bSort = true;
	}
	else
	{
		pEntry->iMessages = 0;
		HANDLE hLastEvent = db_event_last(pEntry->hHandle);
		while(hLastEvent != NULL && hEvent != NULL)
		{
			pEntry->iMessages++;
			if(hLastEvent == hEvent)
				break;
			hLastEvent = db_event_prev(hLastEvent);
		}
	}
	if(pEntry->iMessages >= 100)
		pEntry->strMessages = _T(">99");
	else
	{
		char buffer[8];
		buffer[0] = 0;
		itoa(pEntry->iMessages,buffer,10);
		pEntry->strMessages = toTstring(buffer);
	}

	CListContainer<CContactListEntry*,CContactListGroup*>* pContainer = ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent());
	// Update the contacts group if it has one
	if(pContainer->GetType() != ROOT)
	{
		// Update the groups event count
		if(iOldMessages != 0 && pEntry->iMessages == 0)
			ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,-1);
		else if(iOldMessages == 0 && pEntry->iMessages != 0)
			ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,1);
		else
			return;
		
		// sort the groups parent
		((CListContainer<CContactListEntry*,CContactListGroup*>*)pContainer->GetParent())->sort(CContactList::CompareEntries);
	}
}
LONGLONG GetLastSentMessageTime(MCONTACT hContact)
{
	for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent))
	{
		DBEVENTINFO dbei = { sizeof(dbei) };
		db_event_get(hDbEvent, &dbei);
		if (FLAG_CONTAINS(dbei.flags, DBEF_SENT))
			return dbei.timestamp;
	}
	return -1;
}
Beispiel #6
0
DWORD CompareContacts2_getLMTime(MCONTACT hContact)
{
	MEVENT hDbEvent = db_event_last(hContact);
	while (hDbEvent) {
		DBEVENTINFO dbei = { sizeof(dbei) };
		db_event_get(hDbEvent, &dbei);
		if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
			return dbei.timestamp;
		hDbEvent = db_event_prev(hContact, hDbEvent);
	}
	return 0;
}
Beispiel #7
0
time_t getLastInputMsg(MCONTACT hContact)
{
	MEVENT hDbEvent = db_event_last(hContact);
	while (hDbEvent) {
		DBEVENTINFO dbei = {};
		db_event_get(hDbEvent, &dbei);
		if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
			return dbei.timestamp;
		hDbEvent = db_event_prev(hContact, hDbEvent);
	}
	return -1;
}
Beispiel #8
0
/**
 * calculate message frequency for a single contact
 */
static void MF_CalcFrequency(MCONTACT hContact, DWORD dwCutoffDays, int doSleep)
{
    DWORD     curTime = time(NULL);
    DWORD     frequency, eventCount;
    DBEVENTINFO dbei = {0};
    MEVENT hEvent = db_event_last(hContact);

    eventCount = 0;
    dbei.cbSize = sizeof(dbei);
    dbei.timestamp = 0;

    while(hEvent) {
        dbei.cbBlob = 0;
        dbei.pBlob = NULL;
        db_event_get(hEvent, &dbei);

        if(dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { // record time of last event
            eventCount++;
        }
		/*
		 * consider the most recent 100 messages and ignore messages that are older than the cutoff days.
		 * this will prevent contacts with a high message rate in the past to keep occupying the 
		 * top positions forever.
		 */
        if(eventCount >= 100 || dbei.timestamp < curTime - (dwCutoffDays * 86400))
            break;
        hEvent = db_event_prev(hContact, hEvent);
		// check for main update thread still running (if not, application is shutting down, so terminate our work)
        if(doSleep && mf_updatethread_running == FALSE)
            return;
        if(doSleep)
            Sleep(100);
    }

    if(eventCount == 0) {
        frequency = 0x7fffffff;
        cfg::writeDword(hContact, "CList", "mf_firstEvent", curTime - (dwCutoffDays * 86400));
    }
    else {
        frequency = (curTime - dbei.timestamp) / eventCount;
        cfg::writeDword(hContact, "CList", "mf_firstEvent", dbei.timestamp);
    }

    cfg::writeDword(hContact, "CList", "mf_freq", frequency);
    cfg::writeDword(hContact, "CList", "mf_count", eventCount);
}
Beispiel #9
0
static void FillHistoryThread(void* param)
{
	Thread_SetName("HistoryWindow::FillHistoryThread");

	THistoryThread *hInfo = (THistoryThread*)param;
	HWND hwndList = GetDlgItem(hInfo->hwnd, IDC_LIST);

	SendDlgItemMessage(hInfo->hwnd, IDC_LIST, LB_RESETCONTENT, 0, 0);
	int i = db_event_count(hInfo->hContact);
	SendDlgItemMessage(hInfo->hwnd, IDC_LIST, LB_INITSTORAGE, i, i * 40);

	DBEVENTINFO dbei = { sizeof(dbei) };
	int oldBlobSize = 0;
	MEVENT hDbEvent = db_event_last(hInfo->hContact);

	while (hDbEvent != NULL) {
		if (!IsWindow(hInfo->hwnd))
			break;
		int newBlobSize = db_event_getBlobSize(hDbEvent);
		if (newBlobSize > oldBlobSize) {
			dbei.pBlob = (PBYTE)mir_realloc(dbei.pBlob, newBlobSize);
			oldBlobSize = newBlobSize;
		}
		dbei.cbBlob = oldBlobSize;
		db_event_get(hDbEvent, &dbei);

		TCHAR str[200], eventText[256], strdatetime[64];
		GetObjectSummary(&dbei, str, _countof(str));
		if (str[0]) {
			TimeZone_PrintTimeStamp(NULL, dbei.timestamp, _T("d t"), strdatetime, _countof(strdatetime), 0);
			mir_sntprintf(eventText, _T("%s: %s"), strdatetime, str);
			i = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)eventText);
			SendMessage(hwndList, LB_SETITEMDATA, i, (LPARAM)hDbEvent);
		}
		hDbEvent = db_event_prev(hInfo->hContact, hDbEvent);
	}
	mir_free(dbei.pBlob);

	SendDlgItemMessage(hInfo->hwnd, IDC_LIST, LB_SETCURSEL, 0, 0);
	SendMessage(hInfo->hwnd, WM_COMMAND, MAKEWPARAM(IDC_LIST, LBN_SELCHANGE), 0);
	EnableWindow(GetDlgItem(hInfo->hwnd, IDC_LIST), TRUE);
	mir_free(hInfo);
}
Beispiel #10
0
static int lua_EventReverseIterator(lua_State *L)
{
	MCONTACT hContact = luaL_checkinteger(L, lua_upvalueindex(1));
	MEVENT hEvent = luaL_checkinteger(L, lua_upvalueindex(2));

	hEvent = hEvent == NULL
		? db_event_last(hContact)
		: db_event_prev(hContact, hEvent);

	if (hEvent)
	{
		lua_pushinteger(L, hContact);
		lua_pushvalue(L, -1);
		lua_replace(L, lua_upvalueindex(2));
	}
	else
		lua_pushnil(L);

	return 1;
}
Beispiel #11
0
static void MF_CalcFrequency(MCONTACT hContact, DWORD dwCutoffDays, int doSleep)
{
	DWORD  curTime = time(NULL);
	DWORD  frequency, eventCount;
	MEVENT hEvent = db_event_last(hContact);

	eventCount = 0;

	DBEVENTINFO dbei = { sizeof(dbei) };
	while (hEvent) {
		db_event_get(hEvent, &dbei);

		if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { // record time of last event
			eventCount++;
		}
		if (eventCount >= 100 || dbei.timestamp < curTime - (dwCutoffDays * 86400))
			break;
		hEvent = db_event_prev(hContact, hEvent);
		if (doSleep && mf_updatethread_running == FALSE)
			return;
		if (doSleep)
			Sleep(100);
	}

	if (eventCount == 0) {
		frequency = 0x7fffffff;
		cfg::writeDword(hContact, "CList", "mf_firstEvent", curTime - (dwCutoffDays * 86400));
	}
	else {
		frequency = (curTime - dbei.timestamp) / eventCount;
		cfg::writeDword(hContact, "CList", "mf_firstEvent", dbei.timestamp);
	}

	cfg::writeDword(hContact, "CList", "mf_freq", frequency);
	cfg::writeDword(hContact, "CList", "mf_count", eventCount);
}
Beispiel #12
0
// Returns TRUE if the event already exist in the database
BOOL IsDuplicateEvent(MCONTACT hContact, DBEVENTINFO& dbei)
{
	HANDLE hExistingDbEvent;
	DWORD dwEventTimeStamp;

	// get last event
	if (!(hExistingDbEvent = db_event_last(hContact)))
		return FALSE;

	DBEVENTINFO dbeiExisting = { sizeof(dbeiExisting) };
	db_event_get(hExistingDbEvent, &dbeiExisting);
	dwEventTimeStamp = dbeiExisting.timestamp;

	// compare with last timestamp
	if (dbei.timestamp > dwEventTimeStamp) {
		// remember event
		hPreviousDbEvent = hExistingDbEvent;
		dwPreviousTimeStamp = dwEventTimeStamp;
		return FALSE;
	}

	if (hContact != hPreviousContact) {
		hPreviousContact = hContact;
		// remember event
		hPreviousDbEvent = hExistingDbEvent;
		dwPreviousTimeStamp = dwEventTimeStamp;

		// get first event
		if (!(hExistingDbEvent = db_event_first(hContact)))
			return FALSE;

		memset(&dbeiExisting, 0, sizeof(dbeiExisting));
		dbeiExisting.cbSize = sizeof(dbeiExisting);
		db_event_get(hExistingDbEvent, &dbeiExisting);
		dwEventTimeStamp = dbeiExisting.timestamp;

		// compare with first timestamp
		if (dbei.timestamp <= dwEventTimeStamp) {
			// remember event
			dwPreviousTimeStamp = dwEventTimeStamp;
			hPreviousDbEvent = hExistingDbEvent;

			if ( dbei.timestamp != dwEventTimeStamp )
				return FALSE;
		}
	}

	// check for equal timestamps
	if (dbei.timestamp == dwPreviousTimeStamp) {
		memset(&dbeiExisting, 0, sizeof(dbeiExisting));
		dbeiExisting.cbSize = sizeof(dbeiExisting);
		db_event_get(hPreviousDbEvent, &dbeiExisting);

		if ((dbei.timestamp == dbeiExisting.timestamp) &&
			(dbei.eventType == dbeiExisting.eventType) &&
			(dbei.cbBlob == dbeiExisting.cbBlob) &&
			((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT)))
			return TRUE;

		// find event with another timestamp
		hExistingDbEvent = db_event_next(hContact, hPreviousDbEvent);
		while (hExistingDbEvent != NULL) {
			memset(&dbeiExisting, 0, sizeof(dbeiExisting));
			dbeiExisting.cbSize = sizeof(dbeiExisting);
			db_event_get(hExistingDbEvent, &dbeiExisting);

			if (dbeiExisting.timestamp != dwPreviousTimeStamp) {
				// use found event
				hPreviousDbEvent = hExistingDbEvent;
				dwPreviousTimeStamp = dbeiExisting.timestamp;
				break;
			}

			hPreviousDbEvent = hExistingDbEvent;
			hExistingDbEvent = db_event_next(hContact, hExistingDbEvent);
		}
	}

	hExistingDbEvent = hPreviousDbEvent;

	if (dbei.timestamp <= dwPreviousTimeStamp) {
		// look back
		while (hExistingDbEvent != NULL) {
			memset(&dbeiExisting, 0, sizeof(dbeiExisting));
			dbeiExisting.cbSize = sizeof(dbeiExisting);
			db_event_get(hExistingDbEvent, &dbeiExisting);

			if (dbei.timestamp > dbeiExisting.timestamp) {
				// remember event
				hPreviousDbEvent = hExistingDbEvent;
				dwPreviousTimeStamp = dbeiExisting.timestamp;
				return FALSE;
			}

			// Compare event with import candidate
			if ((dbei.timestamp == dbeiExisting.timestamp) &&
				(dbei.eventType == dbeiExisting.eventType) &&
				(dbei.cbBlob == dbeiExisting.cbBlob) &&
				((dbei.flags & DBEF_SENT) == (dbeiExisting.flags & DBEF_SENT)))
			{
				// remember event
				hPreviousDbEvent = hExistingDbEvent;
				dwPreviousTimeStamp = dbeiExisting.timestamp;
				return TRUE;
			}

			// Get previous event in chain
			hExistingDbEvent = db_event_prev(hContact, hExistingDbEvent);
		}
	}
	else {
		// look forward
		while (hExistingDbEvent != NULL) {
			memset(&dbeiExisting, 0, sizeof(dbeiExisting));
			dbeiExisting.cbSize = sizeof(dbeiExisting);
			db_event_get(hExistingDbEvent, &dbeiExisting);

			if (dbei.timestamp < dbeiExisting.timestamp) {
				// remember event
				hPreviousDbEvent = hExistingDbEvent;
				dwPreviousTimeStamp = dbeiExisting.timestamp;
				return FALSE;
			}

			// Compare event with import candidate
			if ((dbei.timestamp == dbeiExisting.timestamp) &&
				(dbei.eventType == dbeiExisting.eventType) &&
				(dbei.cbBlob == dbeiExisting.cbBlob) &&
				((dbei.flags&DBEF_SENT) == (dbeiExisting.flags&DBEF_SENT)))
			{
				// remember event
				hPreviousDbEvent = hExistingDbEvent;
				dwPreviousTimeStamp = dbeiExisting.timestamp;
				return TRUE;
			}

			// Get next event in chain
			hExistingDbEvent = db_event_next(hContact, hExistingDbEvent);
		}
	}
	// reset last event
	hPreviousContact = INVALID_CONTACT_ID;
	return FALSE;
}
Beispiel #13
0
//************************************************************************
// loads the contacts history
//************************************************************************
void CChatScreen::LoadHistory()
{
	if(!m_hContact)
		return;

	char *szProto = GetContactProto(m_hContact);
	
	if(m_bIRCProtocol && db_get_b(m_hContact, szProto, "ChatRoom", 0) != 0)
	{
		if(!CAppletManager::GetInstance()->IsIRCHookEnabled())
		{
			time_t now;
			tm tm_now;
			time(&now);
			localtime_s(&tm_now,&now);

			AddIncomingMessage(CAppletManager::TranslateString(_T("IRC-Chatroom support is disabled!\nYou need to install the patched IRC.dll (see the readme) to use IRC-Chatrooms on the LCD")),&tm_now,true);
		}
		else
		{
			CIRCHistory *pHistory = CAppletManager::GetInstance()->GetIRCHistory(m_hContact);
			if(pHistory)
			{
				list<SIRCMessage>::iterator iter = pHistory->LMessages.begin();
				while(iter != pHistory->LMessages.end())
				{
					if((*iter).bIsMe)
						AddOutgoingMessage((*iter).strMessage,&((*iter).Time),true);
					else
						AddIncomingMessage((*iter).strMessage,&((*iter).Time),true);
					iter++;
				}
			}
		}
	}
	else
	{
		// Get last events from database
		CEvent Event;
		list<MEVENT> LHandles;
		MEVENT hEvent = db_event_last(m_hContact);
		MEVENT hUnread = db_event_firstUnread(m_hContact);
		
		if(CConfig::GetBoolSetting(SESSION_LOADDB))
		{
			while(hEvent != NULL && hUnread != NULL)
			{
				LHandles.push_front(hEvent);
				if(CConfig::GetBoolSetting(SESSION_LOADDB) && *(LHandles.begin()) == hUnread)
					break;
				hEvent = db_event_prev(m_hContact, hEvent);
			}
		}
		else
		{
			for (int i = CConfig::GetIntSetting(SESSION_LOGSIZE); i > 0 && hEvent!=NULL; i--)
			{
				LHandles.push_front(hEvent);
				hEvent = db_event_prev(m_hContact, hEvent);
			}
		}

		bool bRead = true;
		while(!(LHandles.empty()))
		{
			if(CAppletManager::TranslateDBEvent(&Event,(LPARAM)m_hContact,(WPARAM)*(LHandles.begin())))
			{
				if(Event.hValue == hUnread)
					bRead = false;
				if(Event.eType == EVENT_MSG_RECEIVED)
				{
					AddIncomingMessage(Event.strValue,&Event.Time);
					if(!bRead && CConfig::GetBoolSetting(SESSION_MARKREAD) && !CAppletManager::IsMessageWindowOpen(m_hContact))
						CAppletManager::MarkMessageAsRead(m_hContact,Event.hValue);
				}
				else
					AddOutgoingMessage(Event.strValue,&Event.Time);

			}		
			LHandles.pop_front();
		}
	}
}
Beispiel #14
0
static MEVENT findDbEvent(MCONTACT hContact, MEVENT hDbEvent, int flags)
{
	DBEVENTINFO dbe;
	BOOL bEventOk;

	do {
		memset(&dbe, 0, sizeof(DBEVENTINFO));
		dbe.cbSize = sizeof(DBEVENTINFO);
		dbe.cbBlob = 0;
		dbe.pBlob = NULL;
		if (hContact != NULL) {
			if ((flags & DBE_FIRST) && (flags & DBE_UNREAD)) {
				hDbEvent = db_event_firstUnread(hContact);
				if (hDbEvent == NULL && (flags & DBE_READ))
					hDbEvent = db_event_first(hContact);
			}
			else if (flags & DBE_FIRST)
				hDbEvent = db_event_first(hContact);
			else if (flags & DBE_LAST)
				hDbEvent = db_event_last(hContact);
			else if (flags & DBE_NEXT)
				hDbEvent = db_event_next(hContact, hDbEvent);
			else if (flags & DBE_PREV)
				hDbEvent = db_event_prev(hContact, hDbEvent);
		}
		else {
			MEVENT hMatchEvent = NULL, hSearchEvent = NULL;
			DWORD matchTimestamp = 0, priorTimestamp = 0;

			if (flags & DBE_FIRST) {
				for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) {
					hSearchEvent = findDbEvent(hSearchContact, NULL, flags);
					dbe.cbBlob = 0;
					if (!db_event_get(hSearchEvent, &dbe)) {
						if ((dbe.timestamp < matchTimestamp) || (matchTimestamp == 0)) {
							hMatchEvent = hSearchEvent;
							matchTimestamp = dbe.timestamp;
						}
					}
				}
				hDbEvent = hMatchEvent;
			}
			else if (flags & DBE_LAST) {
				for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) {
					hSearchEvent = findDbEvent(hSearchContact, NULL, flags);
					dbe.cbBlob = 0;
					if (!db_event_get(hSearchEvent, &dbe)) {
						if ((dbe.timestamp > matchTimestamp) || (matchTimestamp == 0)) {
							hMatchEvent = hSearchEvent;
							matchTimestamp = dbe.timestamp;
						}
					}
				}
				hDbEvent = hMatchEvent;
			}
			else if (flags & DBE_NEXT) {
				dbe.cbBlob = 0;
				if (!db_event_get(hDbEvent, &dbe)) {
					priorTimestamp = dbe.timestamp;
					for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) {
						hSearchEvent = findDbEvent(hSearchContact, hDbEvent, flags);
						dbe.cbBlob = 0;
						if (!db_event_get(hSearchEvent, &dbe)) {
							if (((dbe.timestamp < matchTimestamp) || (matchTimestamp == 0)) && (dbe.timestamp > priorTimestamp)) {
								hMatchEvent = hSearchEvent;
								matchTimestamp = dbe.timestamp;
							}
						}
					}
					hDbEvent = hMatchEvent;
				}
			}
			else if (flags & DBE_PREV) {
				if (!db_event_get(hDbEvent, &dbe)) {
					priorTimestamp = dbe.timestamp;
					for (MCONTACT hSearchContact = db_find_first(); hSearchContact; hSearchContact = db_find_next(hSearchContact)) {
						hSearchEvent = findDbEvent(hSearchContact, hDbEvent, flags);
						dbe.cbBlob = 0;
						if (!db_event_get(hSearchEvent, &dbe)) {
							if (((dbe.timestamp > matchTimestamp) || (matchTimestamp == 0)) && (dbe.timestamp < priorTimestamp)) {
								hMatchEvent = hSearchEvent;
								matchTimestamp = dbe.timestamp;
							}
						}
					}
					hDbEvent = hMatchEvent;
				}
			}
		}
		dbe.cbBlob = 0;
		if (db_event_get(hDbEvent, &dbe))
			bEventOk = FALSE;
		else
			bEventOk = isValidDbEvent(&dbe, flags);
		if (!bEventOk) {
			if (flags&DBE_FIRST) {
				flags |= DBE_NEXT;
				flags &= ~DBE_FIRST;
			}
			else if (flags&DBE_LAST) {
				flags |= DBE_PREV;
				flags &= ~DBE_LAST;
			}
		}
	}
	while ((!bEventOk) && (hDbEvent != NULL));

	return hDbEvent;
}