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.

735 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001
  6. //
  7. // File: aclbloat.h
  8. //
  9. // This file contains the implementation of ACLBLOAT class which controls the
  10. // dialog box for aclbloat
  11. //
  12. // Author hiteshr 4th April 2001
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "aclpriv.h"
  16. //+--------------------------------------------------------------------------
  17. //
  18. // Member: CACLBloat::CACLBloat
  19. //
  20. // Synopsis: Constructor
  21. //
  22. //
  23. // History: 04-April 2001 hiteshr Created
  24. //
  25. //---------------------------------------------------------------------------
  26. CACLBloat::CACLBloat(LPSECURITYINFO psi,
  27. LPSECURITYINFO2 psi2,
  28. SI_PAGE_TYPE siPageType,
  29. SI_OBJECT_INFO* psiObjectInfo,
  30. HDPA hEntries,
  31. HDPA hPropEntries):m_psi(psi),
  32. m_psi2(psi2),
  33. m_siPageType(siPageType),
  34. m_psiObjectInfo(psiObjectInfo),
  35. m_hEntries(hEntries),
  36. m_hPropEntries(hPropEntries),
  37. m_hMergedEntries(NULL),
  38. m_hFont(NULL)
  39. {
  40. TraceEnter(TRACE_ACLBLOAT, "CACLBloat::CACLBloat");
  41. if(m_psi)
  42. m_psi->AddRef();
  43. if(m_psi2)
  44. m_psi2->AddRef();
  45. }
  46. CACLBloat::~CACLBloat()
  47. {
  48. if(m_psi)
  49. m_psi->Release();
  50. if(m_psi2)
  51. m_psi2->Release();
  52. if(m_hMergedEntries)
  53. {
  54. UINT cItems = DPA_GetPtrCount(m_hMergedEntries);
  55. for(UINT iItems = 0; iItems < cItems; ++iItems)
  56. {
  57. delete (PACE)DPA_FastGetPtr(m_hMergedEntries, iItems);
  58. }
  59. DPA_Destroy(m_hMergedEntries);
  60. }
  61. if(m_hFont)
  62. DeleteObject(m_hFont);
  63. }
  64. //+--------------------------------------------------------------------------
  65. //
  66. // Member: CACLBloat::IsAclBloated
  67. //
  68. // Synopsis: ACL is bloated if number of entries which inherits to child objects
  69. // is more than 8
  70. //
  71. //
  72. // History: 04-April 2001 hiteshr Created
  73. //
  74. //---------------------------------------------------------------------------
  75. BOOL
  76. CACLBloat::IsAclBloated()
  77. {
  78. TraceEnter(TRACE_ACLBLOAT, "CACLBloat::IsAclBloated");
  79. if(!m_hMergedEntries)
  80. {
  81. m_hMergedEntries = DPA_Create(4);
  82. if(!m_hMergedEntries)
  83. return FALSE;
  84. }
  85. if(SUCCEEDED(MergeAces(m_hEntries, m_hPropEntries, m_hMergedEntries)))
  86. {
  87. int cItems = DPA_GetPtrCount(m_hMergedEntries);
  88. if(cItems > ACL_BLOAT_LIMIT)
  89. return TRUE;
  90. }
  91. return FALSE;
  92. }
  93. //+--------------------------------------------------------------------------
  94. //
  95. // Member: CACLBloat::DoModalDialog
  96. //
  97. // Synopsis: Creates modal dialogbox
  98. //
  99. // Arguments: [hwndParent] - handle to owner window of dialog to create
  100. //
  101. // Returns: Dialog's return code
  102. //
  103. // History: 04-April-2001 hiteshr Created
  104. //
  105. //---------------------------------------------------------------------------
  106. BOOL
  107. CACLBloat::DoModalDialog(HWND hwndParent)
  108. {
  109. TraceEnter(TRACE_ACLBLOAT, "CACLBloat::CACLBloat");
  110. INT_PTR iResult = DialogBoxParam(::hModule,
  111. MAKEINTRESOURCE(IDD_ACLBLOAT),
  112. hwndParent,
  113. CACLBloat::_DlgProc,
  114. (LPARAM) this);
  115. return static_cast<BOOL>(iResult);
  116. }
  117. //+--------------------------------------------------------------------------
  118. //
  119. // Member: CACLBloat::_DlgProc
  120. //
  121. // Synopsis: Dialog box callback
  122. //
  123. // Returns: Dialog's return code
  124. //
  125. // History: 04-April-2001 hiteshr Created
  126. //
  127. //---------------------------------------------------------------------------
  128. INT_PTR CALLBACK
  129. CACLBloat::_DlgProc(HWND hDlg,
  130. UINT uMsg,
  131. WPARAM wParam,
  132. LPARAM lParam)
  133. {
  134. BOOL bReturn = TRUE;
  135. CACLBloat *pThis = (CACLBloat *)GetWindowLongPtr(hDlg, DWLP_USER);
  136. if (!pThis && uMsg != WM_INITDIALOG)
  137. {
  138. return FALSE;
  139. }
  140. switch (uMsg)
  141. {
  142. case WM_INITDIALOG:
  143. pThis = (CACLBloat*) lParam;
  144. ASSERT(pThis);
  145. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) pThis);
  146. pThis->InitDlg(hDlg);
  147. break;
  148. case WM_COMMAND:
  149. bReturn = pThis->OnCommand(hDlg, wParam, lParam);
  150. break;
  151. case WM_NOTIFY:
  152. bReturn = pThis->OnNotify(hDlg, wParam, lParam);
  153. break;
  154. default:
  155. bReturn = FALSE;
  156. break;
  157. }
  158. return bReturn;
  159. }
  160. //+--------------------------------------------------------------------------
  161. //
  162. // Member: CACLBloat::InitDlg
  163. //
  164. // Synopsis: Initialize the ACL bloat dialog box
  165. //
  166. //
  167. // History: 04-April-2001 hiteshr Created
  168. //
  169. //---------------------------------------------------------------------------
  170. HRESULT
  171. CACLBloat::InitDlg( HWND hDlg )
  172. {
  173. TraceEnter(TRACE_ACLBLOAT, "CACLBloat::CACLBloat");
  174. HRESULT hr = S_OK;
  175. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  176. //
  177. // Set up the listview control
  178. //
  179. HWND hListView = GetDlgItem( hDlg, IDC_ACEL_BLOAT );
  180. //
  181. // Set extended LV style for whole line selection with InfoTips
  182. //
  183. ListView_SetExtendedListViewStyleEx(hListView,
  184. LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP,
  185. LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
  186. //
  187. // Add appropriate columns
  188. //
  189. RECT rc;
  190. GetClientRect(hListView, &rc);
  191. LV_COLUMN col;
  192. col.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH;
  193. col.fmt = LVCFMT_LEFT;
  194. col.iSubItem = 0;
  195. col.cx = rc.right;
  196. ListView_InsertColumn(hListView, 0, &col);
  197. //
  198. //Add the aces to listview
  199. //
  200. hr = AddAcesFromDPA(hListView, m_hMergedEntries);
  201. if(FAILED(hr))
  202. return hr;
  203. //
  204. //Add a warning icon
  205. //
  206. // add the warning icon
  207. HICON hWarn = LoadIcon(NULL, IDI_WARNING);
  208. SendDlgItemMessage(hDlg, // dialog box window handle
  209. IDC_BLOAT_WARN_ICON, // icon identifier
  210. STM_SETIMAGE, // message to send
  211. (WPARAM) IMAGE_ICON, // image type
  212. (LPARAM) hWarn); // icon handle
  213. //
  214. //Set the title of dialog box
  215. //
  216. LPTSTR pszCaption = NULL;
  217. if(FormatStringID(&pszCaption,
  218. ::hModule,
  219. m_siPageType == SI_PAGE_AUDIT ? IDS_ACEE_AUDIT_TITLE : IDS_ACEE_PERM_TITLE,
  220. m_psiObjectInfo->pszObjectName))
  221. {
  222. SetWindowText(hDlg, pszCaption);
  223. LocalFreeString(&pszCaption);
  224. }
  225. //
  226. //Set the warning message
  227. //
  228. UINT cItem = DPA_GetPtrCount(m_hMergedEntries);
  229. WCHAR buffer[34];
  230. _itow(cItem,buffer,10);
  231. if(FormatStringID(&pszCaption,
  232. ::hModule,
  233. m_siPageType == SI_PAGE_AUDIT ? IDS_BLOAT_AUDIT_WARN : IDS_BLOAT_PERM_WARN,
  234. buffer))
  235. {
  236. SetDlgItemText(hDlg, IDC_BLOAT_LV_STATIC, pszCaption);
  237. LocalFreeString(&pszCaption);
  238. }
  239. //
  240. //Set the line 1
  241. //
  242. WCHAR szBuffer[1024];
  243. if(LoadString(::hModule,
  244. m_siPageType == SI_PAGE_AUDIT ? IDS_BLOAT_AUDIT_LINE1: IDS_BLOAT_PERM_LINE1,
  245. szBuffer,
  246. 1024))
  247. SetDlgItemText(hDlg,IDC_BLOAT_LINE1_STATIC, szBuffer);
  248. //
  249. //Set the line 2
  250. //
  251. if(LoadString(::hModule,
  252. m_siPageType == SI_PAGE_AUDIT ? IDS_BLOAT_AUDIT_LINE2: IDS_BLOAT_PERM_LINE2,
  253. szBuffer,
  254. 1024))
  255. SetDlgItemText(hDlg,IDC_BLOAT_LINE2_STATIC, szBuffer);
  256. //
  257. //make warning bold
  258. //
  259. MakeBold(GetDlgItem(hDlg,IDC_ACLB_WARNING), &m_hFont);
  260. SetCursor(hcur);
  261. return hr;
  262. }
  263. BOOL
  264. CACLBloat::OnNotify(HWND hDlg, WPARAM wParam, LPARAM lParam)
  265. {
  266. LPNMHDR pnmh = (LPNMHDR)lParam;
  267. LPNM_LISTVIEW pnmlv = (LPNM_LISTVIEW)lParam;
  268. // Set default return value
  269. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  270. switch (pnmh->code)
  271. {
  272. #define lvi (((NMLVDISPINFO*)lParam)->item)
  273. case LVN_GETDISPINFO:
  274. {
  275. PACE pAce = (PACE)lvi.lParam;
  276. if ((lvi.mask & LVIF_TEXT) && pAce)
  277. {
  278. if (0 == lvi.iSubItem)
  279. {
  280. lvi.pszText = pAce->GetAccessType();
  281. }
  282. }
  283. }
  284. break;
  285. #undef lvi
  286. }
  287. return TRUE;
  288. }
  289. //+--------------------------------------------------------------------------
  290. //
  291. // Member: CACLBloat::MergeAces
  292. //
  293. // Synopsis: Merges the aces from Object and Property Pages in to single
  294. // List
  295. //
  296. //
  297. // History: 04-April-2001 hiteshr Created
  298. //
  299. //---------------------------------------------------------------------------
  300. HRESULT
  301. CACLBloat::MergeAces(HDPA hEntries, HDPA hPropEntries, HDPA hMergedList)
  302. {
  303. if(!hMergedList || (!hEntries && !hPropEntries))
  304. return E_POINTER;
  305. HRESULT hr = S_OK;
  306. if(hEntries)
  307. {
  308. UINT cItems = DPA_GetPtrCount(hEntries);
  309. for(UINT iItems = 0; iItems < cItems; ++iItems)
  310. {
  311. hr = AddAce(hMergedList,
  312. (PACE_HEADER)DPA_FastGetPtr(hEntries, iItems));
  313. if(FAILED(hr))
  314. return hr;
  315. }
  316. }
  317. if(hPropEntries)
  318. {
  319. UINT cItems = DPA_GetPtrCount(hPropEntries);
  320. for(UINT iItems = 0; iItems < cItems; ++iItems)
  321. {
  322. hr = AddAce(hMergedList,
  323. (PACE_HEADER)DPA_FastGetPtr(hPropEntries, iItems));
  324. if(FAILED(hr))
  325. return hr;
  326. }
  327. }
  328. return S_OK;
  329. }
  330. //+--------------------------------------------------------------------------
  331. //
  332. // Member: CACLBloat::AddAce
  333. //
  334. // Synopsis: Converts AceHeader to ACLUI Ace structure
  335. //
  336. //
  337. // History: 04-April-2001 hiteshr Created
  338. //
  339. //---------------------------------------------------------------------------
  340. HRESULT
  341. CACLBloat::AddAce(HDPA hEntries,
  342. PACE_HEADER pAceHeader)
  343. {
  344. //
  345. //This Ace doesn't propogate to child objects,
  346. //so we don't show this.
  347. //
  348. if(!(pAceHeader->AceFlags & CONTAINER_INHERIT_ACE))
  349. return S_OK;
  350. PACE pAce = new CAce(pAceHeader);
  351. if (pAce)
  352. {
  353. return AddAce(hEntries, pAce);
  354. }
  355. else
  356. return E_OUTOFMEMORY;
  357. }
  358. //+--------------------------------------------------------------------------
  359. //
  360. // Member: CACLBloat::AddAce
  361. //
  362. // Synopsis: Add an Ace to list. First it tries to merge it with existing
  363. // aces in the list.
  364. //
  365. //
  366. // History: 04-April-2001 hiteshr Created
  367. //
  368. //---------------------------------------------------------------------------
  369. HRESULT
  370. CACLBloat::AddAce(HDPA hEntries,
  371. PACE pAceNew)
  372. {
  373. TraceEnter(TRACE_ACLBLOAT, "CACLBloat::AddAce");
  374. TraceAssert(hEntries != NULL);
  375. TraceAssert(pAceNew != NULL);
  376. if (pAceNew == NULL)
  377. return E_POINTER;
  378. m_psi->MapGeneric(&pAceNew->ObjectType, &pAceNew->AceFlags, &pAceNew->Mask);
  379. //
  380. // Try to merge the new ACE with an existing entry in the list.
  381. //
  382. int cItems = DPA_GetPtrCount(hEntries);
  383. for( int iItems = 0; iItems < cItems; ++iItems)
  384. {
  385. PACE pAceCompare = (PACE)DPA_FastGetPtr(hEntries, iItems);
  386. if (pAceCompare != NULL)
  387. {
  388. switch (pAceNew->Merge(pAceCompare))
  389. {
  390. case MERGE_MODIFIED_FLAGS:
  391. case MERGE_MODIFIED_MASK:
  392. // The ACEs were merged into pAceNew.
  393. case MERGE_OK_1:
  394. //
  395. // The new ACE implies the existing ACE, so the existing
  396. // ACE can be removed.
  397. //
  398. // First copy the name so we don't have to look
  399. // it up again. (Don't copy the other strings
  400. // since they may be different.)
  401. //
  402. // Then keep looking. Maybe we can remove some more entries
  403. // before adding the new one.
  404. //
  405. DPA_DeletePtr(hEntries, iItems);
  406. delete pAceCompare;
  407. --cItems;
  408. --iItems;
  409. break;
  410. case MERGE_OK_2:
  411. //
  412. // The existing ACE implies the new ACE, so we don't
  413. // need to do anything here.
  414. //
  415. delete pAceNew;
  416. return S_OK;
  417. break;
  418. }
  419. }
  420. }
  421. DPA_AppendPtr(hEntries, pAceNew);
  422. return S_OK;
  423. }
  424. //+--------------------------------------------------------------------------
  425. //
  426. // Member: CACLBloat::GetItemString
  427. //
  428. // Synopsis: Gets a display name for the item.
  429. //
  430. //
  431. // History: 04-April-2001 hiteshr Created
  432. //
  433. //---------------------------------------------------------------------------
  434. LPCTSTR
  435. CACLBloat::GetItemString(LPCTSTR pszItem,
  436. LPTSTR pszBuffer,
  437. UINT ccBuffer)
  438. {
  439. TraceEnter(TRACE_ACELIST, "CACLBloat::GetItemString");
  440. if (pszItem == NULL)
  441. {
  442. LoadString(::hModule, IDS_SPECIAL, pszBuffer, ccBuffer);
  443. pszItem = pszBuffer;
  444. }
  445. else if (IS_INTRESOURCE(pszItem))
  446. {
  447. if (LoadString(m_psiObjectInfo->hInstance,
  448. (UINT)((ULONG_PTR)pszItem),
  449. pszBuffer,
  450. ccBuffer) == 0)
  451. {
  452. LoadString(::hModule, IDS_SPECIAL, pszBuffer, ccBuffer);
  453. }
  454. pszItem = pszBuffer;
  455. }
  456. TraceLeaveValue(pszItem);
  457. }
  458. //+--------------------------------------------------------------------------
  459. //
  460. // Member: CACLBloat::TranslateAceIntoRights
  461. //
  462. // Synopsis: Converts Aces Mask in to a string taking into account
  463. // the Object Guid.
  464. //
  465. //
  466. // History: 04-April-2001 hiteshr Created
  467. //
  468. //---------------------------------------------------------------------------
  469. LPCTSTR
  470. CACLBloat::TranslateAceIntoRights(DWORD dwMask,
  471. const GUID *pObjectType,
  472. PSI_ACCESS pAccess,
  473. ULONG cAccess)
  474. {
  475. TraceEnter(TRACE_ACELIST, "CACLBloat::TranslateAceIntoRights");
  476. TraceAssert(pObjectType != NULL);
  477. if(!pAccess || !cAccess)
  478. return NULL;
  479. LPCTSTR pszName = NULL;
  480. if (pAccess && cAccess)
  481. {
  482. //
  483. // Look for a name for the mask
  484. //
  485. for (UINT iItem = 0; iItem < cAccess; iItem++)
  486. {
  487. if ( dwMask == pAccess[iItem].mask &&
  488. IsSameGUID(pObjectType, pAccess[iItem].pguid) )
  489. {
  490. pszName = pAccess[iItem].pszName;
  491. break;
  492. }
  493. }
  494. }
  495. TraceLeaveValue(pszName);
  496. }
  497. //+--------------------------------------------------------------------------
  498. //
  499. // Member: CACLBloat::AddAcesFromDPA
  500. //
  501. // Synopsis: Add ace from list to ListView control.
  502. //
  503. //
  504. // History: 04-April-2001 hiteshr Created
  505. //
  506. //---------------------------------------------------------------------------
  507. HRESULT
  508. CACLBloat::AddAcesFromDPA(HWND hListView, HDPA hEntries)
  509. {
  510. ULONG iDefaultAccess = 0;
  511. PSI_ACCESS pAccess = NULL;
  512. ULONG cAccess = 0;
  513. HRESULT hr = S_OK;
  514. if(!hEntries)
  515. return E_POINTER;
  516. //
  517. //Get the count of items
  518. //
  519. int cItems = DPA_GetPtrCount(hEntries);
  520. GUID* pGUID = NULL;
  521. PACE pAce = (PACE)DPA_FastGetPtr(hEntries, 0);
  522. if(pAce)
  523. {
  524. //
  525. //Get the AccessRight array for the guid
  526. //
  527. hr = m_psi->GetAccessRights(&pAce->InheritedObjectType,
  528. SI_ADVANCED|SI_EDIT_EFFECTIVE,
  529. &pAccess,
  530. &cAccess,
  531. &iDefaultAccess);
  532. if(FAILED(hr))
  533. return hr;
  534. pGUID = &pAce->InheritedObjectType;
  535. }
  536. for( int iItem = 0; iItem < cItems; ++iItem)
  537. {
  538. pAce = (PACE)DPA_FastGetPtr(hEntries, iItem);
  539. if(pAce)
  540. {
  541. if(!IsSameGUID(pGUID, &pAce->InheritedObjectType))
  542. {
  543. //
  544. //if Guid is not same as one for which we have access right info,
  545. //fetch access right info for new guid
  546. //
  547. hr = m_psi->GetAccessRights(&pAce->InheritedObjectType,
  548. SI_ADVANCED | SI_EDIT_EFFECTIVE,
  549. &pAccess,
  550. &cAccess,
  551. &iDefaultAccess);
  552. if(FAILED(hr))
  553. return hr;
  554. pGUID = &pAce->InheritedObjectType;
  555. }
  556. TCHAR szBuffer[MAX_COLUMN_CHARS];
  557. LPCTSTR pszRights = NULL;
  558. pszRights = TranslateAceIntoRights(pAce->Mask,
  559. &pAce->ObjectType,
  560. pAccess,
  561. cAccess);
  562. //
  563. // If this is a property ACE, give it a name like "Read property" or
  564. // "Write property". Also, remember that it's a property ACE so we
  565. // can show the Property page first when editing this ACE.
  566. //
  567. // This is a bit slimy, since it assumes DS property access bits are
  568. // the only ones that will ever be used on the properties page.
  569. //
  570. if ((m_psiObjectInfo->dwFlags & SI_EDIT_PROPERTIES) &&
  571. (pAce->Flags & ACE_OBJECT_TYPE_PRESENT) &&
  572. (pAce->Mask & (ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP)) &&
  573. !(pAce->Mask & ~(ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP)))
  574. {
  575. pAce->SetPropertyAce(TRUE);
  576. if (pszRights == NULL)
  577. {
  578. UINT idString = 0;
  579. switch (pAce->Mask & (ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP))
  580. {
  581. case ACTRL_DS_READ_PROP:
  582. idString = IDS_READ_PROP;
  583. break;
  584. case ACTRL_DS_WRITE_PROP:
  585. idString = IDS_WRITE_PROP;
  586. break;
  587. case (ACTRL_DS_READ_PROP | ACTRL_DS_WRITE_PROP):
  588. idString = IDS_READ_WRITE_PROP;
  589. break;
  590. }
  591. if (idString)
  592. {
  593. LoadString(::hModule, idString, szBuffer, ARRAYSIZE(szBuffer));
  594. pszRights = szBuffer;
  595. }
  596. }
  597. }
  598. pszRights = GetItemString(pszRights, szBuffer, ARRAYSIZE(szBuffer));
  599. pAce->SetAccessType(pszRights);
  600. LV_ITEM lvi;
  601. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  602. lvi.state = 0;
  603. lvi.stateMask = LVIS_CUT;
  604. lvi.iItem = iItem;
  605. lvi.iSubItem = 0;
  606. lvi.pszText = LPSTR_TEXTCALLBACK;
  607. lvi.lParam = (LPARAM)pAce;
  608. //
  609. // insert the item into the list
  610. //
  611. iItem = ListView_InsertItem(hListView, &lvi);
  612. if (iItem == -1)
  613. delete pAce;
  614. }
  615. }
  616. return hr;
  617. }
  618. BOOL
  619. CACLBloat::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
  620. {
  621. BOOL fHandled = TRUE;
  622. switch (LOWORD(wParam))
  623. {
  624. case IDOK:
  625. EndDialog(hDlg, FALSE);
  626. break;
  627. case IDCANCEL:
  628. EndDialog(hDlg, TRUE);
  629. break;
  630. case IDHELP:
  631. HtmlHelp(NULL,
  632. L"aclui.chm::/ACLUI_acl_BP.htm",
  633. HH_DISPLAY_TOPIC,
  634. 0);
  635. break;
  636. default:
  637. fHandled = FALSE;
  638. break;
  639. }
  640. return fHandled;
  641. }