/****************************************************************************** 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 #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 xdnl; CComPtr xdn; CComPtr 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 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 xdnl; CComPtr 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 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 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 xdnl; CComPtr 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 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 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 xdnRootSrc; CComPtr xdnRootDst; CComPtr xdnSrc; CComPtr xdnDst; CComPtr xdnl; CComPtr 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 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 xdnRootSrc; CComPtr xdnRootDst; CComPtr xdnSrc; CComPtr xdnDst; CComPtr xdnl; CComPtr 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 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 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 xdnl; CComPtr 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 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""; __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""; __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 \n\n" ); wprintf( L"Available commands:\n\n" ); wprintf( L" BINPLACE \n" ); wprintf( L" COMPILE \n" ); wprintf( L" LIST \n" ); wprintf( L" EXTRACT \n" ); wprintf( L" INSTALL \n" ); wprintf( L"\n" ); wprintf( L" UNPACK \n" ); wprintf( L" PACK \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 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 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) // { __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) // { __MPC_EXIT_IF_METHOD_FAILS(hr, Compile( argv[0], argv[1] )); adv = 2; } else if(!_wcsicmp( szArg, L"LIST" ) && argc >= 1) // { __MPC_EXIT_IF_METHOD_FAILS(hr, List( argv[0] )); adv = 2; } else if(!_wcsicmp( szArg, L"EXTRACT" ) && argc >= 2) // { __MPC_EXIT_IF_METHOD_FAILS(hr, Extract( argv[0], argv[1] )); adv = 2; } else if(!_wcsicmp( szArg, L"INSTALL" ) && argc >= 1) // { __MPC_EXIT_IF_METHOD_FAILS(hr, Install( argv[0] )); adv = 1; } else if(!_wcsicmp( szArg, L"UNPACK" ) && argc >= 2) // { __MPC_EXIT_IF_METHOD_FAILS(hr, Unpack( argv[0], argv[1] )); adv = 2; } else if(!_wcsicmp( szArg, L"PACK" ) && argc >= 2) // { __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; }