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.

948 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: owner.cpp
  8. //
  9. // This file contains the implementation of the Owner page.
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "aclpriv.h"
  13. #include "sddl.h" // ConvertSidToStringSid
  14. //
  15. // Context Help IDs.
  16. //
  17. const static DWORD aOwnerHelpIDs[] =
  18. {
  19. IDC_OWN_CURRENTOWNER_STATIC, IDH_OWN_CURRENTOWNER,
  20. IDC_OWN_CURRENTOWNER, IDH_OWN_CURRENTOWNER,
  21. IDC_OWN_OWNERLIST_STATIC, IDH_OWN_OWNERLIST,
  22. IDC_OWN_OWNERLIST, IDH_OWN_OWNERLIST,
  23. IDC_OWN_RECURSE, IDH_OWN_RECURSE,
  24. IDC_OWN_RESET, IDH_OWN_RESET,
  25. IDC_ACEL_STATIC, -1,
  26. 0, 0
  27. };
  28. //
  29. // These SIDs are always added to the list of possible owners
  30. //
  31. const static UI_TokenSid g_uiTokenSids[] =
  32. {
  33. UI_TSID_CurrentProcessUser,
  34. UI_TSID_CurrentProcessOwner,
  35. //UI_TSID_CurrentProcessPrimaryGroup,
  36. };
  37. struct Owner_LV_Entry
  38. {
  39. PSID pSid;
  40. LPWSTR pszName;
  41. };
  42. Owner_LV_Entry*
  43. MakeOwnerEntry(PSID pSid,LPWSTR pszName)
  44. {
  45. Owner_LV_Entry * pEntry =
  46. (Owner_LV_Entry *)LocalAlloc(LPTR,sizeof(Owner_LV_Entry));
  47. if(!pEntry)
  48. return NULL;
  49. pEntry->pSid = pSid;
  50. pEntry->pszName = pszName;
  51. return pEntry;
  52. }
  53. void
  54. FreeOwnerEntry(Owner_LV_Entry* pEntry)
  55. {
  56. if(pEntry)
  57. {
  58. if(pEntry->pSid)
  59. LocalFree(pEntry->pSid);
  60. if(pEntry->pszName)
  61. LocalFree(pEntry->pszName);
  62. LocalFree(pEntry);
  63. }
  64. }
  65. //Function for sorting the list view entries
  66. int CALLBACK
  67. OwnerCompareProc(LPARAM lParam1,
  68. LPARAM lParam2,
  69. LPARAM /*lParamSort*/)
  70. {
  71. int iResult = 0;
  72. Owner_LV_Entry* pEntry1 = (Owner_LV_Entry*)lParam1;
  73. Owner_LV_Entry* pEntry2 = (Owner_LV_Entry*)lParam2;
  74. if(!pEntry1 && !pEntry2)
  75. return 0; //Equal
  76. //lParam is null for "other users and groups..." and
  77. //it should always be the last entry
  78. if(!pEntry1)
  79. return 1;
  80. if(!pEntry2)
  81. return -1;
  82. LPWSTR psz1 = pEntry1->pszName;
  83. LPWSTR psz2 = pEntry2->pszName;
  84. if (psz1 && psz2)
  85. {
  86. iResult = CompareString(LOCALE_USER_DEFAULT, 0, psz1, -1, psz2, -1) - 2;
  87. }
  88. TraceLeaveValue(iResult);
  89. }
  90. class COwnerPage : public CSecurityPage
  91. {
  92. private:
  93. PSID m_psidOriginal;
  94. PSID m_psidNetID;
  95. HANDLE m_hSidThread;
  96. BOOL& m_refbNoReadWriteCanWriteOwner;
  97. public:
  98. COwnerPage(LPSECURITYINFO psi,
  99. SI_OBJECT_INFO *psiObjectInfo,
  100. BOOL &refbNoReadWriteCanWriteOwner);
  101. virtual ~COwnerPage(void);
  102. private:
  103. void OnSelect(HWND hDlg);
  104. virtual BOOL DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  105. void InitDlg(HWND hDlg);
  106. int AddSid(HWND hOwner, PSID psid, LPCTSTR pszServerName = NULL);
  107. void OnApply(HWND hDlg, BOOL bClose);
  108. void OnReset(HWND hDlg);
  109. };
  110. HPROPSHEETPAGE
  111. CreateOwnerPage(LPSECURITYINFO psi, SI_OBJECT_INFO *psiObjectInfo, BOOL &refbNoReadWriteCanWriteOwner)
  112. {
  113. HPROPSHEETPAGE hPage = NULL;
  114. COwnerPage *pPage;
  115. TraceEnter(TRACE_OWNER, "CreateOwnerPage");
  116. pPage = new COwnerPage(psi, psiObjectInfo,refbNoReadWriteCanWriteOwner);
  117. if (pPage)
  118. {
  119. hPage = pPage->CreatePropSheetPage(MAKEINTRESOURCE(IDD_OWNER_PAGE));
  120. if (!hPage)
  121. delete pPage;
  122. }
  123. TraceLeaveValue(hPage);
  124. }
  125. COwnerPage::
  126. COwnerPage(LPSECURITYINFO psi,
  127. SI_OBJECT_INFO *psiObjectInfo,
  128. BOOL& refbNoReadWriteCanWriteOwner)
  129. : CSecurityPage(psi, SI_PAGE_OWNER),
  130. m_psidOriginal(NULL),
  131. m_psidNetID(NULL),
  132. m_hSidThread(NULL),
  133. m_refbNoReadWriteCanWriteOwner(refbNoReadWriteCanWriteOwner)
  134. {
  135. // Lookup known SIDs asynchronously so the dialog
  136. // will initialize faster
  137. HDPA hSids = DPA_Create(ARRAYSIZE(g_uiTokenSids));
  138. if (hSids)
  139. {
  140. USES_CONVERSION;
  141. LPCWSTR pszServer = NULL;
  142. if (psiObjectInfo)
  143. pszServer = psiObjectInfo->pszServerName;
  144. for (int i = 0; i < ARRAYSIZE(g_uiTokenSids); i++)
  145. DPA_AppendPtr(hSids, QueryTokenSid(g_uiTokenSids[i]));
  146. m_psidNetID = GetAuthenticationID(pszServer);
  147. if (m_psidNetID)
  148. DPA_AppendPtr(hSids, m_psidNetID);
  149. LookupSidsAsync(hSids, W2CT(pszServer), m_psi2, NULL, 0, &m_hSidThread);
  150. DPA_Destroy(hSids);
  151. }
  152. }
  153. COwnerPage::~COwnerPage(void)
  154. {
  155. if (m_hSidThread)
  156. CloseHandle(m_hSidThread);
  157. if (m_psidOriginal)
  158. LocalFree(m_psidOriginal);
  159. if (m_psidNetID)
  160. LocalFree(m_psidNetID);
  161. }
  162. int
  163. COwnerPage::AddSid(HWND hOwner, PSID psid, LPCTSTR pszServerName)
  164. {
  165. PUSER_LIST pUserList = NULL;
  166. SID_NAME_USE sidType = SidTypeUnknown;
  167. LPCTSTR pszName = NULL;
  168. LPCTSTR pszLogonName = NULL;
  169. int iItem = -1;
  170. int cItems;
  171. LV_ITEM lvItem;
  172. TraceEnter(TRACE_OWNER, "COwnerPage::AddSid");
  173. TraceAssert(!m_bAbortPage);
  174. if (!psid || !IsValidSid(psid))
  175. ExitGracefully(iItem, -1, "Bad SID parameter");
  176. // Get the name for this SID
  177. if (LookupSid(psid, pszServerName, m_psi2, &pUserList))
  178. {
  179. TraceAssert(NULL != pUserList);
  180. TraceAssert(1 == pUserList->cUsers);
  181. sidType = pUserList->rgUsers[0].SidType;
  182. pszName = pUserList->rgUsers[0].pszName;
  183. pszLogonName = pUserList->rgUsers[0].pszLogonName;
  184. }
  185. switch (sidType)
  186. {
  187. case SidTypeDomain:
  188. case SidTypeDeletedAccount:
  189. case SidTypeInvalid:
  190. case SidTypeUnknown:
  191. case SidTypeComputer:
  192. ExitGracefully(iItem, -1, "SID invalid on target");
  193. break;
  194. }
  195. cItems = ListView_GetItemCount(hOwner);
  196. lvItem.mask = LVIF_PARAM;
  197. lvItem.iSubItem = 0;
  198. // See if this SID is already in the list
  199. for (iItem = 0; iItem < cItems; iItem++)
  200. {
  201. lvItem.iItem = iItem;
  202. lvItem.lParam = NULL;
  203. ListView_GetItem(hOwner, &lvItem);
  204. Owner_LV_Entry *pLvEntry = (Owner_LV_Entry *)lvItem.lParam;
  205. if (pLvEntry && pLvEntry->pSid && EqualSid(psid, pLvEntry->pSid))
  206. {
  207. // This is a hack. We often see alias sids more than once when
  208. // filling the list, e.g. BUILTIN\Administrators. We want to use
  209. // the version of the name that includes the target domain, if
  210. // provided. That is, if pszServerName is non-NULL here, switch
  211. // to the version of the name that goes with pszServerName.
  212. if (pszServerName)
  213. {
  214. lvItem.mask = LVIF_TEXT;
  215. lvItem.pszText = NULL;
  216. if (BuildUserDisplayName(&lvItem.pszText, pszName, pszLogonName)
  217. || ConvertSidToStringSid(psid, &lvItem.pszText))
  218. {
  219. if(pLvEntry->pszName)
  220. LocalFree(pLvEntry->pszName);
  221. pLvEntry->pszName = lvItem.pszText;
  222. ListView_SetItem(hOwner, &lvItem);
  223. }
  224. }
  225. break;
  226. }
  227. }
  228. if (iItem == cItems)
  229. {
  230. // The SID doesn't exist in the list. Add a new entry.
  231. PSID psidCopy = LocalAllocSid(psid);
  232. if (psidCopy)
  233. {
  234. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  235. lvItem.iItem = 0;
  236. lvItem.iSubItem = 0;
  237. lvItem.pszText = NULL;
  238. if (!BuildUserDisplayName(&lvItem.pszText, pszName, pszLogonName))
  239. ConvertSidToStringSid(psid, &lvItem.pszText);
  240. lvItem.iImage = GetSidImageIndex(psid, sidType);
  241. lvItem.lParam = (LPARAM)MakeOwnerEntry(psidCopy,lvItem.pszText);
  242. // Insert principal into list
  243. iItem = ListView_InsertItem(hOwner, &lvItem);
  244. }
  245. }
  246. exit_gracefully:
  247. if (NULL != pUserList)
  248. LocalFree(pUserList);
  249. TraceLeaveValue(iItem);
  250. }
  251. VOID
  252. COwnerPage::OnSelect(HWND hDlg)
  253. {
  254. PUSER_LIST pUserList = NULL;
  255. LPEFFECTIVEPERMISSION pei;
  256. HRESULT hr = S_OK;
  257. TraceEnter(TRACE_OWNER, "COwnerPage::OnSelect");
  258. if (S_OK == GetUserGroup(hDlg, FALSE, &pUserList))
  259. {
  260. TraceAssert(NULL != pUserList);
  261. TraceAssert(1 == pUserList->cUsers);
  262. // Copy the new sid
  263. PSID pSid = (PSID)pUserList->rgUsers[0].pSid;
  264. if (pSid)
  265. {
  266. HWND hwndList = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
  267. int iIndex = AddSid(hwndList,
  268. pSid,
  269. m_siObjectInfo.pszServerName);
  270. PropSheet_Changed(GetParent(hDlg), hDlg);
  271. SelectListViewItem(hwndList, iIndex);
  272. //Sort the listview
  273. ListView_SortItems(hwndList,OwnerCompareProc,NULL);
  274. }
  275. LocalFree(pUserList);
  276. }
  277. }
  278. void
  279. COwnerPage::InitDlg(HWND hDlg)
  280. {
  281. TCHAR szBuffer[MAX_PATH];
  282. BOOL bReadOnly;
  283. HWND hOwner = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
  284. HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  285. TraceEnter(TRACE_OWNER, "COwnerPage::InitDlg");
  286. // Hide the Reset button if it isn't supported.
  287. if (!(m_siObjectInfo.dwFlags & SI_RESET) &&
  288. !(m_siObjectInfo.dwFlags & SI_RESET_OWNER))
  289. {
  290. ShowWindow(GetDlgItem(hDlg, IDC_OWN_RESET), SW_HIDE);
  291. }
  292. // Hide the Recurse checkbox if it isn't supported.
  293. if ((m_siObjectInfo.dwFlags & (SI_OWNER_RECURSE | SI_CONTAINER)) != (SI_OWNER_RECURSE | SI_CONTAINER))
  294. {
  295. m_siObjectInfo.dwFlags &= ~SI_OWNER_RECURSE;
  296. HWND hwndRecurse = GetDlgItem(hDlg, IDC_OWN_RECURSE);
  297. ShowWindow(hwndRecurse, SW_HIDE);
  298. EnableWindow(hwndRecurse, FALSE);
  299. }
  300. if (m_bAbortPage)
  301. {
  302. //
  303. // Disable everything
  304. //
  305. bReadOnly = TRUE;
  306. }
  307. else
  308. {
  309. // Create & set the image list for the listview
  310. ListView_SetImageList(hOwner,
  311. LoadImageList(::hModule, MAKEINTRESOURCE(IDB_SID_ICONS)),
  312. LVSIL_SMALL);
  313. //
  314. // Add the "Name" column (the only column on this page)
  315. //
  316. RECT rc;
  317. GetClientRect(hOwner, &rc);
  318. LoadString(::hModule, IDS_NAME, szBuffer, ARRAYSIZE(szBuffer));
  319. LV_COLUMN col;
  320. col.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  321. col.fmt = LVCFMT_LEFT;
  322. col.pszText = szBuffer;
  323. col.iSubItem = 0;
  324. col.cx = rc.right;
  325. ListView_InsertColumn(hOwner, 0, &col);
  326. //
  327. // Make a copy of the current owner sid
  328. //
  329. PSECURITY_DESCRIPTOR pSD = NULL;
  330. HRESULT hr = m_psi->GetSecurity(OWNER_SECURITY_INFORMATION, &pSD, FALSE);
  331. if (pSD)
  332. {
  333. PSID psidOwner = NULL;
  334. BOOL bDefaulted;
  335. GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted);
  336. if (psidOwner)
  337. {
  338. UINT iLength = GetLengthSid(psidOwner);
  339. m_psidOriginal = LocalAlloc(LPTR, iLength);
  340. if (m_psidOriginal)
  341. CopyMemory(m_psidOriginal, psidOwner, iLength);
  342. }
  343. LocalFree(pSD);
  344. }
  345. // Test for writeability
  346. bReadOnly = !!(m_siObjectInfo.dwFlags & SI_OWNER_READONLY);
  347. } // !m_bAbortPage
  348. //
  349. // Iterate through the groups on this process's token looking for
  350. // the SE_GROUP_OWNER attribute.
  351. //
  352. if (!bReadOnly)
  353. {
  354. HANDLE hProcessToken = NULL;
  355. //
  356. // Wait for the known SIDs to be resolved so we don't try
  357. // to look them up twice.
  358. //
  359. if (m_hSidThread)
  360. {
  361. WaitForSingleObject(m_hSidThread, INFINITE);
  362. CloseHandle(m_hSidThread);
  363. m_hSidThread = NULL;
  364. }
  365. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken))
  366. {
  367. // Allocate a buffer for the TOKEN_GROUPS information
  368. ULONG cbBuffer = 1024; // start with 1k
  369. LPVOID pBuffer = LocalAlloc(LPTR, cbBuffer);
  370. if (pBuffer)
  371. {
  372. if (!GetTokenInformation(hProcessToken,
  373. TokenGroups,
  374. pBuffer,
  375. cbBuffer,
  376. &cbBuffer))
  377. {
  378. LocalFree(pBuffer);
  379. pBuffer = NULL;
  380. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  381. {
  382. pBuffer = LocalAlloc(LPTR, cbBuffer);// size returned above
  383. if (pBuffer && !GetTokenInformation(hProcessToken,
  384. TokenGroups,
  385. pBuffer,
  386. cbBuffer,
  387. &cbBuffer))
  388. {
  389. LocalFree(pBuffer);
  390. pBuffer = NULL;
  391. }
  392. }
  393. }
  394. if (pBuffer)
  395. {
  396. PTOKEN_GROUPS ptg = (PTOKEN_GROUPS)pBuffer;
  397. for (ULONG i = 0; i < ptg->GroupCount; i++)
  398. {
  399. DWORD dwAttr = ptg->Groups[i].Attributes;
  400. if ((dwAttr & SE_GROUP_OWNER) && !(dwAttr & SE_GROUP_LOGON_ID))
  401. {
  402. AddSid(hOwner, ptg->Groups[i].Sid, m_siObjectInfo.pszServerName);
  403. }
  404. }
  405. }
  406. if (pBuffer != NULL)
  407. LocalFree(pBuffer);
  408. }
  409. CloseHandle(hProcessToken);
  410. }
  411. //
  412. // Now add in the additional possible sids
  413. //
  414. for (int i = 0; i < ARRAYSIZE(g_uiTokenSids); i++)
  415. AddSid(hOwner, QueryTokenSid(g_uiTokenSids[i]));
  416. AddSid(hOwner, m_psidNetID, m_siObjectInfo.pszServerName);
  417. }
  418. if (!m_bAbortPage)
  419. {
  420. PUSER_LIST pUserList = NULL;
  421. LoadString(::hModule, IDS_OWNER_CANT_DISPLAY, szBuffer, ARRAYSIZE(szBuffer));
  422. // Finally, look up a name for the original SID.
  423. if (m_psidOriginal)
  424. {
  425. LPTSTR pszName = NULL;
  426. // Get the "S-1-5-blah" form of the SID in case the lookup fails
  427. if (ConvertSidToStringSid(m_psidOriginal, &pszName))
  428. {
  429. lstrcpyn(szBuffer, pszName, ARRAYSIZE(szBuffer));
  430. LocalFreeString(&pszName);
  431. }
  432. if (LookupSid(m_psidOriginal, m_siObjectInfo.pszServerName, m_psi2, &pUserList))
  433. {
  434. TraceAssert(NULL != pUserList);
  435. TraceAssert(1 == pUserList->cUsers);
  436. if (BuildUserDisplayName(&pszName, pUserList->rgUsers[0].pszName, pUserList->rgUsers[0].pszLogonName))
  437. {
  438. lstrcpyn(szBuffer, pszName, ARRAYSIZE(szBuffer));
  439. LocalFreeString(&pszName);
  440. }
  441. LocalFree(pUserList);
  442. }
  443. }
  444. SetDlgItemText(hDlg, IDC_OWN_CURRENTOWNER, szBuffer);
  445. }
  446. //
  447. // If the current user cannot change owners, gray out the list box.
  448. //
  449. if (bReadOnly)
  450. {
  451. // Disable the list and notify the user that it's read-only.
  452. EnableWindow(hOwner, FALSE);
  453. EnableWindow(GetDlgItem(hDlg, IDC_OWN_RESET), FALSE);
  454. EnableWindow(GetDlgItem(hDlg, IDC_OWN_RECURSE), FALSE);
  455. //
  456. // If we're aborting, then the user should have been notified
  457. // during the propsheetpage callback. Don't put up another
  458. // message here.
  459. //
  460. if (S_OK == m_hrLastPSPCallbackResult)
  461. {
  462. MsgPopup(hDlg,
  463. MAKEINTRESOURCE(IDS_OWNER_READONLY),
  464. MAKEINTRESOURCE(IDS_SECURITY),
  465. MB_OK | MB_ICONINFORMATION,
  466. ::hModule,
  467. m_siObjectInfo.pszObjectName);
  468. }
  469. }
  470. ListView_SortItems(GetDlgItem(hDlg, IDC_OWN_OWNERLIST),OwnerCompareProc,NULL);
  471. SetCursor(hcur);
  472. TraceLeaveVoid();
  473. }
  474. void
  475. COwnerPage::OnApply(HWND hDlg, BOOL bClose)
  476. {
  477. int iSelected = -1;
  478. HWND hwndOwnerList = NULL;
  479. PSID psid = NULL;
  480. BOOL bRecurse = FALSE;
  481. SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION;
  482. BOOL bEqualSid = FALSE;
  483. TraceEnter(TRACE_OWNER, "COwnerPage::OnApply");
  484. hwndOwnerList = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
  485. Owner_LV_Entry * pLVEntry = (Owner_LV_Entry *)GetSelectedItemData(hwndOwnerList, &iSelected);
  486. if(pLVEntry)
  487. {
  488. psid = pLVEntry->pSid;
  489. }
  490. // If there is no selection, use the original
  491. if (!psid)
  492. psid = m_psidOriginal;
  493. // If no selection and no original, then we can't do anything
  494. if (!psid)
  495. TraceLeaveVoid();
  496. if ((m_siObjectInfo.dwFlags & SI_OWNER_RECURSE)
  497. && IsDlgButtonChecked(hDlg, IDC_OWN_RECURSE) == BST_CHECKED)
  498. {
  499. bRecurse = TRUE;
  500. }
  501. // Has anything changed?
  502. if (m_psidOriginal
  503. && ( (m_psidOriginal == psid) || EqualSid(m_psidOriginal, psid) )
  504. && !bRecurse)
  505. {
  506. // Nothing has changed
  507. TraceLeaveVoid();
  508. }
  509. SECURITY_DESCRIPTOR sd = {0};
  510. DWORD dwPrivs[] = { SE_TAKE_OWNERSHIP_PRIVILEGE, SE_RESTORE_PRIVILEGE };
  511. HANDLE hToken = INVALID_HANDLE_VALUE;
  512. TraceAssert(!m_bAbortPage);
  513. HRESULT hr = S_OK;
  514. if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
  515. {
  516. DWORD dwErr = GetLastError();
  517. ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"InitializeSecurityDescriptor failed");
  518. }
  519. if(!SetSecurityDescriptorOwner(&sd, psid, FALSE))
  520. {
  521. DWORD dwErr = GetLastError();
  522. ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"SetSecurityDescriptorOwner failed");
  523. }
  524. //
  525. // ISecurityInformation::SetSecurity doesn't have a parameter to indicate
  526. // that the owner should be recursively applied. We could add a parameter,
  527. // but for now, just use one of the unused SECURITY_INFORMATION bits.
  528. // The security descriptor structure is unlikely to change so this should
  529. // be ok for now.
  530. if (bRecurse)
  531. si |= SI_OWNER_RECURSE;
  532. hToken = EnablePrivileges(dwPrivs, ARRAYSIZE(dwPrivs));
  533. hr = m_psi->SetSecurity(si, &sd);
  534. ReleasePrivileges(hToken);
  535. if (S_FALSE == hr)
  536. {
  537. // S_FALSE is silent failure (the client should put up UI
  538. // during SetSecurity before returning S_FALSE).
  539. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
  540. }
  541. else if (S_OK == hr && !bClose)
  542. {
  543. if(m_refbNoReadWriteCanWriteOwner)
  544. {
  545. MsgPopup(hDlg,
  546. MAKEINTRESOURCE(IDS_REFRESH_PROPERTYSHEET),
  547. MAKEINTRESOURCE(IDS_SECURITY),
  548. MB_OK | MB_ICONINFORMATION,
  549. ::hModule);
  550. m_refbNoReadWriteCanWriteOwner = FALSE;
  551. }
  552. //Inform the Effective Permission tab that
  553. //Permissions are changed
  554. PropSheet_QuerySiblings(GetParent(hDlg),0,0);
  555. UINT iLength = GetLengthSid(psid);
  556. if (-1 != iSelected)
  557. {
  558. TCHAR szName[MAX_PATH];
  559. szName[0] = TEXT('\0');
  560. ListView_GetItemText(hwndOwnerList, iSelected, 0, szName, ARRAYSIZE(szName));
  561. SetDlgItemText(hDlg, IDC_OWN_CURRENTOWNER, szName);
  562. }
  563. if (!(m_psidOriginal &&
  564. ((m_psidOriginal == psid) || EqualSid(m_psidOriginal, psid))))
  565. {
  566. if (m_psidOriginal)
  567. {
  568. UINT iLengthOriginal = (UINT)LocalSize(m_psidOriginal);
  569. if (iLengthOriginal < iLength)
  570. {
  571. LocalFree(m_psidOriginal);
  572. m_psidOriginal = NULL;
  573. }
  574. else
  575. {
  576. ZeroMemory(m_psidOriginal, iLengthOriginal);
  577. }
  578. }
  579. if (!m_psidOriginal)
  580. m_psidOriginal = LocalAlloc(LPTR, iLength);
  581. if (m_psidOriginal)
  582. {
  583. CopyMemory(m_psidOriginal, psid, iLength);
  584. }
  585. else
  586. {
  587. hr = E_OUTOFMEMORY;
  588. }
  589. }
  590. if (m_siObjectInfo.dwFlags & SI_OWNER_RECURSE)
  591. CheckDlgButton(hDlg, IDC_OWN_RECURSE, BST_UNCHECKED);
  592. }
  593. exit_gracefully:
  594. if (FAILED(hr))
  595. {
  596. if(hr == HRESULT_FROM_WIN32(ERROR_INVALID_OWNER))
  597. {
  598. MsgPopup(hDlg,
  599. MAKEINTRESOURCE(IDS_NO_RESTORE_PRIV),
  600. MAKEINTRESOURCE(IDS_SECURITY),
  601. MB_OK | MB_ICONERROR,
  602. ::hModule,
  603. m_siObjectInfo.pszObjectName);
  604. }
  605. else
  606. {
  607. SysMsgPopup(hDlg,
  608. MAKEINTRESOURCE(IDS_OWNER_WRITE_FAILED),
  609. MAKEINTRESOURCE(IDS_SECURITY),
  610. MB_OK | MB_ICONERROR,
  611. ::hModule,
  612. hr,
  613. m_siObjectInfo.pszObjectName);
  614. }
  615. }
  616. TraceLeaveVoid();
  617. }
  618. void
  619. COwnerPage::OnReset(HWND hDlg)
  620. {
  621. PSECURITY_DESCRIPTOR pSD = NULL;
  622. HWND hOwner;
  623. PSID psid;
  624. HRESULT hr;
  625. TraceEnter(TRACE_OWNER, "COwnerPage::OnReset");
  626. TraceAssert(!m_bAbortPage);
  627. hOwner = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
  628. psid = (PSID)GetSelectedItemData(hOwner, NULL);
  629. hr = m_psi->GetSecurity(OWNER_SECURITY_INFORMATION, &pSD, TRUE);
  630. if (SUCCEEDED(hr))
  631. {
  632. PSID psidDefault = NULL;
  633. BOOL bDefaulted;
  634. if (pSD)
  635. GetSecurityDescriptorOwner(pSD, &psidDefault, &bDefaulted);
  636. if (psidDefault && !EqualSid(psidDefault, psid))
  637. {
  638. int iSel = AddSid(hOwner, psidDefault, m_siObjectInfo.pszServerName);
  639. if (iSel != -1)
  640. {
  641. ListView_SetItemState(hOwner, iSel, LVIS_SELECTED, LVIS_SELECTED);
  642. PropSheet_Changed(GetParent(hDlg), hDlg);
  643. ListView_SortItems(hOwner,OwnerCompareProc,NULL);
  644. }
  645. }
  646. LocalFree(pSD);
  647. }
  648. else
  649. {
  650. SysMsgPopup(hDlg,
  651. MAKEINTRESOURCE(IDS_OPERATION_FAILED),
  652. MAKEINTRESOURCE(IDS_SECURITY),
  653. MB_OK | MB_ICONERROR,
  654. ::hModule,
  655. hr);
  656. }
  657. TraceLeaveVoid();
  658. }
  659. BOOL
  660. COwnerPage::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  661. {
  662. BOOL bResult = TRUE;
  663. switch(uMsg)
  664. {
  665. case WM_INITDIALOG:
  666. InitDlg(hDlg);
  667. break;
  668. case WM_NOTIFY:
  669. {
  670. LPNM_LISTVIEW pnmlv = (LPNM_LISTVIEW)lParam;
  671. switch (((LPNMHDR)lParam)->code)
  672. {
  673. case LVN_ITEMCHANGED:
  674. if (pnmlv->uChanged & LVIF_STATE)
  675. {
  676. //if "Other users or group" entry is selected,
  677. //no action is required
  678. LVITEM lv;
  679. ZeroMemory(&lv,sizeof(LVITEM));
  680. lv.mask = LVIF_PARAM;
  681. lv.iItem = pnmlv->iItem;
  682. ListView_GetItem(((LPNMHDR)lParam)->hwndFrom,&lv);
  683. //A user or group is selected
  684. if(lv.lParam)
  685. {
  686. // item *gaining* selection
  687. if ((pnmlv->uNewState & LVIS_SELECTED) &&
  688. !(pnmlv->uOldState & LVIS_SELECTED))
  689. {
  690. PropSheet_Changed(GetParent(hDlg), hDlg);
  691. }
  692. }
  693. }
  694. break;
  695. case LVN_DELETEITEM:
  696. if (pnmlv->lParam)
  697. FreeOwnerEntry((Owner_LV_Entry*)pnmlv->lParam);
  698. break;
  699. case NM_SETFOCUS:
  700. if (((LPNMHDR)lParam)->idFrom == IDC_OWN_OWNERLIST)
  701. {
  702. // Make sure the listview is always focused on something,
  703. // otherwise you can't tab into the control.
  704. HWND hwndLV = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
  705. if (-1 == ListView_GetNextItem(hwndLV, -1, LVNI_FOCUSED))
  706. ListView_SetItemState(hwndLV, 0, LVIS_FOCUSED, LVIS_FOCUSED);
  707. }
  708. break;
  709. case PSN_QUERYINITIALFOCUS:
  710. {
  711. // Set initial focus to the list of potential owners
  712. HWND hwndLV = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
  713. if (IsWindowEnabled(hwndLV))
  714. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LONG_PTR)hwndLV);
  715. else
  716. bResult = FALSE;
  717. }
  718. break;
  719. case PSN_APPLY:
  720. OnApply(hDlg, (BOOL)(((LPPSHNOTIFY)lParam)->lParam));
  721. break;
  722. case NM_CLICK:
  723. case NM_RETURN:
  724. {
  725. if(wParam == IDC_EFF_STATIC)
  726. {
  727. HtmlHelp(hDlg,
  728. c_szOwnerHelpLink,
  729. HH_DISPLAY_TOPIC,
  730. 0);
  731. }
  732. }
  733. break;
  734. default:
  735. bResult = FALSE;
  736. }
  737. }
  738. break;
  739. case WM_COMMAND:
  740. switch (GET_WM_COMMAND_ID(wParam, lParam))
  741. {
  742. case IDC_OWN_RECURSE:
  743. if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
  744. {
  745. //If there is no original and no sid is selected
  746. //don't enable apply
  747. int iSelected = -1;
  748. HWND hwndOwnerList = NULL;
  749. PSID psid = NULL;
  750. hwndOwnerList = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
  751. Owner_LV_Entry * pLVEntry = (Owner_LV_Entry *)GetSelectedItemData(hwndOwnerList, &iSelected);
  752. if(pLVEntry)
  753. {
  754. psid = pLVEntry->pSid;
  755. }
  756. // If there is no selection, use the original
  757. if (!psid)
  758. psid = m_psidOriginal;
  759. // If no selection and no original, then we can't do anything
  760. if (psid)
  761. PropSheet_Changed(GetParent(hDlg), hDlg);
  762. }
  763. break;
  764. case IDC_OWN_RESET:
  765. OnReset(hDlg);
  766. break;
  767. case IDC_OWN_OTHER_USER:
  768. OnSelect(hDlg);
  769. break;
  770. default:
  771. bResult = FALSE;
  772. }
  773. break;
  774. case WM_HELP:
  775. if (IsWindowEnabled(hDlg))
  776. {
  777. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  778. c_szAcluiHelpFile,
  779. HELP_WM_HELP,
  780. (DWORD_PTR)aOwnerHelpIDs);
  781. }
  782. break;
  783. case WM_CONTEXTMENU:
  784. if (IsWindowEnabled(hDlg))
  785. {
  786. WinHelp(hDlg,
  787. c_szAcluiHelpFile,
  788. HELP_CONTEXTMENU,
  789. (DWORD_PTR)aOwnerHelpIDs);
  790. }
  791. break;
  792. default:
  793. bResult = FALSE;
  794. }
  795. return bResult;
  796. }