Esempio n. 1
0
BOOL CTcpSocket::Write(char * pData, int iLength)
{
	if (m_hOutputEvent == NULL)	return FALSE;

	CSingleLock sLock(&m_critical);
	WSABUF * p = (WSABUF *)malloc(sizeof(WSABUF));
	if (p == NULL)
	{
		OutputDebugString(_T("malloc failed in CTcpSocket::Write\n"));
		return FALSE;
	}
	p->buf = (char *)malloc(TCP_BUFFER_LENGTH);
	if (p->buf == NULL)
	{
		free(p);
		OutputDebugString(_T("malloc failed in CTcpSocket::Write\n"));
		return FALSE;
	}
	memcpy(p->buf, pData, iLength);
	p->len = iLength;
	sLock.Lock();
	m_sendQueue.AddTail(p);
	sLock.Unlock();
	SetEvent(m_hOutputEvent);
//	Sleep(0);
	return TRUE;
}
Esempio n. 2
0
///////////////////////////////////////////////////////////////////////////
// CTSPIConferenceCall::RemoveConferenceCall
//
// Remove the conference call specified from our array.  Callstate
// of the removed call is not changed.  Conference is idle'd if this
// is the last call.
//
void CTSPIConferenceCall::RemoveConferenceCall(CTSPICallAppearance* pCall, bool fForceBreakdown /*=true*/)
{   
    // Locate the call appearance and remove it.
	CEnterCode sLock(this);  // Synch access to object
	TCallHubList::iterator pos = std::find(m_lstConference.begin(), m_lstConference.end(), pCall);
	if (pos != m_lstConference.end())
	{
		m_lstConference.erase(pos);
		pCall->SetConferenceOwner(NULL);
		
		// If we have no more calls in our array, then transition 
		// the conference to IDLE.
		if (m_lstConference.empty() && fForceBreakdown)
			SetCallState(LINECALLSTATE_IDLE);

		// Otherwise if we have a single party and we are supposed to breakdown
		// the conference to a two-party call, then do so now.
		else if (m_lstConference.size() == 1 && fForceBreakdown)
		{
			pCall = GetConferenceCall(0);
			RemoveConferenceCall(pCall);
			if (pCall->GetCallState() == LINECALLSTATE_CONFERENCED)
			{
				// If the remove state is not IDLE, change the call state to the given
				// state in the ADDRESSCAPS structure.
				if (GetAddressOwner()->GetAddressCaps()->dwRemoveFromConfState != LINECALLSTATE_IDLE)
					pCall->SetCallState(GetAddressOwner()->GetAddressCaps()->dwRemoveFromConfState);
				else
					pCall->SetCallState(LINECALLSTATE_CONNECTED);
			}
		}
    }               

}// CTSPIConferenceCall::RemoveConferenceCall
Esempio n. 3
0
VOID CLogFile::CacheLog(enum_LOG_LEVEL	logLevel, const CHAR* pLogString , ... )
{
    //等级太低,不需打印控制台和文件
    if (logLevel < m_eConsoleLogLevel && logLevel < m_eFileLogLevel)
    {
        return ;
    }

    CHAR szLine[MAX_LOG_LINE] = {0};
    va_list	va;
    va_start(va,pLogString);
#ifdef __LINUX
    vsprintf(szLine,pLogString,va);
#else
    vsprintf_s(szLine,MAX_LOG_LINE,pLogString,va);
#endif
    va_end(va);

    DateTime now;
    CHAR szLogStr[MAX_LOG_LINE] = {'\0'};
    _snprintf(szLogStr, MAX_LOG_LINE-1, "%2d/%02d/%02d %02d:%02d:%02d.%03d	tId:%ld	%s\n",
              now.GetYear(),
              now.GetMonth(),
              now.GetDay(),
              now.GetHour(),
              now.GetMinute(),
              now.GetSecond(),
              now.GetMilliSecond(),
              GetThreadID(),
              szLine);
    //高等与控制台等级,则打印到控制台
    if (logLevel >= m_eConsoleLogLevel)
    {
        printf("%s", szLogStr);
    }

    //高等与文件等级,则打印到文件
    if (logLevel >= m_eFileLogLevel)
    {
        CSmartLock sLock(m_lock);

        int strLength = strlen(szLogStr);
        if (m_pWriteBuf + strLength - m_pFrontBuf >=  LOG_BUF_LEN)
        {
            //front 缓冲满了
            if (m_bBackBufAvailable)
            {
                //两块全满了,这条要丢。
                printf("LOG LOST!!, %s", szLogStr);
                return;
            }
            //back空着,将front交换到back
            SwitchBuf();
        }

        //写入front
        strcpy( m_pWriteBuf, szLogStr );
        m_pWriteBuf += strLength;
    }
}
Esempio n. 4
0
void CBuffer::Empty()
{
	CSingleLock sLock(&m_mutex);
	sLock.Lock();
	m_strBuf.Empty();
	sLock.Unlock();
}
Esempio n. 5
0
void MockRemoteDBServer::checkIfUp(InstanceID id) const {
    scoped_spinlock sLock(_lock);

    if (!_isRunning || id < _instanceID) {
        throw mongo::SocketException(mongo::SocketException::CLOSED, _hostAndPort);
    }
}
Esempio n. 6
0
mongo::BSONArray MockRemoteDBServer::query(MockRemoteDBServer::InstanceID id,
                                           const string& ns,
                                           mongo::Query query,
                                           int nToReturn,
                                           int nToSkip,
                                           const BSONObj* fieldsToReturn,
                                           int queryOptions,
                                           int batchSize) {
    checkIfUp(id);

    if (_delayMilliSec > 0) {
        mongo::sleepmillis(_delayMilliSec);
    }

    checkIfUp(id);

    scoped_spinlock sLock(_lock);
    _queryCount++;

    const vector<BSONObj>& coll = _dataMgr[ns];
    BSONArrayBuilder result;
    for (vector<BSONObj>::const_iterator iter = coll.begin(); iter != coll.end(); ++iter) {
        result.append(iter->copy());
    }

    return BSONArray(result.obj());
}
Esempio n. 7
0
CKnownFile* CKnownFileList::FindKnownFile(
	const CPath& filename,
	time_t in_date,
	uint64 in_size)
{
	wxMutexLocker sLock(list_mut);

	if (m_knownSizeMap) {
		std::pair<KnownFileSizeMap::const_iterator, KnownFileSizeMap::const_iterator> p;
		p = m_knownSizeMap->equal_range((uint32) in_size);
		for (KnownFileSizeMap::const_iterator it = p.first; it != p.second; ++it) {
			CKnownFile *cur_file = it->second;
			if (KnownFileMatches(cur_file, filename, in_date, in_size)) {
				return cur_file;
			}
		}
	} else {
		for (CKnownFileMap::const_iterator it = m_knownFileMap.begin();
			 it != m_knownFileMap.end(); ++it) {
			CKnownFile *cur_file = it->second;
			if (KnownFileMatches(cur_file, filename, in_date, in_size)) {
				return cur_file;
			}
		}
	}

	return IsOnDuplicates(filename, in_date, in_size);
}
Esempio n. 8
0
void MockRemoteDBServer::remove(const string& ns, Query query, int flags) {
    scoped_spinlock sLock(_lock);
    if (_dataMgr.count(ns) == 0) {
        return;
    }

    _dataMgr.erase(ns);
}
Esempio n. 9
0
BOOL CBuffer::IsEmpty()
{
	CSingleLock sLock(&m_mutex);
	sLock.Lock();
	BOOL bIsEmpty = m_strBuf.IsEmpty();
	sLock.Unlock();
	return bIsEmpty;
}
Esempio n. 10
0
int CBuffer::GetLength()
{
	CSingleLock sLock(&m_mutex);
	sLock.Lock();
	int len = m_strBuf.GetLength();
	sLock.Unlock();
	return len;
}
Esempio n. 11
0
void CKnownFileList::Clear()
{
	wxMutexLocker sLock(list_mut);

	DeleteContents(m_knownFileMap);
	DeleteContents(m_duplicateFileList);
	ReleaseIndex();
}
Esempio n. 12
0
BOOL CBuffer::Write(LPCTSTR lpszStr)
{
	if (!lpszStr || !*lpszStr) return FALSE;
	CSingleLock sLock(&m_mutex);
	sLock.Lock();
	BOOL res = m_strBuf.IsEmpty();
	m_strBuf += lpszStr;
	sLock.Unlock();
	return res;
}
Esempio n. 13
0
///////////////////////////////////////////////////////////////////////////
// CTSPIConferenceCall::GetConferenceCall
//
// Return the call at the index specified
//
CTSPICallAppearance* CTSPIConferenceCall::GetConferenceCall(unsigned int i)
{   
	CEnterCode sLock(this);  // Synch access to object

	TCallHubList::iterator it, itEnd = m_lstConference.end();
	for (it = m_lstConference.begin(); it != itEnd && i > 0; ++it, --i)
			;
	return (it != itEnd) ? (*it) : NULL;

}// CTSPIConferenceCall::GetConferenceCall
Esempio n. 14
0
LPTSTR CBuffer::Peek()
{
	CSingleLock sLock(&m_mutex);
	sLock.Lock();
	CString strBuf = m_strBuf;
	strBuf.Replace("\r\n", "\n");
	strBuf.Replace("\n", "\r\n");
	LPTSTR lpszStr = new TCHAR[strBuf.GetLength()+1];
	strcpy(lpszStr, strBuf);
	sLock.Unlock();
	return lpszStr;
}
Esempio n. 15
0
bool CKnownFileList::SafeAddKFile(CKnownFile* toadd, bool afterHashing)
{
	bool ret;
	{
		wxMutexLocker sLock(list_mut);
		ret = Append(toadd, afterHashing);
	}
	if (ret) {
		theApp->searchlist->UpdateSearchFileByHash(toadd->GetFileHash());
	}
	return ret;
}
Esempio n. 16
0
    bool MockRemoteDBServer::runCommand(MockRemoteDBServer::InstanceID id,
            const string& dbname,
            const BSONObj& cmdObj,
            BSONObj &info,
            int options) {
        checkIfUp(id);

        // Get the name of the command - copied from _runCommands @ db/dbcommands.cpp
        BSONObj innerCmdObj;
        {
            mongo::BSONElement e = cmdObj.firstElement();
            if (e.type() == mongo::Object && (e.fieldName()[0] == '$'
                    ? mongo::str::equals("query", e.fieldName()+1) :
                            mongo::str::equals("query", e.fieldName()))) {
                innerCmdObj = e.embeddedObject();
            }
            else {
                innerCmdObj = cmdObj;
            }
        }

        string cmdName = innerCmdObj.firstElement().fieldName();
        uassert(16430, str::stream() << "no reply for cmd: " << cmdName,
                _cmdMap.count(cmdName) == 1);

        {
            scoped_spinlock sLock(_lock);
            info = _cmdMap[cmdName]->next();
        }

        if (_delayMilliSec > 0) {
            mongo::sleepmillis(_delayMilliSec);
        }

        checkIfUp(id);

        scoped_spinlock sLock(_lock);
        _cmdCount++;
        return info["ok"].trueValue();
    }
Esempio n. 17
0
///////////////////////////////////////////////////////////////////////////
// CTSPIConferenceCall::OnRelatedCallStateChange
//
// This method is called by all calls which are part of our confernece
// as their state changes.  We use it to insert and delete calls from
// our conference.
//
void CTSPIConferenceCall::OnRelatedCallStateChange (CTSPICallAppearance* pCall, DWORD dwState, DWORD /*dwOldState*/)
{
	CEnterCode sLock(this);  // Synch access to object

    // If the call is now conferenced in, add it to our list.
    if (dwState == LINECALLSTATE_CONFERENCED)
    {    
		// Add it to the conference.
        if (!IsCallInConference(pCall))
			m_lstConference.push_back(pCall);

		// Mark the conference owner if it isn't set yet.
		pCall->SetConferenceOwner(this);

		// If this is the consultation call for the conference, change the type
		// of call and remove the attachment.
		if (GetAttachedCall() == pCall)
		{
			SetConsultationCall(NULL);
			pCall->SetCallType(Normal);
		}

		// Force it to recalculate it's call features
		pCall->RecalcCallFeatures(dwState);

    }
    // Otherwise if it has transitioned to IDLE then remove it from the conference
    else if (dwState == LINECALLSTATE_IDLE)
    {   
        // If this was a consultant call created by PrepareConf or SetupConf, then
        // it is not part of our conference, and now never will be.
        if (GetAttachedCall() == pCall)
        {   
            // Give any derived class an opportunity to do something about the call being
            // destroyed - i.e. some switches actually drop back to a dialtone, which would
            // require a new call be created.  Some switch back to a two party call when only
            // one member is still in the conference.  The default is to do nothing.
			OnConsultantCallIdle(GetConsultationCall());

			// Detach it from the conference
			SetConsultationCall(NULL);
        }
        else
        {   
            // Locate the call appearance which went IDLE and remove it from our conference
            // array.  If the total number of conferenced calls hits zero, then IDLE this
            // call.
            RemoveConferenceCall(pCall);
        }
    }

}// CTSPIConferenceCall::OnRelatedCallStateChange
void DroidMaintenanceModuleDataComponent::payStructures(CreatureObject* player, VectorMap<unsigned long long, int> assignments) {
	// we know each struct to pay and any fees applied.
	ManagedReference<DroidObject*> droid = getDroidObject();

	for(int i=0;i< assignments.size();i++) {
		uint64 objectID = assignments.elementAt(i).getKey();
		int maintToPay = assignments.elementAt(i).getValue();
		ManagedReference<SceneObject*> obj = player->getZoneServer()->getObject(objectID);
		StructureObject* structureObject = cast<StructureObject*>(obj.get());
		if (structureObject != NULL)
			Locker sLock(obj,player);
			structureObject->payMaintenance(maintToPay,player,true);
	}
}
Esempio n. 19
0
CKnownFile* CKnownFileList::FindKnownFileByID(const CMD4Hash& hash)
{
	wxMutexLocker sLock(list_mut);

	if (!hash.IsEmpty()) {
		if (m_knownFileMap.find(hash) != m_knownFileMap.end()) {
			return m_knownFileMap[hash];
		} else {
			return NULL;
		}
	}
	return NULL;

}
Esempio n. 20
0
LPTSTR CBuffer::Read()
{
	CSingleLock sLock(&m_mutex);
	sLock.Lock();
	CString strBuf = m_strBuf;
	// normalize line ends
	strBuf.Replace("\r\n", "\n");
	strBuf.Replace("\n", "\r\n");
	LPTSTR lpszStr = new TCHAR[strBuf.GetLength()+1];
	strcpy(lpszStr, strBuf);
	m_strBuf.Empty();
	sLock.Unlock();
	return lpszStr;
}
Esempio n. 21
0
void InStream::routeUpdateHook() {
	AutoMutex dLock(mDev.mLock);
	AutoMutex sLock(mLock);
	int newDevices = -1;
	mParameters.get(AUDIO_PARAMETER_STREAM_ROUTING, newDevices);
	if (mDevices != newDevices && newDevices != -1) {
		ALOGD("Devices changed from 0x%08x to 0x%08x", mDevices, newDevices);
		mDevices = (audio_devices_t) newDevices;
		mDbgStr.clear();
		deviceUpdatePrepare();
		deviceUpdateFinish();
	}
	else
		ALOGE("Bogus device update 0x%08x", newDevices);
}
Esempio n. 22
0
bool CKnownFileList::Init()
{
	CFile file;

	CPath fullpath = CPath(theApp->ConfigDir + m_filename);
	if (!fullpath.FileExists()) {
		// This is perfectly normal. The file was probably either
		// deleted, or this is the first time running aMule.
		return false;
	}

	if (!file.Open(fullpath)) {
		AddLogLineC(CFormat(_("WARNING: %s cannot be opened.")) % m_filename);
		return false;
	}

	try {
		uint8 version = file.ReadUInt8();
		if ((version != MET_HEADER) && (version != MET_HEADER_WITH_LARGEFILES)) {
			AddLogLineC(_("WARNING: Known file list corrupted, contains invalid header."));
			return false;
		}

		wxMutexLocker sLock(list_mut);
		uint32 RecordsNumber = file.ReadUInt32();
		AddDebugLogLineN(logKnownFiles, CFormat(wxT("Reading %i known files from file format 0x%2.2x."))
			% RecordsNumber % version);
		for (uint32 i = 0; i < RecordsNumber; i++) {
			CScopedPtr<CKnownFile> record;
			if (record->LoadFromFile(&file)) {
				AddDebugLogLineN(logKnownFiles,
					CFormat(wxT("Known file read: %s")) % record->GetFileName());
				Append(record.release());
			} else {
				AddLogLineC(_("Failed to load entry in known file list, file may be corrupt"));
			}
		}
		AddDebugLogLineN(logKnownFiles, wxT("Finished reading known files"));

		return true;
	} catch (const CInvalidPacket& e) {
		AddLogLineC(_("Invalid entry in known file list, file may be corrupt: ") + e.what());
	} catch (const CSafeIOException& e) {
		AddLogLineC(CFormat(_("IO error while reading %s file: %s")) % m_filename % e.what());
	}

	return false;
}
Esempio n. 23
0
    void Observable::notifyObservers() {
        if (settings_.updatesEnabled()) {
            return (*sig_)();
        }

        boost::lock_guard<boost::mutex> sLock(settings_.mutex_);
        if (settings_.updatesEnabled()) {
            return (*sig_)();
        }
        else if (settings_.updatesDeferred()) {
            boost::lock_guard<boost::recursive_mutex> lock(mutex_);
            // if updates are only deferred, flag this for later notification
            // these are held centrally by the settings singleton
            settings_.registerDeferredObservers(observers_);
        }
    }
Esempio n. 24
0
BOOL CTcpSocket::HandleOutputEvent()
{
	if (!m_bWriteOk)
	{	// Wait for next FD_WRITE
		return TRUE;
	}

	BOOL bRet = TRUE;
	CSingleLock sLock(&m_critical);
	WSABUF * p;
	DWORD dwBytesSent;					// needed in WSASend
	int err;

	sLock.Lock();
	while (!m_sendQueue.IsEmpty() && m_bWriteOk)
	{
		p = m_sendQueue.RemoveHead();
		err = WSASend(m_socket, p, 1, &dwBytesSent, 0, NULL, NULL);
		if (err == SOCKET_ERROR) 
		{
			err = WSAGetLastError();
			m_bWriteOk = FALSE;
			if (err == WSAEWOULDBLOCK) 
			{	//  WSAEWOULDBLOCK means we have to wait for an FD_WRITE before we can send.
				m_sendQueue.AddHead(p);
			}
			else 
			{
				OutputDebugString(_T("Unexpected error with WSASend\n"));
				bRet = FALSE;
				free(p->buf);
				free(p);
			}
		}
		else
		{
			if (dwBytesSent != p->len)
			{
				OutputDebugString(_T("Not all data sent out in CTcpSocket::HandleOutputEvent()!\n"));
			}
			free(p->buf);
			free(p);
		}
	}
	sLock.Unlock();
	return bRet;
}
Esempio n. 25
0
    void Observable::unregisterObserver(
        const ext::shared_ptr<Observer::Proxy>& observerProxy) {
        {
            boost::lock_guard<boost::recursive_mutex> lock(mutex_);
            observers_.erase(observerProxy);
        }

        if (settings_.updatesDeferred()) {
            boost::lock_guard<boost::mutex> sLock(settings_.mutex_);
            if (settings_.updatesDeferred()) {
                settings_.unregisterDeferredObserver(observerProxy);
            }
        }

        sig_->disconnect(ext::bind(&Observer::Proxy::update,
                             observerProxy.get()));
    }
Esempio n. 26
0
void CKnownFileList::Save()
{
	CFile file(theApp->ConfigDir + m_filename, CFile::write_safe);
	if (!file.IsOpened()) {
		return;
	}

	wxMutexLocker sLock(list_mut);
	AddDebugLogLineN(logKnownFiles, CFormat(wxT("start saving %s")) % m_filename);

	try {
		// Kry - This is the version, but we don't know it till
		// we know if any largefile is saved. This allows the list
		// to be compatible with previous versions.
		bool bContainsAnyLargeFiles = false;
		file.WriteUInt8(0);

		file.WriteUInt32(m_knownFileMap.size() + m_duplicateFileList.size());

		// Duplicates handling. Duplicates needs to be saved first,
		// since it is the last entry that gets used.
		KnownFileList::iterator itDup = m_duplicateFileList.begin();
		for ( ; itDup != m_duplicateFileList.end(); ++itDup ) {
			(*itDup)->WriteToFile(&file);
			if ((*itDup)->IsLargeFile()) {
				bContainsAnyLargeFiles = true;
			}
		}

		CKnownFileMap::iterator it = m_knownFileMap.begin();
		for (; it != m_knownFileMap.end(); ++it) {
			it->second->WriteToFile(&file);
			if (it->second->IsLargeFile()) {
				bContainsAnyLargeFiles = true;
			}
		}

		file.Seek(0);
		file.WriteUInt8(bContainsAnyLargeFiles ? MET_HEADER_WITH_LARGEFILES : MET_HEADER);
		file.Close();
	} catch (const CIOFailureException& e) {
		AddLogLineC(CFormat(_("Error while saving %s file: %s")) % m_filename % e.what());
	}
	AddDebugLogLineN(logKnownFiles, CFormat(wxT("finished saving %s")) % m_filename);
}
Esempio n. 27
0
//把backbuf的内容写入文件,如果有内容的话
VOID CLogFile::WriteBackBufToFile()
{
    CSmartLock sLock(m_lock);

    CheckLogFileStat();

    if (m_bBackBufAvailable)
    {
        std::ofstream logFile;
        logFile.open(m_szLogFileName, std::ios::app);
        INT outLen = strlen(m_pBackBuf);
        logFile.write(m_pBackBuf, (outLen>LOG_BUF_LEN)?LOG_BUF_LEN:outLen);
        logFile.close();

        *m_pBackBuf = '\0';
        m_bBackBufAvailable = FALSE;
    }
}
Esempio n. 28
0
//front 和 back 缓冲区,都写入文件
VOID CLogFile::WriteAllBufToFile()
{
    CSmartLock sLock(m_lock);

    CheckLogFileStat();

    std::ofstream logFile;
    if (m_bBackBufAvailable)
    {
        logFile.open(m_szLogFileName, std::ios::app);
        INT outLen = strlen(m_pBackBuf);
        logFile.write(m_pBackBuf, (outLen>LOG_BUF_LEN)?LOG_BUF_LEN:outLen);
        *m_pBackBuf = '\0';

        if (*m_pFrontBuf != '\0' && m_pWriteBuf != m_pFrontBuf)
        {
            outLen = strlen(m_pFrontBuf);
            logFile.write(m_pFrontBuf, (outLen>LOG_BUF_LEN)?LOG_BUF_LEN:outLen);
            *m_pFrontBuf = '\0';
            m_pWriteBuf = m_pFrontBuf;
        }
        logFile.close();

        m_bBackBufAvailable = FALSE;
    }
    else
    {
        if (*m_pFrontBuf != '\0' && m_pWriteBuf != m_pFrontBuf)
        {
            logFile.open(m_szLogFileName, std::ios::app);
            INT outLen = strlen(m_pFrontBuf);
            logFile.write(m_pFrontBuf, (outLen>LOG_BUF_LEN)?LOG_BUF_LEN:outLen);
            logFile.close();
            *m_pFrontBuf = '\0';
            m_pWriteBuf = m_pFrontBuf;
        }
    }
}
Esempio n. 29
0
std::auto_ptr<mongo::DBClientCursor> MockRemoteDBServer::query(
    MockRemoteDBServer::InstanceID id,
    const string& ns,
    mongo::Query query,
    int nToReturn,
    int nToSkip,
    const BSONObj* fieldsToReturn,
    int queryOptions,
    int batchSize) {
    checkIfUp(id);

    if (_delayMilliSec > 0) {
        mongo::sleepmillis(_delayMilliSec);
    }

    checkIfUp(id);

    std::auto_ptr<mongo::DBClientCursor> cursor;

    scoped_spinlock sLock(_lock);
    _queryCount++;
    return cursor;
}
Esempio n. 30
0
///////////////////////////////////////////////////////////////////////////
// CTSPIConferenceCall::CanRemoveFromConference
//
// Return true/false indicating whether the call may be removed
// from the conference.
//
bool CTSPIConferenceCall::CanRemoveFromConference(CTSPICallAppearance* pCall) const
{
    // Validate that the call being removed is in the conference.
    if (!IsCallInConference (pCall))
        return false;

    // If our address doesn't allow removal of conference parties, then error out.
    DWORD dwRemoveType = GetAddressOwner()->GetAddressCaps()->dwRemoveFromConfCaps;
    if (dwRemoveType == LINEREMOVEFROMCONF_NONE)
        return false;

    // If only the last party can be removed, make sure this is the last entry in the 
    // conference list.
    else if (dwRemoveType == LINEREMOVEFROMCONF_LAST)
    {
		CEnterCode sLock(this);  // Synch access to object
		if (pCall != m_lstConference.back())
			return false;
	}
    
    // Looks like we can remove it.
    return true;
    
}// CTSPIConferenceCall::CanRemoveFromConference