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.

1238 lines
44 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1997.
  5. //
  6. // File: packages.cpp
  7. //
  8. // Contents: Methods on CComponentDataImpl related to package deployment
  9. // and maintenence of the various index and cross-reference
  10. // structures.
  11. //
  12. // Classes:
  13. //
  14. // Functions:
  15. //
  16. // History: 2-03-1998 stevebl Created
  17. //
  18. //---------------------------------------------------------------------------
  19. // UNDONE - put in exception handling for low memory conditions
  20. #include "precomp.hxx"
  21. IMalloc * g_pIMalloc = NULL;
  22. void CopyPlatformInfo(PLATFORMINFO * &ppiOut, PLATFORMINFO * & ppiIn)
  23. {
  24. if (NULL == ppiIn)
  25. {
  26. ppiOut = NULL;
  27. return;
  28. }
  29. ppiOut = (PLATFORMINFO *)OLEALLOC(sizeof(PLATFORMINFO));
  30. memcpy(ppiOut, ppiIn, sizeof(PLATFORMINFO));
  31. UINT n = ppiIn->cPlatforms;
  32. if (n)
  33. {
  34. ppiOut->prgPlatform = (CSPLATFORM*) OLEALLOC(sizeof(CSPLATFORM) * n);
  35. memcpy(ppiOut->prgPlatform, ppiIn->prgPlatform, sizeof(CSPLATFORM) * n);
  36. }
  37. n = ppiIn->cLocales;
  38. if (n)
  39. {
  40. ppiOut->prgLocale = (LCID *) OLEALLOC(sizeof(LCID) * n);
  41. memcpy(ppiOut->prgLocale, ppiIn->prgLocale, sizeof(LCID) * n);
  42. }
  43. }
  44. void CopyActInfo(ACTIVATIONINFO * & paiOut, ACTIVATIONINFO * & paiIn)
  45. {
  46. if (NULL == paiIn)
  47. {
  48. paiOut = NULL;
  49. return;
  50. }
  51. paiOut = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO));
  52. memcpy(paiOut, paiIn, sizeof(ACTIVATIONINFO));
  53. UINT n = paiIn->cClasses;
  54. if (n)
  55. {
  56. paiOut->pClasses = (CLASSDETAIL *) OLEALLOC(sizeof(CLASSDETAIL) * n);
  57. memcpy(paiOut->pClasses, paiIn->pClasses, sizeof(CLASSDETAIL) * n);
  58. while (n--)
  59. {
  60. UINT n2 = paiIn->pClasses[n].cProgId;
  61. if (n2)
  62. {
  63. paiOut->pClasses[n].prgProgId = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n2);
  64. while (n2--)
  65. {
  66. OLESAFE_COPYSTRING(paiOut->pClasses[n].prgProgId[n2], paiIn->pClasses[n].prgProgId[n2]);
  67. }
  68. }
  69. }
  70. }
  71. n = paiIn->cShellFileExt;
  72. if (n)
  73. {
  74. paiOut->prgPriority = (UINT *) OLEALLOC(sizeof(UINT) * n);
  75. memcpy(paiOut->prgPriority, paiIn->prgPriority, sizeof(UINT) * n);
  76. paiOut->prgShellFileExt = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
  77. while (n--)
  78. {
  79. OLESAFE_COPYSTRING(paiOut->prgShellFileExt[n], paiIn->prgShellFileExt[n]);
  80. }
  81. }
  82. n = paiIn->cInterfaces;
  83. if (n)
  84. {
  85. paiOut->prgInterfaceId = (IID *) OLEALLOC(sizeof(IID) * n);
  86. memcpy(paiOut->prgInterfaceId, paiIn->prgInterfaceId, sizeof(IID) * n);
  87. }
  88. n = paiIn->cTypeLib;
  89. if (n)
  90. {
  91. paiOut->prgTlbId = (GUID *) OLEALLOC(sizeof(GUID) * n);
  92. memcpy(paiOut->prgTlbId, paiIn->prgTlbId, sizeof(GUID) * n);
  93. }
  94. }
  95. void CopyInstallInfo(INSTALLINFO * & piiOut, INSTALLINFO * & piiIn)
  96. {
  97. if (NULL == piiIn)
  98. {
  99. piiOut = NULL;
  100. return;
  101. }
  102. piiOut = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO));
  103. memcpy(piiOut, piiIn, sizeof(INSTALLINFO));
  104. OLESAFE_COPYSTRING(piiOut->pszScriptPath, piiIn->pszScriptPath);
  105. OLESAFE_COPYSTRING(piiOut->pszSetupCommand, piiIn->pszSetupCommand);
  106. OLESAFE_COPYSTRING(piiOut->pszUrl, piiIn->pszUrl);
  107. if (piiIn->pClsid)
  108. {
  109. piiOut->pClsid = (GUID *) OLEALLOC(sizeof(GUID));
  110. memcpy(piiOut->pClsid, piiIn->pClsid, sizeof(GUID));
  111. }
  112. UINT n = piiIn->cUpgrades;
  113. if (n)
  114. {
  115. piiOut->prgUpgradeScript = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
  116. piiOut->prgUpgradeFlag = (DWORD *) OLEALLOC(sizeof(DWORD) * n);
  117. memcpy(piiOut->prgUpgradeFlag, piiIn->prgUpgradeFlag, sizeof(DWORD) * n);
  118. while (n--)
  119. {
  120. OLESAFE_COPYSTRING(piiOut->prgUpgradeScript[n], piiIn->prgUpgradeScript[n]);
  121. }
  122. }
  123. }
  124. void CopyPackageDetail(PACKAGEDETAIL * & ppdOut, PACKAGEDETAIL * & ppdIn)
  125. {
  126. if (NULL == ppdIn)
  127. {
  128. ppdOut = NULL;
  129. return;
  130. }
  131. ppdOut = new PACKAGEDETAIL;
  132. memcpy(ppdOut, ppdIn, sizeof(PACKAGEDETAIL));
  133. OLESAFE_COPYSTRING(ppdOut->pszPackageName, ppdIn->pszPackageName);
  134. UINT n = ppdIn->cSources;
  135. if (n)
  136. {
  137. ppdOut->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
  138. while (n--)
  139. {
  140. OLESAFE_COPYSTRING(ppdOut->pszSourceList[n], ppdIn->pszSourceList[n]);
  141. }
  142. }
  143. n = ppdIn->cCategories;
  144. if (n)
  145. {
  146. ppdOut->rpCategory = (GUID *)OLEALLOC(sizeof(GUID) * n);
  147. memcpy(ppdOut->rpCategory, ppdIn->rpCategory, sizeof(GUID) * n);
  148. }
  149. CopyActInfo(ppdOut->pActInfo, ppdIn->pActInfo);
  150. CopyPlatformInfo(ppdOut->pPlatformInfo, ppdIn->pPlatformInfo);
  151. CopyInstallInfo(ppdOut->pInstallInfo, ppdIn->pInstallInfo);
  152. }
  153. void FreeActInfo(ACTIVATIONINFO * & pai)
  154. {
  155. if (pai)
  156. {
  157. UINT n = pai->cClasses;
  158. while (n--)
  159. {
  160. UINT n2 = pai->pClasses[n].cProgId;
  161. while (n2--)
  162. {
  163. OLESAFE_DELETE(pai->pClasses[n].prgProgId[n2]);
  164. }
  165. OLESAFE_DELETE(pai->pClasses[n].prgProgId);
  166. }
  167. OLESAFE_DELETE(pai->pClasses);
  168. n = pai->cShellFileExt;
  169. while (n--)
  170. {
  171. OLESAFE_DELETE(pai->prgShellFileExt[n]);
  172. }
  173. OLESAFE_DELETE(pai->prgShellFileExt);
  174. OLESAFE_DELETE(pai->prgPriority);
  175. OLESAFE_DELETE(pai->prgInterfaceId);
  176. OLESAFE_DELETE(pai->prgTlbId);
  177. OLESAFE_DELETE(pai);
  178. }
  179. }
  180. void FreePlatformInfo(PLATFORMINFO * &ppi)
  181. {
  182. if (ppi)
  183. {
  184. OLESAFE_DELETE(ppi->prgPlatform);
  185. OLESAFE_DELETE(ppi->prgLocale);
  186. OLESAFE_DELETE(ppi);
  187. }
  188. }
  189. void FreeInstallInfo(INSTALLINFO * &pii)
  190. {
  191. if (pii)
  192. {
  193. OLESAFE_DELETE(pii->pszScriptPath);
  194. OLESAFE_DELETE(pii->pszSetupCommand);
  195. OLESAFE_DELETE(pii->pszUrl);
  196. OLESAFE_DELETE(pii->pClsid);
  197. UINT n = pii->cUpgrades;
  198. while (n--)
  199. {
  200. OLESAFE_DELETE(pii->prgUpgradeScript[n]);
  201. }
  202. if (pii->cUpgrades > 0)
  203. {
  204. OLESAFE_DELETE(pii->prgUpgradeScript);
  205. OLESAFE_DELETE(pii->prgUpgradeFlag);
  206. }
  207. OLESAFE_DELETE(pii);
  208. }
  209. }
  210. void FreePackageDetail(PACKAGEDETAIL * & ppd)
  211. {
  212. if (ppd)
  213. {
  214. OLESAFE_DELETE(ppd->pszPackageName);
  215. UINT n = ppd->cSources;
  216. while (n--)
  217. {
  218. OLESAFE_DELETE(ppd->pszSourceList[n]);
  219. }
  220. OLESAFE_DELETE(ppd->rpCategory);
  221. FreeActInfo(ppd->pActInfo);
  222. FreePlatformInfo(ppd->pPlatformInfo);
  223. FreeInstallInfo(ppd->pInstallInfo);
  224. delete ppd;
  225. ppd = NULL;
  226. }
  227. }
  228. //+--------------------------------------------------------------------------
  229. //
  230. // Member: CComponentDataImpl::GetUniquePackageName
  231. //
  232. // Synopsis: Returns a unique package name.
  233. //
  234. // Arguments: [sz] - [in] the name of the package
  235. // [out] the new name, guaranteed unique on this cs
  236. //
  237. // History: 1-23-1998 stevebl Created
  238. //
  239. // Notes: First the input name is checked for uniqueness. If it is
  240. // already unique it is returned unchanged. If it is not
  241. // unique then a new name is formed by adding " (2)" to the end
  242. // of the string, then " (3)" and " (4)" and so on until a
  243. // unique name is found.
  244. //
  245. //---------------------------------------------------------------------------
  246. void CComponentDataImpl::GetUniquePackageName(CString &sz)
  247. {
  248. std::map<long, APP_DATA>::iterator i;
  249. std::set<CString> sNames;
  250. int cch = sz.GetLength();
  251. for (i=m_AppData.begin(); i != m_AppData.end(); i++)
  252. {
  253. // As an optimization, I'm only going to add names that might match
  254. // this one to the set.
  255. LPOLESTR szName = i->second.pDetails->pszPackageName;
  256. if (0 == wcsncmp(sz, szName, cch))
  257. sNames.insert(szName);
  258. }
  259. CString szRoot = sz;
  260. int index = 2; // start trying new names by adding (2) to the end
  261. // now check for a match
  262. do
  263. {
  264. if (sNames.end() == sNames.find(sz))
  265. {
  266. // we are unique
  267. return;
  268. }
  269. // try a different name
  270. sz.Format(L"%s (%i)", (LPCTSTR)szRoot, index++);
  271. } while (TRUE);
  272. }
  273. //+--------------------------------------------------------------------------
  274. //
  275. // Member: CComponentDataImpl::AddMSIPackage
  276. //
  277. // Synopsis: Add's one or more packages to the class store and adds the
  278. // appropriate entries to the result pane.
  279. //
  280. // Arguments: [szPackagePath] - Full path to the Darwin package.
  281. // [lpFileTitle] - file title from the open file dialog (used
  282. // for UI)
  283. //
  284. // Returns: S_OK - succeeded
  285. // E_FAIL - benign failure (probably a cancellation or something)
  286. // other - significant failure
  287. //
  288. // History: 2-03-1998 stevebl Created
  289. //
  290. //---------------------------------------------------------------------------
  291. HRESULT CComponentDataImpl::AddMSIPackage(LPCOLESTR szPackagePath, LPCOLESTR lpFileTitle)
  292. {
  293. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  294. HRESULT hr = E_FAIL;
  295. if (m_pIClassAdmin)
  296. {
  297. ASSERT(m_pConsole);
  298. {
  299. BOOL fShowPropertySheet = FALSE;
  300. BOOL fShowUpgradeDialog = FALSE;
  301. GUID guid;
  302. PACKAGEDETAIL *ppd = new PACKAGEDETAIL;
  303. memset(ppd, 0, sizeof(PACKAGEDETAIL));
  304. INSTALLINFO * pii = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO));
  305. memset(pii, 0, sizeof(INSTALLINFO));
  306. PLATFORMINFO * ppi = (PLATFORMINFO *) OLEALLOC(sizeof(PLATFORMINFO));
  307. memset(ppi, 0, sizeof(PLATFORMINFO));
  308. ACTIVATIONINFO * pai = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO));
  309. memset(pai, 0, sizeof(ACTIVATIONINFO));
  310. ppd->pActInfo = pai;
  311. ppd->pPlatformInfo = ppi;
  312. ppd->pInstallInfo = pii;
  313. // If appropriate, use the deployment wizard to set the
  314. // deployment type, otherwise use the default settings
  315. switch (m_ToolDefaults.NPBehavior)
  316. {
  317. case NP_WIZARD:
  318. {
  319. CDeployApp dlgDeployApp;
  320. if (IDCANCEL == dlgDeployApp.DoModal())
  321. {
  322. FreePackageDetail(ppd);
  323. return E_FAIL;
  324. }
  325. switch (dlgDeployApp.m_iDeployment)
  326. {
  327. case 0: // upgrade
  328. fShowUpgradeDialog = TRUE;
  329. pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall;
  330. break;
  331. case 1: //published
  332. pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  333. break;
  334. case 2: // assigned
  335. pii->dwActFlags = ACTFLG_Assigned | ACTFLG_OnDemandInstall;
  336. break;
  337. case 4: // custom
  338. fShowPropertySheet = TRUE;
  339. // fall through to disabled
  340. case 3: // disabled
  341. default:
  342. pii->dwActFlags = ACTFLG_Published;
  343. break;
  344. }
  345. }
  346. break;
  347. case NP_PUBLISHED:
  348. pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall;
  349. if (m_ToolDefaults.fAutoInstall)
  350. {
  351. pii->dwActFlags |= ACTFLG_OnDemandInstall;
  352. }
  353. break;
  354. case NP_ASSIGNED:
  355. pii->dwActFlags = ACTFLG_Assigned | ACTFLG_OnDemandInstall;
  356. break;
  357. case NP_PROPPAGE:
  358. fShowPropertySheet = TRUE;
  359. // fall through to disabled
  360. case NP_DISABLED:
  361. default:
  362. pii->dwActFlags = ACTFLG_Published;
  363. break;
  364. }
  365. pii->PathType = DrwFilePath;
  366. pii->InstallUiLevel = m_ToolDefaults.UILevel;
  367. std::set<LCID> sLocales;
  368. // Use MsiSummaryInfoGetProperty to get platform and locale info.
  369. {
  370. MSIHANDLE hSummaryInfo;
  371. UINT msiReturn = MsiGetSummaryInformation(0, szPackagePath, 0, &hSummaryInfo);
  372. if (ERROR_SUCCESS == msiReturn)
  373. {
  374. TCHAR szBuffer[256];
  375. DWORD dwSize = 256;
  376. msiReturn = MsiSummaryInfoGetProperty(hSummaryInfo,
  377. 7, // PID_TEMPLATE
  378. NULL,
  379. NULL,
  380. NULL,
  381. szBuffer,
  382. &dwSize);
  383. if (ERROR_SUCCESS == msiReturn)
  384. {
  385. // break out the locale and platform properties
  386. CString szLocales = szBuffer;
  387. CString szPlatforms = szLocales.SpanExcluding(L";");
  388. szLocales = szLocales.Mid(szPlatforms.GetLength()+1);
  389. CString szTemp;
  390. std::set<DWORD> sPlatforms;
  391. while (szPlatforms.GetLength())
  392. {
  393. szTemp = szPlatforms.SpanExcluding(L",");
  394. if (0 == szTemp.CompareNoCase(L"alpha"))
  395. {
  396. sPlatforms.insert(PROCESSOR_ARCHITECTURE_ALPHA);
  397. }
  398. else if (0 == szTemp.CompareNoCase(L"intel"))
  399. {
  400. sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL);
  401. }
  402. szPlatforms = szPlatforms.Mid(szTemp.GetLength()+1);
  403. }
  404. while (szLocales.GetLength())
  405. {
  406. szTemp = szLocales.SpanExcluding(L",");
  407. LCID lcid;
  408. swscanf(szTemp, L"%i", &lcid);
  409. sLocales.insert(lcid);
  410. szLocales = szLocales.Mid(szTemp.GetLength()+1);
  411. }
  412. if (0 == sLocales.size() || 0 == sPlatforms.size())
  413. {
  414. // either not enough locales or platforms
  415. FreePackageDetail(ppd);
  416. return E_FAIL; // need better error message?
  417. }
  418. ppi->cPlatforms = sPlatforms.size();
  419. ppi->prgPlatform = (CSPLATFORM *) OLEALLOC(sizeof(CSPLATFORM) * (ppi->cPlatforms));;
  420. std::set<DWORD>::iterator iPlatform;
  421. INT n = 0;
  422. for (iPlatform = sPlatforms.begin(); iPlatform != sPlatforms.end(); iPlatform++, n++)
  423. {
  424. ppi->prgPlatform[n].dwPlatformId = VER_PLATFORM_WIN32_NT;
  425. ppi->prgPlatform[n].dwVersionHi = 5;
  426. ppi->prgPlatform[n].dwVersionLo = 0;
  427. ppi->prgPlatform[n].dwProcessorArch = *iPlatform;
  428. }
  429. }
  430. MsiCloseHandle(hSummaryInfo);
  431. }
  432. if (ERROR_SUCCESS != msiReturn)
  433. {
  434. FreePackageDetail(ppd);
  435. return HRESULT_FROM_WIN32(msiReturn);
  436. }
  437. }
  438. ppi->cLocales = 1;
  439. ppi->prgLocale = (LCID *) OLEALLOC(sizeof(LCID));
  440. ppd->cSources = 1;
  441. ppd->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR));
  442. OLESAFE_COPYSTRING(ppd->pszSourceList[0], szPackagePath);
  443. // UNDONE - check to see if we can detect any upgrade relationships
  444. if (fShowUpgradeDialog)
  445. {
  446. CUpgrades dlgUpgrade;
  447. dlgUpgrade.m_pAppData = &m_AppData;
  448. if (IDCANCEL == dlgUpgrade.DoModal())
  449. {
  450. FreePackageDetail(ppd);
  451. return E_FAIL;
  452. }
  453. UINT n = dlgUpgrade.m_UpgradeList.size();
  454. if (n)
  455. {
  456. pii->cUpgrades = n;
  457. pii->prgUpgradeScript = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
  458. pii->prgUpgradeFlag = (DWORD *) OLEALLOC(sizeof(DWORD) * n);
  459. std::map<long, BOOL>::iterator i = dlgUpgrade.m_UpgradeList.begin();
  460. while (n--)
  461. {
  462. if (i->second)
  463. {
  464. pii->prgUpgradeFlag[n] = UPGFLG_Uninstall;
  465. }
  466. else
  467. {
  468. pii->prgUpgradeFlag[n] = UPGFLG_NoUninstall;
  469. }
  470. LPOLESTR sz = m_AppData[i->first].pDetails->pInstallInfo->pszScriptPath;
  471. OLESAFE_COPYSTRING(pii->prgUpgradeScript[n], sz);
  472. i++;
  473. }
  474. }
  475. }
  476. // Put up the locale dialog and allow the user to remove locales
  477. // from the list if he so desires.
  478. if (1 < sLocales.size())
  479. {
  480. CLcidPick dlgLcidPick;
  481. dlgLcidPick.m_psLocales = &sLocales;
  482. int iReturn = dlgLcidPick.DoModal();
  483. if (IDCANCEL == iReturn || 0 == sLocales.size())
  484. {
  485. FreePackageDetail(ppd);
  486. return E_FAIL;
  487. }
  488. }
  489. // For each locale left in the list, publish a package and add
  490. // it to the class store.
  491. int nLocales = sLocales.size();
  492. std::set<LCID>::iterator iLocale;
  493. for (iLocale = sLocales.begin(); iLocale != sLocales.end(); iLocale++)
  494. {
  495. ppi->prgLocale[0] = *iLocale;
  496. // set the script path
  497. hr = CoCreateGuid(&guid);
  498. if (FAILED(hr))
  499. {
  500. FreePackageDetail(ppd);
  501. return hr;
  502. }
  503. OLECHAR sz [256];
  504. StringFromGUID2(guid, sz, 256);
  505. CString szScriptPath = m_szScriptRoot;
  506. szScriptPath += L"\\";
  507. szScriptPath += sz;
  508. szScriptPath += L".aas";
  509. OLESAFE_DELETE(pii->pszScriptPath);
  510. OLESAFE_COPYSTRING(pii->pszScriptPath, szScriptPath);
  511. // set the package name
  512. {
  513. MSIHANDLE hProduct;
  514. UINT msiReturn = MsiOpenPackage(szPackagePath, &hProduct);
  515. if (ERROR_SUCCESS == msiReturn)
  516. {
  517. DWORD dw = 256;
  518. OLECHAR szBuffer[256];
  519. msiReturn = MsiGetProductProperty(hProduct, INSTALLPROPERTY_PRODUCTNAME, szBuffer, &dw);
  520. if (ERROR_SUCCESS == msiReturn)
  521. {
  522. CString sz = szBuffer;
  523. // If there is more than one locale in the
  524. // locale list, then append the locale to the
  525. // name to help distinguish it.
  526. if (1 < nLocales)
  527. {
  528. sz += L" (";
  529. GetLocaleInfo(ppi->prgLocale[0], LOCALE_SLANGUAGE, szBuffer, 256);
  530. sz += szBuffer;
  531. GetLocaleInfo(ppi->prgLocale[0], LOCALE_SCOUNTRY, szBuffer, 256);
  532. sz += _T(" - ");
  533. sz += szBuffer;
  534. sz += L")";
  535. }
  536. // make sure the name is unique
  537. GetUniquePackageName(sz);
  538. OLESAFE_DELETE(ppd->pszPackageName);
  539. OLESAFE_COPYSTRING(ppd->pszPackageName, sz);
  540. }
  541. MsiCloseHandle(hProduct);
  542. }
  543. if (ERROR_SUCCESS != msiReturn)
  544. {
  545. FreePackageDetail(ppd);
  546. return HRESULT_FROM_WIN32(msiReturn);
  547. }
  548. }
  549. HWND hwnd;
  550. m_pConsole->GetMainWindow(&hwnd);
  551. hr = BuildScriptAndGetActInfo(m_szGPTRoot, *ppd);
  552. if (SUCCEEDED(hr))
  553. {
  554. hr = PrepareExtensions(*ppd);
  555. if (SUCCEEDED(hr))
  556. {
  557. // put the script in the class store
  558. hr = m_pIClassAdmin->AddPackage(ppd->pszPackageName, ppd);
  559. }
  560. }
  561. if (S_OK != hr)
  562. {
  563. TCHAR szBuffer[256];
  564. ::LoadString(ghInstance, IDS_ADDFAILED, szBuffer, 256);
  565. #if DBG
  566. TCHAR szDebugBuffer[256];
  567. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  568. NULL,
  569. hr,
  570. 0,
  571. szDebugBuffer,
  572. sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]),
  573. NULL);
  574. if (0 == dw)
  575. {
  576. wsprintf(szDebugBuffer, TEXT("(HRESULT: 0x%lX)"), hr);
  577. }
  578. wcscat(szBuffer, szDebugBuffer);
  579. #endif
  580. m_pConsole->MessageBox(szBuffer,
  581. lpFileTitle,
  582. MB_OK, NULL);
  583. FreePackageDetail(ppd);
  584. return hr;
  585. }
  586. else
  587. {
  588. APP_DATA data;
  589. CopyPackageDetail(data.pDetails, ppd);
  590. data.InitializeExtraInfo();
  591. m_lLastAllocated++;
  592. m_AppData[m_lLastAllocated] = data;
  593. RESULTDATAITEM resultItem;
  594. resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  595. resultItem.str = MMC_CALLBACK;
  596. resultItem.nImage = data.GetImageIndex(this);
  597. // BUGBUG - need to make sure that m_lLastAllocated
  598. // hasn't already been used!
  599. resultItem.lParam = m_lLastAllocated;
  600. hr = m_pSnapin->m_pResult->InsertItem(&resultItem);
  601. if (SUCCEEDED(hr))
  602. {
  603. #if UGLY_SUBDIRECTORY_HACK
  604. if (0 != (data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned))
  605. {
  606. CString sz = m_szGPTRoot;
  607. sz += L"\\";
  608. sz += data.pDetails->pInstallInfo->pszScriptPath;
  609. // copy to subdirectories
  610. CString szRoot;
  611. CString szFile;
  612. int i = sz.ReverseFind(L'\\');
  613. szRoot = sz.Left(i);
  614. szFile = sz.Mid(i+1);
  615. CString szTemp;
  616. for (i = data.pDetails->pPlatformInfo->cPlatforms; i--;)
  617. {
  618. if (PROCESSOR_ARCHITECTURE_INTEL == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
  619. {
  620. szTemp = szRoot;
  621. szTemp += L"\\assigned\\x86\\";
  622. szTemp += szFile;
  623. CopyFile(sz, szTemp, FALSE);
  624. }
  625. if (PROCESSOR_ARCHITECTURE_ALPHA == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
  626. {
  627. szTemp = szRoot;
  628. szTemp += L"\\assigned\\alpha\\";
  629. szTemp += szFile;
  630. CopyFile(sz, szTemp, FALSE);
  631. }
  632. }
  633. }
  634. #endif
  635. m_AppData[m_lLastAllocated].itemID = resultItem.itemID;
  636. InsertExtensionEntry(m_lLastAllocated, m_AppData[m_lLastAllocated]);
  637. if (m_pFileExt)
  638. {
  639. m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0);
  640. }
  641. InsertUpgradeEntry(m_lLastAllocated, m_AppData[m_lLastAllocated]);
  642. m_ScriptIndex[data.pDetails->pInstallInfo->pszScriptPath] = m_lLastAllocated;
  643. // if this is an upgrade, set icons for upgraded apps to
  644. // the proper icon.
  645. UINT n = data.pDetails->pInstallInfo->cUpgrades;
  646. while (n--)
  647. {
  648. std::map<CString, long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
  649. if (i != m_ScriptIndex.end())
  650. {
  651. RESULTDATAITEM rd;
  652. memset(&rd, 0, sizeof(rd));
  653. rd.mask = RDI_IMAGE;
  654. rd.itemID = m_AppData[i->second].itemID;
  655. rd.nImage = IMG_UPGRADE;
  656. m_pSnapin->m_pResult->SetItem(&rd);
  657. }
  658. }
  659. m_pSnapin->m_pResult->Sort(0, 0, -1);
  660. }
  661. }
  662. }
  663. FreePackageDetail(ppd);
  664. }
  665. }
  666. return hr;
  667. }
  668. //+--------------------------------------------------------------------------
  669. //
  670. // Member: CComponentDataImpl::RemovePackage
  671. //
  672. // Synopsis: Removes a package from the class store and the result pane.
  673. //
  674. // Arguments: [pDataObject] - data object for this result pane item
  675. //
  676. // Returns: S_OK - success
  677. //
  678. // History: 2-03-1998 stevebl Created
  679. //
  680. // Notes: bAssigned is used
  681. //
  682. //---------------------------------------------------------------------------
  683. HRESULT CComponentDataImpl::RemovePackage(long cookie)
  684. {
  685. BOOL fAssigned;
  686. HRESULT hr = E_FAIL;
  687. // put up an hourglass (this could take a while)
  688. CHourglass hourglass;
  689. APP_DATA & data = m_AppData[cookie];
  690. // We need to make sure it gets removed from
  691. // the GPT before we delete it from the class store.
  692. CString sz = m_szGPTRoot;
  693. sz += L"\\";
  694. sz += data.pDetails->pInstallInfo->pszScriptPath;
  695. DeleteFile(sz);
  696. #if UGLY_SUBDIRECTORY_HACK
  697. {
  698. // delete from subdirectories
  699. CString szRoot;
  700. CString szFile;
  701. int i = sz.ReverseFind(L'\\');
  702. szRoot = sz.Left(i);
  703. szFile = sz.Mid(i+1);
  704. CString szTemp;
  705. szTemp = szRoot;
  706. szTemp += L"\\assigned\\x86\\";
  707. szTemp += szFile;
  708. DeleteFile(szTemp);
  709. szTemp = szRoot;
  710. szTemp += L"\\assigned\\alpha\\";
  711. szTemp += szFile;
  712. DeleteFile(szTemp);
  713. }
  714. #endif
  715. if (0 != (data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned))
  716. {
  717. fAssigned = TRUE;
  718. }
  719. else
  720. {
  721. fAssigned = FALSE;
  722. }
  723. hr = m_pIClassAdmin->RemovePackage((LPOLESTR)((LPCOLESTR)(data.pDetails->pszPackageName)));
  724. if (SUCCEEDED(hr))
  725. {
  726. hr = m_pSnapin->m_pResult->DeleteItem(data.itemID, 0);
  727. if (SUCCEEDED(hr))
  728. {
  729. // remove its entries in the extension table
  730. RemoveExtensionEntry(cookie, data);
  731. if (m_pFileExt)
  732. {
  733. m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0);
  734. }
  735. RemoveUpgradeEntry(cookie, data);
  736. m_ScriptIndex.erase(data.pDetails->pInstallInfo->pszScriptPath);
  737. // If this thing upgraded other apps, make sure that
  738. // they get the proper icons.
  739. UINT n = data.pDetails->pInstallInfo->cUpgrades;
  740. while (n--)
  741. {
  742. std::map<CString, long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
  743. if (i != m_ScriptIndex.end())
  744. {
  745. RESULTDATAITEM rd;
  746. memset(&rd, 0, sizeof(rd));
  747. rd.mask = RDI_IMAGE;
  748. rd.itemID = m_AppData[i->second].itemID;
  749. rd.nImage = m_AppData[i->second].GetImageIndex(this);
  750. m_pSnapin->m_pResult->SetItem(&rd);
  751. }
  752. }
  753. // If other apps were upgrading this app, do the same.
  754. std::set<long>::iterator i;
  755. for (i = data.sUpgrades.begin(); i != data.sUpgrades.end(); i++)
  756. {
  757. RESULTDATAITEM rd;
  758. memset(&rd, 0, sizeof(rd));
  759. rd.mask = RDI_IMAGE;
  760. rd.itemID = m_AppData[*i].itemID;
  761. rd.nImage = m_AppData[*i].GetImageIndex(this);
  762. m_pSnapin->m_pResult->SetItem(&rd);
  763. }
  764. FreePackageDetail(data.pDetails);
  765. m_AppData.erase(cookie);
  766. m_pSnapin->m_pResult->Sort(0, 0, -1);
  767. // Notify clients of change
  768. if (m_pIGPEInformation && fAssigned)
  769. {
  770. m_pIGPEInformation->PolicyChanged();
  771. }
  772. }
  773. }
  774. return hr;
  775. }
  776. //+--------------------------------------------------------------------------
  777. //
  778. // Member: CComponentDataImpl::PopulateUpgradeLists
  779. //
  780. // Synopsis: Walks the list of apps, making sure that all the upgrade
  781. // tables are complete.
  782. //
  783. // Arguments: none
  784. //
  785. // Returns:
  786. //
  787. // History: 2-02-1998 stevebl Created
  788. //
  789. //---------------------------------------------------------------------------
  790. HRESULT CComponentDataImpl::PopulateUpgradeLists()
  791. {
  792. HRESULT hr = S_OK;
  793. // For each app in the list, insert an entry in the upgrade tables of
  794. // the apps it upgrades.
  795. std::map <long, APP_DATA>::iterator iAppData;
  796. for (iAppData=m_AppData.begin(); iAppData != m_AppData.end(); iAppData++)
  797. {
  798. hr = InsertUpgradeEntry(iAppData->first, iAppData->second);
  799. if (FAILED(hr))
  800. {
  801. return hr;
  802. }
  803. }
  804. return hr;
  805. }
  806. //+--------------------------------------------------------------------------
  807. //
  808. // Member: CComponentDataImpl::InsertUpgradeEntry
  809. //
  810. // Synopsis: For every app that this app upgrades, place an entry in its
  811. // upgrades set so that it points back to this one.
  812. //
  813. // Arguments: [cookie] -
  814. // [data] -
  815. //
  816. // Returns:
  817. //
  818. // History: 2-02-1998 stevebl Created
  819. //
  820. // Notes: Needs to be able to deal with scripts that might not be in
  821. // this OU.
  822. //
  823. //---------------------------------------------------------------------------
  824. HRESULT CComponentDataImpl::InsertUpgradeEntry(long cookie, APP_DATA & data)
  825. {
  826. UINT n = data.pDetails->pInstallInfo->cUpgrades;
  827. while (n--)
  828. {
  829. std::map<CString,long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
  830. if (m_ScriptIndex.end() != i)
  831. {
  832. m_AppData[i->second].sUpgrades.insert(cookie);
  833. }
  834. }
  835. return S_OK;
  836. }
  837. //+--------------------------------------------------------------------------
  838. //
  839. // Member: CComponentDataImpl::RemoveUpgradeEntry
  840. //
  841. // Synopsis: For every app that this app upgraded, remove the entry from
  842. // its upgrades set.
  843. //
  844. // Arguments: [cookie] -
  845. // [data] -
  846. //
  847. // Returns:
  848. //
  849. // History: 2-02-1998 stevebl Created
  850. //
  851. // Notes: Needs to be able to deal with scripts that might not be in
  852. // this OU.
  853. //
  854. //---------------------------------------------------------------------------
  855. HRESULT CComponentDataImpl::RemoveUpgradeEntry(long cookie, APP_DATA & data)
  856. {
  857. UINT n = data.pDetails->pInstallInfo->cUpgrades;
  858. while (n--)
  859. {
  860. std::map<CString,long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
  861. if (m_ScriptIndex.end() != i)
  862. {
  863. m_AppData[i->second].sUpgrades.erase(cookie);
  864. }
  865. }
  866. return S_OK;
  867. }
  868. //+--------------------------------------------------------------------------
  869. //
  870. // Member: CComponentDataImpl::PopulateExtensions
  871. //
  872. // Synopsis: Builds the file extension table from the list of applications.
  873. //
  874. // Arguments: (none)
  875. //
  876. // Returns:
  877. //
  878. // History: 1-29-1998 stevebl Created
  879. //
  880. //---------------------------------------------------------------------------
  881. HRESULT CComponentDataImpl::PopulateExtensions()
  882. {
  883. HRESULT hr = S_OK;
  884. // first erase the old extension list
  885. m_Extensions.erase(m_Extensions.begin(), m_Extensions.end());
  886. // now add each app's extensions to the table
  887. std::map <long, APP_DATA>::iterator iAppData;
  888. for (iAppData=m_AppData.begin(); iAppData != m_AppData.end(); iAppData++)
  889. {
  890. hr = InsertExtensionEntry(iAppData->first, iAppData->second);
  891. if (FAILED(hr))
  892. {
  893. return hr;
  894. }
  895. }
  896. if (m_pFileExt)
  897. {
  898. m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0);
  899. }
  900. return hr;
  901. }
  902. //+--------------------------------------------------------------------------
  903. //
  904. // Member: CComponentDataImpl::InsertExtensionEntry
  905. //
  906. // Synopsis: Adds a single entry to the extension tables.
  907. //
  908. // Arguments: [cookie] -
  909. // [data] -
  910. //
  911. // Returns:
  912. //
  913. // History: 1-29-1998 stevebl Created
  914. //
  915. //---------------------------------------------------------------------------
  916. HRESULT CComponentDataImpl::InsertExtensionEntry(long cookie, APP_DATA & data)
  917. {
  918. UINT n = data.pDetails->pActInfo->cShellFileExt;
  919. while (n--)
  920. {
  921. m_Extensions[data.pDetails->pActInfo->prgShellFileExt[n]].insert(cookie);
  922. }
  923. return S_OK;
  924. }
  925. //+--------------------------------------------------------------------------
  926. //
  927. // Member: CComponentDataImpl::RemoveExtensionEntry
  928. //
  929. // Synopsis: Removes ane entry from the extension tables.
  930. //
  931. // Arguments: [cookie] -
  932. // [data] -
  933. //
  934. // Returns:
  935. //
  936. // History: 1-29-1998 stevebl Created
  937. //
  938. //---------------------------------------------------------------------------
  939. HRESULT CComponentDataImpl::RemoveExtensionEntry(long cookie, APP_DATA & data)
  940. {
  941. UINT n = data.pDetails->pActInfo->cShellFileExt;
  942. while (n--)
  943. {
  944. m_Extensions[data.pDetails->pActInfo->prgShellFileExt[n]].erase(cookie);
  945. if (m_Extensions[data.pDetails->pActInfo->prgShellFileExt[n]].empty())
  946. {
  947. m_Extensions.erase(data.pDetails->pActInfo->prgShellFileExt[n]);
  948. }
  949. }
  950. return S_OK;
  951. }
  952. //+--------------------------------------------------------------------------
  953. //
  954. // Member: CComponentDataImpl::PrepareExtensions
  955. //
  956. // Synopsis: Sets extension priorities so that this data can be inserted
  957. // into the extension list with the proper priority.
  958. //
  959. // Arguments: [pd] -
  960. //
  961. // Returns:
  962. //
  963. // Modifies:
  964. //
  965. // Derivation:
  966. //
  967. // History: 1-29-1998 stevebl Created
  968. //
  969. //---------------------------------------------------------------------------
  970. HRESULT CComponentDataImpl::PrepareExtensions(PACKAGEDETAIL &pd)
  971. {
  972. UINT n = pd.pActInfo->cShellFileExt;
  973. while (n--)
  974. {
  975. // For each extension that is going to be added, we need to assign
  976. // it a priority that is one larger than the largest priority
  977. // already added.
  978. // NOTE: The odds of this number rolling over to 0 are so
  979. // unlikely that it would be pointless to check for it. In any case
  980. // the results of such a bug would be easy for the admin to remedy
  981. // via the file extension priority dialog.
  982. pd.pActInfo->prgPriority[n] = 0;
  983. EXTLIST::iterator i;
  984. CString sz = pd.pActInfo->prgShellFileExt[n];
  985. for (i= m_Extensions[sz].begin(); i != m_Extensions[sz].end(); i++)
  986. {
  987. // look for the entry that matches this file extension
  988. APP_DATA & data = m_AppData[*i];
  989. UINT n2 = data.pDetails->pActInfo->cShellFileExt;
  990. while (n2--)
  991. {
  992. if (0 == sz.CompareNoCase(data.pDetails->pActInfo->prgShellFileExt[n2]))
  993. {
  994. break;
  995. }
  996. }
  997. if (data.pDetails->pActInfo->prgPriority[n2] >= pd.pActInfo->prgPriority[n])
  998. {
  999. pd.pActInfo->prgPriority[n] = data.pDetails->pActInfo->prgPriority[n2] + 1;
  1000. }
  1001. }
  1002. }
  1003. return S_OK;
  1004. }
  1005. //+--------------------------------------------------------------------------
  1006. //
  1007. // Member: CComponentDataImpl::ChangePackageState
  1008. //
  1009. // Synopsis: Changes the state of a package and puts up advisory message
  1010. // boxes informing the admin about the effects of the change.
  1011. //
  1012. // Arguments: [data] - entry to change
  1013. // [dwNewState] - new state
  1014. //
  1015. // History: 2-03-1998 stevebl Created
  1016. //
  1017. //---------------------------------------------------------------------------
  1018. STDMETHODIMP CComponentDataImpl::ChangePackageState(APP_DATA &data, DWORD dwNewState, BOOL fShowUI)
  1019. {
  1020. HRESULT hr = S_OK;
  1021. // first detect what's changed
  1022. DWORD dwOldState = data.pDetails->pInstallInfo->dwActFlags;
  1023. DWORD dwChange = dwOldState ^ dwNewState;
  1024. if (dwChange)
  1025. {
  1026. // something changed
  1027. if (fShowUI)
  1028. {
  1029. // Build a notification message
  1030. CString szNotify = L"";
  1031. WCHAR szBuffer [256];
  1032. BOOL fAskAboutAutoInstall = FALSE;
  1033. // changes we care about:
  1034. //
  1035. // Assigned flag changed:
  1036. // UserInstall flag changed:
  1037. // OnDemandInstall flag changed: (We only care about this if we
  1038. // aren't going to ask)
  1039. if (dwChange & (ACTFLG_Assigned | ACTFLG_Published))
  1040. {
  1041. if (dwNewState & ACTFLG_Assigned)
  1042. {
  1043. ::LoadString(ghInstance, IDS_TO_ASSIGNED, szBuffer, 256);
  1044. }
  1045. else
  1046. {
  1047. ::LoadString(ghInstance, IDS_TO_PUBLISHED, szBuffer, 256);
  1048. if (dwNewState & (ACTFLG_UserInstall | ACTFLG_OnDemandInstall))
  1049. fAskAboutAutoInstall = TRUE;
  1050. }
  1051. szNotify += szBuffer;
  1052. }
  1053. if (dwChange & ACTFLG_UserInstall)
  1054. {
  1055. if (dwNewState & ACTFLG_UserInstall)
  1056. {
  1057. ::LoadString(ghInstance, IDS_USERINSTALL_ON, szBuffer, 256);
  1058. // This check takes care of making sure we ask about
  1059. // AutoInstall when moving from the Disabled to the
  1060. // Published state.
  1061. if ((!(dwNewState & ACTFLG_Assigned)) && !(dwOldState & ACTFLG_OnDemandInstall))
  1062. fAskAboutAutoInstall = TRUE;
  1063. }
  1064. else
  1065. {
  1066. ::LoadString(ghInstance, IDS_USERINSTALL_OFF, szBuffer, 256);
  1067. }
  1068. szNotify += szBuffer;
  1069. }
  1070. if (fAskAboutAutoInstall)
  1071. {
  1072. ::LoadString(ghInstance, IDS_ASK_AUTOINSTALL, szBuffer, 256);
  1073. szNotify += szBuffer;
  1074. int iReturn = ::MessageBox(NULL,
  1075. szNotify,
  1076. data.pDetails->pszPackageName,
  1077. MB_YESNOCANCEL);
  1078. if (IDCANCEL == iReturn)
  1079. {
  1080. return E_ABORT;
  1081. }
  1082. if (IDYES == iReturn)
  1083. dwNewState |= ACTFLG_OnDemandInstall;
  1084. else
  1085. dwNewState &= ~ACTFLG_OnDemandInstall;
  1086. }
  1087. else
  1088. {
  1089. if ((!(dwNewState & ACTFLG_Assigned)) && (dwChange & ACTFLG_OnDemandInstall))
  1090. {
  1091. if (dwNewState & ACTFLG_OnDemandInstall)
  1092. {
  1093. ::LoadString(ghInstance, IDS_AUTOINSTALL_ON, szBuffer, 256);
  1094. }
  1095. else
  1096. {
  1097. ::LoadString(ghInstance, IDS_AUTOINSTALL_OFF, szBuffer, 256);
  1098. }
  1099. szNotify += szBuffer;
  1100. }
  1101. int iReturn = ::MessageBox(NULL,
  1102. szNotify,
  1103. data.pDetails->pszPackageName,
  1104. MB_OKCANCEL);
  1105. if (IDCANCEL == iReturn)
  1106. {
  1107. return E_ABORT;
  1108. }
  1109. }
  1110. }
  1111. // commit changes
  1112. hr = m_pIClassAdmin->ChangePackageProperties(data.pDetails->pszPackageName, NULL, &dwNewState, NULL, NULL, NULL);
  1113. if (SUCCEEDED(hr))
  1114. {
  1115. data.pDetails->pInstallInfo->dwActFlags = dwNewState;
  1116. RESULTDATAITEM rd;
  1117. memset(&rd, 0, sizeof(rd));
  1118. rd.mask = RDI_IMAGE;
  1119. rd.itemID = data.itemID;
  1120. rd.nImage = data.GetImageIndex(this);
  1121. m_pSnapin->m_pResult->SetItem(&rd);
  1122. m_pSnapin->m_pResult->Sort(0, 0, -1);
  1123. data.NotifyChange();
  1124. #if UGLY_SUBDIRECTORY_HACK
  1125. {
  1126. CString sz = m_szGPTRoot;
  1127. sz += L"\\";
  1128. sz += data.pDetails->pInstallInfo->pszScriptPath;
  1129. // copy to subdirectories
  1130. CString szRoot;
  1131. CString szFile;
  1132. int i = sz.ReverseFind(L'\\');
  1133. szRoot = sz.Left(i);
  1134. szFile = sz.Mid(i+1);
  1135. CString szTemp;
  1136. if (0 != (data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned))
  1137. {
  1138. for (i = data.pDetails->pPlatformInfo->cPlatforms; i--;)
  1139. {
  1140. if (PROCESSOR_ARCHITECTURE_INTEL == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
  1141. {
  1142. szTemp = szRoot;
  1143. szTemp += L"\\assigned\\x86\\";
  1144. szTemp += szFile;
  1145. CopyFile(sz, szTemp, FALSE);
  1146. }
  1147. if (PROCESSOR_ARCHITECTURE_ALPHA == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
  1148. {
  1149. szTemp = szRoot;
  1150. szTemp += L"\\assigned\\alpha\\";
  1151. szTemp += szFile;
  1152. CopyFile(sz, szTemp, FALSE);
  1153. }
  1154. }
  1155. }
  1156. else
  1157. {
  1158. szTemp = szRoot;
  1159. szTemp += L"\\assigned\\x86\\";
  1160. szTemp += szFile;
  1161. DeleteFile(szTemp);
  1162. szTemp = szRoot;
  1163. szTemp += L"\\assigned\\alpha\\";
  1164. szTemp += szFile;
  1165. DeleteFile(szTemp);
  1166. }
  1167. }
  1168. #endif
  1169. }
  1170. }
  1171. return hr;
  1172. }