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.
 
 
 
 
 
 

2687 lines
83 KiB

/******************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
main.cpp
Abstract:
This file contains the Unit Test for Cabinet functions.
Revision History:
Davide Massarenti (Dmassare) 09/03/99
created
******************************************************************************/
#include "stdafx.h"
#include <initguid.h>
#include "msscript.h"
#include "HelpServiceTypeLib.h"
#include "HelpServiceTypeLib_i.c"
#include "HelpCenterTypeLib.h"
#include "HelpCenterTypeLib_i.c"
////////////////////////////////////////////////////////////////////////////////
#define LOG__MPC_EXIT_IF_METHOD_FAILS(hr, cmd) \
{ \
if(FAILED(hr=cmd)) \
{ \
l_FileLog.LogRecord( "!!ERROR: %08x %s %d\n", hr, #cmd, __LINE__ ); \
__MPC_TRACE_HRESULT(hr); __MPC_FUNC_LEAVE; \
} \
}
////////////////////////////////////////////////////////////////////////////////
static const DWORD c_dwVersion = 0x07494250; // PBI 07
static const WCHAR c_szNTTREE_BASE [] = L"HelpAndSupportServices";
static const WCHAR c_szNTTREE_INDEX [] = L"index.dat";
static const WCHAR c_szNTTREE_TMP [] = L"%TEMP%";
static const WCHAR c_szPackageDescription [] = L"package_description.xml";
static const WCHAR c_szHHT_rootTag [] = L"METADATA";
static const WCHAR c_szHHT_manual_STOPSIGN [] = L"STOPSIGN_ENTRIES";
static const WCHAR c_szHHT_manual_STOPWORD [] = L"STOPWORD_ENTRIES";
static const WCHAR c_szHHT_manual_OPERATOR [] = L"OPERATOR_ENTRIES";
static const WCHAR c_szHHT_synset_SYNTABLE [] = L"SYNTABLE";
static const WCHAR c_szHHT_loc_SCOPE [] = L"SCOPE_DEFINITION";
static const WCHAR c_szHHT_loc_TAXONOMY [] = L"TAXONOMY_ENTRIES";
static const WCHAR c_szHHT_noloc_FTS [] = L"FTS";
static const WCHAR c_szHHT_noloc_INDEX [] = L"INDEX";
static const WCHAR c_szHHT_noloc_HELPIMAGE [] = L"HELPIMAGE";
static const WCHAR c_szHHT_conv_SCOPE [] = L"SCOPE_DEFINITION/SCOPE";
static LPCWSTR const c_rgHHT_conv_SCOPE [] = { L"DISPLAYNAME" };
static const WCHAR c_szHHT_conv_TAXONOMY [] = L"TAXONOMY_ENTRIES/TAXONOMY_ENTRY";
static LPCWSTR const c_rgHHT_conv_TAXONOMY [] = { L"TITLE", L"DESCRIPTION" };
////////////////////////////////////////
static MPC::FileLog l_FileLog;
static LPCWSTR l_szRoot = NULL;
static LPCWSTR l_szLog = NULL;
static LPCWSTR l_szDBLog = NULL;
static int l_lMaxElements = 1000;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
struct SetupImageEntry;
struct FileEntry;
struct TaxonomyEntry;
struct PackageEntry;
struct PostBuildEntry;
////////////////////////////////////////////////////////////////////////////////
struct SetupImageEntry
{
MPC::wstring m_strSKU;
MPC::wstring m_strLocalization;
MPC::wstring m_strPurpose;
MPC::wstring m_strSourceFile;
MPC::wstring m_strTemporaryName;
MPC::wstring m_strDestinationName;
MPC::wstring m_strDestinationDir;
MPC::wstring m_strTemporaryFullPath;
DATE m_lastModified;
bool m_fUpdated;
SetupImageEntry()
{
m_lastModified = 0;
m_fUpdated = false;
}
friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ SetupImageEntry& val );
friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const SetupImageEntry& val );
HRESULT Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
HRESULT Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
};
////////////////////////////////////////////////////////////////////////////////
struct FileEntry
{
MPC::wstring m_strName;
MPC::wstring m_strFullPath;
DATE m_lastModified_HIGH;
DATE m_lastModified_LOW;
long m_lChunks;
bool m_fUpdated;
FileEntry()
{
m_lastModified_HIGH = 0;
m_lastModified_LOW = 0;
m_lChunks = 0;
m_fUpdated = false;
}
friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ FileEntry& val );
friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const FileEntry& val );
void GenerateChunkName( /*[in]*/ long lChunk, /*[out]*/ MPC::wstring& strFile ) const;
void GetDate( /*[out]*/ DATE& date_HIGH, /*[out]*/ DATE& date_LOW ) const;
void SetDate ( /*[in]*/ bool fLookForChunks = false );
bool WasModified() const;
void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
bool IsNewer( /*[in]*/ const FileEntry& fe );
bool IsNewer( /*[in]*/ DATE date );
};
typedef std::list< FileEntry > FileList;
typedef FileList::iterator FileIter;
typedef FileList::const_iterator FileIterConst;
////////////////////////////////////////////////////////////////////////////////
struct TaxonomyEntry
{
FileEntry m_fe;
FileEntry m_feMANUAL;
FileEntry m_feSYNSET;
FileEntry m_feLOC;
FileEntry m_feNOLOC;
bool m_fUpdated;
FileEntry m_fe_New;
TaxonomyEntry()
{
m_fUpdated = false;
}
friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ TaxonomyEntry& val );
friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const TaxonomyEntry& val );
HRESULT Import( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
HRESULT Export( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
};
typedef std::list< TaxonomyEntry > TaxonomyList;
typedef TaxonomyList::iterator TaxonomyIter;
typedef TaxonomyList::const_iterator TaxonomyIterConst;
////////////////////////////////////////////////////////////////////////////////
struct PackageEntry
{
MPC::wstring m_strDir;
MPC::wstring m_strPackageDescription;
FileList m_flSAF;
FileList m_flINSTALL;
TaxonomyList m_flHHT;
MPC::wstring m_strNew_Cabinet;
MPC::wstring m_strNew_Database;
MPC::wstring m_DB_strSKU;
long m_DB_lLCID;
MPC::wstring m_DB_strDisplayName;
friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ PackageEntry& val );
friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const PackageEntry& val );
HRESULT OpenPackageDescription( /*[in/out]*/ MPC::XmlUtil& xml );
HRESULT Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
HRESULT Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
HRESULT ProcessHHTFile( /*[in]*/ LPCWSTR szHHTFile, /*[in]*/ JetBlue::SessionHandle* handle, /*[in]*/ JetBlue::Database* db );
HRESULT CreateDatabase( /*[in]*/ const MPC::wstring& strTmp );
void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
};
////////////////////////////////////////////////////////////////////////////////
enum PostBuildType
{
POSTBUILDTYPE_NORMAL = 0,
POSTBUILDTYPE_SAF ,
POSTBUILDTYPE_HHT ,
};
struct PostBuildEntry
{
PostBuildType m_pbt;
SetupImageEntry m_entry;
PackageEntry m_package;
friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ PostBuildEntry& val );
friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const PostBuildEntry& val );
void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
};
typedef std::list< PostBuildEntry > PostBuildList;
typedef PostBuildList::iterator PostBuildIter;
typedef PostBuildList::const_iterator PostBuildIterConst;
////////////////////////////////////////////////////////////////////////////////
struct SkuInformation
{
MPC::wstring m_strName;
MPC::wstring m_strCabinet;
MPC::wstring m_strProdFilt;
bool m_fDesktop;
bool m_fServer;
bool m_fEmbedded;
SkuInformation()
{
m_fDesktop = false;
m_fServer = false;
m_fEmbedded = false;
}
friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ SkuInformation& val );
friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const SkuInformation& val );
};
typedef std::list< SkuInformation > SkuInformationList;
typedef SkuInformationList::iterator SkuInformationIter;
typedef SkuInformationList::const_iterator SkuInformationIterConst;
////////////////////////////////////////////////////////////////////////////////
static void GetRootDirectory( /*[out]*/ MPC::wstring& strRoot )
{
strRoot = l_szRoot ? l_szRoot : c_szNTTREE_TMP; MPC::SubstituteEnvVariables( strRoot );
}
static void GetLogFile( /*[out]*/ MPC::wstring& strLog )
{
GetRootDirectory( strLog );
strLog += L"\\";
strLog += l_szLog ? l_szLog : L"hss.log";
}
static void GetDBLogFile( /*[out]*/ MPC::wstring& strDBLog )
{
GetRootDirectory( strDBLog );
strDBLog += L"\\";
strDBLog += l_szDBLog ? l_szDBLog : L"createdb.log";
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
static HRESULT ExtractFile( /*[in]*/ LPCWSTR szCabinet, /*[in]*/ LPCWSTR szDst, /*[in]*/ LPCWSTR szFile )
{
__HCP_FUNC_ENTRY( "ExtractFile" );
HRESULT hr;
l_FileLog.LogRecord( L"Extracting '%s' from '%s'", szFile, szCabinet );
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DecompressFromCabinet( szCabinet, szDst, szFile ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static void RemoveDirectory( /*[in]*/ const MPC::wstring& strDir )
{
MPC::FileSystemObject fso( strDir.c_str() );
(void)fso.DeleteChildren( true, false );
}
////////////////////
static HRESULT MoveDataIsland( /*[in ]*/ MPC::XmlUtil& xmlIN ,
/*[out]*/ MPC::XmlUtil& xmlOUT ,
/*[in ]*/ LPCWSTR szTAG )
{
__HCP_FUNC_ENTRY( "MoveDataIsland" );
HRESULT hr;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
CComPtr<IXMLDOMNode> xdnRoot;
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlOUT.GetRoot( &xdnRoot ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlIN.GetNodes( szTAG, &xdnl ));
for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
{
CComPtr<IXMLDOMNode> xdnReplaced;
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnRoot->appendChild( xdn, &xdnReplaced ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static HRESULT ConvertAttributesToElements( /*[in]*/ MPC::XmlUtil& xml ,
/*[in]*/ LPCWSTR szTAG ,
/*[in]*/ LPCWSTR const* rgATTRIB ,
/*[in]*/ int iATTRIB )
{
__HCP_FUNC_ENTRY( "ConvertAttributesToElements" );
HRESULT hr;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( szTAG, &xdnl ));
for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
{
for(int i=0; i<iATTRIB; i++)
{
LPCWSTR szATTRIB = rgATTRIB[i];
CComPtr<IXMLDOMAttribute> xdna;
bool fFound;
//
// Move the value from the attribute to the element.
//
if(SUCCEEDED(xml.GetAttribute( NULL, szATTRIB, &xdna, fFound, xdn )) && xdna)
{
CComVariant vValue;
CComPtr<IXMLDOMNode> xdnSUB;
__MPC_EXIT_IF_METHOD_FAILS(hr, xdna->get_value( &vValue ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.CreateNode( szATTRIB, &xdnSUB, xdn ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutValue( NULL, vValue, fFound, xdnSUB ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.RemoveAttribute( NULL, szATTRIB, xdn ));
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static HRESULT ConvertElementsToAttributes( /*[in]*/ MPC::XmlUtil& xml ,
/*[in]*/ LPCWSTR szTAG ,
/*[in]*/ LPCWSTR const* rgATTRIB ,
/*[in]*/ int iATTRIB )
{
__HCP_FUNC_ENTRY( "ConvertElementsToAttributes" );
HRESULT hr;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( szTAG, &xdnl ));
for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
{
for(int i=0; i<iATTRIB; i++)
{
LPCWSTR szATTRIB = rgATTRIB[i];
CComPtr<IXMLDOMNode> xdnSUB;
//
// Move the value from the attribute to the element.
//
if(SUCCEEDED(xdn->selectSingleNode( CComBSTR( szATTRIB ), &xdnSUB )) && xdnSUB)
{
CComVariant vValue;
bool fFound;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, vValue, fFound, xdnSUB ));
if(fFound)
{
CComPtr<IXMLDOMAttribute> xdna;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, szATTRIB, &xdna, fFound, xdn ));
if(xdna)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xdna->put_value( vValue ));
}
}
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.RemoveNode( NULL, xdnSUB ));
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static HRESULT SpreadToFiles( /*[in]*/ MPC::XmlUtil& xmlSrc ,
/*[in]*/ FileEntry& fe ,
/*[in]*/ long lLimit )
{
__HCP_FUNC_ENTRY( "SpreadToFiles" );
HRESULT hr;
MPC::XmlUtil xmlDst;
MPC::wstring strFile;
long lCount = 0;
bool fCreate = true;
fe.m_lChunks = 0;
while(1)
{
CComPtr<IXMLDOMNode> xdnRootSrc;
CComPtr<IXMLDOMNode> xdnRootDst;
CComPtr<IXMLDOMNode> xdnSrc;
CComPtr<IXMLDOMNode> xdnDst;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
long lLength;
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlSrc.GetRoot( &xdnRootSrc ));
if(fCreate)
{
fCreate = false;
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.New( xdnRootSrc, /*fDeep*/false ));
}
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.GetRoot( &xdnRootDst ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootSrc->get_firstChild( &xdnSrc ));
if(xdnSrc)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc->get_childNodes( &xdnl ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnl ->get_length ( &lLength ));
if(lLength < lLimit)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->appendChild( xdnSrc, &xdn ));
lCount += lLength;
}
else
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc ->cloneNode ( VARIANT_FALSE, &xdn ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->appendChild( xdn, &xdnDst )); xdn.Release();
for(lCount = 0; lCount < lLimit && SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release(), lCount++)
{
CComPtr<IXMLDOMNode> xdn2;
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnDst->appendChild( xdn, &xdn2 ));
}
}
}
if(xdnSrc == NULL || lCount >= lLimit)
{
fe.GenerateChunkName( fe.m_lChunks++, strFile );
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.Save( strFile.c_str() ));
lCount = 0;
fCreate = true;
}
if(!xdnSrc) break;
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static HRESULT CollateFromFiles( /*[in]*/ MPC::XmlUtil& xmlDst ,
/*[in]*/ LPCWSTR szRoot ,
/*[in]*/ FileEntry& fe )
{
__HCP_FUNC_ENTRY( "CollateFromFiles" );
HRESULT hr;
MPC::XmlUtil xmlSrc;
MPC::wstring strFile;
bool fCreated = false;
bool fLoaded;
bool fFound;
for(long l=0; l<fe.m_lChunks; l++)
{
fe.GenerateChunkName( l, strFile );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, (fCreated ? xmlSrc : xmlDst).Load( strFile.c_str(), szRoot, fLoaded, &fFound ));
if(fLoaded == false ||
fFound == false )
{
l_FileLog.LogRecord( L"Not a valid HHT: '%s'", strFile.c_str() );
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
if(fCreated)
{
CComPtr<IXMLDOMNode> xdnRootSrc;
CComPtr<IXMLDOMNode> xdnRootDst;
CComPtr<IXMLDOMNode> xdnSrc;
CComPtr<IXMLDOMNode> xdnDst;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
CComBSTR bstrTag;
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlSrc.GetRoot( &xdnRootSrc ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.GetRoot( &xdnRootDst ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootSrc->get_firstChild( &xdnSrc ));
if(!xdnSrc) continue;
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc ->get_nodeName ( &bstrTag ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->selectSingleNode( bstrTag, &xdnDst ));
if(!xdnDst)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->appendChild( xdnSrc, &xdn ));
}
else
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc->get_childNodes( &xdnl ));
for(; SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
{
CComPtr<IXMLDOMNode> xdn2;
__MPC_EXIT_IF_METHOD_FAILS(hr, xdnDst->appendChild( xdn, &xdn2 ));
}
}
}
else
{
fCreated = true;
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////
static void FixString( /*[in/out]*/ MPC::wstring& strText, /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
{
if(!_wcsnicmp( strText.c_str(), strRootOld.c_str(), strRootOld.size() ))
{
strText.replace( 0, strRootOld.size(), strRoot );
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
/*[out]*/ SetupImageEntry& val )
{
__HCP_FUNC_ENTRY( "operator>> SetupImageEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strSKU );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strLocalization );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strPurpose );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strSourceFile );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strTemporaryName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strDestinationName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strDestinationDir );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lastModified );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strTemporaryFullPath);
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
/*[in]*/ const SetupImageEntry& val )
{
__HCP_FUNC_ENTRY( "operator<< SetupImageEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strSKU );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strLocalization );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strPurpose );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strSourceFile );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strTemporaryName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strDestinationName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strDestinationDir );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lastModified );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strTemporaryFullPath);
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT SetupImageEntry::Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
{
__HCP_FUNC_ENTRY( "SetupImageEntry::Import" );
HRESULT hr;
DATE dFileSrc;
DATE dFileDst;
m_strTemporaryFullPath = strRoot;
m_strTemporaryFullPath += m_strLocalization;
m_strTemporaryFullPath += L"\\";
m_strTemporaryFullPath += m_strTemporaryName;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( m_strTemporaryFullPath ));
dFileSrc = MPC::GetLastModifiedDate( m_strSourceFile );
dFileDst = MPC::GetLastModifiedDate( m_strTemporaryFullPath );
if(dFileSrc == 0) __MPC_SET_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
if(dFileSrc > dFileDst)
{
l_FileLog.LogRecord( L"Copying file '%s' to '%s'", m_strSourceFile.c_str(), m_strTemporaryFullPath.c_str() );
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CopyFile( m_strSourceFile, m_strTemporaryFullPath ));
m_lastModified = MPC::GetLastModifiedDate( m_strTemporaryFullPath );
m_fUpdated = true;
}
else
{
m_lastModified = dFileDst;
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT SetupImageEntry::Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
{
return S_OK;
}
void SetupImageEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
{
FixString( m_strTemporaryFullPath, strRootOld, strRoot );
}
////////////////////////////////////////
HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
/*[out]*/ FileEntry& val )
{
__HCP_FUNC_ENTRY( "operator>> FileEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strFullPath );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lastModified_HIGH);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lastModified_LOW );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lChunks );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
/*[in]*/ const FileEntry& val )
{
__HCP_FUNC_ENTRY( "operator<< FileEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strFullPath );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lastModified_HIGH);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lastModified_LOW );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lChunks );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
void FileEntry::GenerateChunkName( /*[in]*/ long lChunk ,
/*[out]*/ MPC::wstring& strFile ) const
{
WCHAR rgTmp[64]; _snwprintf( rgTmp, MAXSTRLEN(rgTmp), L"_%ld", lChunk );
strFile = m_strFullPath;
strFile.append( rgTmp );
}
void FileEntry::GetDate( /*[out]*/ DATE& dHIGH ,
/*[out]*/ DATE& dLOW ) const
{
if(m_lChunks == 0)
{
dHIGH = dLOW = MPC::GetLastModifiedDate( m_strFullPath );
}
else
{
MPC::wstring strFile;
DATE date;
bool fNotExist = false;
dHIGH = 0;
dLOW = 0;
for(long l = 0; l<m_lChunks; l++)
{
GenerateChunkName( l, strFile );
date = MPC::GetLastModifiedDate( strFile );
if(date)
{
if(!dHIGH || dHIGH < date) dHIGH = date;
if(!dLOW || dLOW > date) dLOW = date;
}
else
{
fNotExist = true;
}
}
if(fNotExist) dLOW = 0; // In case one chunk doesn't exist, dLOW should reflect that.
}
}
void FileEntry::SetDate( /*[in]*/ bool fLookForChunks )
{
if(fLookForChunks && m_lChunks == 0)
{
MPC::wstring strFile;
while(1)
{
GenerateChunkName( m_lChunks, strFile );
if(!MPC::FileSystemObject::IsFile( strFile.c_str() )) break;
m_lChunks++;
}
}
GetDate( m_lastModified_HIGH, m_lastModified_LOW );
}
bool FileEntry::WasModified() const
{
DATE dHIGH;
DATE dLOW;
GetDate( dHIGH, dLOW );
return (dHIGH == 0 || dHIGH > m_lastModified_HIGH);
}
void FileEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
{
FixString( m_strFullPath, strRootOld, strRoot );
}
bool FileEntry::IsNewer( /*[in]*/ const FileEntry& fe )
{
return IsNewer( fe.m_lastModified_LOW );
}
bool FileEntry::IsNewer( /*[in]*/ DATE date )
{
return (m_lastModified_HIGH > date);
}
////////////////////////////////////////
HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
/*[out]*/ TaxonomyEntry& val )
{
__HCP_FUNC_ENTRY( "operator>> TaxonomyEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fe );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feMANUAL);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feSYNSET);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feLOC );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feNOLOC );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
/*[in]*/ const TaxonomyEntry& val )
{
__HCP_FUNC_ENTRY( "operator<< TaxonomyEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fe );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feMANUAL);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feSYNSET);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feLOC );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feNOLOC );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT TaxonomyEntry::Import( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
{
__HCP_FUNC_ENTRY( "TaxonomyEntry::Import" );
HRESULT hr;
m_feMANUAL.m_strFullPath = m_fe.m_strFullPath; m_feMANUAL.m_strFullPath += L"_MANUAL"; m_feMANUAL.SetDate( );
m_feSYNSET.m_strFullPath = m_fe.m_strFullPath; m_feSYNSET.m_strFullPath += L"_SYNSET"; m_feSYNSET.SetDate( );
m_feLOC .m_strFullPath = m_fe.m_strFullPath; m_feLOC .m_strFullPath += L"_LOC"; m_feLOC .SetDate( /*fLookForChunks*/true );
m_feNOLOC .m_strFullPath = m_fe.m_strFullPath; m_feNOLOC .m_strFullPath += L"_NOLOC"; m_feNOLOC .SetDate( );
if(m_fe.IsNewer( m_feMANUAL ) ||
m_fe.IsNewer( m_feSYNSET ) ||
m_fe.IsNewer( m_feLOC ) ||
m_fe.IsNewer( m_feNOLOC ) )
{
MPC::XmlUtil xml;
bool fLoaded;
bool fFound;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( m_fe.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
if(fLoaded == false ||
fFound == false )
{
l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_fe.m_strFullPath.c_str() );
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
if(m_fe.IsNewer( m_feMANUAL ))
{
MPC::XmlUtil xmlMANUAL;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : MANUAL part", m_fe.m_strFullPath.c_str() );
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlMANUAL.New( c_szHHT_rootTag, L"UTF-16" ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlMANUAL, c_szHHT_manual_STOPSIGN ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlMANUAL, c_szHHT_manual_STOPWORD ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlMANUAL, c_szHHT_manual_OPERATOR ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlMANUAL.Save( m_feMANUAL.m_strFullPath.c_str() ));
m_feMANUAL.SetDate();
m_feMANUAL.m_fUpdated = true;
}
if(m_fe.IsNewer( m_feSYNSET ))
{
MPC::XmlUtil xmlSYNSET;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : SYNSET part", m_fe.m_strFullPath.c_str() );
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlSYNSET.New( c_szHHT_rootTag, L"UTF-16" ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlSYNSET, c_szHHT_synset_SYNTABLE ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlSYNSET.Save( m_feSYNSET.m_strFullPath.c_str() ));
m_feSYNSET.SetDate();
m_feSYNSET.m_fUpdated = true;
}
if(m_fe.IsNewer( m_feLOC ))
{
MPC::XmlUtil xmlLOC;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : LOC part", m_fe.m_strFullPath.c_str() );
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlLOC.New( c_szHHT_rootTag, L"UTF-16" ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlLOC, c_szHHT_loc_SCOPE ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlLOC, c_szHHT_loc_TAXONOMY ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertAttributesToElements( xmlLOC, c_szHHT_conv_SCOPE , c_rgHHT_conv_SCOPE , ARRAYSIZE(c_rgHHT_conv_SCOPE ) ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertAttributesToElements( xmlLOC, c_szHHT_conv_TAXONOMY, c_rgHHT_conv_TAXONOMY, ARRAYSIZE(c_rgHHT_conv_TAXONOMY) ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, SpreadToFiles( xmlLOC, m_feLOC, l_lMaxElements ));
m_feLOC.SetDate();
m_feLOC.m_fUpdated = true;
}
if(m_fe.IsNewer( m_feNOLOC ))
{
MPC::XmlUtil xmlNOLOC;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : NOLOC part", m_fe.m_strFullPath.c_str() );
__MPC_EXIT_IF_METHOD_FAILS(hr, xmlNOLOC.New( c_szHHT_rootTag ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlNOLOC, c_szHHT_noloc_FTS ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlNOLOC, c_szHHT_noloc_INDEX ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlNOLOC, c_szHHT_noloc_HELPIMAGE ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlNOLOC.Save( m_feNOLOC.m_strFullPath.c_str() ));
m_feNOLOC.SetDate();
m_feNOLOC.m_fUpdated = true;
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT TaxonomyEntry::Export( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
{
__HCP_FUNC_ENTRY( "TaxonomyEntry::Export" );
HRESULT hr;
m_fe_New.m_strFullPath = m_fe.m_strFullPath; m_fe_New.m_strFullPath += L"_GEN";
m_feMANUAL.SetDate();
m_feSYNSET.SetDate();
m_feLOC .SetDate();
m_feNOLOC .SetDate();
m_fe_New .SetDate();
if(m_feMANUAL.IsNewer( m_fe_New ) ||
m_feSYNSET.IsNewer( m_fe_New ) ||
m_feLOC .IsNewer( m_fe_New ) ||
m_feNOLOC .IsNewer( m_fe_New ) )
{
MPC::XmlUtil xml;
bool fLoaded;
bool fFound;
l_FileLog.LogRecord( L"Processing HHT '%s'", m_fe_New.m_strFullPath.c_str() );
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.New( c_szHHT_rootTag, L"UTF-16" ));
{
MPC::XmlUtil xmlMANUAL;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : MANUAL part", m_fe_New.m_strFullPath.c_str() );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlMANUAL.Load( m_feMANUAL.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
if(fLoaded == false ||
fFound == false )
{
l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_feMANUAL.m_strFullPath.c_str() );
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlMANUAL, xml, c_szHHT_manual_STOPSIGN ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlMANUAL, xml, c_szHHT_manual_STOPWORD ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlMANUAL, xml, c_szHHT_manual_OPERATOR ));
}
{
MPC::XmlUtil xmlSYNSET;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : SYNSET part", m_fe_New.m_strFullPath.c_str() );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlSYNSET.Load( m_feSYNSET.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
if(fLoaded == false ||
fFound == false )
{
l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_feSYNSET.m_strFullPath.c_str() );
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlSYNSET, xml, c_szHHT_synset_SYNTABLE ));
}
{
MPC::XmlUtil xmlLOC;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : LOC part", m_fe_New.m_strFullPath.c_str() );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, CollateFromFiles( xmlLOC, c_szHHT_rootTag, m_feLOC ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertElementsToAttributes( xmlLOC, c_szHHT_conv_SCOPE , c_rgHHT_conv_SCOPE , ARRAYSIZE(c_rgHHT_conv_SCOPE ) ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertElementsToAttributes( xmlLOC, c_szHHT_conv_TAXONOMY, c_rgHHT_conv_TAXONOMY, ARRAYSIZE(c_rgHHT_conv_TAXONOMY) ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlLOC, xml, c_szHHT_loc_SCOPE ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlLOC, xml, c_szHHT_loc_TAXONOMY ));
}
{
MPC::XmlUtil xmlNOLOC;
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
l_FileLog.LogRecord( L"Processing HHT '%s' : NOLOC part", m_fe_New.m_strFullPath.c_str() );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlNOLOC.Load( m_feNOLOC.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
if(fLoaded == false ||
fFound == false )
{
l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_feNOLOC.m_strFullPath.c_str() );
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlNOLOC, xml, c_szHHT_noloc_FTS ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlNOLOC, xml, c_szHHT_noloc_INDEX ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlNOLOC, xml, c_szHHT_noloc_HELPIMAGE ));
}
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xml.Save( m_fe_New.m_strFullPath.c_str() ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
void TaxonomyEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
{
m_fe .FixRoot( strRootOld, strRoot );
m_feMANUAL.FixRoot( strRootOld, strRoot );
m_feSYNSET.FixRoot( strRootOld, strRoot );
m_feLOC .FixRoot( strRootOld, strRoot );
m_feNOLOC .FixRoot( strRootOld, strRoot );
m_fe_New .FixRoot( strRootOld, strRoot );
}
////////////////////////////////////////
HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
/*[out]*/ PackageEntry& val )
{
__HCP_FUNC_ENTRY( "operator>> PackageEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strDir );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strPackageDescription);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_flSAF );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_flINSTALL );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_flHHT );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_DB_strSKU );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_DB_lLCID );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_DB_strDisplayName );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
/*[in]*/ const PackageEntry& val )
{
__HCP_FUNC_ENTRY( "operator<< PackageEntry" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strDir );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strPackageDescription);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_flSAF );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_flINSTALL );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_flHHT );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_DB_strSKU );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_DB_lLCID );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_DB_strDisplayName );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT PackageEntry::Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
{
__HCP_FUNC_ENTRY( "PackageEntry::Import" );
HRESULT hr;
MPC::Cabinet::List lst;
MPC::wstring strFile;
MPC::wstring strFile_Base;
LPCWSTR szSourceFile;
LPCWSTR szEnd;
DATE dFile_PackageDescription;
strFile = pbe.m_entry.m_strTemporaryFullPath;
//
// Create temp dir from the file name.
//
szSourceFile = strFile.c_str();
szEnd = wcsrchr( szSourceFile, '.' );
if(szEnd)
{
m_strDir.assign( szSourceFile, szEnd );
}
else
{
m_strDir = szSourceFile;
}
m_strDir += L"\\";
if(pbe.m_entry.m_fUpdated)
{
RemoveDirectory( m_strDir );
m_flSAF .clear();
m_flINSTALL.clear();
m_flHHT .clear();
}
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( m_strDir ));
//
// Analyze Package_Description.xml
//
{
MPC::XmlUtil xml;
bool fFound;
m_strPackageDescription = m_strDir;
m_strPackageDescription += c_szPackageDescription;
dFile_PackageDescription = MPC::GetLastModifiedDate( m_strPackageDescription );
if(dFile_PackageDescription == 0 || pbe.m_entry.m_lastModified > dFile_PackageDescription)
{
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ExtractFile( szSourceFile, m_strPackageDescription.c_str(), c_szPackageDescription ));
dFile_PackageDescription = MPC::GetLastModifiedDate( m_strPackageDescription );;
}
__MPC_EXIT_IF_METHOD_FAILS(hr, OpenPackageDescription( xml ));
//
// Parse the SAF section.
//
{
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
FileEntry fe;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( L"CONFIG/SAF/@FILE", &xdnl ));
for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, fe.m_strName, fFound, xdn ));
if(fFound)
{
fe.m_strFullPath = m_strDir;
fe.m_strFullPath += fe.m_strName;
m_flSAF.push_back( fe );
}
}
}
//
// Parse the INSTALL section.
//
{
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
FileEntry fe;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( L"INSTALL_CONTENT/FILE/@SOURCE", &xdnl ));
for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, fe.m_strName, fFound, xdn ));
if(fFound)
{
fe.m_strFullPath = m_strDir;
fe.m_strFullPath += fe.m_strName;
m_flINSTALL.push_back( fe );
}
}
}
//
// Parse the HHT section.
//
{
CComPtr<IXMLDOMNodeList> xdnl;
CComPtr<IXMLDOMNode> xdn;
TaxonomyEntry te;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( L"METADATA/HHT/@FILE", &xdnl ));
for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
{
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, te.m_fe.m_strName, fFound, xdn ));
if(fFound)
{
te.m_fe.m_strFullPath = m_strDir;
te.m_fe.m_strFullPath += te.m_fe.m_strName;
m_flHHT.push_back( te );
}
}
}
}
//
// Extract all the required files.
//
{
MPC::WStringUCSet setDecompress;
MPC::Cabinet cab;
FileIter it1;
FileIter it2;
TaxonomyIter it3;
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.put_CabinetFile( szSourceFile ));
for(it1=m_flSAF.begin(); it1!=m_flSAF.end(); it1++)
{
FileEntry& fe = *it1;
if(dFile_PackageDescription > MPC::GetLastModifiedDate( fe.m_strFullPath ))
{
if(setDecompress.find( fe.m_strName ) == setDecompress.end())
{
setDecompress.insert( fe.m_strName );
l_FileLog.LogRecord( L"Extracting '%s' from '%s'", fe.m_strName.c_str(), szSourceFile );
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
fe.m_fUpdated = true;
}
}
}
for(it2=m_flINSTALL.begin(); it2!=m_flINSTALL.end(); it2++)
{
FileEntry& fe = *it2;
if(dFile_PackageDescription > MPC::GetLastModifiedDate( fe.m_strFullPath ))
{
if(setDecompress.find( fe.m_strName ) == setDecompress.end())
{
setDecompress.insert( fe.m_strName );
l_FileLog.LogRecord( L"Extracting '%s' from '%s'", fe.m_strName.c_str(), szSourceFile );
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
fe.m_fUpdated = true;
}
}
}
for(it3=m_flHHT.begin(); it3!=m_flHHT.end(); it3++)
{
TaxonomyEntry& te = *it3;
if(dFile_PackageDescription > MPC::GetLastModifiedDate( te.m_fe.m_strFullPath ))
{
if(setDecompress.find( te.m_fe.m_strName ) == setDecompress.end())
{
setDecompress.insert( te.m_fe.m_strName );
l_FileLog.LogRecord( L"Extracting '%s' from '%s'", te.m_fe.m_strName.c_str(), szSourceFile );
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( te.m_fe.m_strFullPath.c_str(), te.m_fe.m_strName.c_str() ));
te.m_fe.m_fUpdated = true;
}
}
}
hr = cab.Decompress();
if(FAILED(hr))
{
MPC::Cabinet::List lst;
MPC::Cabinet::Iter it;
if(SUCCEEDED(cab.GetFiles( lst )))
{
for(it=lst.begin(); it != lst.end(); it++)
{
if(it->m_fFound == false)
{
l_FileLog.LogRecord( L"!!ERROR: Missing %s \n", it->m_szName.c_str() );
}
}
}
__MPC_FUNC_LEAVE;
}
for(it1=m_flSAF.begin(); it1!=m_flSAF.end(); it1++)
{
FileEntry& fe = *it1;
fe.SetDate();
}
for(it2=m_flINSTALL.begin(); it2!=m_flINSTALL.end(); it2++)
{
FileEntry& fe = *it2;
fe.SetDate();
}
for(it3=m_flHHT.begin(); it3!=m_flHHT.end(); it3++)
{
TaxonomyEntry& te = *it3;
te.m_fe.SetDate();
}
}
//
// Process the HHTs.
//
{
for(TaxonomyIter it=m_flHHT.begin(); it!=m_flHHT.end(); it++)
{
TaxonomyEntry& te = *it;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, te.Import( *this, pbe, strRoot ));
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT PackageEntry::Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
{
__HCP_FUNC_ENTRY( "PackageEntry::Export" );
HRESULT hr;
DATE dFile_Cabinet;
DATE dFile_PackageDescription;
m_strNew_Cabinet = pbe.m_entry.m_strTemporaryFullPath;
m_strNew_Cabinet += L"_GEN";
dFile_Cabinet = MPC::GetLastModifiedDate( m_strNew_Cabinet );
dFile_PackageDescription = MPC::GetLastModifiedDate( m_strPackageDescription );
//
// Process the HHTs.
//
{
for(TaxonomyIter it=m_flHHT.begin(); it!=m_flHHT.end(); it++)
{
TaxonomyEntry& te = *it;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, te.Export( *this, pbe, strRoot ));
}
}
//
// Compress all the required files.
//
{
MPC::Cabinet cab;
FileIter it1;
FileIter it2;
TaxonomyIter it3;
bool fNew = false;
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.put_CabinetFile( m_strNew_Cabinet.c_str() ));
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( m_strPackageDescription.c_str(), c_szPackageDescription ));
if(dFile_PackageDescription > dFile_Cabinet) fNew = true;
for(it1=m_flSAF.begin(); it1!=m_flSAF.end(); it1++)
{
FileEntry& fe = *it1;
fe.SetDate(); if(fe.IsNewer( dFile_Cabinet )) fNew = true;
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
}
for(it2=m_flINSTALL.begin(); it2!=m_flINSTALL.end(); it2++)
{
FileEntry& fe = *it2;
fe.SetDate(); if(fe.IsNewer( dFile_Cabinet )) fNew = true;
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
}
for(it3=m_flHHT.begin(); it3!=m_flHHT.end(); it3++)
{
TaxonomyEntry& te = *it3;
te.m_fe_New.SetDate(); if(te.m_fe_New.IsNewer( dFile_Cabinet )) fNew = true;
__MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( te.m_fe_New.m_strFullPath.c_str(), te.m_fe.m_strName.c_str() ));
}
if(fNew)
{
l_FileLog.LogRecord( L"Compressing '%s'", m_strNew_Cabinet.c_str() );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, cab.Compress());
}
}
if(pbe.m_pbt == POSTBUILDTYPE_HHT)
{
DATE dCabinet;
DATE dDatabase;
m_strNew_Database = pbe.m_entry.m_strTemporaryFullPath;
m_strNew_Database += L"_EDB";
{
MPC::XmlUtil xml;
__MPC_EXIT_IF_METHOD_FAILS(hr, OpenPackageDescription( xml ));
}
dCabinet = MPC::GetLastModifiedDate( m_strNew_Cabinet );
dDatabase = MPC::GetLastModifiedDate( m_strNew_Database );
if(dDatabase == 0.0 || dCabinet > dDatabase)
{
MPC::wstring strTmp;
GetRootDirectory( strTmp );
strTmp += L"\\EDB_";
strTmp += m_DB_strSKU;
strTmp += L"\\";
l_FileLog.LogRecord( L"Create database '%s'", m_strNew_Database.c_str() );
try
{
hr = CreateDatabase( strTmp );
}
catch(...)
{
hr = E_FAIL;
}
//
// Something JetBlue fails because of a bad checkpoint directory.
//
if(FAILED(hr))
{
try
{
RemoveDirectory( strTmp );
hr = CreateDatabase( strTmp );
}
catch(...)
{
hr = E_FAIL;
}
}
if(FAILED(hr))
{
(void)MPC::DeleteFile( m_strNew_Database );
}
RemoveDirectory( strTmp );
__MPC_EXIT_IF_METHOD_FAILS(hr, hr);
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////
HRESULT PackageEntry::OpenPackageDescription( /*[in/out]*/ MPC::XmlUtil& xml )
{
__HCP_FUNC_ENTRY( "PackageEntry::OpenPackageDescription" );
HRESULT hr;
MPC::wstring strLanguage;
bool fLoaded;
bool fFound;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( m_strPackageDescription.c_str(), L"HELPCENTERPACKAGE", fLoaded, &fFound ));
if(fLoaded == false ||
fFound == false )
{
l_FileLog.LogRecord( L"Not a valid Package_Description: '%s'", m_strPackageDescription.c_str() );
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetAttribute( L"SKU", L"VALUE" , m_DB_strSKU , fFound ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetAttribute( L"SKU", L"DISPLAYNAME", m_DB_strDisplayName, fFound ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetAttribute( L"LANGUAGE", L"VALUE" , strLanguage , fFound )); if(fFound) m_DB_lLCID = _wtol( strLanguage.c_str() );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT PackageEntry::ProcessHHTFile( /*[in]*/ LPCWSTR szHHTFile ,
/*[in]*/ JetBlue::SessionHandle* handle ,
/*[in]*/ JetBlue::Database* db )
{
__HCP_FUNC_ENTRY( "PackageEntry::ProcessHHTFile" );
HRESULT hr;
CComPtr<HCUpdate::Engine> obj;
MPC::wstring strDBLog; GetDBLogFile( strDBLog );
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, obj->PopulateDatabase( m_strNew_Cabinet.c_str(), szHHTFile, strDBLog.c_str(), m_DB_strSKU.c_str(), m_DB_lLCID, *handle, db ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT PackageEntry::CreateDatabase( /*[in]*/ const MPC::wstring& strTmp )
{
__HCP_FUNC_ENTRY( "PackageEntry::CreateDatabase" );
USES_CONVERSION;
HRESULT hr;
JetBlue::SessionPool pool;
JetBlue::SessionHandle handle;
JetBlue::Database* db;
long lMSFTid;
bool fPool = false;
bool fSession = false;
bool fDatabase = false;
// if(g_fVerbose) wprintf( L"Creating database %s\n", szDatabase );
//
// Remove any old database.
//
(void)MPC::DeleteFile( m_strNew_Database );
////////////////////////////////////////////////////////////////////////////////
//
// Create new database.
//
RemoveDirectory( strTmp );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pool.Init( strTmp.c_str() )); fPool = true;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pool.GetSession( handle )); fSession = true;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, handle->GetDatabase( W2A( m_strNew_Database.c_str() ), db, /*fReadOnly*/false, /*fCreate*/true, /*fRepair*/false )) fDatabase = true;
////////////////////////////////////////////////////////////////////////////////
//
// Load the schema in the database.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
{
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::CreateSchema( db ));
}
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
////////////////////////////////////////////////////////////////////////////////
{
Taxonomy::Settings ts( m_DB_strSKU.c_str(), m_DB_lLCID );
Taxonomy::Updater updater;
__MPC_EXIT_IF_METHOD_FAILS(hr, updater.Init( ts, db ));
//
// Generate content owner
//
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
{
__MPC_EXIT_IF_METHOD_FAILS(hr, updater.CreateOwner( lMSFTid, HC_MICROSOFT_DN, /*fIsOEM*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, updater.LocateOwner( HC_MICROSOFT_DN ));
}
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
//
// Create the root and non-mapped node in the topic table
//
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
{
Taxonomy::RS_Taxonomy* rs;
__MPC_EXIT_IF_METHOD_FAILS(hr, updater.GetTaxonomy( &rs ));
rs->m_ID_owner = lMSFTid;
rs->m_strEntry = L"<ROOT>";
__MPC_EXIT_IF_METHOD_FAILS(hr, rs->Insert());
}
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
//
// Create the system scope.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
{
Taxonomy::RS_Scope* rs;
__MPC_EXIT_IF_METHOD_FAILS(hr, updater.GetScope( &rs ));
rs->m_ID_owner = lMSFTid;
rs->m_strID = L"<SYSTEM>";
__MPC_EXIT_IF_METHOD_FAILS(hr, rs->Insert());
}
__MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, updater.Close());
}
////////////////////////////////////////////////////////////////////////////////
//
// Process the HHT file, after closing the updater.
//
{
for(TaxonomyIter it=m_flHHT.begin(); it!=m_flHHT.end(); it++)
{
TaxonomyEntry& te = *it;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ProcessHHTFile( te.m_fe_New.m_strFullPath.c_str(), &handle, db ));
}
}
////////////////////////////////////////////////////////////////////////////////
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(fDatabase) { ; }
if(fSession ) { handle.Release(); }
if(fPool ) { (void)pool.Close( true ); }
__HCP_FUNC_EXIT(hr);
}
void PackageEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
{
FileIter it1;
TaxonomyIter it2;
FixString( m_strDir , strRootOld, strRoot );
FixString( m_strPackageDescription, strRootOld, strRoot );
for(it1=m_flSAF .begin(); it1!=m_flSAF .end(); it1++) it1->FixRoot( strRootOld, strRoot );
for(it1=m_flINSTALL.begin(); it1!=m_flINSTALL.end(); it1++) it1->FixRoot( strRootOld, strRoot );
for(it2=m_flHHT .begin(); it2!=m_flHHT .end(); it2++) it2->FixRoot( strRootOld, strRoot );
FixString( m_strNew_Cabinet , strRootOld, strRoot );
FixString( m_strNew_Database, strRootOld, strRoot );
}
////////////////////////////////////////
HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
/*[out]*/ PostBuildEntry& val )
{
__HCP_FUNC_ENTRY( "operator>> PostBuildEntry" );
HRESULT hr;
long pbt;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> pbt ); val.m_pbt = (PostBuildType)pbt;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_entry );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_package);
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
/*[in]*/ const PostBuildEntry& val )
{
__HCP_FUNC_ENTRY( "operator<< PostBuildEntry" );
HRESULT hr;
long pbt = (long)val.m_pbt;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << pbt );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_entry );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_package);
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
void PostBuildEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
{
m_entry .FixRoot( strRootOld, strRoot );
m_package.FixRoot( strRootOld, strRoot );
}
////////////////////////////////////////
HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
/*[out]*/ SkuInformation& val )
{
__HCP_FUNC_ENTRY( "operator>> SkuInformation" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strCabinet );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strProdFilt);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fDesktop );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fServer );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fEmbedded );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
/*[in]*/ const SkuInformation& val )
{
__HCP_FUNC_ENTRY( "operator<< SkuInformation" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strName );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strCabinet );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strProdFilt);
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fDesktop );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fServer );
__MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fEmbedded );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
static void Usage()
{
wprintf( L"Usage: HssSetupTool <options> <command> <parameters>\n\n" );
wprintf( L"Available commands:\n\n" );
wprintf( L" BINPLACE <sku file> <setup image file> <root directory> <object directory>\n" );
wprintf( L" COMPILE <root directory> <sku>\n" );
wprintf( L" LIST <input cabinet>\n" );
wprintf( L" EXTRACT <input cabinet> <file>\n" );
wprintf( L" INSTALL <input cabinet>\n" );
wprintf( L"\n" );
wprintf( L" UNPACK <input cabinet> <directory>\n" );
wprintf( L" PACK <directory> <output cabinet>\n" );
}
#define CHECK_ARGS(argc,num) if(argc < num) { Usage(); __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); }
////////////////////////////////////////
static bool LookupBoolean( /*[in] */ LPCWSTR szString )
{
if(_wcsicmp( szString, L"TRUE" ) == 0 ||
_wcsicmp( szString, L"1" ) == 0 ||
_wcsicmp( szString, L"ON" ) == 0 )
{
return true;
}
return false;
}
static bool ParseFile( /*[in ]*/ LPSTR szLine ,
/*[out]*/ SetupImageEntry& en )
{
USES_CONVERSION;
HRESULT hr;
LPSTR szEnd;
std::vector<MPC::wstring> vec;
//
// Skip comments.
//
if(szLine[0] == '#') return false;
if((szEnd = strchr( szLine, '\r' ))) szEnd[0] = 0;
if((szEnd = strchr( szLine, '\n' ))) szEnd[0] = 0;
MPC::SplitAtDelimiter( vec, A2W( szLine ), L"," );
if(vec.size() != 7) return false;
en.m_strSKU = vec[0];
en.m_strLocalization = vec[1];
en.m_strPurpose = vec[2];
en.m_strSourceFile = vec[3];
en.m_strTemporaryName = vec[4];
en.m_strDestinationName = vec[5];
en.m_strDestinationDir = vec[6];
return true;
}
static bool ParseFile( /*[in ]*/ LPSTR szLine ,
/*[out]*/ SkuInformation& si )
{
USES_CONVERSION;
HRESULT hr;
LPSTR szEnd;
std::vector<MPC::wstring> vec;
//
// Skip comments.
//
if(szLine[0] == '#') return false;
if((szEnd = strchr( szLine, '\r' ))) szEnd[0] = 0;
if((szEnd = strchr( szLine, '\n' ))) szEnd[0] = 0;
MPC::SplitAtDelimiter( vec, A2W( szLine ), L" ", /*fDelimIsAString*/false, /*fSkipAdjacentDelims*/true );
if(vec.size() != 6) return false;
si.m_strName = vec[0];
si.m_strCabinet = vec[1];
si.m_strProdFilt = vec[2];
si.m_fDesktop = LookupBoolean( vec[3].c_str() );
si.m_fServer = LookupBoolean( vec[4].c_str() );
si.m_fEmbedded = LookupBoolean( vec[5].c_str() );
return true;
}
static bool GetSetupImageFile( /*[in ]*/ SkuInformationList& sil ,
/*[in ]*/ LPCWSTR szSKU ,
/*[out]*/ MPC::wstring& strCabinet ,
/*[out]*/ Taxonomy::InstanceBase& data )
{
if(!_wcsicmp( szSKU, L"NONE" ))
{
strCabinet = L"none.cab";
data.m_fDesktop = false;
data.m_fServer = false;
data.m_fEmbedded = false;
return true;
}
for(SkuInformationIter it=sil.begin(); it!=sil.end(); it++)
{
if(!_wcsicmp( szSKU, it->m_strName.c_str() ))
{
strCabinet = it->m_strCabinet;
data.m_fDesktop = it->m_fDesktop ;
data.m_fServer = it->m_fServer ;
data.m_fEmbedded = it->m_fEmbedded ;
return true;
}
}
return false;
}
static HRESULT OpenFile( /*[in ]*/ const MPC::wstring& strFile ,
/*[out]*/ FILE*& fh )
{
__HCP_FUNC_ENTRY( "OpenFile" );
HRESULT hr;
fh = _wfopen( strFile.c_str(), L"r" );
if(fh == NULL)
{
DWORD dwRes = ::GetLastError();
l_FileLog.LogRecord( L"%08x: Can't open file '%s'", HRESULT_FROM_WIN32(dwRes), strFile.c_str() );
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////
static HRESULT Index_SAVE( /*[in]*/ const MPC::wstring& strRoot ,
/*[in]*/ PostBuildList& pbl ,
/*[in]*/ SkuInformationList& sil )
{
__HCP_FUNC_ENTRY( "Index_SAVE" );
HRESULT hr;
MPC::wstring strFileOut;
HANDLE hFile = NULL;
strFileOut = strRoot;
strFileOut += c_szNTTREE_INDEX;
//
// Create the new file.
//
__MPC_EXIT_IF_INVALID_HANDLE__CLEAN(hr, hFile, ::CreateFileW( strFileOut.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ));
//
// Dump to file.
//
{
MPC::Serializer_File streamReal( hFile );
MPC::Serializer_Buffering streamBuf ( streamReal );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << c_dwVersion );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << strRoot );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << pbl );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << sil );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf.Flush());
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(hFile) ::CloseHandle( hFile );
__HCP_FUNC_EXIT(hr);
}
static HRESULT Index_LOAD( /*[in]*/ const MPC::wstring& strRoot ,
/*[in]*/ PostBuildList& pbl ,
/*[in]*/ SkuInformationList& sil )
{
__HCP_FUNC_ENTRY( "Index_LOAD" );
HRESULT hr;
MPC::wstring strFileOut;
HANDLE hFile = NULL;
strFileOut = strRoot;
strFileOut += c_szNTTREE_INDEX;
pbl.clear();
__MPC_EXIT_IF_INVALID_HANDLE__CLEAN(hr, hFile, ::CreateFileW( strFileOut.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ));
{
MPC::Serializer_File streamReal( hFile );
MPC::Serializer_Buffering streamBuf ( streamReal );
MPC::wstring strRootOld;
DWORD dwVer;
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> dwVer ); if(dwVer != c_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> strRootOld );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> pbl );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> sil );
if(strRootOld != strRoot)
{
for(PostBuildIter it=pbl.begin(); it!=pbl.end(); it++)
{
it->FixRoot( strRootOld, strRoot );
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(hFile) ::CloseHandle( hFile );
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////
static HRESULT Binplace( /*[in]*/ LPCWSTR szSKUList ,
/*[in]*/ LPCWSTR szFileList ,
/*[in]*/ LPCWSTR szRoot ,
/*[in]*/ LPCWSTR szObject )
{
__HCP_FUNC_ENTRY( "Binplace" );
HRESULT hr;
FILE* in = NULL;
char buf[1024];
MPC::wstring strFileList;
MPC::wstring strRoot;
PostBuildList pbl;
SkuInformationList sil;
strFileList = szFileList;
MPC::SubstituteEnvVariables( strFileList );
strRoot = szRoot;
strRoot += L"\\";
strRoot += c_szNTTREE_BASE;
strRoot += L"\\";
MPC::SubstituteEnvVariables( strRoot );
l_FileLog.LogRecord( L"\n==================\n"
L"BINPLACE - start\n\n" );
////////////////////////////////////////
::SetEnvironmentVariableW( L"OBJECTDIR", szObject );
{
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, OpenFile( szSKUList, in ));
while(fgets( buf, 1024, in ))
{
SkuInformation si;
if(ParseFile( buf, si ))
{
sil.push_back( si );
l_FileLog.LogRecord( L"Found SKU: %-30s %-15s %-15s %s%s%s" ,
si.m_strName .c_str() ,
si.m_strCabinet .c_str() ,
si.m_strProdFilt.c_str() ,
si.m_fDesktop ? L"DESKTOP " : L"" ,
si.m_fServer ? L"SERVER " : L"" ,
si.m_fEmbedded ? L"EMBEDDED " : L"" );
}
}
fclose( in ); in = NULL;
l_FileLog.LogRecord( L"\n" );
}
{
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( strRoot.c_str() ));
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, OpenFile( strFileList, in ));
while(fgets( buf, 1024, in ))
{
SetupImageEntry en;
if(ParseFile( buf, en ))
{
PostBuildEntry& pbe = *( pbl.insert( pbl.end() ) );
MPC::SubstituteEnvVariables( en.m_strSourceFile );
pbe.m_entry = en;
//
// This copies the file if newer.
//
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_entry.Import( pbe, strRoot ));
if(!MPC::StrICmp( en.m_strLocalization, L"HHT" ))
{
//
// Expand the cabinet and process the HHTs.
//
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_package.Import( pbe, strRoot ));
pbe.m_pbt = POSTBUILDTYPE_HHT;
}
else if(!MPC::StrICmp( en.m_strLocalization, L"SAF" ))
{
//
// Expand the cabinet and process the channel.
//
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_package.Import( pbe, strRoot ));
pbe.m_pbt = POSTBUILDTYPE_SAF;
}
else
{
pbe.m_pbt = POSTBUILDTYPE_NORMAL;
}
}
}
fclose( in ); in = NULL;
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, Index_SAVE( strRoot, pbl, sil ));
}
////////////////////////////////////////
hr = S_OK;
__HCP_FUNC_CLEANUP;
l_FileLog.LogRecord( L"\nBINPLACE - done\n"
L"=================\n\n" );
if(in) fclose( in );
__HCP_FUNC_EXIT(hr);
}
static HRESULT Compile( /*[in]*/ LPCWSTR szRoot ,
/*[in]*/ LPCWSTR szSKU )
{
__HCP_FUNC_ENTRY( "Compile" );
HRESULT hr;
Installer::Package pkg;
Taxonomy::InstanceBase& data = pkg.GetData();
MPC::wstring strRoot;
MPC::wstring strCabinet;
MPC::wstring strFullPath;
PostBuildList pbl;
SkuInformationList sil;
DATE dFile_SetupImage;
bool fNew = false;
l_FileLog.LogRecord( L"\n==================\n"
L"COMPILE - start\n\n" );
////////////////////////////////////////
strRoot = szRoot;
strRoot += L"\\";
strRoot += c_szNTTREE_BASE;
strRoot += L"\\";
MPC::SubstituteEnvVariables( strRoot );
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, Index_LOAD( strRoot, pbl, sil ));
if(GetSetupImageFile( sil, szSKU, strCabinet, data ) == false)
{
l_FileLog.LogRecord( L"'%s' is not a valid SKU name!\n\n", szSKU );
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
strFullPath = szRoot;
strFullPath += L"\\";
strFullPath += c_szNTTREE_BASE;
strFullPath += L"\\";
strFullPath += strCabinet;
MPC::SubstituteEnvVariables( strFullPath );
dFile_SetupImage = MPC::GetLastModifiedDate( strFullPath );
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( strFullPath.c_str() ));
for(PostBuildIter itPB=pbl.begin(); itPB!=pbl.end(); itPB++)
{
PostBuildEntry& pbe = *itPB;
if(MPC::StrICmp( pbe.m_entry.m_strSKU, L"All" ) == 0 ||
MPC::StrICmp( pbe.m_entry.m_strSKU, szSKU ) == 0 )
{
Installer::Iter itFile = pkg.NewFile();
MPC::wstring strFileSrc = pbe.m_entry.m_strTemporaryFullPath;
MPC::wstring strFileDst = pbe.m_entry.m_strDestinationDir; strFileDst += L"\\"; strFileDst += pbe.m_entry.m_strDestinationName;
__MPC_EXIT_IF_METHOD_FAILS(hr, itFile->SetPurpose( pbe.m_entry.m_strPurpose.c_str() ));
itFile->m_strFileLocal = strFileSrc;
itFile->m_strFileInner = pbe.m_entry.m_strTemporaryName;
itFile->m_strFileLocation = strFileDst;
if(pbe.m_pbt == POSTBUILDTYPE_HHT ||
pbe.m_pbt == POSTBUILDTYPE_SAF )
{
LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_package.Export( pbe, strRoot ));
itFile->m_strFileLocal = (pbe.m_pbt == POSTBUILDTYPE_SAF) ? pbe.m_package.m_strNew_Cabinet : pbe.m_package.m_strNew_Database;
}
if(pbe.m_pbt == POSTBUILDTYPE_HHT)
{
data.m_ths.m_strSKU = pbe.m_package.m_DB_strSKU;
data.m_ths.m_lLCID = pbe.m_package.m_DB_lLCID;
data.m_strDisplayName = pbe.m_package.m_DB_strDisplayName;
data.m_strProductID = L"Windows_XP";
data.m_strVersion = L"1.0.0.0";
}
if(FAILED(hr = itFile->UpdateSignature()))
{
l_FileLog.LogRecord( L"%08x: Can't locate '%s'\n", hr, strFileSrc.c_str() );
__HCP_FUNC_LEAVE;
}
if(MPC::GetLastModifiedDate( itFile->m_strFileLocal ) > dFile_SetupImage) fNew = true;
}
}
if(fNew)
{
l_FileLog.LogRecord( L"Create setup image '%s'", strFullPath.c_str() );
//
// Create the output cabinet.
//
if(FAILED(hr = pkg.Save()))
{
l_FileLog.LogRecord( L"%08x: Can't create output file '%s'\n", strFullPath.c_str() );
__HCP_FUNC_LEAVE;
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
l_FileLog.LogRecord( L"\nCOMPILE - done\n"
L"=================\n\n" );
__HCP_FUNC_EXIT(hr);
}
static HRESULT List( /*[in]*/ LPCWSTR szInput )
{
__HCP_FUNC_ENTRY( "List" );
HRESULT hr;
Installer::Package pkg;
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load());
{
Installer::Iter itBegin = pkg.GetBegin();
Installer::Iter itEnd = pkg.GetEnd ();
for(;itBegin != itEnd; itBegin++)
{
wprintf( L"%s -> %s\n", itBegin->m_strFileInner.c_str(), itBegin->m_strFileLocation.c_str() );
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static HRESULT Extract( /*[in]*/ LPCWSTR szInput ,
/*[in]*/ LPCWSTR szFile )
{
__HCP_FUNC_ENTRY( "Extract" );
HRESULT hr;
Installer::Package pkg;
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load());
{
Installer::Iter itBegin = pkg.GetBegin();
Installer::Iter itEnd = pkg.GetEnd ();
for(;itBegin != itEnd; itBegin++)
{
if(!MPC::StrICmp( itBegin->m_strFileInner, szFile ))
{
itBegin->m_strFileLocal = szFile; // Extract the file in the current directory.
__MPC_EXIT_IF_METHOD_FAILS(hr, itBegin->Extract( szInput ));
break;
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static HRESULT Install( /*[in]*/ LPCWSTR szInput )
{
__HCP_FUNC_ENTRY( "Install" );
HRESULT hr;
Installer::Package pkg;
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Install());
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
static HRESULT Unpack( /*[in]*/ LPCWSTR szInput ,
/*[in]*/ LPCWSTR szDir )
{
__HCP_FUNC_ENTRY( "Unpack" );
HRESULT hr;
Installer::Package pkg;
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Unpack( szDir ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
static HRESULT Pack( /*[in]*/ LPCWSTR szDir ,
/*[in]*/ LPCWSTR szOutput )
{
__HCP_FUNC_ENTRY( "Pack" );
HRESULT hr;
Installer::Package pkg;
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szOutput ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Pack( szDir ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
static HRESULT ProcessArguments( int argc ,
LPCWSTR argv[] )
{
__HCP_FUNC_ENTRY( "ProcessArguments" );
HRESULT hr;
argv++;
argc--;
while(argc-->0)
{
LPCWSTR szArg = *argv++;
int adv = -1;
if(szArg[0] == '-' ||
szArg[0] == '/' )
{
szArg++;
if(argc >= 1)
{
LPCWSTR szArg2 = argv[0];
if(!_wcsicmp( szArg, L"ROOT" )) { l_szRoot = szArg2 ; adv = 1; }
if(!_wcsicmp( szArg, L"LOG" )) { l_szLog = szArg2 ; adv = 1; }
if(!_wcsicmp( szArg, L"DBLOG" )) { l_szDBLog = szArg2 ; adv = 1; }
if(!_wcsicmp( szArg, L"MAXELEMENTS" )) { l_lMaxElements = _wtol( szArg2 ); adv = 1; }
}
}
else
{
{
MPC::wstring strLog;
GetLogFile( strLog );
l_FileLog.SetLocation( strLog.c_str() );
}
if(!_wcsicmp( szArg, L"BINPLACE" ) && argc >= 4) // <sku file> <setup image file> <root directory> <object directory>
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Binplace( argv[0], argv[1], argv[2], argv[3] )); adv = 4;
}
else if(!_wcsicmp( szArg, L"COMPILE" ) && argc >= 2) // <root directory> <sku>
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Compile( argv[0], argv[1] )); adv = 2;
}
else if(!_wcsicmp( szArg, L"LIST" ) && argc >= 1) // <input cabinet>
{
__MPC_EXIT_IF_METHOD_FAILS(hr, List( argv[0] )); adv = 2;
}
else if(!_wcsicmp( szArg, L"EXTRACT" ) && argc >= 2) // <input cabinet> <file>
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Extract( argv[0], argv[1] )); adv = 2;
}
else if(!_wcsicmp( szArg, L"INSTALL" ) && argc >= 1) // <input cabinet>
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Install( argv[0] )); adv = 1;
}
else if(!_wcsicmp( szArg, L"UNPACK" ) && argc >= 2) // <input cabinet> <directory>
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Unpack( argv[0], argv[1] )); adv = 2;
}
else if(!_wcsicmp( szArg, L"PACK" ) && argc >= 2) // <directory> <output cabinet>
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Pack( argv[0], argv[1] )); adv = 2;
}
}
if(adv == -1)
{
Usage(); __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
argv += adv;
argc -= adv;
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
int __cdecl wmain( int argc ,
LPCWSTR argv[] )
{
HRESULT hr;
//DebugBreak();
//
// We need to be a single-threaded application, because we are hosting script engines and
// script engines don't like to be called from different threads...
//
if(SUCCEEDED(hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED )))
{
if(SUCCEEDED(hr = ::CoInitializeSecurity( NULL ,
-1 , // We don't care which authentication service we use.
NULL ,
NULL ,
RPC_C_AUTHN_LEVEL_CONNECT, // We want to identify the callers.
RPC_C_IMP_LEVEL_DELEGATE , // We want to be able to forward the caller's identity.
NULL ,
EOAC_DYNAMIC_CLOAKING , // Let's use the thread token for outbound calls.
NULL )))
{
__MPC_TRACE_INIT();
//
// Process arguments.
//
try
{
hr = ProcessArguments( argc, argv );
}
catch(...)
{
hr = E_FAIL;
}
__MPC_TRACE_TERM();
}
::CoUninitialize();
}
return FAILED(hr) ? 10 : 0;
}