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

2687 lines
83 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. main.cpp
  5. Abstract:
  6. This file contains the Unit Test for Cabinet functions.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 09/03/99
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. #include <initguid.h>
  13. #include "msscript.h"
  14. #include "HelpServiceTypeLib.h"
  15. #include "HelpServiceTypeLib_i.c"
  16. #include "HelpCenterTypeLib.h"
  17. #include "HelpCenterTypeLib_i.c"
  18. ////////////////////////////////////////////////////////////////////////////////
  19. #define LOG__MPC_EXIT_IF_METHOD_FAILS(hr, cmd) \
  20. { \
  21. if(FAILED(hr=cmd)) \
  22. { \
  23. l_FileLog.LogRecord( "!!ERROR: %08x %s %d\n", hr, #cmd, __LINE__ ); \
  24. __MPC_TRACE_HRESULT(hr); __MPC_FUNC_LEAVE; \
  25. } \
  26. }
  27. ////////////////////////////////////////////////////////////////////////////////
  28. static const DWORD c_dwVersion = 0x07494250; // PBI 07
  29. static const WCHAR c_szNTTREE_BASE [] = L"HelpAndSupportServices";
  30. static const WCHAR c_szNTTREE_INDEX [] = L"index.dat";
  31. static const WCHAR c_szNTTREE_TMP [] = L"%TEMP%";
  32. static const WCHAR c_szPackageDescription [] = L"package_description.xml";
  33. static const WCHAR c_szHHT_rootTag [] = L"METADATA";
  34. static const WCHAR c_szHHT_manual_STOPSIGN [] = L"STOPSIGN_ENTRIES";
  35. static const WCHAR c_szHHT_manual_STOPWORD [] = L"STOPWORD_ENTRIES";
  36. static const WCHAR c_szHHT_manual_OPERATOR [] = L"OPERATOR_ENTRIES";
  37. static const WCHAR c_szHHT_synset_SYNTABLE [] = L"SYNTABLE";
  38. static const WCHAR c_szHHT_loc_SCOPE [] = L"SCOPE_DEFINITION";
  39. static const WCHAR c_szHHT_loc_TAXONOMY [] = L"TAXONOMY_ENTRIES";
  40. static const WCHAR c_szHHT_noloc_FTS [] = L"FTS";
  41. static const WCHAR c_szHHT_noloc_INDEX [] = L"INDEX";
  42. static const WCHAR c_szHHT_noloc_HELPIMAGE [] = L"HELPIMAGE";
  43. static const WCHAR c_szHHT_conv_SCOPE [] = L"SCOPE_DEFINITION/SCOPE";
  44. static LPCWSTR const c_rgHHT_conv_SCOPE [] = { L"DISPLAYNAME" };
  45. static const WCHAR c_szHHT_conv_TAXONOMY [] = L"TAXONOMY_ENTRIES/TAXONOMY_ENTRY";
  46. static LPCWSTR const c_rgHHT_conv_TAXONOMY [] = { L"TITLE", L"DESCRIPTION" };
  47. ////////////////////////////////////////
  48. static MPC::FileLog l_FileLog;
  49. static LPCWSTR l_szRoot = NULL;
  50. static LPCWSTR l_szLog = NULL;
  51. static LPCWSTR l_szDBLog = NULL;
  52. static int l_lMaxElements = 1000;
  53. ////////////////////////////////////////////////////////////////////////////////
  54. ////////////////////////////////////////////////////////////////////////////////
  55. struct SetupImageEntry;
  56. struct FileEntry;
  57. struct TaxonomyEntry;
  58. struct PackageEntry;
  59. struct PostBuildEntry;
  60. ////////////////////////////////////////////////////////////////////////////////
  61. struct SetupImageEntry
  62. {
  63. MPC::wstring m_strSKU;
  64. MPC::wstring m_strLocalization;
  65. MPC::wstring m_strPurpose;
  66. MPC::wstring m_strSourceFile;
  67. MPC::wstring m_strTemporaryName;
  68. MPC::wstring m_strDestinationName;
  69. MPC::wstring m_strDestinationDir;
  70. MPC::wstring m_strTemporaryFullPath;
  71. DATE m_lastModified;
  72. bool m_fUpdated;
  73. SetupImageEntry()
  74. {
  75. m_lastModified = 0;
  76. m_fUpdated = false;
  77. }
  78. friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ SetupImageEntry& val );
  79. friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const SetupImageEntry& val );
  80. HRESULT Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
  81. HRESULT Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
  82. void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
  83. };
  84. ////////////////////////////////////////////////////////////////////////////////
  85. struct FileEntry
  86. {
  87. MPC::wstring m_strName;
  88. MPC::wstring m_strFullPath;
  89. DATE m_lastModified_HIGH;
  90. DATE m_lastModified_LOW;
  91. long m_lChunks;
  92. bool m_fUpdated;
  93. FileEntry()
  94. {
  95. m_lastModified_HIGH = 0;
  96. m_lastModified_LOW = 0;
  97. m_lChunks = 0;
  98. m_fUpdated = false;
  99. }
  100. friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ FileEntry& val );
  101. friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const FileEntry& val );
  102. void GenerateChunkName( /*[in]*/ long lChunk, /*[out]*/ MPC::wstring& strFile ) const;
  103. void GetDate( /*[out]*/ DATE& date_HIGH, /*[out]*/ DATE& date_LOW ) const;
  104. void SetDate ( /*[in]*/ bool fLookForChunks = false );
  105. bool WasModified() const;
  106. void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
  107. bool IsNewer( /*[in]*/ const FileEntry& fe );
  108. bool IsNewer( /*[in]*/ DATE date );
  109. };
  110. typedef std::list< FileEntry > FileList;
  111. typedef FileList::iterator FileIter;
  112. typedef FileList::const_iterator FileIterConst;
  113. ////////////////////////////////////////////////////////////////////////////////
  114. struct TaxonomyEntry
  115. {
  116. FileEntry m_fe;
  117. FileEntry m_feMANUAL;
  118. FileEntry m_feSYNSET;
  119. FileEntry m_feLOC;
  120. FileEntry m_feNOLOC;
  121. bool m_fUpdated;
  122. FileEntry m_fe_New;
  123. TaxonomyEntry()
  124. {
  125. m_fUpdated = false;
  126. }
  127. friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ TaxonomyEntry& val );
  128. friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const TaxonomyEntry& val );
  129. HRESULT Import( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
  130. HRESULT Export( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
  131. void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
  132. };
  133. typedef std::list< TaxonomyEntry > TaxonomyList;
  134. typedef TaxonomyList::iterator TaxonomyIter;
  135. typedef TaxonomyList::const_iterator TaxonomyIterConst;
  136. ////////////////////////////////////////////////////////////////////////////////
  137. struct PackageEntry
  138. {
  139. MPC::wstring m_strDir;
  140. MPC::wstring m_strPackageDescription;
  141. FileList m_flSAF;
  142. FileList m_flINSTALL;
  143. TaxonomyList m_flHHT;
  144. MPC::wstring m_strNew_Cabinet;
  145. MPC::wstring m_strNew_Database;
  146. MPC::wstring m_DB_strSKU;
  147. long m_DB_lLCID;
  148. MPC::wstring m_DB_strDisplayName;
  149. friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ PackageEntry& val );
  150. friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const PackageEntry& val );
  151. HRESULT OpenPackageDescription( /*[in/out]*/ MPC::XmlUtil& xml );
  152. HRESULT Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
  153. HRESULT Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot );
  154. HRESULT ProcessHHTFile( /*[in]*/ LPCWSTR szHHTFile, /*[in]*/ JetBlue::SessionHandle* handle, /*[in]*/ JetBlue::Database* db );
  155. HRESULT CreateDatabase( /*[in]*/ const MPC::wstring& strTmp );
  156. void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
  157. };
  158. ////////////////////////////////////////////////////////////////////////////////
  159. enum PostBuildType
  160. {
  161. POSTBUILDTYPE_NORMAL = 0,
  162. POSTBUILDTYPE_SAF ,
  163. POSTBUILDTYPE_HHT ,
  164. };
  165. struct PostBuildEntry
  166. {
  167. PostBuildType m_pbt;
  168. SetupImageEntry m_entry;
  169. PackageEntry m_package;
  170. friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ PostBuildEntry& val );
  171. friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const PostBuildEntry& val );
  172. void FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot );
  173. };
  174. typedef std::list< PostBuildEntry > PostBuildList;
  175. typedef PostBuildList::iterator PostBuildIter;
  176. typedef PostBuildList::const_iterator PostBuildIterConst;
  177. ////////////////////////////////////////////////////////////////////////////////
  178. struct SkuInformation
  179. {
  180. MPC::wstring m_strName;
  181. MPC::wstring m_strCabinet;
  182. MPC::wstring m_strProdFilt;
  183. bool m_fDesktop;
  184. bool m_fServer;
  185. bool m_fEmbedded;
  186. SkuInformation()
  187. {
  188. m_fDesktop = false;
  189. m_fServer = false;
  190. m_fEmbedded = false;
  191. }
  192. friend HRESULT operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ SkuInformation& val );
  193. friend HRESULT operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const SkuInformation& val );
  194. };
  195. typedef std::list< SkuInformation > SkuInformationList;
  196. typedef SkuInformationList::iterator SkuInformationIter;
  197. typedef SkuInformationList::const_iterator SkuInformationIterConst;
  198. ////////////////////////////////////////////////////////////////////////////////
  199. static void GetRootDirectory( /*[out]*/ MPC::wstring& strRoot )
  200. {
  201. strRoot = l_szRoot ? l_szRoot : c_szNTTREE_TMP; MPC::SubstituteEnvVariables( strRoot );
  202. }
  203. static void GetLogFile( /*[out]*/ MPC::wstring& strLog )
  204. {
  205. GetRootDirectory( strLog );
  206. strLog += L"\\";
  207. strLog += l_szLog ? l_szLog : L"hss.log";
  208. }
  209. static void GetDBLogFile( /*[out]*/ MPC::wstring& strDBLog )
  210. {
  211. GetRootDirectory( strDBLog );
  212. strDBLog += L"\\";
  213. strDBLog += l_szDBLog ? l_szDBLog : L"createdb.log";
  214. }
  215. ////////////////////////////////////////////////////////////////////////////////
  216. ////////////////////////////////////////////////////////////////////////////////
  217. static HRESULT ExtractFile( /*[in]*/ LPCWSTR szCabinet, /*[in]*/ LPCWSTR szDst, /*[in]*/ LPCWSTR szFile )
  218. {
  219. __HCP_FUNC_ENTRY( "ExtractFile" );
  220. HRESULT hr;
  221. l_FileLog.LogRecord( L"Extracting '%s' from '%s'", szFile, szCabinet );
  222. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DecompressFromCabinet( szCabinet, szDst, szFile ));
  223. hr = S_OK;
  224. __HCP_FUNC_CLEANUP;
  225. __HCP_FUNC_EXIT(hr);
  226. }
  227. static void RemoveDirectory( /*[in]*/ const MPC::wstring& strDir )
  228. {
  229. MPC::FileSystemObject fso( strDir.c_str() );
  230. (void)fso.DeleteChildren( true, false );
  231. }
  232. ////////////////////
  233. static HRESULT MoveDataIsland( /*[in ]*/ MPC::XmlUtil& xmlIN ,
  234. /*[out]*/ MPC::XmlUtil& xmlOUT ,
  235. /*[in ]*/ LPCWSTR szTAG )
  236. {
  237. __HCP_FUNC_ENTRY( "MoveDataIsland" );
  238. HRESULT hr;
  239. CComPtr<IXMLDOMNodeList> xdnl;
  240. CComPtr<IXMLDOMNode> xdn;
  241. CComPtr<IXMLDOMNode> xdnRoot;
  242. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlOUT.GetRoot( &xdnRoot ));
  243. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlIN.GetNodes( szTAG, &xdnl ));
  244. for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
  245. {
  246. CComPtr<IXMLDOMNode> xdnReplaced;
  247. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRoot->appendChild( xdn, &xdnReplaced ));
  248. }
  249. hr = S_OK;
  250. __HCP_FUNC_CLEANUP;
  251. __HCP_FUNC_EXIT(hr);
  252. }
  253. static HRESULT ConvertAttributesToElements( /*[in]*/ MPC::XmlUtil& xml ,
  254. /*[in]*/ LPCWSTR szTAG ,
  255. /*[in]*/ LPCWSTR const* rgATTRIB ,
  256. /*[in]*/ int iATTRIB )
  257. {
  258. __HCP_FUNC_ENTRY( "ConvertAttributesToElements" );
  259. HRESULT hr;
  260. CComPtr<IXMLDOMNodeList> xdnl;
  261. CComPtr<IXMLDOMNode> xdn;
  262. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( szTAG, &xdnl ));
  263. for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
  264. {
  265. for(int i=0; i<iATTRIB; i++)
  266. {
  267. LPCWSTR szATTRIB = rgATTRIB[i];
  268. CComPtr<IXMLDOMAttribute> xdna;
  269. bool fFound;
  270. //
  271. // Move the value from the attribute to the element.
  272. //
  273. if(SUCCEEDED(xml.GetAttribute( NULL, szATTRIB, &xdna, fFound, xdn )) && xdna)
  274. {
  275. CComVariant vValue;
  276. CComPtr<IXMLDOMNode> xdnSUB;
  277. __MPC_EXIT_IF_METHOD_FAILS(hr, xdna->get_value( &vValue ));
  278. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.CreateNode( szATTRIB, &xdnSUB, xdn ));
  279. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutValue( NULL, vValue, fFound, xdnSUB ));
  280. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.RemoveAttribute( NULL, szATTRIB, xdn ));
  281. }
  282. }
  283. }
  284. hr = S_OK;
  285. __HCP_FUNC_CLEANUP;
  286. __HCP_FUNC_EXIT(hr);
  287. }
  288. static HRESULT ConvertElementsToAttributes( /*[in]*/ MPC::XmlUtil& xml ,
  289. /*[in]*/ LPCWSTR szTAG ,
  290. /*[in]*/ LPCWSTR const* rgATTRIB ,
  291. /*[in]*/ int iATTRIB )
  292. {
  293. __HCP_FUNC_ENTRY( "ConvertElementsToAttributes" );
  294. HRESULT hr;
  295. CComPtr<IXMLDOMNodeList> xdnl;
  296. CComPtr<IXMLDOMNode> xdn;
  297. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( szTAG, &xdnl ));
  298. for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
  299. {
  300. for(int i=0; i<iATTRIB; i++)
  301. {
  302. LPCWSTR szATTRIB = rgATTRIB[i];
  303. CComPtr<IXMLDOMNode> xdnSUB;
  304. //
  305. // Move the value from the attribute to the element.
  306. //
  307. if(SUCCEEDED(xdn->selectSingleNode( CComBSTR( szATTRIB ), &xdnSUB )) && xdnSUB)
  308. {
  309. CComVariant vValue;
  310. bool fFound;
  311. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, vValue, fFound, xdnSUB ));
  312. if(fFound)
  313. {
  314. CComPtr<IXMLDOMAttribute> xdna;
  315. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, szATTRIB, &xdna, fFound, xdn ));
  316. if(xdna)
  317. {
  318. __MPC_EXIT_IF_METHOD_FAILS(hr, xdna->put_value( vValue ));
  319. }
  320. }
  321. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.RemoveNode( NULL, xdnSUB ));
  322. }
  323. }
  324. }
  325. hr = S_OK;
  326. __HCP_FUNC_CLEANUP;
  327. __HCP_FUNC_EXIT(hr);
  328. }
  329. static HRESULT SpreadToFiles( /*[in]*/ MPC::XmlUtil& xmlSrc ,
  330. /*[in]*/ FileEntry& fe ,
  331. /*[in]*/ long lLimit )
  332. {
  333. __HCP_FUNC_ENTRY( "SpreadToFiles" );
  334. HRESULT hr;
  335. MPC::XmlUtil xmlDst;
  336. MPC::wstring strFile;
  337. long lCount = 0;
  338. bool fCreate = true;
  339. fe.m_lChunks = 0;
  340. while(1)
  341. {
  342. CComPtr<IXMLDOMNode> xdnRootSrc;
  343. CComPtr<IXMLDOMNode> xdnRootDst;
  344. CComPtr<IXMLDOMNode> xdnSrc;
  345. CComPtr<IXMLDOMNode> xdnDst;
  346. CComPtr<IXMLDOMNodeList> xdnl;
  347. CComPtr<IXMLDOMNode> xdn;
  348. long lLength;
  349. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlSrc.GetRoot( &xdnRootSrc ));
  350. if(fCreate)
  351. {
  352. fCreate = false;
  353. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.New( xdnRootSrc, /*fDeep*/false ));
  354. }
  355. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.GetRoot( &xdnRootDst ));
  356. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootSrc->get_firstChild( &xdnSrc ));
  357. if(xdnSrc)
  358. {
  359. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc->get_childNodes( &xdnl ));
  360. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnl ->get_length ( &lLength ));
  361. if(lLength < lLimit)
  362. {
  363. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->appendChild( xdnSrc, &xdn ));
  364. lCount += lLength;
  365. }
  366. else
  367. {
  368. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc ->cloneNode ( VARIANT_FALSE, &xdn ));
  369. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->appendChild( xdn, &xdnDst )); xdn.Release();
  370. for(lCount = 0; lCount < lLimit && SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release(), lCount++)
  371. {
  372. CComPtr<IXMLDOMNode> xdn2;
  373. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnDst->appendChild( xdn, &xdn2 ));
  374. }
  375. }
  376. }
  377. if(xdnSrc == NULL || lCount >= lLimit)
  378. {
  379. fe.GenerateChunkName( fe.m_lChunks++, strFile );
  380. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.Save( strFile.c_str() ));
  381. lCount = 0;
  382. fCreate = true;
  383. }
  384. if(!xdnSrc) break;
  385. }
  386. hr = S_OK;
  387. __HCP_FUNC_CLEANUP;
  388. __HCP_FUNC_EXIT(hr);
  389. }
  390. static HRESULT CollateFromFiles( /*[in]*/ MPC::XmlUtil& xmlDst ,
  391. /*[in]*/ LPCWSTR szRoot ,
  392. /*[in]*/ FileEntry& fe )
  393. {
  394. __HCP_FUNC_ENTRY( "CollateFromFiles" );
  395. HRESULT hr;
  396. MPC::XmlUtil xmlSrc;
  397. MPC::wstring strFile;
  398. bool fCreated = false;
  399. bool fLoaded;
  400. bool fFound;
  401. for(long l=0; l<fe.m_lChunks; l++)
  402. {
  403. fe.GenerateChunkName( l, strFile );
  404. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, (fCreated ? xmlSrc : xmlDst).Load( strFile.c_str(), szRoot, fLoaded, &fFound ));
  405. if(fLoaded == false ||
  406. fFound == false )
  407. {
  408. l_FileLog.LogRecord( L"Not a valid HHT: '%s'", strFile.c_str() );
  409. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  410. }
  411. if(fCreated)
  412. {
  413. CComPtr<IXMLDOMNode> xdnRootSrc;
  414. CComPtr<IXMLDOMNode> xdnRootDst;
  415. CComPtr<IXMLDOMNode> xdnSrc;
  416. CComPtr<IXMLDOMNode> xdnDst;
  417. CComPtr<IXMLDOMNodeList> xdnl;
  418. CComPtr<IXMLDOMNode> xdn;
  419. CComBSTR bstrTag;
  420. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlSrc.GetRoot( &xdnRootSrc ));
  421. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlDst.GetRoot( &xdnRootDst ));
  422. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootSrc->get_firstChild( &xdnSrc ));
  423. if(!xdnSrc) continue;
  424. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc ->get_nodeName ( &bstrTag ));
  425. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->selectSingleNode( bstrTag, &xdnDst ));
  426. if(!xdnDst)
  427. {
  428. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRootDst->appendChild( xdnSrc, &xdn ));
  429. }
  430. else
  431. {
  432. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnSrc->get_childNodes( &xdnl ));
  433. for(; SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
  434. {
  435. CComPtr<IXMLDOMNode> xdn2;
  436. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnDst->appendChild( xdn, &xdn2 ));
  437. }
  438. }
  439. }
  440. else
  441. {
  442. fCreated = true;
  443. }
  444. }
  445. hr = S_OK;
  446. __HCP_FUNC_CLEANUP;
  447. __HCP_FUNC_EXIT(hr);
  448. }
  449. ////////////////////
  450. static void FixString( /*[in/out]*/ MPC::wstring& strText, /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
  451. {
  452. if(!_wcsnicmp( strText.c_str(), strRootOld.c_str(), strRootOld.size() ))
  453. {
  454. strText.replace( 0, strRootOld.size(), strRoot );
  455. }
  456. }
  457. ////////////////////////////////////////////////////////////////////////////////
  458. ////////////////////////////////////////////////////////////////////////////////
  459. HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
  460. /*[out]*/ SetupImageEntry& val )
  461. {
  462. __HCP_FUNC_ENTRY( "operator>> SetupImageEntry" );
  463. HRESULT hr;
  464. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strSKU );
  465. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strLocalization );
  466. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strPurpose );
  467. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strSourceFile );
  468. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strTemporaryName );
  469. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strDestinationName );
  470. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strDestinationDir );
  471. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lastModified );
  472. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strTemporaryFullPath);
  473. hr = S_OK;
  474. __HCP_FUNC_CLEANUP;
  475. __HCP_FUNC_EXIT(hr);
  476. }
  477. HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
  478. /*[in]*/ const SetupImageEntry& val )
  479. {
  480. __HCP_FUNC_ENTRY( "operator<< SetupImageEntry" );
  481. HRESULT hr;
  482. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strSKU );
  483. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strLocalization );
  484. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strPurpose );
  485. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strSourceFile );
  486. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strTemporaryName );
  487. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strDestinationName );
  488. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strDestinationDir );
  489. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lastModified );
  490. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strTemporaryFullPath);
  491. hr = S_OK;
  492. __HCP_FUNC_CLEANUP;
  493. __HCP_FUNC_EXIT(hr);
  494. }
  495. HRESULT SetupImageEntry::Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
  496. {
  497. __HCP_FUNC_ENTRY( "SetupImageEntry::Import" );
  498. HRESULT hr;
  499. DATE dFileSrc;
  500. DATE dFileDst;
  501. m_strTemporaryFullPath = strRoot;
  502. m_strTemporaryFullPath += m_strLocalization;
  503. m_strTemporaryFullPath += L"\\";
  504. m_strTemporaryFullPath += m_strTemporaryName;
  505. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( m_strTemporaryFullPath ));
  506. dFileSrc = MPC::GetLastModifiedDate( m_strSourceFile );
  507. dFileDst = MPC::GetLastModifiedDate( m_strTemporaryFullPath );
  508. if(dFileSrc == 0) __MPC_SET_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  509. if(dFileSrc > dFileDst)
  510. {
  511. l_FileLog.LogRecord( L"Copying file '%s' to '%s'", m_strSourceFile.c_str(), m_strTemporaryFullPath.c_str() );
  512. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CopyFile( m_strSourceFile, m_strTemporaryFullPath ));
  513. m_lastModified = MPC::GetLastModifiedDate( m_strTemporaryFullPath );
  514. m_fUpdated = true;
  515. }
  516. else
  517. {
  518. m_lastModified = dFileDst;
  519. }
  520. hr = S_OK;
  521. __HCP_FUNC_CLEANUP;
  522. __HCP_FUNC_EXIT(hr);
  523. }
  524. HRESULT SetupImageEntry::Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
  525. {
  526. return S_OK;
  527. }
  528. void SetupImageEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
  529. {
  530. FixString( m_strTemporaryFullPath, strRootOld, strRoot );
  531. }
  532. ////////////////////////////////////////
  533. HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
  534. /*[out]*/ FileEntry& val )
  535. {
  536. __HCP_FUNC_ENTRY( "operator>> FileEntry" );
  537. HRESULT hr;
  538. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strName );
  539. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strFullPath );
  540. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lastModified_HIGH);
  541. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lastModified_LOW );
  542. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_lChunks );
  543. hr = S_OK;
  544. __HCP_FUNC_CLEANUP;
  545. __HCP_FUNC_EXIT(hr);
  546. }
  547. HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
  548. /*[in]*/ const FileEntry& val )
  549. {
  550. __HCP_FUNC_ENTRY( "operator<< FileEntry" );
  551. HRESULT hr;
  552. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strName );
  553. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strFullPath );
  554. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lastModified_HIGH);
  555. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lastModified_LOW );
  556. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_lChunks );
  557. hr = S_OK;
  558. __HCP_FUNC_CLEANUP;
  559. __HCP_FUNC_EXIT(hr);
  560. }
  561. void FileEntry::GenerateChunkName( /*[in]*/ long lChunk ,
  562. /*[out]*/ MPC::wstring& strFile ) const
  563. {
  564. WCHAR rgTmp[64]; _snwprintf( rgTmp, MAXSTRLEN(rgTmp), L"_%ld", lChunk );
  565. strFile = m_strFullPath;
  566. strFile.append( rgTmp );
  567. }
  568. void FileEntry::GetDate( /*[out]*/ DATE& dHIGH ,
  569. /*[out]*/ DATE& dLOW ) const
  570. {
  571. if(m_lChunks == 0)
  572. {
  573. dHIGH = dLOW = MPC::GetLastModifiedDate( m_strFullPath );
  574. }
  575. else
  576. {
  577. MPC::wstring strFile;
  578. DATE date;
  579. bool fNotExist = false;
  580. dHIGH = 0;
  581. dLOW = 0;
  582. for(long l = 0; l<m_lChunks; l++)
  583. {
  584. GenerateChunkName( l, strFile );
  585. date = MPC::GetLastModifiedDate( strFile );
  586. if(date)
  587. {
  588. if(!dHIGH || dHIGH < date) dHIGH = date;
  589. if(!dLOW || dLOW > date) dLOW = date;
  590. }
  591. else
  592. {
  593. fNotExist = true;
  594. }
  595. }
  596. if(fNotExist) dLOW = 0; // In case one chunk doesn't exist, dLOW should reflect that.
  597. }
  598. }
  599. void FileEntry::SetDate( /*[in]*/ bool fLookForChunks )
  600. {
  601. if(fLookForChunks && m_lChunks == 0)
  602. {
  603. MPC::wstring strFile;
  604. while(1)
  605. {
  606. GenerateChunkName( m_lChunks, strFile );
  607. if(!MPC::FileSystemObject::IsFile( strFile.c_str() )) break;
  608. m_lChunks++;
  609. }
  610. }
  611. GetDate( m_lastModified_HIGH, m_lastModified_LOW );
  612. }
  613. bool FileEntry::WasModified() const
  614. {
  615. DATE dHIGH;
  616. DATE dLOW;
  617. GetDate( dHIGH, dLOW );
  618. return (dHIGH == 0 || dHIGH > m_lastModified_HIGH);
  619. }
  620. void FileEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
  621. {
  622. FixString( m_strFullPath, strRootOld, strRoot );
  623. }
  624. bool FileEntry::IsNewer( /*[in]*/ const FileEntry& fe )
  625. {
  626. return IsNewer( fe.m_lastModified_LOW );
  627. }
  628. bool FileEntry::IsNewer( /*[in]*/ DATE date )
  629. {
  630. return (m_lastModified_HIGH > date);
  631. }
  632. ////////////////////////////////////////
  633. HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
  634. /*[out]*/ TaxonomyEntry& val )
  635. {
  636. __HCP_FUNC_ENTRY( "operator>> TaxonomyEntry" );
  637. HRESULT hr;
  638. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fe );
  639. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feMANUAL);
  640. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feSYNSET);
  641. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feLOC );
  642. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_feNOLOC );
  643. hr = S_OK;
  644. __HCP_FUNC_CLEANUP;
  645. __HCP_FUNC_EXIT(hr);
  646. }
  647. HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
  648. /*[in]*/ const TaxonomyEntry& val )
  649. {
  650. __HCP_FUNC_ENTRY( "operator<< TaxonomyEntry" );
  651. HRESULT hr;
  652. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fe );
  653. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feMANUAL);
  654. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feSYNSET);
  655. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feLOC );
  656. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_feNOLOC );
  657. hr = S_OK;
  658. __HCP_FUNC_CLEANUP;
  659. __HCP_FUNC_EXIT(hr);
  660. }
  661. HRESULT TaxonomyEntry::Import( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
  662. {
  663. __HCP_FUNC_ENTRY( "TaxonomyEntry::Import" );
  664. HRESULT hr;
  665. m_feMANUAL.m_strFullPath = m_fe.m_strFullPath; m_feMANUAL.m_strFullPath += L"_MANUAL"; m_feMANUAL.SetDate( );
  666. m_feSYNSET.m_strFullPath = m_fe.m_strFullPath; m_feSYNSET.m_strFullPath += L"_SYNSET"; m_feSYNSET.SetDate( );
  667. m_feLOC .m_strFullPath = m_fe.m_strFullPath; m_feLOC .m_strFullPath += L"_LOC"; m_feLOC .SetDate( /*fLookForChunks*/true );
  668. m_feNOLOC .m_strFullPath = m_fe.m_strFullPath; m_feNOLOC .m_strFullPath += L"_NOLOC"; m_feNOLOC .SetDate( );
  669. if(m_fe.IsNewer( m_feMANUAL ) ||
  670. m_fe.IsNewer( m_feSYNSET ) ||
  671. m_fe.IsNewer( m_feLOC ) ||
  672. m_fe.IsNewer( m_feNOLOC ) )
  673. {
  674. MPC::XmlUtil xml;
  675. bool fLoaded;
  676. bool fFound;
  677. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( m_fe.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
  678. if(fLoaded == false ||
  679. fFound == false )
  680. {
  681. l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_fe.m_strFullPath.c_str() );
  682. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  683. }
  684. if(m_fe.IsNewer( m_feMANUAL ))
  685. {
  686. MPC::XmlUtil xmlMANUAL;
  687. CComPtr<IXMLDOMNodeList> xdnl;
  688. CComPtr<IXMLDOMNode> xdn;
  689. l_FileLog.LogRecord( L"Processing HHT '%s' : MANUAL part", m_fe.m_strFullPath.c_str() );
  690. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlMANUAL.New( c_szHHT_rootTag, L"UTF-16" ));
  691. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlMANUAL, c_szHHT_manual_STOPSIGN ));
  692. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlMANUAL, c_szHHT_manual_STOPWORD ));
  693. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlMANUAL, c_szHHT_manual_OPERATOR ));
  694. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlMANUAL.Save( m_feMANUAL.m_strFullPath.c_str() ));
  695. m_feMANUAL.SetDate();
  696. m_feMANUAL.m_fUpdated = true;
  697. }
  698. if(m_fe.IsNewer( m_feSYNSET ))
  699. {
  700. MPC::XmlUtil xmlSYNSET;
  701. CComPtr<IXMLDOMNodeList> xdnl;
  702. CComPtr<IXMLDOMNode> xdn;
  703. l_FileLog.LogRecord( L"Processing HHT '%s' : SYNSET part", m_fe.m_strFullPath.c_str() );
  704. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlSYNSET.New( c_szHHT_rootTag, L"UTF-16" ));
  705. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlSYNSET, c_szHHT_synset_SYNTABLE ));
  706. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlSYNSET.Save( m_feSYNSET.m_strFullPath.c_str() ));
  707. m_feSYNSET.SetDate();
  708. m_feSYNSET.m_fUpdated = true;
  709. }
  710. if(m_fe.IsNewer( m_feLOC ))
  711. {
  712. MPC::XmlUtil xmlLOC;
  713. CComPtr<IXMLDOMNodeList> xdnl;
  714. CComPtr<IXMLDOMNode> xdn;
  715. l_FileLog.LogRecord( L"Processing HHT '%s' : LOC part", m_fe.m_strFullPath.c_str() );
  716. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlLOC.New( c_szHHT_rootTag, L"UTF-16" ));
  717. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlLOC, c_szHHT_loc_SCOPE ));
  718. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlLOC, c_szHHT_loc_TAXONOMY ));
  719. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertAttributesToElements( xmlLOC, c_szHHT_conv_SCOPE , c_rgHHT_conv_SCOPE , ARRAYSIZE(c_rgHHT_conv_SCOPE ) ));
  720. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertAttributesToElements( xmlLOC, c_szHHT_conv_TAXONOMY, c_rgHHT_conv_TAXONOMY, ARRAYSIZE(c_rgHHT_conv_TAXONOMY) ));
  721. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, SpreadToFiles( xmlLOC, m_feLOC, l_lMaxElements ));
  722. m_feLOC.SetDate();
  723. m_feLOC.m_fUpdated = true;
  724. }
  725. if(m_fe.IsNewer( m_feNOLOC ))
  726. {
  727. MPC::XmlUtil xmlNOLOC;
  728. CComPtr<IXMLDOMNodeList> xdnl;
  729. CComPtr<IXMLDOMNode> xdn;
  730. l_FileLog.LogRecord( L"Processing HHT '%s' : NOLOC part", m_fe.m_strFullPath.c_str() );
  731. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlNOLOC.New( c_szHHT_rootTag ));
  732. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlNOLOC, c_szHHT_noloc_FTS ));
  733. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlNOLOC, c_szHHT_noloc_INDEX ));
  734. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xml, xmlNOLOC, c_szHHT_noloc_HELPIMAGE ));
  735. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlNOLOC.Save( m_feNOLOC.m_strFullPath.c_str() ));
  736. m_feNOLOC.SetDate();
  737. m_feNOLOC.m_fUpdated = true;
  738. }
  739. }
  740. hr = S_OK;
  741. __HCP_FUNC_CLEANUP;
  742. __HCP_FUNC_EXIT(hr);
  743. }
  744. HRESULT TaxonomyEntry::Export( /*[in]*/ PackageEntry& pe, /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
  745. {
  746. __HCP_FUNC_ENTRY( "TaxonomyEntry::Export" );
  747. HRESULT hr;
  748. m_fe_New.m_strFullPath = m_fe.m_strFullPath; m_fe_New.m_strFullPath += L"_GEN";
  749. m_feMANUAL.SetDate();
  750. m_feSYNSET.SetDate();
  751. m_feLOC .SetDate();
  752. m_feNOLOC .SetDate();
  753. m_fe_New .SetDate();
  754. if(m_feMANUAL.IsNewer( m_fe_New ) ||
  755. m_feSYNSET.IsNewer( m_fe_New ) ||
  756. m_feLOC .IsNewer( m_fe_New ) ||
  757. m_feNOLOC .IsNewer( m_fe_New ) )
  758. {
  759. MPC::XmlUtil xml;
  760. bool fLoaded;
  761. bool fFound;
  762. l_FileLog.LogRecord( L"Processing HHT '%s'", m_fe_New.m_strFullPath.c_str() );
  763. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.New( c_szHHT_rootTag, L"UTF-16" ));
  764. {
  765. MPC::XmlUtil xmlMANUAL;
  766. CComPtr<IXMLDOMNodeList> xdnl;
  767. CComPtr<IXMLDOMNode> xdn;
  768. l_FileLog.LogRecord( L"Processing HHT '%s' : MANUAL part", m_fe_New.m_strFullPath.c_str() );
  769. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlMANUAL.Load( m_feMANUAL.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
  770. if(fLoaded == false ||
  771. fFound == false )
  772. {
  773. l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_feMANUAL.m_strFullPath.c_str() );
  774. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  775. }
  776. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlMANUAL, xml, c_szHHT_manual_STOPSIGN ));
  777. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlMANUAL, xml, c_szHHT_manual_STOPWORD ));
  778. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlMANUAL, xml, c_szHHT_manual_OPERATOR ));
  779. }
  780. {
  781. MPC::XmlUtil xmlSYNSET;
  782. CComPtr<IXMLDOMNodeList> xdnl;
  783. CComPtr<IXMLDOMNode> xdn;
  784. l_FileLog.LogRecord( L"Processing HHT '%s' : SYNSET part", m_fe_New.m_strFullPath.c_str() );
  785. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlSYNSET.Load( m_feSYNSET.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
  786. if(fLoaded == false ||
  787. fFound == false )
  788. {
  789. l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_feSYNSET.m_strFullPath.c_str() );
  790. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  791. }
  792. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlSYNSET, xml, c_szHHT_synset_SYNTABLE ));
  793. }
  794. {
  795. MPC::XmlUtil xmlLOC;
  796. CComPtr<IXMLDOMNodeList> xdnl;
  797. CComPtr<IXMLDOMNode> xdn;
  798. l_FileLog.LogRecord( L"Processing HHT '%s' : LOC part", m_fe_New.m_strFullPath.c_str() );
  799. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, CollateFromFiles( xmlLOC, c_szHHT_rootTag, m_feLOC ));
  800. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertElementsToAttributes( xmlLOC, c_szHHT_conv_SCOPE , c_rgHHT_conv_SCOPE , ARRAYSIZE(c_rgHHT_conv_SCOPE ) ));
  801. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertElementsToAttributes( xmlLOC, c_szHHT_conv_TAXONOMY, c_rgHHT_conv_TAXONOMY, ARRAYSIZE(c_rgHHT_conv_TAXONOMY) ));
  802. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlLOC, xml, c_szHHT_loc_SCOPE ));
  803. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlLOC, xml, c_szHHT_loc_TAXONOMY ));
  804. }
  805. {
  806. MPC::XmlUtil xmlNOLOC;
  807. CComPtr<IXMLDOMNodeList> xdnl;
  808. CComPtr<IXMLDOMNode> xdn;
  809. l_FileLog.LogRecord( L"Processing HHT '%s' : NOLOC part", m_fe_New.m_strFullPath.c_str() );
  810. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xmlNOLOC.Load( m_feNOLOC.m_strFullPath.c_str(), c_szHHT_rootTag, fLoaded, &fFound ));
  811. if(fLoaded == false ||
  812. fFound == false )
  813. {
  814. l_FileLog.LogRecord( L"Not a valid HHT: '%s'", m_feNOLOC.m_strFullPath.c_str() );
  815. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  816. }
  817. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlNOLOC, xml, c_szHHT_noloc_FTS ));
  818. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlNOLOC, xml, c_szHHT_noloc_INDEX ));
  819. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, MoveDataIsland( xmlNOLOC, xml, c_szHHT_noloc_HELPIMAGE ));
  820. }
  821. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xml.Save( m_fe_New.m_strFullPath.c_str() ));
  822. }
  823. hr = S_OK;
  824. __HCP_FUNC_CLEANUP;
  825. __HCP_FUNC_EXIT(hr);
  826. }
  827. void TaxonomyEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
  828. {
  829. m_fe .FixRoot( strRootOld, strRoot );
  830. m_feMANUAL.FixRoot( strRootOld, strRoot );
  831. m_feSYNSET.FixRoot( strRootOld, strRoot );
  832. m_feLOC .FixRoot( strRootOld, strRoot );
  833. m_feNOLOC .FixRoot( strRootOld, strRoot );
  834. m_fe_New .FixRoot( strRootOld, strRoot );
  835. }
  836. ////////////////////////////////////////
  837. HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
  838. /*[out]*/ PackageEntry& val )
  839. {
  840. __HCP_FUNC_ENTRY( "operator>> PackageEntry" );
  841. HRESULT hr;
  842. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strDir );
  843. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strPackageDescription);
  844. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_flSAF );
  845. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_flINSTALL );
  846. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_flHHT );
  847. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_DB_strSKU );
  848. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_DB_lLCID );
  849. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_DB_strDisplayName );
  850. hr = S_OK;
  851. __HCP_FUNC_CLEANUP;
  852. __HCP_FUNC_EXIT(hr);
  853. }
  854. HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
  855. /*[in]*/ const PackageEntry& val )
  856. {
  857. __HCP_FUNC_ENTRY( "operator<< PackageEntry" );
  858. HRESULT hr;
  859. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strDir );
  860. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strPackageDescription);
  861. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_flSAF );
  862. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_flINSTALL );
  863. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_flHHT );
  864. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_DB_strSKU );
  865. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_DB_lLCID );
  866. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_DB_strDisplayName );
  867. hr = S_OK;
  868. __HCP_FUNC_CLEANUP;
  869. __HCP_FUNC_EXIT(hr);
  870. }
  871. HRESULT PackageEntry::Import( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
  872. {
  873. __HCP_FUNC_ENTRY( "PackageEntry::Import" );
  874. HRESULT hr;
  875. MPC::Cabinet::List lst;
  876. MPC::wstring strFile;
  877. MPC::wstring strFile_Base;
  878. LPCWSTR szSourceFile;
  879. LPCWSTR szEnd;
  880. DATE dFile_PackageDescription;
  881. strFile = pbe.m_entry.m_strTemporaryFullPath;
  882. //
  883. // Create temp dir from the file name.
  884. //
  885. szSourceFile = strFile.c_str();
  886. szEnd = wcsrchr( szSourceFile, '.' );
  887. if(szEnd)
  888. {
  889. m_strDir.assign( szSourceFile, szEnd );
  890. }
  891. else
  892. {
  893. m_strDir = szSourceFile;
  894. }
  895. m_strDir += L"\\";
  896. if(pbe.m_entry.m_fUpdated)
  897. {
  898. RemoveDirectory( m_strDir );
  899. m_flSAF .clear();
  900. m_flINSTALL.clear();
  901. m_flHHT .clear();
  902. }
  903. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( m_strDir ));
  904. //
  905. // Analyze Package_Description.xml
  906. //
  907. {
  908. MPC::XmlUtil xml;
  909. bool fFound;
  910. m_strPackageDescription = m_strDir;
  911. m_strPackageDescription += c_szPackageDescription;
  912. dFile_PackageDescription = MPC::GetLastModifiedDate( m_strPackageDescription );
  913. if(dFile_PackageDescription == 0 || pbe.m_entry.m_lastModified > dFile_PackageDescription)
  914. {
  915. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ExtractFile( szSourceFile, m_strPackageDescription.c_str(), c_szPackageDescription ));
  916. dFile_PackageDescription = MPC::GetLastModifiedDate( m_strPackageDescription );;
  917. }
  918. __MPC_EXIT_IF_METHOD_FAILS(hr, OpenPackageDescription( xml ));
  919. //
  920. // Parse the SAF section.
  921. //
  922. {
  923. CComPtr<IXMLDOMNodeList> xdnl;
  924. CComPtr<IXMLDOMNode> xdn;
  925. FileEntry fe;
  926. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( L"CONFIG/SAF/@FILE", &xdnl ));
  927. for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
  928. {
  929. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, fe.m_strName, fFound, xdn ));
  930. if(fFound)
  931. {
  932. fe.m_strFullPath = m_strDir;
  933. fe.m_strFullPath += fe.m_strName;
  934. m_flSAF.push_back( fe );
  935. }
  936. }
  937. }
  938. //
  939. // Parse the INSTALL section.
  940. //
  941. {
  942. CComPtr<IXMLDOMNodeList> xdnl;
  943. CComPtr<IXMLDOMNode> xdn;
  944. FileEntry fe;
  945. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( L"INSTALL_CONTENT/FILE/@SOURCE", &xdnl ));
  946. for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
  947. {
  948. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, fe.m_strName, fFound, xdn ));
  949. if(fFound)
  950. {
  951. fe.m_strFullPath = m_strDir;
  952. fe.m_strFullPath += fe.m_strName;
  953. m_flINSTALL.push_back( fe );
  954. }
  955. }
  956. }
  957. //
  958. // Parse the HHT section.
  959. //
  960. {
  961. CComPtr<IXMLDOMNodeList> xdnl;
  962. CComPtr<IXMLDOMNode> xdn;
  963. TaxonomyEntry te;
  964. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetNodes( L"METADATA/HHT/@FILE", &xdnl ));
  965. for(;SUCCEEDED(hr = xdnl->nextNode( &xdn )) && xdn != NULL; xdn.Release())
  966. {
  967. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, te.m_fe.m_strName, fFound, xdn ));
  968. if(fFound)
  969. {
  970. te.m_fe.m_strFullPath = m_strDir;
  971. te.m_fe.m_strFullPath += te.m_fe.m_strName;
  972. m_flHHT.push_back( te );
  973. }
  974. }
  975. }
  976. }
  977. //
  978. // Extract all the required files.
  979. //
  980. {
  981. MPC::WStringUCSet setDecompress;
  982. MPC::Cabinet cab;
  983. FileIter it1;
  984. FileIter it2;
  985. TaxonomyIter it3;
  986. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.put_CabinetFile( szSourceFile ));
  987. for(it1=m_flSAF.begin(); it1!=m_flSAF.end(); it1++)
  988. {
  989. FileEntry& fe = *it1;
  990. if(dFile_PackageDescription > MPC::GetLastModifiedDate( fe.m_strFullPath ))
  991. {
  992. if(setDecompress.find( fe.m_strName ) == setDecompress.end())
  993. {
  994. setDecompress.insert( fe.m_strName );
  995. l_FileLog.LogRecord( L"Extracting '%s' from '%s'", fe.m_strName.c_str(), szSourceFile );
  996. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
  997. fe.m_fUpdated = true;
  998. }
  999. }
  1000. }
  1001. for(it2=m_flINSTALL.begin(); it2!=m_flINSTALL.end(); it2++)
  1002. {
  1003. FileEntry& fe = *it2;
  1004. if(dFile_PackageDescription > MPC::GetLastModifiedDate( fe.m_strFullPath ))
  1005. {
  1006. if(setDecompress.find( fe.m_strName ) == setDecompress.end())
  1007. {
  1008. setDecompress.insert( fe.m_strName );
  1009. l_FileLog.LogRecord( L"Extracting '%s' from '%s'", fe.m_strName.c_str(), szSourceFile );
  1010. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
  1011. fe.m_fUpdated = true;
  1012. }
  1013. }
  1014. }
  1015. for(it3=m_flHHT.begin(); it3!=m_flHHT.end(); it3++)
  1016. {
  1017. TaxonomyEntry& te = *it3;
  1018. if(dFile_PackageDescription > MPC::GetLastModifiedDate( te.m_fe.m_strFullPath ))
  1019. {
  1020. if(setDecompress.find( te.m_fe.m_strName ) == setDecompress.end())
  1021. {
  1022. setDecompress.insert( te.m_fe.m_strName );
  1023. l_FileLog.LogRecord( L"Extracting '%s' from '%s'", te.m_fe.m_strName.c_str(), szSourceFile );
  1024. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( te.m_fe.m_strFullPath.c_str(), te.m_fe.m_strName.c_str() ));
  1025. te.m_fe.m_fUpdated = true;
  1026. }
  1027. }
  1028. }
  1029. hr = cab.Decompress();
  1030. if(FAILED(hr))
  1031. {
  1032. MPC::Cabinet::List lst;
  1033. MPC::Cabinet::Iter it;
  1034. if(SUCCEEDED(cab.GetFiles( lst )))
  1035. {
  1036. for(it=lst.begin(); it != lst.end(); it++)
  1037. {
  1038. if(it->m_fFound == false)
  1039. {
  1040. l_FileLog.LogRecord( L"!!ERROR: Missing %s \n", it->m_szName.c_str() );
  1041. }
  1042. }
  1043. }
  1044. __MPC_FUNC_LEAVE;
  1045. }
  1046. for(it1=m_flSAF.begin(); it1!=m_flSAF.end(); it1++)
  1047. {
  1048. FileEntry& fe = *it1;
  1049. fe.SetDate();
  1050. }
  1051. for(it2=m_flINSTALL.begin(); it2!=m_flINSTALL.end(); it2++)
  1052. {
  1053. FileEntry& fe = *it2;
  1054. fe.SetDate();
  1055. }
  1056. for(it3=m_flHHT.begin(); it3!=m_flHHT.end(); it3++)
  1057. {
  1058. TaxonomyEntry& te = *it3;
  1059. te.m_fe.SetDate();
  1060. }
  1061. }
  1062. //
  1063. // Process the HHTs.
  1064. //
  1065. {
  1066. for(TaxonomyIter it=m_flHHT.begin(); it!=m_flHHT.end(); it++)
  1067. {
  1068. TaxonomyEntry& te = *it;
  1069. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, te.Import( *this, pbe, strRoot ));
  1070. }
  1071. }
  1072. hr = S_OK;
  1073. __HCP_FUNC_CLEANUP;
  1074. __HCP_FUNC_EXIT(hr);
  1075. }
  1076. HRESULT PackageEntry::Export( /*[in]*/ PostBuildEntry& pbe, /*[in]*/ const MPC::wstring& strRoot )
  1077. {
  1078. __HCP_FUNC_ENTRY( "PackageEntry::Export" );
  1079. HRESULT hr;
  1080. DATE dFile_Cabinet;
  1081. DATE dFile_PackageDescription;
  1082. m_strNew_Cabinet = pbe.m_entry.m_strTemporaryFullPath;
  1083. m_strNew_Cabinet += L"_GEN";
  1084. dFile_Cabinet = MPC::GetLastModifiedDate( m_strNew_Cabinet );
  1085. dFile_PackageDescription = MPC::GetLastModifiedDate( m_strPackageDescription );
  1086. //
  1087. // Process the HHTs.
  1088. //
  1089. {
  1090. for(TaxonomyIter it=m_flHHT.begin(); it!=m_flHHT.end(); it++)
  1091. {
  1092. TaxonomyEntry& te = *it;
  1093. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, te.Export( *this, pbe, strRoot ));
  1094. }
  1095. }
  1096. //
  1097. // Compress all the required files.
  1098. //
  1099. {
  1100. MPC::Cabinet cab;
  1101. FileIter it1;
  1102. FileIter it2;
  1103. TaxonomyIter it3;
  1104. bool fNew = false;
  1105. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.put_CabinetFile( m_strNew_Cabinet.c_str() ));
  1106. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( m_strPackageDescription.c_str(), c_szPackageDescription ));
  1107. if(dFile_PackageDescription > dFile_Cabinet) fNew = true;
  1108. for(it1=m_flSAF.begin(); it1!=m_flSAF.end(); it1++)
  1109. {
  1110. FileEntry& fe = *it1;
  1111. fe.SetDate(); if(fe.IsNewer( dFile_Cabinet )) fNew = true;
  1112. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
  1113. }
  1114. for(it2=m_flINSTALL.begin(); it2!=m_flINSTALL.end(); it2++)
  1115. {
  1116. FileEntry& fe = *it2;
  1117. fe.SetDate(); if(fe.IsNewer( dFile_Cabinet )) fNew = true;
  1118. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( fe.m_strFullPath.c_str(), fe.m_strName.c_str() ));
  1119. }
  1120. for(it3=m_flHHT.begin(); it3!=m_flHHT.end(); it3++)
  1121. {
  1122. TaxonomyEntry& te = *it3;
  1123. te.m_fe_New.SetDate(); if(te.m_fe_New.IsNewer( dFile_Cabinet )) fNew = true;
  1124. __MPC_EXIT_IF_METHOD_FAILS(hr, cab.AddFile( te.m_fe_New.m_strFullPath.c_str(), te.m_fe.m_strName.c_str() ));
  1125. }
  1126. if(fNew)
  1127. {
  1128. l_FileLog.LogRecord( L"Compressing '%s'", m_strNew_Cabinet.c_str() );
  1129. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, cab.Compress());
  1130. }
  1131. }
  1132. if(pbe.m_pbt == POSTBUILDTYPE_HHT)
  1133. {
  1134. DATE dCabinet;
  1135. DATE dDatabase;
  1136. m_strNew_Database = pbe.m_entry.m_strTemporaryFullPath;
  1137. m_strNew_Database += L"_EDB";
  1138. {
  1139. MPC::XmlUtil xml;
  1140. __MPC_EXIT_IF_METHOD_FAILS(hr, OpenPackageDescription( xml ));
  1141. }
  1142. dCabinet = MPC::GetLastModifiedDate( m_strNew_Cabinet );
  1143. dDatabase = MPC::GetLastModifiedDate( m_strNew_Database );
  1144. if(dDatabase == 0.0 || dCabinet > dDatabase)
  1145. {
  1146. MPC::wstring strTmp;
  1147. GetRootDirectory( strTmp );
  1148. strTmp += L"\\EDB_";
  1149. strTmp += m_DB_strSKU;
  1150. strTmp += L"\\";
  1151. l_FileLog.LogRecord( L"Create database '%s'", m_strNew_Database.c_str() );
  1152. try
  1153. {
  1154. hr = CreateDatabase( strTmp );
  1155. }
  1156. catch(...)
  1157. {
  1158. hr = E_FAIL;
  1159. }
  1160. //
  1161. // Something JetBlue fails because of a bad checkpoint directory.
  1162. //
  1163. if(FAILED(hr))
  1164. {
  1165. try
  1166. {
  1167. RemoveDirectory( strTmp );
  1168. hr = CreateDatabase( strTmp );
  1169. }
  1170. catch(...)
  1171. {
  1172. hr = E_FAIL;
  1173. }
  1174. }
  1175. if(FAILED(hr))
  1176. {
  1177. (void)MPC::DeleteFile( m_strNew_Database );
  1178. }
  1179. RemoveDirectory( strTmp );
  1180. __MPC_EXIT_IF_METHOD_FAILS(hr, hr);
  1181. }
  1182. }
  1183. hr = S_OK;
  1184. __HCP_FUNC_CLEANUP;
  1185. __HCP_FUNC_EXIT(hr);
  1186. }
  1187. ////////////////////
  1188. HRESULT PackageEntry::OpenPackageDescription( /*[in/out]*/ MPC::XmlUtil& xml )
  1189. {
  1190. __HCP_FUNC_ENTRY( "PackageEntry::OpenPackageDescription" );
  1191. HRESULT hr;
  1192. MPC::wstring strLanguage;
  1193. bool fLoaded;
  1194. bool fFound;
  1195. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( m_strPackageDescription.c_str(), L"HELPCENTERPACKAGE", fLoaded, &fFound ));
  1196. if(fLoaded == false ||
  1197. fFound == false )
  1198. {
  1199. l_FileLog.LogRecord( L"Not a valid Package_Description: '%s'", m_strPackageDescription.c_str() );
  1200. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  1201. }
  1202. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetAttribute( L"SKU", L"VALUE" , m_DB_strSKU , fFound ));
  1203. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetAttribute( L"SKU", L"DISPLAYNAME", m_DB_strDisplayName, fFound ));
  1204. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetAttribute( L"LANGUAGE", L"VALUE" , strLanguage , fFound )); if(fFound) m_DB_lLCID = _wtol( strLanguage.c_str() );
  1205. hr = S_OK;
  1206. __HCP_FUNC_CLEANUP;
  1207. __HCP_FUNC_EXIT(hr);
  1208. }
  1209. HRESULT PackageEntry::ProcessHHTFile( /*[in]*/ LPCWSTR szHHTFile ,
  1210. /*[in]*/ JetBlue::SessionHandle* handle ,
  1211. /*[in]*/ JetBlue::Database* db )
  1212. {
  1213. __HCP_FUNC_ENTRY( "PackageEntry::ProcessHHTFile" );
  1214. HRESULT hr;
  1215. CComPtr<HCUpdate::Engine> obj;
  1216. MPC::wstring strDBLog; GetDBLogFile( strDBLog );
  1217. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  1218. 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 ));
  1219. hr = S_OK;
  1220. __HCP_FUNC_CLEANUP;
  1221. __HCP_FUNC_EXIT(hr);
  1222. }
  1223. HRESULT PackageEntry::CreateDatabase( /*[in]*/ const MPC::wstring& strTmp )
  1224. {
  1225. __HCP_FUNC_ENTRY( "PackageEntry::CreateDatabase" );
  1226. USES_CONVERSION;
  1227. HRESULT hr;
  1228. JetBlue::SessionPool pool;
  1229. JetBlue::SessionHandle handle;
  1230. JetBlue::Database* db;
  1231. long lMSFTid;
  1232. bool fPool = false;
  1233. bool fSession = false;
  1234. bool fDatabase = false;
  1235. // if(g_fVerbose) wprintf( L"Creating database %s\n", szDatabase );
  1236. //
  1237. // Remove any old database.
  1238. //
  1239. (void)MPC::DeleteFile( m_strNew_Database );
  1240. ////////////////////////////////////////////////////////////////////////////////
  1241. //
  1242. // Create new database.
  1243. //
  1244. RemoveDirectory( strTmp );
  1245. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pool.Init( strTmp.c_str() )); fPool = true;
  1246. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pool.GetSession( handle )); fSession = true;
  1247. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, handle->GetDatabase( W2A( m_strNew_Database.c_str() ), db, /*fReadOnly*/false, /*fCreate*/true, /*fRepair*/false )) fDatabase = true;
  1248. ////////////////////////////////////////////////////////////////////////////////
  1249. //
  1250. // Load the schema in the database.
  1251. //
  1252. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
  1253. {
  1254. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::CreateSchema( db ));
  1255. }
  1256. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
  1257. ////////////////////////////////////////////////////////////////////////////////
  1258. {
  1259. Taxonomy::Settings ts( m_DB_strSKU.c_str(), m_DB_lLCID );
  1260. Taxonomy::Updater updater;
  1261. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.Init( ts, db ));
  1262. //
  1263. // Generate content owner
  1264. //
  1265. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
  1266. {
  1267. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.CreateOwner( lMSFTid, HC_MICROSOFT_DN, /*fIsOEM*/true ));
  1268. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.LocateOwner( HC_MICROSOFT_DN ));
  1269. }
  1270. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
  1271. //
  1272. // Create the root and non-mapped node in the topic table
  1273. //
  1274. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
  1275. {
  1276. Taxonomy::RS_Taxonomy* rs;
  1277. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.GetTaxonomy( &rs ));
  1278. rs->m_ID_owner = lMSFTid;
  1279. rs->m_strEntry = L"<ROOT>";
  1280. __MPC_EXIT_IF_METHOD_FAILS(hr, rs->Insert());
  1281. }
  1282. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
  1283. //
  1284. // Create the system scope.
  1285. //
  1286. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->BeginTransaction());
  1287. {
  1288. Taxonomy::RS_Scope* rs;
  1289. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.GetScope( &rs ));
  1290. rs->m_ID_owner = lMSFTid;
  1291. rs->m_strID = L"<SYSTEM>";
  1292. __MPC_EXIT_IF_METHOD_FAILS(hr, rs->Insert());
  1293. }
  1294. __MPC_EXIT_IF_METHOD_FAILS(hr, handle->CommitTransaction());
  1295. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, updater.Close());
  1296. }
  1297. ////////////////////////////////////////////////////////////////////////////////
  1298. //
  1299. // Process the HHT file, after closing the updater.
  1300. //
  1301. {
  1302. for(TaxonomyIter it=m_flHHT.begin(); it!=m_flHHT.end(); it++)
  1303. {
  1304. TaxonomyEntry& te = *it;
  1305. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, ProcessHHTFile( te.m_fe_New.m_strFullPath.c_str(), &handle, db ));
  1306. }
  1307. }
  1308. ////////////////////////////////////////////////////////////////////////////////
  1309. hr = S_OK;
  1310. __HCP_FUNC_CLEANUP;
  1311. if(fDatabase) { ; }
  1312. if(fSession ) { handle.Release(); }
  1313. if(fPool ) { (void)pool.Close( true ); }
  1314. __HCP_FUNC_EXIT(hr);
  1315. }
  1316. void PackageEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
  1317. {
  1318. FileIter it1;
  1319. TaxonomyIter it2;
  1320. FixString( m_strDir , strRootOld, strRoot );
  1321. FixString( m_strPackageDescription, strRootOld, strRoot );
  1322. for(it1=m_flSAF .begin(); it1!=m_flSAF .end(); it1++) it1->FixRoot( strRootOld, strRoot );
  1323. for(it1=m_flINSTALL.begin(); it1!=m_flINSTALL.end(); it1++) it1->FixRoot( strRootOld, strRoot );
  1324. for(it2=m_flHHT .begin(); it2!=m_flHHT .end(); it2++) it2->FixRoot( strRootOld, strRoot );
  1325. FixString( m_strNew_Cabinet , strRootOld, strRoot );
  1326. FixString( m_strNew_Database, strRootOld, strRoot );
  1327. }
  1328. ////////////////////////////////////////
  1329. HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
  1330. /*[out]*/ PostBuildEntry& val )
  1331. {
  1332. __HCP_FUNC_ENTRY( "operator>> PostBuildEntry" );
  1333. HRESULT hr;
  1334. long pbt;
  1335. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> pbt ); val.m_pbt = (PostBuildType)pbt;
  1336. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_entry );
  1337. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_package);
  1338. hr = S_OK;
  1339. __HCP_FUNC_CLEANUP;
  1340. __HCP_FUNC_EXIT(hr);
  1341. }
  1342. HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
  1343. /*[in]*/ const PostBuildEntry& val )
  1344. {
  1345. __HCP_FUNC_ENTRY( "operator<< PostBuildEntry" );
  1346. HRESULT hr;
  1347. long pbt = (long)val.m_pbt;
  1348. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << pbt );
  1349. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_entry );
  1350. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_package);
  1351. hr = S_OK;
  1352. __HCP_FUNC_CLEANUP;
  1353. __HCP_FUNC_EXIT(hr);
  1354. }
  1355. void PostBuildEntry::FixRoot( /*[in]*/ const MPC::wstring& strRootOld, /*[in]*/ const MPC::wstring& strRoot )
  1356. {
  1357. m_entry .FixRoot( strRootOld, strRoot );
  1358. m_package.FixRoot( strRootOld, strRoot );
  1359. }
  1360. ////////////////////////////////////////
  1361. HRESULT operator>>( /*[in ]*/ MPC::Serializer& stream ,
  1362. /*[out]*/ SkuInformation& val )
  1363. {
  1364. __HCP_FUNC_ENTRY( "operator>> SkuInformation" );
  1365. HRESULT hr;
  1366. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strName );
  1367. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strCabinet );
  1368. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strProdFilt);
  1369. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fDesktop );
  1370. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fServer );
  1371. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fEmbedded );
  1372. hr = S_OK;
  1373. __HCP_FUNC_CLEANUP;
  1374. __HCP_FUNC_EXIT(hr);
  1375. }
  1376. HRESULT operator<<( /*[in]*/ MPC::Serializer& stream ,
  1377. /*[in]*/ const SkuInformation& val )
  1378. {
  1379. __HCP_FUNC_ENTRY( "operator<< SkuInformation" );
  1380. HRESULT hr;
  1381. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strName );
  1382. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strCabinet );
  1383. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strProdFilt);
  1384. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fDesktop );
  1385. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fServer );
  1386. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fEmbedded );
  1387. hr = S_OK;
  1388. __HCP_FUNC_CLEANUP;
  1389. __HCP_FUNC_EXIT(hr);
  1390. }
  1391. ////////////////////////////////////////////////////////////////////////////////
  1392. ////////////////////////////////////////////////////////////////////////////////
  1393. //////////////////////////////////////////////////////////////////////
  1394. static void Usage()
  1395. {
  1396. wprintf( L"Usage: HssSetupTool <options> <command> <parameters>\n\n" );
  1397. wprintf( L"Available commands:\n\n" );
  1398. wprintf( L" BINPLACE <sku file> <setup image file> <root directory> <object directory>\n" );
  1399. wprintf( L" COMPILE <root directory> <sku>\n" );
  1400. wprintf( L" LIST <input cabinet>\n" );
  1401. wprintf( L" EXTRACT <input cabinet> <file>\n" );
  1402. wprintf( L" INSTALL <input cabinet>\n" );
  1403. wprintf( L"\n" );
  1404. wprintf( L" UNPACK <input cabinet> <directory>\n" );
  1405. wprintf( L" PACK <directory> <output cabinet>\n" );
  1406. }
  1407. #define CHECK_ARGS(argc,num) if(argc < num) { Usage(); __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); }
  1408. ////////////////////////////////////////
  1409. static bool LookupBoolean( /*[in] */ LPCWSTR szString )
  1410. {
  1411. if(_wcsicmp( szString, L"TRUE" ) == 0 ||
  1412. _wcsicmp( szString, L"1" ) == 0 ||
  1413. _wcsicmp( szString, L"ON" ) == 0 )
  1414. {
  1415. return true;
  1416. }
  1417. return false;
  1418. }
  1419. static bool ParseFile( /*[in ]*/ LPSTR szLine ,
  1420. /*[out]*/ SetupImageEntry& en )
  1421. {
  1422. USES_CONVERSION;
  1423. HRESULT hr;
  1424. LPSTR szEnd;
  1425. std::vector<MPC::wstring> vec;
  1426. //
  1427. // Skip comments.
  1428. //
  1429. if(szLine[0] == '#') return false;
  1430. if((szEnd = strchr( szLine, '\r' ))) szEnd[0] = 0;
  1431. if((szEnd = strchr( szLine, '\n' ))) szEnd[0] = 0;
  1432. MPC::SplitAtDelimiter( vec, A2W( szLine ), L"," );
  1433. if(vec.size() != 7) return false;
  1434. en.m_strSKU = vec[0];
  1435. en.m_strLocalization = vec[1];
  1436. en.m_strPurpose = vec[2];
  1437. en.m_strSourceFile = vec[3];
  1438. en.m_strTemporaryName = vec[4];
  1439. en.m_strDestinationName = vec[5];
  1440. en.m_strDestinationDir = vec[6];
  1441. return true;
  1442. }
  1443. static bool ParseFile( /*[in ]*/ LPSTR szLine ,
  1444. /*[out]*/ SkuInformation& si )
  1445. {
  1446. USES_CONVERSION;
  1447. HRESULT hr;
  1448. LPSTR szEnd;
  1449. std::vector<MPC::wstring> vec;
  1450. //
  1451. // Skip comments.
  1452. //
  1453. if(szLine[0] == '#') return false;
  1454. if((szEnd = strchr( szLine, '\r' ))) szEnd[0] = 0;
  1455. if((szEnd = strchr( szLine, '\n' ))) szEnd[0] = 0;
  1456. MPC::SplitAtDelimiter( vec, A2W( szLine ), L" ", /*fDelimIsAString*/false, /*fSkipAdjacentDelims*/true );
  1457. if(vec.size() != 6) return false;
  1458. si.m_strName = vec[0];
  1459. si.m_strCabinet = vec[1];
  1460. si.m_strProdFilt = vec[2];
  1461. si.m_fDesktop = LookupBoolean( vec[3].c_str() );
  1462. si.m_fServer = LookupBoolean( vec[4].c_str() );
  1463. si.m_fEmbedded = LookupBoolean( vec[5].c_str() );
  1464. return true;
  1465. }
  1466. static bool GetSetupImageFile( /*[in ]*/ SkuInformationList& sil ,
  1467. /*[in ]*/ LPCWSTR szSKU ,
  1468. /*[out]*/ MPC::wstring& strCabinet ,
  1469. /*[out]*/ Taxonomy::InstanceBase& data )
  1470. {
  1471. if(!_wcsicmp( szSKU, L"NONE" ))
  1472. {
  1473. strCabinet = L"none.cab";
  1474. data.m_fDesktop = false;
  1475. data.m_fServer = false;
  1476. data.m_fEmbedded = false;
  1477. return true;
  1478. }
  1479. for(SkuInformationIter it=sil.begin(); it!=sil.end(); it++)
  1480. {
  1481. if(!_wcsicmp( szSKU, it->m_strName.c_str() ))
  1482. {
  1483. strCabinet = it->m_strCabinet;
  1484. data.m_fDesktop = it->m_fDesktop ;
  1485. data.m_fServer = it->m_fServer ;
  1486. data.m_fEmbedded = it->m_fEmbedded ;
  1487. return true;
  1488. }
  1489. }
  1490. return false;
  1491. }
  1492. static HRESULT OpenFile( /*[in ]*/ const MPC::wstring& strFile ,
  1493. /*[out]*/ FILE*& fh )
  1494. {
  1495. __HCP_FUNC_ENTRY( "OpenFile" );
  1496. HRESULT hr;
  1497. fh = _wfopen( strFile.c_str(), L"r" );
  1498. if(fh == NULL)
  1499. {
  1500. DWORD dwRes = ::GetLastError();
  1501. l_FileLog.LogRecord( L"%08x: Can't open file '%s'", HRESULT_FROM_WIN32(dwRes), strFile.c_str() );
  1502. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  1503. }
  1504. hr = S_OK;
  1505. __HCP_FUNC_CLEANUP;
  1506. __HCP_FUNC_EXIT(hr);
  1507. }
  1508. ////////////////////////////////////////
  1509. static HRESULT Index_SAVE( /*[in]*/ const MPC::wstring& strRoot ,
  1510. /*[in]*/ PostBuildList& pbl ,
  1511. /*[in]*/ SkuInformationList& sil )
  1512. {
  1513. __HCP_FUNC_ENTRY( "Index_SAVE" );
  1514. HRESULT hr;
  1515. MPC::wstring strFileOut;
  1516. HANDLE hFile = NULL;
  1517. strFileOut = strRoot;
  1518. strFileOut += c_szNTTREE_INDEX;
  1519. //
  1520. // Create the new file.
  1521. //
  1522. __MPC_EXIT_IF_INVALID_HANDLE__CLEAN(hr, hFile, ::CreateFileW( strFileOut.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ));
  1523. //
  1524. // Dump to file.
  1525. //
  1526. {
  1527. MPC::Serializer_File streamReal( hFile );
  1528. MPC::Serializer_Buffering streamBuf ( streamReal );
  1529. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << c_dwVersion );
  1530. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << strRoot );
  1531. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << pbl );
  1532. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << sil );
  1533. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf.Flush());
  1534. }
  1535. hr = S_OK;
  1536. __HCP_FUNC_CLEANUP;
  1537. if(hFile) ::CloseHandle( hFile );
  1538. __HCP_FUNC_EXIT(hr);
  1539. }
  1540. static HRESULT Index_LOAD( /*[in]*/ const MPC::wstring& strRoot ,
  1541. /*[in]*/ PostBuildList& pbl ,
  1542. /*[in]*/ SkuInformationList& sil )
  1543. {
  1544. __HCP_FUNC_ENTRY( "Index_LOAD" );
  1545. HRESULT hr;
  1546. MPC::wstring strFileOut;
  1547. HANDLE hFile = NULL;
  1548. strFileOut = strRoot;
  1549. strFileOut += c_szNTTREE_INDEX;
  1550. pbl.clear();
  1551. __MPC_EXIT_IF_INVALID_HANDLE__CLEAN(hr, hFile, ::CreateFileW( strFileOut.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ));
  1552. {
  1553. MPC::Serializer_File streamReal( hFile );
  1554. MPC::Serializer_Buffering streamBuf ( streamReal );
  1555. MPC::wstring strRootOld;
  1556. DWORD dwVer;
  1557. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> dwVer ); if(dwVer != c_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  1558. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> strRootOld );
  1559. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> pbl );
  1560. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> sil );
  1561. if(strRootOld != strRoot)
  1562. {
  1563. for(PostBuildIter it=pbl.begin(); it!=pbl.end(); it++)
  1564. {
  1565. it->FixRoot( strRootOld, strRoot );
  1566. }
  1567. }
  1568. }
  1569. hr = S_OK;
  1570. __HCP_FUNC_CLEANUP;
  1571. if(hFile) ::CloseHandle( hFile );
  1572. __HCP_FUNC_EXIT(hr);
  1573. }
  1574. ////////////////////////////////////////
  1575. static HRESULT Binplace( /*[in]*/ LPCWSTR szSKUList ,
  1576. /*[in]*/ LPCWSTR szFileList ,
  1577. /*[in]*/ LPCWSTR szRoot ,
  1578. /*[in]*/ LPCWSTR szObject )
  1579. {
  1580. __HCP_FUNC_ENTRY( "Binplace" );
  1581. HRESULT hr;
  1582. FILE* in = NULL;
  1583. char buf[1024];
  1584. MPC::wstring strFileList;
  1585. MPC::wstring strRoot;
  1586. PostBuildList pbl;
  1587. SkuInformationList sil;
  1588. strFileList = szFileList;
  1589. MPC::SubstituteEnvVariables( strFileList );
  1590. strRoot = szRoot;
  1591. strRoot += L"\\";
  1592. strRoot += c_szNTTREE_BASE;
  1593. strRoot += L"\\";
  1594. MPC::SubstituteEnvVariables( strRoot );
  1595. l_FileLog.LogRecord( L"\n==================\n"
  1596. L"BINPLACE - start\n\n" );
  1597. ////////////////////////////////////////
  1598. ::SetEnvironmentVariableW( L"OBJECTDIR", szObject );
  1599. {
  1600. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, OpenFile( szSKUList, in ));
  1601. while(fgets( buf, 1024, in ))
  1602. {
  1603. SkuInformation si;
  1604. if(ParseFile( buf, si ))
  1605. {
  1606. sil.push_back( si );
  1607. l_FileLog.LogRecord( L"Found SKU: %-30s %-15s %-15s %s%s%s" ,
  1608. si.m_strName .c_str() ,
  1609. si.m_strCabinet .c_str() ,
  1610. si.m_strProdFilt.c_str() ,
  1611. si.m_fDesktop ? L"DESKTOP " : L"" ,
  1612. si.m_fServer ? L"SERVER " : L"" ,
  1613. si.m_fEmbedded ? L"EMBEDDED " : L"" );
  1614. }
  1615. }
  1616. fclose( in ); in = NULL;
  1617. l_FileLog.LogRecord( L"\n" );
  1618. }
  1619. {
  1620. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( strRoot.c_str() ));
  1621. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, OpenFile( strFileList, in ));
  1622. while(fgets( buf, 1024, in ))
  1623. {
  1624. SetupImageEntry en;
  1625. if(ParseFile( buf, en ))
  1626. {
  1627. PostBuildEntry& pbe = *( pbl.insert( pbl.end() ) );
  1628. MPC::SubstituteEnvVariables( en.m_strSourceFile );
  1629. pbe.m_entry = en;
  1630. //
  1631. // This copies the file if newer.
  1632. //
  1633. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_entry.Import( pbe, strRoot ));
  1634. if(!MPC::StrICmp( en.m_strLocalization, L"HHT" ))
  1635. {
  1636. //
  1637. // Expand the cabinet and process the HHTs.
  1638. //
  1639. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_package.Import( pbe, strRoot ));
  1640. pbe.m_pbt = POSTBUILDTYPE_HHT;
  1641. }
  1642. else if(!MPC::StrICmp( en.m_strLocalization, L"SAF" ))
  1643. {
  1644. //
  1645. // Expand the cabinet and process the channel.
  1646. //
  1647. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_package.Import( pbe, strRoot ));
  1648. pbe.m_pbt = POSTBUILDTYPE_SAF;
  1649. }
  1650. else
  1651. {
  1652. pbe.m_pbt = POSTBUILDTYPE_NORMAL;
  1653. }
  1654. }
  1655. }
  1656. fclose( in ); in = NULL;
  1657. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, Index_SAVE( strRoot, pbl, sil ));
  1658. }
  1659. ////////////////////////////////////////
  1660. hr = S_OK;
  1661. __HCP_FUNC_CLEANUP;
  1662. l_FileLog.LogRecord( L"\nBINPLACE - done\n"
  1663. L"=================\n\n" );
  1664. if(in) fclose( in );
  1665. __HCP_FUNC_EXIT(hr);
  1666. }
  1667. static HRESULT Compile( /*[in]*/ LPCWSTR szRoot ,
  1668. /*[in]*/ LPCWSTR szSKU )
  1669. {
  1670. __HCP_FUNC_ENTRY( "Compile" );
  1671. HRESULT hr;
  1672. Installer::Package pkg;
  1673. Taxonomy::InstanceBase& data = pkg.GetData();
  1674. MPC::wstring strRoot;
  1675. MPC::wstring strCabinet;
  1676. MPC::wstring strFullPath;
  1677. PostBuildList pbl;
  1678. SkuInformationList sil;
  1679. DATE dFile_SetupImage;
  1680. bool fNew = false;
  1681. l_FileLog.LogRecord( L"\n==================\n"
  1682. L"COMPILE - start\n\n" );
  1683. ////////////////////////////////////////
  1684. strRoot = szRoot;
  1685. strRoot += L"\\";
  1686. strRoot += c_szNTTREE_BASE;
  1687. strRoot += L"\\";
  1688. MPC::SubstituteEnvVariables( strRoot );
  1689. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, Index_LOAD( strRoot, pbl, sil ));
  1690. if(GetSetupImageFile( sil, szSKU, strCabinet, data ) == false)
  1691. {
  1692. l_FileLog.LogRecord( L"'%s' is not a valid SKU name!\n\n", szSKU );
  1693. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  1694. }
  1695. strFullPath = szRoot;
  1696. strFullPath += L"\\";
  1697. strFullPath += c_szNTTREE_BASE;
  1698. strFullPath += L"\\";
  1699. strFullPath += strCabinet;
  1700. MPC::SubstituteEnvVariables( strFullPath );
  1701. dFile_SetupImage = MPC::GetLastModifiedDate( strFullPath );
  1702. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( strFullPath.c_str() ));
  1703. for(PostBuildIter itPB=pbl.begin(); itPB!=pbl.end(); itPB++)
  1704. {
  1705. PostBuildEntry& pbe = *itPB;
  1706. if(MPC::StrICmp( pbe.m_entry.m_strSKU, L"All" ) == 0 ||
  1707. MPC::StrICmp( pbe.m_entry.m_strSKU, szSKU ) == 0 )
  1708. {
  1709. Installer::Iter itFile = pkg.NewFile();
  1710. MPC::wstring strFileSrc = pbe.m_entry.m_strTemporaryFullPath;
  1711. MPC::wstring strFileDst = pbe.m_entry.m_strDestinationDir; strFileDst += L"\\"; strFileDst += pbe.m_entry.m_strDestinationName;
  1712. __MPC_EXIT_IF_METHOD_FAILS(hr, itFile->SetPurpose( pbe.m_entry.m_strPurpose.c_str() ));
  1713. itFile->m_strFileLocal = strFileSrc;
  1714. itFile->m_strFileInner = pbe.m_entry.m_strTemporaryName;
  1715. itFile->m_strFileLocation = strFileDst;
  1716. if(pbe.m_pbt == POSTBUILDTYPE_HHT ||
  1717. pbe.m_pbt == POSTBUILDTYPE_SAF )
  1718. {
  1719. LOG__MPC_EXIT_IF_METHOD_FAILS(hr, pbe.m_package.Export( pbe, strRoot ));
  1720. itFile->m_strFileLocal = (pbe.m_pbt == POSTBUILDTYPE_SAF) ? pbe.m_package.m_strNew_Cabinet : pbe.m_package.m_strNew_Database;
  1721. }
  1722. if(pbe.m_pbt == POSTBUILDTYPE_HHT)
  1723. {
  1724. data.m_ths.m_strSKU = pbe.m_package.m_DB_strSKU;
  1725. data.m_ths.m_lLCID = pbe.m_package.m_DB_lLCID;
  1726. data.m_strDisplayName = pbe.m_package.m_DB_strDisplayName;
  1727. data.m_strProductID = L"Windows_XP";
  1728. data.m_strVersion = L"1.0.0.0";
  1729. }
  1730. if(FAILED(hr = itFile->UpdateSignature()))
  1731. {
  1732. l_FileLog.LogRecord( L"%08x: Can't locate '%s'\n", hr, strFileSrc.c_str() );
  1733. __HCP_FUNC_LEAVE;
  1734. }
  1735. if(MPC::GetLastModifiedDate( itFile->m_strFileLocal ) > dFile_SetupImage) fNew = true;
  1736. }
  1737. }
  1738. if(fNew)
  1739. {
  1740. l_FileLog.LogRecord( L"Create setup image '%s'", strFullPath.c_str() );
  1741. //
  1742. // Create the output cabinet.
  1743. //
  1744. if(FAILED(hr = pkg.Save()))
  1745. {
  1746. l_FileLog.LogRecord( L"%08x: Can't create output file '%s'\n", strFullPath.c_str() );
  1747. __HCP_FUNC_LEAVE;
  1748. }
  1749. }
  1750. hr = S_OK;
  1751. __HCP_FUNC_CLEANUP;
  1752. l_FileLog.LogRecord( L"\nCOMPILE - done\n"
  1753. L"=================\n\n" );
  1754. __HCP_FUNC_EXIT(hr);
  1755. }
  1756. static HRESULT List( /*[in]*/ LPCWSTR szInput )
  1757. {
  1758. __HCP_FUNC_ENTRY( "List" );
  1759. HRESULT hr;
  1760. Installer::Package pkg;
  1761. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
  1762. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load());
  1763. {
  1764. Installer::Iter itBegin = pkg.GetBegin();
  1765. Installer::Iter itEnd = pkg.GetEnd ();
  1766. for(;itBegin != itEnd; itBegin++)
  1767. {
  1768. wprintf( L"%s -> %s\n", itBegin->m_strFileInner.c_str(), itBegin->m_strFileLocation.c_str() );
  1769. }
  1770. }
  1771. hr = S_OK;
  1772. __HCP_FUNC_CLEANUP;
  1773. __HCP_FUNC_EXIT(hr);
  1774. }
  1775. static HRESULT Extract( /*[in]*/ LPCWSTR szInput ,
  1776. /*[in]*/ LPCWSTR szFile )
  1777. {
  1778. __HCP_FUNC_ENTRY( "Extract" );
  1779. HRESULT hr;
  1780. Installer::Package pkg;
  1781. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
  1782. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load());
  1783. {
  1784. Installer::Iter itBegin = pkg.GetBegin();
  1785. Installer::Iter itEnd = pkg.GetEnd ();
  1786. for(;itBegin != itEnd; itBegin++)
  1787. {
  1788. if(!MPC::StrICmp( itBegin->m_strFileInner, szFile ))
  1789. {
  1790. itBegin->m_strFileLocal = szFile; // Extract the file in the current directory.
  1791. __MPC_EXIT_IF_METHOD_FAILS(hr, itBegin->Extract( szInput ));
  1792. break;
  1793. }
  1794. }
  1795. }
  1796. hr = S_OK;
  1797. __HCP_FUNC_CLEANUP;
  1798. __HCP_FUNC_EXIT(hr);
  1799. }
  1800. static HRESULT Install( /*[in]*/ LPCWSTR szInput )
  1801. {
  1802. __HCP_FUNC_ENTRY( "Install" );
  1803. HRESULT hr;
  1804. Installer::Package pkg;
  1805. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
  1806. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Install());
  1807. hr = S_OK;
  1808. __HCP_FUNC_CLEANUP;
  1809. __HCP_FUNC_EXIT(hr);
  1810. }
  1811. ////////////////////////////////////////////////////////////////////////////////
  1812. static HRESULT Unpack( /*[in]*/ LPCWSTR szInput ,
  1813. /*[in]*/ LPCWSTR szDir )
  1814. {
  1815. __HCP_FUNC_ENTRY( "Unpack" );
  1816. HRESULT hr;
  1817. Installer::Package pkg;
  1818. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szInput ));
  1819. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Unpack( szDir ));
  1820. hr = S_OK;
  1821. __HCP_FUNC_CLEANUP;
  1822. __HCP_FUNC_EXIT(hr);
  1823. }
  1824. static HRESULT Pack( /*[in]*/ LPCWSTR szDir ,
  1825. /*[in]*/ LPCWSTR szOutput )
  1826. {
  1827. __HCP_FUNC_ENTRY( "Pack" );
  1828. HRESULT hr;
  1829. Installer::Package pkg;
  1830. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( szOutput ));
  1831. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Pack( szDir ));
  1832. hr = S_OK;
  1833. __HCP_FUNC_CLEANUP;
  1834. __HCP_FUNC_EXIT(hr);
  1835. }
  1836. ////////////////////////////////////////////////////////////////////////////////
  1837. static HRESULT ProcessArguments( int argc ,
  1838. LPCWSTR argv[] )
  1839. {
  1840. __HCP_FUNC_ENTRY( "ProcessArguments" );
  1841. HRESULT hr;
  1842. argv++;
  1843. argc--;
  1844. while(argc-->0)
  1845. {
  1846. LPCWSTR szArg = *argv++;
  1847. int adv = -1;
  1848. if(szArg[0] == '-' ||
  1849. szArg[0] == '/' )
  1850. {
  1851. szArg++;
  1852. if(argc >= 1)
  1853. {
  1854. LPCWSTR szArg2 = argv[0];
  1855. if(!_wcsicmp( szArg, L"ROOT" )) { l_szRoot = szArg2 ; adv = 1; }
  1856. if(!_wcsicmp( szArg, L"LOG" )) { l_szLog = szArg2 ; adv = 1; }
  1857. if(!_wcsicmp( szArg, L"DBLOG" )) { l_szDBLog = szArg2 ; adv = 1; }
  1858. if(!_wcsicmp( szArg, L"MAXELEMENTS" )) { l_lMaxElements = _wtol( szArg2 ); adv = 1; }
  1859. }
  1860. }
  1861. else
  1862. {
  1863. {
  1864. MPC::wstring strLog;
  1865. GetLogFile( strLog );
  1866. l_FileLog.SetLocation( strLog.c_str() );
  1867. }
  1868. if(!_wcsicmp( szArg, L"BINPLACE" ) && argc >= 4) // <sku file> <setup image file> <root directory> <object directory>
  1869. {
  1870. __MPC_EXIT_IF_METHOD_FAILS(hr, Binplace( argv[0], argv[1], argv[2], argv[3] )); adv = 4;
  1871. }
  1872. else if(!_wcsicmp( szArg, L"COMPILE" ) && argc >= 2) // <root directory> <sku>
  1873. {
  1874. __MPC_EXIT_IF_METHOD_FAILS(hr, Compile( argv[0], argv[1] )); adv = 2;
  1875. }
  1876. else if(!_wcsicmp( szArg, L"LIST" ) && argc >= 1) // <input cabinet>
  1877. {
  1878. __MPC_EXIT_IF_METHOD_FAILS(hr, List( argv[0] )); adv = 2;
  1879. }
  1880. else if(!_wcsicmp( szArg, L"EXTRACT" ) && argc >= 2) // <input cabinet> <file>
  1881. {
  1882. __MPC_EXIT_IF_METHOD_FAILS(hr, Extract( argv[0], argv[1] )); adv = 2;
  1883. }
  1884. else if(!_wcsicmp( szArg, L"INSTALL" ) && argc >= 1) // <input cabinet>
  1885. {
  1886. __MPC_EXIT_IF_METHOD_FAILS(hr, Install( argv[0] )); adv = 1;
  1887. }
  1888. else if(!_wcsicmp( szArg, L"UNPACK" ) && argc >= 2) // <input cabinet> <directory>
  1889. {
  1890. __MPC_EXIT_IF_METHOD_FAILS(hr, Unpack( argv[0], argv[1] )); adv = 2;
  1891. }
  1892. else if(!_wcsicmp( szArg, L"PACK" ) && argc >= 2) // <directory> <output cabinet>
  1893. {
  1894. __MPC_EXIT_IF_METHOD_FAILS(hr, Pack( argv[0], argv[1] )); adv = 2;
  1895. }
  1896. }
  1897. if(adv == -1)
  1898. {
  1899. Usage(); __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  1900. }
  1901. argv += adv;
  1902. argc -= adv;
  1903. }
  1904. hr = S_OK;
  1905. __HCP_FUNC_CLEANUP;
  1906. __HCP_FUNC_EXIT(hr);
  1907. }
  1908. ////////////////////////////////////////////////////////////////////////////////
  1909. int __cdecl wmain( int argc ,
  1910. LPCWSTR argv[] )
  1911. {
  1912. HRESULT hr;
  1913. //DebugBreak();
  1914. //
  1915. // We need to be a single-threaded application, because we are hosting script engines and
  1916. // script engines don't like to be called from different threads...
  1917. //
  1918. if(SUCCEEDED(hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED )))
  1919. {
  1920. if(SUCCEEDED(hr = ::CoInitializeSecurity( NULL ,
  1921. -1 , // We don't care which authentication service we use.
  1922. NULL ,
  1923. NULL ,
  1924. RPC_C_AUTHN_LEVEL_CONNECT, // We want to identify the callers.
  1925. RPC_C_IMP_LEVEL_DELEGATE , // We want to be able to forward the caller's identity.
  1926. NULL ,
  1927. EOAC_DYNAMIC_CLOAKING , // Let's use the thread token for outbound calls.
  1928. NULL )))
  1929. {
  1930. __MPC_TRACE_INIT();
  1931. //
  1932. // Process arguments.
  1933. //
  1934. try
  1935. {
  1936. hr = ProcessArguments( argc, argv );
  1937. }
  1938. catch(...)
  1939. {
  1940. hr = E_FAIL;
  1941. }
  1942. __MPC_TRACE_TERM();
  1943. }
  1944. ::CoUninitialize();
  1945. }
  1946. return FAILED(hr) ? 10 : 0;
  1947. }