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
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;
|
|
}
|