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.

1746 lines
56 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. SetOfHelpTopics.cpp
  5. Abstract:
  6. This file contains the implementation of the CPCHSetOfHelpTopics class,
  7. that models the set of help file for a particular SKU/Language pair.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 07/01/2000
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. #include <MergedHhk.h>
  14. #include <algorithm>
  15. static const WCHAR c_SetupImage [] = L"PCHDT_";
  16. static const WCHAR c_CabExtension [] = L".cab";
  17. static const WCHAR c_ListPrefix [] = L"[SourceDisksFiles]";
  18. static const WCHAR c_ListPrefixX86 [] = L"[SourceDisksFiles.x86]";
  19. static const WCHAR c_ListPrefixIA64[] = L"[SourceDisksFiles.";
  20. ////////////////////////////////////////////////////////////////////////////////
  21. static HRESULT Local_ParseLayoutInf( /*[in ]*/ LPCWSTR szFile ,
  22. /*[out]*/ MPC::WStringUCLookup* mapAll ,
  23. /*[out]*/ MPC::WStringUCLookup* mapX86 ,
  24. /*[out]*/ MPC::WStringUCLookup* mapIA64 )
  25. {
  26. __HCP_FUNC_ENTRY( "Local_ParseLayoutInf" );
  27. HRESULT hr;
  28. HHK::Reader* reader = NULL;
  29. MPC::wstring strLine;
  30. MPC::WStringUCLookup* mapActive = NULL;
  31. __MPC_EXIT_IF_ALLOC_FAILS(hr, reader, new HHK::Reader);
  32. __MPC_EXIT_IF_METHOD_FAILS(hr, reader->Init( szFile ));
  33. while(reader->GetLine( &strLine ))
  34. {
  35. LPCWSTR szPtr = strLine.c_str();
  36. if(szPtr[0] == '[')
  37. {
  38. if (!_wcsnicmp( szPtr, c_ListPrefix , MAXSTRLEN( c_ListPrefix ) )) mapActive = mapAll;
  39. else if(!_wcsnicmp( szPtr, c_ListPrefixX86 , MAXSTRLEN( c_ListPrefixX86 ) )) mapActive = mapX86;
  40. else if(!_wcsnicmp( szPtr, c_ListPrefixIA64, MAXSTRLEN( c_ListPrefixIA64 ) )) mapActive = mapIA64;
  41. else mapActive = NULL;
  42. }
  43. if(mapActive)
  44. {
  45. std::vector<MPC::wstring> vec1;
  46. //
  47. // <Source filename> = <diskid>,<subdir>,<size>,<checksum>,<spare>,<spare>,<bootmedia>,<targetdir>,<upgradedisp>,<cleandisp>,<targetname>
  48. //
  49. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SplitAtDelimiter( vec1, szPtr, L" \t", false, true ));
  50. if(vec1.size() >= 3)
  51. {
  52. std::vector<MPC::wstring> vec2;
  53. LPCWSTR szCDName = vec1[0].c_str();
  54. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SplitAtDelimiter( vec2, vec1[2].c_str(), L",", false, false ));
  55. if(vec2.size() >= 11)
  56. {
  57. (*mapActive)[vec2[10]] = szCDName;
  58. }
  59. else
  60. {
  61. (*mapActive)[szCDName] = szCDName;
  62. }
  63. }
  64. }
  65. }
  66. hr = S_OK;
  67. __HCP_FUNC_CLEANUP;
  68. delete reader;
  69. __HCP_FUNC_EXIT(hr);
  70. }
  71. ////////////////////////////////////////////////////////////////////////////////
  72. #define FAIL_IF_RUNNING() \
  73. { \
  74. if(Thread_IsRunning()) \
  75. { \
  76. switch(m_shtStatus) \
  77. { \
  78. case SHT_QUERIED : \
  79. case SHT_INSTALLED : \
  80. case SHT_UNINSTALLED: \
  81. case SHT_ABORTED : \
  82. case SHT_FAILED : \
  83. break; \
  84. \
  85. default: \
  86. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BUSY); \
  87. } \
  88. } \
  89. }
  90. #define EXIT_IF_ABORTED() \
  91. { \
  92. if(Thread_IsAborted()) \
  93. { \
  94. (void)put_Status( SHT_ABORTING, NULL ); \
  95. __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT); \
  96. } \
  97. }
  98. #define CHANGE_STATE(x,y) \
  99. { \
  100. EXIT_IF_ABORTED(); \
  101. __MPC_EXIT_IF_METHOD_FAILS(hr, put_Status( x, y )); \
  102. }
  103. #define CHECK_WRITE_PERMISSIONS() __MPC_EXIT_IF_METHOD_FAILS(hr, VerifyWritePermissions());
  104. ////////////////////////////////////////////////////////////////////////////////
  105. CPCHSetOfHelpTopics::CPCHSetOfHelpTopics()
  106. {
  107. // Taxonomy::Settings m_ts;
  108. // Taxonomy::Instance m_inst;
  109. // CComPtr<IDispatch> m_sink_onStatusChange;
  110. m_shtStatus = SHT_NOTACTIVE; // SHT_STATUS m_shtStatus;
  111. m_hrErrorCode = S_OK; // HRESULT m_hrErrorCode;
  112. m_fReadyForCommands = false; // bool m_fReadyForCommands;
  113. //
  114. // MPC::Impersonation m_imp;
  115. //
  116. m_fInstalled = false; // bool m_fInstalled;
  117. //
  118. m_fConnectedToDisk = false; // bool m_fConnectedToDisk;
  119. // MPC::wstring m_strDirectory;
  120. // MPC::wstring m_strCAB;
  121. // MPC::wstring m_strLocalCAB;
  122. //
  123. m_fConnectedToServer = false; // bool m_fConnectedToServer;
  124. // MPC::wstring m_strServer;
  125. // CComPtr<IPCHSetOfHelpTopics> m_sku;
  126. // CComPtr<IPCHService> m_svc;
  127. //
  128. m_fActAsCollection = false; // bool m_fActAsCollection;
  129. // CComPtr<CPCHCollection> m_coll;
  130. }
  131. CPCHSetOfHelpTopics::~CPCHSetOfHelpTopics()
  132. {
  133. (void)Close( true );
  134. }
  135. HRESULT CPCHSetOfHelpTopics::Close( /*[in]*/ bool fCleanup )
  136. {
  137. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Close" );
  138. HRESULT hr;
  139. //
  140. // Do the final cleanup.
  141. //
  142. if(fCleanup)
  143. {
  144. Thread_Wait();
  145. (void)MPC::RemoveTemporaryFile( m_strLocalCAB );
  146. m_fConnectedToDisk = false; // bool m_fConnectedToDisk;
  147. m_strDirectory = L""; // MPC::wstring m_strDirectory;
  148. m_strCAB = L""; // MPC::wstring m_strCAB;
  149. // MPC::wstring m_strLocalCAB;
  150. m_fConnectedToServer = false; // bool m_fConnectedToServer;
  151. m_strServer = L""; // MPC::wstring m_strServer;
  152. m_sku.Release(); // CComPtr<IPCHSetOfHelpTopics> m_sku;
  153. m_svc.Release(); // CComPtr<IPCHService> m_svc;
  154. }
  155. hr = S_OK;
  156. __HCP_FUNC_EXIT(hr);
  157. }
  158. void CPCHSetOfHelpTopics::CleanupWorkerThread( /*[in]*/ HRESULT hr )
  159. {
  160. (void)EndImpersonation();
  161. (void)Close( false );
  162. if(FAILED(hr))
  163. {
  164. m_hrErrorCode = hr;
  165. (void)put_Status( (hr == E_ABORT) ? SHT_ABORTED : SHT_FAILED, NULL );
  166. }
  167. (void)Thread_Abort();
  168. }
  169. HRESULT CPCHSetOfHelpTopics::PrepareSettings()
  170. {
  171. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::PrepareSettings" );
  172. HRESULT hr;
  173. m_ts = m_inst.m_ths;
  174. m_fReadyForCommands = true;
  175. hr = S_OK;
  176. __HCP_FUNC_EXIT(hr);
  177. }
  178. ////////////////////
  179. HRESULT CPCHSetOfHelpTopics::ImpersonateCaller()
  180. {
  181. return m_imp.Impersonate();
  182. }
  183. HRESULT CPCHSetOfHelpTopics::EndImpersonation()
  184. {
  185. return m_imp.RevertToSelf();
  186. }
  187. ////////////////////
  188. HRESULT CPCHSetOfHelpTopics::GetListOfFilesFromDatabase( /*[in]*/ const MPC::wstring& strDB ,
  189. /*[out]*/ MPC::WStringList& lst )
  190. {
  191. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::GetListOfFilesFromDatabase" );
  192. USES_CONVERSION;
  193. HRESULT hr;
  194. LPCSTR szDB = W2A( strDB.c_str() );
  195. JetBlue::SessionHandle sess;
  196. JetBlue::Database* db;
  197. Taxonomy::Updater updater;
  198. __MPC_EXIT_IF_METHOD_FAILS(hr, JetBlue::SessionPool::s_GLOBAL->GetSession( sess ));
  199. __MPC_EXIT_IF_METHOD_FAILS(hr, sess->GetDatabase( szDB, db, /*fCreate*/false, /*fRepair*/false, /*fReadOnly*/true ));
  200. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.Init( m_ts, db ));
  201. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.ListAllTheHelpFiles( lst ));
  202. hr = S_OK;
  203. __HCP_FUNC_CLEANUP;
  204. (void)updater.Close();
  205. sess.Release();
  206. JetBlue::SessionPool::s_GLOBAL->ReleaseDatabase( szDB );
  207. __HCP_FUNC_EXIT(hr);
  208. }
  209. ////////////////////////////////////////////////////////////////////////////////
  210. HRESULT CPCHSetOfHelpTopics::PopulateFromDisk( /*[in]*/ CPCHSetOfHelpTopics* pParent ,
  211. /*[in]*/ const MPC::wstring& strDirectory )
  212. {
  213. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::PopulateFromDisk" );
  214. HRESULT hr;
  215. __MPC_PARAMCHECK_BEGIN(hr)
  216. __MPC_PARAMCHECK_NOTNULL(pParent);
  217. __MPC_PARAMCHECK_END();
  218. __MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
  219. m_imp = pParent->m_imp;
  220. ////////////////////////////////////////
  221. m_fConnectedToDisk = true;
  222. m_strDirectory = strDirectory;
  223. ////////////////////////////////////////
  224. //
  225. // Find SKUs, recursively enumerating folders.
  226. //
  227. {
  228. MPC::wstring strLayout( m_strDirectory ); strLayout += L"\\layout.inf";
  229. MPC::WStringUCLookup mapLayout;
  230. MPC::WStringUCLookupIter itLayout;
  231. LPCWSTR szCAB_first = NULL;
  232. LPCWSTR szCAB_srv = NULL;
  233. EXIT_IF_ABORTED();
  234. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller ( ));
  235. __MPC_EXIT_IF_METHOD_FAILS(hr, Local_ParseLayoutInf( strLayout.c_str(), &mapLayout, NULL, NULL ));
  236. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation ( ));
  237. for(itLayout = mapLayout.begin(); itLayout != mapLayout.end(); itLayout++)
  238. {
  239. LPCWSTR szName = itLayout->first.c_str();
  240. if(!wcsncmp( szName, c_SetupImage, MAXSTRLEN(c_SetupImage) ))
  241. {
  242. LPCWSTR szFile = itLayout->second.c_str();
  243. if(!szCAB_first) szCAB_first = szFile;
  244. //
  245. // Special case for Server: it also contains the AdvancedServer stuff.
  246. //
  247. if(!wcscmp( szName, L"PCHDT_S3.CAB" )) szCAB_srv = szFile;
  248. if(!wcscmp( szName, L"PCHDT_S6.CAB" )) szCAB_srv = szFile;
  249. }
  250. }
  251. if(!szCAB_first)
  252. {
  253. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  254. }
  255. m_strCAB = m_strDirectory; m_strCAB += L"\\"; m_strCAB += (szCAB_srv ? szCAB_srv : szCAB_first);
  256. }
  257. //
  258. // Make a local copy of the data archive, using the user credentials.
  259. //
  260. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetTemporaryFileName ( m_strLocalCAB ));
  261. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::CopyOrExtractFileWhileImpersonating( m_strCAB.c_str(), m_strLocalCAB.c_str(), m_imp ));
  262. EXIT_IF_ABORTED();
  263. //
  264. // Extract the database to a temporary file.
  265. //
  266. {
  267. Installer::Package pkg;
  268. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( m_strLocalCAB.c_str() ));
  269. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load( ));
  270. __MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.InitializeFromBase( pkg.GetData(), /*fSystem*/false, /*fMUI*/false ));
  271. }
  272. EXIT_IF_ABORTED();
  273. ////////////////////////////////////////////////////////////////////////////////
  274. __MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
  275. m_shtStatus = SHT_QUERIED;
  276. hr = S_OK;
  277. __HCP_FUNC_CLEANUP;
  278. CleanupWorkerThread( hr );
  279. __HCP_FUNC_EXIT(hr);
  280. }
  281. HRESULT CPCHSetOfHelpTopics::PopulateFromServer( /*[in]*/ CPCHSetOfHelpTopics* pParent, /*[in]*/ IPCHSetOfHelpTopics* sku, /*[in]*/ IPCHService* svc )
  282. {
  283. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::PopulateFromServer" );
  284. HRESULT hr;
  285. MPC::SmartLock<_ThreadModel> lock( this );
  286. CComBSTR bstrDB_SKU;
  287. long lDB_LCID;
  288. CComBSTR bstrDB_DisplayName;
  289. __MPC_PARAMCHECK_BEGIN(hr)
  290. __MPC_PARAMCHECK_NOTNULL(pParent);
  291. __MPC_PARAMCHECK_NOTNULL(sku);
  292. __MPC_PARAMCHECK_NOTNULL(svc);
  293. __MPC_PARAMCHECK_END();
  294. __MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
  295. m_imp = pParent->m_imp;
  296. ////////////////////////////////////////
  297. m_fConnectedToServer = true;
  298. m_strServer = pParent->m_strServer;
  299. m_sku = sku;
  300. m_svc = svc;
  301. ////////////////////////////////////////////////////////////////////////////////
  302. __MPC_EXIT_IF_METHOD_FAILS(hr, sku->get_SKU ( &bstrDB_SKU ));
  303. __MPC_EXIT_IF_METHOD_FAILS(hr, sku->get_Language ( & lDB_LCID ));
  304. __MPC_EXIT_IF_METHOD_FAILS(hr, sku->get_DisplayName( &bstrDB_DisplayName ));
  305. m_inst.m_ths.m_strSKU = SAFEBSTR( bstrDB_SKU );
  306. m_inst.m_ths.m_lLCID = lDB_LCID ;
  307. m_inst.m_strDisplayName = SAFEBSTR( bstrDB_DisplayName );
  308. ////////////////////////////////////////////////////////////////////////////////
  309. __MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
  310. m_shtStatus = SHT_QUERIED;
  311. hr = S_OK;
  312. __HCP_FUNC_CLEANUP;
  313. CleanupWorkerThread( hr );
  314. __HCP_FUNC_EXIT(hr);
  315. }
  316. ////////////////////////////////////////////////////////////////////////////////
  317. HRESULT CPCHSetOfHelpTopics::VerifyWritePermissions()
  318. {
  319. return MPC::CheckCallerAgainstPrincipal( /*fImpersonate*/true, NULL, MPC::IDENTITY_SYSTEM |
  320. MPC::IDENTITY_ADMIN |
  321. MPC::IDENTITY_ADMINS |
  322. MPC::IDENTITY_POWERUSERS );
  323. }
  324. ////////////////////////////////////////////////////////////////////////////////
  325. HRESULT CPCHSetOfHelpTopics::RunInitFromDisk()
  326. {
  327. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunInitFromDisk" );
  328. HRESULT hr;
  329. MPC::WStringList lst;
  330. //
  331. // There's a possible race condition between the call to ConnectToDisk and the firing of the QUERIED event,
  332. // in case the directory doesn't exist at all: QUERIED is fired before the method returns a pointer to the object...
  333. //
  334. ::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST ); ::Sleep( 10 );
  335. __MPC_TRY_BEGIN();
  336. CHANGE_STATE( SHT_QUERYING, NULL );
  337. ////////////////////////////////////////////////////////////////////////////////
  338. lst.push_back( m_strDirectory );
  339. while(lst.size())
  340. {
  341. MPC::wstring strDir = lst.front(); lst.pop_front();
  342. //
  343. // Look for subfolders.
  344. //
  345. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
  346. {
  347. MPC::FileSystemObject fso( strDir.c_str() );
  348. MPC::FileSystemObject::List fso_lst;
  349. MPC::FileSystemObject::IterConst fso_it;
  350. if(SUCCEEDED(fso.Scan ( )) &&
  351. SUCCEEDED(fso.EnumerateFolders( fso_lst )) )
  352. {
  353. for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
  354. {
  355. MPC::wstring strSubFolder;
  356. if(SUCCEEDED((*fso_it)->get_Path( strSubFolder )))
  357. {
  358. lst.push_back( strSubFolder );
  359. }
  360. EXIT_IF_ABORTED();
  361. }
  362. }
  363. }
  364. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
  365. EXIT_IF_ABORTED();
  366. {
  367. CComPtr<CPCHSetOfHelpTopics> obj;
  368. //
  369. // Create an object to analyze the directory.
  370. //
  371. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  372. {
  373. CPCHSetOfHelpTopics* pObj = obj; // Working around ATL template problem...
  374. if(SUCCEEDED(pObj->PopulateFromDisk( this, strDir )))
  375. {
  376. __MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->AddItem( pObj ));
  377. CHANGE_STATE( SHT_QUERYING, NULL );
  378. }
  379. }
  380. }
  381. }
  382. EXIT_IF_ABORTED();
  383. ////////////////////////////////////////////////////////////////////////////////
  384. CHANGE_STATE( SHT_QUERIED, NULL );
  385. hr = S_OK;
  386. __HCP_FUNC_CLEANUP;
  387. __MPC_TRY_CATCHALL(hr);
  388. CleanupWorkerThread( hr );
  389. __HCP_FUNC_EXIT(hr);
  390. }
  391. HRESULT CPCHSetOfHelpTopics::RunInitFromServer()
  392. {
  393. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunInitFromServer" );
  394. HRESULT hr;
  395. IPCHService* svc;
  396. COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
  397. MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
  398. CComPtr<IPCHCollection> serverSKUs;
  399. //
  400. // There's a possible race condition between the call to ConnectToServer and the firing of the QUERIED event,
  401. // in case the server doesn't exist at all: QUERIED is fired before the method returns a pointer to the object...
  402. //
  403. ::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST ); ::Sleep( 10 );
  404. __MPC_TRY_BEGIN();
  405. CHANGE_STATE( SHT_QUERYING, NULL );
  406. ////////////////////////////////////////
  407. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
  408. si.pwszName = (LPWSTR)m_strServer.c_str();
  409. qi.pIID = &IID_IPCHService;
  410. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
  411. __MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
  412. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
  413. ////////////////////////////////////////
  414. svc = (IPCHService*)qi.pItf;
  415. __MPC_EXIT_IF_METHOD_FAILS(hr, svc->get_RemoteSKUs( &serverSKUs ));
  416. //
  417. // Copy the items in the remote collection.
  418. //
  419. {
  420. long lCount;
  421. long lPos;
  422. __MPC_EXIT_IF_METHOD_FAILS(hr, serverSKUs->get_Count( &lCount ));
  423. for(lPos=1; lPos<=lCount; lPos++)
  424. {
  425. CComVariant v;
  426. CComPtr<IPCHSetOfHelpTopics> sku;
  427. CComPtr<CPCHSetOfHelpTopics> obj;
  428. __MPC_EXIT_IF_METHOD_FAILS(hr, serverSKUs->get_Item( lPos, &v ));
  429. __MPC_EXIT_IF_METHOD_FAILS(hr, v.ChangeType( VT_DISPATCH ));
  430. __MPC_EXIT_IF_METHOD_FAILS(hr, v.pdispVal->QueryInterface( IID_IPCHSetOfHelpTopics, (LPVOID*)&sku ));
  431. //
  432. // Make a proxy of the remote SKU.
  433. //
  434. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  435. {
  436. CPCHSetOfHelpTopics* pObj = obj; // Working around ATL template problem...
  437. __MPC_EXIT_IF_METHOD_FAILS(hr, pObj->PopulateFromServer( this, sku, svc ));
  438. __MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->AddItem( pObj ));
  439. CHANGE_STATE( SHT_QUERYING, NULL );
  440. }
  441. }
  442. }
  443. ////////////////////////////////////////////////////////////////////////////////
  444. CHANGE_STATE( SHT_QUERIED, NULL );
  445. hr = S_OK;
  446. __HCP_FUNC_CLEANUP;
  447. __MPC_TRY_CATCHALL(hr);
  448. MPC::Release( qi.pItf );
  449. CleanupWorkerThread( hr );
  450. __HCP_FUNC_EXIT(hr);
  451. }
  452. ////////////////////
  453. HRESULT CPCHSetOfHelpTopics::RunInstall()
  454. {
  455. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunInstall" );
  456. HRESULT hr;
  457. Installer::Package pkg;
  458. __MPC_TRY_BEGIN();
  459. CHANGE_STATE( SHT_COPYING_DB, NULL );
  460. ////////////////////////////////////////////////////////////////////////////////
  461. //
  462. // Phase Zero: get the database.
  463. //
  464. if(m_fConnectedToServer)
  465. {
  466. CComPtr<IPCHRemoteHelpContents> rhc;
  467. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetTemporaryFileName( m_strLocalCAB ));
  468. __MPC_EXIT_IF_METHOD_FAILS(hr, m_svc->RemoteHelpContents( CComBSTR( m_inst.m_ths.GetSKU() ), m_inst.m_ths.GetLanguage(), &rhc ));
  469. if(rhc == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  470. //
  471. // Get the data archive.
  472. //
  473. {
  474. CComPtr<IUnknown> unkSrc;
  475. CComQIPtr<IStream> streamSrc;
  476. CComPtr<IStream> streamDst;
  477. __MPC_EXIT_IF_METHOD_FAILS(hr, rhc->GetDatabase( &unkSrc )); streamSrc = unkSrc;
  478. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForWrite( m_strLocalCAB.c_str(), &streamDst ));
  479. EXIT_IF_ABORTED();
  480. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( streamSrc, streamDst ));
  481. EXIT_IF_ABORTED();
  482. }
  483. EXIT_IF_ABORTED();
  484. }
  485. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( m_strLocalCAB.c_str() ));
  486. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load( ));
  487. __MPC_EXIT_IF_METHOD_FAILS(hr, DirectInstall( pkg, /*fSetup*/false, /*fSystem*/false, /*fMUI*/false ));
  488. hr = S_OK;
  489. __HCP_FUNC_CLEANUP;
  490. __MPC_TRY_CATCHALL(hr);
  491. CleanupWorkerThread( hr );
  492. //
  493. // In case of failure, remote everything...
  494. //
  495. if(FAILED(hr))
  496. {
  497. (void)DirectUninstall();
  498. }
  499. __HCP_FUNC_EXIT(hr);
  500. }
  501. HRESULT CPCHSetOfHelpTopics::RunUninstall()
  502. {
  503. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunUninstall" );
  504. HRESULT hr;
  505. __MPC_TRY_BEGIN();
  506. CHANGE_STATE( SHT_UNINSTALLING, NULL );
  507. __MPC_EXIT_IF_METHOD_FAILS(hr, DirectUninstall());
  508. CHANGE_STATE( SHT_UNINSTALLED, NULL );
  509. hr = S_OK;
  510. __HCP_FUNC_CLEANUP;
  511. __MPC_TRY_CATCHALL(hr);
  512. CleanupWorkerThread( hr );
  513. __HCP_FUNC_EXIT(hr);
  514. }
  515. ////////////////////////////////////////
  516. HRESULT CPCHSetOfHelpTopics::Fire_onStatusChange( IPCHSetOfHelpTopics* obj, SHT_STATUS lStatus, long hrErrorCode, BSTR bstrFile )
  517. {
  518. CComPtr<IDispatch> func;
  519. CComVariant pvars[4];
  520. //
  521. // Only lock this!
  522. //
  523. {
  524. MPC::SmartLock<_ThreadModel> lock( this );
  525. func = m_sink_onStatusChange;
  526. }
  527. pvars[3] = obj;
  528. pvars[2] = lStatus;
  529. pvars[1] = hrErrorCode;
  530. pvars[0] = bstrFile;
  531. return FireAsync_Generic( DISPID_PCH_SHTE__ONSTATUSCHANGE, pvars, ARRAYSIZE( pvars ), func );
  532. }
  533. HRESULT CPCHSetOfHelpTopics::put_Status( /*[in]*/ SHT_STATUS newVal, /*[in]*/ BSTR bstrFile )
  534. {
  535. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::put_Status" );
  536. HRESULT hr;
  537. long hrErrorCode;
  538. MPC::SmartLock<_ThreadModel> lock( this );
  539. m_shtStatus = newVal;
  540. hrErrorCode = m_hrErrorCode;
  541. lock = NULL; // Unlock before firing events.
  542. __MPC_EXIT_IF_METHOD_FAILS(hr, Fire_onStatusChange( this, newVal, hrErrorCode, bstrFile ));
  543. hr = S_OK;
  544. __HCP_FUNC_CLEANUP;
  545. __HCP_FUNC_EXIT(hr);
  546. }
  547. ////////////////////
  548. HRESULT CPCHSetOfHelpTopics::Init( /*[in]*/ const Taxonomy::Instance& inst )
  549. {
  550. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Init" );
  551. HRESULT hr;
  552. MPC::SmartLock<_ThreadModel> lock( this );
  553. __MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
  554. ////////////////////////////////////////
  555. m_fInstalled = true;
  556. m_inst = inst;
  557. m_shtStatus = SHT_INSTALLED;
  558. __MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
  559. hr = S_OK;
  560. __HCP_FUNC_CLEANUP;
  561. CleanupWorkerThread( hr );
  562. __HCP_FUNC_EXIT(hr);
  563. }
  564. HRESULT CPCHSetOfHelpTopics::InitFromDisk( /*[in]*/ LPCWSTR szDirectory, /*[in]*/ CPCHCollection* pColl )
  565. {
  566. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::InitFromDisk" );
  567. HRESULT hr;
  568. MPC::SmartLock<_ThreadModel> lock( NULL );
  569. __MPC_PARAMCHECK_BEGIN(hr)
  570. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szDirectory);
  571. __MPC_PARAMCHECK_NOTNULL(pColl);
  572. __MPC_PARAMCHECK_END();
  573. Thread_Wait(); lock = this;
  574. __MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
  575. __MPC_EXIT_IF_METHOD_FAILS(hr, m_imp.Initialize());
  576. ////////////////////////////////////////
  577. m_fActAsCollection = true;
  578. m_coll = pColl;
  579. m_strDirectory = szDirectory;
  580. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunInitFromDisk, NULL ));
  581. hr = S_OK;
  582. __HCP_FUNC_CLEANUP;
  583. __HCP_FUNC_EXIT(hr);
  584. }
  585. HRESULT CPCHSetOfHelpTopics::InitFromServer( /*[in]*/ LPCWSTR szServerName, /*[in]*/ CPCHCollection* pColl )
  586. {
  587. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::InitFromServer" );
  588. HRESULT hr;
  589. MPC::SmartLock<_ThreadModel> lock( NULL );
  590. __MPC_PARAMCHECK_BEGIN(hr)
  591. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szServerName);
  592. __MPC_PARAMCHECK_NOTNULL(pColl);
  593. __MPC_PARAMCHECK_END();
  594. Thread_Wait(); lock = this;
  595. __MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
  596. __MPC_EXIT_IF_METHOD_FAILS(hr, m_imp.Initialize());
  597. ////////////////////////////////////////
  598. m_fActAsCollection = true;
  599. m_coll = pColl;
  600. m_strServer = szServerName;
  601. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunInitFromServer, NULL ));
  602. hr = S_OK;
  603. __HCP_FUNC_CLEANUP;
  604. __HCP_FUNC_EXIT(hr);
  605. }
  606. ////////////////////////////////////////////////////////////////////////////////
  607. STDMETHODIMP CPCHSetOfHelpTopics::get_SKU( /*[out, retval]*/ BSTR *pVal )
  608. {
  609. __HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_SKU",hr,pVal);
  610. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_ths.m_strSKU.c_str(), pVal ));
  611. __HCP_END_PROPERTY(hr);
  612. }
  613. STDMETHODIMP CPCHSetOfHelpTopics::get_Language( /*[out, retval]*/ long *pVal )
  614. {
  615. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_Language",hr,pVal,m_inst.m_ths.GetLanguage());
  616. __HCP_END_PROPERTY(hr);
  617. }
  618. STDMETHODIMP CPCHSetOfHelpTopics::get_DisplayName( /*[out, retval]*/ BSTR *pVal )
  619. {
  620. __HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_DisplayName",hr,pVal);
  621. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strDisplayName.c_str(), pVal ));
  622. __HCP_END_PROPERTY(hr);
  623. }
  624. STDMETHODIMP CPCHSetOfHelpTopics::get_ProductID( /*[out, retval]*/ BSTR *pVal )
  625. {
  626. __HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_ProductID",hr,pVal);
  627. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strProductID.c_str(), pVal ));
  628. __HCP_END_PROPERTY(hr);
  629. }
  630. STDMETHODIMP CPCHSetOfHelpTopics::get_Version( /*[out, retval]*/ BSTR *pVal )
  631. {
  632. __HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_Version",hr,pVal);
  633. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strVersion.c_str(), pVal ));
  634. __HCP_END_PROPERTY(hr);
  635. }
  636. ////////////////////////////////////////
  637. STDMETHODIMP CPCHSetOfHelpTopics::get_Location( /*[out, retval]*/ BSTR *pVal )
  638. {
  639. __HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_Location",hr,pVal);
  640. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strHelpFiles.c_str(), pVal ));
  641. __HCP_END_PROPERTY(hr);
  642. }
  643. ////////////////////////////////////////
  644. STDMETHODIMP CPCHSetOfHelpTopics::get_Exported( /*[out, retval]*/ VARIANT_BOOL *pVal )
  645. {
  646. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_Exported",hr,pVal,m_inst.m_fExported);
  647. __HCP_END_PROPERTY(hr);
  648. }
  649. STDMETHODIMP CPCHSetOfHelpTopics::put_Exported( /*[in]*/ VARIANT_BOOL newVal )
  650. {
  651. __HCP_BEGIN_PROPERTY_PUT("CPCHSetOfHelpTopics::put_Exported",hr);
  652. CHECK_WRITE_PERMISSIONS();
  653. FAIL_IF_RUNNING();
  654. m_inst.m_fExported = (newVal == VARIANT_TRUE);
  655. if(m_fInstalled)
  656. {
  657. Taxonomy::LockingHandle handle;
  658. Taxonomy::InstalledInstanceIter it;
  659. bool fFound;
  660. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  661. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_inst.m_ths, fFound, it ));
  662. if(fFound)
  663. {
  664. it->m_inst.m_fExported = m_inst.m_fExported;
  665. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Updated( it ));
  666. }
  667. }
  668. __HCP_END_PROPERTY(hr);
  669. }
  670. ////////////////////////////////////////
  671. STDMETHODIMP CPCHSetOfHelpTopics::put_onStatusChange( /*[in]*/ IDispatch* function )
  672. {
  673. __HCP_BEGIN_PROPERTY_PUT("CPCHSetOfHelpTopics::put_onStatusChange",hr);
  674. m_sink_onStatusChange = function;
  675. __HCP_END_PROPERTY(hr);
  676. }
  677. STDMETHODIMP CPCHSetOfHelpTopics::get_Status( /*[out, retval]*/ SHT_STATUS *pVal )
  678. {
  679. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_Status",hr,pVal,m_shtStatus);
  680. __HCP_END_PROPERTY(hr);
  681. }
  682. STDMETHODIMP CPCHSetOfHelpTopics::get_ErrorCode( /*[out, retval]*/ long *pVal )
  683. {
  684. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_ErrorCode",hr,pVal,m_hrErrorCode);
  685. __HCP_END_PROPERTY(hr);
  686. }
  687. ////////////////////////////////////////
  688. STDMETHODIMP CPCHSetOfHelpTopics::get_IsMachineHelp( /*[out, retval]*/ VARIANT_BOOL *pVal )
  689. {
  690. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_IsMachineHelp",hr,pVal,VARIANT_FALSE);
  691. if(m_fReadyForCommands)
  692. {
  693. if(m_ts.IsMachineHelp())
  694. {
  695. *pVal = VARIANT_TRUE;
  696. }
  697. }
  698. __HCP_END_PROPERTY(hr);
  699. }
  700. STDMETHODIMP CPCHSetOfHelpTopics::get_IsInstalled( /*[out, retval]*/ VARIANT_BOOL *pVal )
  701. {
  702. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_IsInstalled",hr,pVal,VARIANT_FALSE);
  703. if(m_fReadyForCommands)
  704. {
  705. Taxonomy::LockingHandle handle;
  706. Taxonomy::InstalledInstanceIter it;
  707. bool fFound;
  708. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  709. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_inst.m_ths, fFound, it ));
  710. if(fFound)
  711. {
  712. *pVal = VARIANT_TRUE;
  713. }
  714. }
  715. __HCP_END_PROPERTY(hr);
  716. }
  717. STDMETHODIMP CPCHSetOfHelpTopics::get_CanInstall( /*[out, retval]*/ VARIANT_BOOL *pVal )
  718. {
  719. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_CanInstall",hr,pVal,VARIANT_FALSE);
  720. if(m_fReadyForCommands && SUCCEEDED(VerifyWritePermissions()))
  721. {
  722. Taxonomy::LockingHandle handle;
  723. Taxonomy::InstalledInstanceIter it;
  724. bool fFound;
  725. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  726. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_inst.m_ths, fFound, it ));
  727. //
  728. // You can install a SKU only if it's not already installed...
  729. //
  730. if(fFound == false)
  731. {
  732. *pVal = VARIANT_TRUE;
  733. }
  734. }
  735. __HCP_END_PROPERTY(hr);
  736. }
  737. STDMETHODIMP CPCHSetOfHelpTopics::get_CanUninstall( /*[out, retval]*/ VARIANT_BOOL *pVal )
  738. {
  739. __HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_CanUninstall",hr,pVal,VARIANT_FALSE);
  740. if(m_fReadyForCommands && SUCCEEDED(VerifyWritePermissions()))
  741. {
  742. //
  743. // You can only uninstall a SKU that is installed.
  744. //
  745. if(m_fInstalled)
  746. {
  747. Taxonomy::LockingHandle handle;
  748. Taxonomy::InstalledInstanceIter it;
  749. bool fFound;
  750. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  751. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_ts, fFound, it ));
  752. //
  753. // You cannot uninstall a SKU in use.
  754. //
  755. if(fFound && it->m_inst.m_fSystem == false && it->m_inst.m_fMUI == false && it->InUse() == false)
  756. {
  757. *pVal = VARIANT_TRUE;
  758. }
  759. }
  760. }
  761. __HCP_END_PROPERTY(hr);
  762. }
  763. ////////////////////////////////////////
  764. STDMETHODIMP CPCHSetOfHelpTopics::Install()
  765. {
  766. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Install" );
  767. HRESULT hr;
  768. VARIANT_BOOL fRes;
  769. MPC::SmartLock<_ThreadModel> lock( this );
  770. FAIL_IF_RUNNING();
  771. CHECK_WRITE_PERMISSIONS();
  772. __MPC_EXIT_IF_METHOD_FAILS(hr, get_CanInstall( &fRes ));
  773. if(fRes == VARIANT_FALSE)
  774. {
  775. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ALREADY_EXISTS);
  776. }
  777. ////////////////////
  778. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunInstall, NULL ));
  779. hr = S_OK;
  780. __HCP_FUNC_CLEANUP;
  781. __HCP_FUNC_EXIT(hr);
  782. }
  783. STDMETHODIMP CPCHSetOfHelpTopics::Uninstall()
  784. {
  785. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Uninstall" );
  786. HRESULT hr;
  787. VARIANT_BOOL fRes;
  788. MPC::SmartLock<_ThreadModel> lock( this );
  789. FAIL_IF_RUNNING();
  790. CHECK_WRITE_PERMISSIONS();
  791. __MPC_EXIT_IF_METHOD_FAILS(hr, get_CanUninstall( &fRes ));
  792. if(fRes == VARIANT_FALSE)
  793. {
  794. __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED);
  795. }
  796. ////////////////////
  797. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunUninstall, NULL ));
  798. hr = S_OK;
  799. __HCP_FUNC_CLEANUP;
  800. __HCP_FUNC_EXIT(hr);
  801. }
  802. STDMETHODIMP CPCHSetOfHelpTopics::Abort()
  803. {
  804. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Abort" );
  805. HRESULT hr;
  806. Thread_Abort();
  807. if(m_fActAsCollection)
  808. {
  809. MPC::SmartLock<_ThreadModel> lock( this );
  810. long lCount;
  811. long lPos;
  812. __MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->get_Count( &lCount ));
  813. for(lPos=1; lPos<=lCount; lPos++)
  814. {
  815. CComVariant v;
  816. CComPtr<IPCHSetOfHelpTopics> sku;
  817. __MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->get_Item( lPos, &v ));
  818. __MPC_EXIT_IF_METHOD_FAILS(hr, v.ChangeType( VT_DISPATCH ));
  819. __MPC_EXIT_IF_METHOD_FAILS(hr, v.pdispVal->QueryInterface( IID_IPCHSetOfHelpTopics, (LPVOID*)&sku ));
  820. (void)sku->Abort();
  821. }
  822. }
  823. __HCP_FUNC_CLEANUP;
  824. __HCP_FUNC_EXIT(S_OK);
  825. }
  826. ////////////////////////////////////////////////////////////////////////////////
  827. ////////////////////////////////////////////////////////////////////////////////
  828. STDMETHODIMP CPCHSetOfHelpTopics::GetClassID( /*[out]*/ CLSID *pClassID )
  829. {
  830. return E_NOTIMPL;
  831. }
  832. STDMETHODIMP CPCHSetOfHelpTopics::IsDirty()
  833. {
  834. return S_FALSE;
  835. }
  836. STDMETHODIMP CPCHSetOfHelpTopics::Load( /*[in]*/ IStream *pStm )
  837. {
  838. return m_inst.LoadFromStream( pStm );
  839. }
  840. STDMETHODIMP CPCHSetOfHelpTopics::Save( /*[in]*/ IStream *pStm, /*[in]*/ BOOL fClearDirty )
  841. {
  842. return m_inst.SaveToStream( pStm );
  843. }
  844. STDMETHODIMP CPCHSetOfHelpTopics::GetSizeMax( /*[out]*/ ULARGE_INTEGER *pcbSize )
  845. {
  846. return E_NOTIMPL;
  847. }
  848. ////////////////////////////////////////////////////////////////////////////////
  849. ////////////////////////////////////////////////////////////////////////////////
  850. HRESULT CPCHSetOfHelpTopics::CreateIndex()
  851. {
  852. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::CreateIndex" );
  853. HRESULT hr;
  854. CComObject<HCUpdate::Engine>* hc = NULL;
  855. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hc ));
  856. __MPC_EXIT_IF_METHOD_FAILS(hr, hc->SetSkuInfo( m_ts.GetSKU(), m_ts.GetLanguage() ));
  857. __MPC_EXIT_IF_METHOD_FAILS(hr, hc->InternalCreateIndex( VARIANT_FALSE ));
  858. hr = S_OK;
  859. __HCP_FUNC_CLEANUP;
  860. if(hc) hc->Release();
  861. __HCP_FUNC_EXIT(hr);
  862. }
  863. ////////////////////////////////////////////////////////////////////////////////
  864. HRESULT CPCHSetOfHelpTopics::RegisterPackage( /*[in]*/ const MPC::wstring& strFile ,
  865. /*[in]*/ bool fBuiltin )
  866. {
  867. Taxonomy::PackageIter it;
  868. bool fFound;
  869. return Taxonomy::InstalledInstanceStore::s_GLOBAL->Package_Add( strFile.c_str(), NULL, fBuiltin ? &m_ts : NULL, /*fInsertAtTop*/false, fFound, it );
  870. }
  871. HRESULT CPCHSetOfHelpTopics::DirectInstall( /*[in]*/ Installer::Package& pkg ,
  872. /*[in]*/ bool fSetup ,
  873. /*[in]*/ bool fSystem ,
  874. /*[in]*/ bool fMUI )
  875. {
  876. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::DirectInstall" );
  877. HRESULT hr;
  878. Taxonomy::LockingHandle handle;
  879. Taxonomy::InstanceBase& base = pkg.GetData();
  880. Taxonomy::InstanceIter itInstance;
  881. Taxonomy::InstalledInstanceIter itSKU;
  882. bool fFound;
  883. if(fSetup) fSystem = true;
  884. ////////////////////////////////////////////////////////////////////////////////
  885. //
  886. // Phase One: get the database.
  887. //
  888. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  889. __MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.InitializeFromBase( pkg.GetData(), fSystem, fMUI ));
  890. __MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
  891. //
  892. // Loop through the installed instances and remove any duplicates or, if during setup, any SYSTEM or MUI instances.
  893. //
  894. while(1)
  895. {
  896. Taxonomy::InstanceIterConst itBegin;
  897. Taxonomy::InstanceIterConst itEnd;
  898. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_GetList( itBegin, itEnd ));
  899. for(;itBegin != itEnd; itBegin++)
  900. {
  901. const Taxonomy::Instance& inst = *itBegin;
  902. if( inst.m_ths == m_inst.m_ths || // Duplicate
  903. (fSetup && (inst.m_fSystem || inst.m_fMUI)) ) // System and MUI (setup-only)
  904. {
  905. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Find( inst.m_ths, fFound, itInstance ));
  906. if(fFound)
  907. {
  908. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Remove( itInstance ));
  909. //
  910. // Uninstalling an instance could change the system settings, reapply them.
  911. //
  912. __MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.InitializeFromBase( pkg.GetData(), fSystem, fMUI ));
  913. __MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
  914. break;
  915. }
  916. }
  917. }
  918. if(itBegin == itEnd) break;
  919. }
  920. ////////////////////////////////////////////////////////////////////////////////
  921. //
  922. // Phase Two: clean up previous situation, set up permissions.
  923. //
  924. if(fSetup)
  925. {
  926. CPCHSecurityDescriptorDirect sdd;
  927. MPC::wstring strGroupName;
  928. //
  929. // Remove old data from our directories.
  930. //
  931. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_CONFIG , NULL, /*fRemove*/true, /*fRecreate*/true ));
  932. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_DATACOLL , NULL, /*fRemove*/true, /*fRecreate*/true ));
  933. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_LOGS , NULL, /*fRemove*/true, /*fRecreate*/true ));
  934. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_TEMP , NULL, /*fRemove*/true, /*fRecreate*/true ));
  935. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_OFFLINECACHE , NULL, /*fRemove*/true, /*fRecreate*/true ));
  936. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_HELPSET_ROOT HC_HELPSET_SUB_INSTALLEDSKUS, NULL, /*fRemove*/true, /*fRecreate*/true ));
  937. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_BATCH , NULL, /*fRemove*/false, /*fRecreate*/true ));
  938. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_PKGSTORE, NULL, /*fRemove*/false, /*fRecreate*/true ));
  939. //
  940. // Change the ACL for system directories.
  941. //
  942. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::LocalizeString( IDS_HELPSVC_GROUPNAME, strGroupName ));
  943. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Initialize());
  944. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.SetGroup( strGroupName.c_str() ));
  945. //
  946. // Config, Database and Datacoll directories:
  947. //
  948. // LOCAL SYSTEM, Admin, Admins : any access.
  949. //
  950. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_SystemSid ,
  951. ACCESS_ALLOWED_ACE_TYPE ,
  952. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
  953. FILE_ALL_ACCESS ));
  954. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_Alias_AdminsSid ,
  955. ACCESS_ALLOWED_ACE_TYPE ,
  956. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
  957. FILE_ALL_ACCESS ));
  958. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_CONFIG ));
  959. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_DATACOLL ));
  960. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_PKGSTORE ));
  961. //
  962. // Binaries, System, Batch, Temp
  963. //
  964. // LOCAL SYSTEM, Admin, Admins : any access.
  965. // Everyone : read and execute.
  966. //
  967. //
  968. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_EveryoneSid ,
  969. ACCESS_ALLOWED_ACE_TYPE ,
  970. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
  971. FILE_GENERIC_READ | FILE_GENERIC_EXECUTE ));
  972. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_BATCH ));
  973. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_BINARIES ));
  974. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_LOGS ));
  975. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_OFFLINECACHE ));
  976. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_TEMP ));
  977. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_HELPSET_ROOT HC_HELPSET_SUB_INSTALLEDSKUS ));
  978. {
  979. static const Installer::PURPOSE c_allowed[] =
  980. {
  981. Installer::PURPOSE_OTHER ,
  982. Installer::PURPOSE_INVALID,
  983. };
  984. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Install( c_allowed, NULL ));
  985. }
  986. }
  987. ////////////////////////////////////////////////////////////////////////////////
  988. //
  989. // Phase Three: register instance.
  990. //
  991. //
  992. // Install instance.
  993. //
  994. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Add( pkg.GetFile(), m_inst, fFound, itInstance ));
  995. //
  996. // Add the SKU to the list of installed ones.
  997. //
  998. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Add( m_inst, fFound, itSKU ));
  999. ////////////////////////////////////////////////////////////////////////////////
  1000. //
  1001. // Phase Four: copy the Help files.
  1002. //
  1003. if(m_fConnectedToDisk)
  1004. {
  1005. MPC::WStringUCLookup mapLayout;
  1006. MPC::WStringUCLookup mapLayoutX86;
  1007. MPC::WStringUCLookup mapLayoutIA64;
  1008. MPC::WStringList lst;
  1009. MPC::WStringIterConst it;
  1010. MPC::wstring strDir_HelpFiles( m_inst.m_strHelpFiles ); MPC::SubstituteEnvVariables( strDir_HelpFiles );
  1011. MPC::wstring strFile_Database( m_inst.m_strDatabaseFile ); MPC::SubstituteEnvVariables( strFile_Database );
  1012. bool fX86 = (wcsstr( m_inst.m_ths.GetSKU(), L"_32" ) != NULL);
  1013. //
  1014. // Parse the layout.inf file, to create the map of CD files.
  1015. //
  1016. {
  1017. MPC::wstring strLayout( m_strDirectory ); strLayout += L"\\layout.inf";
  1018. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller ( ));
  1019. __MPC_EXIT_IF_METHOD_FAILS(hr, Local_ParseLayoutInf( strLayout.c_str(), &mapLayout, &mapLayoutX86, &mapLayoutIA64 ));
  1020. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation ( ));
  1021. }
  1022. __MPC_EXIT_IF_METHOD_FAILS(hr, GetListOfFilesFromDatabase( strFile_Database, lst ));
  1023. for(it = lst.begin(); it != lst.end(); it++)
  1024. {
  1025. const MPC::wstring& strHelpFile = *it;
  1026. MPC::WStringUCLookupIterConst it2;
  1027. it2 = mapLayout.find( strHelpFile );
  1028. if(it2 == mapLayout.end())
  1029. {
  1030. if(fX86)
  1031. {
  1032. it2 = mapLayoutX86.find( strHelpFile ); if(it2 == mapLayoutX86.end()) continue;
  1033. }
  1034. else
  1035. {
  1036. it2 = mapLayoutIA64.find( strHelpFile ); if(it2 == mapLayoutIA64.end()) continue;
  1037. }
  1038. }
  1039. if(it2->second.empty() == false)
  1040. {
  1041. MPC::wstring strSrcFile;
  1042. MPC::wstring strDstFile;
  1043. strSrcFile = m_strDirectory ; strSrcFile += L"\\"; strSrcFile += it2->second;
  1044. strDstFile = strDir_HelpFiles; strDstFile += L"\\"; strDstFile += strHelpFile;
  1045. CHANGE_STATE( SHT_COPYING_FILES, CComBSTR( strHelpFile.c_str() ) );
  1046. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( strDstFile ));
  1047. if(FAILED(hr = SVC::CopyOrExtractFileWhileImpersonating( strSrcFile.c_str(), strDstFile.c_str(), m_imp )))
  1048. {
  1049. if(hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) __MPC_FUNC_LEAVE;
  1050. continue;
  1051. }
  1052. EXIT_IF_ABORTED();
  1053. }
  1054. }
  1055. }
  1056. if(m_fConnectedToServer)
  1057. {
  1058. CComPtr<IPCHRemoteHelpContents> rhc;
  1059. CComVariant v;
  1060. MPC::WStringList lst;
  1061. MPC::WStringIterConst it;
  1062. __MPC_EXIT_IF_METHOD_FAILS(hr, m_svc->RemoteHelpContents( CComBSTR( m_inst.m_ths.GetSKU() ), m_inst.m_ths.GetLanguage(), &rhc ));
  1063. if(rhc == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  1064. __MPC_EXIT_IF_METHOD_FAILS(hr, rhc->get_ListOfFiles ( &v ));
  1065. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertSafeArrayToList( v, lst ));
  1066. for(it = lst.begin(); it != lst.end(); it++)
  1067. {
  1068. CComPtr<IUnknown> unkSrc;
  1069. CComBSTR bstrSrcFile( it->c_str() );
  1070. MPC::wstring strDstFile;
  1071. strDstFile = m_inst.m_strHelpFiles; MPC::SubstituteEnvVariables( strDstFile );
  1072. strDstFile += L"\\";
  1073. strDstFile += it->c_str();
  1074. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( strDstFile ));
  1075. if(SUCCEEDED(hr = rhc->GetFile( bstrSrcFile, &unkSrc )))
  1076. {
  1077. CComQIPtr<IStream> streamSrc = unkSrc; // TransferData checks for NULL.
  1078. CComPtr<IStream> streamDst;
  1079. CHANGE_STATE( SHT_COPYING_FILES, bstrSrcFile );
  1080. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForWrite( strDstFile.c_str(), &streamDst ));
  1081. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( streamSrc, streamDst ));
  1082. }
  1083. else
  1084. {
  1085. if(hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) __MPC_FUNC_LEAVE;
  1086. }
  1087. }
  1088. }
  1089. ////////////////////////////////////////////////////////////////////////////////
  1090. CHANGE_STATE( SHT_INSTALLING, NULL );
  1091. __MPC_EXIT_IF_METHOD_FAILS(hr, ScanBatch());
  1092. ////////////////////////////////////////////////////////////////////////////////
  1093. CHANGE_STATE( SHT_INSTALLED, NULL );
  1094. hr = S_OK;
  1095. __HCP_FUNC_CLEANUP;
  1096. __HCP_FUNC_EXIT(hr);
  1097. }
  1098. HRESULT CPCHSetOfHelpTopics::DirectUninstall( /*[in]*/ const Taxonomy::HelpSet* ths )
  1099. {
  1100. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::DirectUninstall" );
  1101. HRESULT hr;
  1102. Taxonomy::LockingHandle handle;
  1103. Taxonomy::InstanceIter itInstance;
  1104. bool fFound;
  1105. if(ths) m_ts = *ths;
  1106. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  1107. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Find( m_ts, fFound, itInstance ));
  1108. if(fFound)
  1109. {
  1110. //
  1111. // System SKU cannot be uninstalled!!
  1112. //
  1113. if(itInstance->m_fSystem)
  1114. {
  1115. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ACCESS_DENIED);
  1116. }
  1117. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Remove( itInstance ));
  1118. }
  1119. hr = S_OK;
  1120. __HCP_FUNC_CLEANUP;
  1121. __HCP_FUNC_EXIT(hr);
  1122. }
  1123. HRESULT CPCHSetOfHelpTopics::ScanBatch()
  1124. {
  1125. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::ScanBatch" );
  1126. HRESULT hr;
  1127. MPC::wstring strBatchPath( HC_ROOT_HELPSVC_BATCH ); MPC::SubstituteEnvVariables( strBatchPath );
  1128. MPC::FileSystemObject fso( strBatchPath.c_str() );
  1129. CComObject<HCUpdate::Engine>* hc = NULL;
  1130. Taxonomy::LockingHandle handle;
  1131. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hc ));
  1132. {
  1133. Taxonomy::Logger& log = hc->GetLogger();
  1134. bool fLogStarted = false;
  1135. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle, &log ));
  1136. if(SUCCEEDED(fso.Scan()))
  1137. {
  1138. MPC::FileSystemObject::List fso_lst;
  1139. MPC::FileSystemObject::IterConst fso_it;
  1140. std::vector<MPC::wstringUC> vec;
  1141. std::vector<MPC::wstringUC>::iterator it;
  1142. //
  1143. // Delete any subdirectory.
  1144. //
  1145. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFolders( fso_lst ));
  1146. for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
  1147. {
  1148. __MPC_EXIT_IF_METHOD_FAILS(hr, (*fso_it)->Delete( true, false ));
  1149. }
  1150. fso_lst.clear();
  1151. //
  1152. // For each file, process it if it's a cabinet and then delete!
  1153. //
  1154. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFiles( fso_lst ));
  1155. for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
  1156. {
  1157. MPC::FileSystemObject* fsoFile = *fso_it;
  1158. MPC::wstring strPath;
  1159. LPCWSTR szExt;
  1160. __MPC_EXIT_IF_METHOD_FAILS(hr, fsoFile->get_Path( strPath ));
  1161. if((szExt = wcsrchr( strPath.c_str(), '.' )) && !_wcsicmp( szExt, c_CabExtension ))
  1162. {
  1163. vec.push_back( strPath );
  1164. }
  1165. }
  1166. std::sort( vec.begin(), vec.end() );
  1167. for(it=vec.begin(); it<vec.end(); it++)
  1168. {
  1169. MPC::wstring& strPath = *it;
  1170. Taxonomy::PackageIter it2;
  1171. bool fFound;
  1172. if(!fLogStarted)
  1173. {
  1174. (void)hc->StartLog();
  1175. fLogStarted = true;
  1176. }
  1177. hr = Taxonomy::InstalledInstanceStore::s_GLOBAL->Package_Add( strPath.c_str(), NULL, NULL, /*fInsertAtTop*/false, fFound, it2 );
  1178. if(FAILED(hr))
  1179. {
  1180. ; // Ignore any failure....
  1181. }
  1182. }
  1183. //
  1184. // Remove files.
  1185. //
  1186. for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
  1187. {
  1188. MPC::FileSystemObject* fsoFile = *fso_it;
  1189. __MPC_EXIT_IF_METHOD_FAILS(hr, (*fso_it)->Delete( true, false ));
  1190. }
  1191. fso_lst.clear();
  1192. }
  1193. handle.Release();
  1194. hr = hc->InternalUpdatePkg( NULL, /*fImpersonate*/false );
  1195. if(FAILED(hr))
  1196. {
  1197. ; // Ignore any failure....
  1198. }
  1199. if(fLogStarted)
  1200. {
  1201. (void)hc->EndLog();
  1202. }
  1203. }
  1204. hr = S_OK;
  1205. __HCP_FUNC_CLEANUP;
  1206. if(hc) hc->Release();
  1207. __HCP_FUNC_EXIT(hr);
  1208. }
  1209. ////////////////////////////////////////////////////////////////////////////////
  1210. HRESULT CPCHSetOfHelpTopics::RebuildSKU( /*[in]*/ const Taxonomy::HelpSet& ths )
  1211. {
  1212. __HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RebuildSKU" );
  1213. HRESULT hr;
  1214. CComObject<HCUpdate::Engine>* hc = NULL;
  1215. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hc ));
  1216. {
  1217. Taxonomy::LockingHandle handle;
  1218. bool fUseLogger = SUCCEEDED(hc->StartLog()); // It could be already in use.
  1219. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle, fUseLogger ? &(hc->GetLogger()) : NULL ));
  1220. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->State_InvalidateSKU( ths, /*fAlsoDatabase*/true ));
  1221. __MPC_EXIT_IF_METHOD_FAILS(hr, hc->InternalUpdatePkg( NULL, /*fImpersonate*/false ));
  1222. if(fUseLogger) (void)hc->EndLog();
  1223. }
  1224. hr = S_OK;
  1225. __HCP_FUNC_CLEANUP;
  1226. if(hc) hc->Release();
  1227. __HCP_FUNC_EXIT(hr);
  1228. }