|
|
//========= 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; } } }
|