Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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