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.

3353 lines
101 KiB

  1. #include "aclpriv.h"
  2. //Function for checking the Custom checkbox
  3. VOID
  4. CheckCustom(HWND hwndList,
  5. WORD wColumn, //Allow or Deny column
  6. DWORD dwState )
  7. {
  8. //Custom is always the last checkbox
  9. UINT cRights = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  10. //Don't check if the column is already checked. This fucntion is first
  11. //called for explicit and then for inherited aces. Effect is if explict aces are there
  12. //checkbox is enabled.
  13. DWORD dwStateCurrent = (DWORD)SendMessage(hwndList,
  14. CLM_GETSTATE,
  15. MAKELONG((WORD)(cRights -1), wColumn),
  16. 0);
  17. if (dwStateCurrent & CLST_CHECKED)
  18. return;
  19. //
  20. //Custom Checkbox is always disabled
  21. //
  22. SendMessage(hwndList,
  23. CLM_SETSTATE,
  24. MAKELONG((WORD)(cRights -1), wColumn),
  25. dwState|CLST_DISABLED);
  26. }
  27. VOID
  28. ClearCustom(HWND hwndList,
  29. WORD wColumn) //Allow or Deny column
  30. {
  31. //Custom is always the last checkbox
  32. UINT cRights = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  33. //
  34. //Custom Checkbox is always disabled
  35. //
  36. SendMessage(hwndList,
  37. CLM_SETSTATE,
  38. MAKELONG((WORD)(cRights -1), wColumn),
  39. CLST_DISABLED);
  40. }
  41. //
  42. // CPrincipal implementation
  43. //
  44. CPrincipal::~CPrincipal()
  45. {
  46. if (NULL != m_pSID)
  47. LocalFree(m_pSID);
  48. LocalFreeString(&m_pszName);
  49. LocalFreeString(&m_pszDisplayName);
  50. if( m_hAdditionalAllow != NULL )
  51. DSA_Destroy( m_hAdditionalAllow );
  52. if( m_hAdditionalDeny != NULL )
  53. DSA_Destroy( m_hAdditionalDeny );
  54. }
  55. BOOL
  56. CPrincipal::SetPrincipal(PSID pSID,
  57. SID_NAME_USE sidType,
  58. LPCTSTR pszName,
  59. LPCTSTR pszLogonName)
  60. {
  61. DWORD dwLength;
  62. TraceEnter(TRACE_PRINCIPAL, "CPrincipal::SetPrincipal");
  63. TraceAssert(pSID != NULL);
  64. TraceAssert(IsValidSid(pSID));
  65. if (NULL != m_pSID)
  66. LocalFree(m_pSID);
  67. m_pSID = LocalAllocSid(pSID);
  68. SetSidType(sidType);
  69. SetName(pszName, pszLogonName);
  70. TraceLeaveValue(NULL != m_pSID);
  71. }
  72. BOOL
  73. CPrincipal::SetName(LPCTSTR pszName, LPCTSTR pszLogonName)
  74. {
  75. LocalFreeString(&m_pszName);
  76. m_bHaveRealName = FALSE;
  77. if (BuildUserDisplayName(&m_pszName, pszName, pszLogonName))
  78. m_bHaveRealName = TRUE;
  79. else
  80. ConvertSidToStringSid(m_pSID, &m_pszName);
  81. if(pszName)
  82. {
  83. LocalFreeString(&m_pszDisplayName);
  84. LocalAllocString(&m_pszDisplayName, pszName);
  85. }
  86. return (NULL != m_pszName);
  87. }
  88. CPermissionSet*
  89. CPrincipal::GetPermSet(DWORD dwType, BOOL bInherited)
  90. {
  91. CPermissionSet *pPermSet = NULL;
  92. TraceEnter(TRACE_PRINCIPAL, "CPrincipal::GetPermSet");
  93. switch (dwType)
  94. {
  95. case ACCESS_DENIED_ACE_TYPE:
  96. if (bInherited)
  97. pPermSet = &m_permInheritedDeny;
  98. else
  99. pPermSet = &m_permDeny;
  100. break;
  101. case ACCESS_ALLOWED_ACE_TYPE:
  102. if (bInherited)
  103. pPermSet = &m_permInheritedAllow;
  104. else
  105. pPermSet = &m_permAllow;
  106. break;
  107. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  108. // We don't handle compound ACEs
  109. TraceMsg("Ignoring ACCESS_ALLOWED_COMPOUND_ACE");
  110. break;
  111. #ifdef DEBUG
  112. case SYSTEM_AUDIT_ACE_TYPE:
  113. case SYSTEM_ALARM_ACE_TYPE:
  114. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  115. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  116. default:
  117. // We only process the various ACCESS_ALLOWED_* and ACCESS_DENIED_*
  118. // ACE types, except for ACCESS_ALLOWED_COMPOUND_ACE_TYPE, and these
  119. // are all accounted for above. Something is very wrong if we get
  120. // an audit/alarm ACE or some unknown/future ACE type.
  121. TraceAssert(FALSE);
  122. break;
  123. #endif
  124. }
  125. TraceLeaveValue(pPermSet);
  126. }
  127. BOOL
  128. CPrincipal::AddNormalAce(DWORD dwType, DWORD dwFlags, ACCESS_MASK mask, const GUID *pObjectType)
  129. {
  130. BOOL fResult = FALSE;
  131. TraceEnter(TRACE_PRINCIPAL, "CPrincipal::AddNormalAce");
  132. CPermissionSet *pPermSet = GetPermSet(dwType, (BOOL)(dwFlags & INHERITED_ACE));
  133. if (pPermSet)
  134. fResult = pPermSet->AddAce(pObjectType, mask, dwFlags);
  135. TraceLeaveValue(fResult);
  136. }
  137. BOOL
  138. CPrincipal::AddAdvancedAce(DWORD dwType, PACE_HEADER pAce)
  139. {
  140. BOOL fResult = FALSE;
  141. TraceEnter(TRACE_PRINCIPAL, "CPrincipal::AddAdvancedAce");
  142. CPermissionSet *pPermSet = GetPermSet(dwType, AceInherited(pAce));
  143. if (pPermSet)
  144. fResult = pPermSet->AddAdvancedAce(pAce);
  145. TraceLeaveValue(fResult);
  146. }
  147. BOOL
  148. CPrincipal::AddAce(PACE_HEADER pAce)
  149. {
  150. TraceEnter(TRACE_PRINCIPAL, "CPrincipal::AddAce");
  151. TraceAssert(pAce != NULL);
  152. BOOL fResult = FALSE;
  153. const GUID *pObjectType = NULL;
  154. UCHAR AceType = pAce->AceType;
  155. UCHAR AceFlags = pAce->AceFlags;
  156. ACCESS_MASK AccessMask = ((PKNOWN_ACE)pAce)->Mask;
  157. ULONG ulObjectFlags = 0;
  158. // Get the object type GUID from object ACEs
  159. if (IsObjectAceType(pAce))
  160. {
  161. AceType -= (ACCESS_ALLOWED_OBJECT_ACE_TYPE - ACCESS_ALLOWED_ACE_TYPE);
  162. ulObjectFlags = ((PKNOWN_OBJECT_ACE)pAce)->Flags;
  163. if (m_pPage->m_wDaclRevision < ACL_REVISION_DS)
  164. m_pPage->m_wDaclRevision = ACL_REVISION_DS;
  165. pObjectType = RtlObjectAceObjectType(pAce);
  166. }
  167. if (!pObjectType)
  168. pObjectType = &GUID_NULL;
  169. // Map any generic bits to standard & specific bits.
  170. m_pPage->m_psi->MapGeneric(pObjectType, &AceFlags, &AccessMask);
  171. // Can't have INHERIT_ONLY_ACE without either CONTAINER_INHERIT_ACE or
  172. // OBJECT_INHERIT_ACE, so if we find one of these, skip it.
  173. if ((AceFlags & (INHERIT_ONLY_ACE | ACE_INHERIT_ALL)) != INHERIT_ONLY_ACE)
  174. {
  175. //
  176. //ACE_INHERITED_OBJECT_TYPE_PRESENT is invalid without
  177. //either of container inherit or object inherit flags.
  178. //NTRAID#NTBUG9-287737-2001/01/23-hiteshr
  179. //
  180. if (ulObjectFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT &&
  181. AceFlags & ACE_INHERIT_ALL)
  182. {
  183. // If we have an inherit object type without INHERIT_ONLY_ACE,
  184. // and the inherit object type matches the current object,
  185. // then it applies to this object. Simulate this (per the
  186. // ACL inheritance spec) with 2 ACEs: one with no inheritance
  187. // at all, and one with the inherit type + INHERIT_ONLY_ACE.
  188. // Does it apply to this object?
  189. if ((m_pPage->m_siObjectInfo.dwFlags & SI_OBJECT_GUID) &&
  190. !(AceFlags & INHERIT_ONLY_ACE) &&
  191. IsSameGUID(&m_pPage->m_siObjectInfo.guidObjectType, RtlObjectAceInheritedObjectType(pAce)))
  192. {
  193. // Mask out all flags except INHERITED_ACE and add it
  194. AddNormalAce(AceType, (AceFlags & INHERITED_ACE), AccessMask, pObjectType);
  195. // Turn on INHERIT_ONLY_ACE before adding the "advanced" ACE.
  196. pAce->AceFlags |= INHERIT_ONLY_ACE;
  197. }
  198. // The ACE does not apply directly to this object
  199. fResult = AddAdvancedAce(AceType, pAce);
  200. }
  201. else
  202. {
  203. fResult = AddNormalAce(AceType, AceFlags, AccessMask, pObjectType);
  204. }
  205. }
  206. TraceLeaveValue(fResult);
  207. }
  208. ULONG
  209. CPrincipal::GetAclLength(DWORD dwFlags)
  210. {
  211. // Return an estimate of the buffer size needed to hold the
  212. // requested ACEs. The size of the ACL header is NOT INCLUDED.
  213. // The following flags are always assumed:
  214. // ACL_DENY | ACL_ALLOW | ACL_NONOBJECT | ACL_OBJECT
  215. ULONG nAclLength = 0;
  216. ULONG nSidLength;
  217. TraceEnter(TRACE_PRINCIPAL, "CPrincipal::GetAclLength");
  218. TraceAssert(NULL != m_pSID);
  219. if (NULL == m_pSID)
  220. TraceLeaveValue(0);
  221. nSidLength = GetLengthSid(m_pSID);
  222. if (dwFlags & ACL_NONINHERITED)
  223. {
  224. nAclLength += m_permDeny.GetAclLength(nSidLength);
  225. nAclLength += m_permAllow.GetAclLength(nSidLength);
  226. }
  227. if (dwFlags & ACL_INHERITED)
  228. {
  229. nAclLength += m_permInheritedDeny.GetAclLength(nSidLength);
  230. nAclLength += m_permInheritedAllow.GetAclLength(nSidLength);
  231. }
  232. TraceLeaveValue(nAclLength);
  233. }
  234. BOOL
  235. CPrincipal::AppendToAcl(PACL pAcl,
  236. DWORD dwFlags,
  237. PACE_HEADER *ppAcePos) // position to copy first ACE
  238. {
  239. PACE_HEADER pAceT;
  240. TraceEnter(TRACE_PRINCIPAL, "CPrincipal::AppendToAcl");
  241. TraceAssert(pAcl != NULL && IsValidAcl(pAcl));
  242. TraceAssert(ppAcePos != NULL);
  243. TraceAssert(NULL != m_pSID);
  244. if (NULL == m_pSID)
  245. TraceLeaveValue(FALSE);
  246. pAceT = *ppAcePos;
  247. // Build the ACL in the following order:
  248. // Deny
  249. // Allow
  250. // Inherited Deny
  251. // Inherited Allow
  252. if (dwFlags & ACL_NONINHERITED)
  253. {
  254. if (dwFlags & ACL_DENY)
  255. m_permDeny.AppendToAcl(pAcl, ppAcePos, m_pSID, FALSE, dwFlags);
  256. if (dwFlags & ACL_ALLOW)
  257. m_permAllow.AppendToAcl(pAcl, ppAcePos, m_pSID, TRUE, dwFlags);
  258. }
  259. if (dwFlags & ACL_INHERITED)
  260. {
  261. if (dwFlags & ACL_DENY)
  262. m_permInheritedDeny.AppendToAcl(pAcl, ppAcePos, m_pSID, FALSE, dwFlags);
  263. if (dwFlags & ACL_ALLOW)
  264. m_permInheritedAllow.AppendToAcl(pAcl, ppAcePos, m_pSID, TRUE, dwFlags);
  265. }
  266. if ((dwFlags & ACL_CHECK_CREATOR) && IsCreatorSid(m_pSID))
  267. {
  268. //
  269. // Special case for CreatorOwner/CreatorGroup,
  270. // which are only useful if inherit bits are set.
  271. //
  272. for (; pAceT < *ppAcePos; pAceT = (PACE_HEADER)NextAce(pAceT))
  273. {
  274. pAceT->AceFlags |= INHERIT_ONLY_ACE;
  275. if (!(pAceT->AceFlags & ACE_INHERIT_ALL))
  276. {
  277. pAceT->AceFlags |= ACE_INHERIT_ALL;
  278. //
  279. // Give the client a chance to adjust the flags.
  280. // E.g. DS always turns off OBJECT_INHERIT_ACE
  281. //
  282. UCHAR AceFlags = pAceT->AceFlags;
  283. ACCESS_MASK Mask = GENERIC_ALL;
  284. m_pPage->m_psi->MapGeneric(NULL, &AceFlags, &Mask);
  285. pAceT->AceFlags = AceFlags;
  286. }
  287. }
  288. }
  289. TraceAssert(IsValidAcl(pAcl));
  290. TraceLeaveValue(TRUE);
  291. }
  292. BOOL
  293. CPrincipal::HaveInheritedAces(void)
  294. {
  295. return (m_permInheritedAllow.GetPermCount(TRUE) || m_permInheritedDeny.GetPermCount(TRUE));
  296. }
  297. void
  298. CPrincipal::ConvertInheritedAces(BOOL bDelete)
  299. {
  300. if (bDelete)
  301. {
  302. m_permInheritedDeny.Reset();
  303. m_permInheritedAllow.Reset();
  304. }
  305. else
  306. {
  307. m_permDeny.ConvertInheritedAces(m_permInheritedDeny);
  308. m_permAllow.ConvertInheritedAces(m_permInheritedAllow);
  309. }
  310. }
  311. void
  312. CPrincipal::AddPermission(BOOL bAllow, PPERMISSION pperm)
  313. {
  314. if (bAllow)
  315. m_permAllow.AddPermission(pperm);
  316. else
  317. m_permDeny.AddPermission(pperm);
  318. }
  319. void
  320. CPrincipal::RemovePermission(BOOL bAllow, PPERMISSION pperm)
  321. {
  322. if (bAllow)
  323. m_permAllow.RemovePermission(pperm);
  324. else
  325. m_permDeny.RemovePermission(pperm);
  326. }
  327. //
  328. // CPermPage implementation
  329. //
  330. void
  331. CPermPage::InitPrincipalList(HWND hDlg, PACL pDacl)
  332. {
  333. TraceEnter(TRACE_PERMPAGE, "CPermPage::InitPrincipalList");
  334. TraceAssert(hDlg != NULL);
  335. HWND hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  336. TraceAssert(hwndList != NULL);
  337. // Save the DACL revision
  338. if (pDacl != NULL)
  339. {
  340. m_wDaclRevision = pDacl->AclRevision;
  341. }
  342. // If we have a selection, remember the SID for later
  343. PSID psidTemp = NULL;
  344. LPPRINCIPAL pPrincipal = (LPPRINCIPAL)GetSelectedItemData(hwndList, NULL);
  345. if (pPrincipal != NULL)
  346. psidTemp = LocalAllocSid(pPrincipal->GetSID());
  347. // Empty out the list
  348. ListView_DeleteAllItems(hwndList);
  349. // Enumerate the new DACL and fill the list
  350. EnumerateAcl(hwndList, pDacl);
  351. // Try to re-select the previously selection
  352. if (psidTemp != NULL)
  353. {
  354. int cItems = ListView_GetItemCount(hwndList);
  355. LV_ITEM lvItem;
  356. lvItem.iSubItem = 0;
  357. lvItem.mask = LVIF_PARAM;
  358. // Look for the previously selected principal in the list
  359. while (cItems > 0)
  360. {
  361. --cItems;
  362. lvItem.iItem = cItems;
  363. ListView_GetItem(hwndList, &lvItem);
  364. pPrincipal = (LPPRINCIPAL)lvItem.lParam;
  365. if (EqualSid(psidTemp, pPrincipal->GetSID()))
  366. {
  367. SelectListViewItem(hwndList, cItems);
  368. break;
  369. }
  370. }
  371. LocalFree(psidTemp);
  372. }
  373. TraceLeaveVoid();
  374. }
  375. STDMETHODIMP
  376. _InitCheckList(HWND hwndList,
  377. LPSECURITYINFO psi,
  378. const GUID* pguidObjectType,
  379. DWORD dwFlags,
  380. HINSTANCE hInstance,
  381. DWORD dwType,
  382. PSI_ACCESS *ppDefaultAccess)
  383. {
  384. HRESULT hr;
  385. PSI_ACCESS pAccess;
  386. ULONG cAccesses;
  387. ULONG iDefaultAccess;
  388. TCHAR szName[MAX_PATH];
  389. TraceEnter(TRACE_MISC, "_InitCheckList");
  390. TraceAssert(psi != NULL);
  391. //
  392. // Retrieve the permission list
  393. //
  394. hr = psi->GetAccessRights(pguidObjectType,
  395. dwFlags,
  396. &pAccess,
  397. &cAccesses,
  398. &iDefaultAccess);
  399. if (SUCCEEDED(hr) && cAccesses > 0)
  400. {
  401. if (ppDefaultAccess != NULL)
  402. *ppDefaultAccess = &pAccess[iDefaultAccess];
  403. // Enumerate the permissions and add to the checklist
  404. for (ULONG i = 0; i < cAccesses; i++, pAccess++)
  405. {
  406. LPCTSTR pszName;
  407. // Only add permissions that have any of the flags specified in dwType
  408. if (!(pAccess->dwFlags & dwType))
  409. continue;
  410. pszName = pAccess->pszName;
  411. if (IS_INTRESOURCE(pszName))
  412. {
  413. TraceAssert(hInstance != NULL);
  414. if (LoadString(hInstance,
  415. (UINT)((ULONG_PTR)pszName),
  416. szName,
  417. ARRAYSIZE(szName)) == 0)
  418. {
  419. LoadString(::hModule,
  420. IDS_UNKNOWN,
  421. szName,
  422. ARRAYSIZE(szName));
  423. }
  424. pszName = szName;
  425. }
  426. if (SendMessage(hwndList,
  427. CLM_ADDITEM,
  428. (WPARAM)pszName,
  429. (LPARAM)pAccess) == -1)
  430. {
  431. DWORD dwErr = GetLastError();
  432. ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr), "Failed to add item to checklist");
  433. }
  434. }
  435. }
  436. exit_gracefully:
  437. TraceLeaveResult(hr);
  438. }
  439. HRESULT
  440. CPermPage::InitCheckList(HWND hDlg)
  441. {
  442. HRESULT hr;
  443. TCHAR szName[MAX_PATH];
  444. PSI_ACCESS pAccess;
  445. TraceEnter(TRACE_PERMPAGE, "CPermPage::InitCheckList");
  446. TraceAssert(hDlg != NULL);
  447. HWND hwndList = GetDlgItem(hDlg, IDC_SPP_PERMS); // checklist window
  448. TraceAssert(hwndList != NULL);
  449. DWORD dwType = SI_ACCESS_GENERAL;
  450. if (m_siObjectInfo.dwFlags & SI_CONTAINER)
  451. dwType |= SI_ACCESS_CONTAINER;
  452. // Enumerate the permissions and add to the checklist
  453. hr = _InitCheckList(hwndList,
  454. m_psi,
  455. NULL,
  456. 0,
  457. m_siObjectInfo.hInstance,
  458. dwType,
  459. &m_pDefaultAccess);
  460. if (SUCCEEDED(hr))
  461. {
  462. //Add Custom Checkbox at the bottom of checklist. Custom checkbox is added only if
  463. //Advanced Page is there
  464. if(m_bCustomPermission)
  465. {
  466. if( ( pAccess = (PSI_ACCESS)LocalAlloc( LPTR, sizeof( SI_ACCESS ) ) ) == NULL )
  467. ExitGracefully(hr, HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY), "Failed to allocate Memeory");
  468. pAccess->dwFlags = SI_ACCESS_CUSTOM;
  469. LoadString(::hModule, IDS_CUSTOM, szName, ARRAYSIZE(szName));
  470. if (SendMessage(hwndList, CLM_ADDITEM, (WPARAM)szName, (LPARAM)pAccess) == -1)
  471. {
  472. DWORD dwErr = GetLastError();
  473. ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr), "Failed to add item to checklist");
  474. }
  475. //
  476. //Disable the custom checkbox
  477. //
  478. ClearCustom(hwndList,1);
  479. ClearCustom(hwndList,2);
  480. }
  481. }
  482. exit_gracefully:
  483. TraceLeaveResult(hr);
  484. }
  485. //
  486. // CAUTION - This function modifies the ACEs in the ACL by setting
  487. // the AceType to 0xff (an invalid ACE type).
  488. //
  489. //This function goes through the ACL and groups the aces
  490. //according to SID in PRINCIPAL objects.
  491. void
  492. CPermPage::EnumerateAcl(HWND hwndList, PACL pAcl)
  493. {
  494. LPPRINCIPAL pPrincipal;
  495. PACE_HEADER pAce;
  496. int iEntry;
  497. int iTemp;
  498. PACE_HEADER paceTemp;
  499. HDPA hSids = NULL;
  500. if (pAcl == NULL)
  501. return;
  502. TraceEnter(TRACE_PERMPAGE, "CPermPage::EnumerateAcl");
  503. TraceAssert(IsValidAcl(pAcl));
  504. TraceAssert(hwndList != NULL);
  505. hSids = DPA_Create(4);
  506. if (NULL == hSids)
  507. TraceLeaveVoid();
  508. for (iEntry = 0, pAce = (PACE_HEADER)FirstAce(pAcl);
  509. iEntry < pAcl->AceCount;
  510. iEntry++, pAce = (PACE_HEADER)NextAce(pAce))
  511. {
  512. // Skip ACEs that we've already seen
  513. if (pAce->AceType == 0xff)
  514. continue;
  515. // Found an ACE we haven't seen yet, must be a new principal
  516. pPrincipal = new CPrincipal(this);
  517. if (pPrincipal == NULL)
  518. continue; // memory error (try to continue)
  519. // Initialize new principal
  520. if (!pPrincipal->SetPrincipal(GetAceSid(pAce)))
  521. {
  522. delete pPrincipal;
  523. continue; // probably memory error (try to continue)
  524. }
  525. // Remember the SIDs so that later we can look up all the names
  526. // at once and then add them to the listview.
  527. DPA_AppendPtr(hSids, pPrincipal->GetSID());
  528. // The current ACE belongs to this principal, so add it
  529. pPrincipal->AddAce(pAce);
  530. // Mark the ACE so we don't look at it again
  531. pAce->AceType = 0xff;
  532. // Loop through the rest of the ACEs in the ACL looking
  533. // for the same SID
  534. paceTemp = pAce;
  535. for (iTemp = iEntry + 1; iTemp < pAcl->AceCount; iTemp++)
  536. {
  537. // Move pointer to the current ACE
  538. paceTemp = (PACE_HEADER)NextAce(paceTemp);
  539. // If this ACE belongs to the current principal, add it
  540. if (paceTemp->AceType != 0xff &&
  541. EqualSid(GetAceSid(paceTemp), pPrincipal->GetSID()))
  542. {
  543. // Same principal, add the ACE
  544. pPrincipal->AddAce(paceTemp);
  545. // Mark the ACE so we don't look at it again
  546. paceTemp->AceType = 0xff;
  547. }
  548. }
  549. if (-1 == AddPrincipalToList(hwndList, pPrincipal))
  550. {
  551. delete pPrincipal;
  552. }
  553. }
  554. // Launch thread to look up sids
  555. m_fBusy = TRUE;
  556. LookupSidsAsync(hSids,
  557. m_siObjectInfo.pszServerName,
  558. m_psi2,
  559. GetParent(hwndList),
  560. UM_SIDLOOKUPCOMPLETE);
  561. DPA_Destroy(hSids);
  562. TraceLeaveVoid();
  563. }
  564. HRESULT
  565. CPermPage::SetPrincipalNamesInList(HWND hwndList, PSID pSid)
  566. {
  567. TraceEnter(TRACE_PERMPAGE, "CPermPage::SetPrincipalNamesInList");
  568. HRESULT hr = S_OK;
  569. PUSER_LIST pUserList = NULL;
  570. LPPRINCIPAL pPrincipal = NULL;
  571. LVITEM lvItem = {0};
  572. int cListItems;
  573. int iListItem;
  574. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  575. // Enumerate through each entry in the list view
  576. cListItems = ListView_GetItemCount(hwndList);
  577. for (iListItem = 0; iListItem < cListItems; iListItem++)
  578. {
  579. lvItem.mask = LVIF_PARAM;
  580. lvItem.iItem = iListItem;
  581. lvItem.iSubItem = 0;
  582. if (ListView_GetItem(hwndList, &lvItem))
  583. {
  584. pPrincipal = (LPPRINCIPAL) lvItem.lParam;
  585. if (pPrincipal != NULL)
  586. {
  587. // Are we looking for a particular principal?
  588. if (pSid && !EqualSid(pSid, pPrincipal->GetSID()))
  589. continue;
  590. // Do we already have a good name?
  591. if (pPrincipal->HaveRealName())
  592. {
  593. if (pSid)
  594. break; // only care about this principal, stop here
  595. else
  596. continue; // skip this one and check the rest
  597. }
  598. // Lookup the SID for this principal in the cache
  599. LookupSid(pPrincipal->GetSID(),
  600. m_siObjectInfo.pszServerName,
  601. m_psi2,
  602. &pUserList);
  603. if ((pUserList != NULL) && (pUserList->cUsers == 1))
  604. {
  605. // The list should contain a single item
  606. PUSER_INFO pUserInfo = &pUserList->rgUsers[0];
  607. // Update the principal with this new name information
  608. pPrincipal->SetSidType(pUserInfo->SidType);
  609. pPrincipal->SetName(pUserInfo->pszName, pUserInfo->pszLogonName);
  610. // Set the text of this item to the name we've found
  611. lvItem.mask = LVIF_TEXT | LVIF_IMAGE;
  612. lvItem.pszText = (LPTSTR)pPrincipal->GetName();
  613. lvItem.iImage = pPrincipal->GetImageIndex();
  614. ListView_SetItem(hwndList, &lvItem);
  615. LocalFree(pUserList);
  616. }
  617. }
  618. }
  619. }
  620. SetCursor(hcur);
  621. TraceLeaveResult(hr);
  622. }
  623. int
  624. CPermPage::AddPrincipalToList(HWND hwndList, LPPRINCIPAL pPrincipal)
  625. {
  626. LVITEM lvItem;
  627. int iIndex = -1;
  628. TraceEnter(TRACE_PERMPAGE, "CPermPage::AddPrincipalToList");
  629. TraceAssert(hwndList != NULL);
  630. TraceAssert(pPrincipal != NULL);
  631. // Insert new principal into listview
  632. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  633. lvItem.iItem = 0;
  634. lvItem.iSubItem = 0;
  635. lvItem.lParam = (LPARAM)pPrincipal;
  636. lvItem.pszText = (LPTSTR)pPrincipal->GetName();
  637. lvItem.iImage = pPrincipal->GetImageIndex();
  638. iIndex = ListView_InsertItem(hwndList, &lvItem);
  639. TraceLeaveValue(iIndex);
  640. }
  641. VOID
  642. CPermPage::SetPermLabelText(HWND hDlg)
  643. {
  644. RECT rc;
  645. WCHAR szBuffer[MAX_COLUMN_CHARS];
  646. HWND hwndLabel;
  647. HWND hwndList;
  648. LPTSTR pszCaption = NULL;
  649. SIZE size;
  650. LPCWSTR pszUserName = NULL;
  651. CPrincipal * pPrincipal = NULL;
  652. int iIndex = 0;
  653. //Get Label Dimension
  654. hwndLabel = GetDlgItem(hDlg, IDC_SPP_ACCESS);
  655. GetClientRect(hwndLabel, &rc);
  656. MapDialogRect(hDlg,&rc);
  657. //Get Text Dimension
  658. HDC hdc = GetDC(hDlg);
  659. hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  660. pPrincipal = (LPPRINCIPAL)GetSelectedItemData(hwndList, &iIndex);
  661. if(pPrincipal)
  662. pszUserName = pPrincipal->GetDisplayName();
  663. if(pszUserName)
  664. FormatStringID(&pszCaption, ::hModule, IDS_DYNAMIC_PERMISSION,pszUserName);
  665. else
  666. FormatStringID(&pszCaption, ::hModule, IDS_PERMISSIONS, NULL);
  667. GetTextExtentPoint32(hdc,pszCaption,wcslen(pszCaption),&size);
  668. if(size.cx > rc.right)
  669. {
  670. hwndLabel = GetDlgItem(hDlg, IDC_SPP_ACCESS);
  671. EnableWindow(hwndLabel, FALSE);
  672. ShowWindow(hwndLabel,SW_HIDE);
  673. hwndLabel = GetDlgItem(hDlg, IDC_SPP_ACCESS_BIG);
  674. EnableWindow(hwndLabel, TRUE);
  675. ShowWindow(hwndLabel,SW_SHOW);
  676. SetWindowText(hwndLabel,pszCaption);
  677. }
  678. else
  679. {
  680. hwndLabel = GetDlgItem(hDlg, IDC_SPP_ACCESS_BIG);
  681. EnableWindow(hwndLabel, FALSE);
  682. ShowWindow(hwndLabel,SW_HIDE);
  683. hwndLabel = GetDlgItem(hDlg, IDC_SPP_ACCESS);
  684. EnableWindow(hwndLabel, TRUE);
  685. ShowWindow(hwndLabel,SW_SHOW);
  686. SetWindowText(hwndLabel,pszCaption);
  687. }
  688. hwndLabel = GetDlgItem(hDlg, IDC_EDIT1);
  689. SetWindowText(hwndLabel,pszCaption);
  690. LocalFreeString(&pszCaption);
  691. ReleaseDC(hDlg, hdc);
  692. }
  693. BOOL
  694. CPermPage::InitDlg(HWND hDlg)
  695. {
  696. HRESULT hr = S_OK;
  697. HWND hwnd;
  698. HWND hwndList;
  699. RECT rc;
  700. LV_COLUMN col;
  701. TCHAR szBuffer[MAX_COLUMN_CHARS];
  702. PSECURITY_DESCRIPTOR pSD = NULL;
  703. BOOL bUserNotified = FALSE;
  704. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  705. TraceEnter(TRACE_PERMPAGE, "CPermPage::InitDlg");
  706. TraceAssert(hDlg != NULL);
  707. TraceAssert(m_psi != NULL);
  708. hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  709. //
  710. // Create & set the image list for the listview. If there is a
  711. // problem CreateSidImageList will return NULL which won't hurt
  712. // anything. In that case we'll just continue without an image list.
  713. //
  714. ListView_SetImageList(hwndList,
  715. LoadImageList(::hModule, MAKEINTRESOURCE(IDB_SID_ICONS)),
  716. LVSIL_SMALL);
  717. // Set extended LV style for whole line selection with InfoTips
  718. ListView_SetExtendedListViewStyleEx(hwndList,
  719. LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP,
  720. LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
  721. //
  722. // Add appropriate listview columns
  723. //
  724. GetClientRect(hwndList, &rc);
  725. col.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH;
  726. col.fmt = LVCFMT_LEFT;
  727. col.iSubItem = 0;
  728. col.cx = rc.right;
  729. ListView_InsertColumn(hwndList, 0, &col);
  730. if (!(m_siObjectInfo.dwFlags & SI_ADVANCED))
  731. {
  732. // Hide the Advanced button
  733. hwnd = GetDlgItem(hDlg, IDC_SPP_ADVANCED);
  734. ShowWindow(hwnd, SW_HIDE);
  735. EnableWindow(hwnd, FALSE);
  736. hwnd = GetDlgItem(hDlg, IDC_SPP_STATIC_ADV);
  737. ShowWindow(hwnd, SW_HIDE);
  738. EnableWindow(hwnd, FALSE);
  739. }
  740. if (S_FALSE == m_hrLastPSPCallbackResult)
  741. {
  742. // The propsheetpage callback told us to not show any messages here.
  743. bUserNotified = TRUE;
  744. }
  745. //Additional Permissions?
  746. m_bCustomPermission = (m_siObjectInfo.dwFlags & SI_ADVANCED)
  747. && !(m_siObjectInfo.dwFlags & SI_NO_ADDITIONAL_PERMISSION);
  748. if (m_bAbortPage)
  749. {
  750. // Disable everything except the Advanced button
  751. m_siObjectInfo.dwFlags |= SI_READONLY;
  752. EnableWindow(hwndList, FALSE);
  753. // The user should have been notified during the propsheetpage
  754. // callback, so don't put up another message now.
  755. bUserNotified = TRUE;
  756. }
  757. else
  758. {
  759. //
  760. // Initialize the checklist window
  761. //
  762. hr = InitCheckList(hDlg);
  763. FailGracefully(hr, "Failed to initialize checklist");
  764. //
  765. // Retrieve the DACL from the object and set it into the dialog
  766. //
  767. hr = m_psi->GetSecurity(DACL_SECURITY_INFORMATION, &pSD, FALSE);
  768. if (SUCCEEDED(hr))
  769. {
  770. // We always disable the advanced button until the SID name cache
  771. // is filled on our other thread. See the DlgProc handler for
  772. // UM_SIDLOOKUPCOMPLETE
  773. EnableWindow(GetDlgItem(hDlg, IDC_SPP_ADVANCED), FALSE);
  774. hr = SetDacl(hDlg, pSD);
  775. FailGracefully(hr, "SetDacl failed");
  776. }
  777. else if (hr == E_ACCESSDENIED)
  778. {
  779. if (!bUserNotified)
  780. {
  781. //
  782. // Can't read the DACL or Owner, figure out what we CAN do.
  783. //
  784. UINT idMsg = IDS_PERM_NO_ACCESS;
  785. UINT mbType = MB_OK | MB_ICONWARNING;
  786. if (!(m_siObjectInfo.dwFlags & SI_READONLY))
  787. {
  788. if(!( m_siObjectInfo.dwFlags & SI_MAY_WRITE))
  789. idMsg = IDS_PERM_CANT_READ_CAN_WRITE_DACL;
  790. else
  791. idMsg = IDS_PERM_CANT_READ_MAY_WRITE_DACL;
  792. }
  793. else
  794. {
  795. //
  796. // Can't write the DACL, can we write the owner or edit the SACL?
  797. //
  798. DWORD dwFlags = m_siObjectInfo.dwFlags & (SI_EDIT_AUDITS | SI_OWNER_READONLY);
  799. // If we're not editing the owner, then we can't write it.
  800. if (!(m_siObjectInfo.dwFlags & SI_EDIT_OWNER))
  801. dwFlags |= SI_OWNER_READONLY;
  802. switch(dwFlags)
  803. {
  804. case 0:
  805. // Can write the Owner but can't edit the SACL
  806. idMsg = IDS_PERM_CANT_READ_CAN_WRITE_OWNER;
  807. break;
  808. case SI_EDIT_AUDITS:
  809. // Can edit the SACL and write the Owner
  810. idMsg = IDS_PERM_CANT_READ_CAN_AUDIT_WRITE_OWNER;
  811. break;
  812. case SI_OWNER_READONLY:
  813. // No Access
  814. break;
  815. case SI_OWNER_READONLY | SI_EDIT_AUDITS:
  816. // Can edit the SACL but can't write the Owner
  817. idMsg = IDS_PERM_CANT_READ_CAN_AUDIT;
  818. break;
  819. }
  820. }
  821. if (idMsg == IDS_PERM_NO_ACCESS)
  822. mbType = MB_OK | MB_ICONERROR;
  823. MsgPopup(hDlg,
  824. MAKEINTRESOURCE(idMsg),
  825. MAKEINTRESOURCE(IDS_SECURITY),
  826. mbType,
  827. ::hModule,
  828. m_siObjectInfo.pszObjectName);
  829. bUserNotified = TRUE;
  830. }
  831. EnablePrincipalControls(hDlg, FALSE);
  832. hr = S_OK;
  833. }
  834. else
  835. {
  836. FailGracefully(hr, "GetSecurity failed");
  837. }
  838. } // !m_bAbortPage
  839. if (m_siObjectInfo.dwFlags & SI_READONLY)
  840. {
  841. EnableWindow(GetDlgItem(hDlg, IDC_SPP_ADD), FALSE);
  842. EnablePrincipalControls(hDlg, FALSE);
  843. // Tell the user that we're in read-only mode
  844. //Do not show this dialog box
  845. //Windows Bug 181665
  846. /*if (!bUserNotified)
  847. {
  848. MsgPopup(hDlg,
  849. MAKEINTRESOURCE(IDS_PERM_READONLY),
  850. MAKEINTRESOURCE(IDS_SECURITY),
  851. MB_OK | MB_ICONINFORMATION,
  852. ::hModule,
  853. m_siObjectInfo.pszObjectName);
  854. bUserNotified = TRUE;
  855. }
  856. */
  857. }
  858. exit_gracefully:
  859. if (pSD != NULL)
  860. LocalFree(pSD);
  861. SetCursor(hcur);
  862. if (FAILED(hr))
  863. {
  864. // Hide and disable everything
  865. for (hwnd = GetWindow(hDlg, GW_CHILD);
  866. hwnd != NULL;
  867. hwnd = GetWindow(hwnd, GW_HWNDNEXT))
  868. {
  869. ShowWindow(hwnd, SW_HIDE);
  870. EnableWindow(hwnd, FALSE);
  871. }
  872. // Enable and show the "No Security" message
  873. hwnd = GetDlgItem(hDlg, IDC_SPP_NO_SECURITY);
  874. EnableWindow(hwnd, TRUE);
  875. ShowWindow(hwnd, SW_SHOW);
  876. }
  877. TraceLeaveValue(TRUE);
  878. }
  879. BOOL
  880. CPermPage::OnNotify(HWND hDlg, int /*idCtrl*/, LPNMHDR pnmh)
  881. {
  882. LPNM_LISTVIEW pnmlv = (LPNM_LISTVIEW)pnmh;
  883. TraceEnter(TRACE_PERMPAGE, "CPermPage::OnNotify");
  884. TraceAssert(hDlg != NULL);
  885. TraceAssert(pnmh != NULL);
  886. // Set default return value
  887. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  888. switch (pnmh->code)
  889. {
  890. case LVN_ITEMCHANGED:
  891. if (pnmlv->uChanged & LVIF_STATE)
  892. {
  893. OnSelChange(hDlg);
  894. // item *gaining* selection
  895. if ((pnmlv->uNewState & LVIS_SELECTED) &&
  896. !(pnmlv->uOldState & LVIS_SELECTED))
  897. {
  898. //here bClearCustom should be False. We don't need to clear
  899. //Custom when we select another principal.
  900. //Build Additional List for it.
  901. }
  902. // item *losing* selection
  903. else if (!(pnmlv->uNewState & LVIS_SELECTED) &&
  904. (pnmlv->uOldState & LVIS_SELECTED))
  905. {
  906. // Post ourselves a message to check for a new selection later.
  907. // If we haven't gotten a new selection by the time we process
  908. // this message, then assume the user clicked inside the listview
  909. // but not on an item, thus causing the listview to remove the
  910. // selection. In that case, disable the combobox & Remove button.
  911. //
  912. // Do this via WM_COMMAND rather than WM_NOTIFY so we don't
  913. // have to allocate/free a NMHDR structure.
  914. PostMessage(hDlg,
  915. WM_COMMAND,
  916. GET_WM_COMMAND_MPS(pnmh->idFrom, pnmh->hwndFrom, IDN_CHECKSELECTION));
  917. }
  918. }
  919. break;
  920. case LVN_DELETEITEM:
  921. delete (LPPRINCIPAL)pnmlv->lParam;
  922. break;
  923. case LVN_KEYDOWN:
  924. if (((LPNMLVKEYDOWN)pnmh)->wVKey == VK_DELETE)
  925. {
  926. //Get the status of Remove button. Only if remove is
  927. //enabled do something bug 390243
  928. if( IsWindowEnabled( GetDlgItem( hDlg,IDC_SPP_REMOVE )) )
  929. OnRemovePrincipal(hDlg);
  930. }
  931. break;
  932. #ifdef UNUSED
  933. case NM_DBLCLK:
  934. if (pnmh->idFrom == IDC_SPP_PRINCIPALS)
  935. {
  936. // Must have a selection to get here
  937. TraceAssert(ListView_GetSelectedCount(pnmh->hwndFrom) == 1);
  938. // do something here
  939. }
  940. break;
  941. #endif
  942. case CLN_CLICK:
  943. if (pnmh->idFrom == IDC_SPP_PERMS)
  944. {
  945. LPPRINCIPAL pPrincipal;
  946. int iIndex = -1;
  947. pPrincipal = (LPPRINCIPAL)GetSelectedItemData(GetDlgItem(hDlg, IDC_SPP_PRINCIPALS), &iIndex);
  948. if (pPrincipal)
  949. {
  950. PNM_CHECKLIST pnmc = (PNM_CHECKLIST)pnmh;
  951. PSI_ACCESS pAccess = (PSI_ACCESS)pnmc->dwItemData;
  952. //Custom checkbox is clicked, reqiures special handling
  953. if( pAccess->dwFlags & SI_ACCESS_CUSTOM )
  954. {
  955. if (pnmc->dwState & CLST_CHECKED)
  956. {
  957. //Uncheck the Checkbox. Can checkbox be prevented from checked?
  958. SendMessage(pnmc->hdr.hwndFrom,
  959. CLM_SETSTATE,
  960. MAKELONG((WORD)pnmc->iItem, (WORD)pnmc->iSubItem),
  961. 0
  962. );
  963. //Show the message box
  964. MsgPopup(hDlg,
  965. MAKEINTRESOURCE(IDS_CUSTOM_CHECKBOX_WARNING),
  966. MAKEINTRESOURCE(IDS_SECURITY),
  967. MB_OK | MB_ICONINFORMATION,
  968. ::hModule);
  969. }
  970. else
  971. {
  972. SetDirty(hDlg);
  973. //Clear the Special Checkbox and Permissions
  974. BOOL bClearAllow = (1 == pnmc->iSubItem); // 1 = Allow, 2 = Deny
  975. OnSelChange(hDlg, TRUE, bClearAllow, !bClearAllow);
  976. }
  977. //Break out of Switch
  978. break;
  979. }
  980. }
  981. //
  982. // HandleListClick decides which boxes should be checked and
  983. // unchecked, however, we can't rely only on that to generate
  984. // ACLs (we used to). Suppose the principal has Full Control and
  985. // the user unchecks "Delete" which is a single bit. If there is
  986. // no checkbox corresponding to "Full Control minus Delete" then
  987. // the principal would also lose other bits, such as WRITE_DAC.
  988. //
  989. // So let HandleListClick do its thing. Then remove permission
  990. // bits according to what was checked or unchecked.
  991. //
  992. // But wait, there's more. Removing permission bits turns off
  993. // too much. For example, if the principal has Full Control and
  994. // the user turns off Full Control, then the principal ends up
  995. // with nothing, even though HandleListClick leaves Modify
  996. // checked.
  997. //
  998. // So after removing what was just (un)checked, build new
  999. // permissions from what is still checked and add them.
  1000. //
  1001. // This yields the correct results, and also keeps the principal
  1002. // up-to-date so we don't need to call CommitCurrent anywhere else.
  1003. //
  1004. // Raid 260952
  1005. //
  1006. //HandleListClick decides which boxes should be checked and unchecked.
  1007. //If FullControl was intially Checked, we uncheck Read, Full Control is
  1008. //also unchecked. If a checkbox was intially checked and unchecked in
  1009. //HandleListClick, its added to h[Allow/Deny]UncheckedAccess list.
  1010. //Permission corresponding to these checkboxes is removed.
  1011. // Check/uncheck appropriate boxes in both columns
  1012. HDSA hAllowUncheckedAccess = NULL;
  1013. HDSA hDenyUncheckedAccess = NULL;
  1014. //Does appropriate check-uncheck.
  1015. HandleListClick((PNM_CHECKLIST)pnmh,
  1016. SI_PAGE_PERM,
  1017. m_siObjectInfo.dwFlags & SI_CONTAINER,
  1018. &hAllowUncheckedAccess,
  1019. &hDenyUncheckedAccess,
  1020. m_bCustomPermission);
  1021. pPrincipal = (LPPRINCIPAL)GetSelectedItemData(GetDlgItem(hDlg, IDC_SPP_PRINCIPALS), &iIndex);
  1022. if (pPrincipal)
  1023. {
  1024. PNM_CHECKLIST pnmc = (PNM_CHECKLIST)pnmh;
  1025. PSI_ACCESS pAccess = (PSI_ACCESS)pnmc->dwItemData;
  1026. PERMISSION perm = { pAccess->mask, 0, 0 };
  1027. //If we uncheck Allow Read, Allow Read Checkbox goes into HandleListClick as
  1028. //unchecked and is not in hAllowUncheckedAccess. Perm Corresponding to it
  1029. //especially removed.
  1030. if(!(pnmc->dwState & CLST_CHECKED))
  1031. {
  1032. // Which column was clicked?
  1033. BOOL bRemoveFromAllow = (1 == pnmc->iSubItem); // 1 = Allow, 2 = Deny
  1034. if (pAccess->pguid)
  1035. perm.guid = *pAccess->pguid;
  1036. if (m_siObjectInfo.dwFlags & SI_CONTAINER)
  1037. perm.dwFlags = pAccess->dwFlags & VALID_INHERIT_FLAGS;
  1038. pPrincipal->RemovePermission(bRemoveFromAllow, &perm);
  1039. }
  1040. if( hAllowUncheckedAccess )
  1041. {
  1042. UINT cItems = DSA_GetItemCount(hAllowUncheckedAccess);
  1043. PERMISSION permTemp;
  1044. while (cItems)
  1045. {
  1046. --cItems;
  1047. DSA_GetItem(hAllowUncheckedAccess, cItems, &pAccess);
  1048. permTemp.mask = pAccess->mask;
  1049. if (m_siObjectInfo.dwFlags & SI_CONTAINER)
  1050. permTemp.dwFlags = pAccess->dwFlags & VALID_INHERIT_FLAGS;
  1051. if( pAccess->pguid )
  1052. permTemp.guid = *pAccess->pguid;
  1053. pPrincipal->RemovePermission(TRUE, &permTemp);
  1054. }
  1055. DSA_Destroy(hAllowUncheckedAccess);
  1056. }
  1057. if( hDenyUncheckedAccess )
  1058. {
  1059. UINT cItems = DSA_GetItemCount(hDenyUncheckedAccess);
  1060. PERMISSION permTemp;
  1061. PSI_ACCESS pAccess2 = NULL;
  1062. while (cItems)
  1063. {
  1064. --cItems;
  1065. DSA_GetItem(hDenyUncheckedAccess, cItems, &pAccess2);
  1066. permTemp.mask = pAccess2->mask;
  1067. if (m_siObjectInfo.dwFlags & SI_CONTAINER)
  1068. permTemp.dwFlags = pAccess2->dwFlags & VALID_INHERIT_FLAGS;
  1069. if( pAccess2->pguid )
  1070. permTemp.guid = *pAccess2->pguid;
  1071. pPrincipal->RemovePermission(FALSE, &permTemp);
  1072. }
  1073. DSA_Destroy(hDenyUncheckedAccess);
  1074. }
  1075. }
  1076. SetDirty(hDlg);
  1077. // Add perms according to what is still checked. This is required, since
  1078. // when i uncheck Read, full control is also unchecked and permission corresponding to
  1079. // it is removed. This will remove Write also, though its still checked.
  1080. //CommitCurrent will add permission for checkboxes which are still checked.
  1081. CommitCurrent(hDlg, iIndex);
  1082. //Here i should add additional list to main list, but no need to rebuild addtional list
  1083. // Reset the "There is more stuff" message
  1084. OnSelChange(hDlg, FALSE);
  1085. }
  1086. break;
  1087. case CLN_GETCOLUMNDESC:
  1088. {
  1089. PNM_CHECKLIST pnmc = (PNM_CHECKLIST)pnmh;
  1090. GetDlgItemText(hDlg,
  1091. IDC_SPP_ALLOW - 1 + pnmc->iSubItem,
  1092. pnmc->pszText,
  1093. pnmc->cchTextMax);
  1094. }
  1095. break;
  1096. case PSN_APPLY:
  1097. OnApply(hDlg, (BOOL)(((LPPSHNOTIFY)pnmh)->lParam));
  1098. break;
  1099. default:
  1100. TraceLeaveValue(FALSE); // message not handled
  1101. }
  1102. TraceLeaveValue(TRUE); // message handled
  1103. }
  1104. BOOL
  1105. CheckPermissions(HWND hwndList,
  1106. CPermissionSet &PermSet,
  1107. WORD wColumn,
  1108. BOOL bDisabled,
  1109. BOOL bInheritFlags,
  1110. BOOL bCustom, //Does Custom Checkbox exist?
  1111. BOOL bClearCustom,
  1112. HDSA hAdditional )//Clear Custom Permissions?
  1113. {
  1114. UINT cRights = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  1115. //Custom Checkbox is handled separately the end.
  1116. if( bCustom )
  1117. --cRights;
  1118. UINT cAces = PermSet.GetPermCount();
  1119. BOOL bMorePresent = FALSE;
  1120. WORD wOtherColumn;
  1121. DWORD dwState = CLST_CHECKED;
  1122. TraceEnter(TRACE_MISC, "CheckPermissions");
  1123. HDSA hPermList; //Temp List of PPERMISSION pointers
  1124. if( bClearCustom )
  1125. {
  1126. hPermList = DSA_Create(SIZEOF(PPERMISSION), 4);
  1127. if (hPermList == NULL)
  1128. {
  1129. TraceMsg("DSA_Create failed");
  1130. TraceLeaveValue(FALSE);
  1131. }
  1132. }
  1133. if (wColumn == 1)
  1134. wOtherColumn = 2;
  1135. else
  1136. wOtherColumn = 1;
  1137. if (bDisabled)
  1138. dwState |= CLST_DISABLED;
  1139. for (UINT j = 0; j < cAces; j++)
  1140. {
  1141. ACCESS_MASK maskChecked = 0;
  1142. PPERMISSION pPerm = PermSet[j];
  1143. BOOL bIsNullGuid = IsNullGUID(&pPerm->guid);
  1144. //Igonre custom here
  1145. for (UINT i = 0; i < cRights ; i++)
  1146. {
  1147. PSI_ACCESS pAccess = (PSI_ACCESS)SendMessage(hwndList,
  1148. CLM_GETITEMDATA,
  1149. i,
  1150. 0);
  1151. //
  1152. // The below expression tests to see if this access mask enables
  1153. // this access "rights" line. It could have more bits enabled, but
  1154. // as long as it has all of the ones from the pAccess[i].mask then
  1155. // it effectively has that option enabled.
  1156. //
  1157. if ( (pPerm->mask & pAccess->mask) == pAccess->mask &&
  1158. (bIsNullGuid || IsSameGUID(&pPerm->guid, pAccess->pguid)) )
  1159. {
  1160. DWORD dwStateCompare;
  1161. //
  1162. // Next, check the inherit flags.
  1163. //
  1164. if (bInheritFlags)
  1165. {
  1166. DWORD dwCommonFlags = pPerm->dwFlags & pAccess->dwFlags;
  1167. //
  1168. // This expression tests to see whether the ACE applies
  1169. // to all objects that this access rights line applies to.
  1170. // The ACE must have at least as many of (CONTAINER_INHERIT_ACE,
  1171. // OBJECT_INHERIT_ACE) turned on as the rights line, and
  1172. // if the ACE has INHERIT_ONLY_ACE, then so must the rights line.
  1173. //
  1174. if (!((dwCommonFlags & ACE_INHERIT_ALL) == (pAccess->dwFlags & ACE_INHERIT_ALL)
  1175. && (dwCommonFlags & INHERIT_ONLY_ACE) == (pPerm->dwFlags & INHERIT_ONLY_ACE)))
  1176. continue;
  1177. }
  1178. // The bits say it's checked. We may not actually check the box
  1179. // below, but for other reasons. In any case, we don't want the
  1180. // "Additional stuff is here but I can't show it" message to
  1181. // display because of this perm.
  1182. maskChecked |= pAccess->mask;
  1183. //
  1184. // Ok, the bits say that this box should be checked, but
  1185. // if the other column is already checked and has the same
  1186. // enabled/disabled state, then we don't check this one.
  1187. // This keeps us from having both Allow and Deny checked &
  1188. // enabled on the same line (nonsense) or checked & disabled
  1189. // on the same line (both inherited; we must show both as
  1190. // Allow Inherited can preceede Deny Inherited and we
  1191. // don't know the order at this point.
  1192. //
  1193. if( !(pPerm->dwFlags & INHERITED_ACE) )
  1194. {
  1195. dwStateCompare = (DWORD)SendMessage(hwndList,
  1196. CLM_GETSTATE,
  1197. MAKELONG((WORD)i, wOtherColumn),
  1198. 0);
  1199. if ((dwStateCompare & CLST_CHECKED) &&
  1200. ((dwStateCompare & CLST_DISABLED) == (dwState & CLST_DISABLED)))
  1201. continue;
  1202. }
  1203. //
  1204. // Next, see if the box is already checked. If so, leave it
  1205. // alone. Note that we don't compare the enabled/disabled
  1206. // state. The effect here is that the first check wins.
  1207. // Raid 326000
  1208. //
  1209. dwStateCompare = (DWORD)SendMessage(hwndList,
  1210. CLM_GETSTATE,
  1211. MAKELONG((WORD)i, wColumn),
  1212. 0);
  1213. if (dwStateCompare & CLST_CHECKED)
  1214. continue;
  1215. //
  1216. // Finally, check the box.
  1217. //
  1218. SendMessage(hwndList,
  1219. CLM_SETSTATE,
  1220. MAKELONG((WORD)i, wColumn),
  1221. dwState);
  1222. }
  1223. }
  1224. if( bClearCustom )
  1225. {
  1226. //If an ace don't check anyof the checkboxes,( i.e. maskchecked = 0 ),
  1227. //it should be removed when custom is unchecked.
  1228. if( !maskChecked )
  1229. {
  1230. DSA_AppendItem(hPermList, &pPerm);
  1231. maskChecked = pPerm->mask; //this is done to make sure maskchecked is false
  1232. }
  1233. //Ace checks some checkbox ( maskChecked), so it mask should be maskChecked
  1234. else
  1235. pPerm->mask = maskChecked;
  1236. }
  1237. // Does this ACE have bits that aren't shown on this dialog?
  1238. if (maskChecked != pPerm->mask)
  1239. {
  1240. ACCESS_MASK maskTemp = 0;
  1241. //Add this ace to the list of additional aces,
  1242. //but only the bits which are additional
  1243. if( hAdditional )
  1244. {
  1245. maskTemp = pPerm->mask;
  1246. pPerm->mask &= ~maskChecked;
  1247. DSA_AppendItem(hAdditional, pPerm);
  1248. pPerm->mask = maskTemp;
  1249. }
  1250. bMorePresent = TRUE;
  1251. }
  1252. }
  1253. if( bClearCustom )
  1254. {
  1255. UINT cItems = DSA_GetItemCount(hPermList);
  1256. PPERMISSION pTemp = NULL;
  1257. while (cItems)
  1258. {
  1259. --cItems;
  1260. DSA_GetItem(hPermList, cItems, &pTemp);
  1261. //Removes only the permission which match its inheritance flag, not others.
  1262. //For example it this permission is read applied to subobjects and hence appear as
  1263. //custom permission. On clearing the custom checkbox, only read permission applied to
  1264. //subobjects should go, not the read permission applied to this object ( and/or subobjects)
  1265. // which can be shown in other checkboxes.
  1266. PermSet.RemovePermission(pTemp, TRUE);
  1267. --cAces;
  1268. }
  1269. PermSet.ResetAdvanced();
  1270. DSA_Destroy(hPermList);
  1271. }
  1272. // Does this permission set have "advanced" ACEs that aren't shown
  1273. // on this dialog?
  1274. if (!bMorePresent && cAces != PermSet.GetPermCount(TRUE))
  1275. bMorePresent = TRUE;
  1276. if( bMorePresent && bCustom )
  1277. CheckCustom( hwndList, wColumn, dwState );
  1278. TraceLeaveValue(bMorePresent);
  1279. }
  1280. void
  1281. CPermPage::OnSelChange(HWND hDlg, BOOL bClearFirst, BOOL bClearCustomAllow, BOOL bClearCustomDeny)
  1282. {
  1283. BOOL bDisabled = m_siObjectInfo.dwFlags & SI_READONLY;
  1284. TraceEnter(TRACE_PERMPAGE, "CPermPage::OnSelChange");
  1285. TraceAssert(hDlg != NULL);
  1286. //
  1287. // If the principal list is empty or there is no selection, then we need
  1288. // to disable all of the controls that operate on items in the listbox.
  1289. //
  1290. HWND hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  1291. TraceAssert(hwndList != NULL);
  1292. // Get the selected principal
  1293. LPPRINCIPAL pPrincipal = (LPPRINCIPAL)GetSelectedItemData(hwndList, NULL);
  1294. // Enable/disable the other controls
  1295. if (!bDisabled)
  1296. EnablePrincipalControls(hDlg, pPrincipal != NULL);
  1297. //Change the permission label to reflect the new User/Group
  1298. SetPermLabelText(hDlg);
  1299. if (pPrincipal == NULL)
  1300. TraceLeaveVoid(); // no selection or empty list
  1301. //
  1302. // Check/uncheck the permission boxes
  1303. //
  1304. hwndList = GetDlgItem(hDlg, IDC_SPP_PERMS);
  1305. TraceAssert(hwndList != NULL);
  1306. if (bClearFirst)
  1307. {
  1308. // First need to uncheck everything
  1309. ClearPermissions(hwndList, bDisabled);
  1310. }
  1311. BOOL bIsContainer = m_siObjectInfo.dwFlags & SI_CONTAINER;
  1312. BOOL bMorePresent = FALSE;
  1313. //Clear the Custom Checkboxes. This is the only place where Custom Checkbox is cleared
  1314. if(m_bCustomPermission)
  1315. {
  1316. ClearCustom(hwndList,1);
  1317. ClearCustom(hwndList,2);
  1318. }
  1319. if( !pPrincipal->m_hAdditionalAllow )
  1320. {
  1321. pPrincipal->m_hAdditionalAllow = DSA_Create(SIZEOF(PERMISSION), 4);
  1322. if (pPrincipal->m_hAdditionalAllow == NULL)
  1323. {
  1324. TraceMsg("DSA_Create failed");
  1325. TraceLeaveVoid();
  1326. }
  1327. }
  1328. if( !pPrincipal->m_hAdditionalDeny )
  1329. {
  1330. pPrincipal->m_hAdditionalDeny = DSA_Create(SIZEOF(PERMISSION), 4);
  1331. if (pPrincipal->m_hAdditionalDeny == NULL)
  1332. {
  1333. TraceMsg("DSA_Create failed");
  1334. TraceLeaveVoid();
  1335. }
  1336. }
  1337. UINT cItems = DSA_GetItemCount(pPrincipal->m_hAdditionalAllow);
  1338. PPERMISSION pPermTemp;
  1339. while (cItems)
  1340. {
  1341. --cItems;
  1342. pPermTemp = (PPERMISSION)DSA_GetItemPtr(pPrincipal->m_hAdditionalAllow, cItems );
  1343. if(pPermTemp)
  1344. pPrincipal->AddPermission(TRUE, pPermTemp);
  1345. }
  1346. DSA_DeleteAllItems(pPrincipal->m_hAdditionalAllow);
  1347. cItems = DSA_GetItemCount(pPrincipal->m_hAdditionalDeny);
  1348. while (cItems)
  1349. {
  1350. --cItems;
  1351. pPermTemp = (PPERMISSION)DSA_GetItemPtr(pPrincipal->m_hAdditionalDeny, cItems );
  1352. if(pPermTemp)
  1353. pPrincipal->AddPermission(FALSE, pPermTemp);
  1354. }
  1355. DSA_DeleteAllItems(pPrincipal->m_hAdditionalDeny);
  1356. bMorePresent |= CheckPermissions(hwndList,
  1357. pPrincipal->m_permDeny,
  1358. 2,
  1359. bDisabled,
  1360. bIsContainer,
  1361. m_bCustomPermission,
  1362. bClearCustomDeny,
  1363. pPrincipal->m_hAdditionalDeny);
  1364. bMorePresent |= CheckPermissions(hwndList,
  1365. pPrincipal->m_permAllow,
  1366. 1,
  1367. bDisabled,
  1368. bIsContainer,
  1369. m_bCustomPermission,
  1370. bClearCustomAllow,
  1371. pPrincipal->m_hAdditionalAllow);
  1372. bMorePresent |= CheckPermissions(hwndList,
  1373. pPrincipal->m_permInheritedDeny,
  1374. 2,
  1375. TRUE,
  1376. bIsContainer,
  1377. m_bCustomPermission,
  1378. FALSE,
  1379. NULL);
  1380. bMorePresent |= CheckPermissions(hwndList,
  1381. pPrincipal->m_permInheritedAllow,
  1382. 1,
  1383. TRUE,
  1384. bIsContainer,
  1385. m_bCustomPermission,
  1386. FALSE,NULL);
  1387. if (m_siObjectInfo.dwFlags & SI_ADVANCED)
  1388. {
  1389. ShowWindow(GetDlgItem(hDlg, IDC_SPP_MORE_MSG),
  1390. (bMorePresent ? SW_SHOW : SW_HIDE));
  1391. }
  1392. else if (bMorePresent)
  1393. {
  1394. TraceMsg("Ignoring unknown permissions");
  1395. }
  1396. TraceLeaveVoid();
  1397. }
  1398. void
  1399. CPermPage::OnApply(HWND hDlg, BOOL bClose)
  1400. {
  1401. HRESULT hr = S_OK;
  1402. PSECURITY_DESCRIPTOR pSD;
  1403. TraceEnter(TRACE_PERMPAGE, "CPermPage::OnApply");
  1404. // Build a new DACL without the inherited ACEs.
  1405. if (m_fPageDirty && SUCCEEDED(hr = BuildDacl(hDlg, &pSD, FALSE)) && (hr != S_FALSE))
  1406. {
  1407. PISECURITY_DESCRIPTOR psd = (PISECURITY_DESCRIPTOR)pSD;
  1408. DWORD dwWarning = 0;
  1409. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
  1410. TraceAssert(pSD != NULL);
  1411. TraceAssert(m_psi != NULL);
  1412. // Check for Deny ACEs in the ACL
  1413. if (!m_bWasDenyAcl)
  1414. {
  1415. DWORD dwFullControl = GENERIC_ALL;
  1416. UCHAR aceFlags = 0;
  1417. m_psi->MapGeneric(NULL, &aceFlags, &dwFullControl);
  1418. if (IsDenyACL(psd->Dacl,
  1419. (psd->Control & SE_DACL_PROTECTED),
  1420. dwFullControl,
  1421. &dwWarning))
  1422. {
  1423. TraceAssert(dwWarning != 0);
  1424. // Warn the user about Deny ACEs
  1425. if (IDNO == MsgPopup(hDlg,
  1426. MAKEINTRESOURCE(dwWarning),
  1427. MAKEINTRESOURCE(IDS_SECURITY),
  1428. MB_YESNO | MB_ICONWARNING,
  1429. ::hModule,
  1430. m_siObjectInfo.pszObjectName))
  1431. {
  1432. hr = S_FALSE;
  1433. }
  1434. }
  1435. }
  1436. if (S_FALSE != hr)
  1437. {
  1438. if(!IsAclBloated(hDlg, si, pSD, m_cInheritableAces, m_siObjectInfo.dwFlags & SI_EDIT_PROPERTIES))
  1439. {
  1440. // Apply the new security descriptor on the object
  1441. hr = m_psi->SetSecurity(si, pSD);
  1442. }
  1443. else
  1444. hr = S_FALSE;
  1445. }
  1446. if (S_OK == hr)
  1447. {
  1448. LocalFree(pSD);
  1449. pSD = NULL;
  1450. m_fPageDirty = FALSE;
  1451. if (!bClose)
  1452. {
  1453. //
  1454. // Read the new DACL back from the object. This ensures that we
  1455. // have the "real" current DACL in case it was modified by the
  1456. // object. For example, inherited aces may have been added.
  1457. //
  1458. // This also resets the dialog to the initial state if the
  1459. // user chose No in the confirmation dialog above.
  1460. //
  1461. if (SUCCEEDED(m_psi->GetSecurity(DACL_SECURITY_INFORMATION, &pSD, FALSE)))
  1462. SetDacl(hDlg, pSD);
  1463. }
  1464. }
  1465. else if (S_FALSE == hr)
  1466. {
  1467. // S_FALSE is silent failure (the client should put up UI
  1468. // during SetSecurity before returning S_FALSE).
  1469. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
  1470. }
  1471. if (pSD != NULL)
  1472. LocalFree(pSD);
  1473. }
  1474. if (FAILED(hr))
  1475. {
  1476. // Tell the user there was a problem. If they choose to cancel
  1477. // and the dialog is closing, do nothing (let the dialog close).
  1478. // Otherwise, tell the property sheet that we had a problem.
  1479. if (IDCANCEL != SysMsgPopup(hDlg,
  1480. MAKEINTRESOURCE(IDS_PERM_WRITE_FAILED),
  1481. MAKEINTRESOURCE(IDS_SECURITY),
  1482. (bClose ? MB_RETRYCANCEL : MB_OK) | MB_ICONERROR,
  1483. ::hModule,
  1484. hr,
  1485. m_siObjectInfo.pszObjectName))
  1486. {
  1487. // Return PSNRET_INVALID to abort the Apply and cause the sheet to
  1488. // select this page as the active page.
  1489. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
  1490. }
  1491. }
  1492. TraceLeaveVoid();
  1493. }
  1494. /*-----------------------------------------------------------------------------
  1495. / BuildDacl
  1496. / -------
  1497. / Convert the listbox entries into SD. If the size of security descriptor
  1498. / is more than Max allowed shows a dialog box.
  1499. / ppSD can be NULL for the cases where we want to verify if the SD size is
  1500. / not execeeding the max size.
  1501. /
  1502. /----------------------------------------------------------------------------*/
  1503. HRESULT
  1504. CPermPage::BuildDacl(HWND hDlg,
  1505. PSECURITY_DESCRIPTOR *ppSD,
  1506. BOOL fIncludeInherited)
  1507. {
  1508. PISECURITY_DESCRIPTOR pSD;
  1509. ULONG nAclSize;
  1510. LPPRINCIPAL pPrincipal;
  1511. int cPrincipals = 0;
  1512. DWORD dwFlags;
  1513. int i, j;
  1514. HCURSOR hcur = NULL;
  1515. HWND hwndList = NULL;
  1516. LV_ITEM lvItem;
  1517. lvItem.mask = LVIF_PARAM;
  1518. lvItem.iSubItem = 0;
  1519. static DWORD dwCanonicalFlags[] =
  1520. {
  1521. ACL_DENY | ACL_NONOBJECT,
  1522. ACL_DENY | ACL_OBJECT,
  1523. ACL_ALLOW | ACL_NONOBJECT,
  1524. ACL_ALLOW | ACL_OBJECT
  1525. };
  1526. TraceEnter(TRACE_PERMPAGE, "CPermPage::BuildDacl");
  1527. TraceAssert(hDlg != NULL);
  1528. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1529. //
  1530. // Estimate the size of the buffer necessary to build the
  1531. // Security Descriptor.
  1532. //
  1533. hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  1534. cPrincipals = ListView_GetItemCount(hwndList);
  1535. dwFlags = ACL_NONINHERITED;
  1536. if (fIncludeInherited)
  1537. dwFlags |= ACL_INHERITED;
  1538. WORD nMaxAclSize = 0xffff;
  1539. nAclSize = SIZEOF(ACL);
  1540. for (i = 0; i < cPrincipals; i++)
  1541. {
  1542. lvItem.iItem = i;
  1543. if (ListView_GetItem(hwndList, &lvItem))
  1544. {
  1545. pPrincipal = (LPPRINCIPAL)lvItem.lParam;
  1546. nAclSize += pPrincipal->GetAclLength(dwFlags);
  1547. }
  1548. if(nAclSize > nMaxAclSize)
  1549. {
  1550. //
  1551. //itow converts upto 33 bytes so 34bytes is fine
  1552. //
  1553. WCHAR buffer[34];
  1554. _itow((cPrincipals - i),buffer,10);
  1555. ULONG nMsgId = IDS_ACL_SIZE_ERROR;
  1556. if(!ppSD)
  1557. nMsgId = IDS_ACL_SIZE_ERROR_ADV;
  1558. MsgPopup(hDlg,
  1559. MAKEINTRESOURCE(nMsgId),
  1560. MAKEINTRESOURCE(IDS_SECURITY),
  1561. MB_OK | MB_ICONERROR,
  1562. ::hModule,
  1563. buffer);
  1564. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
  1565. //
  1566. //Do a silent failure since we have already shown the error message
  1567. //
  1568. return S_FALSE;
  1569. }
  1570. }
  1571. if(!ppSD)
  1572. return S_OK;
  1573. *ppSD = NULL;
  1574. //
  1575. // Now that we have the size estimate, allocate the buffer. Note that
  1576. // we allocate enough memory for a self-relative security descriptor, but
  1577. // don't set the SE_SELF_RELATIVE flag in pSD->Control. This lets us
  1578. // use pSD->Dacl, etc. as pointers rather than offsets.
  1579. //
  1580. *ppSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH + nAclSize);
  1581. if (*ppSD == NULL)
  1582. TraceLeaveResult(E_OUTOFMEMORY);
  1583. InitializeSecurityDescriptor(*ppSD, SECURITY_DESCRIPTOR_REVISION);
  1584. pSD = (PISECURITY_DESCRIPTOR)*ppSD;
  1585. //
  1586. // Finally, build the security descriptor
  1587. //
  1588. pSD->Control |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERIT_REQ
  1589. | (m_wSDControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
  1590. if (nAclSize > 0)
  1591. {
  1592. pSD->Dacl = (PACL)(pSD + 1);
  1593. pSD->Dacl->AclRevision = ACL_REVISION;
  1594. pSD->Dacl->AclSize = (WORD)nAclSize;
  1595. pSD->Dacl->AceCount = 0;
  1596. PACE_HEADER pAcePos = (PACE_HEADER)FirstAce(pSD->Dacl);
  1597. DWORD dwExtraFlags = fIncludeInherited ? 0 : ACL_CHECK_CREATOR;
  1598. // Build the DACL in the following order:
  1599. // Deny
  1600. // Allow
  1601. // Inherited Deny
  1602. // Inherited Allow
  1603. for (j = 0; j < ARRAYSIZE(dwCanonicalFlags); j++)
  1604. {
  1605. for (i = 0; i < cPrincipals; i++)
  1606. {
  1607. lvItem.iItem = i;
  1608. if (ListView_GetItem(hwndList, &lvItem))
  1609. {
  1610. pPrincipal = (LPPRINCIPAL)lvItem.lParam;
  1611. pPrincipal->AppendToAcl(pSD->Dacl,
  1612. ACL_NONINHERITED | dwCanonicalFlags[j] | dwExtraFlags,
  1613. &pAcePos);
  1614. }
  1615. }
  1616. }
  1617. if (fIncludeInherited)
  1618. {
  1619. for (j = 0; j < ARRAYSIZE(dwCanonicalFlags); j++)
  1620. {
  1621. for (i = 0; i < cPrincipals; i++)
  1622. {
  1623. lvItem.iItem = i;
  1624. if (ListView_GetItem(hwndList, &lvItem))
  1625. {
  1626. pPrincipal = (LPPRINCIPAL)lvItem.lParam;
  1627. pPrincipal->AppendToAcl(pSD->Dacl,
  1628. ACL_INHERITED | dwCanonicalFlags[j] | dwExtraFlags,
  1629. &pAcePos);
  1630. }
  1631. }
  1632. }
  1633. }
  1634. // Set accurate size information for the ACL
  1635. nAclSize = (ULONG)((PBYTE)pAcePos - (PBYTE)pSD->Dacl);
  1636. TraceAssert(nAclSize >= SIZEOF(ACL));
  1637. TraceAssert(pSD->Dacl->AclSize >= nAclSize);
  1638. if (pSD->Dacl->AclSize > nAclSize)
  1639. pSD->Dacl->AclSize = (WORD)nAclSize;
  1640. TraceAssert(m_psi2 || IsDACLCanonical(pSD->Dacl));
  1641. }
  1642. TraceAssert(pSD && IsValidSecurityDescriptor(pSD));
  1643. SetCursor(hcur);
  1644. TraceLeaveResult(S_OK);
  1645. }
  1646. HRESULT
  1647. CPermPage::SetDacl(HWND hDlg,
  1648. PSECURITY_DESCRIPTOR pSD,
  1649. BOOL bDirty)
  1650. {
  1651. HRESULT hr = S_OK;
  1652. PACL pAcl = NULL;
  1653. PACL paclAllowAll = NULL;
  1654. BOOL bDefaulted;
  1655. BOOL bPresent;
  1656. SECURITY_DESCRIPTOR_CONTROL wSDControl = 0;
  1657. PSECURITY_DESCRIPTOR pSDDefault = NULL;
  1658. DWORD dwRevision;
  1659. TraceEnter(TRACE_PERMPAGE, "CPermPage::SetDacl");
  1660. TraceAssert(hDlg != NULL);
  1661. if (pSD != NULL && !IsValidSecurityDescriptor(pSD))
  1662. TraceLeaveResult(E_INVALIDARG);
  1663. if (pSD != NULL)
  1664. GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision);
  1665. // Save the DACL protection and auto-inherited bits
  1666. m_wSDControl &= ~(SE_DACL_DEFAULTED | SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED);
  1667. m_wSDControl |= (wSDControl & (SE_DACL_DEFAULTED | SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
  1668. // Get a pointer to the new DACL
  1669. if (pSD != NULL)
  1670. GetSecurityDescriptorDacl(pSD, &bPresent, &pAcl, &bDefaulted);
  1671. if (!(m_siObjectInfo.dwFlags & SI_READONLY))
  1672. {
  1673. // Check for canonical ordering (Deny, Allow, Inherited Deny, Inherited Allow)
  1674. if ((m_psi2 && !m_psi2->IsDaclCanonical(pAcl))
  1675. || (!m_psi2 && !IsDACLCanonical(pAcl)))
  1676. {
  1677. TraceMsg("DACL not in canonical order!");
  1678. // Ask the user whether to canonicalize the DACL or
  1679. // blow it away completely.
  1680. if (IDCANCEL == MsgPopup(hDlg,
  1681. MAKEINTRESOURCE(IDS_PERM_NOT_CANONICAL),
  1682. MAKEINTRESOURCE(IDS_SECURITY),
  1683. MB_OKCANCEL | MB_ICONWARNING,
  1684. ::hModule,
  1685. m_siObjectInfo.pszObjectName))
  1686. {
  1687. // Blow it away and start over.
  1688. pAcl = NULL;
  1689. // Does the caller support a default ACL? If so, get it now.
  1690. if (m_siObjectInfo.dwFlags & SI_RESET)
  1691. {
  1692. hr = m_psi->GetSecurity(DACL_SECURITY_INFORMATION,
  1693. &pSDDefault,
  1694. TRUE);
  1695. if (SUCCEEDED(hr) && pSDDefault != NULL)
  1696. {
  1697. // Save the DACL control bits
  1698. GetSecurityDescriptorControl(pSDDefault, &wSDControl, &dwRevision);
  1699. m_wSDControl &= ~(SE_DACL_DEFAULTED | SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED);
  1700. m_wSDControl |= SE_DACL_DEFAULTED | (wSDControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
  1701. // Get a pointer to the new DACL
  1702. GetSecurityDescriptorDacl(pSDDefault, &bPresent, &pAcl, &bDefaulted);
  1703. }
  1704. // else go with a NULL DACL
  1705. }
  1706. }
  1707. // else simply continuing and re-saving will
  1708. // cause the DACL to get sorted correctly
  1709. // This causes a PropSheet_Changed notification to be sent below
  1710. bDirty = TRUE;
  1711. }
  1712. }
  1713. m_bWasDenyAcl = FALSE;
  1714. // A NULL ACL implies "Everyone Full control", so
  1715. // create such an ACL here
  1716. if (pAcl == NULL)
  1717. {
  1718. PSID psidWorld = QuerySystemSid(UI_SID_World);
  1719. DWORD dwSidLength = GetLengthSid(psidWorld);
  1720. DWORD dwAclLength = SIZEOF(ACL) + SIZEOF(ACCESS_ALLOWED_ACE)
  1721. - SIZEOF(DWORD) + dwSidLength;
  1722. m_wDaclRevision = ACL_REVISION;
  1723. paclAllowAll = (PACL)LocalAlloc(LPTR, dwAclLength);
  1724. if (paclAllowAll != NULL)
  1725. {
  1726. paclAllowAll->AclRevision = ACL_REVISION;
  1727. paclAllowAll->AclSize = (WORD)dwAclLength;
  1728. #if 0 //(_WIN32_WINNT >= 0x0500)
  1729. paclAllowAll->AceCount = 0;
  1730. AddAccessAllowedAceEx(paclAllowAll,
  1731. ACL_REVISION,
  1732. ACE_INHERIT_ALL,
  1733. GENERIC_ALL,
  1734. psidWorld);
  1735. #else
  1736. paclAllowAll->AceCount = 1;
  1737. PACE_HEADER pAce = (PACE_HEADER)FirstAce(paclAllowAll);
  1738. pAce->AceType = ACCESS_ALLOWED_ACE_TYPE;
  1739. pAce->AceFlags = ACE_INHERIT_ALL;
  1740. pAce->AceSize = (WORD)dwAclLength - SIZEOF(ACL);
  1741. ((PACCESS_ALLOWED_ACE)pAce)->Mask = GENERIC_ALL;
  1742. CopyMemory(&((PACCESS_ALLOWED_ACE)pAce)->SidStart, psidWorld, dwSidLength);
  1743. #endif
  1744. pAcl = paclAllowAll;
  1745. }
  1746. }
  1747. else
  1748. {
  1749. DWORD dwFullControl = GENERIC_ALL;
  1750. UCHAR aceFlags = 0;
  1751. m_psi->MapGeneric(NULL, &aceFlags, &dwFullControl);
  1752. if (IsDenyACL(pAcl,
  1753. (m_wSDControl & SE_DACL_PROTECTED),
  1754. dwFullControl,
  1755. NULL))
  1756. {
  1757. // Already have Deny ACEs, don't bother warning again later.
  1758. m_bWasDenyAcl = TRUE;
  1759. }
  1760. }
  1761. // Reset the list of principals
  1762. InitPrincipalList(hDlg, pAcl);
  1763. //Get the count of inheritable aces
  1764. m_cInheritableAces = GetCountOfInheritableAces(pAcl);
  1765. // If there aren't any entries, fake a sel change to update
  1766. // (i.e. disable) the other controls.
  1767. if (pAcl == NULL || pAcl->AceCount == 0)
  1768. OnSelChange(hDlg);
  1769. if (bDirty)
  1770. SetDirty(hDlg, TRUE);
  1771. if (paclAllowAll != NULL)
  1772. LocalFree(paclAllowAll);
  1773. if (pSDDefault != NULL)
  1774. LocalFree(pSDDefault);
  1775. TraceLeaveResult(hr);
  1776. }
  1777. void
  1778. CPermPage::OnAddPrincipal(HWND hDlg)
  1779. {
  1780. PUSER_LIST pUserList = NULL;
  1781. TraceEnter(TRACE_PERMPAGE, "CPermPage::OnAddPrincipal");
  1782. TraceAssert(hDlg != NULL);
  1783. if (S_OK == GetUserGroup(hDlg, TRUE, &pUserList))
  1784. {
  1785. PUSER_INFO pUserInfo;
  1786. DWORD i;
  1787. BOOL fPageModified = FALSE;
  1788. int iItem = -1;
  1789. TraceAssert(NULL != pUserList);
  1790. HWND hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  1791. TraceAssert(hwndList != NULL);
  1792. for (i = 0; i < pUserList->cUsers; i++)
  1793. {
  1794. int cItems;
  1795. LV_ITEM lvItem;
  1796. LPPRINCIPAL pPrincipal;
  1797. BYTE buffer[SIZEOF(KNOWN_OBJECT_ACE) + SIZEOF(GUID)];
  1798. PACE_HEADER pAce = (PACE_HEADER)buffer;
  1799. pUserInfo = &pUserList->rgUsers[i];
  1800. iItem = -1;
  1801. // Check whether the new principal is already in our list.
  1802. // If so, don't add it again.
  1803. cItems = ListView_GetItemCount(hwndList);
  1804. lvItem.iSubItem = 0;
  1805. lvItem.mask = LVIF_PARAM;
  1806. while (cItems > 0)
  1807. {
  1808. LPPRINCIPAL pPrincipal2 = NULL;
  1809. --cItems;
  1810. lvItem.iItem = cItems;
  1811. ListView_GetItem(hwndList, &lvItem);
  1812. pPrincipal2 = (LPPRINCIPAL)lvItem.lParam;
  1813. if (EqualSid(pPrincipal2->GetSID(), pUserInfo->pSid))
  1814. {
  1815. iItem = lvItem.iItem;
  1816. break;
  1817. }
  1818. }
  1819. // Did we find it?
  1820. if (iItem != -1)
  1821. continue;
  1822. // ListView_FindItem failed to find a match. Add a
  1823. // new principal.
  1824. pPrincipal = new CPrincipal(this);
  1825. if (!pPrincipal)
  1826. continue;
  1827. // Initialize principal
  1828. if (!pPrincipal->SetPrincipal(pUserInfo->pSid,
  1829. pUserInfo->SidType,
  1830. pUserInfo->pszName,
  1831. pUserInfo->pszLogonName))
  1832. {
  1833. delete pPrincipal;
  1834. continue;
  1835. }
  1836. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  1837. lvItem.iItem = 0;
  1838. lvItem.iSubItem = 0;
  1839. lvItem.pszText = (LPTSTR)pPrincipal->GetName();
  1840. lvItem.iImage = pPrincipal->GetImageIndex();
  1841. lvItem.lParam = (LPARAM)pPrincipal;
  1842. // Insert principal into list
  1843. iItem = ListView_InsertItem(hwndList, &lvItem);
  1844. if (-1 == iItem)
  1845. {
  1846. delete pPrincipal;
  1847. continue;
  1848. }
  1849. // Add ace with default access
  1850. pAce->AceType = ACCESS_ALLOWED_ACE_TYPE;
  1851. pAce->AceFlags = 0;
  1852. pAce->AceSize = SIZEOF(ACCESS_ALLOWED_ACE);
  1853. ((PACCESS_ALLOWED_ACE)pAce)->Mask = m_pDefaultAccess->mask;
  1854. if (m_siObjectInfo.dwFlags & SI_CONTAINER)
  1855. {
  1856. // Pick up inherit bits from the default access
  1857. pAce->AceFlags = (UCHAR)(m_pDefaultAccess->dwFlags & (VALID_INHERIT_FLAGS & ~INHERITED_ACE));
  1858. //
  1859. // Special case for CreatorOwner/CreatorGroup,
  1860. // which are only useful if inherit bits are set.
  1861. //
  1862. if (IsCreatorSid(pUserInfo->pSid))
  1863. {
  1864. // Make sure it inherits onto something
  1865. if (!(pAce->AceFlags & ACE_INHERIT_ALL))
  1866. pAce->AceFlags = ACE_INHERIT_ALL;
  1867. // It never applies to the current object
  1868. pAce->AceFlags |= INHERIT_ONLY_ACE;
  1869. // Set it up so whoever creates an object
  1870. // gets full control by default
  1871. ((PACCESS_ALLOWED_ACE)pAce)->Mask = GENERIC_ALL;
  1872. }
  1873. }
  1874. if (!IsNullGUID(m_pDefaultAccess->pguid))
  1875. {
  1876. pAce->AceType = ACCESS_ALLOWED_OBJECT_ACE_TYPE;
  1877. pAce->AceSize = SIZEOF(KNOWN_OBJECT_ACE) + SIZEOF(GUID);
  1878. ((PKNOWN_OBJECT_ACE)pAce)->Flags = ACE_OBJECT_TYPE_PRESENT;
  1879. *RtlObjectAceObjectType(pAce) = *m_pDefaultAccess->pguid;
  1880. }
  1881. pPrincipal->AddAce(pAce);
  1882. fPageModified = TRUE;
  1883. }
  1884. // Done with this now
  1885. LocalFree(pUserList);
  1886. if (fPageModified)
  1887. {
  1888. // If we've added items, resize the Name column
  1889. //ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
  1890. SetDirty(hDlg);
  1891. }
  1892. if (iItem != -1)
  1893. {
  1894. // Select the last one inserted.
  1895. SelectListViewItem(hwndList, iItem);
  1896. }
  1897. }
  1898. TraceLeaveVoid();
  1899. }
  1900. void
  1901. CPermPage::OnRemovePrincipal(HWND hDlg)
  1902. {
  1903. HWND hwndList;
  1904. int iIndex;
  1905. LPPRINCIPAL pPrincipal;
  1906. TraceEnter(TRACE_PERMPAGE, "CPermPage::OnRemovePrincipal");
  1907. hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  1908. pPrincipal = (LPPRINCIPAL)GetSelectedItemData(hwndList, &iIndex);
  1909. if (pPrincipal)
  1910. {
  1911. BOOL bDirty = FALSE;
  1912. if (pPrincipal->GetAclLength(ACL_INHERITED) > 0)
  1913. {
  1914. // This principal has inherited ACEs so we can't remove the principal
  1915. // from the list. Instead, simply remove the non-inherited ACEs from
  1916. // the principal.
  1917. if (pPrincipal->GetAclLength(ACL_NONINHERITED) > 0)
  1918. {
  1919. pPrincipal->m_permDeny.Reset();
  1920. pPrincipal->m_permAllow.Reset();
  1921. DSA_DeleteAllItems(pPrincipal->m_hAdditionalAllow);
  1922. DSA_DeleteAllItems(pPrincipal->m_hAdditionalDeny);
  1923. bDirty = TRUE;
  1924. // Update the other controls (this happens automatically in the
  1925. // ListView_DeleteItem case below).
  1926. OnSelChange(hDlg);
  1927. }
  1928. else
  1929. {
  1930. // Notify the user that we can't remove inherited ACEs.
  1931. MsgPopup(hDlg,
  1932. MAKEINTRESOURCE(IDS_PERM_CANT_REMOVE),
  1933. MAKEINTRESOURCE(IDS_SECURITY),
  1934. MB_OK | MB_ICONWARNING,
  1935. ::hModule,
  1936. pPrincipal->GetName());
  1937. }
  1938. }
  1939. else
  1940. {
  1941. ListView_DeleteItem(hwndList, iIndex);
  1942. //
  1943. // If we just removed the only item, move the focus to the Add button
  1944. // (the Remove button will be disabled in OnSelChange).
  1945. //
  1946. int cItems = ListView_GetItemCount(hwndList);
  1947. if (cItems == 0)
  1948. SetFocus(GetDlgItem(hDlg, IDC_SPP_ADD));
  1949. else
  1950. {
  1951. // If we deleted the last one, select the previous one
  1952. if (cItems <= iIndex)
  1953. --iIndex;
  1954. SelectListViewItem(hwndList, iIndex);
  1955. //
  1956. //Key board focus is getting lost at this point
  1957. //set it to REMOVE button.
  1958. //
  1959. SetFocus(GetDlgItem(hDlg, IDC_SPP_REMOVE));
  1960. }
  1961. bDirty = TRUE;
  1962. }
  1963. // Notify the property sheet that we've changed
  1964. if (bDirty)
  1965. SetDirty(hDlg);
  1966. }
  1967. TraceLeaveVoid();
  1968. }
  1969. void
  1970. CPermPage::OnAdvanced(HWND hDlg)
  1971. {
  1972. LPSECURITYINFO psi;
  1973. TraceEnter(TRACE_PERMPAGE, "CPermPage::OnAdvanced");
  1974. //
  1975. //Don't go to Advanced page, if DACL size is more than
  1976. //maximum allowed.
  1977. //
  1978. if (m_fPageDirty && (S_FALSE == BuildDacl(hDlg, NULL, FALSE)))
  1979. TraceLeaveVoid();
  1980. //
  1981. // Create an ISecurityInformation wrapper to give to the advanced
  1982. // dialog. The wrapper intercepts GetSecurity & SetSecurity.
  1983. //
  1984. psi = new CSecurityInfo(this, hDlg);
  1985. if (psi != NULL)
  1986. {
  1987. // Invoke the advanced ACL editor
  1988. EditSecurityEx(hDlg, psi,this, 0);
  1989. psi->Release(); // release initial reference
  1990. }
  1991. else
  1992. {
  1993. MsgPopup(hDlg,
  1994. MAKEINTRESOURCE(IDS_OUT_OF_MEMORY),
  1995. MAKEINTRESOURCE(IDS_SECURITY),
  1996. MB_OK | MB_ICONERROR,
  1997. ::hModule);
  1998. }
  1999. TraceLeaveVoid();
  2000. }
  2001. void
  2002. CPermPage::EnablePrincipalControls(HWND hDlg, BOOL fEnable)
  2003. {
  2004. TraceEnter(TRACE_PERMPAGE, "CPermPage::EnablePrincipalControls");
  2005. EnableWindow(GetDlgItem(hDlg, IDC_SPP_PERMS), fEnable);
  2006. if (!fEnable)
  2007. {
  2008. ShowWindow(GetDlgItem(hDlg, IDC_SPP_MORE_MSG), SW_HIDE);
  2009. }
  2010. else
  2011. {
  2012. #if 0
  2013. LPPRINCIPAL pPrincipal
  2014. = (LPPRINCIPAL)GetSelectedItemData(GetDlgItem(hDlg, IDC_SPP_PRINCIPALS),
  2015. NULL);
  2016. // If the selected principal has only inherited ACEs, then disable
  2017. // the Remove button.
  2018. if (pPrincipal &&
  2019. pPrincipal->GetAclLength(ACL_INHERITED) > 0 &&
  2020. pPrincipal->GetAclLength(ACL_NONINHERITED) == 0)
  2021. {
  2022. fEnable = FALSE;
  2023. }
  2024. #endif
  2025. }
  2026. EnableWindow(GetDlgItem(hDlg, IDC_SPP_REMOVE), fEnable);
  2027. TraceLeaveVoid();
  2028. }
  2029. void
  2030. CPermPage::CommitCurrent(HWND hDlg, int iPrincipal)
  2031. {
  2032. // Commit any outstanding bit changes
  2033. HWND hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  2034. TraceEnter(TRACE_PERMPAGE, "CPermPage::CommitCurrent");
  2035. // If an index isn't provided, get the index of the currently
  2036. // selected principal.
  2037. if (iPrincipal == -1)
  2038. iPrincipal = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
  2039. if (iPrincipal != -1)
  2040. {
  2041. // Get the Principal from the selection.
  2042. LV_ITEM lvItem;
  2043. lvItem.mask = LVIF_PARAM;
  2044. lvItem.iItem = iPrincipal;
  2045. lvItem.iSubItem = 0;
  2046. lvItem.lParam = 0;
  2047. ListView_GetItem(hwndList, &lvItem);
  2048. LPPRINCIPAL pPrincipal = (LPPRINCIPAL)lvItem.lParam;
  2049. if (pPrincipal != NULL)
  2050. {
  2051. // Get new ACEs from the checklist window
  2052. HDPA hAceEntries = DPA_Create(4);
  2053. if (hAceEntries != NULL)
  2054. {
  2055. hwndList = GetDlgItem(hDlg, IDC_SPP_PERMS);
  2056. UINT iCount = GetAcesFromCheckList(hwndList,
  2057. pPrincipal->GetSID(),
  2058. TRUE,
  2059. FALSE,
  2060. 0,
  2061. &GUID_NULL,
  2062. hAceEntries);
  2063. // Merge new ACEs into the principal
  2064. while (iCount != 0)
  2065. {
  2066. --iCount;
  2067. PACE_HEADER pAce = (PACE_HEADER)DPA_FastGetPtr(hAceEntries, iCount);
  2068. // Shouldn't get any inherited ACEs here
  2069. TraceAssert(!(pAce->AceFlags & INHERITED_ACE));
  2070. pPrincipal->AddAce(pAce);
  2071. LocalFree(pAce);
  2072. DPA_DeletePtr(hAceEntries, iCount);
  2073. }
  2074. TraceAssert(DPA_GetPtrCount(hAceEntries) == 0);
  2075. DPA_Destroy(hAceEntries);
  2076. }
  2077. }
  2078. }
  2079. TraceLeaveVoid();
  2080. }
  2081. void
  2082. CPermPage::OnSize(HWND hDlg, DWORD dwSizeType, ULONG /*nWidth*/, ULONG /*nHeight*/)
  2083. {
  2084. RECT rc;
  2085. RECT rcDlg;
  2086. LONG dx;
  2087. LONG dy;
  2088. HWND hwndAdvButton;
  2089. HWND hwndPermList;
  2090. HWND hwndPrincipalList;
  2091. HWND hwndBottom;
  2092. HWND hwnd;
  2093. LONG i;
  2094. TraceEnter(TRACE_PERMPAGE, "CPermPage::OnSize");
  2095. if (dwSizeType != SIZE_RESTORED)
  2096. TraceLeaveVoid();
  2097. hwndPrincipalList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  2098. hwndPermList = GetDlgItem(hDlg, IDC_SPP_PERMS);
  2099. hwndAdvButton = GetDlgItem(hDlg, IDC_SPP_ADVANCED);
  2100. GetClientRect(hDlg, &rcDlg);
  2101. GetWindowRect(hwndPrincipalList, &rc);
  2102. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2); // map from screen to dlg
  2103. InflateRect(&rcDlg, -rc.left, -rc.top); // account for margins
  2104. if (GetWindowLong(hwndAdvButton, GWL_STYLE) & WS_VISIBLE)
  2105. {
  2106. hwndBottom = hwndAdvButton;
  2107. }
  2108. else
  2109. {
  2110. hwndBottom = hwndPermList;
  2111. }
  2112. GetWindowRect(hwndBottom, &rc);
  2113. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2114. dy = rcDlg.bottom - rc.bottom;
  2115. GetWindowRect(hwndPermList, &rc);
  2116. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2117. dx = rcDlg.right - rc.right;
  2118. //
  2119. // Never make things smaller, and only make things
  2120. // bigger if the change is worthwhile.
  2121. //
  2122. dx = max(dx, 0);
  2123. if (dx < 5)
  2124. dx = 0;
  2125. dy = max(dy, 0);
  2126. if (dy < 5)
  2127. dy = 0;
  2128. //
  2129. // Reposition and/or resize all controls
  2130. //
  2131. if (dx > 0 || dy > 0)
  2132. {
  2133. // Add, Remove, Reset buttons
  2134. for (i = IDC_SPP_ADD; i <= IDC_SPP_REMOVE; i++)
  2135. {
  2136. hwnd = GetDlgItem(hDlg, i);
  2137. GetWindowRect(hwnd, &rc);
  2138. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2139. SetWindowPos(hwnd,
  2140. NULL,
  2141. rc.left + dx,
  2142. rc.top + dy/2,
  2143. 0,
  2144. 0,
  2145. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  2146. }
  2147. }
  2148. if (dx > 0 || dy > 0)
  2149. {
  2150. // Listview containing User/Group names
  2151. GetWindowRect(hwndPrincipalList, &rc);
  2152. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2153. SetWindowPos(hwndPrincipalList,
  2154. NULL,
  2155. 0,
  2156. 0,
  2157. rc.right - rc.left + dx,
  2158. rc.bottom - rc.top + dy/2,
  2159. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
  2160. // Widen the name column if necessary
  2161. GetClientRect(hwndPrincipalList, &rc);
  2162. if (ListView_GetColumnWidth(hwndPrincipalList, 0) < rc.right)
  2163. ListView_SetColumnWidth(hwndPrincipalList, 0, rc.right);
  2164. }
  2165. if (dy > 0 || dx > 0)
  2166. {
  2167. // Static control "Access"
  2168. hwnd = GetDlgItem(hDlg, IDC_SPP_ACCESS);
  2169. GetWindowRect(hwnd, &rc);
  2170. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2171. SetWindowPos(hwnd,
  2172. NULL,
  2173. rc.left,
  2174. rc.top + dy/2,
  2175. rc.right - rc.left + dx,
  2176. rc.bottom - rc.top,
  2177. SWP_NOACTIVATE | SWP_NOZORDER);
  2178. //Static control Big Permission Label
  2179. hwnd = GetDlgItem(hDlg, IDC_SPP_ACCESS_BIG);
  2180. GetWindowRect(hwnd, &rc);
  2181. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2182. SetWindowPos(hwnd,
  2183. NULL,
  2184. rc.left,
  2185. rc.top + dy/2,
  2186. rc.right - rc.left + dx,
  2187. rc.bottom - rc.top,
  2188. SWP_NOACTIVATE | SWP_NOZORDER);
  2189. }
  2190. if (dx > 0 || dy > 0)
  2191. {
  2192. // Static controls "Allow" and "Deny"
  2193. for (i = IDC_SPP_ALLOW; i <= IDC_SPP_DENY; i++)
  2194. {
  2195. hwnd = GetDlgItem(hDlg, i);
  2196. GetWindowRect(hwnd, &rc);
  2197. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2198. SetWindowPos(hwnd,
  2199. NULL,
  2200. rc.left + dx,
  2201. rc.top + dy/2,
  2202. 0,
  2203. 0,
  2204. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  2205. }
  2206. // List of permission checkboxes
  2207. GetWindowRect(hwndPermList, &rc);
  2208. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2209. SetWindowPos(hwndPermList,
  2210. NULL,
  2211. rc.left,
  2212. rc.top + dy/2,
  2213. rc.right - rc.left + dx,
  2214. rc.bottom - rc.top + dy/2,
  2215. SWP_NOACTIVATE | SWP_NOZORDER);
  2216. }
  2217. if (dy > 0 || dx > 0)
  2218. {
  2219. // Advanced button
  2220. GetWindowRect(hwndAdvButton, &rc);
  2221. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2222. SetWindowPos(hwndAdvButton,
  2223. NULL,
  2224. rc.left + dx,
  2225. rc.top + dy,
  2226. 0,
  2227. 0,
  2228. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  2229. // "More stuff is present but not viewable" message
  2230. hwnd = GetDlgItem(hDlg, IDC_SPP_STATIC_ADV);
  2231. GetWindowRect(hwnd, &rc);
  2232. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  2233. SetWindowPos(hwnd,
  2234. NULL,
  2235. rc.left,
  2236. rc.top + dy,
  2237. 0,
  2238. 0,
  2239. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  2240. }
  2241. TraceLeaveVoid();
  2242. }
  2243. void
  2244. CPermPage::ClearPermissions(HWND hwndList, BOOL bDisabled)
  2245. {
  2246. // Uncheck everything
  2247. UINT cRights = 0;
  2248. DWORD dwState = CLST_UNCHECKED;
  2249. if (bDisabled)
  2250. dwState |= CLST_DISABLED;
  2251. if (hwndList)
  2252. cRights = (UINT)SendMessage(hwndList, CLM_GETITEMCOUNT, 0, 0);
  2253. while (cRights > 0)
  2254. {
  2255. cRights--;
  2256. SendMessage(hwndList, CLM_SETSTATE, MAKELONG((WORD)cRights, 1), dwState);
  2257. SendMessage(hwndList, CLM_SETSTATE, MAKELONG((WORD)cRights, 2), dwState);
  2258. }
  2259. if(m_bCustomPermission)
  2260. {
  2261. ClearCustom(hwndList,1);
  2262. ClearCustom(hwndList,2);
  2263. }
  2264. }
  2265. void
  2266. CPermPage::SetDirty(HWND hDlg, BOOL bDefault)
  2267. {
  2268. if (!bDefault)
  2269. m_wSDControl &= ~SE_DACL_DEFAULTED;
  2270. m_fPageDirty = TRUE;
  2271. PropSheet_Changed(GetParent(hDlg), hDlg);
  2272. }
  2273. BOOL
  2274. CPermPage::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2275. {
  2276. // First check to see if its time to update listview names
  2277. if (uMsg == UM_SIDLOOKUPCOMPLETE)
  2278. {
  2279. HWND hwndList = GetDlgItem(hDlg, IDC_SPP_PRINCIPALS);
  2280. SetPrincipalNamesInList(hwndList, (PSID)lParam);
  2281. SetPermLabelText(hDlg);
  2282. // lParam is zero when all remaining names are looked up
  2283. if (0 == lParam)
  2284. {
  2285. // Sort using the real names
  2286. ListView_SortItems(hwndList, NULL, 0);
  2287. // Make sure the selected item is visible
  2288. int iSelItem;
  2289. if (NULL == GetSelectedItemData(hwndList, &iSelItem))
  2290. {
  2291. // No selection, select the first item
  2292. SelectListViewItem(hwndList, 0);
  2293. }
  2294. else
  2295. {
  2296. ListView_EnsureVisible(hwndList, iSelItem, FALSE);
  2297. }
  2298. // Show normal cursor now
  2299. m_fBusy = FALSE;
  2300. SetCursor(LoadCursor(NULL, IDC_ARROW));
  2301. // Enable the Advanced button if appropriate
  2302. EnableWindow(GetDlgItem(hDlg, IDC_SPP_ADVANCED),
  2303. (m_siObjectInfo.dwFlags & SI_ADVANCED));
  2304. }
  2305. return TRUE;
  2306. }
  2307. switch(uMsg)
  2308. {
  2309. case WM_SETCURSOR:
  2310. if (m_fBusy)
  2311. {
  2312. SetCursor(m_hcurBusy);
  2313. SetWindowLong(hDlg, DWLP_MSGRESULT, TRUE);
  2314. return TRUE;
  2315. }
  2316. else
  2317. return FALSE;
  2318. break;
  2319. case WM_INITDIALOG:
  2320. return InitDlg(hDlg);
  2321. case WM_NOTIFY:
  2322. return OnNotify(hDlg, (int)wParam, (LPNMHDR)lParam);
  2323. case WM_COMMAND:
  2324. switch (GET_WM_COMMAND_ID(wParam, lParam))
  2325. {
  2326. case IDC_SPP_ADD:
  2327. OnAddPrincipal(hDlg);
  2328. break;
  2329. case IDC_SPP_REMOVE:
  2330. OnRemovePrincipal(hDlg);
  2331. break;
  2332. case IDC_SPP_ADVANCED:
  2333. OnAdvanced(hDlg);
  2334. break;
  2335. case IDC_SPP_PRINCIPALS:
  2336. if (GET_WM_COMMAND_CMD(wParam, lParam) == IDN_CHECKSELECTION)
  2337. {
  2338. // See if we have gotten a new selection. If not, then the
  2339. // user must have clicked inside the listview but not on an item,
  2340. // thus causing the listview to remove the selection. In that
  2341. // case, disable the other controls
  2342. if (ListView_GetSelectedCount(GET_WM_COMMAND_HWND(wParam, lParam)) == 0)
  2343. {
  2344. // Uncheck everything first
  2345. ClearPermissions(GetDlgItem(hDlg, IDC_SPP_PERMS));
  2346. EnablePrincipalControls(hDlg, FALSE);
  2347. }
  2348. }
  2349. break;
  2350. default:
  2351. // Command not handled
  2352. return FALSE;
  2353. }
  2354. break;
  2355. case WM_SIZE:
  2356. OnSize(hDlg, (LONG)wParam, (ULONG)LOWORD(lParam), (ULONG)HIWORD(lParam));
  2357. break;
  2358. case WM_HELP:
  2359. if (IsWindowEnabled(hDlg))
  2360. {
  2361. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  2362. c_szAcluiHelpFile,
  2363. HELP_WM_HELP,
  2364. (DWORD_PTR)aPermPageHelpIDs);
  2365. }
  2366. break;
  2367. case WM_CONTEXTMENU:
  2368. if (IsWindowEnabled(hDlg))
  2369. {
  2370. HWND hwnd = (HWND)wParam;
  2371. //
  2372. // Some of the checkboxes may be scrolled out of view, but
  2373. // they are still detected by WinHelp, so we jump through
  2374. // a few extra hoops here.
  2375. //
  2376. if (hwnd == hDlg)
  2377. {
  2378. POINT pt;
  2379. pt.x = GET_X_LPARAM(lParam);
  2380. pt.y = GET_Y_LPARAM(lParam);
  2381. ScreenToClient(hDlg, &pt);
  2382. hwnd = ChildWindowFromPoint(hDlg, pt);
  2383. if (hDlg == hwnd)
  2384. break;
  2385. }
  2386. //
  2387. // WinHelp looks for child windows, but we don't have help id's
  2388. // for the permission checkboxes. If the request is for the
  2389. // checklist window, fake out WinHelp by referring to one of
  2390. // the static labels just above the list.
  2391. //
  2392. if (GetDlgCtrlID(hwnd) == IDC_SPP_PERMS)
  2393. hwnd = GetDlgItem(hDlg, IDC_SPP_ACCESS);
  2394. WinHelp(hwnd,
  2395. c_szAcluiHelpFile,
  2396. HELP_CONTEXTMENU,
  2397. (DWORD_PTR)aPermPageHelpIDs);
  2398. }
  2399. break;
  2400. default:
  2401. // Message not handled
  2402. return FALSE;
  2403. }
  2404. return TRUE;
  2405. }
  2406. //
  2407. // CSecurityInfo implementation
  2408. //
  2409. STDMETHODIMP_(ULONG)
  2410. CSecurityInfo::AddRef()
  2411. {
  2412. return ++m_cRef;
  2413. }
  2414. STDMETHODIMP_(ULONG)
  2415. CSecurityInfo::Release()
  2416. {
  2417. if (--m_cRef == 0)
  2418. {
  2419. delete this;
  2420. return 0;
  2421. }
  2422. return m_cRef;
  2423. }
  2424. STDMETHODIMP
  2425. CSecurityInfo::QueryInterface(REFIID riid, LPVOID FAR* ppv)
  2426. {
  2427. *ppv = NULL;
  2428. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation))
  2429. *ppv = static_cast<LPSECURITYINFO>(this);
  2430. else if (IsEqualIID(riid, IID_ISecurityInformation2))
  2431. {
  2432. if (m_pPage->m_psi2)
  2433. *ppv = static_cast<LPSECURITYINFO2>(this);
  2434. }
  2435. else if (IsEqualIID(riid, IID_IEffectivePermission))
  2436. {
  2437. if(m_pPage->m_pei)
  2438. *ppv = static_cast<LPEFFECTIVEPERMISSION>(this);
  2439. }
  2440. else if (IsEqualIID(riid, IID_ISecurityObjectTypeInfo))
  2441. {
  2442. if(m_pPage->m_psoti)
  2443. *ppv = static_cast<LPSecurityObjectTypeInfo>(this);
  2444. }
  2445. #if(_WIN32_WINNT >= 0x0500)
  2446. else if (IsEqualIID(riid, IID_IDsObjectPicker))
  2447. *ppv = static_cast<IDsObjectPicker*>(this);
  2448. #endif
  2449. if (*ppv)
  2450. {
  2451. m_cRef++;
  2452. return S_OK;
  2453. }
  2454. return E_NOINTERFACE;
  2455. }
  2456. STDMETHODIMP
  2457. CSecurityInfo::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo)
  2458. {
  2459. TraceEnter(TRACE_SI, "CSecurityInfo::GetObjectInformation");
  2460. TraceAssert(m_pPage != NULL);
  2461. *pObjectInfo = m_pPage->m_siObjectInfo;
  2462. TraceLeaveResult(S_OK);
  2463. }
  2464. STDMETHODIMP
  2465. CSecurityInfo::GetSecurity(SECURITY_INFORMATION si,
  2466. PSECURITY_DESCRIPTOR *ppSD,
  2467. BOOL fDefault)
  2468. {
  2469. HRESULT hr;
  2470. TraceEnter(TRACE_SI, "CSecurityInfo::GetSecurity");
  2471. TraceAssert(si != 0);
  2472. TraceAssert(ppSD != NULL);
  2473. TraceAssert(m_pPage != NULL);
  2474. TraceAssert(m_hDlg != NULL);
  2475. *ppSD = NULL;
  2476. //Effective permission page calls with si = DACL + OWNER + GROUP and it should
  2477. //return Actual Security Descriptor. Other pages calls with only one thing at a time
  2478. //and we build dacl and return it if its dirty.
  2479. if (!fDefault && (si == DACL_SECURITY_INFORMATION) && m_pPage->m_fPageDirty)
  2480. {
  2481. // We only get asked for one thing at a time
  2482. TraceAssert(si == DACL_SECURITY_INFORMATION);
  2483. // Return current DACL, including inherited ACEs
  2484. hr = m_pPage->BuildDacl(m_hDlg, ppSD, TRUE);
  2485. }
  2486. else
  2487. {
  2488. TraceAssert(m_pPage->m_psi != NULL);
  2489. // Get it from the object
  2490. hr = m_pPage->m_psi->GetSecurity(si, ppSD, fDefault);
  2491. }
  2492. TraceLeaveResult(hr);
  2493. }
  2494. STDMETHODIMP
  2495. CSecurityInfo::SetSecurity(SECURITY_INFORMATION si,
  2496. PSECURITY_DESCRIPTOR pSD)
  2497. {
  2498. HRESULT hr = E_FAIL;
  2499. TraceEnter(TRACE_SI, "CSecurityInfo::SetSecurity");
  2500. TraceAssert(si != 0);
  2501. TraceAssert(pSD != NULL);
  2502. TraceAssert(m_pPage != NULL);
  2503. TraceAssert(m_hDlg != NULL);
  2504. // Write out the new security descriptor
  2505. if (m_pPage->m_psi != NULL)
  2506. hr = m_pPage->m_psi->SetSecurity(si, pSD);
  2507. if (S_OK == hr && (si & DACL_SECURITY_INFORMATION))
  2508. {
  2509. PSECURITY_DESCRIPTOR psd = NULL;
  2510. m_pPage->m_fPageDirty = FALSE;
  2511. // Read the new DACL back from the object, that is, don't use the one
  2512. // from the passed-in security descriptor. This ensures that we have
  2513. // the "real" current DACL in case it was modified somewhere en route.
  2514. if (SUCCEEDED(m_pPage->m_psi->GetSecurity(DACL_SECURITY_INFORMATION, &psd, FALSE)))
  2515. pSD = psd;
  2516. // Reinitialize the dialog using the new DACL
  2517. m_pPage->SetDacl(m_hDlg, pSD);
  2518. if (psd != NULL)
  2519. LocalFree(psd);
  2520. }
  2521. TraceLeaveResult(hr);
  2522. }
  2523. STDMETHODIMP
  2524. CSecurityInfo::GetAccessRights(const GUID* pguidObjectType,
  2525. DWORD dwFlags,
  2526. PSI_ACCESS *ppAccess,
  2527. ULONG *pcAccesses,
  2528. ULONG *piDefaultAccess)
  2529. {
  2530. HRESULT hr = E_FAIL;
  2531. TraceEnter(TRACE_SI, "CSecurityInfo::GetAccessRights");
  2532. TraceAssert(m_pPage != NULL);
  2533. if (m_pPage->m_psi != NULL)
  2534. hr = m_pPage->m_psi->GetAccessRights(pguidObjectType,
  2535. dwFlags,
  2536. ppAccess,
  2537. pcAccesses,
  2538. piDefaultAccess);
  2539. TraceLeaveResult(hr);
  2540. }
  2541. STDMETHODIMP
  2542. CSecurityInfo::MapGeneric(const GUID* pguidObjectType,
  2543. UCHAR *pAceFlags,
  2544. ACCESS_MASK *pmask)
  2545. {
  2546. HRESULT hr = E_FAIL;
  2547. TraceEnter(TRACE_SI, "CSecurityInfo::MapGeneric");
  2548. TraceAssert(m_pPage != NULL);
  2549. if (m_pPage->m_psi != NULL)
  2550. hr = m_pPage->m_psi->MapGeneric(pguidObjectType, pAceFlags, pmask);
  2551. TraceLeaveResult(hr);
  2552. }
  2553. STDMETHODIMP
  2554. CSecurityInfo::GetInheritTypes(PSI_INHERIT_TYPE *ppInheritTypes,
  2555. ULONG *pcInheritTypes)
  2556. {
  2557. HRESULT hr = E_FAIL;
  2558. TraceEnter(TRACE_SI, "CSecurityInfo::GetInheritTypes");
  2559. TraceAssert(m_pPage != NULL);
  2560. TraceAssert(ppInheritTypes != NULL);
  2561. TraceAssert(pcInheritTypes != NULL);
  2562. *ppInheritTypes = NULL;
  2563. *pcInheritTypes = 0;
  2564. if (m_pPage->m_psi != NULL)
  2565. hr = m_pPage->m_psi->GetInheritTypes(ppInheritTypes,
  2566. pcInheritTypes);
  2567. TraceLeaveResult(hr);
  2568. }
  2569. STDMETHODIMP
  2570. CSecurityInfo::PropertySheetPageCallback(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage)
  2571. {
  2572. HRESULT hr = S_OK;
  2573. TraceEnter(TRACE_SI, "CSecurityInfo::PropertySheetPageCallback");
  2574. TraceAssert(m_pPage != NULL);
  2575. //
  2576. // Pass the call on to the client
  2577. //
  2578. if (m_pPage->m_psi != NULL)
  2579. hr = m_pPage->m_psi->PropertySheetPageCallback(hwnd, uMsg, uPage);
  2580. //
  2581. // If the simple perm page is disabled, make sure the advanced perm
  2582. // page is as well.
  2583. //
  2584. if (SUCCEEDED(hr) && uPage == SI_PAGE_ADVPERM && m_pPage->m_bAbortPage)
  2585. hr = E_FAIL;
  2586. TraceLeaveResult(hr);
  2587. }
  2588. //
  2589. // ISecurityInformation2 methods
  2590. //
  2591. STDMETHODIMP_(BOOL)
  2592. CSecurityInfo::IsDaclCanonical(PACL pDacl)
  2593. {
  2594. BOOL bResult = TRUE;
  2595. TraceEnter(TRACE_SI, "CSecurityInfo::IsDaclCanonical");
  2596. TraceAssert(m_pPage != NULL);
  2597. if (m_pPage->m_psi2 != NULL)
  2598. bResult = m_pPage->m_psi2->IsDaclCanonical(pDacl);
  2599. TraceLeaveValue(bResult);
  2600. }
  2601. STDMETHODIMP
  2602. CSecurityInfo::LookupSids(ULONG cSids, PSID *rgpSids, LPDATAOBJECT *ppdo)
  2603. {
  2604. HRESULT hr = E_NOTIMPL;
  2605. TraceEnter(TRACE_SI, "CSecurityInfo::LookupSids");
  2606. TraceAssert(m_pPage != NULL);
  2607. if (m_pPage->m_psi2 != NULL)
  2608. hr = m_pPage->m_psi2->LookupSids(cSids, rgpSids, ppdo);
  2609. TraceLeaveResult(hr);
  2610. }
  2611. //
  2612. // IDsObjectPicker methods
  2613. //
  2614. #if(_WIN32_WINNT >= 0x0500)
  2615. STDMETHODIMP CSecurityInfo::Initialize(PDSOP_INIT_INFO pInitInfo)
  2616. {
  2617. HRESULT hr;
  2618. IDsObjectPicker *pObjectPicker = NULL;
  2619. hr = m_pPage->GetObjectPicker(&pObjectPicker);
  2620. if (SUCCEEDED(hr))
  2621. {
  2622. if (m_pPage->m_flLastOPOptions != pInitInfo->flOptions)
  2623. {
  2624. m_pPage->m_flLastOPOptions = (DWORD)-1;
  2625. hr = pObjectPicker->Initialize(pInitInfo);
  2626. if (SUCCEEDED(hr))
  2627. {
  2628. m_pPage->m_flLastOPOptions = pInitInfo->flOptions;
  2629. }
  2630. }
  2631. pObjectPicker->Release();
  2632. }
  2633. return hr;
  2634. }
  2635. STDMETHODIMP CSecurityInfo::InvokeDialog(HWND hwndParent,
  2636. IDataObject **ppdoSelection)
  2637. {
  2638. HRESULT hr;
  2639. IDsObjectPicker *pObjectPicker = NULL;
  2640. hr = m_pPage->GetObjectPicker(&pObjectPicker);
  2641. if (SUCCEEDED(hr))
  2642. {
  2643. hr = pObjectPicker->InvokeDialog(hwndParent, ppdoSelection);
  2644. pObjectPicker->Release();
  2645. }
  2646. return hr;
  2647. }
  2648. #endif // _WIN32_WINNT >= 0x0500
  2649. STDMETHODIMP CSecurityInfo::GetInheritSource(SECURITY_INFORMATION si,
  2650. PACL pACL,
  2651. PINHERITED_FROM *ppInheritArray)
  2652. {
  2653. HRESULT hr = E_NOTIMPL;
  2654. TraceEnter(TRACE_SI, "CSecurityInfo::GetInheritSource");
  2655. TraceAssert(m_pPage != NULL);
  2656. if (m_pPage->m_psoti)
  2657. hr = m_pPage->m_psoti->GetInheritSource(si, pACL, ppInheritArray);
  2658. TraceLeaveResult(hr);
  2659. }
  2660. STDMETHODIMP CSecurityInfo::GetEffectivePermission( THIS_ const GUID* pguidObjectType,
  2661. PSID pUserSid,
  2662. LPCWSTR pszServerName,
  2663. PSECURITY_DESCRIPTOR pSD,
  2664. POBJECT_TYPE_LIST *ppObjectTypeList,
  2665. ULONG *pcObjectTypeListLength,
  2666. PACCESS_MASK *ppGrantedAccessList,
  2667. ULONG *pcGrantedAccessListLength)
  2668. {
  2669. HRESULT hr = E_NOTIMPL;
  2670. TraceEnter(TRACE_SI, "CSecurityInfo::GetEffectivePermission");
  2671. TraceAssert(m_pPage != NULL);
  2672. if (m_pPage->m_pei)
  2673. hr = m_pPage->m_pei->GetEffectivePermission(pguidObjectType,
  2674. pUserSid,
  2675. pszServerName,
  2676. pSD,
  2677. ppObjectTypeList,
  2678. pcObjectTypeListLength,
  2679. ppGrantedAccessList,
  2680. pcGrantedAccessListLength);
  2681. TraceLeaveResult(hr);
  2682. }
  2683. //
  2684. // Expose an api to get at the simple permission editor
  2685. //
  2686. HPROPSHEETPAGE
  2687. ACLUIAPI
  2688. CreateSecurityPage(LPSECURITYINFO psi)
  2689. {
  2690. HPROPSHEETPAGE hPage = NULL;
  2691. PPERMPAGE pPage;
  2692. PSIDCACHE pSidCache;
  2693. TraceEnter(TRACE_PERMPAGE, "CreateSecurityPage");
  2694. // Create the global SID Cache
  2695. pSidCache = GetSidCache();
  2696. if (NULL == psi)
  2697. {
  2698. SetLastError(ERROR_INVALID_PARAMETER);
  2699. TraceLeaveValue(NULL);
  2700. }
  2701. pPage = new CPermPage(psi);
  2702. if (pPage)
  2703. {
  2704. SI_OBJECT_INFO siObjectInfo = {0};
  2705. LPCTSTR pszTitle = NULL;
  2706. if (SUCCEEDED(psi->GetObjectInformation(&siObjectInfo)) &&
  2707. (siObjectInfo.dwFlags & SI_PAGE_TITLE))
  2708. {
  2709. pszTitle = siObjectInfo.pszPageTitle;
  2710. }
  2711. hPage = pPage->CreatePropSheetPage(MAKEINTRESOURCE(IDD_SIMPLE_PERM_PAGE), pszTitle);
  2712. if (!hPage)
  2713. delete pPage;
  2714. }
  2715. if (pSidCache)
  2716. pSidCache->Release();
  2717. TraceLeaveValue(hPage);
  2718. }
  2719. BOOL
  2720. ACLUIAPI
  2721. EditSecurity( HWND hwndOwner, LPSECURITYINFO psi )
  2722. {
  2723. HPROPSHEETPAGE hPage[1];
  2724. UINT cPages = 0;
  2725. BOOL bResult = FALSE;
  2726. SI_OBJECT_INFO siObjectInfo = {0};
  2727. HRESULT hr;
  2728. TraceEnter(TRACE_PERMPAGE, "EditSecurity");
  2729. // Get object name for dialog title
  2730. hr = psi->GetObjectInformation(&siObjectInfo);
  2731. if (FAILED(hr))
  2732. {
  2733. if (!GetLastError())
  2734. SetLastError(hr);
  2735. TraceLeaveValue(FALSE);
  2736. }
  2737. hPage[cPages] = CreateSecurityPage( psi );
  2738. if (hPage[cPages])
  2739. cPages++;
  2740. if (cPages)
  2741. {
  2742. // Build dialog title string
  2743. LPTSTR pszCaption = NULL;
  2744. PROPSHEETHEADER psh;
  2745. psh.dwSize = SIZEOF(psh);
  2746. psh.dwFlags = PSH_DEFAULT;
  2747. psh.hwndParent = hwndOwner;
  2748. psh.hInstance = ::hModule;
  2749. psh.nPages = cPages;
  2750. psh.nStartPage = 0;
  2751. psh.phpage = &hPage[0];
  2752. // There has been a request for customization of this dialog title,
  2753. // but this probably isn't the best way to do it, since the dlg title
  2754. // and page title will be the same.
  2755. #if 0
  2756. if ((siObjectInfo.dwFlags & SI_PAGE_TITLE)
  2757. && siObjectInfo.pszPageTitle
  2758. && siObjectInfo.pszPageTitle[0])
  2759. {
  2760. psh.pszCaption = siObjectInfo.pszPageTitle;
  2761. }
  2762. else
  2763. #endif
  2764. {
  2765. FormatStringID(&pszCaption, ::hModule, IDS_SPP_TITLE, siObjectInfo.pszObjectName);
  2766. psh.pszCaption = pszCaption;
  2767. }
  2768. bResult = (BOOL)(PropertySheet(&psh) + 1);
  2769. LocalFreeString(&pszCaption);
  2770. }
  2771. TraceLeaveValue(bResult);
  2772. }
  2773. //