866 lines
29 KiB
C++
866 lines
29 KiB
C++
|
//#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 );
|
||
|
|
||
|
if ( rc == ERROR_SHARING_VIOLATION || rc == ERROR_USER_MAPPED_FILE )
|
||
|
{
|
||
|
// file was busy, we need to rename it and try again
|
||
|
|
||
|
// create temp filename
|
||
|
TCHAR szDestDir[MAX_PATH];
|
||
|
TCHAR szTempFile[MAX_PATH];
|
||
|
|
||
|
safecopy(szDestDir,pszDestinationPath);
|
||
|
|
||
|
TCHAR * lastSlash = _tcsrchr(szDestDir,_T('\\'));
|
||
|
|
||
|
if ( lastSlash )
|
||
|
{
|
||
|
(*lastSlash) = 0;
|
||
|
}
|
||
|
|
||
|
if ( ! ::GetTempFileName( szDestDir, TEXT("~MC"), 0, szTempFile ) )
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
err.SysMsgWrite( 0,
|
||
|
rc,
|
||
|
DCT_MSG_GET_TEMP_FILENAME_FAILED_D,
|
||
|
rc );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DeleteFile( szTempFile );
|
||
|
|
||
|
// rename destination to temp filename
|
||
|
if ( ! ::MoveFile( pszDestinationPath, szTempFile ) )
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
err.SysMsgWrite( 0,
|
||
|
rc,
|
||
|
DCT_MSG_MOVE_FILE_FAILED_SSD,
|
||
|
pszDestinationPath,
|
||
|
szTempFile,
|
||
|
rc );
|
||
|
|
||
|
// can't rename, try rename on reboot
|
||
|
|
||
|
if ( ! ::CopyFile( m_szFilePath, szTempFile, FALSE ) )
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
err.SysMsgWrite( 0,
|
||
|
rc,
|
||
|
DCT_MSG_COPY_FILE_FAILED_SSD,
|
||
|
m_szFilePath,
|
||
|
szTempFile,
|
||
|
rc );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.MsgWrite( 0,
|
||
|
DCT_MSG_SOURCE_COPIED_TO_TEMP_SS,
|
||
|
m_szFilePath,
|
||
|
szTempFile );
|
||
|
|
||
|
|
||
|
if ( ! ::MoveFileEx( szTempFile, pszDestinationPath,
|
||
|
MOVEFILE_DELAY_UNTIL_REBOOT ) )
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
err.SysMsgWrite( 0,
|
||
|
rc,
|
||
|
DCT_MSG_MOVE_FILE_EX_FAILED_SSD,
|
||
|
szTempFile,
|
||
|
pszDestinationPath,
|
||
|
rc );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.MsgWrite( 0,
|
||
|
DCT_MSG_RENAME_ON_REBOOT_SS,
|
||
|
szTempFile,
|
||
|
pszDestinationPath );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.MsgWrite( 0,
|
||
|
DCT_MSG_BUSY_FILE_RENAMED_SS,
|
||
|
pszDestinationPath,
|
||
|
szTempFile );
|
||
|
|
||
|
if ( ! ::MoveFileEx( szTempFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT ) )
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
err.SysMsgWrite( 0,
|
||
|
rc,
|
||
|
DCT_MSG_MOVE_FILE_EX_FAILED_SSD,
|
||
|
szTempFile,
|
||
|
L"NULL",
|
||
|
rc );
|
||
|
}
|
||
|
// try to copy again
|
||
|
if ( ! ::CopyFile( m_szFilePath, pszDestinationPath, FALSE ) )
|
||
|
{
|
||
|
rc = GetLastError();
|
||
|
err.SysMsgWrite( 0,
|
||
|
rc,
|
||
|
DCT_MSG_COPY_FILE_FAILED_SSD,
|
||
|
m_szFilePath,
|
||
|
pszDestinationPath,
|
||
|
rc );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.MsgWrite( 0,
|
||
|
DCT_MSG_FILE_COPIED_2ND_ATTEMPT_SS,
|
||
|
m_szFilePath,
|
||
|
pszDestinationPath );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|