mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-17 06:03:02 +00:00
1
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// vmpi_service.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -0,0 +1,35 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if !defined(AFX_STDAFX_H__A1923E9A_F174_4448_8004_33888CD7DC88__INCLUDED_)
|
||||
#define AFX_STDAFX_H__A1923E9A_F174_4448_8004_33888CD7DC88__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <shellapi.h>
|
||||
#include <winuser.h>
|
||||
#include "basetypes.h"
|
||||
#include <stdio.h>
|
||||
#include "iphelpers.h"
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__A1923E9A_F174_4448_8004_33888CD7DC88__INCLUDED_)
|
||||
@@ -0,0 +1,500 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "tier1/utldict.h"
|
||||
#include <pdh.h>
|
||||
#include <pdhmsg.h>
|
||||
#include "perf_counters.h"
|
||||
|
||||
|
||||
#if 1
|
||||
|
||||
class CPerfTracker : public IPerfTracker
|
||||
{
|
||||
public:
|
||||
|
||||
CPerfTracker()
|
||||
{
|
||||
m_hProcessorTimeCounter = NULL;
|
||||
m_dwProcessID = 0;
|
||||
if ( PdhOpenQuery( NULL, 0, &m_hQuery ) != ERROR_SUCCESS )
|
||||
m_hQuery = NULL;
|
||||
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo( &info );
|
||||
m_nProcessors = (int)info.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
~CPerfTracker()
|
||||
{
|
||||
if ( m_hQuery )
|
||||
PdhCloseQuery( m_hQuery );
|
||||
}
|
||||
|
||||
virtual void Init( unsigned long dwProcessID )
|
||||
{
|
||||
Term();
|
||||
|
||||
m_dwProcessID = dwProcessID;
|
||||
|
||||
char instanceName[512];
|
||||
if ( GetInstanceNameFromProcessID( m_dwProcessID, instanceName, sizeof( instanceName ) ) )
|
||||
{
|
||||
// Create a counter to watch this process' time.
|
||||
char str[512];
|
||||
V_snprintf( str, sizeof( str ), "\\Process(%s)\\%% Processor Time", instanceName );
|
||||
if ( PdhAddCounter( m_hQuery, str, 0, &m_hProcessorTimeCounter ) != ERROR_SUCCESS )
|
||||
{
|
||||
m_hProcessorTimeCounter = NULL;
|
||||
}
|
||||
|
||||
V_snprintf( str, sizeof( str ), "\\Process(%s)\\Private Bytes", instanceName );
|
||||
if ( PdhAddCounter( m_hQuery, str, 0, &m_hPrivateBytesCounter ) != ERROR_SUCCESS )
|
||||
{
|
||||
m_hPrivateBytesCounter = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Term()
|
||||
{
|
||||
if ( m_hProcessorTimeCounter )
|
||||
PdhRemoveCounter( m_hProcessorTimeCounter );
|
||||
|
||||
if ( m_hPrivateBytesCounter )
|
||||
PdhRemoveCounter( m_hPrivateBytesCounter );
|
||||
|
||||
m_hProcessorTimeCounter = NULL;
|
||||
m_hPrivateBytesCounter = NULL;
|
||||
}
|
||||
|
||||
virtual void Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual unsigned long GetProcessID()
|
||||
{
|
||||
return m_dwProcessID;
|
||||
}
|
||||
|
||||
virtual void GetPerfData( int &processorPercentage, int &memoryUsageMegabytes )
|
||||
{
|
||||
processorPercentage = 101;
|
||||
memoryUsageMegabytes = 0;
|
||||
|
||||
// Collect query data..
|
||||
PDH_STATUS ret = PdhCollectQueryData( m_hQuery );
|
||||
if ( ret != ERROR_SUCCESS )
|
||||
return;
|
||||
|
||||
// Check processor usage.
|
||||
DWORD dwType;
|
||||
PDH_FMT_COUNTERVALUE counterValue;
|
||||
if ( PdhGetFormattedCounterValue( m_hProcessorTimeCounter, PDH_FMT_LONG | PDH_FMT_NOCAP100, &dwType, &counterValue ) == ERROR_SUCCESS )
|
||||
processorPercentage = counterValue.longValue / m_nProcessors;
|
||||
else
|
||||
processorPercentage = 101;
|
||||
|
||||
// Check memory usage.
|
||||
if ( PdhGetFormattedCounterValue( m_hPrivateBytesCounter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &dwType, &counterValue ) == ERROR_SUCCESS )
|
||||
memoryUsageMegabytes = (int)(counterValue.doubleValue / (1024.0 * 1024.0));
|
||||
else
|
||||
memoryUsageMegabytes = 0;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool GetInstanceNameFromProcessID( DWORD processID, char *instanceName, int instanceNameLen )
|
||||
{
|
||||
instanceName[0] = 0;
|
||||
|
||||
bool bRet = false;
|
||||
|
||||
// This refreshes the object list. If we don't do this, it won't get new process IDs correctly.
|
||||
DWORD dummy = 0;
|
||||
PdhEnumObjects( NULL, NULL, NULL, &dummy, PERF_DETAIL_NOVICE, true );
|
||||
|
||||
// Find out how much data we need.
|
||||
DWORD counterListLen=2, instanceListLen=2;
|
||||
char *counterList = new char[counterListLen];
|
||||
char *instanceList = new char[instanceListLen];
|
||||
PDH_STATUS stat = PdhEnumObjectItems( NULL, NULL, "Process", counterList, &counterListLen, instanceList, &instanceListLen, PERF_DETAIL_NOVICE, 0 );
|
||||
if ( stat == PDH_MORE_DATA )
|
||||
{
|
||||
delete [] counterList;
|
||||
delete [] instanceList;
|
||||
char *counterList = new char[counterListLen];
|
||||
char *instanceList = new char[instanceListLen];
|
||||
|
||||
stat = PdhEnumObjectItems( NULL, NULL, "Process", counterList, &counterListLen, instanceList, &instanceListLen, PERF_DETAIL_NOVICE, 0 );
|
||||
if ( stat == ERROR_SUCCESS )
|
||||
{
|
||||
// We need the # of each one..
|
||||
CUtlDict<int,int> counts;
|
||||
|
||||
// The instance name list is a bunch of strings terminated with nulls. The final one has two nulls after it.
|
||||
// Walk through the list and get the process ID associated with each instance name.
|
||||
const char *pCur = instanceList;
|
||||
while ( *pCur )
|
||||
{
|
||||
int index = counts.Find( pCur );
|
||||
if ( index == counts.InvalidIndex() )
|
||||
counts.Insert( pCur, 1 );
|
||||
else
|
||||
counts[index]++;
|
||||
|
||||
pCur += strlen( pCur ) + 1;
|
||||
}
|
||||
|
||||
// Each instance (like "vrad") might have multiple versions, like if you're running multiple vrad processes at the same time.
|
||||
for ( int i=counts.First(); i != counts.InvalidIndex(); i=counts.Next( i ) )
|
||||
{
|
||||
const char *pInstanceName = counts.GetElementName( i );
|
||||
int nInstances = counts[i];
|
||||
for ( int iInstance=0; iInstance < nInstances; iInstance++ )
|
||||
{
|
||||
char testInstanceName[256], fullObjectName[256];
|
||||
V_snprintf( testInstanceName, sizeof( testInstanceName ), "%s#%d", pInstanceName, iInstance );
|
||||
V_snprintf( fullObjectName, sizeof( fullObjectName ), "\\Process(%s)\\ID Process", testInstanceName );
|
||||
|
||||
HCOUNTER hCounter = NULL;
|
||||
stat = PdhAddCounter( m_hQuery, fullObjectName, 0, &hCounter );
|
||||
if ( stat == ERROR_SUCCESS )
|
||||
{
|
||||
stat = PdhCollectQueryData( m_hQuery );
|
||||
if ( stat == ERROR_SUCCESS )
|
||||
{
|
||||
DWORD dwType;
|
||||
PDH_FMT_COUNTERVALUE counterValue;
|
||||
stat = PdhGetFormattedCounterValue( hCounter, PDH_FMT_LONG, &dwType, &counterValue );
|
||||
if ( stat == 0 && counterValue.longValue == (long)processID )
|
||||
{
|
||||
// Finall! We found it.
|
||||
V_strncpy( instanceName, testInstanceName, instanceNameLen );
|
||||
bRet = true;
|
||||
PdhRemoveCounter( hCounter );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PdhRemoveCounter( hCounter );
|
||||
}
|
||||
}
|
||||
|
||||
if ( bRet )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] counterList;
|
||||
delete [] instanceList;
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
private:
|
||||
DWORD m_dwProcessID;
|
||||
PDH_HQUERY m_hQuery;
|
||||
HCOUNTER m_hProcessorTimeCounter;
|
||||
HCOUNTER m_hPrivateBytesCounter;
|
||||
int m_nProcessors;
|
||||
};
|
||||
|
||||
|
||||
IPerfTracker* CreatePerfTracker()
|
||||
{
|
||||
return new CPerfTracker;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#include <winperf.h>
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------- //
|
||||
// NOTE: THIS IS THE OLD, UGLY WAY TO DO IT.
|
||||
// --------------------------------------------------------------------------------------------------------------------- //
|
||||
|
||||
class CPerfTracker
|
||||
{
|
||||
public:
|
||||
CPerfTracker();
|
||||
void Init( unsigned long dwProcessID );
|
||||
|
||||
unsigned long GetProcessID();
|
||||
|
||||
// Get the percentage of CPU time that the process is using.
|
||||
int GetCPUPercentage();
|
||||
|
||||
private:
|
||||
DWORD m_dwProcessID;
|
||||
LONGLONG m_lnOldValue;
|
||||
LARGE_INTEGER m_OldPerfTime100nSec;
|
||||
int m_nProcessors;
|
||||
};
|
||||
|
||||
#define TOTALBYTES 100*1024
|
||||
#define BYTEINCREMENT 10*1024
|
||||
|
||||
#define SYSTEM_OBJECT_INDEX 2 // 'System' object
|
||||
#define PROCESS_OBJECT_INDEX 230 // 'Process' object
|
||||
#define PROCESSOR_OBJECT_INDEX 238 // 'Processor' object
|
||||
#define TOTAL_PROCESSOR_TIME_COUNTER_INDEX 240 // '% Total processor time' counter (valid in WinNT under 'System' object)
|
||||
#define PROCESSOR_TIME_COUNTER_INDEX 6 // '% processor time' counter (for Win2K/XP)
|
||||
|
||||
|
||||
//
|
||||
// The performance data is accessed through the registry key
|
||||
// HKEY_PEFORMANCE_DATA.
|
||||
// However, although we use the registry to collect performance data,
|
||||
// the data is not stored in the registry database.
|
||||
// Instead, calling the registry functions with the HKEY_PEFORMANCE_DATA key
|
||||
// causes the system to collect the data from the appropriate system
|
||||
// object managers.
|
||||
//
|
||||
// QueryPerformanceData allocates memory block for getting the
|
||||
// performance data.
|
||||
//
|
||||
//
|
||||
void QueryPerformanceData(PERF_DATA_BLOCK **pPerfData, DWORD dwObjectIndex, DWORD dwCounterIndex)
|
||||
{
|
||||
//
|
||||
// Since i want to use the same allocated area for each query,
|
||||
// i declare CBuffer as static.
|
||||
// The allocated is changed only when RegQueryValueEx return ERROR_MORE_DATA
|
||||
//
|
||||
static CUtlVector<char> Buffer;
|
||||
if ( Buffer.Count() == 0 )
|
||||
Buffer.SetSize( TOTALBYTES );
|
||||
|
||||
DWORD BufferSize = Buffer.Count();
|
||||
LONG lRes;
|
||||
|
||||
char keyName[32];
|
||||
V_snprintf(keyName, sizeof(keyName), "%d",dwObjectIndex);
|
||||
|
||||
memset( Buffer.Base(), 0, Buffer.Count() );
|
||||
while( (lRes = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
|
||||
keyName,
|
||||
NULL,
|
||||
NULL,
|
||||
(LPBYTE)Buffer.Base(),
|
||||
&BufferSize )) == ERROR_MORE_DATA )
|
||||
{
|
||||
// Get a buffer that is big enough.
|
||||
BufferSize += BYTEINCREMENT;
|
||||
Buffer.SetSize( BufferSize );
|
||||
}
|
||||
|
||||
*pPerfData = (PPERF_DATA_BLOCK)Buffer.Base();
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* *
|
||||
* Functions used to navigate through the performance data. *
|
||||
* *
|
||||
*****************************************************************/
|
||||
|
||||
inline PPERF_OBJECT_TYPE FirstObject( PPERF_DATA_BLOCK PerfData )
|
||||
{
|
||||
return( (PPERF_OBJECT_TYPE)((PBYTE)PerfData + PerfData->HeaderLength) );
|
||||
}
|
||||
|
||||
inline PPERF_OBJECT_TYPE NextObject( PPERF_OBJECT_TYPE PerfObj )
|
||||
{
|
||||
return( (PPERF_OBJECT_TYPE)((PBYTE)PerfObj + PerfObj->TotalByteLength) );
|
||||
}
|
||||
|
||||
inline PPERF_COUNTER_DEFINITION FirstCounter( PPERF_OBJECT_TYPE PerfObj )
|
||||
{
|
||||
return( (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj + PerfObj->HeaderLength) );
|
||||
}
|
||||
|
||||
inline PPERF_COUNTER_DEFINITION NextCounter( PPERF_COUNTER_DEFINITION PerfCntr )
|
||||
{
|
||||
return( (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr + PerfCntr->ByteLength) );
|
||||
}
|
||||
|
||||
inline PPERF_INSTANCE_DEFINITION FirstInstance( PPERF_OBJECT_TYPE PerfObj )
|
||||
{
|
||||
return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj + PerfObj->DefinitionLength) );
|
||||
}
|
||||
|
||||
inline PPERF_INSTANCE_DEFINITION NextInstance( PPERF_INSTANCE_DEFINITION PerfInst )
|
||||
{
|
||||
PPERF_COUNTER_BLOCK PerfCntrBlk;
|
||||
|
||||
PerfCntrBlk = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst + PerfInst->ByteLength);
|
||||
|
||||
return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfCntrBlk + PerfCntrBlk->ByteLength) );
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
T GetCounterValueForProcessID(PPERF_OBJECT_TYPE pPerfObj, DWORD dwCounterIndex, DWORD dwProcessID)
|
||||
{
|
||||
unsigned long PROC_ID_COUNTER = 784;
|
||||
|
||||
BOOL bProcessIDExist = FALSE;
|
||||
PPERF_COUNTER_DEFINITION pPerfCntr = NULL;
|
||||
PPERF_COUNTER_DEFINITION pTheRequestedPerfCntr = NULL;
|
||||
PPERF_COUNTER_DEFINITION pProcIDPerfCntr = NULL;
|
||||
PPERF_INSTANCE_DEFINITION pPerfInst = NULL;
|
||||
PPERF_COUNTER_BLOCK pCounterBlock = NULL;
|
||||
|
||||
// Get the first counter.
|
||||
|
||||
pPerfCntr = FirstCounter( pPerfObj );
|
||||
|
||||
for( DWORD j=0; j < pPerfObj->NumCounters; j++ )
|
||||
{
|
||||
if (pPerfCntr->CounterNameTitleIndex == PROC_ID_COUNTER)
|
||||
{
|
||||
pProcIDPerfCntr = pPerfCntr;
|
||||
if (pTheRequestedPerfCntr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pPerfCntr->CounterNameTitleIndex == dwCounterIndex)
|
||||
{
|
||||
pTheRequestedPerfCntr = pPerfCntr;
|
||||
if (pProcIDPerfCntr)
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next counter.
|
||||
|
||||
pPerfCntr = NextCounter( pPerfCntr );
|
||||
}
|
||||
|
||||
if( pPerfObj->NumInstances == PERF_NO_INSTANCES )
|
||||
{
|
||||
pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfObj + pPerfObj->DefinitionLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPerfInst = FirstInstance( pPerfObj );
|
||||
|
||||
for( int k=0; k < pPerfObj->NumInstances; k++ )
|
||||
{
|
||||
pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfInst + pPerfInst->ByteLength);
|
||||
if (pCounterBlock)
|
||||
{
|
||||
DWORD processID = *(DWORD*)((LPBYTE) pCounterBlock + pProcIDPerfCntr->CounterOffset);
|
||||
if (processID == dwProcessID)
|
||||
{
|
||||
bProcessIDExist = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the next instance.
|
||||
pPerfInst = NextInstance( pPerfInst );
|
||||
}
|
||||
}
|
||||
|
||||
if (bProcessIDExist && pCounterBlock)
|
||||
{
|
||||
T *lnValue = NULL;
|
||||
lnValue = (T*)((LPBYTE) pCounterBlock + pTheRequestedPerfCntr->CounterOffset);
|
||||
return *lnValue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
T GetCounterValueForProcessID(PERF_DATA_BLOCK **pPerfData, DWORD dwObjectIndex, DWORD dwCounterIndex, DWORD dwProcessID)
|
||||
{
|
||||
QueryPerformanceData(pPerfData, dwObjectIndex, dwCounterIndex);
|
||||
|
||||
PPERF_OBJECT_TYPE pPerfObj = NULL;
|
||||
T lnValue = {0};
|
||||
|
||||
// Get the first object type.
|
||||
pPerfObj = FirstObject( *pPerfData );
|
||||
|
||||
// Look for the given object index
|
||||
|
||||
for( DWORD i=0; i < (*pPerfData)->NumObjectTypes; i++ )
|
||||
{
|
||||
|
||||
if (pPerfObj->ObjectNameTitleIndex == dwObjectIndex)
|
||||
{
|
||||
lnValue = GetCounterValueForProcessID<T>(pPerfObj, dwCounterIndex, dwProcessID);
|
||||
break;
|
||||
}
|
||||
|
||||
pPerfObj = NextObject( pPerfObj );
|
||||
}
|
||||
return lnValue;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
// CPerfTracker implementation.
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
|
||||
CPerfTracker::CPerfTracker()
|
||||
{
|
||||
Init( 0 );
|
||||
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo( &info );
|
||||
m_nProcessors = (int)info.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
|
||||
void CPerfTracker::Init( unsigned long dwProcessID )
|
||||
{
|
||||
m_dwProcessID = dwProcessID;
|
||||
m_lnOldValue = 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned long CPerfTracker::GetProcessID()
|
||||
{
|
||||
return m_dwProcessID;
|
||||
}
|
||||
|
||||
|
||||
int CPerfTracker::GetCPUPercentage()
|
||||
{
|
||||
DWORD dwObjectIndex = PROCESS_OBJECT_INDEX;
|
||||
DWORD dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX;
|
||||
|
||||
PPERF_DATA_BLOCK pPerfData = NULL;
|
||||
LONGLONG lnNewValue = GetCounterValueForProcessID<LONGLONG>( &pPerfData, dwObjectIndex, dwCpuUsageIndex, m_dwProcessID );
|
||||
LARGE_INTEGER NewPerfTime100nSec = pPerfData->PerfTime100nSec;
|
||||
|
||||
if ( m_lnOldValue == 0 )
|
||||
{
|
||||
m_lnOldValue = lnNewValue;
|
||||
m_OldPerfTime100nSec = NewPerfTime100nSec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LONGLONG lnValueDelta = lnNewValue - m_lnOldValue;
|
||||
double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart;
|
||||
|
||||
m_lnOldValue = lnNewValue;
|
||||
m_OldPerfTime100nSec = NewPerfTime100nSec;
|
||||
|
||||
double a = (double)lnValueDelta / DeltaPerfTime100nSec;
|
||||
|
||||
int CpuUsage = (int) (a*100);
|
||||
if (CpuUsage < 0)
|
||||
return 0;
|
||||
|
||||
return CpuUsage / m_nProcessors;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef PERF_COUNTERS_H
|
||||
#define PERF_COUNTERS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class IPerfTracker
|
||||
{
|
||||
public:
|
||||
virtual void Init( unsigned long dwProcessID ) = 0;
|
||||
virtual void Release() = 0;
|
||||
|
||||
virtual unsigned long GetProcessID() = 0;
|
||||
virtual void GetPerfData( int &processorPercentage, int &memoryUsageMegabytes ) = 0;
|
||||
};
|
||||
|
||||
|
||||
IPerfTracker* CreatePerfTracker();
|
||||
|
||||
|
||||
#endif // PERF_COUNTERS_H
|
||||
@@ -0,0 +1,18 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Vmpi_service.rc
|
||||
//
|
||||
#define IDS_STRING102 102
|
||||
#define IDS_VERSION_STRING 102 // *** If this changes, change the matching value in vmpi_defs.h!
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 103
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,234 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "service_conn_mgr.h"
|
||||
#include "vmpi.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tcpsocket_helpers.h"
|
||||
|
||||
|
||||
#define SERVICECONNMGR_CONNECT_ATTEMPT_INTERVAL 1000
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
// CServiceConn.
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
|
||||
CServiceConn::CServiceConn()
|
||||
{
|
||||
m_pSocket = NULL;
|
||||
}
|
||||
|
||||
|
||||
CServiceConn::~CServiceConn()
|
||||
{
|
||||
if ( m_pSocket )
|
||||
m_pSocket->Release();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
// CServiceConnMgr.
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
|
||||
|
||||
CServiceConnMgr::CServiceConnMgr()
|
||||
{
|
||||
m_bServer = false;
|
||||
m_bShuttingDown = false;
|
||||
m_pListenSocket = NULL;
|
||||
}
|
||||
|
||||
|
||||
CServiceConnMgr::~CServiceConnMgr()
|
||||
{
|
||||
Term();
|
||||
}
|
||||
|
||||
|
||||
bool CServiceConnMgr::InitServer()
|
||||
{
|
||||
Term();
|
||||
|
||||
m_bServer = true;
|
||||
|
||||
// Create a socket to listen on.
|
||||
for ( int iPort=VMPI_SERVICE_FIRST_UI_PORT; iPort <= VMPI_SERVICE_LAST_UI_PORT; iPort++ )
|
||||
{
|
||||
m_pListenSocket = CreateTCPListenSocketEmu( iPort, 5 );
|
||||
if ( m_pListenSocket )
|
||||
break;
|
||||
}
|
||||
if ( !m_pListenSocket )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CServiceConnMgr::InitClient()
|
||||
{
|
||||
Term();
|
||||
|
||||
m_bServer = false;
|
||||
|
||||
AttemptConnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CServiceConnMgr::Term()
|
||||
{
|
||||
m_bShuttingDown = true; // This prevents some reentrancy.
|
||||
|
||||
// Get rid of our registry key.
|
||||
if ( m_pListenSocket )
|
||||
{
|
||||
m_pListenSocket->Release();
|
||||
m_pListenSocket = NULL;
|
||||
}
|
||||
|
||||
m_Connections.PurgeAndDeleteElements();
|
||||
|
||||
m_bShuttingDown = false;
|
||||
}
|
||||
|
||||
|
||||
bool CServiceConnMgr::IsConnected()
|
||||
{
|
||||
return m_Connections.Count() != 0;
|
||||
}
|
||||
|
||||
|
||||
void CServiceConnMgr::Update()
|
||||
{
|
||||
DWORD curTime = GetTickCount();
|
||||
|
||||
// Connect if we're an unconnected client.
|
||||
if ( m_bServer )
|
||||
{
|
||||
if ( m_pListenSocket )
|
||||
{
|
||||
// Listen for more connections.
|
||||
while ( 1 )
|
||||
{
|
||||
CIPAddr addr;
|
||||
ITCPSocket *pSocket = m_pListenSocket->UpdateListen( &addr );
|
||||
if ( !pSocket )
|
||||
break;
|
||||
|
||||
CServiceConn *pConn = new CServiceConn;
|
||||
pConn->m_ID = m_Connections.AddToTail( pConn );
|
||||
pConn->m_LastRecvTime = curTime;
|
||||
pConn->m_pSocket = pSocket;
|
||||
|
||||
OnNewConnection( pConn->m_ID );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !IsConnected() && curTime - m_LastConnectAttemptTime >= SERVICECONNMGR_CONNECT_ATTEMPT_INTERVAL )
|
||||
{
|
||||
AttemptConnect();
|
||||
}
|
||||
}
|
||||
|
||||
// Check for timeouts and send acks.
|
||||
int iNext;
|
||||
for ( int iCur=m_Connections.Head(); iCur != m_Connections.InvalidIndex(); iCur=iNext )
|
||||
{
|
||||
iNext = m_Connections.Next( iCur );
|
||||
CServiceConn *pConn = m_Connections[iCur];
|
||||
|
||||
if ( pConn->m_pSocket->IsConnected() )
|
||||
{
|
||||
DWORD startTime = GetTickCount();
|
||||
CUtlVector<unsigned char> data;
|
||||
while ( pConn->m_pSocket->Recv( data ) )
|
||||
{
|
||||
HandlePacket( (char*)data.Base(), data.Count() );
|
||||
|
||||
// Don't sit in this loop too long.
|
||||
if ( (GetTickCount() - startTime) > 50 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OnTerminateConnection( iCur );
|
||||
m_Connections.Remove( iCur );
|
||||
delete pConn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CServiceConnMgr::SendPacket( int id, const void *pData, int len )
|
||||
{
|
||||
if ( id == -1 )
|
||||
{
|
||||
FOR_EACH_LL( m_Connections, i )
|
||||
{
|
||||
m_Connections[i]->m_pSocket->Send( pData, len );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Connections[id]->m_pSocket->Send( pData, len );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CServiceConnMgr::AttemptConnect()
|
||||
{
|
||||
m_LastConnectAttemptTime = GetTickCount();
|
||||
|
||||
|
||||
ITCPSocket *pSocket = NULL;
|
||||
for ( int iPort=VMPI_SERVICE_FIRST_UI_PORT; iPort <= VMPI_SERVICE_LAST_UI_PORT; iPort++ )
|
||||
{
|
||||
pSocket = CreateTCPSocketEmu();
|
||||
if ( !pSocket || !pSocket->BindToAny( 0 ) )
|
||||
return;
|
||||
|
||||
CIPAddr addr( 127, 0, 0, 1, iPort );
|
||||
if ( TCPSocket_Connect( pSocket, &addr, 0.1 ) )
|
||||
break;
|
||||
|
||||
pSocket->Release();
|
||||
pSocket = NULL;
|
||||
}
|
||||
|
||||
if ( pSocket )
|
||||
{
|
||||
CServiceConn *pConn = new CServiceConn;
|
||||
pConn->m_ID = m_Connections.AddToTail( pConn );
|
||||
pConn->m_LastRecvTime = GetTickCount();
|
||||
pConn->m_pSocket = pSocket;
|
||||
|
||||
OnNewConnection( pConn->m_ID );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CServiceConnMgr::OnNewConnection( int id )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CServiceConnMgr::OnTerminateConnection( int id )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CServiceConnMgr::HandlePacket( const char *pData, int len )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SERVICE_CONN_MGR_H
|
||||
#define SERVICE_CONN_MGR_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "utllinkedlist.h"
|
||||
#include "utlvector.h"
|
||||
#include "tcpsocket.h"
|
||||
#include "ThreadedTCPSocketEmu.h"
|
||||
|
||||
|
||||
class CServiceConn
|
||||
{
|
||||
public:
|
||||
CServiceConn();
|
||||
~CServiceConn();
|
||||
|
||||
int m_ID;
|
||||
ITCPSocket *m_pSocket;
|
||||
DWORD m_LastRecvTime;
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------ //
|
||||
// CServiceConnMgr. This class manages connections to all the UIs (there should only be one UI at
|
||||
// any given time, but it's conceivable that multiple people can be logged into NT servers
|
||||
// simultaneously).
|
||||
// ------------------------------------------------------------------------------------------ //
|
||||
|
||||
class CServiceConnMgr
|
||||
{
|
||||
public:
|
||||
|
||||
CServiceConnMgr();
|
||||
~CServiceConnMgr();
|
||||
|
||||
bool InitServer(); // Registers as a systemwide server.
|
||||
bool InitClient(); // Connects to the server.
|
||||
void Term();
|
||||
|
||||
// Returns true if there are any connections. If you used InitClient() and there are
|
||||
// no connections, it will continuously try to connect with a server.
|
||||
bool IsConnected();
|
||||
|
||||
// This should be called as often as possible. It checks for dead connections and it
|
||||
// handles incoming packets from UIs.
|
||||
void Update();
|
||||
|
||||
// This sends out a message. If id is -1, then it sends to all connections.
|
||||
void SendPacket( int id, const void *pData, int len );
|
||||
|
||||
|
||||
// Overridables.
|
||||
public:
|
||||
|
||||
virtual void OnNewConnection( int id );
|
||||
virtual void OnTerminateConnection( int id );
|
||||
virtual void HandlePacket( const char *pData, int len );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void AttemptConnect();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
CUtlLinkedList<CServiceConn*, int> m_Connections;
|
||||
|
||||
bool m_bShuttingDown;
|
||||
|
||||
// This tells if we're running as a client or server.
|
||||
bool m_bServer;
|
||||
|
||||
// If we're a client, this is the last time we tried to connect.
|
||||
DWORD m_LastConnectAttemptTime;
|
||||
|
||||
// If we're the server, this is the socket we listen on.
|
||||
ITCPListenSocket *m_pListenSocket;
|
||||
};
|
||||
|
||||
|
||||
#endif // SERVICE_CONN_MGR_H
|
||||
@@ -0,0 +1,181 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "service_helpers.h"
|
||||
|
||||
|
||||
static CRITICAL_SECTION g_CtrlHandlerMutex;
|
||||
|
||||
static void (*g_pInternalServiceFn)( void *pParam ) = NULL;
|
||||
static void *g_pInternalServiceParam = NULL;
|
||||
|
||||
static volatile bool g_bShouldExit = false;
|
||||
|
||||
|
||||
SERVICE_STATUS MyServiceStatus;
|
||||
SERVICE_STATUS_HANDLE MyServiceStatusHandle = NULL;
|
||||
|
||||
|
||||
void WINAPI MyServiceCtrlHandler( DWORD Opcode )
|
||||
{
|
||||
DWORD status;
|
||||
|
||||
switch(Opcode)
|
||||
{
|
||||
case SERVICE_CONTROL_STOP:
|
||||
// Do whatever it takes to stop here.
|
||||
ServiceHelpers_ExitEarly();
|
||||
|
||||
MyServiceStatus.dwWin32ExitCode = 0;
|
||||
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
|
||||
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus) )
|
||||
{
|
||||
status = GetLastError();
|
||||
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
|
||||
}
|
||||
|
||||
Msg( "[MY_SERVICE] Leaving MyService \n" );
|
||||
return;
|
||||
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
// Fall through to send current status.
|
||||
break;
|
||||
|
||||
default:
|
||||
Msg("[MY_SERVICE] Unrecognized opcode %ld\n", Opcode );
|
||||
}
|
||||
|
||||
// Send current status.
|
||||
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
|
||||
{
|
||||
status = GetLastError();
|
||||
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WINAPI MyServiceStart( DWORD argc, LPTSTR *argv )
|
||||
{
|
||||
DWORD status;
|
||||
|
||||
MyServiceStatus.dwServiceType = SERVICE_WIN32;
|
||||
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||
MyServiceStatus.dwWin32ExitCode = 0;
|
||||
MyServiceStatus.dwServiceSpecificExitCode = 0;
|
||||
MyServiceStatus.dwCheckPoint = 0;
|
||||
MyServiceStatus.dwWaitHint = 0;
|
||||
|
||||
MyServiceStatusHandle = RegisterServiceCtrlHandler( "MyService", MyServiceCtrlHandler );
|
||||
if ( MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0 )
|
||||
{
|
||||
Msg("[MY_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialization complete - report running status.
|
||||
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
|
||||
if ( !SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus ) )
|
||||
{
|
||||
status = GetLastError();
|
||||
Msg( "[MY_SERVICE] SetServiceStatus error %ld\n", status );
|
||||
}
|
||||
|
||||
|
||||
// Run the app's main in-thread loop.
|
||||
g_pInternalServiceFn( g_pInternalServiceParam );
|
||||
|
||||
|
||||
// Tell the SCM that we're stopped.
|
||||
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
MyServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||||
MyServiceStatus.dwServiceSpecificExitCode = 0;
|
||||
SetServiceStatus( MyServiceStatusHandle, &MyServiceStatus );
|
||||
|
||||
|
||||
// This is where the service does its work.
|
||||
Msg( "[MY_SERVICE] Returning the Main Thread \n" );
|
||||
}
|
||||
|
||||
|
||||
void ServiceHelpers_Init()
|
||||
{
|
||||
InitializeCriticalSection( &g_CtrlHandlerMutex );
|
||||
}
|
||||
|
||||
|
||||
bool ServiceHelpers_StartService( const char *pServiceName, void (*pFn)( void *pParam ), void *pParam )
|
||||
{
|
||||
// Ok, just run the service.
|
||||
const SERVICE_TABLE_ENTRY DispatchTable[2] =
|
||||
{
|
||||
{ (char*)pServiceName, MyServiceStart },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
g_pInternalServiceFn = pFn;
|
||||
g_pInternalServiceParam = pParam;
|
||||
|
||||
if ( StartServiceCtrlDispatcher( DispatchTable ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "StartServiceCtrlDispatcher error = '%s'\n", GetLastErrorString() );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ServiceHelpers_ExitEarly()
|
||||
{
|
||||
EnterCriticalSection( &g_CtrlHandlerMutex );
|
||||
g_bShouldExit = true;
|
||||
LeaveCriticalSection( &g_CtrlHandlerMutex );
|
||||
}
|
||||
|
||||
|
||||
bool ServiceHelpers_ShouldExit()
|
||||
{
|
||||
EnterCriticalSection( &g_CtrlHandlerMutex );
|
||||
bool bRet = g_bShouldExit;
|
||||
LeaveCriticalSection( &g_CtrlHandlerMutex );
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
char* GetLastErrorString()
|
||||
{
|
||||
static char err[2048];
|
||||
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
strncpy( err, (char*)lpMsgBuf, sizeof( err ) );
|
||||
LocalFree( lpMsgBuf );
|
||||
|
||||
err[ sizeof( err ) - 1 ] = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SERVICE_HELPERS_H
|
||||
#define SERVICE_HELPERS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
// Call this if you want to use the ExitEarly() and ShouldExit() helpers.
|
||||
void ServiceHelpers_Init();
|
||||
|
||||
// Start this app in the service control manager.
|
||||
//
|
||||
// The service will run in a thread. If the service starts successfully, then
|
||||
// it will call pFn and pass in pParam. Inside there, you should loop until
|
||||
// ShouldServiceExit() returns true.
|
||||
bool ServiceHelpers_StartService( const char *pServiceName, void (*pFn)( void *pParam ), void *pParam );
|
||||
|
||||
|
||||
// Call this to exit the service early. This will make ShouldServiceExit() return true,
|
||||
// and your main thread function should pick it up and exit.
|
||||
//
|
||||
// NOTE: this can be used even if the service isn't running as long as you call ServiceHelpers_Init().
|
||||
void ServiceHelpers_ExitEarly();
|
||||
|
||||
// Your thread loop should call this each time around. If this function returns true,
|
||||
// then your thread function should return, causing the service to exit.
|
||||
//
|
||||
// NOTE: this can be used even if the service isn't running as long as you call ServiceHelpers_Init().
|
||||
bool ServiceHelpers_ShouldExit();
|
||||
|
||||
|
||||
// This function wants a better home.
|
||||
char* GetLastErrorString();
|
||||
|
||||
|
||||
#endif // SERVICE_HELPERS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#if !defined(AFX_VMPI_SERVICE_H__0EE084DB_9164_4DC2_9E95_CF25D32AAA7B__INCLUDED_)
|
||||
#define AFX_VMPI_SERVICE_H__0EE084DB_9164_4DC2_9E95_CF25D32AAA7B__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
#endif // !defined(AFX_VMPI_SERVICE_H__0EE084DB_9164_4DC2_9E95_CF25D32AAA7B__INCLUDED_)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_VERSION_STRING "3.3"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// VMPI_SERVICE.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,..\..\common,..\"
|
||||
$PreprocessorDefinitions "$BASE;PROTECTED_THINGS_DISABLE"
|
||||
}
|
||||
|
||||
$Linker
|
||||
{
|
||||
$AdditionalDependencies "$BASE pdh.lib ws2_32.lib odbc32.lib odbccp32.lib"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Vmpi_service"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "..\iphelpers.cpp"
|
||||
$File "service_conn_mgr.cpp"
|
||||
$File "service_helpers.cpp"
|
||||
$File "perf_counters.cpp"
|
||||
$File "vmpi_service.rc"
|
||||
$File "StdAfx.cpp"
|
||||
$File "..\tcpsocket_helpers.cpp"
|
||||
$File "..\ThreadedTCPSocket.cpp"
|
||||
$File "..\ThreadedTCPSocketEmu.cpp"
|
||||
$File "..\threadhelpers.cpp"
|
||||
$File "vmpi_service.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "service_conn_mgr.h"
|
||||
$File "service_helpers.h"
|
||||
$File "perf_counters.h"
|
||||
$File "StdAfx.h"
|
||||
$File "resource.h"
|
||||
$File "vmpi_service.h"
|
||||
}
|
||||
|
||||
$Folder "Resource Files"
|
||||
{
|
||||
$File "..\vmpi_service_ui\idi_busy_icon.ico"
|
||||
$File "..\vmpi_service_ui\idi_disabled_icon.ico"
|
||||
$File "..\vmpi_service_ui\idi_waiting_icon.ico"
|
||||
$File "..\vmpi_service_ui\vmpi_service.ico"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user