diff options
Diffstat (limited to 'utils/vmpi/vmpi_services_watch')
16 files changed, 2090 insertions, 0 deletions
diff --git a/utils/vmpi/vmpi_services_watch/PatchTimeout.cpp b/utils/vmpi/vmpi_services_watch/PatchTimeout.cpp new file mode 100644 index 0000000..df242d8 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/PatchTimeout.cpp @@ -0,0 +1,50 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// PatchTimeout.cpp : implementation file +// + +#include "stdafx.h" +#include "PatchTimeout.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPatchTimeout dialog + + +CPatchTimeout::CPatchTimeout(CWnd* pParent /*=NULL*/) + : CDialog(CPatchTimeout::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPatchTimeout) + //}}AFX_DATA_INIT +} + + +void CPatchTimeout::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPatchTimeout) + DDX_Text(pDX, IDC_COMMAND_LINE, m_PatchDirectory); + DDX_Text(pDX, IDC_VMPI_TRANSFER_DIRECTORY, m_VMPITransferDirectory); + DDX_Check(pDX, IDC_FORCE_PATCH, m_bForcePatch); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPatchTimeout, CDialog) + //{{AFX_MSG_MAP(CPatchTimeout) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPatchTimeout message handlers diff --git a/utils/vmpi/vmpi_services_watch/PatchTimeout.h b/utils/vmpi/vmpi_services_watch/PatchTimeout.h new file mode 100644 index 0000000..1efb171 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/PatchTimeout.h @@ -0,0 +1,57 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#if !defined(AFX_PATCHTIMEOUT_H__2D87CBF2_AC88_4F23_BB43_CC8A5C248B64__INCLUDED_) +#define AFX_PATCHTIMEOUT_H__2D87CBF2_AC88_4F23_BB43_CC8A5C248B64__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PatchTimeout.h : header file +// + +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// CPatchTimeout dialog + +class CPatchTimeout : public CDialog +{ +// Construction +public: + CPatchTimeout(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CPatchTimeout) + enum { IDD = IDD_TIMEOUT }; + CString m_PatchDirectory; + CString m_VMPITransferDirectory; + int m_bForcePatch; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPatchTimeout) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPatchTimeout) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PATCHTIMEOUT_H__2D87CBF2_AC88_4F23_BB43_CC8A5C248B64__INCLUDED_) diff --git a/utils/vmpi/vmpi_services_watch/ServicesDlg.cpp b/utils/vmpi/vmpi_services_watch/ServicesDlg.cpp new file mode 100644 index 0000000..dd8ea5f --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/ServicesDlg.cpp @@ -0,0 +1,1161 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// ServicesDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "ServicesDlg.h" +#include "vmpi.h" +#include "bitbuf.h" +#include "tier1/strtools.h" +#include "patchtimeout.h" +#include "SetPasswordDlg.h" +#include "vmpi_browser_helpers.h" +#include <io.h> + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define SERVICE_OFF_TIMEOUT (20*1000) // If we haven't heard from a service in this long, + // then we assume the service is off. + +#define SERVICES_PING_INTERVAL (3*1000) // ping the services every so often + +#define SERVICE_MAX_UPDATE_INTERVAL (8*1000) // Update each service in the listbox at least this often. + + + +int V_AfxMessageBox( int mbType, const char *pFormat, ... ) +{ + char msg[4096]; + va_list marker; + va_start( marker, pFormat ); + _vsnprintf( msg, sizeof( msg ), pFormat, marker ); + va_end( marker ); + + return AfxMessageBox( msg, mbType ); +} + + +bool CServiceInfo::IsOff() const +{ + return (Plat_MSTime() - m_LastPingTimeMS) > SERVICE_OFF_TIMEOUT; +} + + +// Returns the argument following pName. +// If pName is the last argument on the command line, returns pEndArgDefault. +// Returns NULL if there is no argument with pName. +const char* FindArg( const char *pName, const char *pEndArgDefault="" ) +{ + for ( int i=0; i < __argc; i++ ) + { + if ( stricmp( pName, __argv[i] ) == 0 ) + { + if ( (i+1) < __argc ) + return __argv[i+1]; + else + return pEndArgDefault; + } + } + return NULL; +} + +void AppendStr( char *dest, int destSize, const char *pFormat, ... ) +{ + char str[4096]; + va_list marker; + va_start( marker, pFormat ); + _vsnprintf( str, sizeof( str ), pFormat, marker ); + va_end( marker ); + str[sizeof( str ) - 1] = 0; + + V_strncat( dest, str, destSize ); +} + + +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; +} + +const char* GetStatusString( CServiceInfo *pInfo ) +{ + if ( pInfo->IsOff() ) + return "off"; + else if ( pInfo->m_iState == VMPI_STATE_BUSY ) + return "busy"; + else if ( pInfo->m_iState == VMPI_STATE_PATCHING ) + return "patching"; + else if ( pInfo->m_iState == VMPI_STATE_DISABLED ) + return "disabled"; + else if ( pInfo->m_iState == VMPI_STATE_SCREENSAVER_DISABLED ) + return "disabled (screensaver)"; + else if ( pInfo->m_iState == VMPI_STATE_DOWNLOADING ) + return "downloading"; + else + return "idle"; +} + + +// --------------------------------------------------------------------------------------------------------- // +// Column sort functions. +// --------------------------------------------------------------------------------------------------------- // +typedef int (CALLBACK *ServicesSortFn)( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ); + +static int CALLBACK SortByName( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return strcmp( pInfo1->m_ComputerName, pInfo2->m_ComputerName ); +} + +static int CALLBACK SortByStatus( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return -strcmp( GetStatusString( pInfo2 ), GetStatusString( pInfo1 ) ); +} + +static int CALLBACK SortByRunningTime( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + int v1 = pInfo1->m_LiveTimeMS / (1000*60); // Sort on minutes so it doesn't constantly resort the list. + int v2 = pInfo2->m_LiveTimeMS / (1000*60); + if ( v2 > v1 ) + return 1; + else if ( v2 < v1 ) + return -1; + else + return 0; +} + +static int CALLBACK SortByWorkerAppRunningTime( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + int v1 = pInfo1->m_WorkerAppTimeMS / (1000*60); // Sort on minutes so it doesn't constantly resort the list. + int v2 = pInfo2->m_WorkerAppTimeMS / (1000*60); + if ( v2 > v1 ) + return 1; + else if ( v2 < v1 ) + return -1; + else + return 0; +} + +static int CALLBACK SortByMasterName( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return -strcmp( pInfo2->m_MasterName, pInfo1->m_MasterName ); +} + +static int CALLBACK SortByProtocol( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return pInfo1->m_ProtocolVersion > pInfo2->m_ProtocolVersion; +} + +static int CALLBACK SortByPassword( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return -strcmp( pInfo2->m_Password, pInfo1->m_Password ); +} + +static int CALLBACK SortByServiceVersion( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return -strcmp( pInfo2->m_ServiceVersion, pInfo1->m_ServiceVersion ); +} + +static int CALLBACK SortByExe( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return -strcmp( pInfo2->m_ExeName, pInfo1->m_ExeName ); +} + +static int CALLBACK SortByMap( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + return -strcmp( pInfo2->m_MapName, pInfo1->m_MapName ); +} + +static int CALLBACK SortByCPUPercentage( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + if ( pInfo2->m_CPUPercentage > pInfo1->m_CPUPercentage ) + return 1; + else if ( pInfo2->m_CPUPercentage < pInfo1->m_CPUPercentage ) + return -1; + else + return 0; +} + +static int CALLBACK SortByMemUsage( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + CServiceInfo *pInfo1 = (CServiceInfo*)iItem1; + CServiceInfo *pInfo2 = (CServiceInfo*)iItem2; + + if ( pInfo2->m_MemUsageMB > pInfo1->m_MemUsageMB ) + return 1; + else if ( pInfo2->m_MemUsageMB < pInfo1->m_MemUsageMB ) + return -1; + else + return 0; +} + +// --------------------------------------------------------------------------------------------------------- // +// Column information. +// --------------------------------------------------------------------------------------------------------- // + +struct +{ + char *pText; + int width; + ServicesSortFn sortFn; +} g_ColumnInfos[] = +{ + {"Computer Name", 150, SortByName}, + {"Status", 95, SortByStatus}, + {"Service Run Time", 100, SortByRunningTime}, + {"Worker App Run Time", 125, SortByWorkerAppRunningTime}, + {"Master", 150, SortByMasterName}, + {"Password", 60, SortByPassword}, + {"Protocol", 60, SortByProtocol}, + {"Version", 50, SortByServiceVersion}, + {"CPU", 50, SortByCPUPercentage}, + {"Memory (MB)", 80, SortByMemUsage}, + {"Exe", 80, SortByExe}, + {"Map", 90, SortByMap}, +}; +#define COLUMN_COMPUTER_NAME 0 +#define COLUMN_STATUS 1 +#define COLUMN_RUNNING_TIME 2 +#define COLUMN_WORKER_APP_RUNNING_TIME 3 +#define COLUMN_MASTER_NAME 4 +#define COLUMN_PASSWORD 5 +#define COLUMN_PROTOCOL_VERSION 6 +#define COLUMN_SERVICE_VERSION 7 +#define COLUMN_CPU_PERCENTAGE 8 +#define COLUMN_MEM_USAGE 9 +#define COLUMN_EXE_NAME 10 +#define COLUMN_MAP_NAME 11 + + +// Used to sort all the columns. +// When they click on a column, we add that index to entry 0 in here. +// Then when sorting, if 2 columns are equal, we move to the next sort function. +CUtlVector<int> g_SortColumns; + +static void PushSortColumn( int iColumn ) +{ + // First, get rid of all entries with this same index. + int iPrev = g_SortColumns.Find( iColumn ); + if ( iPrev != g_SortColumns.InvalidIndex() ) + g_SortColumns.Remove( iPrev ); + + // Now add this one. + g_SortColumns.AddToTail( iColumn ); +} + +static int CALLBACK MainSortFn( LPARAM iItem1, LPARAM iItem2, LPARAM lpParam ) +{ + int curStatus = 0; + for ( int i = (int)g_SortColumns.Count()-1; i >= 0; i-- ) + { + curStatus = g_ColumnInfos[g_SortColumns[i]].sortFn( iItem1, iItem2, lpParam ); + if ( curStatus != 0 ) + break; + } + return curStatus; +} + + +///////////////////////////////////////////////////////////////////////////// +// CServicesDlg dialog + + +CServicesDlg::CServicesDlg(CWnd* pParent /*=NULL*/) + : CIdleDialog(CServicesDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CServicesDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pServicesPingSocket = NULL; +} + + +void CServicesDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CServicesDlg) + DDX_Control(pDX, IDC_NUM_SERVICES, m_NumServicesControl); + DDX_Control(pDX, IDC_NUM_DISABLED_SERVICES, m_NumDisabledServicesControl); + DDX_Control(pDX, IDC_NUM_WORKING_SERVICES, m_NumWorkingServicesControl); + DDX_Control(pDX, IDC_NUM_WAITING_SERVICES, m_NumWaitingServicesControl); + DDX_Control(pDX, IDC_NUM_OFF_SERVICES, m_NumOffServicesControl); + DDX_Control(pDX, IDC_CURRENT_PASSWORD, m_PasswordDisplay); + DDX_Control(pDX, IDC_SERVICES_LIST, m_ServicesList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CServicesDlg, CIdleDialog) + //{{AFX_MSG_MAP(CServicesDlg) + ON_BN_CLICKED(ID_PATCH_SERVICES, OnPatchServices) + ON_BN_CLICKED(ID_STOP_SERVICES, OnStopServices) + ON_BN_CLICKED(ID_STOP_JOBS, OnStopJobs) + ON_BN_CLICKED(ID_FILTER_BY_PASSWORD, OnFilterByPassword) + ON_BN_CLICKED(ID_FORCE_PASSWORD, OnForcePassword) + ON_BN_CLICKED(ID_COPY_TO_CLIPBOARD, OnCopyToClipboard) + ON_NOTIFY(NM_DBLCLK, IDC_SERVICES_LIST, OnDblclkServicesList) + ON_WM_SIZE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CServicesDlg message handlers + +BOOL CServicesDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Initially, just sort by computer name. + PushSortColumn( COLUMN_COMPUTER_NAME ); + + HICON hIcon = LoadIcon( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_MAINFRAME ) ); + SetIcon( hIcon, true ); + + m_ServicesList.SetExtendedStyle( LVS_EX_FULLROWSELECT ); + + // Setup the headers. + for ( int i=0; i < ARRAYSIZE( g_ColumnInfos ); i++ ) + { + m_ServicesList.InsertColumn( i, g_ColumnInfos[i].pText, LVCFMT_LEFT, g_ColumnInfos[i].width, i ); + } + + m_pServicesPingSocket = CreateIPSocket(); + if ( m_pServicesPingSocket ) + { + m_pServicesPingSocket->BindToAny( 0 ); + } + + m_dwLastServicesPing = GetTickCount() - SERVICES_PING_INTERVAL; + StartIdleProcessing( 100 ); // get idle messages every half second + + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_SERVICES_LABEL ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_SERVICES ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_DISABLED_SERVICES_LABEL ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_DISABLED_SERVICES ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_WORKING_SERVICES_LABEL ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_WORKING_SERVICES ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_WAITING_SERVICES_LABEL ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_WAITING_SERVICES ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_OFF_SERVICES_LABEL ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_NUM_OFF_SERVICES ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_CURRENT_PASSWORD_LABEL ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_CURRENT_PASSWORD ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( ID_PATCH_SERVICES ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( ID_STOP_SERVICES ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( ID_STOP_JOBS ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( ID_FORCE_PASSWORD ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + m_AnchorMgr.AddAnchor( this, GetDlgItem( ID_FILTER_BY_PASSWORD ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + + m_AnchorMgr.AddAnchor( this, GetDlgItem( ID_COPY_TO_CLIPBOARD ), ANCHOR_LEFT, ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_BOTTOM ); + + m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_SERVICES_LIST ), ANCHOR_LEFT, ANCHOR_TOP, ANCHOR_RIGHT, ANCHOR_BOTTOM ); + + // Unless they specify admin mode, hide all the controls that can mess with the services. + if ( !FindArg( "-Admin" ) ) + { + ::ShowWindow( ::GetDlgItem( m_hWnd, ID_PATCH_SERVICES ), SW_HIDE ); + ::ShowWindow( ::GetDlgItem( m_hWnd, ID_STOP_SERVICES ), SW_HIDE ); + ::ShowWindow( ::GetDlgItem( m_hWnd, ID_STOP_JOBS ), SW_HIDE ); + ::ShowWindow( ::GetDlgItem( m_hWnd, ID_FORCE_PASSWORD ), SW_HIDE ); + } + + m_NetViewThread.Init(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CServicesDlg::BuildVMPIPingPacket( CUtlVector<char> &out, char cPacketID, unsigned char protocolVersion, bool bIgnorePassword ) +{ + out.Purge(); + out.AddToTail( protocolVersion ); + + const char *pPassword = m_Password; + if ( pPassword[0] == 0 || bIgnorePassword ) + { + // If they haven't set a password to filter by, then we want all services to report in. + out.AddToTail( VMPI_PASSWORD_OVERRIDE ); + out.AddToTail( 0 ); + } + else + { + out.AddMultipleToTail( strlen( pPassword ) + 1, pPassword ); // password. + } + + out.AddToTail( cPacketID ); +} + + +void CServicesDlg::UpdateServicesFromNetMessages() +{ + while ( 1 ) + { + char in[1024]; + CIPAddr ipFrom; + + int len = m_pServicesPingSocket->RecvFrom( in, sizeof( in ), &ipFrom ); + if ( len < 4 ) + break; + + bf_read buf( in, len ); + unsigned char protocolVersion = buf.ReadByte(); + if ( protocolVersion == 4 || protocolVersion == VMPI_PROTOCOL_VERSION ) // Protocol version 4 is almost the same. + { + int packetID = buf.ReadByte(); + if ( packetID == VMPI_PING_RESPONSE ) + { + int iState = buf.ReadByte(); + unsigned long liveTimeMS = (unsigned long)buf.ReadLong(); + + int iPort = buf.ReadLong(); + char computerName[512]; + buf.ReadString( computerName, sizeof( computerName ) ); + + char masterName[512]; + if ( buf.GetNumBitsLeft() ) + buf.ReadString( masterName, sizeof( masterName ) ); + else + masterName[0] = 0; + + unsigned long workerAppTimeMS = 0; + if ( buf.GetNumBitsLeft() ) + workerAppTimeMS = buf.ReadLong(); + + char password[512] = {0}; + if ( protocolVersion == VMPI_PROTOCOL_VERSION ) + buf.ReadString( password, sizeof( password ) ); + + char serviceVersion[32]; + if ( protocolVersion == VMPI_PROTOCOL_VERSION ) + buf.ReadString( serviceVersion, sizeof( serviceVersion ) ); + else + V_strncpy( serviceVersion, "old", sizeof( serviceVersion ) ); + + int cpuPercentage = -1; + if ( buf.GetNumBytesLeft() >= 1 ) + cpuPercentage = buf.ReadByte(); + + char exeName[512]; + if ( buf.GetNumBytesLeft() >= 1 ) + buf.ReadString( exeName, sizeof( exeName ) ); + else + V_strncpy( exeName, "-", sizeof( exeName ) ); + + short memUsage = -1; + if ( buf.GetNumBytesLeft() >= 2 ) + memUsage = buf.ReadShort(); + + char mapName[256]; + if ( buf.GetNumBytesLeft() >= 1 ) + buf.ReadString( mapName, sizeof( mapName ) ); + else + V_strncpy( mapName, "-", sizeof( mapName ) ); + + + CServiceInfo *pInfo = FindServiceByComputerName( computerName ); + if ( !pInfo ) + { + pInfo = new CServiceInfo; + m_Services.AddToTail( pInfo ); + pInfo->m_ComputerName = computerName; + + pInfo->m_pLastStatusText = NULL; + + pInfo->m_Addr.port = iPort; + pInfo->m_LastPingTimeMS = Plat_MSTime(); + pInfo->m_MasterName = "?"; + + int iItem = m_ServicesList.InsertItem( COLUMN_COMPUTER_NAME, pInfo->m_ComputerName, NULL ); + m_ServicesList.SetItemData( iItem, (DWORD)pInfo ); + + // Update the display of # of services. + UpdateServiceCountDisplay(); + } + + pInfo->m_ProtocolVersion = protocolVersion; + V_strncpy( pInfo->m_ServiceVersion, serviceVersion, sizeof( pInfo->m_ServiceVersion ) ); + pInfo->m_Addr = ipFrom; + pInfo->m_CPUPercentage = cpuPercentage; + pInfo->m_MemUsageMB = memUsage; + pInfo->m_ExeName = exeName; + pInfo->m_MapName = mapName; + pInfo->m_MasterName = masterName; + pInfo->m_LiveTimeMS = liveTimeMS; + pInfo->m_WorkerAppTimeMS = workerAppTimeMS; + pInfo->m_iState = iState; + pInfo->m_LastPingTimeMS = Plat_MSTime(); + pInfo->m_Password = password; + + UpdateServiceInListbox( pInfo ); + } + } + } +} + + +void CServicesDlg::UpdateServicesFromNetView() +{ + CUtlVector<char*> computerNames; + m_NetViewThread.GetComputerNames( computerNames ); + + for ( int i=0; i < computerNames.Count(); i++ ) + { + CServiceInfo *pInfo = FindServiceByComputerName( computerNames[i] ); + if ( !pInfo ) + { + pInfo = new CServiceInfo; + m_Services.AddToTail( pInfo ); + pInfo->m_ComputerName = computerNames[i]; + pInfo->m_LastPingTimeMS = Plat_MSTime() - SERVICE_OFF_TIMEOUT*2; // so it's marked as "off" + pInfo->m_LastLiveTimeMS = Plat_MSTime(); + pInfo->m_LiveTimeMS = 0; + pInfo->m_WorkerAppTimeMS = 0; + pInfo->m_ProtocolVersion = 0; + pInfo->m_ServiceVersion[0] = 0; + pInfo->m_CPUPercentage = -1; + pInfo->m_MemUsageMB = -1; + + int iItem = m_ServicesList.InsertItem( COLUMN_COMPUTER_NAME, pInfo->m_ComputerName, NULL ); + m_ServicesList.SetItemData( iItem, (DWORD)pInfo ); + + // Update the display of # of services. + UpdateServiceCountDisplay(); + + UpdateServiceInListbox( pInfo ); + } + } + + computerNames.PurgeAndDeleteElements(); +} + + +void CServicesDlg::OnIdle() +{ + DWORD curTime = GetTickCount(); + + if ( !m_pServicesPingSocket ) + return; + + // Broadcast out to all the services? + if ( curTime - m_dwLastServicesPing >= SERVICES_PING_INTERVAL ) + { + m_dwLastServicesPing = curTime; + + for ( int i=VMPI_SERVICE_PORT; i <= VMPI_LAST_SERVICE_PORT; i++ ) + { + CUtlVector<char> data; + BuildVMPIPingPacket( data, VMPI_PING_REQUEST ); + m_pServicesPingSocket->Broadcast( data.Base(), data.Count(), i ); + + // Also send out a version 4 one because we understand a version 4 response. + BuildVMPIPingPacket( data, VMPI_PING_REQUEST, 4 ); + m_pServicesPingSocket->Broadcast( data.Base(), data.Count(), i ); + } + + UpdateServiceCountDisplay(); + } + + m_ServicesList.SetRedraw( false ); + + // Check for messages from services. + UpdateServicesFromNetMessages(); + + // Issue a "net view" command, parse the output, and add any computers it lists. + // This lets us figure out which PCs on the network are not running the service. + UpdateServicesFromNetView(); + + + FOR_EACH_LL( m_Services, iService ) + { + CServiceInfo *pInfo = m_Services[iService]; + if ( Plat_MSTime() - pInfo->m_LastUpdateTime > SERVICE_MAX_UPDATE_INTERVAL ) + { + UpdateServiceInListbox( pInfo ); + } + } + + if ( m_bListChanged ) + { + ResortItems(); + m_bListChanged = false; + } + + m_ServicesList.SetRedraw( true ); +} + + +CServiceInfo* CServicesDlg::FindServiceByComputerName( const char *pComputerName ) +{ + FOR_EACH_LL( m_Services, i ) + { + if ( Q_stricmp( m_Services[i]->m_ComputerName, pComputerName ) == 0 ) + return m_Services[i]; + } + return NULL; +} + + +void CServicesDlg::SendToSelectedServices( const char *pData, int len ) +{ + POSITION pos = m_ServicesList.GetFirstSelectedItemPosition(); + while ( pos ) + { + int iItem = m_ServicesList.GetNextSelectedItem( pos ); + + CServiceInfo *pInfo = (CServiceInfo*)m_ServicesList.GetItemData( iItem ); + m_pServicesPingSocket->SendTo( &pInfo->m_Addr, pData, len ); + } +} + + +void UpdateItemText( CListCtrl &ctrl, int iItem, int iColumn, const char *pNewVal ) +{ + CString str = ctrl.GetItemText( iItem, iColumn ); + if ( V_stricmp( str, pNewVal ) != 0 ) + ctrl.SetItemText( iItem, iColumn, pNewVal ); +} + + +void CServicesDlg::UpdateServiceInListbox( CServiceInfo *pInfo ) +{ + // First, find this item in the listbox. + LVFINDINFO info; + info.flags = LVFI_PARAM; + info.lParam = (LPARAM)pInfo; + int iItem = m_ServicesList.FindItem( &info ); + if ( iItem != -1 ) + { + UpdateItemText( m_ServicesList, iItem, COLUMN_COMPUTER_NAME, pInfo->m_ComputerName ); + + const char *pText = GetStatusString( pInfo ); + UpdateItemText( m_ServicesList, iItem, COLUMN_STATUS, pText ); + + char timeStr[512]; + FormatTimeString( pInfo->m_LiveTimeMS / 1000, timeStr, sizeof( timeStr ) ); + UpdateItemText( m_ServicesList, iItem, COLUMN_RUNNING_TIME, timeStr ); + + FormatTimeString( pInfo->m_WorkerAppTimeMS / 1000, timeStr, sizeof( timeStr ) ); + UpdateItemText( m_ServicesList, iItem, COLUMN_WORKER_APP_RUNNING_TIME, timeStr ); + + UpdateItemText( m_ServicesList, iItem, COLUMN_MASTER_NAME, pInfo->m_MasterName ); + + char str[512]; + V_snprintf( str, sizeof( str ), "%d", pInfo->m_ProtocolVersion ); + UpdateItemText( m_ServicesList, iItem, COLUMN_PROTOCOL_VERSION, str ); + + UpdateItemText( m_ServicesList, iItem, COLUMN_PASSWORD, pInfo->m_Password ); + UpdateItemText( m_ServicesList, iItem, COLUMN_SERVICE_VERSION, pInfo->m_ServiceVersion ); + + if ( pInfo->m_CPUPercentage == -1 ) + V_snprintf( str, sizeof( str ), "-" ); + else if ( pInfo->m_CPUPercentage == 101 ) + V_snprintf( str, sizeof( str ), "(err)" ); + else + V_snprintf( str, sizeof( str ), "%d%%", pInfo->m_CPUPercentage ); + UpdateItemText( m_ServicesList, iItem, COLUMN_CPU_PERCENTAGE, str ); + + UpdateItemText( m_ServicesList, iItem, COLUMN_EXE_NAME, pInfo->m_ExeName ); + UpdateItemText( m_ServicesList, iItem, COLUMN_MAP_NAME, pInfo->m_MapName ); + + if ( pInfo->m_MemUsageMB == -1 ) + V_snprintf( str, sizeof( str ), "-" ); + else + V_snprintf( str, sizeof( str ), "%d", pInfo->m_MemUsageMB ); + UpdateItemText( m_ServicesList, iItem, COLUMN_MEM_USAGE, str ); + + pInfo->m_pLastStatusText = pText; + pInfo->m_LastLiveTimeMS = pInfo->m_LiveTimeMS; + pInfo->m_LastMasterName = pInfo->m_MasterName; + pInfo->m_LastUpdateTime = Plat_MSTime(); + + // Detect changes. + if ( !m_bListChanged && iItem > 0 ) + { + CServiceInfo *pPrevItem = (CServiceInfo*)m_ServicesList.GetItemData( iItem-1 ); + if ( pPrevItem && MainSortFn( (LPARAM)pPrevItem, (LPARAM)pInfo, NULL ) > 0 ) + m_bListChanged = true; + } + + if ( !m_bListChanged && (iItem+1) < m_ServicesList.GetItemCount() ) + { + CServiceInfo *pNextItem = (CServiceInfo*)m_ServicesList.GetItemData( iItem+1 ); + if ( pNextItem && MainSortFn( (LPARAM)pInfo, (LPARAM)pNextItem, NULL ) > 0 ) + m_bListChanged = true; + } + } +} + + +void CServicesDlg::ResortItems() +{ + m_ServicesList.SortItems( MainSortFn, (LPARAM)this ); +} + + +void CServicesDlg::UpdateServiceCountDisplay() +{ + char str[512]; + Q_snprintf( str, sizeof( str ), "%d", m_Services.Count() ); + m_NumServicesControl.SetWindowText( str ); + + // Now count the various types. + int nDisabled = 0, nWorking = 0, nWaiting = 0, nOff = 0; + FOR_EACH_LL( m_Services, i ) + { + if ( m_Services[i]->IsOff() ) + { + ++nOff; + } + else if ( m_Services[i]->m_iState == VMPI_STATE_BUSY || m_Services[i]->m_iState == VMPI_STATE_DOWNLOADING ) + { + ++nWorking; + } + else if ( m_Services[i]->m_iState == VMPI_STATE_IDLE ) + { + ++nWaiting; + } + else + { + ++nDisabled; + } + } + + Q_snprintf( str, sizeof( str ), "%d", nDisabled ); + m_NumDisabledServicesControl.SetWindowText( str ); + + Q_snprintf( str, sizeof( str ), "%d", nWorking ); + m_NumWorkingServicesControl.SetWindowText( str ); + + Q_snprintf( str, sizeof( str ), "%d", nWaiting ); + m_NumWaitingServicesControl.SetWindowText( str ); + + Q_snprintf( str, sizeof( str ), "%d", nOff ); + m_NumOffServicesControl.SetWindowText( str ); +} + + +// This monstrosity is here because of the way they bundle string resources into groups in an exe file. +// See http://support.microsoft.com/kb/q196774/. +bool FindStringResourceEx( HINSTANCE hinst, UINT uId, UINT langId, char *pStr, int outLen ) +{ + // Convert the string ID into a bundle number + bool bRet = false; + HRSRC hrsrc = FindResourceEx(hinst, RT_STRING, MAKEINTRESOURCE(uId / 16 + 1), langId); + if (hrsrc) + { + HGLOBAL hglob = LoadResource(hinst, hrsrc); + if (hglob) + { + LPCWSTR pwsz = reinterpret_cast<LPCWSTR>( LockResource(hglob) ); + if (pwsz) + { + // okay now walk the string table + for (UINT i = 0; i < (uId & 15); i++) + { + pwsz += 1 + (UINT)*pwsz; + } + + // First word in the resource is the length and the rest is the data. + int nChars = min( (int)pwsz[0], outLen-1 ); + ++pwsz; + V_wcstostr( pwsz, nChars, pStr, outLen ); + pStr[nChars] = 0; + bRet = true; + } + FreeResource(hglob); + } + } + return bRet; +} + + +int CheckServiceVersion( const char *pPatchDir, char *pServiceVersion, int maxServiceVersionLen ) +{ + char filename[MAX_PATH]; + V_ComposeFileName( pPatchDir, "vmpi_service.exe", filename, sizeof( filename ) ); + + int ret = IDCANCEL; + HINSTANCE hInst = LoadLibrary( filename ); + if ( hInst ) + { + bool bFound = FindStringResourceEx( hInst, VMPI_SERVICE_IDS_VERSION_STRING, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), pServiceVersion, maxServiceVersionLen ); + if ( bFound ) + { + ret = V_AfxMessageBox( MB_YESNOCANCEL, "Service version in %s is %s.\n\nIs this correct?", filename, pServiceVersion ); + } + else + { + V_AfxMessageBox( MB_OK, "Can't get IDS_VERSION_STRING resource from %s.", filename ); + } + + FreeLibrary( hInst ); + } + else + { + V_AfxMessageBox( MB_OK, "Can't load %s to get service version.", filename ); + } + + return ret; +} + +void CServicesDlg::OnPatchServices() +{ + // Inquire about the timeout. + CPatchTimeout dlg; + dlg.m_PatchDirectory = "\\\\fileserver\\vmpi\\testservice"; + dlg.m_VMPITransferDirectory = dlg.m_PatchDirectory; + dlg.m_bForcePatch = false; + +TryAgain:; + + if ( dlg.DoModal() == IDOK ) + { + // Launch the transfer app. + char commandLine[32 * 1024] = {0}; + + char transferExe[MAX_PATH]; + V_ComposeFileName( dlg.m_VMPITransferDirectory, "vmpi_transfer.exe", transferExe, sizeof( transferExe ) ); + if ( _access( transferExe, 0 ) != 0 ) + { + V_AfxMessageBox( MB_OK, "Can't find '%s' to run the patch.", transferExe ); + goto TryAgain; + } + + char strServiceVersion[64]; + int ret = CheckServiceVersion( dlg.m_PatchDirectory, strServiceVersion, sizeof( strServiceVersion ) ); + if ( ret == IDCANCEL ) + return; + else if ( ret == IDNO ) + goto TryAgain; + + AppendStr( commandLine, sizeof( commandLine ), "\"%s\" -PatchHost", transferExe ); + AppendStr( commandLine, sizeof( commandLine ), " -mpi_PatchVersion %s", strServiceVersion ); + AppendStr( commandLine, sizeof( commandLine ), " -mpi_PatchDirectory \"%s\"", (const char*)dlg.m_PatchDirectory ); + + if ( dlg.m_bForcePatch ) + AppendStr( commandLine, sizeof( commandLine ), " -mpi_ForcePatch" ); + + // Collect the list of addresses. + CUtlVector<CIPAddr> addrs; + POSITION pos = m_ServicesList.GetFirstSelectedItemPosition(); + while ( pos ) + { + int iItem = m_ServicesList.GetNextSelectedItem( pos ); + + CServiceInfo *pInfo = (CServiceInfo*)m_ServicesList.GetItemData( iItem ); + if ( pInfo->m_Addr.ip[0] != 0 ) // "off" services won't have an IP + addrs.AddToTail( pInfo->m_Addr ); + } + if ( addrs.Count() == 0 ) + { + AfxMessageBox( "No workers selected, or they all are off." ); + return; + } + + AppendStr( commandLine, sizeof( commandLine ), " -mpi_PatchWorkers %d", addrs.Count() ); + for ( int i=0; i < addrs.Count(); i++ ) + { + AppendStr( commandLine, sizeof( commandLine ), " %d.%d.%d.%d", addrs[i].ip[0], addrs[i].ip[1], addrs[i].ip[2], addrs[i].ip[3] ); + } + + STARTUPINFO si; + memset( &si, 0, sizeof( si ) ); + si.cb = sizeof( si ); + + PROCESS_INFORMATION pi; + memset( &pi, 0, sizeof( pi ) ); + + if ( CreateProcess( NULL, commandLine, + NULL, NULL, false, + 0, + NULL, + (const char *)dlg.m_PatchDirectory, + &si, + &pi ) ) + { + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + + V_AfxMessageBox( MB_OK, "Patch master successfully started.\nServices patching now.\nClose the patch master console app when finished." ); + } + else + { + V_AfxMessageBox( MB_OK, "Error starting patch master: %s", GetLastErrorString() ); + } + } +} + + +void CServicesDlg::OnStopServices() +{ + if ( MessageBox( "Warning: if you stop these services, you won't be able to control them from this application, and must restart them manually. Contine?", "Warning", MB_YESNO ) == IDYES ) + { + CUtlVector<char> data; + BuildVMPIPingPacket( data, VMPI_STOP_SERVICE ); + SendToSelectedServices( data.Base(), data.Count() ); + } +} + +void CServicesDlg::OnStopJobs() +{ + CUtlVector<char> data; + BuildVMPIPingPacket( data, VMPI_KILL_PROCESS ); + SendToSelectedServices( data.Base(), data.Count() ); +} + + +void CServicesDlg::OnFilterByPassword() +{ + CSetPasswordDlg dlg( IDD_SET_PASSWORD ); + dlg.m_Password = m_Password; + + if ( dlg.DoModal() == IDOK ) + { + m_Password = dlg.m_Password; + m_PasswordDisplay.SetWindowText( m_Password ); + + m_Services.PurgeAndDeleteElements(); + m_ServicesList.DeleteAllItems(); + + UpdateServiceCountDisplay(); + + // Re-ping everyone immediately. + m_dwLastServicesPing = GetTickCount() - SERVICES_PING_INTERVAL; + } +} + +// This sets a new password on the selected services. +void CServicesDlg::OnForcePassword() +{ + CSetPasswordDlg dlg( IDD_FORCE_PASSWORD ); + dlg.m_Password = "password"; + + if ( dlg.DoModal() == IDOK ) + { + CUtlVector<char> data; + + BuildVMPIPingPacket( data, VMPI_FORCE_PASSWORD_CHANGE, VMPI_PROTOCOL_VERSION, true ); + const char *pNewPassword = dlg.m_Password; + data.AddMultipleToTail( V_strlen( pNewPassword ) + 1, pNewPassword ); + + SendToSelectedServices( data.Base(), data.Count() ); + } +} + +void CServicesDlg::OnDblclkServicesList(NMHDR* pNMHDR, LRESULT* pResult) +{ + POSITION pos = m_ServicesList.GetFirstSelectedItemPosition(); + if ( pos ) + { + int iItem = m_ServicesList.GetNextSelectedItem( pos ); + if ( iItem != -1 ) + { + CServiceInfo *pInfo = (CServiceInfo*)m_ServicesList.GetItemData( iItem ); + if ( pInfo ) + { + // Launch vmpi_browser_job_search and have it auto-select this worker. + char cmdLine[1024]; + Q_snprintf( cmdLine, sizeof( cmdLine ), "vmpi_job_search -SelectWorker %s", (const char*)pInfo->m_ComputerName ); + + STARTUPINFO si; + memset( &si, 0, sizeof( si ) ); + si.cb = sizeof( si ); + + PROCESS_INFORMATION pi; + memset( &pi, 0, sizeof( pi ) ); + + if ( !CreateProcess( + NULL, + (char*)(const char*)cmdLine, + NULL, // security + NULL, + TRUE, + 0, // flags + NULL, // environment + NULL, // current directory + &si, + &pi ) ) + { + char err[512]; + Q_snprintf( err, sizeof( err ), "Can't run '%s'", (LPCTSTR)cmdLine ); + MessageBox( err, "Error", MB_OK ); + } + } + } + } + + *pResult = 0; +} + +void CServicesDlg::OnSize(UINT nType, int cx, int cy) +{ + CIdleDialog::OnSize(nType, cx, cy); + + m_AnchorMgr.UpdateAnchors( this ); +} + + +BOOL CServicesDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) +{ + NMHDR *pHdr = (NMHDR*)lParam; + if ( pHdr->idFrom == IDC_SERVICES_LIST ) + { + if ( pHdr->code == LVN_COLUMNCLICK ) + { + LPNMLISTVIEW pListView = (LPNMLISTVIEW)lParam; + + // Now sort by this column. + int iSortColumn = max( 0, min( pListView->iSubItem, (int)ARRAYSIZE( g_ColumnInfos ) - 1 ) ); + PushSortColumn( iSortColumn ); + ResortItems(); + } + } + + return CIdleDialog::OnNotify(wParam, lParam, pResult); +} + + +void CServicesDlg::BuildClipboardText( CUtlVector<char> &clipboardText ) +{ + // Add the header information. + CHeaderCtrl *pHeader = m_ServicesList.GetHeaderCtrl(); + for ( int i=0; i < pHeader->GetItemCount(); i++ ) + { + char tempBuffer[512]; + HDITEM item; + memset( &item, 0, sizeof( item ) ); + item.mask = HDI_TEXT; + item.pszText = tempBuffer; + item.cchTextMax = sizeof( tempBuffer ) - 1; + + if ( !pHeader->GetItem( i, &item ) ) + item.pszText = "<bug>"; + + clipboardText.AddMultipleToTail( strlen( item.pszText ), item.pszText ); + clipboardText.AddToTail( '\t' ); + } + clipboardText.AddMultipleToTail( 2, "\r\n" ); + + // Now add each line of data. + int nItem = -1; + while ( (nItem = m_ServicesList.GetNextItem( nItem, LVNI_ALL )) != -1 ) + { + char tempBuffer[512]; + LVITEM item; + memset( &item, 0, sizeof( item ) ); + item.mask = LVIF_TEXT; + item.iItem = nItem; + item.pszText = tempBuffer; + item.cchTextMax = sizeof( tempBuffer ) - 1; + + for ( int i=0; i < pHeader->GetItemCount(); i++ ) + { + item.iSubItem = i; + if ( !m_ServicesList.GetItem( &item ) ) + { + item.pszText = "<bug>"; + } + + clipboardText.AddMultipleToTail( strlen( item.pszText ), item.pszText ); + clipboardText.AddToTail( '\t' ); + } + clipboardText.AddMultipleToTail( 2, "\r\n" ); + } + clipboardText.AddToTail( 0 ); +} + + +void CServicesDlg::OnCopyToClipboard() +{ + // Open and clear the clipboard. + if ( !OpenClipboard() ) + return; + + EmptyClipboard(); + + // Setup the clipboard text. + CUtlVector<char> clipboardText; + BuildClipboardText( clipboardText ); + + // Put the clipboard text into a global memory object. + HANDLE hMem = GlobalAlloc( GMEM_MOVEABLE, clipboardText.Count() ); + void *ptr = GlobalLock( hMem ); + memcpy( ptr, clipboardText.Base(), clipboardText.Count() ); + GlobalUnlock( hMem ); + + // Put it in the clipboard. + SetClipboardData( CF_TEXT, hMem ); + + // Cleanup. + GlobalFree( hMem ); + CloseClipboard(); +} diff --git a/utils/vmpi/vmpi_services_watch/ServicesDlg.h b/utils/vmpi/vmpi_services_watch/ServicesDlg.h new file mode 100644 index 0000000..8ff35e3 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/ServicesDlg.h @@ -0,0 +1,150 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#if !defined(AFX_SERVICESDLG_H__FD755233_0A7A_4CBB_BA5E_A5D0B3B5F830__INCLUDED_) +#define AFX_SERVICESDLG_H__FD755233_0A7A_4CBB_BA5E_A5D0B3B5F830__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ServicesDlg.h : header file +// + +#include "iphelpers.h" +#include "idle_dialog.h" +#include "utllinkedlist.h" +#include "resource.h" +#include "window_anchor_mgr.h" +#include "net_view_thread.h" +#include "vmpi_defs.h" + + +class CServiceInfo +{ +public: + + bool IsOff() const; // Returns true if the time since we've heard from this guy is too long. + + +public: + + CString m_ComputerName; + CString m_MasterName; + CString m_Password; + int m_iState; + + // Since the live time is always changing, we only update it every 10 seconds or so. + DWORD m_LiveTimeMS; // How long the service has been running (in milliseconds). + + DWORD m_WorkerAppTimeMS; // How long the worker app has been running (0 if it's not running). + + DWORD m_LastPingTimeMS; // Last time we heard from this machine. Used to detect if the service + // is off or not. + + // Used to detect if we need to re-sort the list. + const char *m_pLastStatusText; + DWORD m_LastLiveTimeMS; + CString m_LastMasterName; + + int m_CPUPercentage; + CString m_ExeName; + CString m_MapName; + int m_MemUsageMB; + + // Last time we updated the service in the listbox.. used to make sure we update its on/off status + // every once in a while. + DWORD m_LastUpdateTime; + + int m_ProtocolVersion; // i.e. the service's VMPI_SERVICE_PROTOCOL_VERSION. + char m_ServiceVersion[32]; // Version string. + + CIPAddr m_Addr; +}; + + + +///////////////////////////////////////////////////////////////////////////// +// CServicesDlg dialog + +class CServicesDlg : public CIdleDialog +{ +// Construction +public: + CServicesDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CServicesDlg) + enum { IDD = IDD_SERVICES }; + CStatic m_NumServicesControl; + CStatic m_NumDisabledServicesControl; + CStatic m_NumWorkingServicesControl; + CStatic m_NumWaitingServicesControl; + CStatic m_NumOffServicesControl; + CStatic m_PasswordDisplay; + CListCtrl m_ServicesList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CServicesDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + //}}AFX_VIRTUAL + +// Implementation +protected: + void BuildVMPIPingPacket( CUtlVector<char> &out, char cPacketID, unsigned char cProtocolVersion=VMPI_PROTOCOL_VERSION, bool bIgnorePassword=false ); + + virtual void OnIdle(); + + + CServiceInfo* FindServiceByComputerName( const char *pComputerName ); + void SendToSelectedServices( const char *pData, int len ); + void UpdateServiceInListbox( CServiceInfo *pInfo ); + void UpdateServiceCountDisplay(); + void ResortItems(); + + void UpdateServicesFromNetMessages(); + void UpdateServicesFromNetView(); + void BuildClipboardText( CUtlVector<char> &clipboardText ); + + + ISocket *m_pServicesPingSocket; + DWORD m_dwLastServicesPing; // Last time we pinged all the services. + + // Restricts the password so we only see a particular set of VMPI services. + CString m_Password; + + CUtlLinkedList<CServiceInfo*, int> m_Services; + CNetViewThread m_NetViewThread; + + + CWindowAnchorMgr m_AnchorMgr; + + bool m_bListChanged; // Used to detect if we need to re-sort the list. + + // Generated message map functions + //{{AFX_MSG(CServicesDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPatchServices(); + afx_msg void OnStopServices(); + afx_msg void OnStopJobs(); + afx_msg void OnFilterByPassword(); + afx_msg void OnForcePassword(); + afx_msg void OnCopyToClipboard(); + afx_msg void OnDblclkServicesList(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SERVICESDLG_H__FD755233_0A7A_4CBB_BA5E_A5D0B3B5F830__INCLUDED_) diff --git a/utils/vmpi/vmpi_services_watch/SetPasswordDlg.cpp b/utils/vmpi/vmpi_services_watch/SetPasswordDlg.cpp new file mode 100644 index 0000000..ebe0b6a --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/SetPasswordDlg.cpp @@ -0,0 +1,49 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// SetPasswordDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "SetPasswordDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSetPasswordDlg dialog + + +CSetPasswordDlg::CSetPasswordDlg(int dlgID, CWnd* pParent /*=NULL*/) + : CDialog(dlgID, pParent) +{ + //{{AFX_DATA_INIT(CSetPasswordDlg) + m_Password = _T(""); + //}}AFX_DATA_INIT +} + + +void CSetPasswordDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSetPasswordDlg) + DDX_Text(pDX, IDC_PASSWORD, m_Password); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSetPasswordDlg, CDialog) + //{{AFX_MSG_MAP(CSetPasswordDlg) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSetPasswordDlg message handlers diff --git a/utils/vmpi/vmpi_services_watch/SetPasswordDlg.h b/utils/vmpi/vmpi_services_watch/SetPasswordDlg.h new file mode 100644 index 0000000..f738af1 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/SetPasswordDlg.h @@ -0,0 +1,54 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#if !defined(AFX_SETPASSWORDDLG_H__A349B943_49B8_4C7E_863B_BF1929AD5443__INCLUDED_) +#define AFX_SETPASSWORDDLG_H__A349B943_49B8_4C7E_863B_BF1929AD5443__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SetPasswordDlg.h : header file +// + +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// CSetPasswordDlg dialog + +class CSetPasswordDlg : public CDialog +{ +// Construction +public: + CSetPasswordDlg(int dlgID, CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CSetPasswordDlg) + CString m_Password; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSetPasswordDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSetPasswordDlg) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SETPASSWORDDLG_H__A349B943_49B8_4C7E_863B_BF1929AD5443__INCLUDED_) diff --git a/utils/vmpi/vmpi_services_watch/StdAfx.cpp b/utils/vmpi/vmpi_services_watch/StdAfx.cpp new file mode 100644 index 0000000..5ee32bc --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/StdAfx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// vmpi_browser_services.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/utils/vmpi/vmpi_services_watch/StdAfx.h b/utils/vmpi/vmpi_services_watch/StdAfx.h new file mode 100644 index 0000000..a73914f --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/StdAfx.h @@ -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__BC4FB757_77BB_4E3A_8842_290307F41798__INCLUDED_) +#define AFX_STDAFX_H__BC4FB757_77BB_4E3A_8842_290307F41798__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include "tier0/wchartypes.h" +#include <afxwin.h> // MFC core and standard components +#include <afxext.h> // MFC extensions +#include <afxdisp.h> // MFC Automation classes +#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include <afxcmn.h> // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__BC4FB757_77BB_4E3A_8842_290307F41798__INCLUDED_) diff --git a/utils/vmpi/vmpi_services_watch/res/vmpi.ico b/utils/vmpi/vmpi_services_watch/res/vmpi.ico Binary files differnew file mode 100644 index 0000000..09720c0 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/res/vmpi.ico diff --git a/utils/vmpi/vmpi_services_watch/res/vmpi_browser_services.ico b/utils/vmpi/vmpi_services_watch/res/vmpi_browser_services.ico Binary files differnew file mode 100644 index 0000000..7eef0bc --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/res/vmpi_browser_services.ico diff --git a/utils/vmpi/vmpi_services_watch/res/vmpi_browser_services.rc2 b/utils/vmpi/vmpi_services_watch/res/vmpi_browser_services.rc2 new file mode 100644 index 0000000..a322a2e --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/res/vmpi_browser_services.rc2 @@ -0,0 +1,13 @@ +// +// VMPI_BROWSER_SERVICES.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/utils/vmpi/vmpi_services_watch/resource.h b/utils/vmpi/vmpi_services_watch/resource.h new file mode 100644 index 0000000..1f172da --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/resource.h @@ -0,0 +1,48 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by vmpi_browser_services.rc +// +#define IDD_VMPI_BROWSER_SERVICES_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDD_SET_PASSWORD 130 +#define IDD_SERVICES 133 +#define IDD_TIMEOUT 134 +#define IDD_FORCE_PASSWORD 135 +#define IDC_CURRENT_PASSWORD_LABEL 1000 +#define IDC_PASSWORD 1001 +#define IDC_NUM_SERVICES_LABEL 1001 +#define IDC_NUM_DISABLED_SERVICES_LABEL 1002 +#define IDC_COMMAND_LINE 1002 +#define IDC_NUM_WORKING_SERVICES_LABEL 1003 +#define IDC_VMPI_TRANSFER_DIRECTORY 1003 +#define IDC_NUM_WAITING_SERVICES_LABEL 1004 +#define IDC_CHECK1 1004 +#define IDC_FORCE_PATCH 1004 +#define IDC_TIMEOUT_SECONDS 1005 +#define IDC_NUM_OFF_SERVICES_LABEL 1005 +#define IDC_SERVICES_LIST 1009 +#define ID_PATCH_SERVICES 1010 +#define ID_STOP_SERVICES 1011 +#define ID_STOP_JOBS 1012 +#define ID_CHANGE_PASSWORD 1013 +#define ID_FILTER_BY_PASSWORD 1013 +#define IDC_CURRENT_PASSWORD 1014 +#define ID_COPY_TO_CLIPBOARD 1015 +#define IDC_NUM_SERVICES 1016 +#define IDC_NUM_DISABLED_SERVICES 1017 +#define IDC_NUM_WORKING_SERVICES 1018 +#define IDC_NUM_WAITING_SERVICES 1019 +#define IDC_NUM_OFF_SERVICES 1020 +#define ID_FORCE_PASSWORD 1022 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1005 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/utils/vmpi/vmpi_services_watch/vmpi_browser_services.cpp b/utils/vmpi/vmpi_services_watch/vmpi_browser_services.cpp new file mode 100644 index 0000000..168e4ef --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/vmpi_browser_services.cpp @@ -0,0 +1,81 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// vmpi_browser_services.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "vmpi_browser_services.h" +#include "ServicesDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CVMPIBrowserServicesApp + +BEGIN_MESSAGE_MAP(CVMPIBrowserServicesApp, CWinApp) + //{{AFX_MSG_MAP(CVMPIBrowserServicesApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CVMPIBrowserServicesApp construction + +CVMPIBrowserServicesApp::CVMPIBrowserServicesApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CVMPIBrowserServicesApp object + +CVMPIBrowserServicesApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CVMPIBrowserServicesApp initialization + +BOOL CVMPIBrowserServicesApp::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + CServicesDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/utils/vmpi/vmpi_services_watch/vmpi_browser_services.h b/utils/vmpi/vmpi_services_watch/vmpi_browser_services.h new file mode 100644 index 0000000..6bfe0f8 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/vmpi_browser_services.h @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// vmpi_browser_services.h : main header file for the VMPI_BROWSER_SERVICES application +// + +#if !defined(AFX_VMPI_BROWSER_SERVICES_H__B03E2165_4E70_48AC_A991_EB0289A3471E__INCLUDED_) +#define AFX_VMPI_BROWSER_SERVICES_H__B03E2165_4E70_48AC_A991_EB0289A3471E__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CVMPIBrowserServicesApp: +// See vmpi_browser_services.cpp for the implementation of this class +// + +class CVMPIBrowserServicesApp : public CWinApp +{ +public: + CVMPIBrowserServicesApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CVMPIBrowserServicesApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CVMPIBrowserServicesApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VMPI_BROWSER_SERVICES_H__B03E2165_4E70_48AC_A991_EB0289A3471E__INCLUDED_) diff --git a/utils/vmpi/vmpi_services_watch/vmpi_browser_services.rc b/utils/vmpi/vmpi_services_watch/vmpi_browser_services.rc new file mode 100644 index 0000000..e3e3245 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/vmpi_browser_services.rc @@ -0,0 +1,249 @@ +// 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 + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\vmpi_browser_services.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\vmpi.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "FileDescription", "vmpi_browser_services MFC Application" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "vmpi_browser_services" + VALUE "LegalCopyright", "Copyright (C) 2003" + VALUE "OriginalFilename", "vmpi_browser_services.EXE" + VALUE "ProductName", "vmpi_browser_services Application" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SERVICES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 791 + TOPMARGIN, 7 + BOTTOMMARGIN, 246 + END + + IDD_TIMEOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 355 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_SET_PASSWORD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 212 + TOPMARGIN, 7 + BOTTOMMARGIN, 91 + END + + IDD_FORCE_PASSWORD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 212 + TOPMARGIN, 7 + BOTTOMMARGIN, 71 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SERVICES DIALOGEX 0, 0, 798, 253 +STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "VMPI Services" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + CONTROL "List1",IDC_SERVICES_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP,7,7,784,155 + DEFPUSHBUTTON "Filter By Password",ID_FILTER_BY_PASSWORD,715,166,76,14 + DEFPUSHBUTTON "Copy To Clipboard",ID_COPY_TO_CLIPBOARD,7,232,76,14 + DEFPUSHBUTTON "Force Password",ID_FORCE_PASSWORD,184,232,76,14 + DEFPUSHBUTTON "Stop Service(s)",ID_STOP_SERVICES,361,232,76,14 + DEFPUSHBUTTON "Stop Job(s)",ID_STOP_JOBS,538,232,76,14 + DEFPUSHBUTTON "Patch Services",ID_PATCH_SERVICES,715,232,76,14 + LTEXT "Filtering By Password:",IDC_CURRENT_PASSWORD_LABEL,128,169,70,8 + LTEXT "",IDC_CURRENT_PASSWORD,198,169,55,8 + LTEXT "# Machines:",IDC_NUM_SERVICES_LABEL,7,169,40,8 + LTEXT "2",IDC_NUM_SERVICES,47,169,55,8 + LTEXT "# Disabled:",IDC_NUM_DISABLED_SERVICES_LABEL,7,181,37,8 + LTEXT "2",IDC_NUM_DISABLED_SERVICES,47,181,55,8 + LTEXT "# Working:",IDC_NUM_WORKING_SERVICES_LABEL,7,192,36,8 + LTEXT "2",IDC_NUM_WORKING_SERVICES,47,192,55,8 + LTEXT "# Waiting:",IDC_NUM_WAITING_SERVICES_LABEL,7,203,34,8 + LTEXT "2",IDC_NUM_WAITING_SERVICES,47,203,55,8 + LTEXT "# Off:",IDC_NUM_OFF_SERVICES_LABEL,7,214,19,8 + LTEXT "2",IDC_NUM_OFF_SERVICES,47,214,55,8 +END + +IDD_TIMEOUT DIALOGEX 0, 0, 362, 166 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Patch" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_COMMAND_LINE,93,78,262,14,ES_AUTOHSCROLL + EDITTEXT IDC_VMPI_TRANSFER_DIRECTORY,93,98,262,14,ES_AUTOHSCROLL + CONTROL "Force Patch (otherwise, the service will ignore the patch if the new version is not higher)",IDC_FORCE_PATCH, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,121,291,10 + DEFPUSHBUTTON "OK",IDOK,123,145,50,14 + PUSHBUTTON "Cancel",IDCANCEL,189,145,50,14 + LTEXT "This will setup all the selected services to be patched.",IDC_STATIC,7,7,348,11 + LTEXT "Patch Directory:",IDC_STATIC,7,81,52,8 + LTEXT "First, it will run vmpi_transfer from the VMPI_Transfer directory. This is kept separate because the vmpi_transfer.exe in that directory might be a different version than the new one in the patch directory.",IDC_STATIC,7,21,348,18 + LTEXT "VMPI_Transfer Directory:",IDC_STATIC,7,101,80,8 + LTEXT "The selected services will download the patch files, then run vmpi_service_install.",IDC_STATIC,7,42,348,13 +END + +IDD_SET_PASSWORD DIALOGEX 0, 0, 219, 98 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Filter By Password" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_PASSWORD,7,56,205,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,7,77,50,14 + PUSHBUTTON "Cancel",IDCANCEL,162,77,50,14 + LTEXT "This will cause the services browser to only show services that are using the specified password.\n\nIf you enter a blank password, then all services will be shown regardless of their password.",IDC_CURRENT_PASSWORD_LABEL,7,7,195,46 +END + +IDD_FORCE_PASSWORD DIALOGEX 0, 0, 219, 78 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Force Password" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_PASSWORD,7,38,205,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,7,57,50,14 + PUSHBUTTON "Cancel",IDCANCEL,162,57,50,14 + LTEXT "This will set the specified password on all selected services. VMPI jobs must run with -mpi_pw <password> to use those services.",IDC_CURRENT_PASSWORD_LABEL,7,7,195,27 +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\vmpi_browser_services.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/utils/vmpi/vmpi_services_watch/vmpi_services_watch.vpc b/utils/vmpi/vmpi_services_watch/vmpi_services_watch.vpc new file mode 100644 index 0000000..a58e2a6 --- /dev/null +++ b/utils/vmpi/vmpi_services_watch/vmpi_services_watch.vpc @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// vmpi_services_watch.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" +$Macro OUTBINNAME "vmpi_services_watch" + +$Include "$SRCDIR\vpc_scripts\source_exe_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE;.\;..\;..\..\common" + $PreprocessorDefinitions "$BASE;PROTECTED_THINGS_DISABLE;WINVER=0x501;NO_WARN_MBCS_MFC_DEPRECATION" + $EnableC++Exceptions "Yes (/EHsc)" + } + + $Linker + { + $AdditionalDependencies "$BASE ws2_32.lib" + } +} + +$Project "vmpi_services_watch" +{ + $Folder "Source Files" + { + -$File "$SRCDIR\public\tier0\memoverride.cpp" + + $File "..\idle_dialog.cpp" + $File "..\net_view_thread.cpp" + $File "PatchTimeout.cpp" + $File "ServicesDlg.cpp" + $File "SetPasswordDlg.cpp" + $File "..\vmpi_browser_helpers.cpp" + $File "vmpi_browser_services.cpp" + $File "vmpi_browser_services.rc" + $File "..\win_idle.cpp" + $File "..\window_anchor_mgr.cpp" + $File "StdAfx.cpp" + } + + $Folder "Header Files" + { + $File "..\idle_dialog.h" + $File "..\net_view_thread.h" + $File "PatchTimeout.h" + $File "Resource.h" + $File "ServicesDlg.h" + $File "SetPasswordDlg.h" + $File "StdAfx.h" + $File "vmpi_browser_services.h" + $File "..\vmpi_defs.h" + $File "..\win_idle.h" + $File "..\window_anchor_mgr.h" + } + + $Folder "Resources" + { + $File "res\vmpi_browser_services.ico" + $File "res\vmpi_browser_services.rc2" + } + + $Folder "Link Libraries" + { + $Lib vmpi + } +} |