HRESULT CServer::OnDataRecieved()
{
   if (!m_pSocketServer)
   {
      return Error(L"Server hasn't been initialised - programming error!");
   }

   if (!m_pIDataInit || !m_pIData)
   {
      return Error(L"Internal error: failed to create Data object");
   }
   
   CCOMSocketServer::Socket *pSocket = m_pSocketServer->GetSocket();

   CIOBuffer *pBuffer = m_pSocketServer->GetBuffer();

   if (!pSocket || !pBuffer)
   {
      return Error(L"Internal error: pSocket or pBuffer is 0");
   }

   ISocket *pISocket = reinterpret_cast<ISocket*>(pSocket->GetUserPtr());

   HRESULT hr = m_pIDataInit->Init(pBuffer->GetBuffer(), pBuffer->GetUsed());

   if (SUCCEEDED(hr))
   {  
      Fire_OnDataReceived(pISocket, m_pIData);   // this can stall if the handler doesnt return - 
                                                 // the ATL implementation is difficult to multi thread...
   }

   return hr;
}
void CSocketServer::Write(
				   Socket *pSocket,
				   const char *pData,
				   size_t dataLength, 
				   bool thenShutdown)
{
	if ( !pSocket || !pData || dataLength <= 0 )
	{
		return;
	}
   /*
    * Post a write request to the iocp so that the actual socket write gets performed by
	* one of our IO threads...
	*/

   CIOBuffer *pBuffer = Allocate();
   
   /*
    * Call to unqualified virtual function
    */
#ifdef NETWORK_DEBUG
//{
   PreWrite( pSocket, pBuffer, pData, dataLength + PACK_HEADER_LEN + sizeof(BYTE) );
//}
#else
//{
   PreWrite( pSocket, pBuffer, pData, dataLength );
//}
#endif // NETWORK_DEBUG

   pBuffer->AddData( pData, dataLength );
   
#ifdef NETWORK_DEBUG
//{
	const BYTE *pPackData = pBuffer->GetBuffer();

	PACK_HEADER ph = {0};

	memcpy( (BYTE *)&ph, pPackData, PACK_HEADER_LEN );

	pBuffer->AddData( (BYTE *)&ph, PACK_HEADER_LEN );
	pBuffer->AddData( 0xAA );
//}
#endif // NETWORK_DEBUG

   pBuffer->SetUserData( IO_Write_Request );

   pSocket->AddRef();

   m_iocp.PostStatus( (ULONG_PTR)pSocket, thenShutdown, pBuffer );
}
int CSocketServer::Run()
{
	try
	{
		vector<WorkerThread *> workers;
		
		workers.reserve( m_numThreads );
		
		for ( size_t i = 0; i < m_numThreads; ++i )
		{
			/*
			 * Call to unqualified virtual function
			 */
			WorkerThread *pThread = CreateWorkerThread( m_iocp ); 
			
			workers.push_back( pThread );
			
			pThread->Start();
		}
		
		HANDLE handlesToWaitFor[2];
		
		handlesToWaitFor[0] = m_shutdownEvent.GetEvent();
		handlesToWaitFor[1] = m_acceptConnectionsEvent.GetEvent();
		
		while ( !m_shutdownEvent.Wait( 0 ) )
		{
			DWORD waitResult = ::WaitForMultipleObjects( 2, handlesToWaitFor, false, INFINITE );
			
			if ( waitResult == WAIT_OBJECT_0 )
			{
				/*
				 * Time to shutdown
				 */
				break;
			}
			else if ( waitResult == WAIT_OBJECT_0 + 1 )
			{
				/*
				 * accept connections
				 */
				
				while ( !m_shutdownEvent.Wait( 0 ) && m_acceptConnectionsEvent.Wait( 0 ) )
				{
					CIOBuffer *pAddress = Allocate();
					
					int addressSize = (int)pAddress->GetSize();
					
					SOCKET acceptedSocket = ::WSAAccept(
									m_listeningSocket, 
									reinterpret_cast<sockaddr *>(const_cast<BYTE *>( pAddress->GetBuffer() ) ), 
									&addressSize, 
									0, 
									0);
					
					pAddress->Use( addressSize );
					
					if ( acceptedSocket != INVALID_SOCKET )
					{
						Socket *pSocket = AllocateSocket( acceptedSocket );
						
						/*
						 * Call to unqualified virtual function
						 */
						OnConnectionEstablished( pSocket, pAddress );
					}
					else if ( m_acceptConnectionsEvent.Wait( 0 ) )
					{
						/*
						 * Call to unqualified virtual function
						 */
						OnError( _T("CSocketServer::Run() - WSAAccept:") + GetLastErrorMessage( ::WSAGetLastError() ) );
					}
					
					pAddress->Release();
				}
			}
			else
			{
				/*
				 * Call to unqualified virtual function
				 */
				OnError( _T("CSocketServer::Run() - WaitForMultipleObjects: ") + GetLastErrorMessage( ::GetLastError() ) );
			}
		}
		
		for ( i = 0; i < m_numThreads; ++i )
		{
			workers[i]->InitiateShutdown();
		}  
		
		for ( i = 0; i < m_numThreads; ++i )
		{
			workers[i]->WaitForShutdownToComplete();
			
			delete workers[i];
			
			workers[i] = 0;
		}  
	}
	catch( const CException &e )
	{
		/*
		 * Call to unqualified virtual function
		 */
		OnError( _T("CSocketServer::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
	}
	catch(...)
	{
		/*
		 * Call to unqualified virtual function
		 */
		OnError( _T("CSocketServer::Run() - Unexpected exception") );
	}
	
	/*
	 * Call to unqualified virtual function
	 */
	OnShutdownComplete();
	
	return 0;
}