summaryrefslogtreecommitdiff
path: root/utils/vmpi/vmpi_service_ui
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/vmpi/vmpi_service_ui
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/vmpi/vmpi_service_ui')
-rw-r--r--utils/vmpi/vmpi_service_ui/StdAfx.cpp15
-rw-r--r--utils/vmpi/vmpi_service_ui/StdAfx.h30
-rw-r--r--utils/vmpi/vmpi_service_ui/idi_busy_icon.icobin0 -> 318 bytes
-rw-r--r--utils/vmpi/vmpi_service_ui/idi_disabled_icon.icobin0 -> 318 bytes
-rw-r--r--utils/vmpi/vmpi_service_ui/idi_waiting_icon.icobin0 -> 318 bytes
-rw-r--r--utils/vmpi/vmpi_service_ui/resource.h47
-rw-r--r--utils/vmpi/vmpi_service_ui/shell_icon_mgr.cpp187
-rw-r--r--utils/vmpi/vmpi_service_ui/shell_icon_mgr.h66
-rw-r--r--utils/vmpi/vmpi_service_ui/unconnec.icobin0 -> 318 bytes
-rw-r--r--utils/vmpi/vmpi_service_ui/vmpi_service.icobin0 -> 1078 bytes
-rw-r--r--utils/vmpi/vmpi_service_ui/vmpi_service_ui.cpp617
-rw-r--r--utils/vmpi/vmpi_service_ui/vmpi_service_ui.rc171
-rw-r--r--utils/vmpi/vmpi_service_ui/vmpi_service_ui.vpc58
13 files changed, 1191 insertions, 0 deletions
diff --git a/utils/vmpi/vmpi_service_ui/StdAfx.cpp b/utils/vmpi/vmpi_service_ui/StdAfx.cpp
new file mode 100644
index 0000000..d22d5d4
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/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_service_ui.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
diff --git a/utils/vmpi/vmpi_service_ui/StdAfx.h b/utils/vmpi/vmpi_service_ui/StdAfx.h
new file mode 100644
index 0000000..31b5d12
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/StdAfx.h
@@ -0,0 +1,30 @@
+//========= 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__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
+#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__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>
+
+
+// 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__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
diff --git a/utils/vmpi/vmpi_service_ui/idi_busy_icon.ico b/utils/vmpi/vmpi_service_ui/idi_busy_icon.ico
new file mode 100644
index 0000000..ac62654
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/idi_busy_icon.ico
Binary files differ
diff --git a/utils/vmpi/vmpi_service_ui/idi_disabled_icon.ico b/utils/vmpi/vmpi_service_ui/idi_disabled_icon.ico
new file mode 100644
index 0000000..e49e952
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/idi_disabled_icon.ico
Binary files differ
diff --git a/utils/vmpi/vmpi_service_ui/idi_waiting_icon.ico b/utils/vmpi/vmpi_service_ui/idi_waiting_icon.ico
new file mode 100644
index 0000000..a52165d
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/idi_waiting_icon.ico
Binary files differ
diff --git a/utils/vmpi/vmpi_service_ui/resource.h b/utils/vmpi/vmpi_service_ui/resource.h
new file mode 100644
index 0000000..95b752b
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/resource.h
@@ -0,0 +1,47 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vmpi_service_ui.rc
+//
+#define IDC_MYICON 2
+#define IDI_DISABLED_ICON 101
+#define IDD_VMPI_SERVICE_DIALOG 102
+#define IDI_BUSY_ICON 102
+#define IDD_ABOUTBOX 103
+#define IDS_APP_TITLE 103
+#define IDR_POPUP_MENU 103
+#define IDM_ABOUT 104
+#define IDM_EXIT 105
+#define IDI_WAITING_ICON 105
+#define IDS_HELLO 106
+#define IDI_VMPI_SERVICE 107
+#define IDI_SMALL 108
+#define IDC_VMPI_SERVICE 109
+#define IDR_MAINFRAME 128
+#define IDD_VMPI_SERVICE 129
+#define IDD_SET_PASSWORD 130
+#define IDI_UNCONNECTED 132
+#define ID_KILLCURRENTJOB 133
+#define IDC_DEBUG_OUTPUT 1000
+#define IDC_PASSWORD 1001
+#define ID_SET_PASSWORD 32771
+#define ID_IGNORECSXCOMPILES 32772
+#define ID_HIGHLIGHT_ICON_WHEN_BUSY 32773
+#define ID_SCREENSAVER_MODE 32774
+#define ID_ENABLE_WORKER 40001
+#define ID_DISABLE_WORKER 40003
+#define ID_EXIT_SERVICE 40004
+#define ID_SHOW_CONSOLE_WINDOW 40005
+#define ID_HIDE_CONSOLE_WINDOW 40006
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 133
+#define _APS_NEXT_COMMAND_VALUE 32775
+#define _APS_NEXT_CONTROL_VALUE 1002
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/utils/vmpi/vmpi_service_ui/shell_icon_mgr.cpp b/utils/vmpi/vmpi_service_ui/shell_icon_mgr.cpp
new file mode 100644
index 0000000..cfdf759
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/shell_icon_mgr.cpp
@@ -0,0 +1,187 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "stdafx.h"
+#include "shell_icon_mgr.h"
+#include "tier1/strtools.h"
+#include "tier0/dbg.h"
+#include "shellapi.h"
+
+
+#define SHELLICONMGR_CLASSNAME "VMPI_ShellIconMgr"
+
+
+
+CShellIconMgr::CShellIconMgr()
+{
+ m_hWnd = NULL;
+ m_hWndClass = NULL;
+ m_uTaskbarRestart = (UINT)-1;
+ m_iCurIconResourceID = 0;
+ m_pHelper = NULL;
+}
+
+
+CShellIconMgr::~CShellIconMgr()
+{
+ Term();
+}
+
+
+bool CShellIconMgr::Init(
+ IShellIconMgrHelper *pHelper,
+ const char *pToolTip,
+ int iCallbackMessage,
+ int iIconResourceID )
+{
+ Term();
+
+ m_pHelper = pHelper;
+ m_iCallbackMessage = iCallbackMessage;
+ m_pToolTip = pToolTip;
+
+ // Create the window class.
+ WNDCLASS wndclass;
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.lpfnWndProc = &CShellIconMgr::StaticWindowProc;
+ wndclass.hInstance = (HINSTANCE)pHelper->GetHInstance();
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = SHELLICONMGR_CLASSNAME;
+ m_hWndClass = RegisterClass( &wndclass );
+ if ( !m_hWndClass )
+ {
+ Assert( false );
+ Warning( "RegisterClass failed.\n" );
+ Term();
+ return false;
+ }
+
+
+ // Create the window.
+ m_hWnd = CreateWindow(
+ SHELLICONMGR_CLASSNAME,
+ SHELLICONMGR_CLASSNAME,
+ WS_DISABLED, // we only want shell notify messages
+ 0, 0, 0, 0, // position
+ NULL, // parent
+ NULL, // menu
+ pHelper->GetHInstance(), // hInstance
+ this // lpParam
+ );
+ if ( !m_hWnd )
+ {
+ Assert( false );
+ Warning( "CreateWindow failed.\n" );
+ Term();
+ return false;
+ }
+
+ m_uTaskbarRestart = RegisterWindowMessage( TEXT( "TaskbarCreated" ) );
+ SetWindowLong( m_hWnd, GWL_USERDATA, (LONG)this );
+ UpdateWindow( m_hWnd );
+
+ // Don't handle errors here because the taskbar may not be created yet if we are a service.
+ m_iCurIconResourceID = iIconResourceID;
+ CreateTrayIcon();
+ return true;
+}
+
+
+void CShellIconMgr::Term()
+{
+ if ( m_hWndClass )
+ {
+ UnregisterClass( SHELLICONMGR_CLASSNAME, m_pHelper->GetHInstance() );
+ m_hWndClass = NULL;
+ }
+
+ if ( m_hWnd )
+ {
+ // Remove the shell icon if there is one.
+ NOTIFYICONDATA data;
+ memset( &data, 0, sizeof( data ) );
+ data.cbSize = sizeof( data );
+ data.hWnd = m_hWnd;
+ Shell_NotifyIcon( NIM_DELETE, &data );
+
+ DestroyWindow( m_hWnd );
+ m_hWnd = NULL;
+ }
+}
+
+
+void CShellIconMgr::ChangeIcon( int iIconResourceID )
+{
+ NOTIFYICONDATA data;
+
+ memset( &data, 0, sizeof( data ) );
+ data.cbSize = sizeof( data );
+ data.uFlags = NIF_ICON;
+ data.hWnd = m_hWnd;
+ data.hIcon = LoadIcon( m_pHelper->GetHInstance(), MAKEINTRESOURCE( iIconResourceID ) );
+
+ Shell_NotifyIcon( NIM_MODIFY, &data );
+
+ m_iCurIconResourceID = iIconResourceID;
+}
+
+
+void CShellIconMgr::CreateTrayIcon()
+{
+ // Now create the shell icon.
+ NOTIFYICONDATA data;
+
+ memset( &data, 0, sizeof( data ) );
+ data.cbSize = sizeof( data );
+ data.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
+ data.uCallbackMessage = m_iCallbackMessage;
+ data.hWnd = m_hWnd;
+ data.hIcon = LoadIcon( m_pHelper->GetHInstance(), MAKEINTRESOURCE( m_iCurIconResourceID ) );
+ Q_strncpy( data.szTip, m_pToolTip, sizeof( data.szTip ) );
+
+ Shell_NotifyIcon( NIM_ADD, &data );
+}
+
+
+LRESULT CShellIconMgr::WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ if ( hWnd != m_hWnd )
+ {
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+ }
+
+ if ( uMsg == m_uTaskbarRestart )
+ {
+ CreateTrayIcon();
+ return 0;
+ }
+
+ return m_pHelper->WindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+LRESULT CShellIconMgr::StaticWindowProc(
+ HWND hwnd, // handle to window
+ UINT uMsg, // message identifier
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ CShellIconMgr *pMgr = (CShellIconMgr*)GetWindowLong( hwnd, GWL_USERDATA );
+ if ( pMgr )
+ {
+ return pMgr->WindowProc( hwnd, uMsg, wParam, lParam );
+ }
+ else
+ {
+ return DefWindowProc( hwnd, uMsg, wParam, lParam );
+ }
+}
+
diff --git a/utils/vmpi/vmpi_service_ui/shell_icon_mgr.h b/utils/vmpi/vmpi_service_ui/shell_icon_mgr.h
new file mode 100644
index 0000000..81188d4
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/shell_icon_mgr.h
@@ -0,0 +1,66 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef SHELL_ICON_MGR_H
+#define SHELL_ICON_MGR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+class IShellIconMgrHelper
+{
+public:
+ virtual HINSTANCE GetHInstance() = 0;
+ virtual int WindowProc( void *hWnd, int uMsg, long wParam, long lParam ) = 0;
+};
+
+class CShellIconMgr
+{
+public:
+
+ CShellIconMgr();
+ ~CShellIconMgr();
+
+ bool Init(
+ IShellIconMgrHelper *pHelper,
+ const char *pToolTip, // This must be allocated by the caller and must be valid as
+ // long as the CShellIconMgr exists.
+ int iCallbackMessage,
+ int iIconResourceID );
+
+ void Term();
+
+ void ChangeIcon( int iIconResourceID );
+
+
+private:
+
+ void CreateTrayIcon();
+
+ LRESULT WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+ static LRESULT CALLBACK StaticWindowProc(
+ HWND hwnd, // handle to window
+ UINT uMsg, // message identifier
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ );
+
+ HWND m_hWnd; // Invisible window to get timer and shell icon messages.
+ ATOM m_hWndClass;
+
+ UINT m_uTaskbarRestart; // This message is sent to us when the taskbar is created.
+ int m_iCurIconResourceID;
+ int m_iCallbackMessage;
+ const char *m_pToolTip;
+
+ IShellIconMgrHelper *m_pHelper;
+};
+
+
+#endif // SHELL_ICON_MGR_H
diff --git a/utils/vmpi/vmpi_service_ui/unconnec.ico b/utils/vmpi/vmpi_service_ui/unconnec.ico
new file mode 100644
index 0000000..5cfdcdb
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/unconnec.ico
Binary files differ
diff --git a/utils/vmpi/vmpi_service_ui/vmpi_service.ico b/utils/vmpi/vmpi_service_ui/vmpi_service.ico
new file mode 100644
index 0000000..3868835
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/vmpi_service.ico
Binary files differ
diff --git a/utils/vmpi/vmpi_service_ui/vmpi_service_ui.cpp b/utils/vmpi/vmpi_service_ui/vmpi_service_ui.cpp
new file mode 100644
index 0000000..7bb756f
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/vmpi_service_ui.cpp
@@ -0,0 +1,617 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// vmpi_service_ui.cpp : Defines the entry point for the application.
+//
+
+#include "stdafx.h"
+#include "consolewnd.h"
+#include "resource.h"
+#include "tier0/dbg.h"
+#include "tier1/strtools.h"
+#include "shell_icon_mgr.h"
+#include "vmpi.h"
+#include "service_conn_mgr.h"
+#include <io.h>
+#include <time.h>
+
+
+
+void UpdatePopupMenuState();
+
+
+
+const char *g_pIconTooltip = VMPI_SERVICE_NAME;
+
+IConsoleWnd *g_pConsoleWnd = NULL;
+HINSTANCE g_hInstance = NULL;
+
+
+#define MYWM_NOTIFYICON (WM_APP+100)
+CShellIconMgr g_ShellIconMgr;
+
+bool g_bHighlightIconWhenBusy = false;
+
+
+// STATE THE SERVICE OWNS.
+int g_iCurState = 0; // One of the VMPI_SERVICE_STATE_ defines.
+char *g_pPassword = NULL;
+bool g_bScreensaverMode = false;
+
+
+void LogString( const char *pStr, ... )
+{
+#ifdef VMPI_SERVICE_LOGS
+ char str[4096];
+ va_list marker;
+ va_start( marker, pStr );
+ _vsnprintf( str, sizeof( str ), pStr, marker );
+ va_end( marker );
+
+ static FILE *fp = fopen( "c:\\vmpi_service_ui.log", "wt" );
+ if ( fp )
+ {
+ fprintf( fp, "%s", str );
+ fflush( fp );
+ }
+#endif
+}
+
+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), (LPTSTR) &lpMsgBuf, 0, NULL );
+ strncpy( err, (char*)lpMsgBuf, sizeof( err ) );
+ LocalFree( lpMsgBuf );
+
+ err[ sizeof( err ) - 1 ] = 0;
+ return err;
+}
+
+
+// ------------------------------------------------------------------------------------------ //
+// Persistent state in the registry.
+// ------------------------------------------------------------------------------------------ //
+void LoadStateFromRegistry()
+{
+ HKEY hKey = NULL;
+ RegCreateKey( HKEY_LOCAL_MACHINE, VMPI_SERVICE_KEY, &hKey );
+ if ( hKey )
+ {
+ DWORD val = 0;
+ DWORD type = REG_DWORD;
+ DWORD size = sizeof( val );
+ if ( RegQueryValueEx(
+ hKey,
+ "HighlightIconWhenBusy",
+ 0,
+ &type,
+ (unsigned char*)&val,
+ &size ) == ERROR_SUCCESS &&
+ type == REG_DWORD &&
+ size == sizeof( val ) )
+ {
+ g_bHighlightIconWhenBusy = (val != 0);
+ }
+ }
+}
+
+void SaveStateToRegistry()
+{
+ HKEY hKey = NULL;
+ RegCreateKey( HKEY_LOCAL_MACHINE, VMPI_SERVICE_KEY, &hKey );
+ if ( hKey )
+ {
+ DWORD val = g_bHighlightIconWhenBusy;
+ RegSetValueEx(
+ hKey,
+ "HighlightIconWhenBusy",
+ 0,
+ REG_DWORD,
+ (unsigned char*)&val,
+ sizeof( val ) );
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------ //
+// Our CServiceConnMgr packet handler.
+// ------------------------------------------------------------------------------------------ //
+
+void UpdateAppIcon()
+{
+ if ( g_iCurState == VMPI_SERVICE_STATE_IDLE )
+ {
+ g_ShellIconMgr.ChangeIcon( IDI_WAITING_ICON );
+ }
+ else if ( g_iCurState == VMPI_SERVICE_STATE_BUSY )
+ {
+ if ( g_bHighlightIconWhenBusy )
+ g_ShellIconMgr.ChangeIcon( IDI_BUSY_ICON );
+ else
+ g_ShellIconMgr.ChangeIcon( IDI_WAITING_ICON );
+ }
+ else
+ {
+ g_ShellIconMgr.ChangeIcon( IDI_DISABLED_ICON );
+ }
+}
+
+
+class CUIConnMgr : public CServiceConnMgr
+{
+public:
+ virtual void HandlePacket( const char *pData, int len );
+};
+
+
+void CUIConnMgr::HandlePacket( const char *pData, int len )
+{
+ if ( pData[0] != VMPI_SERVICE_UI_PROTOCOL_VERSION )
+ return;
+
+ int packetID = pData[1];
+
+ int offset = 2;
+ if ( packetID == VMPI_SERVICE_TO_UI_CONSOLE_TEXT )
+ {
+ Msg( &pData[offset] );
+ }
+ else if ( packetID == VMPI_SERVICE_TO_UI_STATE )
+ {
+ // Get the new state out..
+ g_iCurState = *((int*)&pData[offset]);
+ offset += 4;
+
+ LogString( "New UI state: %d.\n", g_iCurState );
+
+ // Update our icon.
+ UpdateAppIcon();
+
+ g_bScreensaverMode = (*((char*)&pData[offset]) != 0);
+ ++offset;
+
+ // Store the current password.
+ if ( g_pPassword )
+ delete [] g_pPassword;
+
+ const char *pStr = &pData[offset];
+ g_pPassword = new char[ strlen( pStr ) + 1 ];
+ strcpy( g_pPassword, pStr );
+ offset += strlen( pStr ) + 1;
+
+ UpdatePopupMenuState();
+ }
+ else if ( packetID == VMPI_SERVICE_TO_UI_PATCHING )
+ {
+ LogString( "Got a VMPI_SERVICE_TO_UI_PATCHING packet.\n" );
+
+ int bExitAfter = pData[offset];
+ ++offset;
+
+ char workingDir[MAX_PATH], commandLine[4096];
+ V_strncpy( workingDir, &pData[offset], sizeof( workingDir ) );
+ offset += V_strlen( workingDir ) + 1;
+
+ V_strncpy( commandLine, &pData[offset], sizeof( commandLine ) );
+ offset += V_strlen( commandLine ) + 1;
+
+ // Run whatever they said to run.
+ 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, CREATE_NO_WINDOW, NULL, workingDir, &si, &pi ) )
+ {
+ LogString( "CreateProcess succeeded:\n%s\n", commandLine );
+
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
+
+ if ( bExitAfter )
+ PostQuitMessage( 0 );
+ }
+ else
+ {
+ LogString( "CreateProcess failed: %s", GetLastErrorString() );
+ }
+ }
+ else if ( packetID == VMPI_SERVICE_TO_UI_EXIT )
+ {
+ // Exit.
+ PostQuitMessage( 0 );
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------ //
+// Helpers.
+// ------------------------------------------------------------------------------------------ //
+
+void InternalSpew( const char *pMsg )
+{
+ if ( g_pConsoleWnd )
+ {
+ g_pConsoleWnd->PrintToConsole( pMsg );
+ }
+
+ OutputDebugString( pMsg );
+}
+
+
+SpewRetval_t MySpewOutputFunc( SpewType_t spewType, const char *pMsg )
+{
+ // Prepend the time.
+ time_t aclock;
+ time( &aclock );
+ struct tm *newtime = localtime( &aclock );
+
+ // Get rid of the \n.
+ char timeString[512];
+ Q_strncpy( timeString, asctime( newtime ), sizeof( timeString ) );
+ char *pEnd = strstr( timeString, "\n" );
+ if ( pEnd )
+ *pEnd = 0;
+ InternalSpew( timeString );
+
+ InternalSpew( " - " );
+ InternalSpew( pMsg );
+
+ if ( spewType == SPEW_ASSERT )
+ return SPEW_DEBUGGER;
+ else if( spewType == SPEW_ERROR )
+ return SPEW_ABORT;
+ else
+ return SPEW_CONTINUE;
+}
+
+
+
+CUIConnMgr g_ConnMgr;
+
+void InitConsoleWindow()
+{
+ // Only initialize it once.
+ if ( g_pConsoleWnd )
+ return;
+
+ g_pConsoleWnd = CreateConsoleWnd(
+ g_hInstance,
+ IDD_VMPI_SERVICE,
+ IDC_DEBUG_OUTPUT,
+ false );
+}
+
+
+// ------------------------------------------------------------------------------------------ //
+// Implementation of IShellIconMgrHelper.
+// ------------------------------------------------------------------------------------------ //
+
+HMENU g_hMenu = NULL;
+HMENU g_hPopupMenu = NULL; // This is just a submenu of g_hMenu.
+
+
+bool LoadPopupMenu()
+{
+ g_hMenu = LoadMenu( g_hInstance, MAKEINTRESOURCE( IDR_POPUP_MENU ) );
+ if ( !g_hMenu )
+ {
+ Assert( false );
+ Warning( "LoadMenu failed.\n" );
+ return false;
+ }
+
+ g_hPopupMenu = GetSubMenu( g_hMenu, 0 );
+ return true;
+}
+
+
+void TermPopupMenu()
+{
+ if ( g_hMenu )
+ {
+ DestroyMenu( g_hMenu );
+ g_hMenu = NULL;
+ }
+ g_hPopupMenu = NULL;
+}
+
+
+void UpdatePopupMenuState()
+{
+ bool bEnabled = (g_iCurState == VMPI_SERVICE_STATE_IDLE || g_iCurState == VMPI_SERVICE_STATE_BUSY);
+ EnableMenuItem( g_hPopupMenu, ID_ENABLE_WORKER, bEnabled ? MF_GRAYED : MF_ENABLED );
+ EnableMenuItem( g_hPopupMenu, ID_DISABLE_WORKER, !bEnabled ? MF_GRAYED : MF_ENABLED );
+
+ // Enable or disable console items.
+ EnableMenuItem( g_hPopupMenu, ID_SHOW_CONSOLE_WINDOW, g_pConsoleWnd->IsVisible() ? MF_GRAYED : MF_ENABLED );
+ EnableMenuItem( g_hPopupMenu, ID_HIDE_CONSOLE_WINDOW, !g_pConsoleWnd->IsVisible() ? MF_GRAYED : MF_ENABLED );
+
+ CheckMenuItem( g_hPopupMenu, ID_SCREENSAVER_MODE, g_bScreensaverMode ? MF_CHECKED : MF_UNCHECKED );
+ CheckMenuItem( g_hPopupMenu, ID_HIGHLIGHT_ICON_WHEN_BUSY, g_bHighlightIconWhenBusy ? MF_CHECKED : MF_UNCHECKED );
+}
+
+
+int CALLBACK SetPasswordDlgProc(
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+)
+{
+ switch( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ if ( g_pPassword )
+ {
+ HWND hWnd = GetDlgItem( hwndDlg, IDC_PASSWORD );
+ SetWindowText( hWnd, g_pPassword );
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ switch( wParam )
+ {
+ case IDOK:
+ {
+ // Set our new password.
+ HWND hWnd = GetDlgItem( hwndDlg, IDC_PASSWORD );
+ if ( hWnd )
+ {
+ char tempBuf[512];
+ GetWindowText( hWnd, tempBuf, sizeof( tempBuf ) );
+
+ // Send it to the service.
+ CUtlVector<char> data;
+ data.AddToTail( VMPI_SERVICE_UPDATE_PASSWORD );
+ data.AddMultipleToTail( strlen( tempBuf ) + 1, tempBuf );
+ g_ConnMgr.SendPacket( -1, data.Base(), data.Count() );
+ }
+ EndDialog( hwndDlg, 0 );
+ }
+ break;
+
+ case IDCANCEL:
+ {
+ EndDialog( hwndDlg, 0 );
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+class CShellIconMgrHelper : public IShellIconMgrHelper
+{
+public:
+ virtual HINSTANCE GetHInstance()
+ {
+ return g_hInstance;
+ }
+
+ virtual int WindowProc( void *pWnd, int uMsg, long wParam, long lParam )
+ {
+ HWND hWnd = (HWND)pWnd;
+
+ switch( uMsg )
+ {
+ // Right button brings up the popup menu.
+ case MYWM_NOTIFYICON:
+ {
+ if ( lParam == WM_RBUTTONDOWN )
+ {
+ POINT cursorPos;
+ GetCursorPos( &cursorPos );
+
+ UpdatePopupMenuState();
+
+ // Make a popup menu.
+ SetForegroundWindow( hWnd );
+ TrackPopupMenu( g_hPopupMenu, TPM_RIGHTALIGN | TPM_BOTTOMALIGN, cursorPos.x, cursorPos.y, 0, hWnd, NULL );
+ return 0;
+ }
+ else if ( lParam == WM_LBUTTONDOWN )
+ {
+ // Left button brings up the console.
+ g_pConsoleWnd->SetVisible( true );
+ UpdatePopupMenuState();
+ return 0;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ switch( wParam )
+ {
+ case ID_ENABLE_WORKER:
+ {
+ char cPacket = VMPI_SERVICE_ENABLE;
+ g_ConnMgr.SendPacket( -1, &cPacket, 1 );
+ }
+ break;
+
+ case ID_DISABLE_WORKER:
+ {
+ char cPacket = VMPI_SERVICE_DISABLE;
+ g_ConnMgr.SendPacket( -1, &cPacket, 1 );
+ }
+ break;
+
+ case ID_KILLCURRENTJOB:
+ {
+ char cPacket = VMPI_KILL_PROCESS;
+ g_ConnMgr.SendPacket( -1, &cPacket, 1 );
+ }
+ break;
+
+ case ID_HIGHLIGHT_ICON_WHEN_BUSY:
+ {
+ g_bHighlightIconWhenBusy = !g_bHighlightIconWhenBusy;
+ SaveStateToRegistry();
+ UpdateAppIcon();
+ UpdatePopupMenuState();
+ }
+ break;
+
+ case ID_SCREENSAVER_MODE:
+ {
+ g_bScreensaverMode = !g_bScreensaverMode;
+ char cPacket[2] = { VMPI_SERVICE_SCREENSAVER_MODE, g_bScreensaverMode };
+ g_ConnMgr.SendPacket( -1, cPacket, sizeof( cPacket ) );
+ }
+ break;
+
+
+ case ID_SHOW_CONSOLE_WINDOW:
+ {
+ g_pConsoleWnd->SetVisible( true );
+ UpdatePopupMenuState();
+ }
+ break;
+
+ case ID_HIDE_CONSOLE_WINDOW:
+ {
+ g_pConsoleWnd->SetVisible( false );
+ UpdatePopupMenuState();
+ }
+ break;
+
+ case ID_SET_PASSWORD:
+ {
+ DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_SET_PASSWORD ), NULL, SetPasswordDlgProc );
+ }
+ break;
+
+ case ID_EXIT_SERVICE:
+ {
+ // Quit the service app..
+ char cPacket = VMPI_SERVICE_EXIT;
+ g_ConnMgr.SendPacket( -1, &cPacket, 1 );
+
+ // Stop showing the icon.
+ g_ShellIconMgr.Term();
+
+ // Wait for a bit for the connection to go away.
+ DWORD startTime = GetTickCount();
+ while ( GetTickCount()-startTime < 2000 )
+ {
+ g_ConnMgr.Update();
+ if ( !g_ConnMgr.IsConnected() )
+ break;
+ else
+ Sleep( 10 );
+ }
+
+ // Quit the UI app.
+ PostQuitMessage( 0 );
+ return 1;
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return DefWindowProc( (HWND)hWnd, uMsg, wParam, lParam );
+ }
+};
+
+CShellIconMgrHelper g_ShellIconMgrHelper;
+
+
+
+int APIENTRY WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow)
+{
+ g_hInstance = hInstance;
+
+
+ LogString( "vmpi_service_ui startup.\n" );
+
+ // Don't run multiple instances.
+ HANDLE hMutex = CreateMutex( NULL, FALSE, "vmpi_service_ui_mutex" );
+ if ( hMutex && GetLastError() == ERROR_ALREADY_EXISTS )
+ return 1;
+
+
+ // Hook spew output.
+ SpewOutputFunc( MySpewOutputFunc );
+ InitConsoleWindow();
+ LogString( "Setup console window.\n" );
+
+ LoadStateFromRegistry();
+
+ // Setup the popup menu.
+ if( !LoadPopupMenu() )
+ {
+ return false;
+ }
+ UpdatePopupMenuState();
+
+
+ // Setup the tray icon.
+ Msg( "Waiting for jobs...\n" );
+ if ( !g_ShellIconMgr.Init( &g_ShellIconMgrHelper, g_pIconTooltip, MYWM_NOTIFYICON, IDI_WAITING_ICON ) )
+ {
+ return false;
+ }
+
+
+ // Connect to the VMPI service.
+ g_ConnMgr.InitClient();
+
+ LogString( "Entering main loop.\n" );
+
+ while ( 1 )
+ {
+ MSG msg;
+ msg.message = !WM_QUIT; // So it doesn't accidentally exit.
+ while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
+ {
+ if ( msg.message == WM_QUIT )
+ break;
+
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ if ( msg.message == WM_QUIT )
+ break;
+
+ g_ConnMgr.Update();
+ if ( !g_ConnMgr.IsConnected() )
+ {
+ g_ShellIconMgr.ChangeIcon( IDI_UNCONNECTED );
+ }
+
+ Sleep( 30 );
+ }
+
+ // Important that we call this instead of letting the destructor do it because it deletes its
+ // socket and it needs to cleanup some threads.
+ g_ConnMgr.Term();
+
+ g_ShellIconMgr.Term();
+
+ return 0;
+}
+
+
+
diff --git a/utils/vmpi/vmpi_service_ui/vmpi_service_ui.rc b/utils/vmpi/vmpi_service_ui/vmpi_service_ui.rc
new file mode 100644
index 0000000..c3a6c62
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/vmpi_service_ui.rc
@@ -0,0 +1,171 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+#include "resource.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
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_DISABLED_ICON ICON "idi_disabled_icon.ico"
+IDI_VMPI_SERVICE ICON "vmpi_service.ICO"
+IDI_BUSY_ICON ICON "idi_busy_icon.ico"
+IDI_WAITING_ICON ICON "idi_waiting_icon.ico"
+IDI_UNCONNECTED ICON "unconnec.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_POPUP_MENU MENU
+BEGIN
+ POPUP "item1"
+ BEGIN
+ MENUITEM "&Enable", ID_ENABLE_WORKER
+ MENUITEM "&Disable", ID_DISABLE_WORKER
+ MENUITEM "&Kill Current Job", ID_KILLCURRENTJOB
+ MENUITEM SEPARATOR
+ MENUITEM "&Show Console Window", ID_SHOW_CONSOLE_WINDOW
+ MENUITEM "&Hide Console Window", ID_HIDE_CONSOLE_WINDOW
+ MENUITEM SEPARATOR
+ MENUITEM "Set &Password", ID_SET_PASSWORD
+ MENUITEM "Highlight Icon When Busy", ID_HIGHLIGHT_ICON_WHEN_BUSY
+ MENUITEM "Screensaver Mode", ID_SCREENSAVER_MODE
+ MENUITEM SEPARATOR
+ MENUITEM "&Exit Service", ID_EXIT_SERVICE
+ END
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""resource.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_VMPI_SERVICE DIALOG 0, 0, 454, 225
+STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "Valve MPI Service"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_DEBUG_OUTPUT,7,7,440,211,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL
+END
+
+IDD_SET_PASSWORD DIALOG 0, 0, 134, 50
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Set Password (-mpi_pw)"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_PASSWORD,7,7,120,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,7,29,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,77,29,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_VMPI_SERVICE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 447
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 218
+ END
+
+ IDD_SET_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 127
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 43
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_APP_TITLE "vmpi_service"
+ IDS_HELLO "Hello World!"
+ IDC_VMPI_SERVICE "VMPI_SERVICE"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/utils/vmpi/vmpi_service_ui/vmpi_service_ui.vpc b/utils/vmpi/vmpi_service_ui/vmpi_service_ui.vpc
new file mode 100644
index 0000000..0f33d66
--- /dev/null
+++ b/utils/vmpi/vmpi_service_ui/vmpi_service_ui.vpc
@@ -0,0 +1,58 @@
+//-----------------------------------------------------------------------------
+// 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,..\,..\vmpi_service"
+ $PreprocessorDefinitions "$BASE;PROTECTED_THINGS_DISABLE"
+ }
+
+ $Linker
+ {
+ $AdditionalDependencies "$BASE ws2_32.lib odbc32.lib odbccp32.lib"
+ }
+}
+
+$Project "Vmpi_service_ui"
+{
+ $Folder "Source Files"
+ {
+ $File "..\iphelpers.cpp"
+ $File "shell_icon_mgr.cpp"
+ $File "vmpi_service_ui.cpp"
+ $File "vmpi_service_ui.rc"
+ $File "StdAfx.cpp"
+ $File "..\tcpsocket_helpers.cpp"
+ $File "..\ThreadedTCPSocket.cpp"
+ $File "..\..\common\consolewnd.cpp"
+ $File "..\vmpi_service\service_conn_mgr.cpp"
+ $File "..\ThreadedTCPSocketEmu.cpp"
+ $File "..\threadhelpers.cpp"
+ }
+
+ $Folder "Header Files"
+ {
+ $File "shell_icon_mgr.h"
+ $File "resource.h"
+ $File "StdAfx.h"
+ }
+
+ $Folder "Resource Files"
+ {
+ $File "idi_busy_icon.ico"
+ $File "idi_disabled_icon.ico"
+ $File "idi_waiting_icon.ico"
+ $File "unconnec.ico"
+ $File "vmpi_service.ico"
+ }
+}