|
|
//#pragma title("TFile - Install File class")
/*---------------------------------------------------------------------------
File: TFile.CPP
Comments: This file contains file installation functions.
(c) Copyright 1995-1999, Mission Critical Software, Inc., All Rights Reserved Proprietary and confidential to Mission Critical Software, Inc.
REVISION LOG ENTRY Author: Juan Medrano l Revision By: Christy Boles Revised on 7/9/97
---------------------------------------------------------------------------*/
#ifdef USE_STDAFX
#include "stdafx.h"
#else
#include <windows.h>
#endif
#include <tchar.h>
#include "Common.hpp"
#include "UString.hpp"
#include "ErrDct.hpp"
#include "TReg.hpp"
#include "TFile.hpp"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
extern TErrorDct err;
//----------------------------------------------------------------------------
// TInstallFile::TInstallFile - constructor initializes variables and if
// pszFileDir is specified, it will get file information for the file located
// in that directory.
//----------------------------------------------------------------------------
TInstallFile::TInstallFile( TCHAR const * pszFileName, // in -file name (not a full path)
TCHAR const * pszFileDir, // in -directory path (without file name)
BOOL silent ) { m_bCopyNeeded = FALSE; m_VersionInfo = NULL; m_dwLanguageCode = 0; m_szFileName[0] = 0; m_szFilePath[0] = 0; m_szTargetPath[0] = 0; m_szFileVersion[0] = 0; m_szFileSize[0] = 0; m_szFileDateTime[0] = 0; m_bSilent = silent;
ZeroMemory( &m_FixedFileInfo, sizeof m_FixedFileInfo ); ZeroMemory( &m_FileData, sizeof m_FileData );
if ( pszFileName ) { safecopy(m_szFileName,pszFileName); }
if ( pszFileDir ) { OpenFileInfo( pszFileDir ); } }
//----------------------------------------------------------------------------
// TInstallFile::OpenFileInfo - gathers file information (file size, mod time,
// version info) and stores it in member variables for later use.
//----------------------------------------------------------------------------
DWORD // ret -last OS return code
TInstallFile::OpenFileInfo( TCHAR const * pszFileDir // in -directory path (without filename)
) { DWORD rc = 0; // OS return code
DWORD dwBytes; // version info structure size
DWORD dwHandle; // version info handle
DWORD * dwVerPointer; // pointer to version language code
UINT uBytes; // version info size
HANDLE hFile; // file handle
VS_FIXEDFILEINFO * lpBuffer; // pointer to version info structure
// construct a full path for the file
safecopy(m_szFilePath,pszFileDir); UStrCpy(m_szFilePath + UStrLen(m_szFilePath),TEXT("\\")); UStrCpy(m_szFilePath + UStrLen(m_szFilePath),m_szFileName);
// get file size, mod time info
hFile = FindFirstFile( m_szFilePath, &m_FileData ); if ( hFile == INVALID_HANDLE_VALUE ) { rc = GetLastError(); if ( ! m_bSilent ) { err.SysMsgWrite( 0, rc, DCT_MSG_OPEN_FILE_INFO_FAILED_SD, m_szFilePath, rc ); } } else { FindClose( hFile ); dwBytes = GetFileVersionInfoSize( m_szFilePath, &dwHandle ); if ( dwBytes <= 0 ) { //err.MsgWrite( 0,
// "No version resource: %ls",
// m_szFilePath );
} else { delete [] m_VersionInfo; m_VersionInfo = new WCHAR[dwBytes + 1];
// get version resource info
if ( ! GetFileVersionInfo( m_szFilePath, 0, dwBytes, m_VersionInfo ) ) { rc = GetLastError(); if ( ! m_bSilent ) {
err.SysMsgWrite( 0, rc, DCT_MSG_GET_VERSION_INFO_FAILED_SD, m_szFilePath, rc ); } } else { // get fixed file info
if ( ! VerQueryValue( m_VersionInfo, TEXT("\\"), (void **) &lpBuffer, &uBytes) ) { if ( ! m_bSilent ) { err.MsgWrite( 0, DCT_MSG_VER_QUERY_VALUE_FAILED_SS, m_szFilePath, L"\\"); } } else { m_FixedFileInfo = *lpBuffer;
// get variable file info language code
if ( ! VerQueryValue( m_VersionInfo, TEXT("\\VarFileInfo\\Translation"), (void **) &dwVerPointer, &uBytes) ) { if ( ! m_bSilent ) { err.MsgWrite( 0, DCT_MSG_VER_QUERY_VALUE_FAILED_SS, m_szFilePath, L"\\VarFileInfo\\Translation"); } } else { m_dwLanguageCode = *dwVerPointer; } } } } }
return rc; }
//----------------------------------------------------------------------------
// TInstallFile::CopyTo - copies the file to a destination path. if it is busy,
// renames the file and tries to copy again.
//----------------------------------------------------------------------------
DWORD // ret -last OS return code
TInstallFile::CopyTo( TCHAR const * pszDestinationPath // in -destination path (full path)
) { DWORD rc = 0; // OS return code
DWORD dwFileAttributes; // file attribute mask
// make sure read-only flag of destination is turned off
dwFileAttributes = ::GetFileAttributes( pszDestinationPath ); if ( dwFileAttributes != 0xFFFFFFFF ) { // Turn off read-only file attribute
if ( dwFileAttributes & FILE_ATTRIBUTE_READONLY ) { ::SetFileAttributes( pszDestinationPath, dwFileAttributes & ~FILE_ATTRIBUTE_READONLY ); } }
// copy file to destination path
if ( ! ::CopyFile( m_szFilePath, pszDestinationPath, FALSE ) ) { rc = GetLastError(); err.SysMsgWrite( 0, rc, DCT_MSG_COPY_FILE_FAILED_SSD, m_szFilePath, pszDestinationPath, rc ); }
return rc; }
//----------------------------------------------------------------------------
// TInstallFile::CompareFile - compares the version, date, and size of the
// file object to the given target file object
//----------------------------------------------------------------------------
int // ret -(-1) if source < target
TInstallFile::CompareFile( // ( 0) if source = target
// ( 1) if source > target
TInstallFile * pFileTrg // in -target file object
) { int nComp; // comparison result
nComp = CompareFileVersion( pFileTrg ); if ( nComp == 0 ) { // versions are the same, compare dates
nComp = CompareFileDateTime( pFileTrg ); if ( nComp <= 0 ) { // source date is less than or equal to target date
// compare file size
nComp = CompareFileSize( pFileTrg ); if ( nComp != 0 ) { // file sizes are not equal, return (source > target)
nComp = 1; } } }
return nComp; }
//----------------------------------------------------------------------------
// TInstallFile::CompareFileSize - compares the file size of the this file
// object with the size of the target file object
//----------------------------------------------------------------------------
int // ret -(-1) if source < target
TInstallFile::CompareFileSize( // ( 0) if source = target
// ( 1) if source > target
TInstallFile * pFileTrg // in -target file object
) { int nCompResult = 0; // comparison result
DWORD dwSrcFileSize = 0; // source file size
DWORD dwTrgFileSize = 0; // target file size
dwSrcFileSize = m_FileData.nFileSizeLow; dwTrgFileSize = pFileTrg->m_FileData.nFileSizeLow;
if ( dwSrcFileSize && dwTrgFileSize ) { if ( dwSrcFileSize < dwTrgFileSize ) { nCompResult = -1; } else if ( dwSrcFileSize > dwTrgFileSize ) { nCompResult = 1; } }
return nCompResult; }
//----------------------------------------------------------------------------
// TInstallFile::CompareFileDateTime - compares the file modification time of
// this file object with the time of the target file object
//----------------------------------------------------------------------------
int // ret -(-1) if source < target
TInstallFile::CompareFileDateTime( // ( 0) if source = target
// ( 1) if source > target
TInstallFile * pFileTrg // in -target file object
) { int nCompResult = 0; // comparison result
__int64 cmp = *(__int64*)&m_FileData.ftLastWriteTime - *(__int64*)&pFileTrg->m_FileData.ftLastWriteTime; if ( cmp ) { // The following lines do a "fuzzy" compare so that file systems that
// store timestamps with different precision levels can be compared for
// equivalence. 20,000,000 represents the number of 100ns intervals in
// a FAT/HPFS twosec file timestamp.
if ( cmp < 0 ) { cmp = -cmp; } if ( cmp >= 20000000 ) { // the timestamps differ by more than 2 seconds, so we need to
// compare the filetime structures
nCompResult = CompareFileTime( &m_FileData.ftLastWriteTime, &pFileTrg->m_FileData.ftLastWriteTime ); } }
return nCompResult; }
//---------------------------------------------------------------
// TInstallFile::CompareFileVersion - compares the version of this
// file object with the version of the target file object
//---------------------------------------------------------------
int // ret -(-1) if source version < target version
TInstallFile::CompareFileVersion( // ( 0) if source version = target version
// ( 1) if source version > target version
TInstallFile * pFileTrg // in -target file object
) { int nCompResult = 0; // comparison result
DWORDLONG dwlSrcVersion = 0; // source version
DWORDLONG dwlTrgVersion = 0; // target version
dwlSrcVersion = ((DWORDLONG)m_FixedFileInfo.dwFileVersionMS << 32) | (DWORDLONG)m_FixedFileInfo.dwFileVersionLS;
dwlTrgVersion = ((DWORDLONG)pFileTrg->m_FixedFileInfo.dwFileVersionMS << 32) | (DWORDLONG)pFileTrg->m_FixedFileInfo.dwFileVersionLS;
if ( dwlTrgVersion ) { if ( dwlSrcVersion < dwlTrgVersion ) { nCompResult = -1; } else if ( dwlSrcVersion > dwlTrgVersion ) { nCompResult = 1; } } else { nCompResult = 1; }
return nCompResult; }
//---------------------------------------------------------------
// TInstallFile::GetFileVersion - retrieves the version as separate
// components: Major, Minor, Release, Modification
//---------------------------------------------------------------
void TInstallFile::GetFileVersion( UINT * uVerMaj, // out -major version
UINT * uVerMin, // out -minor version
UINT * uVerRel, // out -release version
UINT * uVerMod // out -modification version
) { *uVerMaj = HIWORD(m_FixedFileInfo.dwFileVersionMS); *uVerMin = LOWORD(m_FixedFileInfo.dwFileVersionMS); *uVerRel = HIWORD(m_FixedFileInfo.dwFileVersionLS); *uVerMod = LOWORD(m_FixedFileInfo.dwFileVersionLS); }
//---------------------------------------------------------------
// TInstallFile::GetFileVersionString - retrieves the FileVersion
// string of the version resource
//---------------------------------------------------------------
TCHAR * // ret -version string
TInstallFile::GetFileVersionString() { UINT uBytes; // size of version info
TCHAR * szBuffer; // version info buffer
if ( m_VersionInfo && m_szFileVersion[0] == 0 ) { TCHAR szStrFileInfo[MAX_PATH]; _stprintf(szStrFileInfo,TEXT( "\\StringFileInfo\\%04X%04X\\FileVersion"), LOWORD(m_dwLanguageCode), HIWORD(m_dwLanguageCode) );
if ( ! VerQueryValue( m_VersionInfo, szStrFileInfo, (void **) &szBuffer, &uBytes) ) { err.MsgWrite( 0, DCT_MSG_VER_QUERY_VALUE_FAILED_SS, m_szFilePath, szStrFileInfo ); } else { safecopy(m_szFileVersion,szBuffer); } }
return m_szFileVersion; }
//---------------------------------------------------------------
// TInstallFile::GetFileSizeString - retrieves the file size as a string
//---------------------------------------------------------------
TCHAR * // ret -file size string
TInstallFile::GetFileSizeString() { _stprintf(m_szFileSize,TEXT("%ld"), m_FileData.nFileSizeLow ); return m_szFileSize; }
//---------------------------------------------------------------
// TInstallFile::GetFileDateTimeString - retrieves the file modification
// time as a string
//---------------------------------------------------------------
TCHAR * // ret -file mod string
TInstallFile::GetFileDateTimeString( TCHAR const * szFormatString // in -date/time format string
) { //safecopy(m_szFileDateTime,ctime(m_FileData.ftLastWriteTime));
return m_szFileDateTime; }
//----------------------------------------------------------------------------
// TInstallFile::IsBusy - determines if the file is busy by trying to open it
// for reading and writing.
//----------------------------------------------------------------------------
BOOL // ret -TRUE if the file is busy
TInstallFile::IsBusy() // -FALSE otherwise
{ BOOL bIsBusy = FALSE; // is the file busy?
HANDLE hFile; // file handle
DWORD rc; // OS return code
// try to open file for read and write
hFile = CreateFile( m_szFilePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) { rc = GetLastError(); if ( rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION ) { err.MsgWrite( 0, DCT_MSG_FILE_IN_USE_S, m_szFilePath ); bIsBusy = TRUE; } else { if ( ! m_bSilent ) err.SysMsgWrite( 0, rc, DCT_MSG_CREATE_FILE_FAILED_SD, m_szFilePath, rc ); } } else { CloseHandle( hFile ); }
return bIsBusy; }
//----------------------------------------------------------------------------
// TDllFile::TDllFile - constructor for DLL file objects.
//----------------------------------------------------------------------------
TDllFile::TDllFile( TCHAR const * pszFileName, // in -file name (not a full path)
TCHAR const * pszFileDir, // in -directory (without file name)
TCHAR const * pszProgId, // in -Prog ID (for OCX's)
BOOL bSystemFile // in -TRUE if file is a system file
) : TInstallFile( pszFileName, pszFileDir ) { m_bSystemFile = bSystemFile; m_bRegistrationNeeded = FALSE; m_bRegisterTarget = FALSE; m_szProgId[0] = 0; m_szRegPath[0] = 0;
if ( pszProgId ) { safecopy(m_szProgId,pszProgId); } }
//----------------------------------------------------------------------------
// TDllFile::SupportsSelfReg - determines whether the file supports self-registration
//----------------------------------------------------------------------------
BOOL // ret -TRUE if file supports self-reg
TDllFile::SupportsSelfReg() // -FALSE otherwise
{ BOOL bSelfReg = FALSE; // supports self-reg?
UINT uBytes; // size of version info
TCHAR * szBuffer; // version info buffer
if ( m_VersionInfo ) { TCHAR szStrFileInfo[MAX_PATH]; _stprintf(szStrFileInfo,TEXT("\\StringFileInfo\\%04X%04X\\OLESelfRegister"), LOWORD(m_dwLanguageCode), HIWORD(m_dwLanguageCode) );
if ( ! VerQueryValue( m_VersionInfo, szStrFileInfo, (void **) &szBuffer, &uBytes) ) { if ( *m_szProgId ) { bSelfReg = TRUE; } else { err.MsgWrite( 0, DCT_MSG_FILE_NO_SELF_REGISTRATION_S, m_szFilePath ); } } else { bSelfReg = TRUE; } }
return bSelfReg; }
//----------------------------------------------------------------------------
// TDllFile::IsRegistered - determines whether a file is registered
//----------------------------------------------------------------------------
BOOL // ret -TRUE if file is registered
TDllFile::IsRegistered() // -FALSE otherwise
{ BOOL bIsRegistered = FALSE; // is the file registered?
DWORD rc; // OS return code
HRESULT hr; // OLE return code
CLSID clsid; // CLSID for registered class
IClassFactory * pICFGetClassObject; // ClassFactory interface
TCHAR szBuffer[MAX_PATH]; // registry key buffer
// initialize OLE
CoInitialize( NULL ); hr = CLSIDFromProgID( SysAllocString(m_szProgId), &clsid ); if ( SUCCEEDED( hr ) ) { hr = CoGetClassObject( clsid, CLSCTX_ALL, NULL, IID_IClassFactory, (void **)&pICFGetClassObject ); if ( SUCCEEDED( hr ) ) { bIsRegistered = TRUE; pICFGetClassObject->Release(); } } CoUninitialize();
if ( bIsRegistered ) { WCHAR szKeyName[MAX_PATH];
safecopy(szKeyName,m_szProgId);
UStrCpy(szKeyName + UStrLen(szKeyName),"\\CLSID"); TRegKey regKey;
rc = regKey.OpenRead( szKeyName, HKEY_CLASSES_ROOT ); if ( ! rc ) { rc = regKey.ValueGetStr( _T(""), szBuffer, sizeof szBuffer ); if ( ! rc ) { regKey.Close(); UStrCpy(szKeyName,"CLSID\\"); UStrCpy(szKeyName + UStrLen(szKeyName),szBuffer); UStrCpy(szKeyName + UStrLen(szKeyName),"\\InProcServer32"); rc = regKey.OpenRead( szKeyName, HKEY_CLASSES_ROOT ); if ( ! rc ) { rc = regKey.ValueGetStr( _T(""), szBuffer, sizeof szBuffer ); if ( ! rc ) { regKey.Close(); safecopy(m_szRegPath,szBuffer); bIsRegistered = TRUE; } } } } }
return bIsRegistered; }
//----------------------------------------------------------------------------
// TDllFile::CallDllFunction - call an exported function of a dll
//----------------------------------------------------------------------------
DWORD // ret -TRUE if function call success
TDllFile::CallDllFunction( // FALSE if function call failure
TCHAR const * pszFunctionName, // in -Exported function name
TCHAR const * pszDllName // in -name of dll file
) { DWORD rc = 0; // OS return code
HINSTANCE hLib; // handle
WCHAR szDllNameUsed[MAX_PATH]; char pszFunctionNameA[MAX_PATH];
safecopy(pszFunctionNameA,pszFunctionName);
if ( pszDllName ) { safecopy(szDllNameUsed,pszDllName); } else { safecopy(szDllNameUsed,m_szFilePath); }
// load the dll into memory
hLib = LoadLibrary( szDllNameUsed ); if ( ! hLib ) { rc = GetLastError(); err.SysMsgWrite( 0, rc, DCT_MSG_LOAD_LIBRARY_FAILED_SD, szDllNameUsed, rc ); } else { // Find the entry point.
FARPROC lpDllEntryPoint = GetProcAddress( hLib, pszFunctionNameA ); if ( lpDllEntryPoint == NULL ) { rc = GetLastError(); err.SysMsgWrite( 0, rc, DCT_MSG_GET_PROC_ADDRESS_FAILED_SSD, szDllNameUsed, pszFunctionName, rc ); } else { // call the dll function
rc = (DWORD)(*lpDllEntryPoint)(); }
FreeLibrary( hLib ); }
return rc; }
//----------------------------------------------------------------------------
// TDllFile::Register - registers the file
//----------------------------------------------------------------------------
DWORD // ret -last OS return code
TDllFile::Register() { DWORD rc = 0; // OS return code
TCHAR const szFunctionName[MAX_PATH] = _T("DllRegisterServer");
if ( m_bRegisterTarget ) { rc = CallDllFunction( szFunctionName, m_szTargetPath ); } else { rc = CallDllFunction( szFunctionName ); }
if ( rc ) { err.MsgWrite( 0, DCT_MSG_DLL_CALL_FAILED_SDS, szFunctionName, rc, "failed to register object classes" ); }
return rc; }
//----------------------------------------------------------------------------
// TDllFile::Unregister - unregisters the file
//----------------------------------------------------------------------------
DWORD // ret -last OS return code
TDllFile::Unregister() { DWORD rc = 0; // OS return code
TCHAR const szFunctionName[MAX_PATH] = _T("DllUnregisterServer");
if ( m_bRegisterTarget ) { rc = CallDllFunction( szFunctionName, m_szTargetPath ); } else { rc = CallDllFunction( szFunctionName ); }
if ( rc ) { err.MsgWrite( 0, DCT_MSG_DLL_CALL_FAILED_SDS, szFunctionName, rc, "failed to unregister object classes" ); } return rc; }
|