Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

554 lines
14 KiB

//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "uddimsifiler.h"
static PTCHAR GetFileLongName( PTCHAR szFileName );
static PTCHAR GetErrorMsg( UINT iRet );
static bool UpdateFileTable( void );
static bool FileExists( PTCHAR szFileName );
static bool UpdateFile( PTCHAR szFile, PTCHAR szFilePath );
static bool LookupComponentTargetFolder( PTCHAR szComponent, PTCHAR szComponentFolder );
static bool UpdateFileHash( PTCHAR szFile, PTCHAR szFilePath );
static bool UpdateMSIVerFromFile( LPCTSTR szFile );
static void LogError( LPCTSTR fmt, ... );
PMSIHANDLE g_hDatabase;
TCHAR g_MSIFile[ MAX_PATH + 1 ];
TCHAR g_LogFile[ MAX_PATH + 1 ];
TCHAR g_SourceDir[ MAX_PATH + 1 ];
TCHAR g_VerFile[ MAX_PATH + 1 ];
//--------------------------------------------------------------
int __cdecl _tmain( int argc, TCHAR* argv[], TCHAR* envp[] )
{
UINT iRet = 0;
bool bDisplayUsage = false;
ZeroMemory( g_MSIFile, sizeof g_MSIFile );
ZeroMemory( g_LogFile, sizeof g_LogFile );
ZeroMemory( g_VerFile, sizeof g_VerFile );
ZeroMemory( g_SourceDir, sizeof g_SourceDir );
if ( argc > 1 )
{
// loop through all the arguments
for ( int i=1; i<argc; i++ )
{
// -d is the path to the msi file
if ( _tcscmp( argv[ i ], TEXT( "-d" ) )==0 )
{
i++;
if ( i >= argc )
{
bDisplayUsage = true;
break;
}
_tcscpy( g_MSIFile, argv[ i ] );
continue;
}
// -s is the path to the source files
if( 0 == _tcscmp( argv[ i ], TEXT( "-s" ) ) )
{
i++;
if ( i >= argc )
{
bDisplayUsage = true;
break;
}
_tcscpy( g_SourceDir, argv[ i ] );
continue;
}
// -L is the log file
if( 0 == _tcsicmp( argv[ i ], TEXT( "-L" ) ) )
{
i++;
if ( i >= argc )
{
bDisplayUsage = true;
break;
}
_tcscpy( g_LogFile, argv[ i ] );
continue;
}
// -v is a file containing the version stamp
if( 0 == _tcsicmp( argv[ i ], TEXT( "-v" ) ) )
{
i++;
if ( i >= argc )
{
bDisplayUsage = true;
break;
}
_tcscpy( g_VerFile, argv[ i ] );
continue;
}
}
}
// usage
if ( bDisplayUsage || argc == 1 || NULL != _tcsrchr( argv[ 1 ], '?' ) )
{
_tprintf( TEXT( "Updates the File Table with files in a folder ( using File.File key names )\n\n" ) );
_tprintf( TEXT( "Usage: %s -d <MSI database> -s <location of files> [ -L <log file> ] [-v <product version file>]\n\n" ), argv[ 0 ] );
return 0;
}
//
// open the database
//
if( !FileExists( g_MSIFile ) )
{
LogError( TEXT( "***ERROR: MSI File does not exist: %s" ), g_MSIFile );
return 1;
}
//
// open the MSI file
//
iRet = MsiOpenDatabase( g_MSIFile, MSIDBOPEN_TRANSACT, &g_hDatabase );
if( ERROR_SUCCESS != iRet )
{
LogError( TEXT( "***ERROR: MsiOpenDatabase Error: %s" ), GetErrorMsg( iRet ) );
return 1;
}
bool bRet = UpdateFileTable();
//
// update the ProductVersion property
//
UpdateMSIVerFromFile( g_VerFile );
iRet = MsiDatabaseCommit( g_hDatabase );
if( ERROR_SUCCESS != iRet )
{
LogError( TEXT( "***ERROR: MsiDatabaseCommit Error: %s" ), GetErrorMsg( iRet ) );
return 0;
}
return bRet ? 0 : 1;
}
//--------------------------------------------------------------
static bool UpdateFileTable( void )
{
UINT iRet;
PMSIHANDLE hView;
PMSIHANDLE hRecord = 0;
//
// open a view and submit the SQL query
//
iRet = MsiDatabaseOpenView( g_hDatabase, TEXT( "select File from File" ), &hView );
if( ERROR_SUCCESS != iRet )
{
LogError( TEXT( "***ERROR: MsiDatabaseOpenView Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
//
// execute the SQL query
//
iRet = MsiViewExecute( hView, hRecord );
if( ERROR_SUCCESS != iRet )
{
LogError( TEXT( "***ERROR: MsiViewExecute Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
//
// fetch the data
//
TCHAR szFile[ 256 ];
TCHAR szFilePath[ 256 ];
DWORD cchValueBuf;
while( ERROR_NO_MORE_ITEMS != MsiViewFetch( hView, &hRecord ) )
{
cchValueBuf = 256;
MsiRecordGetString( hRecord, 1, szFile, &cchValueBuf );
//
// create the full path to the file in \binaries folder
//
_stprintf( szFilePath, TEXT( "%s\\%s" ), g_SourceDir, szFile );
//LogError( TEXT( "Updating: %s\n" ), szFilePath );
//
// does the file exist?
//
if( !FileExists( szFilePath ) )
{
LogError( TEXT( "***ERROR: Source File does not exist: %s" ), szFilePath );
return false;
}
//
// update the size, version, language and hash table
//
if( !UpdateFile( szFile, szFilePath ) )
{
LogError( TEXT( "***ERROR: Unable to update file %s\n" ), szFile );
return false;
}
}
return true;
}
//--------------------------------------------------------------
static bool UpdateFile( PTCHAR szFile, PTCHAR szFilePath )
{
PMSIHANDLE hView;
PMSIHANDLE hRecord = 0;
//
// get the version and language of this file
//
TCHAR szVersionBuf[ 100 ];
DWORD dwVersionBuf = 100;
TCHAR szLanguageBuf[ 100 ];
DWORD dwLanguageBuf = 100;
UINT iRet = MsiGetFileVersion(
szFilePath, // path to the file
szVersionBuf, // returned version string
&dwVersionBuf, // buffer byte count
szLanguageBuf, // returned language string
&dwLanguageBuf ); // buffer byte count
if ( ERROR_SUCCESS != iRet )
{
_tcscpy( szVersionBuf, TEXT( "" ) );
_tcscpy( szLanguageBuf, TEXT( "" ) );
UpdateFileHash( szFile, szFilePath );
}
//
// get the file's size
//
HANDLE hFile = CreateFile( szFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( INVALID_HANDLE_VALUE == hFile )
{
return false;
}
LARGE_INTEGER liSize;
if( 0 == GetFileSizeEx( hFile, &liSize ) )
{
LogError( TEXT( "***ERROR: Unable to get file size for file %s\n" ), szFilePath );
CloseHandle( hFile );
return false;
}
CloseHandle( hFile );
//
// update the file's version, language and size
//
TCHAR szSQLQuery[ 256 ];
_stprintf( szSQLQuery, TEXT( "UPDATE File SET FileSize = ?, Version = ?, Language = ? where File = ?" ) );
iRet = MsiDatabaseOpenView( g_hDatabase, szSQLQuery, &hView );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiDatabaseOpenView Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// create a temp record to store the replacable values
hRecord = MsiCreateRecord( 4 );
if ( NULL == hRecord )
{
LogError( 0, TEXT( "***ERROR: MsiCreateRecord failed" ) );
return false;
}
int index = 1;
// Size goes in #1
iRet = MsiRecordSetInteger( hRecord, index++, liSize.LowPart );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiRecordSetString Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// Version goes in #2
iRet = MsiRecordSetString( hRecord, index++, szVersionBuf );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiRecordSetString Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// Language goes in #3
iRet = MsiRecordSetString( hRecord, index++, szLanguageBuf );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiRecordSetString Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// File goes in #4
iRet = MsiRecordSetString( hRecord, index++, szFile );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiRecordSetString Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// execute the update query
iRet = MsiViewExecute( hView, hRecord );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiViewExecute Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
return true;
}
//--------------------------------------------------------------
static bool UpdateMSIVerFromFile( LPCTSTR szFileName )
{
MSIHANDLE hView;
TCHAR szVersionBuf[ 256 ];
TCHAR szLanguageBuf[ 256 ];
TCHAR szQuery[ 256 ];
DWORD dwLanguageBuf = 0, dwVersionBuf = 0;
if ( !szFileName )
return false;
if ( !FileExists( (LPTSTR)szFileName ) )
return false;
dwVersionBuf = sizeof szVersionBuf / sizeof szVersionBuf[0];
dwLanguageBuf = sizeof szLanguageBuf / sizeof szLanguageBuf[0];
UINT iRet = MsiGetFileVersion( szFileName, // path to the file
szVersionBuf, // returned version string
&dwVersionBuf, // buffer byte count
szLanguageBuf, // returned language string
&dwLanguageBuf ); // buffer byte count
if ( iRet != ERROR_SUCCESS )
{
LogError( TEXT( "***ERROR: MsiGetFileVersion Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
_tcscpy( szQuery, TEXT( "UPDATE Property SET Property.Value='" ) );
_tcscat( szQuery, szVersionBuf );
_tcscat( szQuery, TEXT("' WHERE Property.Property='ProductVersion'") );
iRet = MsiDatabaseOpenView( g_hDatabase, szQuery, &hView );
if ( ERROR_SUCCESS != iRet )
{
LogError( TEXT( "***ERROR: MsiDatabaseOpenView Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// execute the update query
iRet = MsiViewExecute( hView, NULL );
if ( ERROR_SUCCESS != iRet )
{
LogError( TEXT( "***ERROR: MsiViewExecute Error: %s" ), GetErrorMsg( iRet ) );
MsiCloseHandle( hView );
return false;
}
MsiCloseHandle( hView );
return true;
}
//--------------------------------------------------------------
static bool UpdateFileHash( PTCHAR szFile, PTCHAR szFilePath )
{
PMSIHANDLE hView;
PMSIHANDLE hRecord = 0;
//
// get the file's size
//
MSIFILEHASHINFO hashinfo;
hashinfo.dwFileHashInfoSize = sizeof( MSIFILEHASHINFO );
UINT iRet = MsiGetFileHash( szFilePath, 0, &hashinfo );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiGetFileHash Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
//
// update the file's version, language and size
//
TCHAR szSQLQuery[ 256 ];
_stprintf( szSQLQuery, TEXT( "UPDATE MsiFileHash SET HashPart1 = ?, HashPart2 = ?, HashPart3 = ?, HashPart4 = ? where File_ = ?" ) );
iRet = MsiDatabaseOpenView( g_hDatabase, szSQLQuery, &hView );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiDatabaseOpenView Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// create a temp record to store the replacable values
hRecord = MsiCreateRecord( 5 );
if ( NULL == hRecord )
{
LogError( 0, TEXT( "***ERROR: MsiCreateRecord failed" ) );
return false;
}
int index = 1;
for( int i=0; i<4; i++ )
{
iRet = MsiRecordSetInteger( hRecord, index++, hashinfo.dwData[ i ] );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiRecordSetInteger Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
}
// File goes in #5
iRet = MsiRecordSetString( hRecord, index++, szFile );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiRecordSetString Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
// execute the update query
iRet = MsiViewExecute( hView, hRecord );
if ( ERROR_SUCCESS != iRet )
{
LogError( 0, TEXT( "***ERROR: MsiViewExecute Error: %s" ), GetErrorMsg( iRet ) );
return false;
}
return true;
}
//--------------------------------------------------------------
static bool FileExists( PTCHAR szFileName )
{
FILE *file = _tfopen( szFileName, TEXT( "rt" ) );
if( NULL == file )
{
return false;
}
fclose( file );
return true;
}
//--------------------------------------------------------------
static PTCHAR GetErrorMsg( UINT iRet )
{
static TCHAR szErrMsg[ 100 ];
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
iRet,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
( LPTSTR ) szErrMsg,
100,
NULL );
return szErrMsg;
}
//--------------------------------------------------------------------------
static void LogError( LPCTSTR fmt, ... )
{
TCHAR szTime[ 10 ];
TCHAR szDate[ 10 ];
::_tstrtime( szTime );
::_tstrdate( szDate );
va_list marker;
TCHAR szBuf[ 1024 ];
size_t cbSize = ( sizeof( szBuf ) / sizeof( TCHAR ) ) - 1; // one byte for null
_sntprintf( szBuf, cbSize, TEXT( "%s %s: " ), szDate, szTime );
szBuf[ 1023 ] = '\0';
cbSize -= _tcslen( szBuf );
va_start( marker, fmt );
_vsntprintf( szBuf + _tcslen( szBuf ), cbSize, fmt, marker );
szBuf[ 1023 ] = '\0';
cbSize -= _tcslen( szBuf );
va_end( marker );
_tcsncat( szBuf, TEXT( "\r\n" ), cbSize );
_tprintf( TEXT( "%s" ), szBuf );
if( 0 == _tcslen( g_LogFile ) )
return;
// write the data out to the log file
char szBufA[ 1024 ];
WideCharToMultiByte( CP_ACP, 0, szBuf, -1, szBufA, 1024, NULL, NULL );
HANDLE hFile = CreateFile(
g_LogFile, // file name
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // no security
OPEN_ALWAYS, // open and create if not exists
FILE_ATTRIBUTE_NORMAL, // normal file
NULL ); // no attr. template
if( hFile == INVALID_HANDLE_VALUE )
{
return;
}
//
// move the file pointer to the end so that we can append
//
SetFilePointer( hFile, 0, NULL, FILE_END );
DWORD dwNumberOfBytesWritten;
BOOL bOK = WriteFile(
hFile,
szBufA,
( UINT ) strlen( szBufA ), // number of bytes to write
&dwNumberOfBytesWritten, // number of bytes written
NULL ); // overlapped buffer
FlushFileBuffers ( hFile );
CloseHandle( hFile );
}