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.

424 lines
14 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1998.
  5. //
  6. // File: addupgrd.cpp
  7. //
  8. // Contents: add upgrade dialog
  9. //
  10. // Classes: CAddUpgrade
  11. //
  12. // History: 03-14-1998 stevebl Commented
  13. //
  14. //---------------------------------------------------------------------------
  15. #include "precomp.hxx"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CAddUpgrade dialog
  23. CAddUpgrade::CAddUpgrade(CWnd* pParent /*=NULL*/)
  24. : CDialog(CAddUpgrade::IDD, pParent)
  25. {
  26. //{{AFX_DATA_INIT(CAddUpgrade)
  27. m_iUpgradeType = 1; // default to rip-and-replace
  28. m_iSource = 0; // default to current container
  29. m_szGPOName = L"";
  30. //}}AFX_DATA_INIT
  31. m_fPopulated = FALSE;
  32. }
  33. void CAddUpgrade::DoDataExchange(CDataExchange* pDX)
  34. {
  35. CDialog::DoDataExchange(pDX);
  36. //{{AFX_DATA_MAP(CAddUpgrade)
  37. DDX_Radio(pDX, IDC_RADIO4, m_iUpgradeType);
  38. DDX_Radio(pDX, IDC_RADIO1, m_iSource);
  39. DDX_Text(pDX, IDC_EDIT1, m_szGPOName);
  40. //}}AFX_DATA_MAP
  41. }
  42. BEGIN_MESSAGE_MAP(CAddUpgrade, CDialog)
  43. //{{AFX_MSG_MAP(CAddUpgrade)
  44. ON_BN_CLICKED(IDC_RADIO1, OnCurrentContainer)
  45. ON_BN_CLICKED(IDC_RADIO2, OnOtherContainer)
  46. ON_BN_CLICKED(IDC_RADIO10, OnAllContainers)
  47. ON_BN_CLICKED(IDC_BUTTON1, OnBrowse)
  48. ON_LBN_DBLCLK(IDC_LIST1, OnOK)
  49. ON_WM_CONTEXTMENU()
  50. //}}AFX_MSG_MAP
  51. END_MESSAGE_MAP()
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CAddUpgrade message handlers
  54. BOOL CAddUpgrade::OnInitDialog()
  55. {
  56. // If m_fPopulated is FALSE then populate the map with all packages in
  57. // this GPO container _EXCEPT_ the current app.
  58. if (!m_fPopulated)
  59. {
  60. OnCurrentContainer();
  61. m_szGPO = m_pScope->m_szGPO;
  62. m_fPopulated = TRUE;
  63. }
  64. else
  65. {
  66. // This will be done in OnCurrentContainer if m_fPopulated is FALSE
  67. RefreshList();
  68. }
  69. CDialog::OnInitDialog();
  70. return TRUE; // return TRUE unless you set the focus to a control
  71. // EXCEPTION: OCX Property Pages should return FALSE
  72. }
  73. void CAddUpgrade::RefreshList()
  74. {
  75. // For every element in the map, if it isn't already in the upgrade
  76. // list then add it to the list.
  77. CListBox * pList = (CListBox *)GetDlgItem(IDC_LIST1);
  78. pList->ResetContent();
  79. BOOL fEnable = FALSE;
  80. // add all elements that aren't already in the upgrade list
  81. map<CString, CUpgradeData>::iterator i;
  82. for (i = m_NameIndex.begin(); i != m_NameIndex.end(); i++)
  83. {
  84. if (m_pUpgradeList->end() == m_pUpgradeList->find(GetUpgradeIndex(i->second.m_PackageGuid)))
  85. {
  86. fEnable = TRUE;
  87. pList->AddString(i->first);
  88. CDC * pDC = pList->GetDC();
  89. CSize size = pDC->GetTextExtent(i->first);
  90. pDC->LPtoDP(&size);
  91. pList->ReleaseDC(pDC);
  92. if (pList->GetHorizontalExtent() < size.cx)
  93. {
  94. pList->SetHorizontalExtent(size.cx);
  95. }
  96. }
  97. }
  98. GetDlgItem(IDOK)->EnableWindow(fEnable);
  99. if (NULL == GetFocus())
  100. {
  101. GetDlgItem(IDCANCEL)->SetFocus();
  102. }
  103. pList->SetCurSel(0);
  104. }
  105. void CAddUpgrade::OnOK()
  106. {
  107. CListBox * pList = (CListBox *)GetDlgItem(IDC_LIST1);
  108. int iSel = pList->GetCurSel();
  109. if (iSel != LB_ERR)
  110. {
  111. // only allow the dialog to close with IDOK if a selection has been made
  112. CDialog::OnOK();
  113. // Do this part later to make sure that all data members are
  114. // refreshed (this happens as part of the OnOk processing)
  115. pList->GetText(iSel, m_szPackageName);
  116. m_UpgradeData = m_NameIndex[m_szPackageName];
  117. m_UpgradeData.m_flags = (m_iUpgradeType == 1) ? UPGFLG_Uninstall : UPGFLG_NoUninstall;
  118. }
  119. }
  120. void CAddUpgrade::OnCurrentContainer()
  121. {
  122. // Populate the map with all packages in this GPO container _EXCEPT_ the
  123. // current app.
  124. CString szClassStore;
  125. HRESULT hr = m_pScope->GetClassStoreName(szClassStore, FALSE);
  126. ASSERT(hr == S_OK);
  127. m_NameIndex.erase(m_NameIndex.begin(), m_NameIndex.end());
  128. map <MMC_COOKIE, CAppData>::iterator i;
  129. for (i = m_pScope->m_AppData.begin(); i != m_pScope->m_AppData.end(); i ++)
  130. {
  131. CString szIndex = GetUpgradeIndex(i->second.m_pDetails->pInstallInfo->PackageGuid);
  132. if (0 != _wcsicmp(szIndex, m_szMyGuid))
  133. {
  134. // make sure we exclude legacy apps
  135. if (i->second.m_pDetails->pInstallInfo->PathType != SetupNamePath)
  136. {
  137. CUpgradeData data;
  138. memcpy(&data.m_PackageGuid, &i->second.m_pDetails->pInstallInfo->PackageGuid, sizeof(GUID));
  139. data.m_szClassStore = szClassStore;
  140. // Add this element to the list
  141. m_NameIndex[i->second.m_pDetails->pszPackageName] = data;
  142. }
  143. }
  144. }
  145. RefreshList();
  146. }
  147. void CAddUpgrade::OnOtherContainer()
  148. {
  149. // Populate the map with all packages in the other container.
  150. m_NameIndex.erase(m_NameIndex.begin(), m_NameIndex.end());
  151. WCHAR szBuffer[MAX_DS_PATH];
  152. LPGROUPPOLICYOBJECT pGPO = NULL;
  153. HRESULT hr = CoCreateInstance(CLSID_GroupPolicyObject, NULL,
  154. CLSCTX_SERVER, IID_IGroupPolicyObject,
  155. (void **)&pGPO);
  156. if (SUCCEEDED(hr))
  157. {
  158. // open GPO object without opening registry data
  159. hr = pGPO->OpenDSGPO((LPOLESTR)((LPCOLESTR)m_szGPO), GPO_OPEN_READ_ONLY);
  160. if (SUCCEEDED(hr))
  161. {
  162. hr = pGPO->GetDSPath(m_pScope->m_fMachine ? GPO_SECTION_MACHINE : GPO_SECTION_USER, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]));
  163. if (SUCCEEDED(hr))
  164. {
  165. // OK, we should now have a DS path that we can use to locate
  166. // a class store.
  167. LPOLESTR szCSPath;
  168. hr = CsGetClassStorePath((LPOLESTR)((LPCOLESTR)szBuffer), &szCSPath);
  169. if (SUCCEEDED(hr))
  170. {
  171. // now we should have the DS path to the class store itself
  172. IClassAdmin * pIClassAdmin;
  173. hr = CsGetClassStore((LPOLESTR)((LPCOLESTR)szCSPath), (LPVOID*)&pIClassAdmin);
  174. if (SUCCEEDED(hr))
  175. {
  176. // and finally we should have a pointer to the IClassAdmin
  177. IEnumPackage * pIPE = NULL;
  178. HRESULT hr = pIClassAdmin->EnumPackages(NULL,
  179. NULL,
  180. APPQUERY_ADMINISTRATIVE,
  181. NULL,
  182. NULL,
  183. &pIPE);
  184. if (SUCCEEDED(hr))
  185. {
  186. hr = pIPE->Reset();
  187. PACKAGEDISPINFO stPDI;
  188. ULONG nceltFetched;
  189. while (SUCCEEDED(hr))
  190. {
  191. hr = pIPE->Next(1, &stPDI, &nceltFetched);
  192. if (nceltFetched)
  193. {
  194. // make sure we exclude legacy apps
  195. // and deleted apps
  196. if (stPDI.PathType != SetupNamePath)
  197. {
  198. CString szIndex = GetUpgradeIndex(stPDI.PackageGuid);
  199. if (0 != _wcsicmp(szIndex, m_szMyGuid))
  200. {
  201. // Add this element to the list
  202. CString sz = stPDI.pszPackageName;
  203. if (0 != _wcsicmp(m_szGPO, m_pScope->m_szGPO))
  204. {
  205. // This isn't in the host GPO
  206. sz += L" (";
  207. sz += m_szGPOName;
  208. sz += L")";
  209. }
  210. CUpgradeData data;
  211. data.m_szClassStore = szCSPath;
  212. memcpy(&data.m_PackageGuid, &stPDI.PackageGuid, sizeof(GUID));
  213. m_NameIndex[sz] = data;
  214. }
  215. }
  216. }
  217. else
  218. {
  219. break;
  220. }
  221. OLESAFE_DELETE(stPDI.pszPackageName);
  222. OLESAFE_DELETE(stPDI.pszScriptPath);
  223. OLESAFE_DELETE(stPDI.pszPublisher);
  224. OLESAFE_DELETE(stPDI.pszUrl);
  225. UINT n = stPDI.cUpgrades;
  226. while (n--)
  227. {
  228. OLESAFE_DELETE(stPDI.prgUpgradeInfoList[n].szClassStore);
  229. }
  230. OLESAFE_DELETE(stPDI.prgUpgradeInfoList);
  231. }
  232. pIPE->Release();
  233. }
  234. pIClassAdmin->Release();
  235. }
  236. OLESAFE_DELETE(szCSPath);
  237. }
  238. }
  239. }
  240. pGPO->Release();
  241. }
  242. RefreshList();
  243. }
  244. void CAddUpgrade::OnAllContainers()
  245. {
  246. RefreshList();
  247. }
  248. //+--------------------------------------------------------------------------
  249. //
  250. // Function: GetDomainFromLDAPPath
  251. //
  252. // Synopsis: returns a freshly allocated string containing the LDAP path
  253. // to the domain name contained with an arbitrary LDAP path.
  254. //
  255. // Arguments: [szIn] - LDAP path to the initial object
  256. //
  257. // Returns: NULL - if no domain could be found or if OOM
  258. //
  259. // History: 5-06-1998 stevebl Created
  260. // 10-20-1998 stevebl modified to preserve server names
  261. //
  262. // Notes: This routine works by repeatedly removing leaf elements from
  263. // the LDAP path until an element with the "DC=" prefix is
  264. // found, indicating that a domain name has been located. If a
  265. // path is given that is not rooted in a domain (is that even
  266. // possible?) then NULL would be returned.
  267. //
  268. // The caller must free this path using the standard c++ delete
  269. // operation. (I/E this isn't an exportable function.)
  270. //
  271. // Stolen from GPEDIT\UTIL.CPP
  272. //
  273. //---------------------------------------------------------------------------
  274. LPOLESTR GetDomainFromLDAPPath(LPOLESTR szIn)
  275. {
  276. LPOLESTR sz = NULL;
  277. IADsPathname * pADsPathname = NULL;
  278. HRESULT hr = CoCreateInstance(CLSID_Pathname,
  279. NULL,
  280. CLSCTX_INPROC_SERVER,
  281. IID_IADsPathname,
  282. (LPVOID*)&pADsPathname);
  283. if (SUCCEEDED(hr))
  284. {
  285. hr = pADsPathname->Set(szIn, ADS_SETTYPE_FULL);
  286. if (SUCCEEDED(hr))
  287. {
  288. BSTR bstr;
  289. BOOL fStop = FALSE;
  290. while (!fStop)
  291. {
  292. hr = pADsPathname->Retrieve(ADS_FORMAT_LEAF, &bstr);
  293. if (SUCCEEDED(hr))
  294. {
  295. // keep peeling them off until we find something
  296. // that is a domain name
  297. fStop = (0 == _wcsnicmp(L"DC=", bstr, 3));
  298. SysFreeString(bstr);
  299. }
  300. else
  301. {
  302. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve leaf with 0x%x."), hr));
  303. }
  304. if (!fStop)
  305. {
  306. hr = pADsPathname->RemoveLeafElement();
  307. if (FAILED(hr))
  308. {
  309. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to remove leaf with 0x%x."), hr));
  310. fStop = TRUE;
  311. }
  312. }
  313. }
  314. hr = pADsPathname->Retrieve(ADS_FORMAT_X500, &bstr);
  315. if (SUCCEEDED(hr))
  316. {
  317. sz = new OLECHAR[wcslen(bstr)+1];
  318. if (sz)
  319. {
  320. wcscpy(sz, bstr);
  321. }
  322. SysFreeString(bstr);
  323. }
  324. else
  325. {
  326. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve full path with 0x%x."), hr));
  327. }
  328. }
  329. else
  330. {
  331. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to set pathname with 0x%x."), hr));
  332. }
  333. pADsPathname->Release();
  334. }
  335. else
  336. {
  337. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to CoCreateInstance for IID_IADsPathname with 0x%x."), hr));
  338. }
  339. return sz;
  340. }
  341. void CAddUpgrade::OnBrowse()
  342. {
  343. // Browse to the other container and then call OnOtherContainer.
  344. OLECHAR szPath[MAX_DS_PATH];
  345. OLECHAR szName[256];
  346. GPOBROWSEINFO stGBI;
  347. memset(&stGBI, 0, sizeof(GPOBROWSEINFO));
  348. stGBI.dwSize = sizeof(GPOBROWSEINFO);
  349. stGBI.dwFlags = GPO_BROWSE_NOCOMPUTERS | GPO_BROWSE_INITTOALL;
  350. stGBI.hwndOwner = m_hWnd;
  351. stGBI.lpInitialOU = GetDomainFromLDAPPath((LPWSTR)((LPCWSTR)m_szGPO));
  352. stGBI.lpDSPath = szPath;
  353. stGBI.dwDSPathSize = MAX_DS_PATH;
  354. stGBI.lpName = szName;
  355. stGBI.dwNameSize = 256;
  356. if (SUCCEEDED(BrowseForGPO(&stGBI)))
  357. {
  358. m_szGPO = szPath;
  359. m_szGPOName = szName;
  360. m_iSource = 1;
  361. UpdateData(FALSE);
  362. OnOtherContainer();
  363. }
  364. if (stGBI.lpInitialOU != NULL)
  365. {
  366. delete [] stGBI.lpInitialOU;
  367. }
  368. }
  369. LRESULT CAddUpgrade::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  370. {
  371. switch (message)
  372. {
  373. case WM_HELP:
  374. StandardHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, IDD);
  375. return 0;
  376. default:
  377. return CDialog::WindowProc(message, wParam, lParam);
  378. }
  379. }
  380. void CAddUpgrade::OnContextMenu(CWnd* pWnd, CPoint point)
  381. {
  382. StandardContextMenu(pWnd->m_hWnd, IDD_FIND_UPGRADE);
  383. }