Leaked source code of windows server 2003
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.

1748 lines
54 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. InitCheckList(hDlg, m_pAce);
  484. HWND hInheritType = GetDlgItem(hDlg, IDC_ACEE_INHERITTYPE);
  485. HWND hInheritImmed = GetDlgItem(hDlg, IDC_ACEE_INHERITIMMEDIATE);
  486. if (m_siObjectInfo.dwFlags & SI_NO_TREE_APPLY)
  487. {
  488. ShowWindow(hInheritImmed, SW_HIDE);
  489. EnableWindow(hInheritImmed, FALSE);
  490. }
  491. //
  492. // Get inherit types from callback
  493. //
  494. ULONG cItems = 0;
  495. PSI_INHERIT_TYPE psiInheritType = NULL;
  496. hr = m_psi->GetInheritTypes(&psiInheritType, &cItems);
  497. if (SUCCEEDED(hr))
  498. {
  499. // Check these inherit bits for a match
  500. DWORD dwInheritMask = INHERIT_ONLY_ACE | ACE_INHERIT_ALL;
  501. // Don't check INHERIT_ONLY_ACE if the ACE inherit type
  502. // matches the current object
  503. if ((m_siObjectInfo.dwFlags & SI_OBJECT_GUID) &&
  504. IsSameGUID(&m_siObjectInfo.guidObjectType, &m_guidInheritType))
  505. {
  506. dwInheritMask &= ~INHERIT_ONLY_ACE;
  507. }
  508. //
  509. // Add inherit types to combobox
  510. //
  511. for ( ; cItems > 0; cItems--, psiInheritType++)
  512. {
  513. UINT iIndex = _AddInheritType(hInheritType,
  514. psiInheritType,
  515. m_siObjectInfo.hInstance);
  516. // See if this entry matches the incoming ACE
  517. if ((psiInheritType->dwFlags & dwInheritMask) == (ULONG)(AceFlags & dwInheritMask)
  518. && IsSameGUID(&m_guidInheritType, psiInheritType->pguid))
  519. {
  520. // Got a match, select this entry
  521. SendMessage(hInheritType, CB_SETCURSEL, iIndex, 0);
  522. }
  523. }
  524. }
  525. //
  526. // If GetInheritTypes failed, or we failed to find a match,
  527. // pick a default string and build an appropriate inherit type.
  528. //
  529. if (FAILED(hr) || CB_ERR == SendMessage(hInheritType, CB_GETCURSEL, 0, 0))
  530. {
  531. // Pick a default string
  532. UINT ids = IDS_SPECIAL;
  533. if (IsNullGUID(&m_guidInheritType))
  534. {
  535. if (AceFlags & INHERIT_ONLY_ACE)
  536. ids = s_aInheritOnlyTypes[AceFlags & ACE_INHERIT_ALL];
  537. else
  538. ids = s_aInheritTypes[AceFlags & ACE_INHERIT_ALL];
  539. }
  540. // Fill in m_siInheritUnknown with the pertinent info
  541. m_siInheritUnknown.pguid = &m_guidInheritType;
  542. m_siInheritUnknown.dwFlags = AceFlags & (INHERIT_ONLY_ACE | ACE_INHERIT_ALL);
  543. m_siInheritUnknown.pszName = MAKEINTRESOURCE(ids);
  544. // Insert and select it
  545. UINT iIndex = _AddInheritType(hInheritType,
  546. &m_siInheritUnknown,
  547. ::hModule);
  548. SendMessage(hInheritType, CB_SETCURSEL, iIndex, 0);
  549. if (FAILED(hr))
  550. {
  551. // GetInheritTypes failed, which means the only entry is the
  552. // default one we just added. Disable the combo.
  553. EnableWindow(hInheritType, FALSE);
  554. }
  555. }
  556. //
  557. // Select the options which match the incoming ace
  558. //
  559. if (!(AceFlags & (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE)))
  560. {
  561. SendMessage(hInheritImmed, BM_SETCHECK, BST_UNCHECKED, 0);
  562. EnableWindow(hInheritImmed, FALSE);
  563. m_fInheritImmediateEnabled = FALSE;
  564. m_fPreviousImmediateSetting = BST_UNCHECKED;
  565. }
  566. else
  567. {
  568. SendMessage(hInheritImmed,
  569. BM_SETCHECK,
  570. (AceFlags & NO_PROPAGATE_INHERIT_ACE) ? BST_CHECKED : BST_UNCHECKED,
  571. 0);
  572. m_fInheritImmediateEnabled = TRUE;
  573. }
  574. if (!(m_siObjectInfo.dwFlags & SI_CONTAINER) || m_fReadOnly || (AceFlags & INHERITED_ACE))
  575. {
  576. // Disable all inheritance
  577. EnableWindow(hInheritType, FALSE);
  578. EnableWindow(hInheritImmed, FALSE);
  579. }
  580. if (m_fReadOnly || (AceFlags & INHERITED_ACE))
  581. {
  582. // Disable the "change name" and "clear all" buttons
  583. EnableWindow(GetDlgItem(hDlg, IDC_ACEE_NAMEBUTTON), FALSE);
  584. EnableWindow(GetDlgItem(hDlg, IDC_ACEE_CLEAR), FALSE);
  585. }
  586. PropSheet_QuerySiblings(GetParent(hDlg),0,(LPARAM)this);
  587. LocalFreeString(&pszNameT);
  588. SetCursor(hcur);
  589. TraceLeaveVoid();
  590. }
  591. BOOL
  592. CACEPage::OnChangeName(HWND hDlg)
  593. {
  594. PUSER_LIST pUserList = NULL;
  595. BOOL bResult = FALSE;
  596. TraceEnter(TRACE_ACEEDIT, "CACEPage::OnChangeName");
  597. if (S_OK == GetUserGroup(hDlg, FALSE, &pUserList))
  598. {
  599. TraceAssert(NULL != pUserList);
  600. TraceAssert(1 == pUserList->cUsers);
  601. // Free up previous sid
  602. if (m_pSid)
  603. LocalFree(m_pSid);
  604. // Copy the new sid
  605. m_pSid = LocalAllocSid(pUserList->rgUsers[0].pSid);
  606. if (m_pSid)
  607. {
  608. SetDlgItemText(hDlg, IDC_ACEE_NAME, pUserList->rgUsers[0].pszName);
  609. bResult = TRUE;
  610. }
  611. LocalFree(pUserList);
  612. }
  613. TraceLeaveValue(bResult);
  614. }
  615. BOOL
  616. CACEPage::OnClearAll(HWND hDlg)
  617. {
  618. HWND hwndList;
  619. ULONG cPermissions;
  620. TraceEnter(TRACE_ACEEDIT, "CACEPage::OnClearAll");
  621. TraceAssert(!m_fReadOnly);
  622. hwndList = GetDlgItem(hDlg, IDC_ACEE_LIST);
  623. cPermissions = (ULONG)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  624. while (cPermissions != 0)
  625. {
  626. WORD wCol = COLUMN_ALLOW;
  627. cPermissions--;
  628. while (wCol == COLUMN_ALLOW || wCol == COLUMN_DENY)
  629. {
  630. WPARAM wItem = MAKELONG((WORD)cPermissions, wCol);
  631. if (!(CLST_DISABLED & SendMessage(hwndList, CLM_GETSTATE, wItem, 0)))
  632. SendMessage(hwndList, CLM_SETSTATE, wItem, CLST_UNCHECKED);
  633. wCol++;
  634. }
  635. }
  636. TraceLeaveValue(TRUE);
  637. }
  638. void
  639. CACEPage::HandleSelChange(HWND hDlg, HWND hWnd) // inherit type change
  640. {
  641. PSI_INHERIT_TYPE psiInheritType;
  642. BOOL fEnableInheritImmediate = FALSE;
  643. const GUID *pguidInheritType = &GUID_NULL;
  644. TraceEnter(TRACE_ACEEDIT, "CACEPage::HandleSelChange");
  645. psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hWnd,
  646. CB_GETITEMDATA,
  647. SendMessage(hWnd, CB_GETCURSEL, 0, 0),
  648. 0);
  649. if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL)
  650. {
  651. if (psiInheritType->dwFlags & (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE))
  652. fEnableInheritImmediate = TRUE;
  653. if( psiInheritType->pguid )
  654. pguidInheritType = psiInheritType->pguid;
  655. }
  656. if (fEnableInheritImmediate != m_fInheritImmediateEnabled)
  657. {
  658. HWND hInheritImmediate = GetDlgItem(hDlg, IDC_ACEE_INHERITIMMEDIATE);
  659. if (fEnableInheritImmediate)
  660. {
  661. SendMessage(hInheritImmediate, BM_SETCHECK, m_fPreviousImmediateSetting, 0);
  662. }
  663. else
  664. {
  665. m_fPreviousImmediateSetting = (BOOL)SendMessage(hInheritImmediate,
  666. BM_GETCHECK,
  667. 0,
  668. 0);
  669. SendMessage(hInheritImmediate, BM_SETCHECK, BST_UNCHECKED, 0);
  670. }
  671. EnableWindow(hInheritImmediate, fEnableInheritImmediate);
  672. m_fInheritImmediateEnabled = fEnableInheritImmediate;
  673. }
  674. // If the inherit type GUID has changed, reinitialize the checklist.
  675. if (!IsSameGUID(pguidInheritType, &m_guidInheritType))
  676. {
  677. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  678. HDPA hNewEntries = DPA_Create(4);
  679. if (hNewEntries)
  680. {
  681. GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST),
  682. m_pSid,
  683. m_siPageType == SI_PAGE_ADVPERM,
  684. TRUE,
  685. 0, // don't care about flags
  686. NULL, // or inherit type here
  687. hNewEntries);
  688. // Save new inherit type and reset the checklist
  689. m_guidInheritType = *pguidInheritType;
  690. ReInitCheckList(hDlg, hNewEntries);
  691. DestroyDPA(hNewEntries);
  692. }
  693. SetCursor(hcur);
  694. }
  695. TraceLeaveVoid();
  696. }
  697. void
  698. HandleListClick(PNM_CHECKLIST pnmc,
  699. SI_PAGE_TYPE siType,
  700. BOOL bInheritFlags,
  701. HDSA *phAllowUncheckedAccess,
  702. HDSA *phDenyUncheckedAccess,
  703. BOOL bCustomPresent)
  704. {
  705. HWND hChkList;
  706. UINT iRow;
  707. WORD wCol;
  708. PSI_ACCESS pAccess;
  709. DWORD dwState;
  710. BOOL bNullGuid;
  711. UINT iRowCompare;
  712. PSI_ACCESS pAccessCompare;
  713. TraceEnter(TRACE_MISC, "HandleListClick");
  714. TraceAssert(pnmc != NULL);
  715. hChkList = pnmc->hdr.hwndFrom;
  716. iRow = pnmc->iItem;
  717. wCol = (WORD)pnmc->iSubItem; // 1 = Allow, 2 = Deny
  718. pAccess = (PSI_ACCESS)pnmc->dwItemData;
  719. dwState = pnmc->dwState;
  720. if (pAccess == NULL)
  721. TraceLeaveVoid();
  722. if( phAllowUncheckedAccess )
  723. {
  724. *phAllowUncheckedAccess = DSA_Create(SIZEOF(PSI_ACCESS), 4);
  725. if (*phAllowUncheckedAccess == NULL)
  726. {
  727. TraceMsg("DSA_Create failed");
  728. TraceLeaveVoid();
  729. }
  730. }
  731. if( phDenyUncheckedAccess )
  732. {
  733. *phDenyUncheckedAccess = DSA_Create(SIZEOF(PSI_ACCESS), 4);
  734. if (*phDenyUncheckedAccess == NULL)
  735. {
  736. TraceMsg("DSA_Create failed");
  737. TraceLeaveVoid();
  738. }
  739. }
  740. bNullGuid = IsNullGUID(pAccess->pguid);
  741. iRowCompare = (UINT)SendMessage(hChkList, CLM_GETITEMCOUNT, 0, 0);
  742. //Custom checkbox is handled Separately
  743. if( bCustomPresent )
  744. --iRowCompare;
  745. while (iRowCompare != 0)
  746. {
  747. WPARAM wItem;
  748. DWORD dwStateCompareOriginal;
  749. DWORD dwStateCompare;
  750. WORD wColCompare;
  751. BOOL bSameGuid;
  752. BOOL bNullGuidCompare;
  753. --iRowCompare;
  754. pAccessCompare = (PSI_ACCESS)SendMessage(hChkList, CLM_GETITEMDATA, iRowCompare, 0);
  755. if (!pAccessCompare)
  756. continue;
  757. bSameGuid = IsSameGUID(pAccessCompare->pguid, pAccess->pguid);
  758. bNullGuidCompare = IsNullGUID(pAccessCompare->pguid);
  759. // If the GUIDs are incompatible, then we can't do anything
  760. if (!(bSameGuid || bNullGuid || bNullGuidCompare))
  761. continue;
  762. //
  763. // Yukky, complicated mechanism to determine whether to
  764. // turn on or off the allow or deny check marks.
  765. //
  766. // REVIEW: This algorithm of changing check marks based on other
  767. // checkmarks handles a lot of cases, but it doesn't handle a
  768. // two good ones.
  769. //
  770. // (1) If you have a right which implies other rights and you turn,
  771. // it off, then maybe we should turn off all of the implied ones
  772. // too. For example, you turn off change (which is the combination
  773. // of read and write) maybe we should turn off both read and write.
  774. //
  775. // (2) If you turn on all of the component rights of one which
  776. // implies them all, then we should turn on that one (because
  777. // it implies them all).
  778. //
  779. #ifdef NO_RADIOBUTTON_BEHAVIOR
  780. wColCompare = wCol;
  781. #else
  782. for (wColCompare = COLUMN_ALLOW; wColCompare <= COLUMN_DENY; wColCompare++)
  783. #endif
  784. {
  785. wItem = MAKELONG((WORD)iRowCompare, wColCompare);
  786. dwStateCompareOriginal = (DWORD)SendMessage(hChkList, CLM_GETSTATE, wItem, 0);
  787. //
  788. // If the other box is disabled, then it represents an
  789. // inherited right so don't do anything with it.
  790. //
  791. // nb: Depending on NO_RADIOBUTTON_BEHAVIOR, this may continue to the
  792. // for(wColCompare) loop or the while(iRowCompare) loop as appropriate
  793. //
  794. if (dwStateCompareOriginal & CLST_DISABLED)
  795. continue;
  796. dwStateCompare = dwStateCompareOriginal;
  797. if (dwState & CLST_CHECKED)
  798. {
  799. if (wCol == wColCompare)
  800. {
  801. //
  802. // If this right implies some other right,
  803. // then turn it on too.
  804. //
  805. if ((bSameGuid || bNullGuid) && AllFlagsOn(pAccess->mask, pAccessCompare->mask))
  806. {
  807. if (!bInheritFlags ||
  808. AllFlagsOn(pAccess->dwFlags & ACE_INHERIT_ALL, pAccessCompare->dwFlags & ACE_INHERIT_ALL))
  809. {
  810. dwStateCompare |= CLST_CHECKED;
  811. }
  812. }
  813. }
  814. else
  815. {
  816. #ifndef NO_RADIOBUTTON_BEHAVIOR
  817. //
  818. // If this right implies or is implied by some other
  819. // right in the other column, then turn it off.
  820. //
  821. if ( (siType == SI_PAGE_PERM || siType == SI_PAGE_ADVPERM) &&
  822. (((bSameGuid || bNullGuid) && AllFlagsOn(pAccess->mask, pAccessCompare->mask)) ||
  823. ((bSameGuid || bNullGuidCompare) && AllFlagsOn(pAccessCompare->mask, pAccess->mask))) )
  824. {
  825. if (!bInheritFlags ||
  826. (AllFlagsOn(pAccessCompare->dwFlags & ACE_INHERIT_ALL, pAccess->dwFlags & ACE_INHERIT_ALL) ||
  827. AllFlagsOn(pAccess->dwFlags & ACE_INHERIT_ALL, pAccessCompare->dwFlags & ACE_INHERIT_ALL)) )
  828. {
  829. dwStateCompare &= ~(CLST_CHECKED);
  830. }
  831. }
  832. #endif
  833. }
  834. }
  835. else
  836. {
  837. if (wCol == wColCompare)
  838. {
  839. //
  840. // If this right is implied by some other right, then
  841. // turn it off too.
  842. //
  843. if ((bSameGuid || bNullGuidCompare) && AllFlagsOn(pAccessCompare->mask, pAccess->mask))
  844. {
  845. if (!bInheritFlags ||
  846. AllFlagsOn(pAccessCompare->dwFlags & ACE_INHERIT_ALL, pAccess->dwFlags & ACE_INHERIT_ALL))
  847. {
  848. dwStateCompare &= ~(CLST_CHECKED);
  849. }
  850. }
  851. }
  852. }
  853. if (dwStateCompareOriginal != dwStateCompare)
  854. {
  855. SendMessage(hChkList, CLM_SETSTATE, wItem, (LPARAM)dwStateCompare);
  856. //If a checkbox was intially checked and and now unchecked, add to
  857. //h[Allow|Deny]UncheckedAccess.
  858. if( dwStateCompareOriginal & CLST_CHECKED && !(dwStateCompare & CLST_CHECKED) )
  859. {
  860. if( phDenyUncheckedAccess && ( wColCompare == COLUMN_DENY ) )
  861. DSA_AppendItem(*phDenyUncheckedAccess, &pAccessCompare);
  862. if( phAllowUncheckedAccess && ( wColCompare == COLUMN_ALLOW ) )
  863. DSA_AppendItem(*phAllowUncheckedAccess, &pAccessCompare);
  864. }
  865. }
  866. }
  867. }
  868. TraceLeaveVoid();
  869. }
  870. UINT
  871. GetAcesFromCheckList(HWND hChkList,
  872. PSID pSid, // All aces get this SID
  873. BOOL fPerm, // Create ACCESS or AUDIT aces?
  874. BOOL fAceFlagsProvided, // Use uAceFlagsAll instead of pAccess->dwFlags
  875. UCHAR uAceFlagsAll, // All aces get these flags
  876. const GUID *pInheritGUID, // All aces get this inherit GUID
  877. HDPA hEntries) // Store new aces here
  878. {
  879. UINT cCheckRows;
  880. UINT iCheckRow;
  881. UINT cbSidSize;
  882. UINT iCount;
  883. BOOL bInheritTypePresent = FALSE;
  884. TraceEnter(TRACE_MISC, "GetAcesFromCheckList");
  885. TraceAssert(hChkList != NULL);
  886. TraceAssert(pSid != NULL);
  887. TraceAssert(hEntries != NULL);
  888. cbSidSize = GetLengthSid(pSid);
  889. if (pInheritGUID == NULL)
  890. pInheritGUID = &GUID_NULL;
  891. else if (!IsNullGUID(pInheritGUID))
  892. bInheritTypePresent = TRUE;
  893. //
  894. // First clear out the old HDPA
  895. //
  896. iCount = DPA_GetPtrCount(hEntries);
  897. while (iCount != 0)
  898. {
  899. --iCount;
  900. LocalFree(DPA_FastGetPtr(hEntries, iCount));
  901. DPA_DeletePtr(hEntries, iCount);
  902. }
  903. cCheckRows = (UINT)SendMessage(hChkList, CLM_GETITEMCOUNT, 0, 0);
  904. for (iCheckRow = 0; iCheckRow < cCheckRows; iCheckRow++)
  905. {
  906. PSI_ACCESS pAccess;
  907. DWORD dwObjectFlagsNew;
  908. WORD wCol;
  909. UCHAR uAceFlagsNew;
  910. pAccess = (PSI_ACCESS)SendMessage(hChkList, CLM_GETITEMDATA, iCheckRow, 0);
  911. uAceFlagsNew = (UCHAR)(fAceFlagsProvided ? uAceFlagsAll : pAccess->dwFlags);
  912. dwObjectFlagsNew = 0;
  913. if (!IsNullGUID(pAccess->pguid))
  914. dwObjectFlagsNew |= ACE_OBJECT_TYPE_PRESENT;
  915. if (bInheritTypePresent)
  916. dwObjectFlagsNew |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
  917. wCol = COLUMN_ALLOW;
  918. while (wCol == COLUMN_ALLOW || wCol == COLUMN_DENY)
  919. {
  920. WPARAM wItem;
  921. DWORD dwState;
  922. wItem = MAKELONG((WORD)iCheckRow, wCol);
  923. dwState = (DWORD)SendMessage(hChkList, CLM_GETSTATE, wItem, 0);
  924. if ((dwState & CLST_CHECKED) && !(dwState & CLST_DISABLED))
  925. {
  926. //
  927. // Ok, time to make an ACE for this check mark, see if we
  928. // can merge it into an already existing ACE, or whether we
  929. // we need to create a new entry
  930. //
  931. UCHAR uAceTypeNew;
  932. DWORD dwMaskNew = pAccess->mask;
  933. UINT cbSize = SIZEOF(KNOWN_ACE);
  934. if (fPerm)
  935. {
  936. if (wCol == COLUMN_ALLOW)
  937. uAceTypeNew = ACCESS_ALLOWED_ACE_TYPE;
  938. else
  939. uAceTypeNew = ACCESS_DENIED_ACE_TYPE;
  940. }
  941. else
  942. {
  943. uAceTypeNew = SYSTEM_AUDIT_ACE_TYPE;
  944. uAceFlagsNew &= ~(SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG);
  945. if (wCol == COLUMN_ALLOW)
  946. uAceFlagsNew |= SUCCESSFUL_ACCESS_ACE_FLAG;
  947. else
  948. uAceFlagsNew |= FAILED_ACCESS_ACE_FLAG;
  949. }
  950. if (dwObjectFlagsNew != 0)
  951. {
  952. uAceTypeNew += (ACCESS_ALLOWED_OBJECT_ACE_TYPE - ACCESS_ALLOWED_ACE_TYPE);
  953. cbSize = SIZEOF(KNOWN_OBJECT_ACE);
  954. if (dwObjectFlagsNew & ACE_OBJECT_TYPE_PRESENT)
  955. cbSize += SIZEOF(GUID);
  956. if (dwObjectFlagsNew & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  957. cbSize += SIZEOF(GUID);
  958. }
  959. cbSize += cbSidSize - SIZEOF(ULONG);
  960. //
  961. // See if it exists
  962. //
  963. iCount = DPA_GetPtrCount(hEntries);
  964. while(iCount != 0)
  965. {
  966. PACE_HEADER pAce;
  967. BOOL bObjectTypePresent = FALSE;
  968. const GUID *pObjectType = NULL;
  969. --iCount;
  970. pAce = (PACE_HEADER)DPA_FastGetPtr(hEntries, iCount);
  971. if (IsObjectAceType(pAce))
  972. pObjectType = RtlObjectAceObjectType(pAce);
  973. if (!pObjectType)
  974. pObjectType = &GUID_NULL;
  975. else
  976. bObjectTypePresent = TRUE;
  977. //
  978. // Test the new ACE against each existing ACE to see if
  979. // we can combine them.
  980. //
  981. if (IsEqualACEType(pAce->AceType, uAceTypeNew))
  982. {
  983. DWORD dwMergeFlags = 0;
  984. DWORD dwMergeStatus;
  985. DWORD dwMergeResult;
  986. if (dwObjectFlagsNew & ACE_OBJECT_TYPE_PRESENT)
  987. dwMergeFlags |= MF_OBJECT_TYPE_1_PRESENT;
  988. if (bObjectTypePresent)
  989. dwMergeFlags |= MF_OBJECT_TYPE_2_PRESENT;
  990. if (!(dwMergeFlags & (MF_OBJECT_TYPE_1_PRESENT | MF_OBJECT_TYPE_2_PRESENT)))
  991. {
  992. // Neither are present, so they are the same
  993. dwMergeFlags |= MF_OBJECT_TYPE_EQUAL;
  994. }
  995. else if (IsSameGUID(pAccess->pguid, pObjectType))
  996. dwMergeFlags |= MF_OBJECT_TYPE_EQUAL;
  997. if (!fPerm)
  998. dwMergeFlags |= MF_AUDIT_ACE_TYPE;
  999. dwMergeStatus = MergeAceHelper(uAceFlagsNew,
  1000. dwMaskNew,
  1001. pAce->AceFlags,
  1002. ((PKNOWN_ACE)pAce)->Mask,
  1003. dwMergeFlags,
  1004. &dwMergeResult);
  1005. if (dwMergeStatus == MERGE_MODIFIED_FLAGS)
  1006. {
  1007. uAceFlagsNew = (UCHAR)dwMergeResult;
  1008. dwMergeStatus = MERGE_OK_1;
  1009. }
  1010. else if (dwMergeStatus == MERGE_MODIFIED_MASK)
  1011. {
  1012. dwMaskNew = dwMergeResult;
  1013. dwMergeStatus = MERGE_OK_1;
  1014. }
  1015. if (dwMergeStatus == MERGE_OK_1)
  1016. {
  1017. //
  1018. // The new ACE implies the existing ACE, so
  1019. // the existing one can be removed.
  1020. //
  1021. LocalFree(pAce);
  1022. DPA_DeletePtr(hEntries, iCount);
  1023. //
  1024. // Keep looking. Maybe we can remove some more entries
  1025. // before adding the new one.
  1026. //
  1027. }
  1028. else if (dwMergeStatus == MERGE_OK_2)
  1029. {
  1030. iCount = 1; // non-zero for match found
  1031. break;
  1032. }
  1033. }
  1034. }
  1035. //
  1036. // Otherwise, add it
  1037. //
  1038. if (iCount == 0)
  1039. {
  1040. PACE_HEADER pAce = (PACE_HEADER)LocalAlloc(LPTR, cbSize);
  1041. if (pAce)
  1042. {
  1043. PSID pSidT;
  1044. pAce->AceType = uAceTypeNew;
  1045. pAce->AceFlags = uAceFlagsNew;
  1046. pAce->AceSize = (USHORT)cbSize;
  1047. ((PKNOWN_ACE)pAce)->Mask = dwMaskNew;
  1048. pSidT = &((PKNOWN_ACE)pAce)->SidStart;
  1049. if (dwObjectFlagsNew != 0)
  1050. {
  1051. GUID *pGuid;
  1052. ((PKNOWN_OBJECT_ACE)pAce)->Flags = dwObjectFlagsNew;
  1053. pGuid = RtlObjectAceObjectType(pAce);
  1054. if (pGuid)
  1055. {
  1056. if (pAccess->pguid)
  1057. *pGuid = *pAccess->pguid;
  1058. else
  1059. *pGuid = GUID_NULL;
  1060. }
  1061. pGuid = RtlObjectAceInheritedObjectType(pAce);
  1062. if (pGuid)
  1063. *pGuid = *pInheritGUID;
  1064. pSidT = RtlObjectAceSid(pAce);
  1065. }
  1066. CopyMemory(pSidT, pSid, cbSidSize);
  1067. DPA_AppendPtr(hEntries, pAce);
  1068. }
  1069. }
  1070. }
  1071. wCol++;
  1072. }
  1073. }
  1074. iCount = DPA_GetPtrCount(hEntries);
  1075. TraceLeaveValue(iCount);
  1076. }
  1077. LONG
  1078. CACEPage::OnApply(HWND hDlg, BOOL /*bClose*/)
  1079. {
  1080. const GUID *pInheritGUID;
  1081. UCHAR uAceFlagsNew = 0;
  1082. HDPA hEntries;
  1083. BOOL bAclBloated = FALSE;
  1084. //
  1085. //If this page is property page and user has not clicked on
  1086. //the object page, aclbloat must be checked from this page
  1087. //only.
  1088. //
  1089. if((m_siFlags == SI_ACCESS_PROPERTY) && !m_pOtherPage)
  1090. bAclBloated = IsAclBloated(hDlg);
  1091. if(m_siFlags != SI_ACCESS_PROPERTY)
  1092. bAclBloated = IsAclBloated(hDlg);
  1093. if(bAclBloated)
  1094. return PSNRET_INVALID_NOCHANGEPAGE;
  1095. if (!m_fPageDirty)
  1096. return PSNRET_NOERROR;
  1097. TraceEnter(TRACE_ACEEDIT, "CACEPage::Apply");
  1098. //
  1099. // Determine inheritance for containers
  1100. //
  1101. pInheritGUID = &GUID_NULL;
  1102. if ((m_siObjectInfo.dwFlags & SI_CONTAINER) != 0)
  1103. {
  1104. PSI_INHERIT_TYPE psiInheritType = NULL;
  1105. HWND hInheritType = GetDlgItem( hDlg, IDC_ACEE_INHERITTYPE);
  1106. int iSel = (int)SendMessage(hInheritType, CB_GETCURSEL, 0,0);
  1107. if (iSel != CB_ERR)
  1108. {
  1109. psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hInheritType,
  1110. CB_GETITEMDATA,
  1111. iSel,
  1112. 0);
  1113. }
  1114. if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL)
  1115. {
  1116. pInheritGUID = psiInheritType->pguid;
  1117. uAceFlagsNew = (UCHAR)(psiInheritType->dwFlags & VALID_INHERIT_FLAGS);
  1118. }
  1119. else if (m_pAce)
  1120. {
  1121. uAceFlagsNew = m_pAce->AceFlags;
  1122. }
  1123. if (m_fInheritImmediateEnabled)
  1124. {
  1125. if (IsDlgButtonChecked(hDlg, IDC_ACEE_INHERITIMMEDIATE) == BST_CHECKED)
  1126. uAceFlagsNew |= NO_PROPAGATE_INHERIT_ACE;
  1127. else
  1128. uAceFlagsNew &= ~NO_PROPAGATE_INHERIT_ACE;
  1129. }
  1130. }
  1131. if (m_phEntries != NULL)
  1132. {
  1133. if (*m_phEntries == NULL)
  1134. *m_phEntries = DPA_Create(4);
  1135. GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST),
  1136. m_pSid,
  1137. m_siPageType == SI_PAGE_ADVPERM,
  1138. TRUE,
  1139. uAceFlagsNew,
  1140. pInheritGUID,
  1141. *m_phEntries);
  1142. }
  1143. if (m_pdwResult)
  1144. *m_pdwResult |= (m_siFlags == SI_ACCESS_PROPERTY ? EAE_NEW_PROPERTY_ACE : EAE_NEW_OBJECT_ACE);
  1145. m_fPageDirty = FALSE;
  1146. TraceLeaveValue(PSNRET_NOERROR);
  1147. }
  1148. BOOL
  1149. CACEPage::IsAclBloated(HWND hDlg)
  1150. {
  1151. TraceEnter(TRACE_MISC, "CACEPage::ShowAclBloat");
  1152. HDPA hEntries = NULL;
  1153. HDPA hPropEntries = NULL;
  1154. BOOL bReturn = FALSE;
  1155. hEntries = GetAceList(hDlg);
  1156. if(m_pOtherPage)
  1157. {
  1158. hPropEntries = m_pOtherPage->GetAceList(m_pOtherPage->m_hwnd);
  1159. }
  1160. CACLBloat bloat(m_psi,
  1161. m_psi2,
  1162. m_siPageType,
  1163. &m_siObjectInfo,
  1164. hEntries,
  1165. hPropEntries);
  1166. if(bloat.IsAclBloated())
  1167. bReturn = bloat.DoModalDialog(hDlg);
  1168. if(hEntries)
  1169. DestroyDPA(hEntries);
  1170. if(hPropEntries)
  1171. DestroyDPA(hPropEntries);
  1172. return bReturn;
  1173. }
  1174. HDPA
  1175. CACEPage::GetAceList(HWND hDlg)
  1176. {
  1177. TraceEnter(TRACE_ACEEDIT, "CACEPage::GetAceList");
  1178. if (!m_fPageDirty)
  1179. return NULL;
  1180. //
  1181. // Determine inheritance for containers
  1182. //
  1183. const GUID *pInheritGUID = &GUID_NULL;
  1184. UCHAR uAceFlagsNew = 0;
  1185. HDPA hEntries = NULL;
  1186. if ((m_siObjectInfo.dwFlags & SI_CONTAINER) != 0)
  1187. {
  1188. PSI_INHERIT_TYPE psiInheritType = NULL;
  1189. HWND hInheritType = GetDlgItem( hDlg, IDC_ACEE_INHERITTYPE);
  1190. int iSel = (int)SendMessage(hInheritType, CB_GETCURSEL, 0,0);
  1191. if (iSel != CB_ERR)
  1192. {
  1193. psiInheritType = (PSI_INHERIT_TYPE)SendMessage(hInheritType,
  1194. CB_GETITEMDATA,
  1195. iSel,
  1196. 0);
  1197. }
  1198. if (psiInheritType != (PSI_INHERIT_TYPE)CB_ERR && psiInheritType != NULL)
  1199. {
  1200. pInheritGUID = psiInheritType->pguid;
  1201. uAceFlagsNew = (UCHAR)(psiInheritType->dwFlags & VALID_INHERIT_FLAGS);
  1202. }
  1203. else if (m_pAce)
  1204. {
  1205. uAceFlagsNew = m_pAce->AceFlags;
  1206. }
  1207. if (m_fInheritImmediateEnabled)
  1208. {
  1209. if (IsDlgButtonChecked(hDlg, IDC_ACEE_INHERITIMMEDIATE) == BST_CHECKED)
  1210. uAceFlagsNew |= NO_PROPAGATE_INHERIT_ACE;
  1211. else
  1212. uAceFlagsNew &= ~NO_PROPAGATE_INHERIT_ACE;
  1213. }
  1214. }
  1215. hEntries = DPA_Create(4);
  1216. if(hEntries)
  1217. {
  1218. GetAcesFromCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST),
  1219. m_pSid,
  1220. m_siPageType == SI_PAGE_ADVPERM,
  1221. TRUE,
  1222. uAceFlagsNew,
  1223. pInheritGUID,
  1224. hEntries);
  1225. }
  1226. return hEntries;
  1227. }
  1228. BOOL
  1229. CACEPage::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1230. {
  1231. switch (uMsg)
  1232. {
  1233. case WM_INITDIALOG:
  1234. InitDlg(hDlg);
  1235. break;
  1236. case WM_DESTROY:
  1237. EmptyCheckList(GetDlgItem(hDlg, IDC_ACEE_LIST));
  1238. break;
  1239. case PWM_SELECT_PAGE:
  1240. PropSheet_SetCurSel(GetParent(hDlg), lParam, wParam);
  1241. break;
  1242. case WM_COMMAND:
  1243. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1244. {
  1245. case IDC_ACEE_NAMEBUTTON:
  1246. if (OnChangeName(hDlg))
  1247. {
  1248. PropSheet_Changed(GetParent(hDlg), hDlg);
  1249. m_fPageDirty = TRUE;
  1250. }
  1251. break;
  1252. case IDC_ACEE_INHERITTYPE:
  1253. if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
  1254. {
  1255. HandleSelChange(hDlg, (HWND)lParam);
  1256. PropSheet_Changed(GetParent(hDlg), hDlg);
  1257. m_fPageDirty = TRUE;
  1258. }
  1259. break;
  1260. case IDC_ACEE_INHERITIMMEDIATE:
  1261. if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
  1262. {
  1263. PropSheet_Changed(GetParent(hDlg), hDlg);
  1264. m_fPageDirty = TRUE;
  1265. }
  1266. break;
  1267. case IDC_ACEE_CLEAR:
  1268. if (OnClearAll(hDlg))
  1269. {
  1270. PropSheet_Changed(GetParent(hDlg), hDlg);
  1271. m_fPageDirty = TRUE;
  1272. }
  1273. break;
  1274. default:
  1275. return FALSE;
  1276. }
  1277. break;
  1278. case WM_NOTIFY:
  1279. switch (((NMHDR *)lParam)->code)
  1280. {
  1281. case CLN_CLICK:
  1282. if (lParam)
  1283. {
  1284. HandleListClick((PNM_CHECKLIST)lParam, m_siPageType, FALSE);
  1285. PropSheet_Changed(GetParent(hDlg), hDlg);
  1286. m_fPageDirty = TRUE;
  1287. }
  1288. break;
  1289. case CLN_GETCOLUMNDESC:
  1290. {
  1291. PNM_CHECKLIST pnmc = (PNM_CHECKLIST)lParam;
  1292. GetDlgItemText(hDlg,
  1293. IDC_ACEE_ALLOW - 1 + pnmc->iSubItem,
  1294. pnmc->pszText,
  1295. pnmc->cchTextMax);
  1296. }
  1297. break;
  1298. case PSN_APPLY:
  1299. SetWindowLongPtr(hDlg,
  1300. DWLP_MSGRESULT,
  1301. OnApply(hDlg, (BOOL)(((LPPSHNOTIFY)lParam)->lParam)));
  1302. break;
  1303. }
  1304. break;
  1305. case PSM_QUERYSIBLINGS:
  1306. {
  1307. BOOL bSendQuery = !m_pOtherPage;
  1308. if(this != (CACEPage*)lParam)
  1309. m_pOtherPage = (CACEPage*)lParam;
  1310. if(bSendQuery)
  1311. PostMessage(GetParent(hDlg),PSM_QUERYSIBLINGS,0,(LPARAM)this);
  1312. }
  1313. break;
  1314. case WM_HELP:
  1315. if (IsWindowEnabled(hDlg))
  1316. {
  1317. const DWORD *pdwHelpIDs = aAcePermHelpIDs;
  1318. if (m_siPageType == SI_PAGE_AUDIT)
  1319. pdwHelpIDs = aAceAuditHelpIDs;
  1320. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  1321. c_szAcluiHelpFile,
  1322. HELP_WM_HELP,
  1323. (DWORD_PTR)pdwHelpIDs);
  1324. }
  1325. break;
  1326. case WM_CONTEXTMENU:
  1327. if (IsWindowEnabled(hDlg))
  1328. {
  1329. HWND hwnd = (HWND)wParam;
  1330. const DWORD *pdwHelpIDs = aAcePermHelpIDs;
  1331. if (m_siPageType == SI_PAGE_AUDIT)
  1332. pdwHelpIDs = aAceAuditHelpIDs;
  1333. //
  1334. // Some of the checkboxes may be scrolled out of view, but
  1335. // they are still detected by WinHelp, so we jump through
  1336. // a few extra hoops here.
  1337. //
  1338. if (hwnd == hDlg)
  1339. {
  1340. POINT pt;
  1341. pt.x = GET_X_LPARAM(lParam);
  1342. pt.y = GET_Y_LPARAM(lParam);
  1343. ScreenToClient(hDlg, &pt);
  1344. hwnd = ChildWindowFromPoint(hDlg, pt);
  1345. if (hDlg == hwnd)
  1346. break;
  1347. }
  1348. //
  1349. // WinHelp looks for child windows, but we don't have help id's
  1350. // for the permission checkboxes. If the request is for the
  1351. // checklist window, fake out WinHelp by referring to one of
  1352. // the static labels just above the list.
  1353. //
  1354. if (GetDlgCtrlID(hwnd) == IDC_ACEE_LIST)
  1355. hwnd = GetWindow((HWND)wParam, GW_HWNDPREV); // Static label "Deny"
  1356. WinHelp(hwnd,
  1357. c_szAcluiHelpFile,
  1358. HELP_CONTEXTMENU,
  1359. (DWORD_PTR)pdwHelpIDs);
  1360. }
  1361. break;
  1362. default:
  1363. return FALSE;
  1364. }
  1365. return TRUE;
  1366. }
  1367. HPROPSHEETPAGE
  1368. CreateACEPage(LPSECURITYINFO psi,
  1369. SI_PAGE_TYPE siType,
  1370. PACE pAce,
  1371. BOOL bReadOnly,
  1372. DWORD dwFlags,
  1373. DWORD *pdwResult,
  1374. HDPA *phEntries)
  1375. {
  1376. HPROPSHEETPAGE hPage = NULL;
  1377. LPCTSTR pszTitle = NULL;
  1378. LPACEPAGE pPage;
  1379. TraceEnter(TRACE_ACEEDIT, "CreateACEPage");
  1380. TraceAssert(psi != NULL);
  1381. TraceAssert(phEntries != NULL);
  1382. pPage = new CACEPage(psi,
  1383. siType,
  1384. pAce,
  1385. bReadOnly,
  1386. dwFlags,
  1387. pdwResult,
  1388. phEntries);
  1389. if (pPage)
  1390. {
  1391. int iDlgTemplate = IDD_ACEENTRY_PERM_PAGE;
  1392. if (siType == SI_PAGE_AUDIT)
  1393. iDlgTemplate = IDD_ACEENTRY_AUDIT_PAGE;
  1394. if (dwFlags == SI_ACCESS_PROPERTY)
  1395. pszTitle = MAKEINTRESOURCE(IDS_ACEE_PROPERTY_TITLE);
  1396. hPage = pPage->CreatePropSheetPage(MAKEINTRESOURCE(iDlgTemplate), pszTitle);
  1397. }
  1398. TraceLeaveValue(hPage);
  1399. }
  1400. BOOL
  1401. EditACEEntry(HWND hwndOwner,
  1402. LPSECURITYINFO psi,
  1403. PACE pAce,
  1404. SI_PAGE_TYPE siType,
  1405. LPCTSTR pszObjectName,
  1406. BOOL bReadOnly,
  1407. DWORD *pdwResult,
  1408. HDPA *phEntries,
  1409. HDPA *phPropertyEntries,
  1410. UINT nStartPage)
  1411. {
  1412. HPROPSHEETPAGE hPage[2];
  1413. UINT cPages = 0;
  1414. BOOL bResult = FALSE;
  1415. TraceEnter(TRACE_ACEEDIT, "EditACEEntry");
  1416. TraceAssert(psi != NULL);
  1417. if (phEntries)
  1418. {
  1419. hPage[cPages] = CreateACEPage(psi,
  1420. siType,
  1421. pAce,
  1422. bReadOnly,
  1423. SI_ACCESS_SPECIFIC,
  1424. pdwResult,
  1425. phEntries);
  1426. if (hPage[cPages])
  1427. cPages++;
  1428. }
  1429. if (phPropertyEntries)
  1430. {
  1431. hPage[cPages] = CreateACEPage(psi,
  1432. siType,
  1433. pAce,
  1434. bReadOnly,
  1435. SI_ACCESS_PROPERTY,
  1436. pdwResult,
  1437. phPropertyEntries);
  1438. if (hPage[cPages])
  1439. cPages++;
  1440. }
  1441. if (cPages)
  1442. {
  1443. // Build dialog title string
  1444. LPTSTR pszCaption = NULL;
  1445. FormatStringID(&pszCaption,
  1446. ::hModule,
  1447. siType == SI_PAGE_AUDIT ? IDS_ACEE_AUDIT_TITLE : IDS_ACEE_PERM_TITLE,
  1448. pszObjectName);
  1449. PROPSHEETHEADER psh;
  1450. psh.dwSize = SIZEOF(psh);
  1451. psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW;
  1452. psh.hwndParent = hwndOwner;
  1453. psh.hInstance = ::hModule;
  1454. psh.pszCaption = pszCaption;
  1455. psh.nPages = cPages;
  1456. psh.nStartPage = 0;
  1457. psh.phpage = &hPage[0];
  1458. if (nStartPage < cPages)
  1459. psh.nStartPage = nStartPage;
  1460. bResult = (PropertySheet(&psh) == IDOK);
  1461. LocalFreeString(&pszCaption);
  1462. }
  1463. TraceLeaveValue(bResult);
  1464. }