diff options
Diffstat (limited to 'utils/vmpi/net_view_thread.cpp')
| -rw-r--r-- | utils/vmpi/net_view_thread.cpp | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/utils/vmpi/net_view_thread.cpp b/utils/vmpi/net_view_thread.cpp new file mode 100644 index 0000000..19ab38d --- /dev/null +++ b/utils/vmpi/net_view_thread.cpp @@ -0,0 +1,208 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "stdafx.h" +#include "net_view_thread.h" + + +char* CopyAlloc( const char *pStr ) +{ + char *pRet = new char[ strlen( pStr ) + 1]; + strcpy( pRet, pStr ); + return pRet; +} + + +CNetViewThread::CNetViewThread() +{ + m_hThread = NULL; + m_hThreadExitEvent = NULL; + InitializeCriticalSection( &m_ComputerNamesCS ); +} + + +CNetViewThread::~CNetViewThread() +{ + Term(); + DeleteCriticalSection( &m_ComputerNamesCS ); +} + + +void CNetViewThread::Init() +{ + Term(); + + m_hThreadExitEvent = CreateEvent( NULL, false, false, NULL ); + + DWORD dwThreadID = 0; + m_hThread = CreateThread( + NULL, + 0, + &CNetViewThread::StaticThreadFn, + this, + 0, + &dwThreadID ); +} + + +void CNetViewThread::Term() +{ + if ( m_hThread ) + { + SetEvent( m_hThreadExitEvent ); + WaitForSingleObject( m_hThread, INFINITE ); + CloseHandle( m_hThread ); + m_hThread = NULL; + } + + if ( m_hThreadExitEvent ) + { + CloseHandle( m_hThreadExitEvent ); + m_hThreadExitEvent = NULL; + } +} + + +void CNetViewThread::GetComputerNames( CUtlVector<char*> &computerNames ) +{ + EnterCriticalSection( &m_ComputerNamesCS ); + + computerNames.Purge(); + for ( int i=0; i < m_ComputerNames.Count(); i++ ) + { + computerNames.AddToTail( CopyAlloc( m_ComputerNames[i] ) ); + } + + LeaveCriticalSection( &m_ComputerNamesCS ); +} + + +void CNetViewThread::UpdateServicesFromNetView() +{ + HANDLE hChildStdoutRd, hChildStdoutWr; + + // Set the bInheritHandle flag so pipe handles are inherited. + SECURITY_ATTRIBUTES saAttr; + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + if( CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0 ) ) + { + STARTUPINFO si; + memset(&si, 0, sizeof si); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = hChildStdoutWr; + + PROCESS_INFORMATION pi; + + if( CreateProcess( + NULL, + "net view", + NULL, // lpProcessAttributes + NULL, // lpThreadAttributes + TRUE, // bInheritHandls + DETACHED_PROCESS, // dwCreationFlags + NULL, // lpEnvironment + NULL, // lpCurrentDirectory + &si, // lpStartupInfo + &pi // lpProcessInformation + ) ) + { + // read from pipe.. + #define BUFFER_SIZE 8192 + char buffer[BUFFER_SIZE]; + BOOL bDone = FALSE; + CUtlVector<char> totalBuffer; + + while(1) + { + DWORD dwCount = 0; + DWORD dwRead = 0; + + // read from input handle + PeekNamedPipe(hChildStdoutRd, NULL, NULL, NULL, &dwCount, NULL); + if (dwCount) + { + dwCount = min (dwCount, (DWORD)BUFFER_SIZE - 1); + ReadFile(hChildStdoutRd, buffer, dwCount, &dwRead, NULL); + } + if(dwRead) + { + buffer[dwRead] = 0; + totalBuffer.AddMultipleToTail( dwRead, buffer ); + } + // check process termination + else if( WaitForSingleObject( pi.hProcess, 1000 ) != WAIT_TIMEOUT ) + { + if ( bDone ) + break; + + bDone = TRUE; // next time we get it + } + } + + // Now parse the output. + totalBuffer.AddToTail( 0 ); + ParseComputerNames( totalBuffer.Base() ); + } + + CloseHandle( hChildStdoutRd ); + CloseHandle( hChildStdoutWr ); + } +} + + +void CNetViewThread::ParseComputerNames( const char *pNetViewOutput ) +{ + EnterCriticalSection( &m_ComputerNamesCS ); + + m_ComputerNames.PurgeAndDeleteElements(); + + const char *pCur = pNetViewOutput; + while ( *pCur != 0 ) + { + // If we get a \\, then it's a computer name followed by whitespace. + if ( pCur[0] == '\\' && pCur[1] == '\\' ) + { + char curComputerName[512]; + char *pOutPos = curComputerName; + + pCur += 2; + while ( *pCur && !V_isspace( *pCur ) && (pOutPos-curComputerName < 510) ) + { + *pOutPos++ = *pCur++; + } + *pOutPos = 0; + + m_ComputerNames.AddToTail( CopyAlloc( curComputerName ) ); + } + ++pCur; + } + + LeaveCriticalSection( &m_ComputerNamesCS ); +} + + +DWORD CNetViewThread::ThreadFn() +{ + // Update the services list every 30 seconds. + do + { + UpdateServicesFromNetView(); + } while ( WaitForSingleObject( m_hThreadExitEvent, 30000 ) != WAIT_OBJECT_0 ); + + return 0; +} + + +DWORD CNetViewThread::StaticThreadFn( LPVOID lpParameter ) +{ + return ((CNetViewThread*)lpParameter)->ThreadFn(); +} + + |