Source code of Windows XP (NT5)
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.

3172 lines
113 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1998.
  5. //
  6. // File: packages.cpp
  7. //
  8. // Contents: Methods on CScopePane related to package deployment
  9. // and maintenence of the various index and cross-reference
  10. // structures.
  11. //
  12. // Classes:
  13. //
  14. // Functions: CopyPackageDetail
  15. // FreePackageDetail
  16. // GetMsiProperty
  17. //
  18. // History: 2-03-1998 stevebl Created
  19. // 3-25-1998 stevebl Added GetMsiProperty
  20. // 5-20-1998 RahulTh - Added DetectUpgrades for automatic upgrade
  21. // detection
  22. // - Added GetCapitalizedExt
  23. //
  24. //---------------------------------------------------------------------------
  25. // UNDONE - put in exception handling for low memory conditions
  26. #include "precomp.hxx"
  27. // uncomment this line to get the old behavior of putting up an upgrade
  28. // dialog for auto-detected upgrades
  29. //#define SHOWDETECTEDUPGRADEDIALOG
  30. //IMalloc * g_pIMalloc = NULL;
  31. BOOL IsNullGUID (GUID *pguid)
  32. {
  33. return ( (pguid->Data1 == 0) &&
  34. (pguid->Data2 == 0) &&
  35. (pguid->Data3 == 0) &&
  36. (pguid->Data4[0] == 0) &&
  37. (pguid->Data4[1] == 0) &&
  38. (pguid->Data4[2] == 0) &&
  39. (pguid->Data4[3] == 0) &&
  40. (pguid->Data4[4] == 0) &&
  41. (pguid->Data4[5] == 0) &&
  42. (pguid->Data4[6] == 0) &&
  43. (pguid->Data4[7] == 0) );
  44. }
  45. void FreePlatformInfo(PLATFORMINFO * &ppiOut)
  46. {
  47. if (ppiOut)
  48. {
  49. OLESAFE_DELETE(ppiOut->prgPlatform);
  50. OLESAFE_DELETE(ppiOut->prgLocale);
  51. OLESAFE_DELETE(ppiOut);
  52. }
  53. }
  54. HRESULT CopyPlatformInfo(PLATFORMINFO * &ppiOut, PLATFORMINFO * & ppiIn)
  55. {
  56. if (NULL == ppiIn)
  57. {
  58. ppiOut = NULL;
  59. return S_OK;
  60. }
  61. UINT n;
  62. ppiOut = (PLATFORMINFO *)OLEALLOC(sizeof(PLATFORMINFO));
  63. if (!ppiOut)
  64. {
  65. goto out_of_memory;
  66. }
  67. memcpy(ppiOut, ppiIn, sizeof(PLATFORMINFO));
  68. ppiOut->prgPlatform = NULL;
  69. ppiOut->prgLocale = NULL;
  70. n = ppiIn->cPlatforms;
  71. if (n)
  72. {
  73. ppiOut->prgPlatform = (CSPLATFORM*) OLEALLOC(sizeof(CSPLATFORM) * n);
  74. if (!ppiOut->prgPlatform)
  75. {
  76. goto out_of_memory;
  77. }
  78. memcpy(ppiOut->prgPlatform, ppiIn->prgPlatform, sizeof(CSPLATFORM) * n);
  79. }
  80. n = ppiIn->cLocales;
  81. if (n)
  82. {
  83. ppiOut->prgLocale = (LCID *) OLEALLOC(sizeof(LCID) * n);
  84. if (!ppiOut->prgLocale)
  85. {
  86. goto out_of_memory;
  87. }
  88. memcpy(ppiOut->prgLocale, ppiIn->prgLocale, sizeof(LCID) * n);
  89. }
  90. return S_OK;
  91. out_of_memory:
  92. FreePlatformInfo(ppiOut);
  93. return E_OUTOFMEMORY;
  94. }
  95. void FreeActInfo(ACTIVATIONINFO * &paiOut)
  96. {
  97. if (paiOut)
  98. {
  99. if (paiOut->pClasses)
  100. {
  101. UINT n = paiOut->cClasses;
  102. while (n--)
  103. {
  104. OLESAFE_DELETE(paiOut->pClasses[n].prgProgId);
  105. }
  106. OLESAFE_DELETE(paiOut->pClasses);
  107. }
  108. OLESAFE_DELETE(paiOut->prgInterfaceId);
  109. OLESAFE_DELETE(paiOut->prgPriority);
  110. if (paiOut->prgShellFileExt)
  111. {
  112. UINT n = paiOut->cShellFileExt;
  113. while (n--)
  114. {
  115. OLESAFE_DELETE(paiOut->prgShellFileExt[n])
  116. }
  117. OLESAFE_DELETE(paiOut->prgShellFileExt);
  118. }
  119. OLESAFE_DELETE(paiOut->prgTlbId);
  120. OLESAFE_DELETE(paiOut);
  121. }
  122. }
  123. HRESULT CopyActInfo(ACTIVATIONINFO * & paiOut, ACTIVATIONINFO * & paiIn)
  124. {
  125. if (NULL == paiIn)
  126. {
  127. paiOut = NULL;
  128. return S_OK;
  129. }
  130. UINT n;
  131. paiOut = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO));
  132. if (!paiOut)
  133. {
  134. goto out_of_memory;
  135. }
  136. memcpy(paiOut, paiIn, sizeof(ACTIVATIONINFO));
  137. paiOut->prgInterfaceId = NULL;
  138. paiOut->prgPriority = NULL;
  139. paiOut->prgShellFileExt = NULL;
  140. paiOut->prgTlbId = NULL;
  141. paiOut->pClasses = NULL;
  142. n = paiIn->cClasses;
  143. paiOut->bHasClasses = paiIn->bHasClasses;
  144. if (n)
  145. {
  146. paiOut->pClasses = (CLASSDETAIL *) OLEALLOC(sizeof(CLASSDETAIL) * n);
  147. if (!paiOut->pClasses)
  148. {
  149. goto out_of_memory;
  150. }
  151. memcpy(paiOut->pClasses, paiIn->pClasses, sizeof(CLASSDETAIL) * n);
  152. while (n--)
  153. {
  154. UINT n2 = paiIn->pClasses[n].cProgId;
  155. if (n2)
  156. {
  157. paiOut->pClasses[n].prgProgId = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n2);
  158. if (!paiOut->pClasses[n].prgProgId)
  159. {
  160. goto out_of_memory;
  161. }
  162. while (n2--)
  163. {
  164. OLESAFE_COPYSTRING(paiOut->pClasses[n].prgProgId[n2], paiIn->pClasses[n].prgProgId[n2]);
  165. }
  166. }
  167. }
  168. }
  169. n = paiIn->cShellFileExt;
  170. if (n)
  171. {
  172. paiOut->prgPriority = (UINT *) OLEALLOC(sizeof(UINT) * n);
  173. if (!paiOut->prgPriority)
  174. {
  175. goto out_of_memory;
  176. }
  177. memcpy(paiOut->prgPriority, paiIn->prgPriority, sizeof(UINT) * n);
  178. paiOut->prgShellFileExt = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
  179. if (!paiOut->prgShellFileExt)
  180. {
  181. goto out_of_memory;
  182. }
  183. while (n--)
  184. {
  185. OLESAFE_COPYSTRING(paiOut->prgShellFileExt[n], paiIn->prgShellFileExt[n]);
  186. }
  187. }
  188. n = paiIn->cInterfaces;
  189. if (n)
  190. {
  191. paiOut->prgInterfaceId = (IID *) OLEALLOC(sizeof(IID) * n);
  192. if (!paiOut->prgInterfaceId)
  193. {
  194. goto out_of_memory;
  195. }
  196. memcpy(paiOut->prgInterfaceId, paiIn->prgInterfaceId, sizeof(IID) * n);
  197. }
  198. n = paiIn->cTypeLib;
  199. if (n)
  200. {
  201. paiOut->prgTlbId = (GUID *) OLEALLOC(sizeof(GUID) * n);
  202. if (!paiOut->prgTlbId)
  203. {
  204. goto out_of_memory;
  205. }
  206. memcpy(paiOut->prgTlbId, paiIn->prgTlbId, sizeof(GUID) * n);
  207. }
  208. return S_OK;
  209. out_of_memory:
  210. FreeActInfo(paiOut);
  211. return E_OUTOFMEMORY;
  212. }
  213. void FreeInstallInfo(INSTALLINFO * &piiOut)
  214. {
  215. if (piiOut)
  216. {
  217. if (piiOut->prgUpgradeInfoList)
  218. {
  219. UINT n = piiOut->cUpgrades;
  220. while (n--)
  221. {
  222. OLESAFE_DELETE(piiOut->prgUpgradeInfoList[n].szClassStore);
  223. }
  224. OLESAFE_DELETE(piiOut->prgUpgradeInfoList);
  225. }
  226. OLESAFE_DELETE(piiOut->pClsid);
  227. OLESAFE_DELETE(piiOut->pszScriptPath);
  228. OLESAFE_DELETE(piiOut->pszSetupCommand);
  229. OLESAFE_DELETE(piiOut->pszUrl);
  230. OLESAFE_DELETE(piiOut);
  231. }
  232. }
  233. HRESULT CopyInstallInfo(INSTALLINFO * & piiOut, INSTALLINFO * & piiIn)
  234. {
  235. ULONG n;
  236. if (NULL == piiIn)
  237. {
  238. piiOut = NULL;
  239. return S_OK;
  240. }
  241. piiOut = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO));
  242. if (!piiOut)
  243. {
  244. goto out_of_memory;
  245. }
  246. memcpy(piiOut, piiIn, sizeof(INSTALLINFO));
  247. piiOut->pClsid = NULL;
  248. piiOut->prgUpgradeInfoList = NULL;
  249. piiOut->pszScriptPath = NULL;
  250. piiOut->pszSetupCommand = NULL;
  251. piiOut->pszUrl = NULL;
  252. OLESAFE_COPYSTRING(piiOut->pszScriptPath, piiIn->pszScriptPath);
  253. OLESAFE_COPYSTRING(piiOut->pszSetupCommand, piiIn->pszSetupCommand);
  254. OLESAFE_COPYSTRING(piiOut->pszUrl, piiIn->pszUrl);
  255. if (piiIn->pClsid)
  256. {
  257. piiOut->pClsid = (GUID *) OLEALLOC(sizeof(GUID));
  258. if (!piiOut->pClsid)
  259. {
  260. goto out_of_memory;
  261. }
  262. memcpy(piiOut->pClsid, piiIn->pClsid, sizeof(GUID));
  263. }
  264. n = piiIn->cUpgrades;
  265. if (n)
  266. {
  267. piiOut->prgUpgradeInfoList = (UPGRADEINFO *) OLEALLOC(sizeof(UPGRADEINFO) * n);
  268. if (!piiOut->prgUpgradeInfoList)
  269. {
  270. goto out_of_memory;
  271. }
  272. memcpy(piiOut->prgUpgradeInfoList, piiIn->prgUpgradeInfoList, sizeof(UPGRADEINFO) * n);
  273. while (n--)
  274. {
  275. OLESAFE_COPYSTRING(piiOut->prgUpgradeInfoList[n].szClassStore, piiIn->prgUpgradeInfoList[n].szClassStore);
  276. }
  277. }
  278. return S_OK;
  279. out_of_memory:
  280. FreeInstallInfo(piiOut);
  281. return E_OUTOFMEMORY;
  282. }
  283. void InternalFreePackageDetail(PACKAGEDETAIL * &ppdOut)
  284. {
  285. if (ppdOut)
  286. {
  287. FreeActInfo(ppdOut->pActInfo);
  288. FreePlatformInfo(ppdOut->pPlatformInfo);
  289. FreeInstallInfo(ppdOut->pInstallInfo);
  290. OLESAFE_DELETE(ppdOut->pszPackageName);
  291. OLESAFE_DELETE(ppdOut->pszPublisher);
  292. if (ppdOut->pszSourceList)
  293. {
  294. UINT n = ppdOut->cSources;
  295. while (n--)
  296. {
  297. OLESAFE_DELETE(ppdOut->pszSourceList[n]);
  298. }
  299. OLESAFE_DELETE(ppdOut->pszSourceList);
  300. }
  301. OLESAFE_DELETE(ppdOut->rpCategory);
  302. }
  303. }
  304. HRESULT CopyPackageDetail(PACKAGEDETAIL * & ppdOut, PACKAGEDETAIL * & ppdIn)
  305. {
  306. ULONG n;
  307. if (NULL == ppdIn)
  308. {
  309. ppdOut = NULL;
  310. return S_OK;
  311. }
  312. ppdOut = new PACKAGEDETAIL;
  313. if (!ppdOut)
  314. {
  315. goto out_of_memory;
  316. }
  317. memcpy(ppdOut, ppdIn, sizeof(PACKAGEDETAIL));
  318. ppdOut->pActInfo = NULL;
  319. ppdOut->pInstallInfo = NULL;
  320. ppdOut->pPlatformInfo = NULL;
  321. ppdOut->pszPackageName = NULL;
  322. ppdOut->pszPublisher = NULL;
  323. ppdOut->pszSourceList = NULL;
  324. ppdOut->rpCategory = NULL;
  325. OLESAFE_COPYSTRING(ppdOut->pszPackageName, ppdIn->pszPackageName);
  326. n = ppdIn->cSources;
  327. if (n)
  328. {
  329. ppdOut->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
  330. if (!ppdOut->pszSourceList)
  331. {
  332. goto out_of_memory;
  333. }
  334. while (n--)
  335. {
  336. OLESAFE_COPYSTRING(ppdOut->pszSourceList[n], ppdIn->pszSourceList[n]);
  337. }
  338. }
  339. n = ppdIn->cCategories;
  340. if (n)
  341. {
  342. ppdOut->rpCategory = (GUID *)OLEALLOC(sizeof(GUID) * n);
  343. if (!ppdOut->rpCategory)
  344. {
  345. goto out_of_memory;
  346. }
  347. memcpy(ppdOut->rpCategory, ppdIn->rpCategory, sizeof(GUID) * n);
  348. }
  349. if FAILED(CopyActInfo(ppdOut->pActInfo, ppdIn->pActInfo))
  350. goto out_of_memory;
  351. if FAILED(CopyPlatformInfo(ppdOut->pPlatformInfo, ppdIn->pPlatformInfo))
  352. goto out_of_memory;
  353. if FAILED(CopyInstallInfo(ppdOut->pInstallInfo, ppdIn->pInstallInfo))
  354. goto out_of_memory;
  355. return S_OK;
  356. out_of_memory:
  357. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, E_OUTOFMEMORY);
  358. InternalFreePackageDetail(ppdOut);
  359. if (ppdOut)
  360. delete ppdOut;
  361. return E_OUTOFMEMORY;
  362. }
  363. void FreePackageDetail(PACKAGEDETAIL * & ppd)
  364. {
  365. if (ppd)
  366. {
  367. ReleasePackageDetail(ppd);
  368. delete ppd;
  369. ppd = NULL;
  370. }
  371. }
  372. //+--------------------------------------------------------------------------
  373. //
  374. // Member: CScopePane::GetUniquePackageName
  375. //
  376. // Synopsis: Returns a unique package name.
  377. //
  378. // Arguments: [sz] - [in] the name of the package
  379. // [out] the new name, guaranteed unique on this cs
  380. //
  381. // History: 1-23-1998 stevebl Created
  382. //
  383. // Notes: First the input name is checked for uniqueness. If it is
  384. // already unique it is returned unchanged. If it is not
  385. // unique then a new name is formed by adding " (2)" to the end
  386. // of the string, then " (3)" and " (4)" and so on until a
  387. // unique name is found.
  388. //
  389. // If you don't want a number appended to the name, nHint must
  390. // be 1.
  391. //
  392. // The value passed back in nHint will be the seed for the
  393. // next try.
  394. //
  395. //---------------------------------------------------------------------------
  396. void CScopePane::GetUniquePackageName(CString szRoot, CString &szOut, int &nHint)
  397. {
  398. map<MMC_COOKIE, CAppData>::iterator i;
  399. set<CString> sNames;
  400. int cch = szRoot.GetLength();
  401. for (i=m_AppData.begin(); i != m_AppData.end(); i++)
  402. {
  403. // As an optimization, I'm only going to add names that might match
  404. // this one to the set.
  405. LPOLESTR szName = i->second.m_pDetails->pszPackageName;
  406. if ((0 == wcsncmp(szRoot, szName, cch)) && (i->second.m_fVisible))
  407. sNames.insert(szName);
  408. }
  409. szOut = szRoot;
  410. if (nHint++ == 1) // try the first name
  411. {
  412. if (sNames.end() == sNames.find(szOut))
  413. return;
  414. }
  415. // now check for a match
  416. do
  417. {
  418. szOut.Format(L"%s (%i)", (LPCTSTR)szRoot, nHint++);
  419. if (sNames.end() == sNames.find(szOut))
  420. {
  421. // we are unique
  422. return;
  423. }
  424. // try a different name
  425. } while (TRUE);
  426. }
  427. //+--------------------------------------------------------------------------
  428. //
  429. // Member: CScopePand::GetDeploymentType
  430. //
  431. // Synopsis:
  432. //
  433. // Arguments: [szPackagePath] -
  434. // [lpFileTitle] -
  435. //
  436. // Returns:
  437. //
  438. // Modifies:
  439. //
  440. // Derivation:
  441. //
  442. // History: 6-29-1998 stevebl Created
  443. //
  444. // Notes:
  445. //
  446. //---------------------------------------------------------------------------
  447. HRESULT CScopePane::GetDeploymentType(PACKAGEDETAIL * ppd, BOOL & fShowPropertySheet)
  448. {
  449. INSTALLINFO * pii = ppd->pInstallInfo;
  450. if (m_ToolDefaults.fUseWizard)
  451. {
  452. CDeployApp dlgDeployApp;
  453. // Turn on theme'ing for the dialog by activating the theme context
  454. CThemeContextActivator themer;
  455. dlgDeployApp.m_fMachine = m_fMachine;
  456. dlgDeployApp.m_fCrappyZaw = pii->PathType == SetupNamePath;
  457. if (IDCANCEL == dlgDeployApp.DoModal())
  458. {
  459. return E_FAIL;
  460. }
  461. switch (dlgDeployApp.m_iDeployment)
  462. {
  463. default:
  464. case 0: //published
  465. pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  466. break;
  467. case 1: // assigned
  468. pii->dwActFlags = ACTFLG_Assigned | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  469. break;
  470. case 3: // disabled
  471. pii->dwActFlags = 0;
  472. break;
  473. case 2: // custom
  474. if (m_fMachine)
  475. {
  476. pii->dwActFlags = ACTFLG_Assigned | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  477. }
  478. else
  479. {
  480. pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  481. }
  482. fShowPropertySheet = TRUE;
  483. }
  484. }
  485. else
  486. {
  487. switch (m_ToolDefaults.NPBehavior)
  488. {
  489. default:
  490. case NP_PUBLISHED:
  491. if (!m_fMachine)
  492. {
  493. pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  494. break;
  495. }
  496. case NP_ASSIGNED:
  497. if (pii->PathType != SetupNamePath)
  498. {
  499. pii->dwActFlags = ACTFLG_Assigned | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  500. }
  501. else
  502. {
  503. // Crappy ZAW app.. force it to be published.
  504. pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  505. }
  506. break;
  507. case NP_DISABLED:
  508. pii->dwActFlags = 0;
  509. break;
  510. }
  511. if (m_ToolDefaults.fCustomDeployment)
  512. {
  513. fShowPropertySheet = TRUE;
  514. }
  515. }
  516. return S_OK;
  517. }
  518. //+--------------------------------------------------------------------------
  519. //
  520. // Member: CScopePane::DeployPackage
  521. //
  522. // Synopsis:
  523. //
  524. // Arguments: [hr] -
  525. // [hr] -
  526. //
  527. // Returns:
  528. //
  529. // Modifies:
  530. //
  531. // Derivation:
  532. //
  533. // History: 6-29-1998 stevebl Created
  534. //
  535. // Notes:
  536. //
  537. //---------------------------------------------------------------------------
  538. HRESULT CScopePane::DeployPackage(PACKAGEDETAIL * ppd, BOOL fShowPropertySheet)
  539. {
  540. CHourglass hourglass;
  541. INSTALLINFO * pii = ppd->pInstallInfo;
  542. HRESULT hr = S_OK;
  543. hr = PrepareExtensions(*ppd);
  544. if (SUCCEEDED(hr))
  545. {
  546. DWORD dwRememberFlags;
  547. // put the entry in the class store
  548. if (fShowPropertySheet)
  549. {
  550. dwRememberFlags = pii->dwActFlags;
  551. pii->dwActFlags = 0; // disabled state
  552. }
  553. if (!m_pIClassAdmin)
  554. {
  555. hr = GetClassStore(TRUE);
  556. if (FAILED(hr))
  557. {
  558. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_NOCLASSSTORE_ERROR, hr);
  559. DebugMsg((DM_WARNING, TEXT("GetClassStore failed with 0x%x"), hr));
  560. }
  561. }
  562. if (SUCCEEDED(hr))
  563. {
  564. hr = m_pIClassAdmin->AddPackage(ppd, &ppd->pInstallInfo->PackageGuid);
  565. if (FAILED(hr))
  566. {
  567. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_ADDPACKAGE_ERROR, hr, ppd->pszPackageName);
  568. DebugMsg((DM_WARNING, TEXT("AddPackage failed with 0x%x"), hr));
  569. }
  570. }
  571. if (FAILED(hr))
  572. {
  573. return hr;
  574. }
  575. if (fShowPropertySheet)
  576. {
  577. pii->dwActFlags = dwRememberFlags; // restore state
  578. }
  579. }
  580. if (SUCCEEDED(hr))
  581. {
  582. CString szCSPath;
  583. hr = GetClassStoreName(szCSPath, FALSE);
  584. if (FAILED(hr))
  585. {
  586. DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr));
  587. return hr;
  588. }
  589. CAppData data;
  590. hr = CopyPackageDetail(data.m_pDetails, ppd);
  591. if (FAILED(hr))
  592. {
  593. DebugMsg((DM_WARNING, TEXT("CopyPackageDetail failed with 0x%x"), hr));
  594. return hr;
  595. }
  596. data.InitializeExtraInfo();
  597. m_lLastAllocated++;
  598. // make sure that m_lLastAllocated hasn't already been used
  599. while (m_AppData.end() != m_AppData.find(m_lLastAllocated))
  600. {
  601. m_lLastAllocated++;
  602. }
  603. data.m_fVisible = FALSE;
  604. m_AppData[m_lLastAllocated] = data;
  605. BOOL fAddOk = TRUE;
  606. // The admin has said he wants to do a "custom" deployment.
  607. if (fShowPropertySheet)
  608. {
  609. HRESULT hr; // errors that happen while setting up
  610. // the property sheets are NOT to be
  611. // reported as deployment errors.
  612. MMC_COOKIE cookie = m_lLastAllocated;
  613. PROPSHEETHEADER psh;
  614. memset(&psh, 0, sizeof(psh));
  615. psh.dwSize = sizeof(psh);
  616. psh.dwFlags = PSH_NOAPPLYNOW | PSH_PROPTITLE;
  617. psh.pszCaption = m_AppData[m_lLastAllocated].m_pDetails->pszPackageName;
  618. int nPage = 0;
  619. HPROPSHEETPAGE rgPages[6];
  620. psh.phpage = rgPages;
  621. //
  622. // Create the Product property page
  623. //
  624. CProduct prpProduct;
  625. prpProduct.m_fPreDeploy = TRUE;
  626. prpProduct.m_pData = &m_AppData[m_lLastAllocated];
  627. prpProduct.m_cookie = cookie;
  628. prpProduct.m_pScopePane = this;
  629. prpProduct.m_pAppData = &m_AppData;
  630. prpProduct.m_pIGPEInformation = m_pIGPEInformation;
  631. prpProduct.m_fMachine = m_fMachine;
  632. prpProduct.m_fRSOP = m_fRSOP;
  633. // no longer need to marshal this interface, just set it
  634. prpProduct.m_pIClassAdmin = m_pIClassAdmin;
  635. m_pIClassAdmin->AddRef();
  636. rgPages[nPage++] = CreateThemedPropertySheetPage(&prpProduct.m_psp);
  637. //
  638. // Create the Depeployment property page
  639. //
  640. CDeploy prpDeploy;
  641. prpDeploy.m_fPreDeploy = TRUE;
  642. prpDeploy.m_pData = &m_AppData[m_lLastAllocated];
  643. prpDeploy.m_cookie = cookie;
  644. prpDeploy.m_fMachine = m_fMachine;
  645. prpDeploy.m_fRSOP = m_fRSOP;
  646. prpDeploy.m_pScopePane = this;
  647. #if 0
  648. prpDeploy.m_pIGPEInformation = m_pIGPEInformation;
  649. #endif
  650. // no longer need to marshal this interface, just set it
  651. prpDeploy.m_pIClassAdmin = m_pIClassAdmin;
  652. m_pIClassAdmin->AddRef();
  653. rgPages[nPage++] = CreateThemedPropertySheetPage(&prpDeploy.m_psp);
  654. CUpgradeList prpUpgradeList;
  655. if (pii->PathType != SetupNamePath)
  656. {
  657. //
  658. // Create the upgrades property page
  659. //
  660. prpUpgradeList.m_pData = &m_AppData[m_lLastAllocated];
  661. prpUpgradeList.m_cookie = cookie;
  662. prpUpgradeList.m_pScopePane = this;
  663. prpUpgradeList.m_fPreDeploy = TRUE;
  664. prpUpgradeList.m_fMachine = m_fMachine;
  665. prpUpgradeList.m_fRSOP = m_fRSOP;
  666. #if 0
  667. prpUpgradeList.m_pIGPEInformation = m_pIGPEInformation;
  668. #endif
  669. // no longer need to marshal the interface, just set it
  670. prpUpgradeList.m_pIClassAdmin = m_pIClassAdmin;
  671. m_pIClassAdmin->AddRef();
  672. rgPages[nPage++] = CreateThemedPropertySheetPage(&prpUpgradeList.m_psp);
  673. }
  674. //
  675. // make sure we have an up-to-date categories list
  676. //
  677. ClearCategories();
  678. hr = CsGetAppCategories(&m_CatList);
  679. if (FAILED(hr))
  680. {
  681. // report it
  682. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GETCATEGORIES_ERROR, hr, NULL);
  683. // Since failure only means the categories list will be
  684. // empty, we'll proceed as if nothing happened.
  685. hr = S_OK;
  686. }
  687. //
  688. // Create the Category property page
  689. //
  690. CCategory prpCategory;
  691. prpCategory.m_pData = &m_AppData[m_lLastAllocated];
  692. prpCategory.m_cookie = cookie;
  693. prpCategory.m_pCatList = &m_CatList;
  694. prpCategory.m_fRSOP = m_fRSOP;
  695. prpCategory.m_fPreDeploy = TRUE;
  696. // no longer need to marshal this interface, just set it
  697. prpCategory.m_pIClassAdmin = m_pIClassAdmin;
  698. m_pIClassAdmin->AddRef();
  699. rgPages[nPage++] = CreateThemedPropertySheetPage(&prpCategory.m_psp);
  700. CXforms prpXforms;
  701. if (pii->PathType != SetupNamePath)
  702. {
  703. //
  704. // Create the Xforms property page
  705. //
  706. prpXforms.m_fPreDeploy = TRUE;
  707. prpXforms.m_pData = &m_AppData[m_lLastAllocated];
  708. prpXforms.m_cookie = cookie;
  709. prpXforms.m_pScopePane = this;
  710. // no longer need to marshal the interface, just set it
  711. prpXforms.m_pIClassAdmin = m_pIClassAdmin;
  712. m_pIClassAdmin->AddRef();
  713. rgPages[nPage++] = CreateThemedPropertySheetPage(&prpXforms.m_psp);
  714. }
  715. //
  716. // Create the security property page
  717. //
  718. CString szPath;
  719. hr = GetPackageDSPath(szPath, m_AppData[m_lLastAllocated].m_pDetails->pszPackageName);
  720. if (SUCCEEDED(hr))
  721. {
  722. LPSECURITYINFO pSI;
  723. hr = DSCreateISecurityInfoObject(szPath,
  724. NULL,
  725. 0,
  726. &pSI,
  727. NULL,
  728. NULL,
  729. 0);
  730. if (SUCCEEDED(hr))
  731. {
  732. rgPages[nPage++] = CreateSecurityPage(pSI);
  733. pSI->Release();
  734. }
  735. else
  736. {
  737. DebugMsg((DM_WARNING, TEXT("DSCreateISecurityInfoObject failed with 0x%x"), hr));
  738. }
  739. }
  740. else
  741. {
  742. DebugMsg((DM_WARNING, TEXT("GetPackageDSPath failed with 0x%x"), hr));
  743. }
  744. psh.nPages = nPage;
  745. psh.hwndParent = m_hwndMainWindow;
  746. if (IDOK != PropertySheet(&psh))
  747. {
  748. fAddOk = FALSE;
  749. RemovePackage(cookie, FALSE, TRUE);
  750. }
  751. else
  752. {
  753. // Make sure that the package is deployed with the proper
  754. // deployment type
  755. hr = m_pIClassAdmin->ChangePackageProperties(m_AppData[m_lLastAllocated].m_pDetails->pszPackageName,
  756. NULL,
  757. &m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->dwActFlags,
  758. NULL,
  759. NULL,
  760. NULL,
  761. NULL);
  762. if (SUCCEEDED(hr))
  763. {
  764. if (FAILED(m_pIGPEInformation->PolicyChanged(m_fMachine, TRUE, &guidExtension,
  765. m_fMachine ? &guidMachSnapin
  766. : &guidUserSnapin )))
  767. {
  768. ReportPolicyChangedError(m_hwndMainWindow);
  769. }
  770. }
  771. }
  772. }
  773. if (fAddOk)
  774. {
  775. set <CResultPane *>::iterator i;
  776. for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++)
  777. {
  778. RESULTDATAITEM resultItem;
  779. memset(&resultItem, 0, sizeof(resultItem));
  780. if ((*i)->_fVisible)
  781. {
  782. resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  783. resultItem.str = MMC_CALLBACK;
  784. resultItem.nImage = m_AppData[m_lLastAllocated].GetImageIndex(this);
  785. resultItem.lParam = m_lLastAllocated;
  786. hr = (*i)->m_pResult->InsertItem(&resultItem);
  787. }
  788. // The following code must be excecuted wheather the InsertItem
  789. // call succeeds or not.
  790. // There are legitimate cases when InsertItem will fail. For
  791. // instance, if the scope pane is being shown, but not the
  792. // result pane.
  793. m_AppData[m_lLastAllocated].m_fVisible = TRUE;
  794. m_AppData[m_lLastAllocated].m_itemID = resultItem.itemID;
  795. InsertExtensionEntry(m_lLastAllocated, m_AppData[m_lLastAllocated]);
  796. if (m_pFileExt)
  797. {
  798. m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0);
  799. }
  800. InsertUpgradeEntry(m_lLastAllocated, m_AppData[m_lLastAllocated]);
  801. m_UpgradeIndex[GetUpgradeIndex(m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->PackageGuid)] = m_lLastAllocated;
  802. // if this is an upgrade, set icons for upgraded apps to
  803. // the proper icon and refresh any open property sheets
  804. UINT n = m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->cUpgrades;
  805. while (n--)
  806. {
  807. map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->prgUpgradeInfoList[n].PackageGuid));
  808. if (i != m_UpgradeIndex.end())
  809. {
  810. if (m_AppData[i->second].m_pUpgradeList)
  811. {
  812. m_AppData[i->second].m_pUpgradeList->SendMessage(WM_USER_REFRESH, 0, 0);
  813. }
  814. }
  815. }
  816. if ((*i)->_fVisible)
  817. {
  818. if (SUCCEEDED(hr))
  819. {
  820. (*i)->m_pResult->SetItem(&resultItem);
  821. (*i)->m_pResult->Sort((*i)->m_nSortColumn, (*i)->m_dwSortOptions, -1);
  822. }
  823. else
  824. {
  825. DebugMsg((DM_WARNING, TEXT("InsertItem failed with 0x%x"), hr));
  826. hr = S_OK;
  827. }
  828. }
  829. }
  830. }
  831. }
  832. return hr;
  833. }
  834. //+--------------------------------------------------------------------------
  835. //
  836. // Member: CScopePane::AddZAPPackage
  837. //
  838. // Synopsis:
  839. //
  840. // Arguments: [szPackagePath] -
  841. // [lpFileTitle] -
  842. //
  843. // Returns:
  844. //
  845. // Modifies:
  846. //
  847. // Derivation:
  848. //
  849. // History: 6-29-1998 stevebl Created
  850. //
  851. // Notes:
  852. //
  853. //---------------------------------------------------------------------------
  854. HRESULT CScopePane::AddZAPPackage(LPCOLESTR szPackagePath, LPCOLESTR lpFileTitle)
  855. {
  856. CHourglass hourglass;
  857. HRESULT hr = E_FAIL;
  858. OLECHAR szBuffer[1024];
  859. OLECHAR * sz = szBuffer;
  860. CString szFriendlyName;
  861. CString szUniqueFriendlyName;
  862. int nHint = 1;
  863. DWORD dw = GetPrivateProfileString(
  864. L"Application",
  865. L"FriendlyName",
  866. NULL,
  867. sz,
  868. sizeof(szBuffer) / sizeof(szBuffer[0]),
  869. szPackagePath);
  870. if (0 == dw)
  871. {
  872. // either bogus FriendlyName or no setup command, both of which are fatal
  873. goto bad_script;
  874. }
  875. szFriendlyName = sz; // save this for later
  876. dw = GetPrivateProfileString(
  877. L"Application",
  878. L"SetupCommand",
  879. NULL,
  880. sz,
  881. sizeof(szBuffer) / sizeof(szBuffer[0]),
  882. szPackagePath);
  883. if (0 == dw)
  884. {
  885. // either bogus file or no setup command, both of which are fatal
  886. bad_script:
  887. {
  888. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADZAP_ERROR, HRESULT_FROM_WIN32(dw), lpFileTitle);
  889. TCHAR szBuffer[256];
  890. ::LoadString(ghInstance, IDS_ADDFAILED_ZAP, szBuffer, 256);
  891. m_pConsole->MessageBox(szBuffer,
  892. lpFileTitle,
  893. MB_OK | MB_ICONEXCLAMATION, NULL);
  894. }
  895. return E_FAIL;
  896. }
  897. INSTALLINFO * pii = NULL;
  898. PLATFORMINFO * ppi = NULL;
  899. ACTIVATIONINFO * pai = NULL;
  900. PACKAGEDETAIL *ppd = new PACKAGEDETAIL;
  901. if (!ppd)
  902. {
  903. goto out_of_memory;
  904. }
  905. memset(ppd, 0, sizeof(PACKAGEDETAIL));
  906. pii = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO));
  907. ppd->pInstallInfo = pii;
  908. if (!pii)
  909. {
  910. goto out_of_memory;
  911. }
  912. memset(pii, 0, sizeof(INSTALLINFO));
  913. ppi = (PLATFORMINFO *) OLEALLOC(sizeof(PLATFORMINFO));
  914. ppd->pPlatformInfo = ppi;
  915. if (!ppi)
  916. {
  917. goto out_of_memory;
  918. }
  919. memset(ppi, 0, sizeof(PLATFORMINFO));
  920. pai = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO));
  921. ppd->pActInfo = pai;
  922. if (!pai)
  923. {
  924. goto out_of_memory;
  925. }
  926. else
  927. {
  928. memset(pai, 0, sizeof(ACTIVATIONINFO));
  929. pai->bHasClasses = ! m_ToolDefaults.fExtensionsOnly;
  930. // Munge the setup path.
  931. // surround the path in quotes to be sure that spaces are dealt
  932. // with properly
  933. CString szPath = L'"';
  934. szPath += szPackagePath;
  935. // strip off the package name
  936. int ich = szPath.ReverseFind(L'\\');
  937. // check for either slash symbol (just in case)
  938. int ich2 = szPath.ReverseFind(L'/');
  939. if (ich2 > ich)
  940. {
  941. ich = ich2;
  942. }
  943. if (ich >= 0)
  944. {
  945. szPath = szPath.Left(ich + 1); // keep the path separator
  946. }
  947. // merge it with the setup command string
  948. BOOL fNeedQuote = TRUE;
  949. if (sz[0] == L'"')
  950. {
  951. // remember that we had a leading quote (no need to insert a quote)
  952. // and strip it off
  953. sz++;
  954. fNeedQuote = FALSE;
  955. }
  956. while (sz[0])
  957. {
  958. if (sz[0] == L'.' && sz[1] == L'.' && (sz[2] == L'/' || sz[2] == L'\\'))
  959. {
  960. // strip off the last path element
  961. // First strip off the path separator (the one we kept previously)
  962. szPath = szPath.Left(ich);
  963. // now find the symbol
  964. ich = szPath.ReverseFind(L'\\');
  965. // check for either slash symbol (just in case)
  966. ich2 = szPath.ReverseFind(L'/');
  967. if (ich2 > ich)
  968. {
  969. ich = ich2;
  970. }
  971. if (ich >= 0)
  972. {
  973. szPath = szPath.Left(ich + 1); // keep the path separator
  974. }
  975. // skip the "..\"
  976. sz += 3;
  977. }
  978. else
  979. {
  980. if ((0 != sz[0] && L':' == sz[1])
  981. ||
  982. ((L'\\' == sz[0] || L'/' == sz[0]) && (L'\\' == sz[1] || L'/' == sz[1]))
  983. ||
  984. (0 == wcsncmp(L"http:",sz,5)))
  985. {
  986. // hard path
  987. // throw away szPath;
  988. szPath = L"";
  989. if (!fNeedQuote)
  990. {
  991. // make sure we don't drop that quote
  992. szPath += L'"';
  993. }
  994. // and make sure we don't insert quotes where they're not wanted
  995. fNeedQuote = FALSE;
  996. }
  997. // break the loop on anything other than "..\"
  998. break;
  999. }
  1000. }
  1001. if (fNeedQuote)
  1002. {
  1003. CString szTemp = sz;
  1004. // copy everything up to the first space
  1005. ich = szTemp.Find(L' ');
  1006. szPath += szTemp.Left(ich);
  1007. // then add a quote
  1008. szPath += L'"';
  1009. szPath += szTemp.Mid(ich);
  1010. }
  1011. else
  1012. {
  1013. szPath += sz;
  1014. }
  1015. OLESAFE_COPYSTRING(pii->pszScriptPath, szPath);
  1016. sz = szBuffer;
  1017. dw = GetPrivateProfileString(
  1018. L"Application",
  1019. L"DisplayVersion",
  1020. NULL,
  1021. sz,
  1022. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1023. szPackagePath);
  1024. if (dw)
  1025. {
  1026. // parse product version
  1027. CString sz = szBuffer;
  1028. sz.TrimLeft();
  1029. CString szTemp = sz.SpanIncluding(L"0123456789");
  1030. swscanf(szTemp, L"%u", &pii->dwVersionHi);
  1031. sz = sz.Mid(szTemp.GetLength());
  1032. szTemp = sz.SpanExcluding(L"0123456789");
  1033. sz = sz.Mid(szTemp.GetLength());
  1034. swscanf(sz, L"%u", &pii->dwVersionLo);
  1035. }
  1036. dw = GetPrivateProfileString(
  1037. L"Application",
  1038. L"Publisher",
  1039. NULL,
  1040. sz,
  1041. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1042. szPackagePath);
  1043. if (dw)
  1044. {
  1045. OLESAFE_COPYSTRING(ppd->pszPublisher, sz);
  1046. }
  1047. dw = GetPrivateProfileString(
  1048. L"Application",
  1049. L"URL",
  1050. NULL,
  1051. sz,
  1052. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1053. szPackagePath);
  1054. if (dw)
  1055. {
  1056. OLESAFE_COPYSTRING(pii->pszUrl, sz);
  1057. }
  1058. set<DWORD> sPlatforms;
  1059. dw = GetPrivateProfileString(
  1060. L"Application",
  1061. L"Architecture",
  1062. NULL,
  1063. sz,
  1064. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1065. szPackagePath);
  1066. BOOL fValidPlatform;
  1067. fValidPlatform = FALSE;
  1068. if (dw)
  1069. {
  1070. CString szPlatforms = szBuffer;
  1071. CString szTemp;
  1072. while (szPlatforms.GetLength())
  1073. {
  1074. szTemp = szPlatforms.SpanExcluding(L",");
  1075. if (0 == szTemp.CompareNoCase(L"intel"))
  1076. {
  1077. sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL);
  1078. fValidPlatform = TRUE;
  1079. }
  1080. else if (0 == szTemp.CompareNoCase(L"intel64"))
  1081. {
  1082. sPlatforms.insert(PROCESSOR_ARCHITECTURE_IA64);
  1083. fValidPlatform = TRUE;
  1084. }
  1085. szPlatforms = szPlatforms.Mid(szTemp.GetLength()+1);
  1086. }
  1087. }
  1088. //
  1089. // Ensure that if we saw any platforms, at least one of them
  1090. // was a supported platform
  1091. //
  1092. if ( dw && ! fValidPlatform )
  1093. {
  1094. TCHAR szBuffer[256];
  1095. ::LoadString(ghInstance, IDS_ILLEGAL_PLATFORM, szBuffer, 256);
  1096. m_pConsole->MessageBox(szBuffer,
  1097. lpFileTitle,
  1098. MB_OK | MB_ICONEXCLAMATION, NULL);
  1099. delete ppd;
  1100. return E_FAIL;
  1101. }
  1102. if (0 == sPlatforms.size())
  1103. {
  1104. // If the ZAP file doesn't specify an architecture
  1105. // then we'll treat is as an x86 package
  1106. sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL);
  1107. DebugMsg((DL_VERBOSE, TEXT("No platform detected, assuming x86.")));
  1108. }
  1109. ppi->cPlatforms = sPlatforms.size();
  1110. ppi->prgPlatform = (CSPLATFORM *) OLEALLOC(sizeof(CSPLATFORM) * (ppi->cPlatforms));;
  1111. if (!ppi->prgPlatform)
  1112. {
  1113. ppi->cPlatforms = 0;
  1114. goto out_of_memory;
  1115. }
  1116. set<DWORD>::iterator iPlatform;
  1117. INT n = 0;
  1118. for (iPlatform = sPlatforms.begin(); iPlatform != sPlatforms.end(); iPlatform++, n++)
  1119. {
  1120. ppi->prgPlatform[n].dwPlatformId = VER_PLATFORM_WIN32_NT;
  1121. ppi->prgPlatform[n].dwVersionHi = 5;
  1122. ppi->prgPlatform[n].dwVersionLo = 0;
  1123. ppi->prgPlatform[n].dwProcessorArch = *iPlatform;
  1124. }
  1125. ppi->prgLocale = (LCID *) OLEALLOC(sizeof(LCID));
  1126. if (!ppi->prgLocale)
  1127. {
  1128. goto out_of_memory;
  1129. }
  1130. ppi->cLocales = 1;
  1131. ppi->prgLocale[0] = 0; // if none is supplied we assume language neutral
  1132. dw = GetPrivateProfileString(
  1133. L"Application",
  1134. L"LCID",
  1135. NULL,
  1136. sz,
  1137. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1138. szPackagePath);
  1139. if (dw)
  1140. {
  1141. swscanf(szBuffer, L"%i", &ppi->prgLocale[0]);
  1142. // we only deploy one LCID (the primary one)
  1143. }
  1144. // Get the list of extensions
  1145. dw = GetPrivateProfileString(
  1146. L"ext",
  1147. NULL,
  1148. NULL,
  1149. sz,
  1150. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1151. szPackagePath);
  1152. if (dw)
  1153. {
  1154. vector<CString> v;
  1155. TCHAR szName[256];
  1156. while (sz < &szBuffer[dw])
  1157. {
  1158. while ('.' == sz[0])
  1159. sz++;
  1160. CString szExt = ".";
  1161. szExt += sz;
  1162. v.push_back(szExt);
  1163. sz += (wcslen(sz) + 1);
  1164. }
  1165. // build the new list
  1166. UINT n = v.size();
  1167. if (n > 0)
  1168. {
  1169. pai->prgShellFileExt = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
  1170. if (!pai->prgShellFileExt)
  1171. {
  1172. goto out_of_memory;
  1173. }
  1174. pai->prgPriority = (UINT *) OLEALLOC(sizeof(UINT) * n);
  1175. if (!pai->prgPriority)
  1176. {
  1177. goto out_of_memory;
  1178. }
  1179. pai->cShellFileExt = n;
  1180. while (n--)
  1181. {
  1182. CString &sz = v[n];
  1183. sz.MakeLower();
  1184. OLESAFE_COPYSTRING(pai->prgShellFileExt[n], sz);
  1185. pai->prgPriority[n] = 0;
  1186. }
  1187. }
  1188. }
  1189. // get the list of CLSIDs
  1190. vector<CLASSDETAIL> v;
  1191. sz = szBuffer;
  1192. dw = GetPrivateProfileString(
  1193. L"CLSIDs",
  1194. NULL,
  1195. NULL,
  1196. sz,
  1197. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1198. szPackagePath);
  1199. if (dw)
  1200. {
  1201. while (sz < &szBuffer[dw])
  1202. {
  1203. OLECHAR szType[256];
  1204. DWORD dwSubKey = GetPrivateProfileString(
  1205. L"CLSIDs",
  1206. sz,
  1207. NULL,
  1208. szType,
  1209. sizeof(szType) / sizeof(szType[0]),
  1210. szPackagePath);
  1211. CLASSDETAIL cd;
  1212. memset(&cd, 0, sizeof(CLASSDETAIL));
  1213. hr = CLSIDFromString(sz, &cd.Clsid);
  1214. if (SUCCEEDED(hr))
  1215. {
  1216. CString szTypes = szType;
  1217. szTypes.MakeLower();
  1218. if (szTypes.Find(L"inprocserver32") >= 0)
  1219. {
  1220. cd.dwComClassContext |= CLSCTX_INPROC_SERVER;
  1221. }
  1222. if (szTypes.Find(L"localserver32") >= 0)
  1223. {
  1224. cd.dwComClassContext |= CLSCTX_LOCAL_SERVER;
  1225. }
  1226. if (szTypes.Find(L"inprochandler32") >= 0)
  1227. {
  1228. cd.dwComClassContext |= CLSCTX_INPROC_HANDLER;
  1229. }
  1230. v.push_back(cd);
  1231. }
  1232. sz += (wcslen(sz) + 1);
  1233. }
  1234. }
  1235. // get the list of ProgIDs
  1236. sz = szBuffer;
  1237. dw = GetPrivateProfileString(
  1238. L"ProgIDs",
  1239. NULL,
  1240. NULL,
  1241. sz,
  1242. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1243. szPackagePath);
  1244. if (dw)
  1245. {
  1246. while (sz < &szBuffer[dw])
  1247. {
  1248. OLECHAR szType[256];
  1249. DWORD dwSubKey = GetPrivateProfileString(
  1250. L"ProgIDs",
  1251. sz,
  1252. NULL,
  1253. szType,
  1254. sizeof(szType) / sizeof(szType[0]),
  1255. szPackagePath);
  1256. CLSID cid;
  1257. hr = CLSIDFromString(sz, &cid);
  1258. if (SUCCEEDED(hr))
  1259. {
  1260. // Match it to its CLASSDETAIL structure and insert it into the
  1261. // ProgID list.
  1262. // (fat and slow method)
  1263. vector<CLASSDETAIL>::iterator i;
  1264. for (i = v.begin(); i != v.end(); i++)
  1265. {
  1266. if (0 == memcmp(&i->Clsid, &cid, sizeof(CLSID)))
  1267. {
  1268. // found a match
  1269. // hereiam
  1270. vector <CString> vIds;
  1271. CString szAppIds = szType;
  1272. CString szTemp;
  1273. while (szAppIds.GetLength())
  1274. {
  1275. szTemp = szAppIds.SpanExcluding(L",");
  1276. szTemp.TrimLeft();
  1277. vIds.push_back(szTemp);
  1278. szAppIds = szAppIds.Mid(szTemp.GetLength()+1);
  1279. }
  1280. while (i->cProgId--)
  1281. {
  1282. OLESAFE_DELETE(i->prgProgId[i->cProgId]);
  1283. }
  1284. OLESAFE_DELETE(i->prgProgId);
  1285. DWORD cProgId = vIds.size();
  1286. LPOLESTR * prgProgId = (LPOLESTR *)
  1287. OLEALLOC(sizeof(LPOLESTR) * (cProgId));
  1288. if (!prgProgId)
  1289. {
  1290. goto out_of_memory;
  1291. }
  1292. i->cProgId = cProgId;
  1293. while (cProgId--)
  1294. {
  1295. OLESAFE_COPYSTRING(prgProgId[cProgId], vIds[cProgId]);
  1296. }
  1297. i->prgProgId = prgProgId;
  1298. }
  1299. }
  1300. }
  1301. sz += (wcslen(sz) + 1);
  1302. }
  1303. }
  1304. // create the list of CLASSDETAIL structures
  1305. {
  1306. UINT n = v.size();
  1307. if (n > 0)
  1308. {
  1309. pai->pClasses = (CLASSDETAIL *) OLEALLOC(sizeof(CLASSDETAIL) * n);
  1310. if (!pai->pClasses)
  1311. {
  1312. goto out_of_memory;
  1313. }
  1314. pai->cClasses = n;
  1315. while (n--)
  1316. {
  1317. pai->pClasses[n] = v[n];
  1318. }
  1319. }
  1320. }
  1321. ppd->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR));
  1322. if (!ppd->pszSourceList)
  1323. {
  1324. goto out_of_memory;
  1325. }
  1326. ppd->cSources = 1;
  1327. OLESAFE_COPYSTRING(ppd->pszSourceList[0], szPackagePath);
  1328. GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint);
  1329. OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName);
  1330. // Popup UI
  1331. pii->PathType = SetupNamePath;
  1332. BOOL fShowPropertyPage = FALSE;
  1333. hr = GetDeploymentType(ppd, fShowPropertyPage);
  1334. if (SUCCEEDED(hr))
  1335. {
  1336. CHourglass hourglass;
  1337. if (m_ToolDefaults.fZapOn64)
  1338. {
  1339. pii->dwActFlags |= ACTFLG_ExcludeX86OnIA64; // same as ACTFLG_ZAP_IncludeX86OfIA64
  1340. }
  1341. do
  1342. {
  1343. hr = DeployPackage(ppd, fShowPropertyPage);
  1344. if (hr == CS_E_OBJECT_ALREADY_EXISTS)
  1345. {
  1346. OLESAFE_DELETE(ppd->pszPackageName);
  1347. GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint);
  1348. OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName);
  1349. }
  1350. } while (hr == CS_E_OBJECT_ALREADY_EXISTS);
  1351. }
  1352. if (FAILED(hr) && hr != E_FAIL) // don't report E_FAIL error
  1353. // because it's a benign error
  1354. // (probably a dialog cancellation)
  1355. {
  1356. // report the error in the event log
  1357. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_DEPLOYMENT_ERROR, hr, lpFileTitle);
  1358. // now try to come up with a meaningful message for the user
  1359. TCHAR szBuffer[256];
  1360. if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr)
  1361. {
  1362. // access permission failure
  1363. ::LoadString(ghInstance, IDS_ADDFAILED_ACCESS_DENIED, szBuffer, 256);
  1364. }
  1365. else
  1366. {
  1367. switch (hr)
  1368. {
  1369. // For these errors, we'll report the party line:
  1370. case CS_E_CLASS_NOTFOUND:
  1371. case CS_E_INVALID_VERSION:
  1372. case CS_E_NO_CLASSSTORE:
  1373. case CS_E_OBJECT_NOTFOUND:
  1374. case CS_E_OBJECT_ALREADY_EXISTS:
  1375. case CS_E_INVALID_PATH:
  1376. case CS_E_NETWORK_ERROR:
  1377. case CS_E_ADMIN_LIMIT_EXCEEDED:
  1378. case CS_E_SCHEMA_MISMATCH:
  1379. case CS_E_PACKAGE_NOTFOUND:
  1380. case CS_E_INTERNAL_ERROR:
  1381. {
  1382. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  1383. NULL,
  1384. hr,
  1385. 0,
  1386. szBuffer,
  1387. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1388. NULL);
  1389. if (0 != dw)
  1390. {
  1391. // got a valid message string
  1392. break;
  1393. }
  1394. // otherwise fall through and give the generic message
  1395. }
  1396. // Either these CS errors don't apply or an admin
  1397. // wouldn't know what they mean:
  1398. case CS_E_NOT_DELETABLE:
  1399. default:
  1400. // generic class store problem
  1401. ::LoadString(ghInstance, IDS_ADDFAILED_CSFAILURE, szBuffer, 256);
  1402. break;
  1403. }
  1404. }
  1405. #if DBG
  1406. TCHAR szDebugBuffer[256];
  1407. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  1408. NULL,
  1409. hr,
  1410. 0,
  1411. szDebugBuffer,
  1412. sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]),
  1413. NULL);
  1414. if (0 == dw)
  1415. {
  1416. wsprintf(szDebugBuffer, TEXT("(HRESULT: 0x%lX)"), hr);
  1417. }
  1418. wcscat(szBuffer, szDebugBuffer);
  1419. #endif
  1420. m_pConsole->MessageBox(szBuffer,
  1421. lpFileTitle,
  1422. MB_OK | MB_ICONEXCLAMATION, NULL);
  1423. }
  1424. FreePackageDetail(ppd);
  1425. }
  1426. return hr;
  1427. out_of_memory:
  1428. if (ppd)
  1429. {
  1430. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, E_OUTOFMEMORY);
  1431. InternalFreePackageDetail(ppd);
  1432. delete ppd;
  1433. }
  1434. return E_OUTOFMEMORY;
  1435. }
  1436. //+--------------------------------------------------------------------------
  1437. //
  1438. // Member: CScopePane::AddMSIPackage
  1439. //
  1440. // Synopsis: Add's one or more packages to the class store and adds the
  1441. // appropriate entries to the result pane.
  1442. //
  1443. // Arguments: [szPackagePath] - Full path to the Darwin package.
  1444. // [lpFileTitle] - file title from the open file dialog (used
  1445. // for UI)
  1446. //
  1447. // Returns: S_OK - succeeded
  1448. // E_FAIL - benign failure (probably a cancellation or something)
  1449. // other - significant failure
  1450. //
  1451. // History: 2-03-1998 stevebl Created
  1452. //
  1453. //---------------------------------------------------------------------------
  1454. HRESULT CScopePane::AddMSIPackage(LPCOLESTR szPackagePath, LPCOLESTR lpFileTitle)
  1455. {
  1456. CHourglass hourglass;
  1457. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1458. HRESULT hr = E_FAIL;
  1459. BOOL fPreparationDone = FALSE; // Used to identify if the routine has
  1460. // progressed passed the "prep" stage
  1461. // and is now in the deployment stage.
  1462. // Errors in the earlier part are most
  1463. // likely due to Darwin problems.
  1464. // Errors in teh latter part are most
  1465. // likely due to Class Store problems.
  1466. set<LCID> sLocales;
  1467. CUpgrades dlgUpgrade;
  1468. int nLocales;
  1469. set<LCID>::iterator iLocale;
  1470. PACKAGEDETAIL *ppd = NULL;
  1471. CString szFriendlyName;
  1472. CString szUniqueFriendlyName;
  1473. int nHint = 1;
  1474. ASSERT(m_pConsole);
  1475. {
  1476. BOOL fShowPropertySheet = FALSE;
  1477. GUID guid;
  1478. INSTALLINFO *pii = NULL;
  1479. PLATFORMINFO *ppi = NULL;
  1480. ACTIVATIONINFO *pai = NULL;
  1481. ppd = new PACKAGEDETAIL;
  1482. if (!ppd)
  1483. {
  1484. goto out_of_memory;
  1485. }
  1486. memset(ppd, 0, sizeof(PACKAGEDETAIL));
  1487. pii = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO));
  1488. if (!pii)
  1489. {
  1490. goto out_of_memory;
  1491. }
  1492. memset(pii, 0, sizeof(INSTALLINFO));
  1493. ppi = (PLATFORMINFO *) OLEALLOC(sizeof(PLATFORMINFO));
  1494. ppd->pPlatformInfo = ppi;
  1495. if (!ppi)
  1496. {
  1497. goto out_of_memory;
  1498. }
  1499. ppd->pInstallInfo = pii;
  1500. memset(ppi, 0, sizeof(PLATFORMINFO));
  1501. pai = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO));
  1502. ppd->pActInfo = pai;
  1503. if (!pai)
  1504. {
  1505. goto out_of_memory;
  1506. }
  1507. else
  1508. {
  1509. memset(pai, 0, sizeof(ACTIVATIONINFO));
  1510. pai->bHasClasses = ! m_ToolDefaults.fExtensionsOnly;
  1511. pii->PathType = DrwFilePath;
  1512. hr = GetDeploymentType(ppd, fShowPropertySheet);
  1513. CHourglass hourglass;
  1514. if (FAILED(hr))
  1515. {
  1516. goto done;
  1517. }
  1518. if (!m_ToolDefaults.f32On64)
  1519. {
  1520. pii->dwActFlags |= ACTFLG_ExcludeX86OnIA64; // same as ACTFLG_ZAP_IncludeX86OfIA64
  1521. }
  1522. if (m_ToolDefaults.fUninstallOnPolicyRemoval)
  1523. {
  1524. pii->dwActFlags |= ACTFLG_UninstallOnPolicyRemoval;
  1525. }
  1526. else
  1527. {
  1528. pii->dwActFlags |= ACTFLG_OrphanOnPolicyRemoval;
  1529. }
  1530. if (m_fMachine)
  1531. {
  1532. pii->dwActFlags |= ACTFLG_ForceUpgrade;
  1533. }
  1534. pii->InstallUiLevel = m_ToolDefaults.UILevel;
  1535. // disable MSI ui
  1536. MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
  1537. // Use MsiSummaryInfoGetProperty to get platform and locale info.
  1538. {
  1539. MSIHANDLE hSummaryInfo;
  1540. UINT msiReturn = MsiGetSummaryInformation(0, szPackagePath, 0, &hSummaryInfo);
  1541. if (ERROR_SUCCESS == msiReturn)
  1542. {
  1543. TCHAR szBuffer[256];
  1544. DWORD dwSize = 256;
  1545. msiReturn = MsiSummaryInfoGetProperty(hSummaryInfo,
  1546. 7, // PID_TEMPLATE
  1547. NULL,
  1548. NULL,
  1549. NULL,
  1550. szBuffer,
  1551. &dwSize);
  1552. if (ERROR_SUCCESS == msiReturn)
  1553. {
  1554. // break out the locale and platform properties
  1555. CString szLocales = szBuffer;
  1556. CString szPlatforms = szLocales.SpanExcluding(L";");
  1557. szLocales = szLocales.Mid(szPlatforms.GetLength()+1);
  1558. CString szTemp;
  1559. set<DWORD> sPlatforms;
  1560. BOOL fValidPlatform;
  1561. BOOL fPlatformsSpecified;
  1562. fValidPlatform = FALSE;
  1563. fPlatformsSpecified = 0 != szPlatforms.GetLength();
  1564. while (szPlatforms.GetLength())
  1565. {
  1566. szTemp = szPlatforms.SpanExcluding(L",");
  1567. if (0 == szTemp.CompareNoCase(L"intel"))
  1568. {
  1569. sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL);
  1570. fValidPlatform = TRUE;
  1571. }
  1572. else if (0 == szTemp.CompareNoCase(L"intel64"))
  1573. {
  1574. sPlatforms.insert(PROCESSOR_ARCHITECTURE_IA64);
  1575. fValidPlatform = TRUE;
  1576. }
  1577. szPlatforms = szPlatforms.Mid(szTemp.GetLength()+1);
  1578. }
  1579. //
  1580. // If platforms have been specified, at least one of them
  1581. // must be valid
  1582. //
  1583. if ( fPlatformsSpecified && ! fValidPlatform )
  1584. {
  1585. hr = HRESULT_FROM_WIN32( ERROR_INSTALL_PLATFORM_UNSUPPORTED );
  1586. ppi->cPlatforms = 0;
  1587. goto done;
  1588. }
  1589. while (szLocales.GetLength())
  1590. {
  1591. szTemp = szLocales.SpanExcluding(L",");
  1592. LCID lcid;
  1593. swscanf(szTemp, L"%i", &lcid);
  1594. sLocales.insert(lcid);
  1595. szLocales = szLocales.Mid(szTemp.GetLength()+1);
  1596. }
  1597. if (0 == sPlatforms.size())
  1598. {
  1599. // If the MSI file doesn't specify an architecture
  1600. // then we'll mark it X86-allow on IA64.
  1601. sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL);
  1602. pii->dwActFlags &= ~ACTFLG_ExcludeX86OnIA64;
  1603. DebugMsg((DL_VERBOSE, TEXT("No platform detected, setting to X86 - allow on IA64.")));
  1604. }
  1605. if (0 == sLocales.size())
  1606. {
  1607. // If the MSI file doesn't specify a locale then
  1608. // we'll just assume it's language neutral.
  1609. DebugMsg((DL_VERBOSE, TEXT("No locale detected, assuming neutral.")));
  1610. sLocales.insert(0);
  1611. }
  1612. ppi->cPlatforms = sPlatforms.size();
  1613. ppi->prgPlatform = (CSPLATFORM *) OLEALLOC(sizeof(CSPLATFORM) * (ppi->cPlatforms));;
  1614. if (!ppi->prgPlatform)
  1615. {
  1616. ppi->cPlatforms = 0;
  1617. goto out_of_memory;
  1618. }
  1619. set<DWORD>::iterator iPlatform;
  1620. INT n = 0;
  1621. for (iPlatform = sPlatforms.begin(); iPlatform != sPlatforms.end(); iPlatform++, n++)
  1622. {
  1623. ppi->prgPlatform[n].dwPlatformId = VER_PLATFORM_WIN32_NT;
  1624. ppi->prgPlatform[n].dwVersionHi = 5;
  1625. ppi->prgPlatform[n].dwVersionLo = 0;
  1626. ppi->prgPlatform[n].dwProcessorArch = *iPlatform;
  1627. }
  1628. }
  1629. MsiCloseHandle(hSummaryInfo);
  1630. }
  1631. if (ERROR_SUCCESS != msiReturn)
  1632. {
  1633. hr = HRESULT_FROM_WIN32(msiReturn);
  1634. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle);
  1635. goto done;
  1636. }
  1637. }
  1638. {
  1639. // Grovel through the database to get additional information
  1640. // that for some reason MSI won't give us any other way.
  1641. TCHAR szBuffer[256];
  1642. DWORD cch = 256;
  1643. UINT msiReturn = GetMsiProperty(szPackagePath, L"ProductVersion", szBuffer, &cch);
  1644. if (ERROR_SUCCESS != msiReturn)
  1645. {
  1646. hr = HRESULT_FROM_WIN32(msiReturn);
  1647. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle);
  1648. goto done;
  1649. }
  1650. if (ERROR_SUCCESS == msiReturn)
  1651. {
  1652. // Parse Product Version
  1653. CString sz = szBuffer;
  1654. sz.TrimLeft();
  1655. CString szTemp = sz.SpanIncluding(L"0123456789");
  1656. swscanf(szTemp, L"%u", &pii->dwVersionHi);
  1657. sz = sz.Mid(szTemp.GetLength());
  1658. szTemp = sz.SpanExcluding(L"0123456789");
  1659. sz = sz.Mid(szTemp.GetLength());
  1660. swscanf(sz, L"%u", &pii->dwVersionLo);
  1661. }
  1662. cch = 256;
  1663. msiReturn = GetMsiProperty(szPackagePath, L"ProductCode", szBuffer, &cch);
  1664. if (ERROR_SUCCESS != msiReturn)
  1665. {
  1666. hr = HRESULT_FROM_WIN32(msiReturn);
  1667. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle);
  1668. goto done;
  1669. }
  1670. if (ERROR_SUCCESS == msiReturn)
  1671. {
  1672. // Parse Product Code
  1673. CLSIDFromString(szBuffer, &pii->ProductCode);
  1674. }
  1675. cch = 256;
  1676. msiReturn = GetMsiProperty(szPackagePath, L"ARPHELPLINK", szBuffer, &cch);
  1677. if (ERROR_SUCCESS == msiReturn)
  1678. {
  1679. OLESAFE_COPYSTRING(pii->pszUrl, szBuffer);
  1680. }
  1681. cch = 256;
  1682. msiReturn = GetMsiProperty(szPackagePath, L"LIMITUI", szBuffer, &cch);
  1683. if (ERROR_SUCCESS == msiReturn)
  1684. {
  1685. pii->dwActFlags |= ACTFLG_MinimalInstallUI;
  1686. pii->InstallUiLevel = INSTALLUILEVEL_BASIC;
  1687. }
  1688. }
  1689. ppi->prgLocale = (LCID *) OLEALLOC(sizeof(LCID));
  1690. if (!ppi->prgLocale)
  1691. {
  1692. goto out_of_memory;
  1693. }
  1694. ppi->cLocales = 1;
  1695. ppd->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR));
  1696. if (!ppd->pszSourceList)
  1697. {
  1698. goto out_of_memory;
  1699. }
  1700. ppd->cSources = 1;
  1701. OLESAFE_COPYSTRING(ppd->pszSourceList[0], szPackagePath);
  1702. if (S_OK == DetectUpgrades(szPackagePath, ppd, dlgUpgrade))
  1703. {
  1704. UINT n = dlgUpgrade.m_UpgradeList.size();
  1705. if (n)
  1706. {
  1707. pii->prgUpgradeInfoList = (UPGRADEINFO *) OLEALLOC(sizeof(UPGRADEINFO) * n);
  1708. if (!pii->prgUpgradeInfoList)
  1709. {
  1710. goto out_of_memory;
  1711. }
  1712. pii->cUpgrades = n;
  1713. map<CString, CUpgradeData>::iterator i = dlgUpgrade.m_UpgradeList.begin();
  1714. while (n--)
  1715. {
  1716. pii->prgUpgradeInfoList[n].Flag = i->second.m_flags;
  1717. OLESAFE_COPYSTRING(pii->prgUpgradeInfoList[n].szClassStore, i->second.m_szClassStore);
  1718. memcpy(&pii->prgUpgradeInfoList[n].PackageGuid, &i->second.m_PackageGuid, sizeof(GUID));
  1719. i++;
  1720. }
  1721. }
  1722. }
  1723. //
  1724. // Only one locale may be specified for this package
  1725. //
  1726. nLocales = 1;
  1727. iLocale = sLocales.begin();
  1728. {
  1729. ppi->prgLocale[0] = *iLocale;
  1730. // set the script path
  1731. hr = CoCreateGuid(&guid);
  1732. if (FAILED(hr))
  1733. {
  1734. goto done;
  1735. }
  1736. OLECHAR sz [256];
  1737. StringFromGUID2(guid, sz, 256);
  1738. CString szScriptPath = m_szGPT_Path;
  1739. szScriptPath += L"\\";
  1740. szScriptPath += sz;
  1741. szScriptPath += L".aas";
  1742. OLESAFE_DELETE(pii->pszScriptPath);
  1743. OLESAFE_COPYSTRING(pii->pszScriptPath, szScriptPath);
  1744. HWND hwnd;
  1745. m_pConsole->GetMainWindow(&hwnd);
  1746. hr = BuildScriptAndGetActInfo(*ppd, m_ToolDefaults.fExtensionsOnly);
  1747. // make sure the name is unique
  1748. szFriendlyName = ppd->pszPackageName;
  1749. GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint);
  1750. OLESAFE_DELETE(ppd->pszPackageName);
  1751. OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName);
  1752. if (SUCCEEDED(hr))
  1753. {
  1754. fPreparationDone = TRUE;
  1755. do
  1756. {
  1757. hr = DeployPackage(ppd, fShowPropertySheet);
  1758. if (hr == CS_E_OBJECT_ALREADY_EXISTS)
  1759. {
  1760. GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint);
  1761. OLESAFE_DELETE(ppd->pszPackageName);
  1762. OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName);
  1763. }
  1764. } while (hr == CS_E_OBJECT_ALREADY_EXISTS);
  1765. }
  1766. if (FAILED(hr))
  1767. {
  1768. // clean up script file if deployment fails
  1769. DeleteFile(pii->pszScriptPath);
  1770. }
  1771. }
  1772. done:
  1773. if (FAILED(hr) && hr != E_FAIL) // don't report E_FAIL error
  1774. // because it's a benign error
  1775. // (probably a dialog cancellation)
  1776. {
  1777. // report the error in the event log
  1778. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_DEPLOYMENT_ERROR, hr, lpFileTitle);
  1779. TCHAR szBuffer[256];
  1780. if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr)
  1781. {
  1782. // access permission failure
  1783. ::LoadString(ghInstance, IDS_ADDFAILED_ACCESS_DENIED, szBuffer, 256);
  1784. }
  1785. else if ( HRESULT_FROM_WIN32( ERROR_INSTALL_PLATFORM_UNSUPPORTED ) == hr )
  1786. {
  1787. ::LoadString(ghInstance, IDS_ILLEGAL_PLATFORM, szBuffer, 256);
  1788. }
  1789. else if ( HRESULT_FROM_WIN32( CS_E_ADMIN_LIMIT_EXCEEDED ) == hr )
  1790. {
  1791. ::LoadString(ghInstance, IDS_ADDFAILED_METADATA_OVERFLOW, szBuffer, 256);
  1792. }
  1793. else
  1794. {
  1795. if (fPreparationDone)
  1796. {
  1797. switch (hr)
  1798. {
  1799. // For these errors, we'll report the party line:
  1800. case CS_E_CLASS_NOTFOUND:
  1801. case CS_E_INVALID_VERSION:
  1802. case CS_E_NO_CLASSSTORE:
  1803. case CS_E_OBJECT_NOTFOUND:
  1804. case CS_E_OBJECT_ALREADY_EXISTS:
  1805. case CS_E_INVALID_PATH:
  1806. case CS_E_NETWORK_ERROR:
  1807. case CS_E_SCHEMA_MISMATCH:
  1808. case CS_E_PACKAGE_NOTFOUND:
  1809. case CS_E_INTERNAL_ERROR:
  1810. {
  1811. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  1812. NULL,
  1813. hr,
  1814. 0,
  1815. szBuffer,
  1816. sizeof(szBuffer) / sizeof(szBuffer[0]),
  1817. NULL);
  1818. if (0 != dw)
  1819. {
  1820. // got a valid message string
  1821. break;
  1822. }
  1823. // otherwise fall through and give the generic message
  1824. }
  1825. // Either these CS errors don't apply or an admin
  1826. // wouldn't know what they mean:
  1827. case CS_E_NOT_DELETABLE:
  1828. default:
  1829. // generic class store problem
  1830. ::LoadString(ghInstance, IDS_ADDFAILED_CSFAILURE, szBuffer, 256);
  1831. break;
  1832. }
  1833. }
  1834. else
  1835. {
  1836. // probably some error with the package itself
  1837. ::LoadString(ghInstance, IDS_ADDFAILED, szBuffer, 256);
  1838. }
  1839. }
  1840. #if DBG
  1841. TCHAR szDebugBuffer[256];
  1842. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  1843. NULL,
  1844. hr,
  1845. 0,
  1846. szDebugBuffer,
  1847. sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]),
  1848. NULL);
  1849. if (0 == dw)
  1850. {
  1851. wsprintf(szDebugBuffer, TEXT("(HRESULT: 0x%lX)"), hr);
  1852. }
  1853. wcscat(szBuffer, szDebugBuffer);
  1854. #endif
  1855. m_pConsole->MessageBox(szBuffer,
  1856. lpFileTitle,
  1857. MB_OK | MB_ICONEXCLAMATION, NULL);
  1858. }
  1859. InternalFreePackageDetail(ppd);
  1860. delete ppd;
  1861. }
  1862. }
  1863. return hr;
  1864. out_of_memory:
  1865. if (ppd)
  1866. {
  1867. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, E_OUTOFMEMORY);
  1868. InternalFreePackageDetail(ppd);
  1869. delete ppd;
  1870. }
  1871. return E_OUTOFMEMORY;
  1872. }
  1873. //+--------------------------------------------------------------------------
  1874. //
  1875. // Member: CScopePane::DetectUpgrades
  1876. //
  1877. // Synopsis: This functions checks if any of the existing packages in the
  1878. // class store can be upgraded by a given package. If any such
  1879. // packages exist, then this function populates the m_UpgradeList
  1880. // member of the dlgUpgrade parameter passed to it. This function
  1881. // also adds the upgrade code GUID to the PACKAGEDETAIL structure
  1882. // passed to it.
  1883. //
  1884. // Arguments:
  1885. // szPackagePath - the path of the given package
  1886. // ppd - pointer to the PACKAGEDETAIL structure of the
  1887. // given package
  1888. // dlgUpgrade - the dialog whose member m_UpgradeList needs to be
  1889. // populated
  1890. //
  1891. // Returns:
  1892. // S_OK the function succeeded in finding upgradeable packages
  1893. // S_FALSE the function did not encounter any errors, but no
  1894. // upgradeable packages were found
  1895. // other failure codes the function encountered errors
  1896. //
  1897. // History: 5/19/1998 RahulTh created
  1898. //
  1899. // Notes:
  1900. //
  1901. //---------------------------------------------------------------------------
  1902. HRESULT CScopePane::DetectUpgrades (LPCOLESTR szPackagePath, const PACKAGEDETAIL* ppd, CUpgrades& dlgUpgrade)
  1903. {
  1904. DWORD dwBufSize = 50;
  1905. TCHAR szUpgradeCode[50]; //the upgrade GUID
  1906. GUID guidUpgradeCode;
  1907. TCHAR szData[50];
  1908. DWORD dwOperator;
  1909. HRESULT hr;
  1910. HRESULT hres;
  1911. MSIHANDLE hDatabase;
  1912. UINT msiReturn;
  1913. map<MMC_COOKIE, CAppData>::iterator i;
  1914. INSTALLINFO* pii;
  1915. BOOL fUpgradeable;
  1916. LARGE_INTEGER verNew, verExisting;
  1917. CString szCSPath;
  1918. hr = GetClassStoreName(szCSPath, FALSE);
  1919. if (FAILED(hr))
  1920. {
  1921. DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr));
  1922. }
  1923. msiReturn = GetMsiProperty(szPackagePath, TEXT("UpgradeCode"), szUpgradeCode, &dwBufSize);
  1924. if (ERROR_SUCCESS != msiReturn)
  1925. return HRESULT_FROM_WIN32(msiReturn); //no upgrade code was found
  1926. hr = CLSIDFromString(szUpgradeCode, &guidUpgradeCode);
  1927. if (FAILED(hr))
  1928. return hr;
  1929. //insert the upgrade code GUID into the packagedetail structure.
  1930. memcpy((LPVOID)&(ppd->pInstallInfo->Mvipc), (LPVOID)&guidUpgradeCode, sizeof(GUID));
  1931. verNew.LowPart = ppd->pInstallInfo->dwVersionLo;
  1932. verNew.HighPart = ppd->pInstallInfo->dwVersionHi;
  1933. hr = S_FALSE; //this will get set to S_OK only if we find any upgradeable packages
  1934. msiReturn = MsiOpenDatabase (szPackagePath, MSIDBOPEN_READONLY, &hDatabase);
  1935. if (ERROR_SUCCESS == msiReturn)
  1936. {
  1937. CString szQuery;
  1938. szQuery.Format (TEXT("SELECT `UpgradeCode`, `Attributes`, `VersionMin`, `VersionMax`, `Language` FROM `Upgrade`"));
  1939. MSIHANDLE hView;
  1940. msiReturn = MsiDatabaseOpenView(hDatabase, szQuery, &hView);
  1941. if (ERROR_SUCCESS == msiReturn)
  1942. {
  1943. msiReturn = MsiViewExecute (hView, 0);
  1944. if (ERROR_SUCCESS == msiReturn)
  1945. {
  1946. MSIHANDLE hRecord;
  1947. //for each operator value returned by the query, if an operator is found that permits
  1948. //upgrades, iterate through the list of existing packages to see if any of those are
  1949. //upgradeable by the supplied package. If any such package is found, add it to the
  1950. //m_UpgradeList member of the upgrade dialog dlgUpgrade.
  1951. do
  1952. {
  1953. msiReturn = MsiViewFetch (hView, &hRecord);
  1954. if (ERROR_SUCCESS == msiReturn)
  1955. {
  1956. //reset dwBufSize since it is modified by MsiRecordString during every iteration
  1957. //of the loop.
  1958. dwBufSize = 50;
  1959. //get the upgrade code for this upgrade table entry
  1960. msiReturn = MsiRecordGetString (hRecord, 1, szData, &dwBufSize);
  1961. hres = CLSIDFromString (szData, &guidUpgradeCode);
  1962. if (FAILED(hres))
  1963. {
  1964. MsiCloseHandle(hRecord);
  1965. continue; //ignore this package and move on to the next
  1966. }
  1967. dwBufSize = 50; //must reset to reflect the correct buffer size
  1968. //get the operator for this upgrade table entry
  1969. msiReturn = MsiRecordGetString (hRecord, 2, szData, &dwBufSize);
  1970. swscanf(szData, TEXT("%d"), &dwOperator);
  1971. if (0 == (dwOperator & 0x002))
  1972. {
  1973. // we have a potential hit
  1974. LARGE_INTEGER verMin;
  1975. LARGE_INTEGER verMax;
  1976. // get min version
  1977. dwBufSize = 50; //must reset to reflect the correct buffer size
  1978. BOOL fMin = FALSE;
  1979. msiReturn = MsiRecordGetString (hRecord, 3, szData, &dwBufSize);
  1980. if (ERROR_SUCCESS == msiReturn && 0 != szData[0])
  1981. {
  1982. fMin = TRUE;
  1983. // Parse Product Version
  1984. CString sz = szData;
  1985. sz.TrimLeft();
  1986. CString szTemp = sz.SpanIncluding(L"0123456789");
  1987. swscanf(szTemp, L"%u", &verMin.HighPart);
  1988. sz = sz.Mid(szTemp.GetLength());
  1989. szTemp = sz.SpanExcluding(L"0123456789");
  1990. sz = sz.Mid(szTemp.GetLength());
  1991. swscanf(sz, L"%u", &verMin.LowPart);
  1992. }
  1993. else
  1994. {
  1995. LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath);
  1996. }
  1997. // get max version
  1998. dwBufSize = 50; //must reset to reflect the correct buffer size
  1999. BOOL fMax = FALSE;
  2000. msiReturn = MsiRecordGetString (hRecord, 4, szData, &dwBufSize);
  2001. if (ERROR_SUCCESS == msiReturn && 0 != szData[0])
  2002. {
  2003. fMax = TRUE;
  2004. // Parse Product Version
  2005. CString sz = szData;
  2006. sz.TrimLeft();
  2007. CString szTemp = sz.SpanIncluding(L"0123456789");
  2008. swscanf(szTemp, L"%u", &verMax.HighPart);
  2009. sz = sz.Mid(szTemp.GetLength());
  2010. szTemp = sz.SpanExcluding(L"0123456789");
  2011. sz = sz.Mid(szTemp.GetLength());
  2012. swscanf(sz, L"%u", &verMax.LowPart);
  2013. }
  2014. else
  2015. {
  2016. LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath);
  2017. }
  2018. // get lcid list
  2019. dwBufSize = 0; //must reset to reflect the correct buffer size
  2020. BOOL fLcids = FALSE;
  2021. set<LCID> sLCID;
  2022. msiReturn = MsiRecordGetString (hRecord, 5, szData, &dwBufSize);
  2023. if (ERROR_MORE_DATA == msiReturn)
  2024. {
  2025. dwBufSize++;
  2026. TCHAR * szLanguages = new TCHAR[dwBufSize];
  2027. if (szLanguages)
  2028. {
  2029. msiReturn = MsiRecordGetString (hRecord, 5, szLanguages, &dwBufSize);
  2030. if (ERROR_SUCCESS == msiReturn)
  2031. {
  2032. // build set of LCIDs
  2033. CString sz = szLanguages;
  2034. sz.TrimLeft();
  2035. while (!sz.IsEmpty())
  2036. {
  2037. fLcids = TRUE;
  2038. LCID lcid;
  2039. CString szTemp = sz.SpanIncluding(L"0123456789");
  2040. swscanf(szTemp, L"%u", &lcid);
  2041. sz = sz.Mid(szTemp.GetLength());
  2042. szTemp = sz.SpanExcluding(L"0123456789");
  2043. sz = sz.Mid(szTemp.GetLength());
  2044. sLCID.insert(lcid);
  2045. }
  2046. }
  2047. else
  2048. {
  2049. LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath);
  2050. }
  2051. delete [] szLanguages;
  2052. }
  2053. }
  2054. else
  2055. {
  2056. LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath);
  2057. }
  2058. //if an operator is found that that does not block installs and
  2059. //does not force uninstalling of existing apps, then search
  2060. //for any packages that can be upgraded
  2061. for (i = m_AppData.begin(); i != m_AppData.end(); i++)
  2062. {
  2063. //get the install info. for the app.
  2064. pii = (i->second.m_pDetails)->pInstallInfo;
  2065. //process this only if it has the same upgrade code
  2066. if ( (guidUpgradeCode == pii->Mvipc) && ! IsNullGUID(&guidUpgradeCode) )
  2067. {
  2068. //check if other conditions for the operator are satisfied.
  2069. verExisting.LowPart = pii->dwVersionLo;
  2070. verExisting.HighPart = pii->dwVersionHi;
  2071. // don't even bother to upgrade unless the
  2072. // new version is greater or equal to the
  2073. // old version
  2074. fUpgradeable = (verNew.QuadPart >= verExisting.QuadPart);
  2075. if (fMin && fUpgradeable)
  2076. {
  2077. // check minimum
  2078. if (0 != (dwOperator & 0x100))
  2079. {
  2080. // inclusive
  2081. fUpgradeable = verExisting.QuadPart >= verMin.QuadPart;
  2082. }
  2083. else
  2084. {
  2085. // exclusive
  2086. fUpgradeable = verExisting.QuadPart > verMin.QuadPart;
  2087. }
  2088. }
  2089. if (fMax && fUpgradeable)
  2090. {
  2091. // check maximum
  2092. if (0 != (dwOperator & 0x200))
  2093. {
  2094. // inclusive
  2095. fUpgradeable = verExisting.QuadPart <= verMax.QuadPart;
  2096. }
  2097. else
  2098. {
  2099. // exclusive
  2100. fUpgradeable = verExisting.QuadPart < verMax.QuadPart;
  2101. }
  2102. }
  2103. if (fLcids && fUpgradeable)
  2104. {
  2105. // check the lcid
  2106. BOOL fMatch = FALSE;
  2107. // look for a match
  2108. PLATFORMINFO * ppi = (i->second.m_pDetails)->pPlatformInfo;
  2109. UINT n = ppi->cLocales;
  2110. while ((n--) && !fMatch)
  2111. {
  2112. if (sLCID.end() != sLCID.find(ppi->prgLocale[n]))
  2113. {
  2114. fMatch = TRUE;
  2115. }
  2116. }
  2117. // set the upgradeable flag
  2118. if (0 != (dwOperator & 0x400))
  2119. {
  2120. // exclusive
  2121. fUpgradeable = !fMatch;
  2122. }
  2123. else
  2124. {
  2125. // inclusive
  2126. fUpgradeable = fMatch;
  2127. }
  2128. }
  2129. if (fUpgradeable) //the package in question can be upgraded
  2130. {
  2131. CUpgradeData data;
  2132. data.m_szClassStore = szCSPath;
  2133. memcpy(&data.m_PackageGuid, &pii->PackageGuid, sizeof(GUID));
  2134. data.m_flags = UPGFLG_NoUninstall | UPGFLG_Enforced;
  2135. dlgUpgrade.m_UpgradeList.insert(pair<const CString, CUpgradeData>(GetUpgradeIndex(data.m_PackageGuid), data));
  2136. hr = S_OK;
  2137. }
  2138. }
  2139. }
  2140. }
  2141. MsiCloseHandle(hRecord);
  2142. }
  2143. } while (NULL != hRecord && ERROR_SUCCESS == msiReturn);
  2144. MsiViewClose (hView); //close the view to be on the safe side, though it is not absolutely essential
  2145. }
  2146. else
  2147. hr = HRESULT_FROM_WIN32(msiReturn);
  2148. MsiCloseHandle(hView);
  2149. }
  2150. else
  2151. hr = HRESULT_FROM_WIN32(msiReturn);
  2152. MsiCloseHandle (hDatabase);
  2153. }
  2154. else
  2155. hr = HRESULT_FROM_WIN32(msiReturn);
  2156. if (FAILED(hr))
  2157. {
  2158. if (msiReturn != ERROR_SUCCESS)
  2159. {
  2160. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, szPackagePath);
  2161. }
  2162. else
  2163. {
  2164. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, hr);
  2165. }
  2166. }
  2167. return hr;
  2168. }
  2169. //+--------------------------------------------------------------------------
  2170. //
  2171. // Member: CScopePane::DisplayPropSheet
  2172. //
  2173. // Synopsis: a generic routine for showing the property sheet for a package
  2174. //
  2175. // Arguments: [szPackeName] - name of the package to show properties for
  2176. // [iPage] - index of the preferred page to display
  2177. //
  2178. // Returns: nothing
  2179. //
  2180. // History: 3-11-1998 stevebl Created
  2181. //
  2182. // Notes: The property sheet will be started on the preferred page
  2183. // only if it isn't already being displayed, in which case
  2184. // whatever page was being displayed will retain the focus.
  2185. //
  2186. //---------------------------------------------------------------------------
  2187. void CScopePane::DisplayPropSheet(CString szPackageName, int iPage)
  2188. {
  2189. map <MMC_COOKIE, CAppData>::iterator i = m_AppData.begin();
  2190. while (i != m_AppData.end())
  2191. {
  2192. if (0 == szPackageName.Compare(i->second.m_pDetails->pszPackageName))
  2193. {
  2194. IDataObject * pDataObject;
  2195. HRESULT hr = QueryDataObject(i->first, CCT_RESULT, &pDataObject);
  2196. if (SUCCEEDED(hr))
  2197. {
  2198. set <CResultPane *>::iterator i2;
  2199. for (i2 = m_sResultPane.begin(); i2 != m_sResultPane.end(); i2++)
  2200. {
  2201. hr = m_pIPropertySheetProvider->FindPropertySheet(i->first, (*i2), pDataObject);
  2202. if (S_FALSE == hr)
  2203. {
  2204. m_pIPropertySheetProvider->CreatePropertySheet(i->second.m_pDetails->pszPackageName, TRUE, i->first, pDataObject, 0);
  2205. m_pIPropertySheetProvider->AddPrimaryPages((*i2)->GetUnknown(), FALSE, NULL, FALSE);
  2206. m_pIPropertySheetProvider->AddExtensionPages();
  2207. m_pIPropertySheetProvider->Show(NULL, iPage);
  2208. }
  2209. }
  2210. }
  2211. return;
  2212. }
  2213. i++;
  2214. }
  2215. }
  2216. //+--------------------------------------------------------------------------
  2217. //
  2218. // Member: CScopePane::RemovePackage
  2219. //
  2220. // Synopsis: Removes a package from the class store and the result pane.
  2221. //
  2222. // Arguments: [pDataObject] - data object for this result pane item
  2223. // [fForceUninstall] - TRUE - force app to be uninstalled on
  2224. // client machines
  2225. // FALSE - orphan any installations
  2226. //
  2227. // Returns: S_OK - success
  2228. //
  2229. // History: 2-03-1998 stevebl Created
  2230. // 3-30-1998 stevebl adde fForceUninstall
  2231. //
  2232. // Notes: bAssigned is used
  2233. //
  2234. //---------------------------------------------------------------------------
  2235. HRESULT CScopePane::RemovePackage(MMC_COOKIE cookie, BOOL fForceUninstall, BOOL fRemoveNow)
  2236. {
  2237. BOOL fAssigned;
  2238. HRESULT hr = E_FAIL;
  2239. // put up an hourglass (this could take a while)
  2240. CHourglass hourglass;
  2241. CAppData & data = m_AppData[cookie];
  2242. CString szPackageName = data.m_pDetails->pszPackageName;
  2243. // We are now not removing script files here; instead the script
  2244. // file will be removed by the class store code when the package
  2245. // is actually removed from the DS.
  2246. #if 0
  2247. // only remove script files for packages that have script files
  2248. if (data.m_pDetails->pInstallInfo->PathType == DrwFilePath)
  2249. {
  2250. // We need to make sure it gets removed from
  2251. // the GPT before we delete it from the class store.
  2252. // check to see if it's an old style relative path
  2253. if (L'\\' != data.m_pDetails->pInstallInfo->pszScriptPath[0])
  2254. {
  2255. // find the last element in the path
  2256. int iBreak = m_szGPT_Path.ReverseFind(L'{');
  2257. CString sz = m_szGPT_Path.Left(iBreak-1);
  2258. sz += L"\\";
  2259. sz += data.m_pDetails->pInstallInfo->pszScriptPath;
  2260. DeleteFile(sz);
  2261. }
  2262. else
  2263. DeleteFile(data.m_pDetails->pInstallInfo->pszScriptPath);
  2264. }
  2265. #endif
  2266. if (0 != (data.m_pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned))
  2267. {
  2268. fAssigned = TRUE;
  2269. }
  2270. else
  2271. {
  2272. fAssigned = FALSE;
  2273. }
  2274. hr = m_pIClassAdmin->RemovePackage((LPOLESTR)((LPCOLESTR)(data.m_pDetails->pszPackageName)),
  2275. fRemoveNow ? 0 :
  2276. ((fForceUninstall ? ACTFLG_Uninstall : ACTFLG_Orphan) |
  2277. (data.m_pDetails->pInstallInfo->dwActFlags &
  2278. (ACTFLG_ExcludeX86OnIA64 | ACTFLG_IgnoreLanguage))) );
  2279. if (SUCCEEDED(hr))
  2280. {
  2281. // Notify clients of change
  2282. if (FAILED(m_pIGPEInformation->PolicyChanged(m_fMachine, TRUE, &guidExtension,
  2283. m_fMachine ? &guidMachSnapin
  2284. : &guidUserSnapin)))
  2285. {
  2286. ReportPolicyChangedError(m_hwndMainWindow);
  2287. }
  2288. #if 0
  2289. if (data.m_fVisible)
  2290. {
  2291. set <CResultPane *>::iterator i;
  2292. for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++)
  2293. {
  2294. (*i)->m_pResult->DeleteItem(data.m_itemID, 0);
  2295. }
  2296. }
  2297. if (SUCCEEDED(hr))
  2298. {
  2299. CString szCSPath;
  2300. hr = GetClassStoreName(szCSPath, FALSE);
  2301. if (FAILED(hr))
  2302. {
  2303. DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr));
  2304. }
  2305. // remove its entries in the extension table
  2306. RemoveExtensionEntry(cookie, data);
  2307. if (m_pFileExt)
  2308. {
  2309. m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0);
  2310. }
  2311. RemoveUpgradeEntry(cookie, data);
  2312. m_UpgradeIndex.erase(GetUpgradeIndex(data.m_pDetails->pInstallInfo->PackageGuid));
  2313. // If this thing upgraded other apps or had apps that were
  2314. // upgrading, make sure that they get the proper icons and any
  2315. // property sheets get updated.
  2316. UINT n = data.m_pDetails->pInstallInfo->cUpgrades;
  2317. while (n--)
  2318. {
  2319. map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(data.m_pDetails->pInstallInfo->prgUpgradeInfoList[n].PackageGuid));
  2320. if (i != m_UpgradeIndex.end())
  2321. {
  2322. RESULTDATAITEM rd;
  2323. memset(&rd, 0, sizeof(rd));
  2324. rd.mask = RDI_IMAGE;
  2325. rd.itemID = m_AppData[i->second].m_itemID;
  2326. rd.nImage = m_AppData[i->second].GetImageIndex(this);
  2327. set <CResultPane *>::iterator i2;
  2328. for (i2 = m_sResultPane.begin(); i2 != m_sResultPane.end(); i2++)
  2329. {
  2330. (*i2)->m_pResult->SetItem(&rd);
  2331. }
  2332. if (m_AppData[i->second].m_pUpgradeList)
  2333. {
  2334. m_AppData[i->second].m_pUpgradeList->SendMessage(WM_USER_REFRESH, 0, 0);
  2335. }
  2336. }
  2337. }
  2338. FreePackageDetail(data.m_pDetails);
  2339. m_AppData.erase(cookie);
  2340. set <CResultPane *>::iterator i;
  2341. for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++)
  2342. {
  2343. (*i)->m_pResult->Sort((*i)->m_nSortColumn, (*i)->m_dwSortOptions, -1);
  2344. }
  2345. }
  2346. #else
  2347. // just force a refresh
  2348. Refresh();
  2349. }
  2350. #endif
  2351. else
  2352. {
  2353. DebugMsg((DM_WARNING, TEXT("RemovePackage failed with 0x%x"), hr));
  2354. }
  2355. if (FAILED(hr) && hr != E_FAIL) // don't report E_FAIL error
  2356. {
  2357. LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_REMOVE_ERROR, hr, data.m_pDetails->pszPackageName);
  2358. TCHAR szBuffer[256];
  2359. if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr)
  2360. {
  2361. // access permission failure
  2362. ::LoadString(ghInstance, IDS_DELFAILED_ACCESS_DENIED, szBuffer, 256);
  2363. }
  2364. else
  2365. {
  2366. switch (hr)
  2367. {
  2368. // For these errors, we'll report the party line:
  2369. case CS_E_CLASS_NOTFOUND:
  2370. case CS_E_INVALID_VERSION:
  2371. case CS_E_NO_CLASSSTORE:
  2372. case CS_E_OBJECT_NOTFOUND:
  2373. case CS_E_OBJECT_ALREADY_EXISTS:
  2374. case CS_E_INVALID_PATH:
  2375. case CS_E_NETWORK_ERROR:
  2376. case CS_E_ADMIN_LIMIT_EXCEEDED:
  2377. case CS_E_SCHEMA_MISMATCH:
  2378. case CS_E_PACKAGE_NOTFOUND:
  2379. case CS_E_INTERNAL_ERROR:
  2380. case CS_E_NOT_DELETABLE:
  2381. {
  2382. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  2383. NULL,
  2384. hr,
  2385. 0,
  2386. szBuffer,
  2387. sizeof(szBuffer) / sizeof(szBuffer[0]),
  2388. NULL);
  2389. if (0 != dw)
  2390. {
  2391. // got a valid message string
  2392. break;
  2393. }
  2394. // otherwise fall through and give the generic message
  2395. }
  2396. // Either these CS errors don't apply or an admin
  2397. // wouldn't know what they mean:
  2398. default:
  2399. // generic class store problem
  2400. ::LoadString(ghInstance, IDS_DELFAILED_CSFAILURE, szBuffer, 256);
  2401. break;
  2402. }
  2403. }
  2404. #if DBG
  2405. TCHAR szDebugBuffer[256];
  2406. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  2407. NULL,
  2408. hr,
  2409. 0,
  2410. szDebugBuffer,
  2411. sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]),
  2412. NULL);
  2413. if (0 == dw)
  2414. {
  2415. wsprintf(szDebugBuffer, TEXT("(HRESULT: 0x%lX)"), hr);
  2416. }
  2417. wcscat(szBuffer, szDebugBuffer);
  2418. #endif
  2419. m_pConsole->MessageBox(szBuffer,
  2420. szPackageName,
  2421. MB_OK | MB_ICONEXCLAMATION, NULL);
  2422. }
  2423. return hr;
  2424. }
  2425. //+--------------------------------------------------------------------------
  2426. //
  2427. // Member: CScopePane::PopulateUpgradeLists
  2428. //
  2429. // Synopsis: Walks the list of apps, making sure that all the upgrade
  2430. // tables are complete.
  2431. //
  2432. // Arguments: none
  2433. //
  2434. // Returns:
  2435. //
  2436. // History: 2-02-1998 stevebl Created
  2437. //
  2438. //---------------------------------------------------------------------------
  2439. HRESULT CScopePane::PopulateUpgradeLists()
  2440. {
  2441. HRESULT hr = S_OK;
  2442. // For each app in the list, insert an entry in the upgrade tables of
  2443. // the apps it upgrades.
  2444. map <MMC_COOKIE, CAppData>::iterator iAppData;
  2445. for (iAppData=m_AppData.begin(); iAppData != m_AppData.end(); iAppData++)
  2446. {
  2447. hr = InsertUpgradeEntry(iAppData->first, iAppData->second);
  2448. if (FAILED(hr))
  2449. {
  2450. return hr;
  2451. }
  2452. }
  2453. return hr;
  2454. }
  2455. //+--------------------------------------------------------------------------
  2456. //
  2457. // Member: CScopePane::InsertUpgradeEntry
  2458. //
  2459. // Synopsis: For every app that this app upgrades, place an entry in its
  2460. // upgrades set so that it points back to this one.
  2461. //
  2462. // Arguments: [cookie] -
  2463. // [data] -
  2464. //
  2465. // Returns:
  2466. //
  2467. // History: 2-02-1998 stevebl Created
  2468. //
  2469. // Notes: Needs to be able to deal with scripts that might not be in
  2470. // this OU.
  2471. //
  2472. //---------------------------------------------------------------------------
  2473. HRESULT CScopePane::InsertUpgradeEntry(MMC_COOKIE cookie, CAppData & data)
  2474. {
  2475. CString szCSPath;
  2476. HRESULT hr = GetClassStoreName(szCSPath, FALSE);
  2477. if (FAILED(hr))
  2478. {
  2479. DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr));
  2480. }
  2481. UINT n = data.m_pDetails->pInstallInfo->cUpgrades;
  2482. while (n--)
  2483. {
  2484. map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(data.m_pDetails->pInstallInfo->prgUpgradeInfoList[n].PackageGuid));
  2485. if (m_UpgradeIndex.end() != i)
  2486. {
  2487. // Make sure the entry isn't already added:
  2488. INSTALLINFO * pii = m_AppData[i->second].m_pDetails->pInstallInfo;
  2489. BOOL fExists = FALSE;
  2490. UINT n = pii->cUpgrades;
  2491. while (n--)
  2492. {
  2493. if (0 == memcmp(&data.m_pDetails->pInstallInfo->PackageGuid, &pii->prgUpgradeInfoList[n].PackageGuid, sizeof(GUID)))
  2494. {
  2495. // it already exists
  2496. fExists = TRUE;
  2497. break;
  2498. }
  2499. }
  2500. if (!fExists)
  2501. {
  2502. // Add the entry to this app.
  2503. // We don't need to update the class store because it should
  2504. // maintain referential integrity for us. But we do need to
  2505. // update our own internal structures so we're consistent with
  2506. // what's in the class store.
  2507. UINT n = ++(pii->cUpgrades);
  2508. UPGRADEINFO * prgUpgradeInfoList = (UPGRADEINFO *)OLEALLOC(sizeof(UPGRADEINFO) * n);
  2509. if (!prgUpgradeInfoList)
  2510. {
  2511. // out of memory
  2512. // back out the change (this would be unfortunate but not fatal)
  2513. pii->cUpgrades--;
  2514. }
  2515. else
  2516. {
  2517. if (n > 1)
  2518. {
  2519. memcpy(prgUpgradeInfoList, pii->prgUpgradeInfoList, sizeof(UPGRADEINFO) * (n-1));
  2520. OLESAFE_DELETE(pii->prgUpgradeInfoList);
  2521. }
  2522. OLESAFE_COPYSTRING(prgUpgradeInfoList[n-1].szClassStore, (LPOLESTR)((LPCWSTR)szCSPath));
  2523. memcpy(&prgUpgradeInfoList[n-1].PackageGuid, &data.m_pDetails->pInstallInfo->PackageGuid, sizeof(GUID));
  2524. prgUpgradeInfoList[n-1].Flag = UPGFLG_UpgradedBy;
  2525. pii->prgUpgradeInfoList = prgUpgradeInfoList;
  2526. }
  2527. }
  2528. }
  2529. }
  2530. return S_OK;
  2531. }
  2532. //+--------------------------------------------------------------------------
  2533. //
  2534. // Member: CScopePane::RemoveUpgradeEntry
  2535. //
  2536. // Synopsis: For every app that this app upgraded, remove the entry from
  2537. // its upgrades set.
  2538. //
  2539. // Arguments: [cookie] -
  2540. // [data] -
  2541. //
  2542. // Returns:
  2543. //
  2544. // History: 2-02-1998 stevebl Created
  2545. //
  2546. // Notes: Needs to be able to deal with scripts that might not be in
  2547. // this OU.
  2548. //
  2549. //---------------------------------------------------------------------------
  2550. HRESULT CScopePane::RemoveUpgradeEntry(MMC_COOKIE cookie, CAppData & data)
  2551. {
  2552. UINT n = data.m_pDetails->pInstallInfo->cUpgrades;
  2553. while (n--)
  2554. {
  2555. map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(data.m_pDetails->pInstallInfo->prgUpgradeInfoList[n].PackageGuid));
  2556. if (m_UpgradeIndex.end() != i)
  2557. {
  2558. // Find which entry needs to be erased.
  2559. INSTALLINFO * pii = m_AppData[i->second].m_pDetails->pInstallInfo;
  2560. UINT n = pii->cUpgrades;
  2561. while (n--)
  2562. {
  2563. if (0 == memcmp(&data.m_pDetails->pInstallInfo->PackageGuid, &pii->prgUpgradeInfoList[n].PackageGuid, sizeof(GUID)))
  2564. {
  2565. // Now free this entry, copy the last entry over this
  2566. // one and decrement cUpgrades. Don't need to actually
  2567. // reallocate the array because it will be freed later.
  2568. OLESAFE_DELETE(pii->prgUpgradeInfoList[n].szClassStore);
  2569. if (--(pii->cUpgrades))
  2570. {
  2571. memcpy(&pii->prgUpgradeInfoList[n], &pii->prgUpgradeInfoList[pii->cUpgrades], sizeof(UPGRADEINFO));
  2572. }
  2573. else
  2574. {
  2575. OLESAFE_DELETE(pii->prgUpgradeInfoList);
  2576. }
  2577. // If we ever were to need to update the class store,
  2578. // this is where we would do it.
  2579. break;
  2580. }
  2581. }
  2582. }
  2583. }
  2584. return S_OK;
  2585. }
  2586. //+--------------------------------------------------------------------------
  2587. //
  2588. // Member: CScopePane::PopulateExtensions
  2589. //
  2590. // Synopsis: Builds the file extension table from the list of applications.
  2591. //
  2592. // Arguments: (none)
  2593. //
  2594. // Returns:
  2595. //
  2596. // History: 1-29-1998 stevebl Created
  2597. //
  2598. //---------------------------------------------------------------------------
  2599. HRESULT CScopePane::PopulateExtensions()
  2600. {
  2601. HRESULT hr = S_OK;
  2602. // first erase the old extension list
  2603. m_Extensions.erase(m_Extensions.begin(), m_Extensions.end());
  2604. // now add each app's extensions to the table
  2605. map <MMC_COOKIE, CAppData>::iterator iAppData;
  2606. for (iAppData=m_AppData.begin(); iAppData != m_AppData.end(); iAppData++)
  2607. {
  2608. hr = InsertExtensionEntry(iAppData->first, iAppData->second);
  2609. if (FAILED(hr))
  2610. {
  2611. return hr;
  2612. }
  2613. }
  2614. if (m_pFileExt)
  2615. {
  2616. m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0);
  2617. }
  2618. return hr;
  2619. }
  2620. //+--------------------------------------------------------------------------
  2621. //
  2622. // Member: CScopePane::InsertExtensionEntry
  2623. //
  2624. // Synopsis: Adds a single entry to the extension tables.
  2625. //
  2626. // Arguments: [cookie] -
  2627. // [data] -
  2628. //
  2629. // Returns:
  2630. //
  2631. // History: 1-29-1998 stevebl Created
  2632. //
  2633. //---------------------------------------------------------------------------
  2634. HRESULT CScopePane::InsertExtensionEntry(MMC_COOKIE cookie, CAppData & data)
  2635. {
  2636. UINT n = data.m_pDetails->pActInfo->cShellFileExt;
  2637. while (n--)
  2638. {
  2639. m_Extensions[data.m_pDetails->pActInfo->prgShellFileExt[n]].insert(cookie);
  2640. }
  2641. return S_OK;
  2642. }
  2643. //+--------------------------------------------------------------------------
  2644. //
  2645. // Member: CScopePane::RemoveExtensionEntry
  2646. //
  2647. // Synopsis: Removes ane entry from the extension tables.
  2648. //
  2649. // Arguments: [cookie] -
  2650. // [data] -
  2651. //
  2652. // Returns:
  2653. //
  2654. // History: 1-29-1998 stevebl Created
  2655. //
  2656. //---------------------------------------------------------------------------
  2657. HRESULT CScopePane::RemoveExtensionEntry(MMC_COOKIE cookie, CAppData & data)
  2658. {
  2659. UINT n = data.m_pDetails->pActInfo->cShellFileExt;
  2660. while (n--)
  2661. {
  2662. m_Extensions[data.m_pDetails->pActInfo->prgShellFileExt[n]].erase(cookie);
  2663. if (m_Extensions[data.m_pDetails->pActInfo->prgShellFileExt[n]].empty())
  2664. {
  2665. m_Extensions.erase(data.m_pDetails->pActInfo->prgShellFileExt[n]);
  2666. }
  2667. }
  2668. return S_OK;
  2669. }
  2670. //+--------------------------------------------------------------------------
  2671. //
  2672. // Member: CScopePane::PrepareExtensions
  2673. //
  2674. // Synopsis: Sets extension priorities so that this data can be inserted
  2675. // into the extension list with the proper priority.
  2676. //
  2677. // Arguments: [pd] -
  2678. //
  2679. // Returns:
  2680. //
  2681. // Modifies:
  2682. //
  2683. // Derivation:
  2684. //
  2685. // History: 1-29-1998 stevebl Created
  2686. //
  2687. //---------------------------------------------------------------------------
  2688. HRESULT CScopePane::PrepareExtensions(PACKAGEDETAIL &pd)
  2689. {
  2690. UINT n = pd.pActInfo->cShellFileExt;
  2691. while (n--)
  2692. {
  2693. // For each extension that is going to be added, we need to assign
  2694. // it a priority that is one larger than the largest priority
  2695. // already added.
  2696. // NOTE: The odds of this number rolling over to 0 are so
  2697. // unlikely that it would be pointless to check for it. In any case
  2698. // the results of such a bug would be easy for the admin to remedy
  2699. // via the file extension priority dialog.
  2700. pd.pActInfo->prgPriority[n] = 0;
  2701. EXTLIST::iterator i;
  2702. CString sz = pd.pActInfo->prgShellFileExt[n];
  2703. for (i= m_Extensions[sz].begin(); i != m_Extensions[sz].end(); i++)
  2704. {
  2705. // look for the entry that matches this file extension
  2706. CAppData & data = m_AppData[*i];
  2707. UINT n2 = data.m_pDetails->pActInfo->cShellFileExt;
  2708. while (n2--)
  2709. {
  2710. if (0 == sz.CompareNoCase(data.m_pDetails->pActInfo->prgShellFileExt[n2]))
  2711. {
  2712. break;
  2713. }
  2714. }
  2715. if (data.m_pDetails->pActInfo->prgPriority[n2] >= pd.pActInfo->prgPriority[n])
  2716. {
  2717. pd.pActInfo->prgPriority[n] = data.m_pDetails->pActInfo->prgPriority[n2] + 1;
  2718. }
  2719. }
  2720. }
  2721. return S_OK;
  2722. }
  2723. //+--------------------------------------------------------------------------
  2724. //
  2725. // Member: CScopePane::ChangePackageState
  2726. //
  2727. // Synopsis: Changes the state of a package and puts up advisory message
  2728. // boxes informing the admin about the effects of the change.
  2729. //
  2730. // Arguments: [data] - entry to change
  2731. // [dwNewState] - new state
  2732. //
  2733. // History: 2-03-1998 stevebl Created
  2734. //
  2735. //---------------------------------------------------------------------------
  2736. STDMETHODIMP CScopePane::ChangePackageState(CAppData &data, DWORD dwNewState, BOOL fShowUI)
  2737. {
  2738. HRESULT hr = S_OK;
  2739. // first detect what's changed
  2740. DWORD dwOldState = data.m_pDetails->pInstallInfo->dwActFlags;
  2741. DWORD dwChange = dwOldState ^ dwNewState;
  2742. if (dwChange)
  2743. {
  2744. // commit changes
  2745. hr = m_pIClassAdmin->ChangePackageProperties(data.m_pDetails->pszPackageName, NULL, &dwNewState, NULL, NULL, NULL, NULL);
  2746. if (SUCCEEDED(hr))
  2747. {
  2748. if (data.m_fVisible)
  2749. {
  2750. data.m_pDetails->pInstallInfo->dwActFlags = dwNewState;
  2751. RESULTDATAITEM rd;
  2752. memset(&rd, 0, sizeof(rd));
  2753. rd.mask = RDI_IMAGE;
  2754. rd.itemID = data.m_itemID;
  2755. rd.nImage = data.GetImageIndex(this);
  2756. set <CResultPane *>::iterator i;
  2757. for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++)
  2758. {
  2759. (*i)->m_pResult->SetItem(&rd);
  2760. (*i)->m_pResult->Sort((*i)->m_nSortColumn, (*i)->m_dwSortOptions, -1);
  2761. }
  2762. }
  2763. data.NotifyChange();
  2764. if (FAILED(m_pIGPEInformation->PolicyChanged(m_fMachine, TRUE, &guidExtension,
  2765. m_fMachine ? &guidMachSnapin
  2766. : &guidUserSnapin)))
  2767. {
  2768. ReportPolicyChangedError(m_hwndMainWindow);
  2769. }
  2770. }
  2771. else
  2772. {
  2773. DebugMsg((DM_WARNING, TEXT("ChangePackageProperties failed with 0x%x"), hr));
  2774. }
  2775. }
  2776. return hr;
  2777. }
  2778. HRESULT CScopePane::ClearCategories()
  2779. {
  2780. while (m_CatList.cCategory)
  2781. {
  2782. m_CatList.cCategory--;
  2783. OLESAFE_DELETE(m_CatList.pCategoryInfo[m_CatList.cCategory].pszDescription);
  2784. }
  2785. OLESAFE_DELETE(m_CatList.pCategoryInfo);
  2786. return S_OK;
  2787. }
  2788. //+--------------------------------------------------------------------------
  2789. //
  2790. // Function: GetUpgradeIndex
  2791. //
  2792. // Synopsis: utility function that returns an upgrade index entry for a package.
  2793. //
  2794. // Arguments: [PackageID] - the PackageID guid
  2795. //
  2796. // Returns: S_OK on success
  2797. //
  2798. // History: 8-12-1998 stevebl Created
  2799. //
  2800. // Notes: Pretty simple really, the index is just the string form of
  2801. // the GUID.
  2802. //
  2803. //---------------------------------------------------------------------------
  2804. CString GetUpgradeIndex(GUID & PackageID)
  2805. {
  2806. CString szIndex;
  2807. WCHAR wsz[256];
  2808. StringFromGUID2(PackageID, wsz, 256);
  2809. return wsz;
  2810. }
  2811. //+--------------------------------------------------------------------------
  2812. //
  2813. // Member: CScopePane::GetPackageNameFromUpgradeInfo
  2814. //
  2815. // Synopsis: returns the name of a package given its PackageGuid and CSPath
  2816. //
  2817. // Arguments: [szPackageName] - [out] name of the package associated with
  2818. // this script
  2819. // [szScript] - [in] path to the script
  2820. //
  2821. // Returns: S_OK - found a package associated with this script
  2822. // (other) - failed to find a package (could be for any number
  2823. // of reasons)
  2824. //
  2825. // History: 4-07-1998 stevebl Created
  2826. //
  2827. // Notes: In cases where the package does not reside in this
  2828. // container, the package name will be returned as
  2829. // "Package Name (container name)"
  2830. // Note that this does not return the friendly name of the
  2831. // MSI package, it returns the name of the package entry in the
  2832. // class store. The two are not always the same.
  2833. //
  2834. //---------------------------------------------------------------------------
  2835. HRESULT CScopePane::GetPackageNameFromUpgradeInfo(CString & szPackageName, GUID &PackageGuid, LPOLESTR szCSPath)
  2836. {
  2837. HRESULT hr;
  2838. IEnumPackage * pIPE = NULL;
  2839. CString szMyCSPath;
  2840. hr = GetClassStoreName(szMyCSPath, FALSE);
  2841. if (FAILED(hr))
  2842. {
  2843. DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr));
  2844. }
  2845. // see if it's in our container
  2846. if (0 == _wcsicmp((LPOLESTR)((LPCWSTR)szMyCSPath), szCSPath))
  2847. {
  2848. hr = E_FAIL;
  2849. map <CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(PackageGuid));
  2850. if (m_UpgradeIndex.end() != i)
  2851. {
  2852. szPackageName = m_AppData[i->second].m_pDetails->pszPackageName;
  2853. hr = S_OK;
  2854. }
  2855. }
  2856. else
  2857. {
  2858. IClassAdmin * pIClassAdmin;
  2859. hr = CsGetClassStore((LPOLESTR)((LPCOLESTR)szCSPath), (LPVOID*)&pIClassAdmin);
  2860. if (SUCCEEDED(hr))
  2861. {
  2862. PACKAGEDETAIL pd;
  2863. hr = pIClassAdmin->GetPackageDetailsFromGuid(PackageGuid,
  2864. &pd);
  2865. if (SUCCEEDED(hr))
  2866. {
  2867. if (0 == (pd.pInstallInfo->dwActFlags & (ACTFLG_Orphan | ACTFLG_Uninstall)))
  2868. {
  2869. GUID guid;
  2870. LPOLESTR pszPolicyName;
  2871. hr = pIClassAdmin->GetGPOInfo(&guid,
  2872. &pszPolicyName);
  2873. if (SUCCEEDED(hr))
  2874. {
  2875. szPackageName = pd.pszPackageName;
  2876. szPackageName += L" (";
  2877. szPackageName += pszPolicyName;
  2878. szPackageName += L")";
  2879. OLESAFE_DELETE(pszPolicyName);
  2880. }
  2881. }
  2882. else
  2883. {
  2884. // this app is marked as deleted
  2885. hr = E_FAIL;
  2886. }
  2887. ReleasePackageDetail(&pd);
  2888. }
  2889. pIClassAdmin->Release();
  2890. }
  2891. }
  2892. return hr;
  2893. }
  2894. //+--------------------------------------------------------------------------
  2895. //
  2896. // Function: GetMsiProperty
  2897. //
  2898. // Synopsis: Retrieves a property from the Property table of an MSI package.
  2899. //
  2900. // Arguments: [szPackagePath] - path to the MSI package
  2901. // [szProperty] - property to fetch
  2902. // [szValue] - buffer to contain the value
  2903. // [puiSize] - size of the buffer
  2904. //
  2905. // Returns: ERROR_SUCCESS if successful
  2906. //
  2907. // History: 3-25-1998 stevebl Created
  2908. //
  2909. //---------------------------------------------------------------------------
  2910. UINT GetMsiProperty(const TCHAR * szPackagePath, const TCHAR* szProperty, TCHAR* szValue, DWORD* puiSize)
  2911. {
  2912. MSIHANDLE hDatabase;
  2913. UINT msiReturn = MsiOpenDatabase(szPackagePath, MSIDBOPEN_READONLY, &hDatabase);
  2914. if (ERROR_SUCCESS == msiReturn)
  2915. {
  2916. CString szQuery;
  2917. szQuery.Format(L"SELECT `Value` FROM `Property` WHERE `Property`='%s'", szProperty);
  2918. MSIHANDLE hView;
  2919. msiReturn = MsiDatabaseOpenView(hDatabase, szQuery, &hView);
  2920. if (ERROR_SUCCESS == msiReturn)
  2921. {
  2922. msiReturn = MsiViewExecute(hView, 0);
  2923. if (ERROR_SUCCESS == msiReturn)
  2924. {
  2925. MSIHANDLE hRecord;
  2926. msiReturn = MsiViewFetch(hView, &hRecord);
  2927. if (ERROR_SUCCESS == msiReturn)
  2928. {
  2929. msiReturn = MsiRecordGetString(hRecord, 1, szValue, puiSize);
  2930. MsiCloseHandle(hRecord);
  2931. }
  2932. }
  2933. MsiCloseHandle(hView);
  2934. }
  2935. MsiCloseHandle(hDatabase);
  2936. }
  2937. return msiReturn;
  2938. }
  2939. //+--------------------------------------------------------------------------
  2940. //
  2941. // Function: GetCapitalizedExt
  2942. //
  2943. // Synopsis: Given a file name, this function finds the filename
  2944. // extension, and returns it capitalized.
  2945. //
  2946. // Arguments:
  2947. // [in] [szName] The file name
  2948. // [out][szExt] The capitalized extension
  2949. //
  2950. // Returns:
  2951. // TRUE - an extension was found
  2952. // FALSE - an extension could not be found
  2953. //
  2954. // History: 5/20/1998 RahulTh created
  2955. //
  2956. // Notes: If an extension cannot be found, then this function makes
  2957. // szExt an empty string
  2958. //
  2959. //---------------------------------------------------------------------------
  2960. BOOL GetCapitalizedExt (LPCOLESTR szName, CString& szExt)
  2961. {
  2962. int slashpos, dotpos;
  2963. BOOL fRetVal = FALSE;
  2964. CString szFileName = szName;
  2965. szExt.Empty(); //to be on the safe side
  2966. //get the positions of the last . and last backslash
  2967. dotpos = szFileName.ReverseFind('.');
  2968. slashpos = szFileName.ReverseFind('\\');
  2969. //if the last dot occurs after the last slash, this file has an extension
  2970. if (dotpos > slashpos)
  2971. {
  2972. szExt = szFileName.Mid(dotpos + 1);
  2973. szExt.MakeUpper();
  2974. fRetVal = TRUE;
  2975. }
  2976. return fRetVal;
  2977. }