Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "stdafx.h"
  7. #include "net_view_thread.h"
  8. char* CopyAlloc( const char *pStr )
  9. {
  10. char *pRet = new char[ strlen( pStr ) + 1];
  11. strcpy( pRet, pStr );
  12. return pRet;
  13. }
  14. CNetViewThread::CNetViewThread()
  15. {
  16. m_hThread = NULL;
  17. m_hThreadExitEvent = NULL;
  18. InitializeCriticalSection( &m_ComputerNamesCS );
  19. }
  20. CNetViewThread::~CNetViewThread()
  21. {
  22. Term();
  23. DeleteCriticalSection( &m_ComputerNamesCS );
  24. }
  25. void CNetViewThread::Init()
  26. {
  27. Term();
  28. m_hThreadExitEvent = CreateEvent( NULL, false, false, NULL );
  29. DWORD dwThreadID = 0;
  30. m_hThread = CreateThread(
  31. NULL,
  32. 0,
  33. &CNetViewThread::StaticThreadFn,
  34. this,
  35. 0,
  36. &dwThreadID );
  37. }
  38. void CNetViewThread::Term()
  39. {
  40. if ( m_hThread )
  41. {
  42. SetEvent( m_hThreadExitEvent );
  43. WaitForSingleObject( m_hThread, INFINITE );
  44. CloseHandle( m_hThread );
  45. m_hThread = NULL;
  46. }
  47. if ( m_hThreadExitEvent )
  48. {
  49. CloseHandle( m_hThreadExitEvent );
  50. m_hThreadExitEvent = NULL;
  51. }
  52. }
  53. void CNetViewThread::GetComputerNames( CUtlVector<char*> &computerNames )
  54. {
  55. EnterCriticalSection( &m_ComputerNamesCS );
  56. computerNames.Purge();
  57. for ( int i=0; i < m_ComputerNames.Count(); i++ )
  58. {
  59. computerNames.AddToTail( CopyAlloc( m_ComputerNames[i] ) );
  60. }
  61. LeaveCriticalSection( &m_ComputerNamesCS );
  62. }
  63. void CNetViewThread::UpdateServicesFromNetView()
  64. {
  65. HANDLE hChildStdoutRd, hChildStdoutWr;
  66. // Set the bInheritHandle flag so pipe handles are inherited.
  67. SECURITY_ATTRIBUTES saAttr;
  68. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  69. saAttr.bInheritHandle = TRUE;
  70. saAttr.lpSecurityDescriptor = NULL;
  71. if( CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0 ) )
  72. {
  73. STARTUPINFO si;
  74. memset(&si, 0, sizeof si);
  75. si.cb = sizeof(si);
  76. si.dwFlags = STARTF_USESTDHANDLES;
  77. si.hStdOutput = hChildStdoutWr;
  78. PROCESS_INFORMATION pi;
  79. if( CreateProcess(
  80. NULL,
  81. "net view",
  82. NULL, // lpProcessAttributes
  83. NULL, // lpThreadAttributes
  84. TRUE, // bInheritHandls
  85. DETACHED_PROCESS, // dwCreationFlags
  86. NULL, // lpEnvironment
  87. NULL, // lpCurrentDirectory
  88. &si, // lpStartupInfo
  89. &pi // lpProcessInformation
  90. ) )
  91. {
  92. // read from pipe..
  93. #define BUFFER_SIZE 8192
  94. char buffer[BUFFER_SIZE];
  95. BOOL bDone = FALSE;
  96. CUtlVector<char> totalBuffer;
  97. while(1)
  98. {
  99. DWORD dwCount = 0;
  100. DWORD dwRead = 0;
  101. // read from input handle
  102. PeekNamedPipe(hChildStdoutRd, NULL, NULL, NULL, &dwCount, NULL);
  103. if (dwCount)
  104. {
  105. dwCount = min (dwCount, (DWORD)BUFFER_SIZE - 1);
  106. ReadFile(hChildStdoutRd, buffer, dwCount, &dwRead, NULL);
  107. }
  108. if(dwRead)
  109. {
  110. buffer[dwRead] = 0;
  111. totalBuffer.AddMultipleToTail( dwRead, buffer );
  112. }
  113. // check process termination
  114. else if( WaitForSingleObject( pi.hProcess, 1000 ) != WAIT_TIMEOUT )
  115. {
  116. if ( bDone )
  117. break;
  118. bDone = TRUE; // next time we get it
  119. }
  120. }
  121. // Now parse the output.
  122. totalBuffer.AddToTail( 0 );
  123. ParseComputerNames( totalBuffer.Base() );
  124. }
  125. CloseHandle( hChildStdoutRd );
  126. CloseHandle( hChildStdoutWr );
  127. }
  128. }
  129. void CNetViewThread::ParseComputerNames( const char *pNetViewOutput )
  130. {
  131. EnterCriticalSection( &m_ComputerNamesCS );
  132. m_ComputerNames.PurgeAndDeleteElements();
  133. const char *pCur = pNetViewOutput;
  134. while ( *pCur != 0 )
  135. {
  136. // If we get a \\, then it's a computer name followed by whitespace.
  137. if ( pCur[0] == '\\' && pCur[1] == '\\' )
  138. {
  139. char curComputerName[512];
  140. char *pOutPos = curComputerName;
  141. pCur += 2;
  142. while ( *pCur && !V_isspace( *pCur ) && (pOutPos-curComputerName < 510) )
  143. {
  144. *pOutPos++ = *pCur++;
  145. }
  146. *pOutPos = 0;
  147. m_ComputerNames.AddToTail( CopyAlloc( curComputerName ) );
  148. }
  149. ++pCur;
  150. }
  151. LeaveCriticalSection( &m_ComputerNamesCS );
  152. }
  153. DWORD CNetViewThread::ThreadFn()
  154. {
  155. // Update the services list every 30 seconds.
  156. do
  157. {
  158. UpdateServicesFromNetView();
  159. } while ( WaitForSingleObject( m_hThreadExitEvent, 30000 ) != WAIT_OBJECT_0 );
  160. return 0;
  161. }
  162. DWORD CNetViewThread::StaticThreadFn( LPVOID lpParameter )
  163. {
  164. return ((CNetViewThread*)lpParameter)->ThreadFn();
  165. }