BOOL CLpxStreamListener::GetAcceptResult( OUT SOCKADDR_LPX* lpLocalAddr, OUT SOCKADDR_LPX* lpRemoteAddr, OUT LPDWORD lpcbReceived, OUT CONST BYTE** ppbData, OUT LPDWORD lpdwFlags /* = NULL */) { BOOL fSuccess = ::WSAGetOverlappedResult( m_sock, &m_ovReceive, lpcbReceived, TRUE, lpdwFlags); if (!fSuccess) { XTLTRACE("CLpxStreamListener.WSAGetOverlappedResult failed, error=0x%X\n", GetLastError()); return FALSE; } *ppbData = (CONST BYTE*) m_wsaReceiveBuffer.buf; SOCKADDR_LPX *pLocalAddr, *pRemoteAddr; INT iLocalAddrLen, iRemoteAddrLen; LPFN_GETACCEPTEXSOCKADDRS lpfnAcceptExSockaddrs = NULL; GUID GuidAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS; DWORD cbRead; INT iResult = ::WSAIoctl(m_sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptExSockaddrs, sizeof(GuidAcceptExSockaddrs), &lpfnAcceptExSockaddrs, sizeof(lpfnAcceptExSockaddrs), &cbRead, NULL, NULL); if (NULL == lpfnAcceptExSockaddrs) { XTLTRACE("Cannot load AcceptEx function, error=0x%X\n", GetLastError()); return FALSE; } lpfnAcceptExSockaddrs( m_wsaReceiveBuffer.buf, m_wsaReceiveBuffer.len, sizeof(SOCKADDR_LPX) + 16, sizeof(SOCKADDR_LPX) + 16, (sockaddr**) &pLocalAddr, &iLocalAddrLen, (sockaddr**) &pRemoteAddr, &iRemoteAddrLen); *lpLocalAddr = *pLocalAddr; *lpRemoteAddr = *pRemoteAddr; return TRUE; }
BOOL CLpxStreamConnection::Connect( CONST SOCKADDR_LPX* pRemoteAddr, CONST BYTE* lpSendBuffer, DWORD dwSendDataLen, LPDWORD lpcbSent) { _ASSERTE(INVALID_SOCKET != m_sock); ResetSendOverlapped(); LPFN_CONNECTEX lpfnConnectEx = NULL; GUID GuidConnectEx = WSAID_CONNECTEX; DWORD cbRead; INT iResult = ::WSAIoctl(m_sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidConnectEx, sizeof(GuidConnectEx), &lpfnConnectEx, sizeof(lpfnConnectEx), &cbRead, NULL, NULL); if (NULL == lpfnConnectEx) { XTLTRACE("Cannot load ConnectEx function, error=0x%X\n", GetLastError()); return FALSE; } BOOL fSuccess = lpfnConnectEx( m_sock, (const sockaddr*) pRemoteAddr, sizeof(SOCKADDR_LPX), (PVOID) lpSendBuffer, dwSendDataLen, lpcbSent, &m_ovSend); if (fSuccess) { fSuccess = ::SetEvent(m_hSentEvent); _ASSERTE(fSuccess); return TRUE; } if (ERROR_IO_PENDING != ::WSAGetLastError()) { XTLTRACE("CLpxStreamConnection.ConnectEx failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), WSAGetLastError()); return FALSE; } return TRUE; }
BOOL CLpxDatagramBroadcastSocket::Create() { BOOL fSuccess = CLpxDatagramSocket::Create(); if (!fSuccess) { return FALSE; } BOOL bBroadcast = TRUE; fSuccess = CLpxAsyncSocket::SetSockOpt( SO_BROADCAST, (CONST BYTE*) &bBroadcast, sizeof(bBroadcast)); if (!fSuccess) { DWORD error = GetLastError(); (void) CLpxAsyncSocket::Close(); XTLTRACE("Setting opt to SO_BROADCAST failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), error); return FALSE; } return TRUE; }
BOOL CLpxAsyncSocket::_GetRecvResult( OUT LPDWORD lpcbReceived, OUT BYTE** ppbData, OUT LPDWORD lpdwFlags /* = NULL */) { DWORD cbReceived = 0; DWORD dwFlags = 0; BOOL fSuccess = ::WSAGetOverlappedResult( m_sock, &m_ovReceive, &cbReceived, TRUE, &dwFlags); if (!fSuccess) { XTLTRACE("GetRecvResult.WSAGetOverlappedResult failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } *ppbData = (BYTE*)m_wsaReceiveBuffer.buf; if (lpcbReceived) *lpcbReceived = cbReceived; if (lpdwFlags) *lpdwFlags = dwFlags; return TRUE; }
BOOL CLpxAsyncSocket::AllocRecvBuf(DWORD cbSize) { if (cbSize > m_wsaReceiveBuffer.len) { if (NULL != m_wsaReceiveBuffer.buf) { m_wsaReceiveBuffer.buf = (char*) ::HeapReAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, m_wsaReceiveBuffer.buf, cbSize); } else { m_wsaReceiveBuffer.buf = (char*) ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize); } if (NULL == m_wsaReceiveBuffer.buf) { XTLTRACE("Allocating RecvBuf %d bytes failed, error=0x%X\n", cbSize, ERROR_OUTOFMEMORY); m_wsaReceiveBuffer.len = 0; SetLastError(ERROR_OUTOFMEMORY); return FALSE; } m_wsaReceiveBuffer.len = cbSize; } return TRUE; }
DWORD CNdasService::Impl::OnServiceShutdown() { XTLTRACE("System is shutting down...\n"); m_cLogDeviceManager.OnShutdown(); m_cDeviceEventHandler.OnShutdown(); XTLVERIFY( ::LfsFiltCtlShutdown() ); return NO_ERROR; }
BOOL CLpxSockAddrListChangeNotifier::Reset() { BOOL fSuccess = ::ResetEvent(m_hEvent); _ASSERT(fSuccess); if (INVALID_SOCKET != m_sock) { ::closesocket(m_sock); } // ::ZeroMemory(&m_overlapped, sizeof(WSAOVERLAPPED)); m_overlapped.Internal = m_overlapped.InternalHigh = m_overlapped.Offset = m_overlapped.OffsetHigh = 0; m_overlapped.hEvent = m_hEvent; XTL::AutoSocket sock = ::WSASocket( AF_LPX, SOCK_DGRAM, LPXPROTO_DGRAM, NULL, 0, WSA_FLAG_OVERLAPPED); if (INVALID_SOCKET == (SOCKET) sock) { return FALSE; } int iError; DWORD cbBytesReturned; iError = ::WSAIoctl( sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &cbBytesReturned, &m_overlapped, NULL); if (0 != iError && WSA_IO_PENDING != ::WSAGetLastError()) { // SOCKET_ERROR // TODO: Error Event Log from WSAGetLastError XTLTRACE("WSAIoctl SIO_ADDRESS_LIST_CHANGE failed, error=0x%X\n", GetLastError()); return FALSE; } m_sock = sock.Detach(); return TRUE; }
BOOL CLpxStreamListener::Listen(INT nBacklog /* = SOMAXCONN */) { _ASSERTE(INVALID_SOCKET != m_sock); INT iResult = ::listen(m_sock, nBacklog); if (0 != iResult) { XTLTRACE("CLpxStreamListener.listen failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), WSAGetLastError()); return FALSE; } return TRUE; }
BOOL CLpxAsyncSocket::ShutDown(INT nHow) { _ASSERTE(INVALID_SOCKET != m_sock); INT iResult = ::shutdown(m_sock, nHow); if (0 != iResult) { XTLTRACE("shutdown failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } return TRUE; }
BOOL CLpxSockAddrListChangeNotifier::Initialize() { if (NULL == m_hEvent) { m_hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); if (NULL == m_hEvent) { XTLTRACE("Creating a event failed, error=0x%X\n", GetLastError()); return FALSE; } } return TRUE; }
// #if WINVER >= 0x0501 BOOL CLpxStreamConnection::Disconnect(DWORD dwFlags) { _ASSERTE(INVALID_SOCKET != m_sock); LPFN_DISCONNECTEX lpfnDisconnectEx = NULL; GUID GuidDisconnectEx = WSAID_CONNECTEX; DWORD cbRead; INT iResult = ::WSAIoctl(m_sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidDisconnectEx, sizeof(GuidDisconnectEx), &lpfnDisconnectEx, sizeof(lpfnDisconnectEx), &cbRead, NULL, NULL); if (NULL == lpfnDisconnectEx) { XTLTRACE("Cannot load DisconnectEx function, error=0x%X\n", WSAGetLastError()); return FALSE; } BOOL fSuccess = lpfnDisconnectEx( m_sock, NULL, dwFlags, 0); if (!fSuccess) { XTLTRACE("DisconnectEx failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), WSAGetLastError()); return FALSE; } return TRUE; }
BOOL CLpxDatagramSocket::GetSendToResult(LPDWORD lpcbSent) { BOOL fSuccess = CLpxAsyncSocket::_GetSendResult(lpcbSent); if (!fSuccess) { XTLTRACE("CLpxDatagramSocket._GetSendResult failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } UnlockSendQueue(); return TRUE; }
BOOL CLpxDatagramSocket::SendToSync( CONST SOCKADDR_LPX* pRemoteAddr, DWORD cbToSend, CONST BYTE* lpbData, DWORD dwSendFlags, LPDWORD lpcbSent) { BOOL fSuccess = SendTo(pRemoteAddr, cbToSend, lpbData, dwSendFlags); if (!fSuccess) { XTLTRACE("CLpxDatagramSocket.SendTo failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } fSuccess = GetSendToResult(lpcbSent); if (!fSuccess) { XTLTRACE("CLpxDatagramSocket.GetSendToResult failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } return TRUE; }
BOOL CLpxStreamConnection::Recv(DWORD cbBufferMax, LPDWORD lpdwFlags) { _ASSERTE(INVALID_SOCKET != m_sock); BOOL fSuccess = FALSE; DWORD cbReceived = 0; fSuccess = AllocRecvBuf(cbBufferMax); if (!fSuccess) { XTLTRACE("AllocRecvBuf failed, error=0x%X\n", GetLastError()); return FALSE; } ResetRecvOverlapped(); INT iResult = ::WSARecv( m_sock, &m_wsaReceiveBuffer, 1, &cbReceived, lpdwFlags, &m_ovReceive, NULL); if (0 != iResult && WSA_IO_PENDING != ::WSAGetLastError()) { XTLTRACE("CLpxStreamConnection.Recv failed, max bytes=%d, socket=%p, error=0x%X\n", cbBufferMax, reinterpret_cast<PVOID>(m_sock), WSAGetLastError()); return FALSE; } if (0 == iResult) { fSuccess = ::SetEvent(m_hReceivedEvent); _ASSERTE(fSuccess); return TRUE; } return TRUE; }
BOOL CLpxAsyncSocket::Bind(CONST SOCKADDR_LPX* pBindAddr) { _ASSERTE(INVALID_SOCKET != m_sock); INT iResult = ::bind( m_sock, (const sockaddr*) pBindAddr, sizeof(SOCKADDR_LPX)); if (0 != iResult) { XTLTRACE("CLpxAsyncSocket.bind failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } m_localAddr = *pBindAddr; return TRUE; }
BOOL CLpxAsyncSocket::Close() { _ASSERTE(INVALID_SOCKET != m_sock); // // We need to reset recv and send event // If there is a previous data is not fetched, // Data Received/Sent event will be fetched on a closed socket. // BOOL fSuccess = ::ResetEvent(m_hReceivedEvent); _ASSERTE(fSuccess); fSuccess = ::ResetEvent(m_hSentEvent); _ASSERTE(fSuccess); if (m_lSendQueueLocks > 0) { UnlockSendQueue(); _ASSERTE(0 == m_lSendQueueLocks); } if (m_lRecvQueueLocks > 0) { UnlockRecvQueue(); _ASSERTE(0 == m_lRecvQueueLocks); } // // Reset Queue Locks // m_lSendQueueLocks = 0; m_lRecvQueueLocks = 0; INT iResult = ::closesocket(m_sock); if (0 != iResult) { XTLTRACE("Closing a sock %p failed, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } m_sock = INVALID_SOCKET; return TRUE; }
BOOL CLpxAsyncSocket::CreateEx(INT nSocketType /* = SOCK_STREAM */) { _ASSERTE(INVALID_SOCKET == m_sock); _ASSERTE(SOCK_STREAM == nSocketType || SOCK_DGRAM == nSocketType); m_sock = ::WSASocket( AF_LPX, nSocketType, (nSocketType == SOCK_STREAM) ? LPXPROTO_STREAM : LPXPROTO_DGRAM, NULL, 0, WSA_FLAG_OVERLAPPED); if (INVALID_SOCKET == m_sock) { XTLTRACE("CLpxAsyncSocket.Creating a sock failed, error=0x%X\n", GetLastError()); return FALSE; } return TRUE; }
BOOL CLpxAsyncSocket::SetSockOpt( INT nOptName, CONST BYTE* lpOptVal, INT nOptLen, INT nLevel /* = SOL_SOCKET */) { _ASSERTE(INVALID_SOCKET != m_sock); INT iResult = ::setsockopt( m_sock, nLevel, nOptName, (const char*) lpOptVal, nOptLen); if (0 != iResult) { XTLTRACE("CLpxAsyncSocket.SetSockOpt failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } return TRUE; }
BOOL CLpxDatagramSocket::GetRecvFromResult( OUT SOCKADDR_LPX* pRemoteAddr, OUT LPDWORD lpcbReceived, OUT BYTE** ppbData, OUT LPDWORD lpdwFlags) { BOOL fSuccess = CLpxAsyncSocket::_GetRecvResult( lpcbReceived, ppbData, lpdwFlags); if (!fSuccess) { XTLTRACE("CLpxDatagramSocket._GetRecvResult failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } if (pRemoteAddr) *pRemoteAddr = m_remoteAddr; UnlockRecvQueue(); return TRUE; }
BOOL CLpxStreamConnection::Send( DWORD cbToSend, CONST BYTE* lpbData, DWORD dwFlags /* = 0 */) { _ASSERTE(INVALID_SOCKET != m_sock); BOOL fSuccess = FALSE; ResetSendOverlapped(); m_wsaSendBuffer.len = cbToSend; m_wsaSendBuffer.buf = (char*) lpbData; DWORD cbSent = 0; INT iResult = ::WSASend( m_sock, &m_wsaSendBuffer, 1, &cbSent, dwFlags, &m_ovSend, NULL); if (0 != iResult && WSA_IO_PENDING != ::WSAGetLastError()) { XTLTRACE("CLpxStreamConnection.Send failed, bytes=%d, socket=%p, error=0x%X\n", cbToSend, reinterpret_cast<PVOID>(m_sock), WSAGetLastError()); return FALSE; } if (0 == iResult) { fSuccess = ::SetEvent(m_hSentEvent); _ASSERTE(fSuccess); return TRUE; } return TRUE; }
BOOL CLpxAsyncSocket::_GetSendResult(LPDWORD lpcbSent) { DWORD dwFlags = 0; DWORD cbSent = 0; BOOL fSuccess = ::WSAGetOverlappedResult( m_sock, &m_ovSend, &cbSent, TRUE, &dwFlags); if (!fSuccess) { XTLTRACE("GetSendResult.WSAGetOverlappedResult failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), GetLastError()); return FALSE; } if (lpcbSent) *lpcbSent = cbSent; return fSuccess; }
BOOL CLpxStreamConnection::GetConnectResult( OUT LPDWORD lpcbSent) { _ASSERTE(INVALID_SOCKET != m_sock); BOOL fSuccess = _GetSendResult(lpcbSent); if (!fSuccess) { return FALSE; } fSuccess = CLpxAsyncSocket::SetSockOpt( SO_UPDATE_CONNECT_CONTEXT, NULL, 0); if (!fSuccess) { XTLTRACE("Setsockopt SO_UPDATE_ACCEPT_CONTEXT failed, socket=%p, error=0x%X\n", reinterpret_cast<PVOID>(m_sock), WSAGetLastError()); } return TRUE; }
DWORD CNdasCommandServer:: ThreadStart(LPVOID lpParam) { HANDLE hStopEvent = static_cast<HANDLE>(lpParam); CmdWorkItemVector workItems; workItems.reserve(MaxPipeInstances); size_t size = workItems.size(); XTLASSERT(0 == size); std::generate_n( std::back_inserter(workItems), MaxPipeInstances, pWorkItemPtrGenerator); size = workItems.size(); XTLASSERT(MaxPipeInstances == size); DWORD nWorkItems = 0; for (DWORD i = 0; i < MaxPipeInstances; ++i) { CmdWorkItemPtr p = workItems[i]; BOOL fSuccess = p->QueueUserWorkItemEx( this, &CNdasCommandServer::CommandProcessStart, hStopEvent, WT_EXECUTELONGFUNCTION); if (fSuccess) { ++nWorkItems; } else { XTLTRACE_ERR("Starting work item (%d/%d) failed.\n", i + 1, MaxPipeInstances); } } // Release semaphore to start workers (semaphore increment) LONG prev; XTLVERIFY( ::ReleaseSemaphore(m_hProcSemaphore, nWorkItems, &prev) ); XTLASSERT( 0 == prev ); // Wait for stop event XTLVERIFY(WAIT_OBJECT_0 == ::WaitForSingleObject(hStopEvent, INFINITE)); // Stopped and waits for user work items DWORD finished = 0; while (finished < nWorkItems) { ::Sleep(0); DWORD waitResult = ::WaitForSingleObject(m_hProcSemaphore, 0); if (waitResult == WAIT_OBJECT_0) { XTLTRACE("Command Process work item finished (%d/%d).\n", finished + 1, nWorkItems); ++finished; } XTLVERIFY(WAIT_OBJECT_0 == waitResult || WAIT_TIMEOUT == waitResult); } // Now Finally this thread can stop return 0; }
DWORD CNdasService::Impl::OnServiceStop() { ////////////////////////////////////////////////////////////////////////// // We should report the SCM that the service is stopping // Otherwise, the service will terminate the thread. // And we'll get ACCESS VIOLATION ERROR! ////////////////////////////////////////////////////////////////////////// XTLTRACE("Service is stopping...\n"); ReportServiceStopPending(1000); XTLVERIFY( ::SetEvent(m_hStopServiceEvent) ); // Yield to other threads to finish themselves. ::Sleep(0); ////////////////////////////////////////////////////////////////////////// // Wait for the command processor thread to stop ////////////////////////////////////////////////////////////////////////// XTLTRACE("Waiting for worker threads to stop....\n"); DWORD waitResult = WAIT_TIMEOUT; while (WAIT_OBJECT_0 != waitResult) { ReportServiceStopPending(3000); // yield to work threads for them to handle their terminations ::Sleep(0); waitResult = ::WaitForSingleObject(m_wiCmdServer.GetThreadHandle(), 3000); XTLVERIFY(WAIT_OBJECT_0 == waitResult || WAIT_TIMEOUT == waitResult); XTLTRACE("Waiting for command processors to stop in 3 seconds....\n"); } XTLTRACE("Command processors stopped....\n"); ////////////////////////////////////////////////////////////////////////// // Wait for the work items to stop ////////////////////////////////////////////////////////////////////////// DWORD finished = 0; while (finished < m_nWorkItems) { ReportServiceStopPending(1500); // yield to work threads for them to handle their terminations ::Sleep(0); DWORD waitResult = ::WaitForSingleObject(m_hWorkItemSemaphore, 1000); if (waitResult == WAIT_OBJECT_0) { ++finished; XTLTRACE("(%d/%d) WorkItems stopped...\n", finished, m_nWorkItems); } XTLVERIFY(WAIT_OBJECT_0 == waitResult || WAIT_TIMEOUT == waitResult); } ////////////////////////////////////////////////////////////////////////// // All threads and work items are done ////////////////////////////////////////////////////////////////////////// XTLTRACE("All work items stopped....\n"); XTLTRACE("Reporting to the SCM that the service is stopped....\n"); m_cDeviceEventHandler.Uninitialize(); m_cDeviceRegistrar.Cleanup(); m_cLogDeviceManager.Cleanup(); ReportServiceStopped(); return NO_ERROR; }
BOOL CLpxStreamListener::Accept(SOCKET sockAccept, DWORD cbDataBuffer) { _ASSERTE(INVALID_SOCKET != m_sock); _ASSERTE(INVALID_SOCKET != sockAccept); BOOL fSuccess = FALSE; DWORD cbBufReq = (sizeof(SOCKADDR_LPX) + 16) * 2 + cbDataBuffer; fSuccess = AllocRecvBuf(cbBufReq); if (!fSuccess) { XTLTRACE("AllocRecvBuf failed.\n"); return FALSE; } DWORD cbAcceptBuffer = m_wsaReceiveBuffer.len; PVOID pbAcceptBuffer = m_wsaReceiveBuffer.buf; ResetRecvOverlapped(); //---------------------------------------- // Load the AcceptEx function into memory using WSAIoctl. // The WSAIoctl function is an extension of the ioctlsocket() // function that can use overlapped I/O. The function's 3rd // through 6th parameters are input and output buffers where // we pass the pointer to our AcceptEx function. This is used // so that we can call the AcceptEx function directly, rather // than refer to the Mswsock.lib library. LPFN_ACCEPTEX lpfnAcceptEx = NULL; GUID GuidAcceptEx = WSAID_ACCEPTEX; DWORD cbRead; INT iResult = ::WSAIoctl(m_sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof(GuidAcceptEx), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &cbRead, NULL, NULL); if (NULL == lpfnAcceptEx) { XTLTRACE("Cannot load AcceptEx function, error=0x%X\n", GetLastError()); return FALSE; } DWORD cbReceived = 0; fSuccess = lpfnAcceptEx( m_sock, sockAccept, pbAcceptBuffer, cbDataBuffer, sizeof(SOCKADDR_LPX) + 16, sizeof(SOCKADDR_LPX) + 16, &cbReceived, &m_ovReceive); if (!fSuccess && ERROR_IO_PENDING != ::GetLastError()) { return FALSE; } iResult = ::setsockopt( sockAccept, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&m_sock, sizeof(m_sock)); if (0 != iResult) { XTLTRACE("Setting SO_UPDATE_ACCEPT_CONTEXT failed, error=0x%X\n", GetLastError()); } if (fSuccess) { ::SetEvent(m_hReceivedEvent); return TRUE; } return TRUE; }