diff options
Diffstat (limited to 'utils/vmpi/vmpi_service_install')
| -rw-r--r-- | utils/vmpi/vmpi_service_install/ServiceInstallDlg.cpp | 1043 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/ServiceInstallDlg.h | 72 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/StdAfx.cpp | 15 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/StdAfx.h | 41 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/res/vmpi.ico | bin | 0 -> 3310 bytes | |||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/res/vmpi_service_install.ico | bin | 0 -> 1078 bytes | |||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/res/vmpi_service_install.rc2 | 13 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/resource.h | 27 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/vmpi_service_install.cpp | 75 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/vmpi_service_install.h | 56 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/vmpi_service_install.rc | 173 | ||||
| -rw-r--r-- | utils/vmpi/vmpi_service_install/vmpi_service_install.vpc | 87 |
12 files changed, 1602 insertions, 0 deletions
diff --git a/utils/vmpi/vmpi_service_install/ServiceInstallDlg.cpp b/utils/vmpi/vmpi_service_install/ServiceInstallDlg.cpp new file mode 100644 index 0000000..6a22176 --- /dev/null +++ b/utils/vmpi/vmpi_service_install/ServiceInstallDlg.cpp @@ -0,0 +1,1043 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// JobWatchDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "ServiceInstallDlg.h" +#include "tier1/strtools.h" + + +#define DEFAULT_INSTALL_LOCATION "C:\\Program Files\\Valve\\vmpi_service" + +#define HLKM_WINDOWS_RUN_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run" +#define VMPI_SERVICE_VALUE_NAME "VMPI Service" +#define VMPI_SERVICE_UI_VALUE_NAME "VMPI Service UI" + +// These are the files required for installation. +char *g_pInstallFiles[] = +{ + "vmpi_service.exe", + "vmpi_service_ui.exe", + "WaitAndRestart.exe", + "vmpi_service_install.exe", + "tier0.dll", + "vmpi_transfer.exe", + "filesystem_stdio.dll", + "vstdlib.dll" +}; + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +HWND g_hMessageControl = NULL; +HKEY g_hVMPIKey = NULL; // hklm/software/valve/vmpi. +bool g_bNoOutput = false; +bool g_bDontTouchUI = false; +bool g_bReinstalling = false; + +FILE *g_fpLog = NULL; + + +char* FindArg( int argc, char **argv, const char *pArgName, char *pDefaultValue="" ) +{ + for ( int i=0; i < argc; i++ ) + { + if ( stricmp( argv[i], pArgName ) == 0 ) + { + if ( (i+1) >= argc ) + return pDefaultValue; + else + return argv[i+1]; + } + } + return NULL; +} + +void CloseLog() +{ + if ( g_fpLog ) + { + fflush( g_fpLog ); + fclose( g_fpLog ); + flushall(); + g_fpLog = NULL; + } +} + +void OpenLog() +{ + CloseLog(); + g_fpLog = fopen( "c:\\vmpi_service_install.log", "wt" ); +} + + +void AddToLog( const char *pMsg ) +{ + if ( g_fpLog ) + { + fprintf( g_fpLog, "%s", pMsg ); + } +} + + +SpewRetval_t MySpewOutputFunc( SpewType_t spewType, const tchar *pMsg ) +{ + AddToLog( pMsg ); + + if ( spewType == SPEW_MESSAGE || spewType == SPEW_WARNING ) + { + // Format the message and send it to the control. + CUtlVector<char> msg; + msg.SetSize( V_strlen( pMsg )*2 + 1 ); + + char *pOut = msg.Base(); + const char *pIn = pMsg; + while ( *pIn ) + { + if ( *pIn == '\n' ) + { + *pOut++ = '\r'; + *pOut++ = '\n'; + } + else + { + *pOut++ = *pIn; + } + ++pIn; + } + *pOut = 0; + + int nLen = (int)SendMessage( g_hMessageControl, EM_GETLIMITTEXT, 0, 0 ); + SendMessage( g_hMessageControl, EM_SETSEL, nLen, nLen ); + SendMessage( g_hMessageControl, EM_REPLACESEL, FALSE, (LPARAM)msg.Base() ); + } + + // Show a message box for warnings and errors. + if ( spewType == SPEW_ERROR || spewType == SPEW_WARNING ) + { + if ( !g_bNoOutput ) + AfxMessageBox( pMsg, MB_OK ); + } + + if ( spewType == SPEW_ERROR ) + { + CloseLog(); + TerminateProcess( GetCurrentProcess(), 2 ); + } + + return SPEW_CONTINUE; +} + + +void ScanDirectory( const char *pDirName, CUtlVector<CString> &subDirs, CUtlVector<CString> &files ) +{ + subDirs.Purge(); + files.Purge(); + + char strPattern[MAX_PATH]; + V_ComposeFileName( pDirName, "*.*", strPattern, sizeof( strPattern ) ); + + WIN32_FIND_DATA fileInfo; // File information + HANDLE hFile = ::FindFirstFile( strPattern, &fileInfo ); + if ( hFile == INVALID_HANDLE_VALUE ) + return; + + do + { + if ( fileInfo.cFileName[0] == '.' ) + continue; + + if ( fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + subDirs.AddToTail( fileInfo.cFileName ); + else + files.AddToTail( fileInfo.cFileName ); + } while( ::FindNextFile(hFile, &fileInfo) ); + + ::FindClose( hFile ); +} + + +int DeleteDirectory( const char *pRootDir, bool bDeleteSubdirectories, char errorFile[MAX_PATH] ) +{ + errorFile[0] = 0; + + CUtlVector<CString> subDirs, files; + ScanDirectory( pRootDir, subDirs, files ); + + // First nuke any subdirectories. + if ( bDeleteSubdirectories && !g_bReinstalling ) + { + for ( int i=0; i < subDirs.Count(); i++ ) + { + char fullName[MAX_PATH]; + V_ComposeFileName( pRootDir, subDirs[i], fullName, sizeof( fullName ) ); + + // Delete subdirectory + int iRC = DeleteDirectory( fullName, bDeleteSubdirectories, errorFile ); + if ( iRC ) + return iRC; + } + } + + for ( int i=0; i < files.Count(); i++ ) + { + char fullName[MAX_PATH]; + V_ComposeFileName( pRootDir, files[i], fullName, sizeof( fullName ) ); + + // Set file attributes + if ( !SetFileAttributes( fullName, FILE_ATTRIBUTE_NORMAL ) ) + return GetLastError(); + + // Delete file + if ( !DeleteFile( fullName ) ) + { + V_strncpy( errorFile, fullName, MAX_PATH ); + return GetLastError(); + } + } + + if( !g_bReinstalling ) + { + // Set directory attributes + if ( !SetFileAttributes( pRootDir, FILE_ATTRIBUTE_NORMAL ) ) + return GetLastError(); + + // Delete directory + if ( !RemoveDirectory( pRootDir ) ) + return GetLastError(); + } + + return 0; +} + + +bool CreateDirectory_R( const char *pDirName ) +{ + char chPrevDir[MAX_PATH]; + V_strncpy( chPrevDir, pDirName, sizeof( chPrevDir ) ); + if ( V_StripLastDir( chPrevDir, sizeof( chPrevDir ) ) ) + { + if ( V_stricmp( chPrevDir, ".\\" ) != 0 && V_stricmp( chPrevDir, "./" ) != 0 ) + if ( !CreateDirectory_R( chPrevDir ) ) + return false; + } + + if ( _access( pDirName, 0 ) == 0 ) + return true; + + return CreateDirectory( pDirName, NULL ) || GetLastError() == ERROR_ALREADY_EXISTS; +} + + +bool SetupStartMenuSubFolderName( const char *pSubFolderName, char *pOut, int outLen ) +{ + LPITEMIDLIST pidl; + + // Get a pointer to an item ID list that represents the path of a special folder + HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_PROGRAMS, &pidl); + if ( hr != S_OK ) + return false; + + // Convert the item ID list's binary representation into a file system path + char szPath[_MAX_PATH]; + BOOL f = SHGetPathFromIDList(pidl, szPath); + + // Free the LPITEMIDLIST they gave us. + LPMALLOC pMalloc; + hr = SHGetMalloc(&pMalloc); + pMalloc->Free(pidl); + pMalloc->Release(); + + if ( f ) + { + V_ComposeFileName( szPath, pSubFolderName, pOut, outLen ); + return true; + } + else + { + return false; + } +} + +bool CreateStartMenuLink( const char *pSubFolderName, const char *pLinkName, const char *pLinkTarget, const char *pArguments ) +{ + char fullFolderName[MAX_PATH]; + if ( !SetupStartMenuSubFolderName( pSubFolderName, fullFolderName, sizeof( fullFolderName ) ) ) + return false; + + // Create the folder if necessary. + if ( !CreateDirectory_R( fullFolderName ) ) + { + Msg( "CreateStartMenuLink failed - can't create directory %s.\n", fullFolderName ); + return false; + } + + IShellLink* psl = NULL; + + // Get a pointer to the IShellLink interface. + bool bRet = false; + CoInitialize( NULL ); + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast<void**>(&psl)); + if (SUCCEEDED(hres)) + { + psl->SetPath( pLinkTarget ); // Set the path to the shortcut target + if ( pArguments ) + psl->SetArguments( pArguments ); + + // Query IShellLink for the IPersistFile interface for saving + //the shortcut in persistent storage. + IPersistFile* ppf = NULL; + hres = psl->QueryInterface( IID_IPersistFile, reinterpret_cast<void**>(&ppf) ); + if (SUCCEEDED(hres)) + { + // Setup the filename for the link. + char linkFilename[MAX_PATH]; + V_ComposeFileName( fullFolderName, pLinkName, linkFilename, sizeof( linkFilename ) ); + V_strncat( linkFilename, ".lnk", sizeof( linkFilename ) ); + + // Ensure that the string is ANSI. + WCHAR wsz[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, linkFilename, -1, wsz, MAX_PATH); + + // Save the link by calling IPersistFile::Save. + hres = ppf->Save( wsz, TRUE ); + ppf->Release(); + bRet = true; + } + + psl->Release(); + } + CoUninitialize(); + return bRet; +} + + + +char* GetLastErrorString() +{ + static char err[2048]; + + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + strncpy( err, (char*)lpMsgBuf, sizeof( err ) ); + LocalFree( lpMsgBuf ); + + err[ sizeof( err ) - 1 ] = 0; + + return err; +} + + +bool LaunchApp( char *pCommandLine, const char *pBaseDir ) +{ + STARTUPINFO si; + memset( &si, 0, sizeof( si ) ); + si.cb = sizeof( si ); + + PROCESS_INFORMATION pi; + memset( &pi, 0, sizeof( pi ) ); + + return CreateProcess( NULL, pCommandLine, NULL, NULL, FALSE, 0, NULL, pBaseDir, &si, &pi ) != 0; +} + + +bool StartVMPIServiceUI( const char *pInstallLocation ) +{ + if ( g_bDontTouchUI ) + { + Msg( "StartVMPIServiceUI: Ignoring due to -DontTouchUI.\n" ); + return true; + } + + char cmdLine[MAX_PATH]; + V_ComposeFileName( pInstallLocation, "vmpi_service_ui.exe", cmdLine, sizeof( cmdLine ) ); + return LaunchApp( cmdLine, pInstallLocation ); +} + + +bool StartVMPIService( SC_HANDLE hSCManager ) +{ + bool bRet = true; + + // First, get rid of an old service with the same name. + SC_HANDLE hMyService = OpenService( hSCManager, VMPI_SERVICE_NAME_INTERNAL, SERVICE_START ); + if ( hMyService ) + { + if ( StartService( hMyService, NULL, NULL ) ) + { + Msg( "Started!\n" ); + } + else + { + Error( "Can't start the service.\n" ); + bRet = false; + } + } + else + { + Error( "Can't open service: %s\n", VMPI_SERVICE_NAME_INTERNAL ); + bRet = false; + } + + CloseServiceHandle( hMyService ); + return bRet; +} + + +bool StopRunningApp() +{ + if ( g_bDontTouchUI ) + { + Msg( "StopRunningApp: -DontTouchUI was specified, so exiting before stopping the app.\n" ); + return true; + } + + // Send the + ISocket *pSocket = CreateIPSocket(); + if ( pSocket ) + { + if ( pSocket->BindToAny( 0 ) ) + { + CUtlVector<char> protocolVersions; + protocolVersions.AddToTail( VMPI_PROTOCOL_VERSION ); + if ( VMPI_PROTOCOL_VERSION == 5 ) + protocolVersions.AddToTail( 4 ); // We want this installer to kill the previous services too. + + for ( int iProtocolVersion=0; iProtocolVersion < protocolVersions.Count(); iProtocolVersion++ ) + { + char cPacket[4] = + { + protocolVersions[iProtocolVersion], + VMPI_PASSWORD_OVERRIDE, // (force it to accept this message). + 0, + VMPI_STOP_SERVICE + }; + + CIPAddr addr( 127, 0, 0, 1, 0 ); + + for ( int iPort=VMPI_SERVICE_PORT; iPort <= VMPI_LAST_SERVICE_PORT; iPort++ ) + { + addr.port = iPort; + pSocket->SendTo( &addr, cPacket, sizeof( cPacket ) ); + } + } + + // Give it a sec to get the message and shutdown in case we're restarting. + Sleep( 2000 ); + + + // This is the overkill method. If it didn't shutdown gracefully, kill it. + HMODULE hInst = LoadLibrary( "psapi.dll" ); + if ( hInst ) + { + typedef BOOL (WINAPI *EnumProcessesFn)(DWORD *lpidProcess, DWORD cb, DWORD *cbNeeded); + typedef BOOL (WINAPI *EnumProcessModulesFn)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ); + typedef DWORD (WINAPI *GetModuleBaseNameFn)( HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize ); + + EnumProcessesFn EnumProcesses = (EnumProcessesFn)GetProcAddress( hInst, "EnumProcesses" ); + EnumProcessModulesFn EnumProcessModules = (EnumProcessModulesFn)GetProcAddress( hInst, "EnumProcessModules" ); + GetModuleBaseNameFn GetModuleBaseName = (GetModuleBaseNameFn)GetProcAddress( hInst, "GetModuleBaseNameA" ); + if ( EnumProcessModules && EnumProcesses ) + { + // Now just to make sure, kill the processes we're interested in. + DWORD procIDs[1024]; + DWORD nBytes; + if ( EnumProcesses( procIDs, sizeof( procIDs ), &nBytes ) ) + { + DWORD nProcs = nBytes / sizeof( procIDs[0] ); + for ( DWORD i=0; i < nProcs; i++ ) + { + HANDLE hProc = OpenProcess( PROCESS_ALL_ACCESS, FALSE, procIDs[i] ); + if ( hProc ) + { + HMODULE hModules[1024]; + if ( EnumProcessModules( hProc, hModules, sizeof( hModules ), &nBytes ) ) + { + DWORD nModules = nBytes / sizeof( hModules[0] ); + for ( DWORD iModule=0; iModule < nModules; iModule++ ) + { + char filename[512]; + if ( GetModuleBaseName( hProc, hModules[iModule], filename, sizeof( filename ) ) ) + { + if ( Q_stristr( filename, "vmpi_service.exe" ) || Q_stristr( filename, "vmpi_service_ui.exe" ) ) + { + TerminateProcess( hProc, 1 ); + CloseHandle( hProc ); + hProc = NULL; + break; + } + } + } + } + + CloseHandle( hProc ); + } + } + } + } + + FreeLibrary( hInst ); + } + } + + pSocket->Release(); + } + + return true; +} + + +bool StopOrDeleteService( SC_HANDLE hSCManager, bool bDelete ) +{ + bool bRet = true; + + // First, get rid of an old service with the same name. + SC_HANDLE hOldService = OpenService( hSCManager, VMPI_SERVICE_NAME_INTERNAL, SERVICE_STOP | DELETE ); + if ( hOldService ) + { + // Stop the service. + Msg( "Found the service already running.\n" ); + Msg( "Stopping service...\n" ); + SERVICE_STATUS status; + ControlService( hOldService, SERVICE_CONTROL_STOP, &status ); + + if ( bDelete ) + { + Msg( "Deleting service...\n" ); + bool bExitedNicely = false; + DWORD startTime = GetTickCount(); + while ( 1 ) + { + BOOL bRet = DeleteService( hOldService ); + if ( !bRet || bRet == ERROR_SERVICE_MARKED_FOR_DELETE ) + { + Msg( "Deleted old service.\n" ); + bExitedNicely = true; + break; + } + + // Wait for the service to stop for 8 seconds. + if ( GetTickCount() - startTime > 8000 ) + break; + } + + if ( !bExitedNicely ) + { + Error( "Couldn't delete the old '%s' service! Error: %s.\n", VMPI_SERVICE_NAME, GetLastErrorString() ); + bRet = false; + } + } + + CloseServiceHandle( hOldService ); + } + + return bRet; +} + + +bool GetExistingInstallationLocation( CString &strInstallLocation ) +{ + char buf[1024]; + DWORD bufSize = sizeof( buf ); + DWORD dwType; + if ( RegQueryValueEx( g_hVMPIKey, SERVICE_INSTALL_LOCATION_KEY, NULL, &dwType, (LPBYTE)buf, &bufSize ) == ERROR_SUCCESS ) + { + if ( dwType == REG_SZ ) + { + strInstallLocation = buf; + return true; + } + } + + return false; +} + +void RemoveRegistryKeys() +{ + // Delete the run values (that tells it to run the app when the user logs in). + HKEY hKey = NULL; + RegCreateKey( HKEY_LOCAL_MACHINE, HLKM_WINDOWS_RUN_KEY, &hKey ); + RegDeleteValue( hKey, VMPI_SERVICE_VALUE_NAME ); + RegDeleteValue( hKey, VMPI_SERVICE_UI_VALUE_NAME ); + + // Get rid of the "InstallLocation" value. + RegDeleteValue( g_hVMPIKey, SERVICE_INSTALL_LOCATION_KEY ); +} + + +bool IsAnInstallFile( const char *pName ) +{ + for ( int i=0; i < ARRAYSIZE( g_pInstallFiles ); i++ ) + { + if ( V_stricmp( g_pInstallFiles[i], pName ) == 0 ) + return true; + } + return false; +} + + +bool AnyNonInstallFilesInDirectory( const char *strInstallLocation ) +{ + char searchStr[MAX_PATH]; + V_ComposeFileName( strInstallLocation, "*.*", searchStr, sizeof( searchStr ) ); + + _finddata_t data; + long handle = _findfirst( searchStr, &data ); + if ( handle != -1 ) + { + do + { + if ( data.name[0] == '.' || (data.attrib & _A_SUBDIR) != 0 ) + continue; + + if ( !IsAnInstallFile( data.name ) ) + return true; + + } while( _findnext( handle, &data ) == 0 ); + + _findclose( handle ); + } + return false; +} + + +///////////////////////////////////////////////////////////////////////////// +// CServiceInstallDlg dialog + + +CServiceInstallDlg::CServiceInstallDlg(CWnd* pParent /*=NULL*/) + : CDialog(CServiceInstallDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CServiceInstallDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +CServiceInstallDlg::~CServiceInstallDlg() +{ +} + + +void CServiceInstallDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CServiceInstallDlg) + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CServiceInstallDlg, CDialog) + //{{AFX_MSG_MAP(CServiceInstallDlg) + ON_BN_CLICKED(IDC_CANCEL_BUTTON, OnCancel) + ON_BN_CLICKED(IDC_INSTALL_BUTTON, OnInstall) + ON_BN_CLICKED(IDC_UNINSTALL_BUTTON2, OnUninstall) + ON_BN_CLICKED(IDC_START_EXISTING_BUTTON, OnStartExisting) + ON_BN_CLICKED(IDC_STOP_EXISTING_BUTTON, OnStopExisting) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CServiceInstallDlg message handlers + +const char* FindArg( const char *pArgName, const char *pDefault="" ) +{ + for ( int i=1; i < __argc; i++ ) + { + if ( Q_stricmp( pArgName, __argv[i] ) == 0 ) + { + if ( (i+1) < __argc ) + return __argv[i+1]; + else + return pDefault; + } + } + return NULL; +} + + +BOOL CServiceInstallDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + HICON hIcon = LoadIcon( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_MAINFRAME ) ); + SetIcon( hIcon, true ); + + OpenLog(); + + // Setup the registry key for the install location. + if ( RegCreateKey( HKEY_LOCAL_MACHINE, VMPI_SERVICE_KEY, &g_hVMPIKey ) != ERROR_SUCCESS ) + { + Error( "Can't open registry key: %s.", VMPI_SERVICE_KEY ); + return FALSE; + } + + VerifyInstallFiles(); + + g_hMessageControl = ::GetDlgItem( GetSafeHwnd(), IDC_TEXTOUTPUT ); + SpewOutputFunc( MySpewOutputFunc ); + + // Init the service manager. + m_hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + if ( !m_hSCManager ) + { + Error( "OpenSCManager failed (%s)!\n", GetLastErrorString() ); + return FALSE; + } + + + // See if there is a previous installation. + CString strInstallLocation; + if ( GetExistingInstallationLocation( strInstallLocation ) ) + SetDlgItemText( IDC_INSTALL_LOCATION, strInstallLocation ); + else + SetDlgItemText( IDC_INSTALL_LOCATION, DEFAULT_INSTALL_LOCATION ); + + // Now, if they passed in a command line option . + if ( FindArg( __argc, __argv, "-install_quiet" ) ) + { + g_bReinstalling = true; + g_bNoOutput = true; + g_bDontTouchUI = (FindArg( __argc, __argv, "-DontTouchUI", NULL ) != 0); + OnInstall(); + EndDialog( 0 ); + } + else if ( FindArg( __argc, __argv, "-uninstall_quiet" ) ) + { + g_bNoOutput = true; + DoUninstall( false ); + EndDialog( 0 ); + } + else if ( FindArg( __argc, __argv, "-start" ) ) + { + OnStartExisting(); + } + + else if ( FindArg( __argc, __argv, "-stop" ) ) + { + OnStopExisting(); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CServiceInstallDlg::OnCancel(void) +{ + EndDialog( 1 ); +} + +// This function registers the service with the service manager. +bool InstallService( SC_HANDLE hSCManager, const char *pBaseDir ) +{ + char filename[512], uiFilename[512]; + V_ComposeFileName( pBaseDir, "vmpi_service.exe", filename, sizeof( filename ) ); + V_ComposeFileName( pBaseDir, "vmpi_service_ui.exe", uiFilename, sizeof( uiFilename ) ); + + + // Try a to reinstall the service for up to 5 seconds. + Msg( "Creating new service...\n" ); + + SC_HANDLE hMyService = NULL; + DWORD startTime = GetTickCount(); + while ( GetTickCount() - startTime < 5000 ) + { + // Now reinstall it. + hMyService = CreateService( + hSCManager, // Service Control Manager database. + VMPI_SERVICE_NAME_INTERNAL, // Service name. + VMPI_SERVICE_NAME, // Display name. + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, // Start automatically on system bootup. + SERVICE_ERROR_NORMAL, + filename, // Executable to register for the service. + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // no dependencies + NULL, // account + NULL // password + ); + + if ( hMyService ) + break; + else + Sleep( 300 ); + } + + if ( !hMyService ) + { + Warning( "CreateService failed (%s)!\n", GetLastErrorString() ); + CloseServiceHandle( hSCManager ); + return false; + } + + + // Now setup the UI executable to run when their system starts. + HKEY hUIKey = NULL; + RegCreateKey( HKEY_LOCAL_MACHINE, HLKM_WINDOWS_RUN_KEY, &hUIKey ); + if ( !hUIKey || RegSetValueEx( hUIKey, VMPI_SERVICE_UI_VALUE_NAME, 0, REG_SZ, (unsigned char*)uiFilename, strlen( uiFilename) + 1 ) != ERROR_SUCCESS ) + { + Warning( "Can't install registry key for %s\n", uiFilename ); + return false; + } + + CloseServiceHandle( hMyService ); + return true; +} + + +void SetupStartMenuLinks( const char *pInstallerFilename ) +{ + CreateStartMenuLink( "Valve\\VMPI", "Start VMPI Service", pInstallerFilename, "-start" ); + CreateStartMenuLink( "Valve\\VMPI", "Stop VMPI Service", pInstallerFilename, "-stop" ); + CreateStartMenuLink( "Valve\\VMPI", "Uninstall VMPI", pInstallerFilename, NULL ); +} + + +void RemoveStartMenuLinks() +{ + char fullFolderName[MAX_PATH]; + if ( !SetupStartMenuSubFolderName( "Valve\\VMPI", fullFolderName, sizeof( fullFolderName ) ) ) + return; + + char errorFile[MAX_PATH]; + if ( !DeleteDirectory( fullFolderName, true, errorFile ) ) + { + Msg( "Unable to remove Start Menu items in %s.\n", fullFolderName ); + } +} + + +void CServiceInstallDlg::OnInstall() +{ + // Get the install location. + Msg( "Verifying install location.\n" ); + CString strInstallLocation; + if ( !GetDlgItemText( IDC_INSTALL_LOCATION, strInstallLocation ) ) + { + Error( "Can't get install location." ); + return; + } + + if ( strchr( strInstallLocation, ':' ) == NULL ) + { + Warning( "Install location must be an absolute path (include a colon)." ); + return; + } + + // Stop the existing service. + if ( !DoUninstall( false ) ) + return; + + // Create the directory. + Msg( "Creating install directory %s.\n", strInstallLocation ); + if ( !CreateDirectory_R( strInstallLocation ) ) + { + Warning( "Unable to create directory: %s.", (const char*)strInstallLocation ); + return; + } + + // Copy the files down. + Msg( "Copying files.\n" ); + char chDir[MAX_PATH]; + GetModuleFileName( NULL, chDir, sizeof( chDir ) ); + V_StripFilename( chDir ); + for ( int i=0; i < ARRAYSIZE( g_pInstallFiles ); i++ ) + { + char srcFilename[MAX_PATH], destFilename[MAX_PATH]; + V_ComposeFileName( chDir, g_pInstallFiles[i], srcFilename, sizeof( srcFilename ) ); + V_ComposeFileName( strInstallLocation, g_pInstallFiles[i], destFilename, sizeof( destFilename ) ); + + if ( !CopyFile( srcFilename, destFilename, FALSE ) ) + { + Sleep( 2000 ); + + if ( !CopyFile( srcFilename, destFilename, FALSE ) ) + { + Error( "CopyFile() failed.\nSrc: %s\nDest: %s\n%s", srcFilename, destFilename, GetLastErrorString() ); + return; + } + } + } + + // Register the service. + if ( !InstallService( m_hSCManager, strInstallLocation ) ) + return; + + // Write the new location to the registry. + Msg( "Updating registry.\n" ); + if ( RegSetValueEx( g_hVMPIKey, SERVICE_INSTALL_LOCATION_KEY, 0, REG_SZ, (BYTE*)(const char*)strInstallLocation, V_strlen( strInstallLocation ) + 1 ) != ERROR_SUCCESS ) + { + Error( "RegSetValueEx( %s, %s ) failed.", SERVICE_INSTALL_LOCATION_KEY, (const char*)strInstallLocation ); + return; + } + + // Setup start menu links. + char installerFilename[MAX_PATH]; + V_ComposeFileName( strInstallLocation, "vmpi_service_install.exe", installerFilename, sizeof( installerFilename ) ); + SetupStartMenuLinks( installerFilename ); + + // Start the new service. + Msg( "Starting new service.\n" ); + if ( DoStartExisting() ) + { + Warning( "Installed successfully!" ); + } +} + +bool CServiceInstallDlg::DoUninstall( bool bShowMessage ) +{ + // Figure out where to uninstall from. + CString strInstallLocation; + if ( !GetDlgItemText( IDC_INSTALL_LOCATION, strInstallLocation ) ) + { + Error( "Can't get install location." ); + return false; + } + + if ( _access( strInstallLocation, 0 ) == 0 && !g_bNoOutput ) + { + // Don't ask if they care if we delete all the files in that directory if the only exes in there are the install exes. + if ( AnyNonInstallFilesInDirectory( strInstallLocation ) ) + { + char str[512]; + V_snprintf( str, sizeof( str ), "Warning: this will delete all files under this directory: \n%s\nContinue?", strInstallLocation ); + if ( AfxMessageBox( str, MB_YESNO ) != IDYES ) + return false; + } + } + + // Stop both the service and the win app. + bool bDone = StopRunningApp() && StopOrDeleteService( m_hSCManager, true ); + if ( !bDone ) + return false; + + bool bSuccess = true; + RemoveRegistryKeys(); + char errorFile[MAX_PATH]; + if ( !NukeDirectory( strInstallLocation, errorFile ) ) + { + // When reinstalling, the service may not be done exiting, so give it a sec. + Sleep( 2000 ); + if ( !NukeDirectory( strInstallLocation, errorFile ) ) + { + if ( errorFile[0] ) + Msg( "NukeDirectory( %s ) failed.\nError on file: %s\n", strInstallLocation, errorFile ); + else + Msg( "NukeDirectory( %s ) failed.\n", strInstallLocation ); + + Msg( "Uninstall complete, but files are left over in %s.\n", strInstallLocation ); + + bSuccess = false; + } + } + + RemoveStartMenuLinks(); + + if ( bShowMessage && bSuccess ) + AfxMessageBox( "Uninstall successful." ); + + return true; +} + +void CServiceInstallDlg::OnUninstall() +{ + DoUninstall( true ); +} + +void CServiceInstallDlg::OnStartExisting() +{ + if ( DoStartExisting() ) + AfxMessageBox( "Started successfully." ); +} + +bool CServiceInstallDlg::DoStartExisting() +{ + StopRunningApp(); + StopOrDeleteService( m_hSCManager, false ); + + CString strInstallLocation; + if ( !GetExistingInstallationLocation( strInstallLocation ) ) + { + Error( "The VMPI service is not installed." ); + return false; + } + + if ( StartVMPIService( m_hSCManager ) ) + { + return StartVMPIServiceUI( strInstallLocation ); + } + else + { + return false; + } +} + +void CServiceInstallDlg::OnStopExisting() +{ + + // Stop the app but don't delete it. + bool bDone = StopRunningApp() && StopOrDeleteService( m_hSCManager, false ); + if ( bDone ) + { + AfxMessageBox( "Service successfully stopped." ); + } +} + +bool CServiceInstallDlg::NukeDirectory( const char *pDir, char errorFile[MAX_PATH] ) +{ + // If the directory doesn't exist anyways, then return true.. + if ( _access( pDir, 0 ) != 0 ) + return true; + + return DeleteDirectory( pDir, true, errorFile ) == 0; +} + + +void CServiceInstallDlg::VerifyInstallFiles() +{ + char chDir[MAX_PATH]; + GetModuleFileName( NULL, chDir, sizeof( chDir ) ); + V_StripFilename( chDir ); + + for ( int i=0; i < ARRAYSIZE( g_pInstallFiles ); i++ ) + { + char filename[MAX_PATH]; + V_ComposeFileName( chDir, g_pInstallFiles[i], filename, sizeof( filename ) ); + + if ( _access( filename, 0 ) != 0 ) + { + char szErrorMessage[MAX_PATH]; + + V_snprintf( szErrorMessage, sizeof( szErrorMessage ), "Required installation file missing: %s", filename ); + + AfxMessageBox( szErrorMessage ); + return; + } + } +} + diff --git a/utils/vmpi/vmpi_service_install/ServiceInstallDlg.h b/utils/vmpi/vmpi_service_install/ServiceInstallDlg.h new file mode 100644 index 0000000..01dc433 --- /dev/null +++ b/utils/vmpi/vmpi_service_install/ServiceInstallDlg.h @@ -0,0 +1,72 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#if !defined(AFX_SERVICEINSTALLDLG_H__761BDEEF_D549_4F10_817C_1C1FAF9FCA47__INCLUDED_) +#define AFX_SERVICEINSTALLDLG_H__761BDEEF_D549_4F10_817C_1C1FAF9FCA47__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// JobWatchDlg.h : header file +// + + +#include "resource.h" +#include "tier1/utlvector.h" + + + +///////////////////////////////////////////////////////////////////////////// +// CJobWatchDlg dialog + +class CServiceInstallDlg : public CDialog +{ +// Construction +public: + CServiceInstallDlg( CWnd* pParent = NULL); // standard constructor + virtual ~CServiceInstallDlg(); + +// Dialog Data + //{{AFX_DATA(CJobWatchDlg) + enum { IDD = IDD_SERVICE_INSTALL_DIALOG}; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CJobWatchDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + SC_HANDLE m_hSCManager; + + void VerifyInstallFiles(); + + bool DoStartExisting(); + bool NukeDirectory( const char *pDir, char errorFile[MAX_PATH] ); + bool DoUninstall( bool bShowMessage ); + + // Generated message map functions + //{{AFX_MSG(CJobWatchDlg) + virtual BOOL OnInitDialog(); + virtual void OnCancel(); + virtual void OnInstall(); + virtual void OnUninstall(); + virtual void OnStartExisting(); + virtual void OnStopExisting(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SERVICEINSTALLDLG_H__761BDEEF_D549_4F10_817C_1C1FAF9FCA47__INCLUDED_) diff --git a/utils/vmpi/vmpi_service_install/StdAfx.cpp b/utils/vmpi/vmpi_service_install/StdAfx.cpp new file mode 100644 index 0000000..e10b100 --- /dev/null +++ b/utils/vmpi/vmpi_service_install/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_install.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_install/StdAfx.h b/utils/vmpi/vmpi_service_install/StdAfx.h new file mode 100644 index 0000000..d243112 --- /dev/null +++ b/utils/vmpi/vmpi_service_install/StdAfx.h @@ -0,0 +1,41 @@ +//========= 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__E8FBDA6A_CE57_4416_8329_90155CD6CEC3__INCLUDED_) +#define AFX_STDAFX_H__E8FBDA6A_CE57_4416_8329_90155CD6CEC3__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include "tier0/basetypes.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 + +#include <winsvc.h> +#include <io.h> + +#include "iphelpers.h" +#include "vmpi.h" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__E8FBDA6A_CE57_4416_8329_90155CD6CEC3__INCLUDED_) diff --git a/utils/vmpi/vmpi_service_install/res/vmpi.ico b/utils/vmpi/vmpi_service_install/res/vmpi.ico Binary files differnew file mode 100644 index 0000000..24dc2cf --- /dev/null +++ b/utils/vmpi/vmpi_service_install/res/vmpi.ico diff --git a/utils/vmpi/vmpi_service_install/res/vmpi_service_install.ico b/utils/vmpi/vmpi_service_install/res/vmpi_service_install.ico Binary files differnew file mode 100644 index 0000000..7eef0bc --- /dev/null +++ b/utils/vmpi/vmpi_service_install/res/vmpi_service_install.ico diff --git a/utils/vmpi/vmpi_service_install/res/vmpi_service_install.rc2 b/utils/vmpi/vmpi_service_install/res/vmpi_service_install.rc2 new file mode 100644 index 0000000..6e93fd0 --- /dev/null +++ b/utils/vmpi/vmpi_service_install/res/vmpi_service_install.rc2 @@ -0,0 +1,13 @@ +// +// VMPI_BROWSER_JOB_WATCH.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_service_install/resource.h b/utils/vmpi/vmpi_service_install/resource.h new file mode 100644 index 0000000..9330dcb --- /dev/null +++ b/utils/vmpi/vmpi_service_install/resource.h @@ -0,0 +1,27 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by vmpi_service_install.rc +// +#define IDD_SERVICE_INSTALL_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDD_SERVICE_INSTALL 135 +#define IDC_TEXTOUTPUT 200 +#define IDC_COMMAND_LINE 201 +#define IDC_INSTALL_LOCATION 201 +#define IDC_INSTALL_BUTTON 1011 +#define IDC_CANCEL_BUTTON 1012 +#define IDC_UNINSTALL_BUTTON2 1013 +#define IDC_START_EXISTING_BUTTON 1014 +#define IDC_STOP_EXISTING_BUTTON 1015 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 131 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1012 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/utils/vmpi/vmpi_service_install/vmpi_service_install.cpp b/utils/vmpi/vmpi_service_install/vmpi_service_install.cpp new file mode 100644 index 0000000..f366efa --- /dev/null +++ b/utils/vmpi/vmpi_service_install/vmpi_service_install.cpp @@ -0,0 +1,75 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// vmpi_browser_job_watch.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "vmpi_service_install.h" +#include "ServiceInstallDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CServiceInstallApp + +BEGIN_MESSAGE_MAP(CServiceInstallApp, CWinApp) + //{{AFX_MSG_MAP(CServiceInstallApp) + // 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() + +///////////////////////////////////////////////////////////////////////////// +// CServiceInstallApp construction + +CServiceInstallApp::CServiceInstallApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CServiceInstallApp object + +CServiceInstallApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CServiceInstallApp initialization + +BOOL CServiceInstallApp::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. + + CServiceInstallDlg 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_service_install/vmpi_service_install.h b/utils/vmpi/vmpi_service_install/vmpi_service_install.h new file mode 100644 index 0000000..e29f338 --- /dev/null +++ b/utils/vmpi/vmpi_service_install/vmpi_service_install.h @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// vmpi_browser_job_watch.h : main header file for the VMPI_BROWSER_JOB_WATCH application +// + +#if !defined(AFX_VMPI_SERVICE_INSTALL_H__1DF22047_F615_4799_913A_222E3701BE5E__INCLUDED_) +#define AFX_VMPI_SERVICE_INSTALL_H__1DF22047_F615_4799_913A_222E3701BE5E__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 + +///////////////////////////////////////////////////////////////////////////// +// CVMPIBrowserJobWatchApp: +// See vmpi_browser_job_watch.cpp for the implementation of this class +// + +class CServiceInstallApp : public CWinApp +{ +public: + CServiceInstallApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CVMPIBrowserJobWatchApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CVMPIBrowserJobWatchApp) + // 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_SERVICE_INSTALL_H__1DF22047_F615_4799_913A_222E3701BE5E__INCLUDED_) diff --git a/utils/vmpi/vmpi_service_install/vmpi_service_install.rc b/utils/vmpi/vmpi_service_install/vmpi_service_install.rc new file mode 100644 index 0000000..f9d59aa --- /dev/null +++ b/utils/vmpi/vmpi_service_install/vmpi_service_install.rc @@ -0,0 +1,173 @@ +// 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_service_install.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_service_install MFC Application" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "vmpi_service_install" + VALUE "LegalCopyright", "Copyright (C) 2003" + VALUE "OriginalFilename", "vmpi_service_install.EXE" + VALUE "ProductName", "vmpi_service_install Application" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SERVICE_INSTALL_DIALOG DIALOGEX 0, 0, 467, 366 +STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "VMPI Service Installer" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_INSTALL_LOCATION,69,52,388,14,ES_AUTOHSCROLL + PUSHBUTTON "&Install / Update",IDC_INSTALL_BUTTON,9,78,107,14 + PUSHBUTTON "&Uninstall",IDC_UNINSTALL_BUTTON2,9,103,50,14 + PUSHBUTTON "&Start Existing",IDC_START_EXISTING_BUTTON,66,103,50,14 + PUSHBUTTON "S&top Existing",IDC_STOP_EXISTING_BUTTON,123,103,50,14 + PUSHBUTTON "&Quit",IDC_CANCEL_BUTTON,180,103,50,14 + EDITTEXT IDC_TEXTOUTPUT,9,132,448,224,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL + LTEXT "Install Directory:",IDC_STATIC,9,55,51,8 + LTEXT "This application will install the VMPI service onto your local machine.\nPlease enter a location to install it and click the Install button.",IDC_STATIC,15,9,442,36 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SERVICE_INSTALL_DIALOG, DIALOG + BEGIN + VERTGUIDE, 9 + VERTGUIDE, 457 + END +END +#endif // APSTUDIO_INVOKED + +#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_service_install.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/utils/vmpi/vmpi_service_install/vmpi_service_install.vpc b/utils/vmpi/vmpi_service_install/vmpi_service_install.vpc new file mode 100644 index 0000000..2c40ddb --- /dev/null +++ b/utils/vmpi/vmpi_service_install/vmpi_service_install.vpc @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// VMPI_SERVICE_INSTALL.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" +$Macro OUTBINNAME "vmpi_service_install" + +$Include "$SRCDIR\vpc_scripts\source_exe_win_win32_base.vpc" + +$Configuration "Debug" +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,.\,..\,..\..\common,..\..\..\public" + $PreprocessorDefinitions "$BASE;PROTECTED_THINGS_DISABLE;WINVER=0x400" + $Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)" + $Create/UsePCHThroughFile "stdafx.h" + } + + $Linker + { + $AdditionalDependencies "nafxcwd.lib" + $IgnoreSpecificLibrary "nafxcw.lib libcmt.lib libcmtd.lib" + } +} + +$Configuration "Release" +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,.\,..\,..\..\common,..\..\..\public" + $PreprocessorDefinitions "$BASE;PROTECTED_THINGS_DISABLE;WINVER=0x400" + $Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)" + $Create/UsePCHThroughFile "stdafx.h" + } + + $Linker + { + $AdditionalDependencies "nafxcw.lib libcmt.lib" + $IgnoreSpecificLibrary "nafxcwd.lib libcmtd.lib" + } +} + +$Project "Vmpi_service_install" +{ + $Folder "Source Files" + { + -$File "$SRCDIR\public\tier0\memoverride.cpp" + + $File "StdAfx.cpp" + { + $Configuration + { + $Compiler + { + $Create/UsePrecompiledHeader "Create Precompiled Header (/Yc)" + } + } + } + + $File "ServiceInstallDlg.cpp" + $File "vmpi_service_install.cpp" + $File "vmpi_service_install.rc" + } + + $Folder "Header Files" + { + $File "ServiceInstallDlg.h" + $File "Resource.h" + $File "StdAfx.h" + $File "vmpi_service_install.h" + } + + $Folder "Resource Files" + { + $File "res\vmpi_service_install.ico" + $File "res\vmpi_service_install.rc2" + } + + $Folder "Link Libraries" + { + $DynamicFile "$SRCDIR\lib\public\vmpi.lib" + } +} |