mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-22 22:27:05 +00:00
209 lines
4.2 KiB
C++
209 lines
4.2 KiB
C++
//========= 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();
|
|
}
|
|
|
|
|