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.

1757 lines
53 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: aceedit.cpp
  8. //
  9. // This file contains the implementation for the advanced ACE editor
  10. // page.
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "aclpriv.h"
  14. #include "sddl.h" // ConvertSidToStringSid
  15. #define PWM_SELECT_PAGE (WM_APP - 1)
  16. //
  17. // Context Help IDs.
  18. //
  19. const static DWORD aAcePermHelpIDs[] =
  20. {
  21. IDC_ACEE_INHERITWARNING, IDH_NOHELP,
  22. IDC_ACEE_NAME_STATIC, IDH_ACEE_PERM_NAME,
  23. IDC_ACEE_NAME, IDH_ACEE_PERM_NAME,
  24. IDC_ACEE_NAMEBUTTON, IDH_ACEE_PERM_NAMEBUTTON,
  25. IDC_ACEE_APPLYONTO_STATIC, IDH_ACEE_PERM_INHERITTYPE,
  26. IDC_ACEE_INHERITTYPE, IDH_ACEE_PERM_INHERITTYPE,
  27. IDC_ACEE_ACCESS, IDH_ACEE_PERM_LIST,
  28. IDC_ACEE_ALLOW, IDH_ACEE_PERM_LIST,
  29. IDC_ACEE_DENY, IDH_ACEE_PERM_LIST,
  30. IDC_ACEE_LIST, IDH_ACEE_PERM_LIST,
  31. IDC_ACEE_INHERITIMMEDIATE, IDH_ACEE_PERM_INHERITIMMEDIATE,
  32. IDC_ACEE_CLEAR, IDH_ACEE_PERM_CLEAR,
  33. 0, 0
  34. };
  35. const static DWORD aAceAuditHelpIDs[] =
  36. {
  37. IDC_ACEE_INHERITWARNING, IDH_NOHELP,
  38. IDC_ACEE_NAME_STATIC, IDH_ACEE_AUDIT_NAME,
  39. IDC_ACEE_NAME, IDH_ACEE_AUDIT_NAME,
  40. IDC_ACEE_NAMEBUTTON, IDH_ACEE_AUDIT_NAMEBUTTON,
  41. IDC_ACEE_APPLYONTO_STATIC, IDH_ACEE_AUDIT_INHERITTYPE,
  42. IDC_ACEE_INHERITTYPE, IDH_ACEE_AUDIT_INHERITTYPE,
  43. IDC_ACEE_ACCESS, IDH_ACEE_AUDIT_LIST,
  44. IDC_ACEE_ALLOW, IDH_ACEE_AUDIT_LIST,
  45. IDC_ACEE_DENY, IDH_ACEE_AUDIT_LIST,
  46. IDC_ACEE_LIST, IDH_ACEE_AUDIT_LIST,
  47. IDC_ACEE_INHERITIMMEDIATE, IDH_ACEE_AUDIT_INHERITIMMEDIATE,
  48. IDC_ACEE_CLEAR, IDH_ACEE_AUDIT_CLEAR,
  49. 0, 0
  50. };
  51. class CACEPage : public CSecurityPage
  52. {
  53. private:
  54. PACE m_pAce;
  55. HDPA *m_phEntries;
  56. PSID m_pSid;
  57. DWORD m_siFlags;
  58. DWORD *m_pdwResult;
  59. GUID m_guidInheritType;
  60. BOOL m_fInheritImmediateEnabled;
  61. BOOL m_fPreviousImmediateSetting;
  62. BOOL m_fReadOnly;
  63. BOOL m_fPageDirty;
  64. SI_INHERIT_TYPE m_siInheritUnknown;
  65. CACEPage *m_pOtherPage;
  66. HWND m_hwnd;
  67. public:
  68. CACEPage(LPSECURITYINFO psi,
  69. SI_PAGE_TYPE siType,
  70. PACE pAce,
  71. BOOL bReadOnly,
  72. DWORD dwFlags,
  73. DWORD *pdwResult,
  74. HDPA *phEntries);
  75. virtual ~CACEPage();
  76. private:
  77. virtual BOOL DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  78. // Prevent propsheet callbacks from reaching the object that invoked us
  79. virtual UINT PSPageCallback(HWND, UINT, LPPROPSHEETPAGE) { return 1; }
  80. void EmptyCheckList(HWND hwndList);
  81. LONG CheckPermBoxes(HWND hwndList, PACE pAce, DWORD dwState);
  82. LONG InitCheckList(HWND hDlg, PACE pAce);
  83. LONG ReInitCheckList(HWND hDlg, HDPA hEntries);
  84. VOID DisplayNoControlMessage(HWND hDlg, BOOL bDisplay);
  85. void HideInheritedAceWarning(HWND hDlg);
  86. void InitDlg(HWND hDlg);
  87. BOOL OnChangeName(HWND hDlg);
  88. BOOL OnClearAll(HWND hDlg);
  89. void HandleSelChange(HWND hDlg, HWND hWnd);
  90. LONG OnApply(HWND hDlg, BOOL bClose);
  91. HWND m_hwndNoPerm;
  92. BOOL IsAclBloated(HWND hDlg);
  93. HDPA GetAceList(HWND hDlg);
  94. };
  95. typedef class CACEPage *LPACEPAGE;
  96. CACEPage::CACEPage(LPSECURITYINFO psi,
  97. SI_PAGE_TYPE siType,
  98. PACE pAce,
  99. BOOL bReadOnly,
  100. DWORD dwFlags,
  101. DWORD *pdwResult,
  102. HDPA *phEntries)
  103. : CSecurityPage(psi, siType), m_pAce(pAce), m_fReadOnly(bReadOnly),
  104. m_siFlags(dwFlags), m_pdwResult(pdwResult), m_phEntries(phEntries),
  105. m_hwndNoPerm(NULL),m_pOtherPage(NULL)
  106. {
  107. if (m_pdwResult)
  108. *m_pdwResult = 0;
  109. }
  110. CACEPage::~CACEPage()
  111. {
  112. if (m_pSid)
  113. LocalFree(m_pSid);
  114. if(m_hwndNoPerm)
  115. DestroyWindow(m_hwndNoPerm);
  116. }
  117. void
  118. CACEPage::EmptyCheckList(HWND hwndList)
  119. {
  120. SendMessage(hwndList, CLM_RESETCONTENT, 0, 0);
  121. }
  122. LONG
  123. CACEPage::CheckPermBoxes(HWND hwndList, PACE pAce, DWORD dwState)
  124. {
  125. LONG nLastChecked = -1;
  126. UINT cItems;
  127. BOOL bColumnAllow = FALSE;
  128. BOOL bColumnDeny = FALSE;
  129. //
  130. // Check all boxes that correspond to a particular ACE
  131. //
  132. if (hwndList == NULL || pAce == NULL)
  133. return -1;
  134. if (pAce->AceFlags & INHERITED_ACE)
  135. dwState |= CLST_DISABLED;
  136. if (m_siPageType == SI_PAGE_ADVPERM)
  137. {
  138. // Only check one column (either allow or deny)
  139. if (IsEqualACEType(pAce->AceType, ACCESS_ALLOWED_ACE_TYPE))
  140. bColumnAllow = TRUE; // Access allowed
  141. else if (IsEqualACEType(pAce->AceType, ACCESS_DENIED_ACE_TYPE))
  142. bColumnDeny = TRUE; // Access denied
  143. else
  144. return -1; // Bogus ACE
  145. }
  146. else if (m_siPageType == SI_PAGE_AUDIT)
  147. {
  148. // Either or both columns can be checked for audits
  149. if (pAce->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
  150. bColumnAllow = TRUE; // Audit successful access
  151. if (pAce->AceFlags & FAILED_ACCESS_ACE_FLAG)
  152. bColumnDeny = TRUE; // Audit failed access
  153. }
  154. else
  155. return -1;
  156. cItems = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  157. while (cItems > 0)
  158. {
  159. PSI_ACCESS pAccess;
  160. --cItems;
  161. pAccess = (PSI_ACCESS)SendMessage(hwndList, CLM_GETITEMDATA, cItems, 0);
  162. //
  163. // The below expression tests to see if this access mask enables
  164. // this access "rights" line. It could have more bits enabled, but
  165. // as long as it has all of the ones from the pAccess->mask then
  166. // it effectively has that option enabled.
  167. //
  168. if (pAccess &&
  169. AllFlagsOn(pAce->Mask, pAccess->mask) &&
  170. (!(pAce->Flags & ACE_OBJECT_TYPE_PRESENT) ||
  171. IsSameGUID(pAccess->pguid, &pAce->ObjectType)))
  172. {
  173. WPARAM wItem;
  174. nLastChecked = cItems;
  175. if (bColumnAllow)
  176. {
  177. wItem = MAKELONG((WORD)cItems, COLUMN_ALLOW);
  178. SendMessage(hwndList,
  179. CLM_SETSTATE,
  180. wItem,
  181. (LPARAM)dwState);
  182. }
  183. if (bColumnDeny)
  184. {
  185. wItem = MAKELONG((WORD)cItems, COLUMN_DENY);
  186. SendMessage(hwndList,
  187. CLM_SETSTATE,
  188. wItem,
  189. (LPARAM)dwState);
  190. }
  191. }
  192. }
  193. return nLastChecked;
  194. }
  195. LONG
  196. CACEPage::InitCheckList(HWND hDlg, PACE pAce)
  197. {
  198. LONG nTopItemChecked;
  199. HDPA hList = NULL;
  200. TraceEnter(TRACE_ACEEDIT, "CACEPage::InitCheckList");
  201. TraceAssert(hDlg != NULL);
  202. if (m_siPageType == SI_PAGE_AUDIT)
  203. SendDlgItemMessage(hDlg, IDC_ACEE_LIST, CLM_SETCOLUMNWIDTH, 0, 40);
  204. hList = DPA_Create(1);
  205. if (hList && pAce)
  206. DPA_AppendPtr(hList, pAce->Copy());
  207. nTopItemChecked = ReInitCheckList(hDlg, hList);
  208. if (hList)
  209. DestroyDPA(hList);
  210. TraceLeaveValue(nTopItemChecked);
  211. }
  212. LONG
  213. CACEPage::ReInitCheckList(HWND hDlg, HDPA hEntries)
  214. {
  215. LONG nTopItemChecked = -1;
  216. HWND hwndList;
  217. DWORD dwFlags;
  218. HRESULT hr;
  219. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  220. TraceEnter(TRACE_ACEEDIT, "CACEPage::ReInitCheckList");
  221. TraceAssert(hDlg != NULL);
  222. hwndList = GetDlgItem(hDlg, IDC_ACEE_LIST);
  223. EmptyCheckList(hwndList);
  224. dwFlags = SI_ADVANCED;
  225. if (m_siPageType == SI_PAGE_AUDIT)
  226. dwFlags |= SI_EDIT_AUDITS;
  227. if (m_siFlags == SI_ACCESS_PROPERTY)
  228. dwFlags |= SI_EDIT_PROPERTIES;
  229. //
  230. // Enumerate the permissions and add to the checklist
  231. //
  232. hr = _InitCheckList(hwndList,
  233. m_psi,
  234. &m_guidInheritType,
  235. dwFlags,
  236. m_siObjectInfo.hInstance,
  237. m_siFlags,
  238. NULL);
  239. if (SUCCEEDED(hr))
  240. {
  241. UINT cItems = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  242. //
  243. //On object page display the message if number
  244. //cItems is zero.
  245. //
  246. if(m_siFlags == SI_ACCESS_SPECIFIC)
  247. DisplayNoControlMessage(hDlg, !cItems);
  248. ULONG cAces = 0;
  249. if (hEntries)
  250. cAces = DPA_GetPtrCount(hEntries);
  251. //
  252. // Check the appropriate boxes
  253. //
  254. nTopItemChecked = MAXLONG;
  255. while (cAces > 0)
  256. {
  257. PACE_HEADER pAceHeader;
  258. --cAces;
  259. pAceHeader = (PACE_HEADER)DPA_FastGetPtr(hEntries, cAces);
  260. if (pAceHeader)
  261. {
  262. CAce Ace(pAceHeader);
  263. LONG nTop = CheckPermBoxes(hwndList, &Ace, CLST_CHECKED);
  264. if (-1 != nTop)
  265. nTopItemChecked = min(nTopItemChecked, nTop);
  266. }
  267. }
  268. if (MAXLONG == nTopItemChecked)
  269. nTopItemChecked = -1;
  270. // Make sure the top item checked is scrolled into view.
  271. // (-1 scrolls to the top, same as 0.)
  272. SendMessage(hwndList, CLM_ENSUREVISIBLE, nTopItemChecked, 0);
  273. // Disable all of the boxes if we're in read-only mode
  274. if (m_fReadOnly)
  275. SendMessage(hwndList, WM_ENABLE, FALSE, 0);
  276. }
  277. SetCursor(hcur);
  278. TraceLeaveValue(nTopItemChecked);
  279. }
  280. VOID CACEPage::DisplayNoControlMessage(HWND hDlg, BOOL bDisplay)
  281. {
  282. RECT rc;
  283. if(bDisplay)
  284. {
  285. ShowWindow(m_hwndNoPerm, SW_SHOW);
  286. }
  287. else
  288. {
  289. ShowWindow(m_hwndNoPerm, SW_HIDE);
  290. }
  291. }
  292. void CACEPage::HideInheritedAceWarning(HWND hDlg)
  293. // Hides the message informing the user that the current ACE is inherited from
  294. // the parent. Also moves and resizes controls as appropriate.
  295. {
  296. // Array of control IDs to move up
  297. static UINT rgMoveControls[] =
  298. {
  299. IDC_ACEE_NAME_STATIC,
  300. IDC_ACEE_NAME,
  301. IDC_ACEE_NAMEBUTTON,
  302. IDC_ACEE_APPLYONTO_STATIC,
  303. IDC_ACEE_INHERITTYPE,
  304. IDC_ACEE_ACCESS,
  305. IDC_ACEE_ALLOW,
  306. IDC_ACEE_DENY,
  307. };
  308. // Get the message window dimensions
  309. HWND hwndControl = GetDlgItem(hDlg, IDC_ACEE_INHERITWARNING);
  310. RECT rect;
  311. GetWindowRect(hwndControl, &rect);
  312. // We need to move controls up this amount:
  313. int nMoveUpAmount = rect.bottom - rect.top;
  314. // Rather than hide the message window, destroy it altogether so WinHelp
  315. // doesn't confuse it with the "Name:" static during WM_CONTEXTMENU.
  316. DestroyWindow(hwndControl);
  317. // Move each of the controls we need to move up
  318. for (int nControl = 0; nControl < ARRAYSIZE(rgMoveControls); nControl++)
  319. {
  320. hwndControl = GetDlgItem(hDlg, rgMoveControls[nControl]);
  321. GetWindowRect(hwndControl, &rect);
  322. MapWindowPoints(NULL, hDlg, (LPPOINT)&rect, 2);
  323. SetWindowPos(hwndControl,
  324. NULL,
  325. rect.left,
  326. rect.top - nMoveUpAmount,
  327. 0,
  328. 0,
  329. SWP_NOSIZE | SWP_NOZORDER);
  330. }
  331. // Finally, we need to resize the list control, including adjusting its height
  332. hwndControl = GetDlgItem(hDlg, IDC_ACEE_LIST);
  333. GetWindowRect(hwndControl, &rect);
  334. MapWindowPoints(NULL, hDlg, (LPPOINT)&rect, 2);
  335. SetWindowPos(hwndControl,
  336. NULL,
  337. rect.left,
  338. rect.top - nMoveUpAmount,
  339. rect.right - rect.left,
  340. rect.bottom - (rect.top - nMoveUpAmount),
  341. SWP_NOZORDER);
  342. }
  343. //
  344. // Default "Apply onto" strings for when GetInheritTypes
  345. // fails or we don't find a matching inherit type.
  346. //
  347. // If desirable, different strings can be created for
  348. // CONTAINER_INHERIT_ACE vs OBJECT_INHERIT_ACE.
  349. //
  350. static const UINT s_aInheritTypes[] =
  351. {
  352. IDS_THIS_OBJECT_ONLY, // 0 = <no inheritance>
  353. IDS_THIS_OBJECT_AND_SUBOBJECTS, // 1 = OBJECT_INHERIT_ACE
  354. IDS_THIS_OBJECT_AND_SUBOBJECTS, // 2 = CONTAINER_INHERIT_ACE
  355. IDS_THIS_OBJECT_AND_SUBOBJECTS, // 3 = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
  356. };
  357. // These are used when INHERIT_ONLY_ACE is present
  358. static const UINT s_aInheritOnlyTypes[] =
  359. {
  360. IDS_INVALID_INHERIT, // 0 = <invalid>
  361. IDS_SUBOBJECTS_ONLY, // 1 = OBJECT_INHERIT_ACE
  362. IDS_SUBOBJECTS_ONLY, // 2 = CONTAINER_INHERIT_ACE
  363. IDS_SUBOBJECTS_ONLY, // 3 = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
  364. };
  365. static int
  366. _AddInheritType(HWND hInheritType,
  367. PSI_INHERIT_TYPE psiInheritType,
  368. HINSTANCE hInstance)
  369. {
  370. UINT iIndex;
  371. TCHAR szName[MAX_PATH];
  372. LPCTSTR pszName = psiInheritType->pszName;
  373. if (IS_INTRESOURCE(pszName))
  374. {
  375. if (LoadString(hInstance,
  376. (ULONG)((ULONG_PTR)pszName),
  377. szName,
  378. ARRAYSIZE(szName)) == 0)
  379. {
  380. LoadString(::hModule,
  381. IDS_UNKNOWN,
  382. szName,
  383. ARRAYSIZE(szName));
  384. }
  385. pszName = szName;
  386. }
  387. iIndex = (UINT)SendMessage(hInheritType, CB_ADDSTRING, 0, (LPARAM)pszName);
  388. if (CB_ERR != iIndex)
  389. SendMessage(hInheritType, CB_SETITEMDATA, iIndex, (LPARAM)psiInheritType);
  390. return iIndex;
  391. }
  392. void
  393. CACEPage::InitDlg(HWND hDlg)
  394. {
  395. #define X_COR 7
  396. #define Y_COR 7
  397. UCHAR AceFlags = 0;
  398. PSID pSid = NULL;
  399. LPCTSTR pszName = NULL;
  400. LPTSTR pszNameT = NULL;
  401. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  402. HRESULT hr;
  403. TraceEnter(TRACE_ACEEDIT, "CACEPage::InitDlg");
  404. //
  405. //Store the hDlg
  406. //
  407. m_hwnd = hDlg;
  408. if(m_siFlags == SI_ACCESS_SPECIFIC)
  409. {
  410. //
  411. //Create a label to show message when no generic
  412. //permissions exist for the object
  413. //
  414. WCHAR szName[1024];
  415. LoadString(::hModule, IDS_NO_OBJECT_PERM, szName, ARRAYSIZE(szName));
  416. RECT rc;
  417. GetWindowRect(GetDlgItem(hDlg,IDC_ACEE_LIST),&rc);
  418. // Create a new label control
  419. m_hwndNoPerm = CreateWindowEx(0,
  420. TEXT("STATIC"),
  421. szName,
  422. WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP | SS_NOPREFIX,
  423. X_COR,
  424. Y_COR,
  425. rc.right - rc.left - 2*X_COR,
  426. rc.bottom - rc.top - 2*Y_COR,
  427. GetDlgItem(hDlg,IDC_ACEE_LIST),
  428. (HMENU)IntToPtr(0xffff),
  429. ::hModule,
  430. NULL);
  431. // Set the font
  432. SendMessage(m_hwndNoPerm,
  433. WM_SETFONT,
  434. SendMessage(hDlg, WM_GETFONT, 0, 0),
  435. 0);
  436. }
  437. if (m_pAce)
  438. {
  439. AceFlags = m_pAce->AceFlags;
  440. m_guidInheritType = m_pAce->InheritedObjectType;
  441. pSid = m_pAce->psid;
  442. pszName = m_pAce->LookupName(m_siObjectInfo.pszServerName, m_psi2);
  443. }
  444. else
  445. {
  446. if (m_siObjectInfo.dwFlags & SI_CONTAINER)
  447. AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
  448. pSid = QuerySystemSid(UI_SID_World);
  449. }
  450. // Make sure the AceFlags are valid
  451. ACCESS_MASK Mask = 0;
  452. m_psi->MapGeneric(&m_guidInheritType, &AceFlags, &Mask);
  453. // Hide the inherit warning and adjust other control positions
  454. if (!(AceFlags & INHERITED_ACE))
  455. HideInheritedAceWarning(hDlg);
  456. // Make a copy of the sid and get the name
  457. if (pSid)
  458. {
  459. PUSER_LIST pUserList = NULL;
  460. m_pSid = LocalAllocSid(pSid);
  461. if (pszName == NULL)
  462. {
  463. // This should only happen when m_pAce is NULL and we're
  464. // using UI_SID_World
  465. if (LookupSid(pSid, m_siObjectInfo.pszServerName, m_psi2, &pUserList))
  466. {
  467. TraceAssert(NULL != pUserList);
  468. TraceAssert(1 == pUserList->cUsers);
  469. if (BuildUserDisplayName(&pszNameT,
  470. pUserList->rgUsers[0].pszName,
  471. pUserList->rgUsers[0].pszLogonName)
  472. || ConvertSidToStringSid(pSid, &pszNameT))
  473. {
  474. pszName = pszNameT;
  475. }
  476. }
  477. }
  478. SetDlgItemText(hDlg, IDC_ACEE_NAME, pszName);
  479. if (NULL != pUserList)
  480. LocalFree(pUserList);
  481. }
  482. // Get the list of permissions and initialize the check boxes
  483. LONG nTopChecked = InitCheckList(hDlg, m_pAce);
  484. if (-1 == nTopChecked &&
  485. m_pAce &&
  486. m_pAce->Mask &&
  487. (m_siObjectInfo.dwFlags & SI_EDIT_PROPERTIES) &&
  488. m_siFlags != SI_ACCESS_PROPERTY)
  489. {
  490. // Must be a property ACE, switch to the Properties page
  491. PostMessage(hDlg, PWM_SELECT_PAGE, 1, 0);
  492. }
  493. HWND hInheritType = GetDlgItem(hDlg, IDC_ACEE_INHERITTYPE);
  494. HWND hInheritImmed = GetDlgItem(hDlg, IDC_ACEE_INHERITIMMEDIATE);
  495. if (m_siObjectInfo.dwFlags & SI_NO_TREE_APPLY)
  496. {
  497. ShowWindow(hInheritImmed, SW_HIDE);
  498. EnableWindow(hInheritImmed, FALSE);
  499. }
  500. //
  501. // Get inherit types from callback
  502. //
  503. ULONG cItems = 0;
  504. PSI_INHERIT_TYPE psiInheritType = NULL;
  505. hr = m_psi->GetInheritTypes(&psiInheritType, &cItems);
  506. if (SUCCEEDED(hr))
  507. {
  508. // Check these inherit bits for a match
  509. DWORD dwInheritMask = INHERIT_ONLY_ACE | ACE_INHERIT_ALL;
  510. // Don't check INHERIT_ONLY_ACE if the ACE inherit type
  511. // matches the current object
  512. if ((m_siObjectInfo.dwFlags & SI_OBJECT_GUID) &&
  513. IsSameGUID(&m_siObjectInfo.guidObjectType, &m_guidInheritType))
  514. {
  515. dwInheritMask &= ~INHERIT_ONLY_ACE;
  516. }
  517. //
  518. // Add inherit types to combobox
  519. //
  520. for ( ; cItems > 0; cItems--, psiInheritType++)
  521. {
  522. UINT iIndex = _AddInheritType(hInheritType,
  523. psiInheritType,
  524. m_siObjectInfo.hInstance);
  525. // See if this entry matches the incoming ACE
  526. if ((psiInheritType->dwFlags & dwInheritMask) == (ULONG)(AceFlags & dwInheritMask)
  527. && IsSameGUID(&m_guidInheritType, psiInheritType->pguid))
  528. {
  529. // Got a match, select this entry
  530. SendMessage(hInheritType, CB_SETCURSEL, iIndex, 0);
  531. }
  532. }
  533. }
  534. //
  535. // If GetInheritTypes failed, or we failed to find a match,
  536. // pick a default string and build an appropriate inherit type.
  537. //
  538. if (FAILED(hr) || CB_ERR == SendMessage(hInheritType, CB_GETCURSEL, 0, 0))
  539. {
  540. // Pick a default string
  541. UINT ids = IDS_SPECIAL;
  542. if (IsNullGUID(&m_guidInheritType))
  543. {
  544. if (AceFlags & INHERIT_ONLY_ACE)
  545. ids = s_aInheritOnlyTypes[AceFlags & ACE_INHERIT_ALL];
  546. else
  547. ids = s_aInheritTypes[AceFlags & ACE_INHERIT_ALL];
  548. }
  549. // Fill in m_siInheritUnknown with the pertinent info
  550. m_siInheritUnknown.pguid = &m_guidInheritType;
  551. m_siInheritUnknown.dwFlags = AceFlags & (INHERIT_ONLY_ACE | ACE_INHERIT_ALL);
  552. m_siInheritUnknown.pszName = MAKEINTRESOURCE(ids);
  553. // Insert and select it
  554. UINT iIndex = _AddInheritType(hInheritType,
  555. &m_siInheritUnknown,
  556. ::hModule);
  557. SendMessage(hInheritType, CB_SETCURSEL, iIndex, 0);
  558. if (FAILED(hr))
  559. {
  560. // GetInheritTypes failed, which means the only entry is the
  561. // default one we just added. Disable the combo.
  562. EnableWindow(hInheritType, FALSE);
  563. }
  564. }
  565. //
  566. // Select the options which match the incoming ace
  567. //
  568. if (!(AceFlags & (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE)))
  569. {
  570. SendMessage(hInheritImmed, BM_SETCHECK, BST_UNCHECKED, 0);
  571. EnableWindow(hInheritImmed, FALSE);
  572. m_fInheritImmediateEnabled = FALSE;
  573. m_fPreviousImmediateSetting = BST_UNCHECKED;
  574. }
  575. else
  576. {
  577. SendMessage(hInheritImmed,
  578. BM_SETCHECK,
  579. (AceFlags & NO_PROPAGATE_INHERIT_ACE) ? BST_CHECKED : BST_UNCHECKED,
  580. 0);
  581. m_fInheritImmediateEnabled = TRUE;
  582. }
  583. if (!(m_siObjectInfo.dwFlags & SI_CONTAINER) || m_fReadOnly || (AceFlags & INHERITED_ACE))
  584. {
  585. // Disable all inheritance
  586. EnableWindow(hInheritType, FALSE);
  587. EnableWindow(hInheritImmed, FALSE);
  588. }
  589. if (m_fReadOnly || (AceFlags & INHERITED_ACE))
  590. {
  591. // Disable the "change name" and "clear all" buttons
  592. EnableWindow(GetDlgItem(hDlg, IDC_ACEE_NAMEBUTTON), FALSE);
  593. EnableWindow(GetDlgItem(hDlg, IDC_ACEE_CLEAR), FALSE);
  594. }
  595. PropSheet_QuerySiblings(GetParent(hDlg),0,(LPARAM)this);
  596. LocalFreeString(&pszNameT);
  597. SetCursor(hcur);
  598. TraceLeaveVoid();
  599. }
  600. BOOL
  601. CACEPage::OnChangeName(HWND hDlg)
  602. {
  603. PUSER_LIST pUserList = NULL;
  604. BOOL bResult = FALSE;
  605. TraceEnter(TRACE_ACEEDIT, "CACEPage::OnChangeName");
  606. if (S_OK == GetUserGroup(hDlg, FALSE, &pUserList))
  607. {
  608. TraceAssert(NULL != pUserList);
  609. TraceAssert(1 == pUserList->cUsers);
  610. // Free up previous sid
  611. if (m_pSid)
  612. LocalFree(m_pSid);
  613. // Copy the new sid
  614. m_pSid = LocalAllocSid(pUserList->rgUsers[0].pSid);
  615. if (m_pSid)
  616. {
  617. SetDlgItemText(hDlg, IDC_ACEE_NAME, pUserList->rgUsers[0].pszName);
  618. bResult = TRUE;
  619. }
  620. LocalFree(pUserList);
  621. }
  622. TraceLeaveValue(bResult);
  623. }
  624. BOOL
  625. CACEPage::OnClearAll(HWND hDlg)
  626. {
  627. HWND hwndList;
  628. ULONG cPermissions;
  629. TraceEnter(TRACE_ACEEDIT, "CACEPage::OnClearAll");
  630. TraceAssert(!m_fReadOnly);
  631. hwndList = GetDlgItem(hDlg, IDC_ACEE_LIST);
  632. cPermissions = (ULONG)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  633. while (cPermissions != 0)
  634. {
  635. WORD wCol = COLUMN_ALLOW;
  636. cPermissions--;
  637. while (wCol == COLUMN_ALLOW || wCol == COLUMN_DENY)
  638. {
  639. WPARAM wItem = MAKELONG((WORD)cPermissions, wCol);
  640. if (!(CLST_DISABLED & SendMessage(hwndList, CLM_GETSTATE, wItem, 0)))
  641. SendMessage(hwndList, CLM_SETSTATE, wItem, CLST_UNCHECKED);
  642. wCol++;
  643. }
  644. }
  645. TraceLeaveValue(TRUE);
  646. }
  647. void
  648. CACEPage::HandleSelChange(HWND hDlg, HWND hWnd) // inherit type change
  649. {
  650. PSI_INHERIT_TYPE psiInheritType;
  651. BOOL fEnableInheritImmediate = FALSE;
  652. const GUID *pguidInheritType = &GUID_NULL;
  653. TraceEnter(TRACE_ACEEDIT, "CACEPage::HandleSelChange");
  654. psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hWnd,
  655. CB_GETITEMDATA,
  656. SendMessage(hWnd, CB_GETCURSEL, 0, 0),
  657. 0);
  658. if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL)
  659. {
  660. if (psiInheritType->dwFlags & (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE))
  661. fEnableInheritImmediate = TRUE;
  662. if( psiInheritType->pguid )
  663. pguidInheritType = psiInheritType->pguid;
  664. }
  665. if (fEnableInheritImmediate != m_fInheritImmediateEnabled)
  666. {
  667. HWND hInheritImmediate = GetDlgItem(hDlg, IDC_ACEE_INHERITIMMEDIATE);
  668. if (fEnableInheritImmediate)
  669. {
  670. SendMessage(hInheritImmediate, BM_SETCHECK, m_fPreviousImmediateSetting, 0);
  671. }
  672. else
  673. {
  674. m_fPreviousImmediateSetting = (BOOL)SendMessage(hInheritImmediate,
  675. BM_GETCHECK,
  676. 0,
  677. 0);
  678. SendMessage(hInheritImmediate, BM_SETCHECK, BST_UNCHECKED, 0);
  679. }
  680. EnableWindow(hInheritImmediate, fEnableInheritImmediate);
  681. m_fInheritImmediateEnabled = fEnableInheritImmediate;
  682. }
  683. // If the inherit type GUID has changed, reinitialize the checklist.
  684. if (!IsSameGUID(pguidInheritType, &m_guidInheritType))
  685. {
  686. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  687. HDPA hNewEntries = DPA_Create(4);
  688. if (hNewEntries)
  689. {
  690. GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST),
  691. m_pSid,
  692. m_siPageType == SI_PAGE_ADVPERM,
  693. TRUE,
  694. 0, // don't care about flags
  695. NULL, // or inherit type here
  696. hNewEntries);
  697. // Save new inherit type and reset the checklist
  698. m_guidInheritType = *pguidInheritType;
  699. ReInitCheckList(hDlg, hNewEntries);
  700. DestroyDPA(hNewEntries);
  701. }
  702. SetCursor(hcur);
  703. }
  704. TraceLeaveVoid();
  705. }
  706. void
  707. HandleListClick(PNM_CHECKLIST pnmc,
  708. SI_PAGE_TYPE siType,
  709. BOOL bInheritFlags,
  710. HDSA *phAllowUncheckedAccess,
  711. HDSA *phDenyUncheckedAccess,
  712. BOOL bCustomPresent)
  713. {
  714. HWND hChkList;
  715. UINT iRow;
  716. WORD wCol;
  717. PSI_ACCESS pAccess;
  718. DWORD dwState;
  719. BOOL bNullGuid;
  720. UINT iRowCompare;
  721. PSI_ACCESS pAccessCompare;
  722. TraceEnter(TRACE_MISC, "HandleListClick");
  723. TraceAssert(pnmc != NULL);
  724. hChkList = pnmc->hdr.hwndFrom;
  725. iRow = pnmc->iItem;
  726. wCol = (WORD)pnmc->iSubItem; // 1 = Allow, 2 = Deny
  727. pAccess = (PSI_ACCESS)pnmc->dwItemData;
  728. dwState = pnmc->dwState;
  729. if (pAccess == NULL)
  730. TraceLeaveVoid();
  731. if( phAllowUncheckedAccess )
  732. {
  733. *phAllowUncheckedAccess = DSA_Create(SIZEOF(PSI_ACCESS), 4);
  734. if (*phAllowUncheckedAccess == NULL)
  735. {
  736. TraceMsg("DSA_Create failed");
  737. TraceLeaveVoid();
  738. }
  739. }
  740. if( phDenyUncheckedAccess )
  741. {
  742. *phDenyUncheckedAccess = DSA_Create(SIZEOF(PSI_ACCESS), 4);
  743. if (*phDenyUncheckedAccess == NULL)
  744. {
  745. TraceMsg("DSA_Create failed");
  746. TraceLeaveVoid();
  747. }
  748. }
  749. bNullGuid = IsNullGUID(pAccess->pguid);
  750. iRowCompare = (UINT)SendMessage(hChkList, CLM_GETITEMCOUNT, 0, 0);
  751. //Custom checkbox is handled Separately
  752. if( bCustomPresent )
  753. --iRowCompare;
  754. while (iRowCompare != 0)
  755. {
  756. WPARAM wItem;
  757. DWORD dwStateCompareOriginal;
  758. DWORD dwStateCompare;
  759. WORD wColCompare;
  760. BOOL bSameGuid;
  761. BOOL bNullGuidCompare;
  762. --iRowCompare;
  763. pAccessCompare = (PSI_ACCESS)SendMessage(hChkList, CLM_GETITEMDATA, iRowCompare, 0);
  764. if (!pAccessCompare)
  765. continue;
  766. bSameGuid = IsSameGUID(pAccessCompare->pguid, pAccess->pguid);
  767. bNullGuidCompare = IsNullGUID(pAccessCompare->pguid);
  768. // If the GUIDs are incompatible, then we can't do anything
  769. if (!(bSameGuid || bNullGuid || bNullGuidCompare))
  770. continue;
  771. //
  772. // Yukky, complicated mechanism to determine whether to
  773. // turn on or off the allow or deny check marks.
  774. //
  775. // REVIEW: This algorithm of changing check marks based on other
  776. // checkmarks handles a lot of cases, but it doesn't handle a
  777. // two good ones.
  778. //
  779. // (1) If you have a right which implies other rights and you turn,
  780. // it off, then maybe we should turn off all of the implied ones
  781. // too. For example, you turn off change (which is the combination
  782. // of read and write) maybe we should turn off both read and write.
  783. //
  784. // (2) If you turn on all of the component rights of one which
  785. // implies them all, then we should turn on that one (because
  786. // it implies them all).
  787. //
  788. #ifdef NO_RADIOBUTTON_BEHAVIOR
  789. wColCompare = wCol;
  790. #else
  791. for (wColCompare = COLUMN_ALLOW; wColCompare <= COLUMN_DENY; wColCompare++)
  792. #endif
  793. {
  794. wItem = MAKELONG((WORD)iRowCompare, wColCompare);
  795. dwStateCompareOriginal = (DWORD)SendMessage(hChkList, CLM_GETSTATE, wItem, 0);
  796. //
  797. // If the other box is disabled, then it represents an
  798. // inherited right so don't do anything with it.
  799. //
  800. // nb: Depending on NO_RADIOBUTTON_BEHAVIOR, this may continue to the
  801. // for(wColCompare) loop or the while(iRowCompare) loop as appropriate
  802. //
  803. if (dwStateCompareOriginal & CLST_DISABLED)
  804. continue;
  805. dwStateCompare = dwStateCompareOriginal;
  806. if (dwState & CLST_CHECKED)
  807. {
  808. if (wCol == wColCompare)
  809. {
  810. //
  811. // If this right implies some other right,
  812. // then turn it on too.
  813. //
  814. if ((bSameGuid || bNullGuid) && AllFlagsOn(pAccess->mask, pAccessCompare->mask))
  815. {
  816. if (!bInheritFlags ||
  817. AllFlagsOn(pAccess->dwFlags & ACE_INHERIT_ALL, pAccessCompare->dwFlags & ACE_INHERIT_ALL))
  818. {
  819. dwStateCompare |= CLST_CHECKED;
  820. }
  821. }
  822. }
  823. else
  824. {
  825. #ifndef NO_RADIOBUTTON_BEHAVIOR
  826. //
  827. // If this right implies or is implied by some other
  828. // right in the other column, then turn it off.
  829. //
  830. if ( (siType == SI_PAGE_PERM || siType == SI_PAGE_ADVPERM) &&
  831. (((bSameGuid || bNullGuid) && AllFlagsOn(pAccess->mask, pAccessCompare->mask)) ||
  832. ((bSameGuid || bNullGuidCompare) && AllFlagsOn(pAccessCompare->mask, pAccess->mask))) )
  833. {
  834. if (!bInheritFlags ||
  835. (AllFlagsOn(pAccessCompare->dwFlags & ACE_INHERIT_ALL, pAccess->dwFlags & ACE_INHERIT_ALL) ||
  836. AllFlagsOn(pAccess->dwFlags & ACE_INHERIT_ALL, pAccessCompare->dwFlags & ACE_INHERIT_ALL)) )
  837. {
  838. dwStateCompare &= ~(CLST_CHECKED);
  839. }
  840. }
  841. #endif
  842. }
  843. }
  844. else
  845. {
  846. if (wCol == wColCompare)
  847. {
  848. //
  849. // If this right is implied by some other right, then
  850. // turn it off too.
  851. //
  852. if ((bSameGuid || bNullGuidCompare) && AllFlagsOn(pAccessCompare->mask, pAccess->mask))
  853. {
  854. if (!bInheritFlags ||
  855. AllFlagsOn(pAccessCompare->dwFlags & ACE_INHERIT_ALL, pAccess->dwFlags & ACE_INHERIT_ALL))
  856. {
  857. dwStateCompare &= ~(CLST_CHECKED);
  858. }
  859. }
  860. }
  861. }
  862. if (dwStateCompareOriginal != dwStateCompare)
  863. {
  864. SendMessage(hChkList, CLM_SETSTATE, wItem, (LPARAM)dwStateCompare);
  865. //If a checkbox was intially checked and and now unchecked, add to
  866. //h[Allow|Deny]UncheckedAccess.
  867. if( dwStateCompareOriginal & CLST_CHECKED && !(dwStateCompare & CLST_CHECKED) )
  868. {
  869. if( phDenyUncheckedAccess && ( wColCompare == COLUMN_DENY ) )
  870. DSA_AppendItem(*phDenyUncheckedAccess, &pAccessCompare);
  871. if( phAllowUncheckedAccess && ( wColCompare == COLUMN_ALLOW ) )
  872. DSA_AppendItem(*phAllowUncheckedAccess, &pAccessCompare);
  873. }
  874. }
  875. }
  876. }
  877. TraceLeaveVoid();
  878. }
  879. UINT
  880. GetAcesFromCheckList(HWND hChkList,
  881. PSID pSid, // All aces get this SID
  882. BOOL fPerm, // Create ACCESS or AUDIT aces?
  883. BOOL fAceFlagsProvided, // Use uAceFlagsAll instead of pAccess->dwFlags
  884. UCHAR uAceFlagsAll, // All aces get these flags
  885. const GUID *pInheritGUID, // All aces get this inherit GUID
  886. HDPA hEntries) // Store new aces here
  887. {
  888. UINT cCheckRows;
  889. UINT iCheckRow;
  890. UINT cbSidSize;
  891. UINT iCount;
  892. BOOL bInheritTypePresent = FALSE;
  893. TraceEnter(TRACE_MISC, "GetAcesFromCheckList");
  894. TraceAssert(hChkList != NULL);
  895. TraceAssert(pSid != NULL);
  896. TraceAssert(hEntries != NULL);
  897. cbSidSize = GetLengthSid(pSid);
  898. if (pInheritGUID == NULL)
  899. pInheritGUID = &GUID_NULL;
  900. else if (!IsNullGUID(pInheritGUID))
  901. bInheritTypePresent = TRUE;
  902. //
  903. // First clear out the old HDPA
  904. //
  905. iCount = DPA_GetPtrCount(hEntries);
  906. while (iCount != 0)
  907. {
  908. --iCount;
  909. LocalFree(DPA_FastGetPtr(hEntries, iCount));
  910. DPA_DeletePtr(hEntries, iCount);
  911. }
  912. cCheckRows = (UINT)SendMessage(hChkList, CLM_GETITEMCOUNT, 0, 0);
  913. for (iCheckRow = 0; iCheckRow < cCheckRows; iCheckRow++)
  914. {
  915. PSI_ACCESS pAccess;
  916. DWORD dwObjectFlagsNew;
  917. WORD wCol;
  918. UCHAR uAceFlagsNew;
  919. pAccess = (PSI_ACCESS)SendMessage(hChkList, CLM_GETITEMDATA, iCheckRow, 0);
  920. uAceFlagsNew = (UCHAR)(fAceFlagsProvided ? uAceFlagsAll : pAccess->dwFlags);
  921. dwObjectFlagsNew = 0;
  922. if (!IsNullGUID(pAccess->pguid))
  923. dwObjectFlagsNew |= ACE_OBJECT_TYPE_PRESENT;
  924. if (bInheritTypePresent)
  925. dwObjectFlagsNew |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
  926. wCol = COLUMN_ALLOW;
  927. while (wCol == COLUMN_ALLOW || wCol == COLUMN_DENY)
  928. {
  929. WPARAM wItem;
  930. DWORD dwState;
  931. wItem = MAKELONG((WORD)iCheckRow, wCol);
  932. dwState = (DWORD)SendMessage(hChkList, CLM_GETSTATE, wItem, 0);
  933. if ((dwState & CLST_CHECKED) && !(dwState & CLST_DISABLED))
  934. {
  935. //
  936. // Ok, time to make an ACE for this check mark, see if we
  937. // can merge it into an already existing ACE, or whether we
  938. // we need to create a new entry
  939. //
  940. UCHAR uAceTypeNew;
  941. DWORD dwMaskNew = pAccess->mask;
  942. UINT cbSize = SIZEOF(KNOWN_ACE);
  943. if (fPerm)
  944. {
  945. if (wCol == COLUMN_ALLOW)
  946. uAceTypeNew = ACCESS_ALLOWED_ACE_TYPE;
  947. else
  948. uAceTypeNew = ACCESS_DENIED_ACE_TYPE;
  949. }
  950. else
  951. {
  952. uAceTypeNew = SYSTEM_AUDIT_ACE_TYPE;
  953. uAceFlagsNew &= ~(SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG);
  954. if (wCol == COLUMN_ALLOW)
  955. uAceFlagsNew |= SUCCESSFUL_ACCESS_ACE_FLAG;
  956. else
  957. uAceFlagsNew |= FAILED_ACCESS_ACE_FLAG;
  958. }
  959. if (dwObjectFlagsNew != 0)
  960. {
  961. uAceTypeNew += (ACCESS_ALLOWED_OBJECT_ACE_TYPE - ACCESS_ALLOWED_ACE_TYPE);
  962. cbSize = SIZEOF(KNOWN_OBJECT_ACE);
  963. if (dwObjectFlagsNew & ACE_OBJECT_TYPE_PRESENT)
  964. cbSize += SIZEOF(GUID);
  965. if (dwObjectFlagsNew & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  966. cbSize += SIZEOF(GUID);
  967. }
  968. cbSize += cbSidSize - SIZEOF(ULONG);
  969. //
  970. // See if it exists
  971. //
  972. iCount = DPA_GetPtrCount(hEntries);
  973. while(iCount != 0)
  974. {
  975. PACE_HEADER pAce;
  976. BOOL bObjectTypePresent = FALSE;
  977. const GUID *pObjectType = NULL;
  978. --iCount;
  979. pAce = (PACE_HEADER)DPA_FastGetPtr(hEntries, iCount);
  980. if (IsObjectAceType(pAce))
  981. pObjectType = RtlObjectAceObjectType(pAce);
  982. if (!pObjectType)
  983. pObjectType = &GUID_NULL;
  984. else
  985. bObjectTypePresent = TRUE;
  986. //
  987. // Test the new ACE against each existing ACE to see if
  988. // we can combine them.
  989. //
  990. if (IsEqualACEType(pAce->AceType, uAceTypeNew))
  991. {
  992. DWORD dwMergeFlags = 0;
  993. DWORD dwMergeStatus;
  994. DWORD dwMergeResult;
  995. if (dwObjectFlagsNew & ACE_OBJECT_TYPE_PRESENT)
  996. dwMergeFlags |= MF_OBJECT_TYPE_1_PRESENT;
  997. if (bObjectTypePresent)
  998. dwMergeFlags |= MF_OBJECT_TYPE_2_PRESENT;
  999. if (!(dwMergeFlags & (MF_OBJECT_TYPE_1_PRESENT | MF_OBJECT_TYPE_2_PRESENT)))
  1000. {
  1001. // Neither are present, so they are the same
  1002. dwMergeFlags |= MF_OBJECT_TYPE_EQUAL;
  1003. }
  1004. else if (IsSameGUID(pAccess->pguid, pObjectType))
  1005. dwMergeFlags |= MF_OBJECT_TYPE_EQUAL;
  1006. if (!fPerm)
  1007. dwMergeFlags |= MF_AUDIT_ACE_TYPE;
  1008. dwMergeStatus = MergeAceHelper(uAceFlagsNew,
  1009. dwMaskNew,
  1010. pAce->AceFlags,
  1011. ((PKNOWN_ACE)pAce)->Mask,
  1012. dwMergeFlags,
  1013. &dwMergeResult);
  1014. if (dwMergeStatus == MERGE_MODIFIED_FLAGS)
  1015. {
  1016. uAceFlagsNew = (UCHAR)dwMergeResult;
  1017. dwMergeStatus = MERGE_OK_1;
  1018. }
  1019. else if (dwMergeStatus == MERGE_MODIFIED_MASK)
  1020. {
  1021. dwMaskNew = dwMergeResult;
  1022. dwMergeStatus = MERGE_OK_1;
  1023. }
  1024. if (dwMergeStatus == MERGE_OK_1)
  1025. {
  1026. //
  1027. // The new ACE implies the existing ACE, so
  1028. // the existing one can be removed.
  1029. //
  1030. LocalFree(pAce);
  1031. DPA_DeletePtr(hEntries, iCount);
  1032. //
  1033. // Keep looking. Maybe we can remove some more entries
  1034. // before adding the new one.
  1035. //
  1036. }
  1037. else if (dwMergeStatus == MERGE_OK_2)
  1038. {
  1039. iCount = 1; // non-zero for match found
  1040. break;
  1041. }
  1042. }
  1043. }
  1044. //
  1045. // Otherwise, add it
  1046. //
  1047. if (iCount == 0)
  1048. {
  1049. PACE_HEADER pAce = (PACE_HEADER)LocalAlloc(LPTR, cbSize);
  1050. if (pAce)
  1051. {
  1052. PSID pSidT;
  1053. pAce->AceType = uAceTypeNew;
  1054. pAce->AceFlags = uAceFlagsNew;
  1055. pAce->AceSize = (USHORT)cbSize;
  1056. ((PKNOWN_ACE)pAce)->Mask = dwMaskNew;
  1057. pSidT = &((PKNOWN_ACE)pAce)->SidStart;
  1058. if (dwObjectFlagsNew != 0)
  1059. {
  1060. GUID *pGuid;
  1061. ((PKNOWN_OBJECT_ACE)pAce)->Flags = dwObjectFlagsNew;
  1062. pGuid = RtlObjectAceObjectType(pAce);
  1063. if (pGuid)
  1064. {
  1065. if (pAccess->pguid)
  1066. *pGuid = *pAccess->pguid;
  1067. else
  1068. *pGuid = GUID_NULL;
  1069. }
  1070. pGuid = RtlObjectAceInheritedObjectType(pAce);
  1071. if (pGuid)
  1072. *pGuid = *pInheritGUID;
  1073. pSidT = RtlObjectAceSid(pAce);
  1074. }
  1075. CopyMemory(pSidT, pSid, cbSidSize);
  1076. DPA_AppendPtr(hEntries, pAce);
  1077. }
  1078. }
  1079. }
  1080. wCol++;
  1081. }
  1082. }
  1083. iCount = DPA_GetPtrCount(hEntries);
  1084. TraceLeaveValue(iCount);
  1085. }
  1086. LONG
  1087. CACEPage::OnApply(HWND hDlg, BOOL /*bClose*/)
  1088. {
  1089. const GUID *pInheritGUID;
  1090. UCHAR uAceFlagsNew = 0;
  1091. HDPA hEntries;
  1092. BOOL bAclBloated = FALSE;
  1093. //
  1094. //If this page is property page and user has not clicked on
  1095. //the object page, aclbloat must be checked from this page
  1096. //only.
  1097. //
  1098. if((m_siFlags == SI_ACCESS_PROPERTY) && !m_pOtherPage)
  1099. bAclBloated = IsAclBloated(hDlg);
  1100. if(m_siFlags != SI_ACCESS_PROPERTY)
  1101. bAclBloated = IsAclBloated(hDlg);
  1102. if(bAclBloated)
  1103. return PSNRET_INVALID_NOCHANGEPAGE;
  1104. if (!m_fPageDirty)
  1105. return PSNRET_NOERROR;
  1106. TraceEnter(TRACE_ACEEDIT, "CACEPage::Apply");
  1107. //
  1108. // Determine inheritance for containers
  1109. //
  1110. pInheritGUID = &GUID_NULL;
  1111. if ((m_siObjectInfo.dwFlags & SI_CONTAINER) != 0)
  1112. {
  1113. PSI_INHERIT_TYPE psiInheritType = NULL;
  1114. HWND hInheritType = GetDlgItem( hDlg, IDC_ACEE_INHERITTYPE);
  1115. int iSel = (int)SendMessage(hInheritType, CB_GETCURSEL, 0,0);
  1116. if (iSel != CB_ERR)
  1117. {
  1118. psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hInheritType,
  1119. CB_GETITEMDATA,
  1120. iSel,
  1121. 0);
  1122. }
  1123. if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL)
  1124. {
  1125. pInheritGUID = psiInheritType->pguid;
  1126. uAceFlagsNew = (UCHAR)(psiInheritType->dwFlags & VALID_INHERIT_FLAGS);
  1127. }
  1128. else if (m_pAce)
  1129. {
  1130. uAceFlagsNew = m_pAce->AceFlags;
  1131. }
  1132. if (m_fInheritImmediateEnabled)
  1133. {
  1134. if (IsDlgButtonChecked(hDlg, IDC_ACEE_INHERITIMMEDIATE) == BST_CHECKED)
  1135. uAceFlagsNew |= NO_PROPAGATE_INHERIT_ACE;
  1136. else
  1137. uAceFlagsNew &= ~NO_PROPAGATE_INHERIT_ACE;
  1138. }
  1139. }
  1140. if (m_phEntries != NULL)
  1141. {
  1142. if (*m_phEntries == NULL)
  1143. *m_phEntries = DPA_Create(4);
  1144. GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST),
  1145. m_pSid,
  1146. m_siPageType == SI_PAGE_ADVPERM,
  1147. TRUE,
  1148. uAceFlagsNew,
  1149. pInheritGUID,
  1150. *m_phEntries);
  1151. }
  1152. if (m_pdwResult)
  1153. *m_pdwResult |= (m_siFlags == SI_ACCESS_PROPERTY ? EAE_NEW_PROPERTY_ACE : EAE_NEW_OBJECT_ACE);
  1154. m_fPageDirty = FALSE;
  1155. TraceLeaveValue(PSNRET_NOERROR);
  1156. }
  1157. BOOL
  1158. CACEPage::IsAclBloated(HWND hDlg)
  1159. {
  1160. TraceEnter(TRACE_MISC, "CACEPage::ShowAclBloat");
  1161. HDPA hEntries = NULL;
  1162. HDPA hPropEntries = NULL;
  1163. BOOL bReturn = FALSE;
  1164. hEntries = GetAceList(hDlg);
  1165. if(m_pOtherPage)
  1166. {
  1167. hPropEntries = m_pOtherPage->GetAceList(m_pOtherPage->m_hwnd);
  1168. }
  1169. CACLBloat bloat(m_psi,
  1170. m_psi2,
  1171. m_siPageType,
  1172. &m_siObjectInfo,
  1173. hEntries,
  1174. hPropEntries);
  1175. if(bloat.IsAclBloated())
  1176. bReturn = bloat.DoModalDialog(hDlg);
  1177. if(hEntries)
  1178. DestroyDPA(hEntries);
  1179. if(hPropEntries)
  1180. DestroyDPA(hPropEntries);
  1181. return bReturn;
  1182. }
  1183. HDPA
  1184. CACEPage::GetAceList(HWND hDlg)
  1185. {
  1186. TraceEnter(TRACE_ACEEDIT, "CACEPage::GetAceList");
  1187. if (!m_fPageDirty)
  1188. return NULL;
  1189. //
  1190. // Determine inheritance for containers
  1191. //
  1192. const GUID *pInheritGUID = &GUID_NULL;
  1193. UCHAR uAceFlagsNew = 0;
  1194. HDPA hEntries = NULL;
  1195. if ((m_siObjectInfo.dwFlags & SI_CONTAINER) != 0)
  1196. {
  1197. PSI_INHERIT_TYPE psiInheritType = NULL;
  1198. HWND hInheritType = GetDlgItem( hDlg, IDC_ACEE_INHERITTYPE);
  1199. int iSel = (int)SendMessage(hInheritType, CB_GETCURSEL, 0,0);
  1200. if (iSel != CB_ERR)
  1201. {
  1202. psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hInheritType,
  1203. CB_GETITEMDATA,
  1204. iSel,
  1205. 0);
  1206. }
  1207. if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL)
  1208. {
  1209. pInheritGUID = psiInheritType->pguid;
  1210. uAceFlagsNew = (UCHAR)(psiInheritType->dwFlags & VALID_INHERIT_FLAGS);
  1211. }
  1212. else if (m_pAce)
  1213. {
  1214. uAceFlagsNew = m_pAce->AceFlags;
  1215. }
  1216. if (m_fInheritImmediateEnabled)
  1217. {
  1218. if (IsDlgButtonChecked(hDlg, IDC_ACEE_INHERITIMMEDIATE) == BST_CHECKED)
  1219. uAceFlagsNew |= NO_PROPAGATE_INHERIT_ACE;
  1220. else
  1221. uAceFlagsNew &= ~NO_PROPAGATE_INHERIT_ACE;
  1222. }
  1223. }
  1224. hEntries = DPA_Create(4);
  1225. if(hEntries)
  1226. {
  1227. GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST),
  1228. m_pSid,
  1229. m_siPageType == SI_PAGE_ADVPERM,
  1230. TRUE,
  1231. uAceFlagsNew,
  1232. pInheritGUID,
  1233. hEntries);
  1234. }
  1235. return hEntries;
  1236. }
  1237. BOOL
  1238. CACEPage::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1239. {
  1240. switch (uMsg)
  1241. {
  1242. case WM_INITDIALOG:
  1243. InitDlg(hDlg);
  1244. break;
  1245. case WM_DESTROY:
  1246. EmptyCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST));
  1247. break;
  1248. case PWM_SELECT_PAGE:
  1249. PropSheet_SetCurSel(GetParent(hDlg), lParam, wParam);
  1250. break;
  1251. case WM_COMMAND:
  1252. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1253. {
  1254. case IDC_ACEE_NAMEBUTTON:
  1255. if (OnChangeName(hDlg))
  1256. {
  1257. PropSheet_Changed(GetParent(hDlg), hDlg);
  1258. m_fPageDirty = TRUE;
  1259. }
  1260. break;
  1261. case IDC_ACEE_INHERITTYPE:
  1262. if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
  1263. {
  1264. HandleSelChange(hDlg, (HWND)lParam);
  1265. PropSheet_Changed(GetParent(hDlg), hDlg);
  1266. m_fPageDirty = TRUE;
  1267. }
  1268. break;
  1269. case IDC_ACEE_INHERITIMMEDIATE:
  1270. if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
  1271. {
  1272. PropSheet_Changed(GetParent(hDlg), hDlg);
  1273. m_fPageDirty = TRUE;
  1274. }
  1275. break;
  1276. case IDC_ACEE_CLEAR:
  1277. if (OnClearAll(hDlg))
  1278. {
  1279. PropSheet_Changed(GetParent(hDlg), hDlg);
  1280. m_fPageDirty = TRUE;
  1281. }
  1282. break;
  1283. default:
  1284. return FALSE;
  1285. }
  1286. break;
  1287. case WM_NOTIFY:
  1288. switch (((NMHDR *)lParam)->code)
  1289. {
  1290. case CLN_CLICK:
  1291. if (lParam)
  1292. {
  1293. HandleListClick((PNM_CHECKLIST)lParam, m_siPageType, FALSE);
  1294. PropSheet_Changed(GetParent(hDlg), hDlg);
  1295. m_fPageDirty = TRUE;
  1296. }
  1297. break;
  1298. case CLN_GETCOLUMNDESC:
  1299. {
  1300. PNM_CHECKLIST pnmc = (PNM_CHECKLIST)lParam;
  1301. GetDlgItemText(hDlg,
  1302. IDC_ACEE_ALLOW - 1 + pnmc->iSubItem,
  1303. pnmc->pszText,
  1304. pnmc->cchTextMax);
  1305. }
  1306. break;
  1307. case PSN_APPLY:
  1308. SetWindowLongPtr(hDlg,
  1309. DWLP_MSGRESULT,
  1310. OnApply(hDlg, (BOOL)(((LPPSHNOTIFY)lParam)->lParam)));
  1311. break;
  1312. }
  1313. break;
  1314. case PSM_QUERYSIBLINGS:
  1315. {
  1316. BOOL bSendQuery = !m_pOtherPage;
  1317. if(this != (CACEPage*)lParam)
  1318. m_pOtherPage = (CACEPage*)lParam;
  1319. if(bSendQuery)
  1320. PostMessage(GetParent(hDlg),PSM_QUERYSIBLINGS,0,(LPARAM)this);
  1321. }
  1322. break;
  1323. case WM_HELP:
  1324. if (IsWindowEnabled(hDlg))
  1325. {
  1326. const DWORD *pdwHelpIDs = aAcePermHelpIDs;
  1327. if (m_siPageType == SI_PAGE_AUDIT)
  1328. pdwHelpIDs = aAceAuditHelpIDs;
  1329. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  1330. c_szAcluiHelpFile,
  1331. HELP_WM_HELP,
  1332. (DWORD_PTR)pdwHelpIDs);
  1333. }
  1334. break;
  1335. case WM_CONTEXTMENU:
  1336. if (IsWindowEnabled(hDlg))
  1337. {
  1338. HWND hwnd = (HWND)wParam;
  1339. const DWORD *pdwHelpIDs = aAcePermHelpIDs;
  1340. if (m_siPageType == SI_PAGE_AUDIT)
  1341. pdwHelpIDs = aAceAuditHelpIDs;
  1342. //
  1343. // Some of the checkboxes may be scrolled out of view, but
  1344. // they are still detected by WinHelp, so we jump through
  1345. // a few extra hoops here.
  1346. //
  1347. if (hwnd == hDlg)
  1348. {
  1349. POINT pt;
  1350. pt.x = GET_X_LPARAM(lParam);
  1351. pt.y = GET_Y_LPARAM(lParam);
  1352. ScreenToClient(hDlg, &pt);
  1353. hwnd = ChildWindowFromPoint(hDlg, pt);
  1354. if (hDlg == hwnd)
  1355. break;
  1356. }
  1357. //
  1358. // WinHelp looks for child windows, but we don't have help id's
  1359. // for the permission checkboxes. If the request is for the
  1360. // checklist window, fake out WinHelp by referring to one of
  1361. // the static labels just above the list.
  1362. //
  1363. if (GetDlgCtrlID(hwnd) == IDC_ACEE_LIST)
  1364. hwnd = GetWindow((HWND)wParam, GW_HWNDPREV); // Static label "Deny"
  1365. WinHelp(hwnd,
  1366. c_szAcluiHelpFile,
  1367. HELP_CONTEXTMENU,
  1368. (DWORD_PTR)pdwHelpIDs);
  1369. }
  1370. break;
  1371. default:
  1372. return FALSE;
  1373. }
  1374. return TRUE;
  1375. }
  1376. HPROPSHEETPAGE
  1377. CreateACEPage(LPSECURITYINFO psi,
  1378. SI_PAGE_TYPE siType,
  1379. PACE pAce,
  1380. BOOL bReadOnly,
  1381. DWORD dwFlags,
  1382. DWORD *pdwResult,
  1383. HDPA *phEntries)
  1384. {
  1385. HPROPSHEETPAGE hPage = NULL;
  1386. LPCTSTR pszTitle = NULL;
  1387. LPACEPAGE pPage;
  1388. TraceEnter(TRACE_ACEEDIT, "CreateACEPage");
  1389. TraceAssert(psi != NULL);
  1390. TraceAssert(phEntries != NULL);
  1391. pPage = new CACEPage(psi,
  1392. siType,
  1393. pAce,
  1394. bReadOnly,
  1395. dwFlags,
  1396. pdwResult,
  1397. phEntries);
  1398. if (pPage)
  1399. {
  1400. int iDlgTemplate = IDD_ACEENTRY_PERM_PAGE;
  1401. if (siType == SI_PAGE_AUDIT)
  1402. iDlgTemplate = IDD_ACEENTRY_AUDIT_PAGE;
  1403. if (dwFlags == SI_ACCESS_PROPERTY)
  1404. pszTitle = MAKEINTRESOURCE(IDS_ACEE_PROPERTY_TITLE);
  1405. hPage = pPage->CreatePropSheetPage(MAKEINTRESOURCE(iDlgTemplate), pszTitle);
  1406. }
  1407. TraceLeaveValue(hPage);
  1408. }
  1409. BOOL
  1410. EditACEEntry(HWND hwndOwner,
  1411. LPSECURITYINFO psi,
  1412. PACE pAce,
  1413. SI_PAGE_TYPE siType,
  1414. LPCTSTR pszObjectName,
  1415. BOOL bReadOnly,
  1416. DWORD *pdwResult,
  1417. HDPA *phEntries,
  1418. HDPA *phPropertyEntries,
  1419. UINT nStartPage)
  1420. {
  1421. HPROPSHEETPAGE hPage[2];
  1422. UINT cPages = 0;
  1423. BOOL bResult = FALSE;
  1424. TraceEnter(TRACE_ACEEDIT, "EditACEEntry");
  1425. TraceAssert(psi != NULL);
  1426. if (phEntries)
  1427. {
  1428. hPage[cPages] = CreateACEPage(psi,
  1429. siType,
  1430. pAce,
  1431. bReadOnly,
  1432. SI_ACCESS_SPECIFIC,
  1433. pdwResult,
  1434. phEntries);
  1435. if (hPage[cPages])
  1436. cPages++;
  1437. }
  1438. if (phPropertyEntries)
  1439. {
  1440. hPage[cPages] = CreateACEPage(psi,
  1441. siType,
  1442. pAce,
  1443. bReadOnly,
  1444. SI_ACCESS_PROPERTY,
  1445. pdwResult,
  1446. phPropertyEntries);
  1447. if (hPage[cPages])
  1448. cPages++;
  1449. }
  1450. if (cPages)
  1451. {
  1452. // Build dialog title string
  1453. LPTSTR pszCaption = NULL;
  1454. FormatStringID(&pszCaption,
  1455. ::hModule,
  1456. siType == SI_PAGE_AUDIT ? IDS_ACEE_AUDIT_TITLE : IDS_ACEE_PERM_TITLE,
  1457. pszObjectName);
  1458. PROPSHEETHEADER psh;
  1459. psh.dwSize = SIZEOF(psh);
  1460. psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW;
  1461. psh.hwndParent = hwndOwner;
  1462. psh.hInstance = ::hModule;
  1463. psh.pszCaption = pszCaption;
  1464. psh.nPages = cPages;
  1465. psh.nStartPage = 0;
  1466. psh.phpage = &hPage[0];
  1467. if (nStartPage < cPages)
  1468. psh.nStartPage = nStartPage;
  1469. bResult = (PropertySheet(&psh) == IDOK);
  1470. LocalFreeString(&pszCaption);
  1471. }
  1472. TraceLeaveValue(bResult);
  1473. }