You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
4.2 KiB
208 lines
4.2 KiB
//========= 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(); |
|
} |
|
|
|
|
|
|