745 lines
21 KiB
C++
745 lines
21 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||
|
//
|
||
|
// File: owner.cpp
|
||
|
//
|
||
|
// This file contains the implementation of the Owner page.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include "aclpriv.h"
|
||
|
#include "sddl.h" // ConvertSidToStringSid
|
||
|
|
||
|
|
||
|
//
|
||
|
// Context Help IDs.
|
||
|
//
|
||
|
const static DWORD aOwnerHelpIDs[] =
|
||
|
{
|
||
|
IDC_OWN_CURRENTOWNER_STATIC, IDH_OWN_CURRENTOWNER,
|
||
|
IDC_OWN_CURRENTOWNER, IDH_OWN_CURRENTOWNER,
|
||
|
IDC_OWN_OWNERLIST_STATIC, IDH_OWN_OWNERLIST,
|
||
|
IDC_OWN_OWNERLIST, IDH_OWN_OWNERLIST,
|
||
|
IDC_OWN_RECURSE, IDH_OWN_RECURSE,
|
||
|
IDC_OWN_RESET, IDH_OWN_RESET,
|
||
|
IDC_ACEL_STATIC, -1,
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// These SIDs are always added to the list of possible owners
|
||
|
//
|
||
|
const static UI_TokenSid g_uiTokenSids[] =
|
||
|
{
|
||
|
UI_TSID_CurrentProcessUser,
|
||
|
UI_TSID_CurrentProcessOwner,
|
||
|
//UI_TSID_CurrentProcessPrimaryGroup,
|
||
|
};
|
||
|
|
||
|
|
||
|
class COwnerPage : public CSecurityPage
|
||
|
{
|
||
|
private:
|
||
|
PSID m_psidOriginal;
|
||
|
PSID m_psidNetID;
|
||
|
HANDLE m_hSidThread;
|
||
|
|
||
|
public:
|
||
|
COwnerPage(LPSECURITYINFO psi, SI_OBJECT_INFO *psiObjectInfo);
|
||
|
virtual ~COwnerPage(void);
|
||
|
|
||
|
private:
|
||
|
virtual BOOL DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
void InitDlg(HWND hDlg);
|
||
|
int AddSid(HWND hOwner, PSID psid, LPCTSTR pszServerName = NULL);
|
||
|
void OnApply(HWND hDlg, BOOL bClose);
|
||
|
void OnReset(HWND hDlg);
|
||
|
};
|
||
|
|
||
|
|
||
|
HPROPSHEETPAGE
|
||
|
CreateOwnerPage(LPSECURITYINFO psi, SI_OBJECT_INFO *psiObjectInfo)
|
||
|
{
|
||
|
HPROPSHEETPAGE hPage = NULL;
|
||
|
COwnerPage *pPage;
|
||
|
|
||
|
TraceEnter(TRACE_OWNER, "CreateOwnerPage");
|
||
|
|
||
|
pPage = new COwnerPage(psi, psiObjectInfo);
|
||
|
|
||
|
if (pPage)
|
||
|
{
|
||
|
hPage = pPage->CreatePropSheetPage(MAKEINTRESOURCE(IDD_OWNER_PAGE));
|
||
|
|
||
|
if (!hPage)
|
||
|
delete pPage;
|
||
|
}
|
||
|
|
||
|
TraceLeaveValue(hPage);
|
||
|
}
|
||
|
|
||
|
|
||
|
COwnerPage::COwnerPage(LPSECURITYINFO psi, SI_OBJECT_INFO *psiObjectInfo)
|
||
|
: CSecurityPage(psi, SI_PAGE_OWNER), m_psidOriginal(NULL), m_psidNetID(NULL),
|
||
|
m_hSidThread(NULL)
|
||
|
{
|
||
|
// Lookup known SIDs asynchronously so the dialog
|
||
|
// will initialize faster
|
||
|
HDPA hSids = DPA_Create(ARRAYSIZE(g_uiTokenSids));
|
||
|
if (hSids)
|
||
|
{
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
LPCWSTR pszServer = NULL;
|
||
|
if (psiObjectInfo)
|
||
|
pszServer = psiObjectInfo->pszServerName;
|
||
|
|
||
|
for (int i = 0; i < ARRAYSIZE(g_uiTokenSids); i++)
|
||
|
DPA_AppendPtr(hSids, QueryTokenSid(g_uiTokenSids[i]));
|
||
|
|
||
|
m_psidNetID = GetAuthenticationID(pszServer);
|
||
|
if (m_psidNetID)
|
||
|
DPA_AppendPtr(hSids, m_psidNetID);
|
||
|
|
||
|
LookupSidsAsync(hSids, W2CT(pszServer), m_psi2, NULL, 0, &m_hSidThread);
|
||
|
DPA_Destroy(hSids);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
COwnerPage::~COwnerPage(void)
|
||
|
{
|
||
|
if (m_hSidThread)
|
||
|
CloseHandle(m_hSidThread);
|
||
|
|
||
|
if (m_psidOriginal)
|
||
|
LocalFree(m_psidOriginal);
|
||
|
|
||
|
if (m_psidNetID)
|
||
|
LocalFree(m_psidNetID);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
COwnerPage::AddSid(HWND hOwner, PSID psid, LPCTSTR pszServerName)
|
||
|
{
|
||
|
PUSER_LIST pUserList = NULL;
|
||
|
SID_NAME_USE sidType = SidTypeUnknown;
|
||
|
LPCTSTR pszName = NULL;
|
||
|
LPCTSTR pszLogonName = NULL;
|
||
|
int iItem = -1;
|
||
|
int cItems;
|
||
|
LV_ITEM lvItem;
|
||
|
|
||
|
TraceEnter(TRACE_OWNER, "COwnerPage::AddSid");
|
||
|
TraceAssert(!m_bAbortPage);
|
||
|
|
||
|
if (!psid || !IsValidSid(psid))
|
||
|
ExitGracefully(iItem, -1, "Bad SID parameter");
|
||
|
|
||
|
// Get the name for this SID
|
||
|
if (LookupSid(psid, pszServerName, m_psi2, &pUserList))
|
||
|
{
|
||
|
TraceAssert(NULL != pUserList);
|
||
|
TraceAssert(1 == pUserList->cUsers);
|
||
|
|
||
|
sidType = pUserList->rgUsers[0].SidType;
|
||
|
pszName = pUserList->rgUsers[0].pszName;
|
||
|
pszLogonName = pUserList->rgUsers[0].pszLogonName;
|
||
|
}
|
||
|
|
||
|
switch (sidType)
|
||
|
{
|
||
|
case SidTypeDomain:
|
||
|
case SidTypeDeletedAccount:
|
||
|
case SidTypeInvalid:
|
||
|
case SidTypeUnknown:
|
||
|
case SidTypeComputer:
|
||
|
ExitGracefully(iItem, -1, "SID invalid on target");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
cItems = ListView_GetItemCount(hOwner);
|
||
|
lvItem.mask = LVIF_PARAM;
|
||
|
lvItem.iSubItem = 0;
|
||
|
|
||
|
// See if this SID is already in the list
|
||
|
for (iItem = 0; iItem < cItems; iItem++)
|
||
|
{
|
||
|
lvItem.iItem = iItem;
|
||
|
lvItem.lParam = NULL;
|
||
|
ListView_GetItem(hOwner, &lvItem);
|
||
|
|
||
|
if (lvItem.lParam && EqualSid(psid, (PSID)lvItem.lParam))
|
||
|
{
|
||
|
// This is a hack. We often see alias sids more than once when
|
||
|
// filling the list, e.g. BUILTIN\Administrators. We want to use
|
||
|
// the version of the name that includes the target domain, if
|
||
|
// provided. That is, if pszServerName is non-NULL here, switch
|
||
|
// to the version of the name that goes with pszServerName.
|
||
|
if (pszServerName)
|
||
|
{
|
||
|
lvItem.mask = LVIF_TEXT;
|
||
|
lvItem.pszText = NULL;
|
||
|
if (BuildUserDisplayName(&lvItem.pszText, pszName, pszLogonName)
|
||
|
|| ConvertSidToStringSid(psid, &lvItem.pszText))
|
||
|
{
|
||
|
ListView_SetItem(hOwner, &lvItem);
|
||
|
LocalFreeString(&lvItem.pszText);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (iItem == cItems)
|
||
|
{
|
||
|
// The SID doesn't exist in the list. Add a new entry.
|
||
|
|
||
|
PSID psidCopy = LocalAllocSid(psid);
|
||
|
if (psidCopy)
|
||
|
{
|
||
|
lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||
|
lvItem.iItem = 0;
|
||
|
lvItem.iSubItem = 0;
|
||
|
lvItem.pszText = NULL;
|
||
|
if (!BuildUserDisplayName(&lvItem.pszText, pszName, pszLogonName))
|
||
|
ConvertSidToStringSid(psid, &lvItem.pszText);
|
||
|
lvItem.iImage = GetSidImageIndex(psid, sidType);
|
||
|
lvItem.lParam = (LPARAM)psidCopy;
|
||
|
|
||
|
// Insert principal into list
|
||
|
iItem = ListView_InsertItem(hOwner, &lvItem);
|
||
|
LocalFreeString(&lvItem.pszText);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if (NULL != pUserList)
|
||
|
LocalFree(pUserList);
|
||
|
|
||
|
TraceLeaveValue(iItem);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
COwnerPage::InitDlg(HWND hDlg)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
BOOL bReadOnly;
|
||
|
HWND hOwner = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
|
||
|
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||
|
|
||
|
TraceEnter(TRACE_OWNER, "COwnerPage::InitDlg");
|
||
|
|
||
|
// Hide the Reset button if it isn't supported.
|
||
|
if (!(m_siObjectInfo.dwFlags & SI_RESET) &&
|
||
|
!(m_siObjectInfo.dwFlags & SI_RESET_OWNER))
|
||
|
{
|
||
|
ShowWindow(GetDlgItem(hDlg, IDC_OWN_RESET), SW_HIDE);
|
||
|
}
|
||
|
|
||
|
// Hide the Recurse checkbox if it isn't supported.
|
||
|
if ((m_siObjectInfo.dwFlags & (SI_OWNER_RECURSE | SI_CONTAINER)) != (SI_OWNER_RECURSE | SI_CONTAINER))
|
||
|
{
|
||
|
m_siObjectInfo.dwFlags &= ~SI_OWNER_RECURSE;
|
||
|
HWND hwndRecurse = GetDlgItem(hDlg, IDC_OWN_RECURSE);
|
||
|
ShowWindow(hwndRecurse, SW_HIDE);
|
||
|
EnableWindow(hwndRecurse, FALSE);
|
||
|
}
|
||
|
|
||
|
if (m_bAbortPage)
|
||
|
{
|
||
|
//
|
||
|
// Disable everything
|
||
|
//
|
||
|
bReadOnly = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Create & set the image list for the listview
|
||
|
ListView_SetImageList(hOwner,
|
||
|
LoadImageList(::hModule, MAKEINTRESOURCE(IDB_SID_ICONS)),
|
||
|
LVSIL_SMALL);
|
||
|
|
||
|
//
|
||
|
// Add the "Name" column (the only column on this page)
|
||
|
//
|
||
|
RECT rc;
|
||
|
GetClientRect(hOwner, &rc);
|
||
|
|
||
|
LoadString(::hModule, IDS_NAME, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
|
||
|
LV_COLUMN col;
|
||
|
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
|
||
|
col.fmt = LVCFMT_LEFT;
|
||
|
col.pszText = szBuffer;
|
||
|
col.iSubItem = 0;
|
||
|
col.cx = rc.right;
|
||
|
ListView_InsertColumn(hOwner, 0, &col);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Make a copy of the current owner sid
|
||
|
//
|
||
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
||
|
|
||
|
HRESULT hr = m_psi->GetSecurity(OWNER_SECURITY_INFORMATION, &pSD, FALSE);
|
||
|
if (pSD)
|
||
|
{
|
||
|
PSID psidOwner = NULL;
|
||
|
BOOL bDefaulted;
|
||
|
|
||
|
GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted);
|
||
|
|
||
|
if (psidOwner)
|
||
|
{
|
||
|
UINT iLength = GetLengthSid(psidOwner);
|
||
|
m_psidOriginal = LocalAlloc(LPTR, iLength);
|
||
|
if (m_psidOriginal)
|
||
|
CopyMemory(m_psidOriginal, psidOwner, iLength);
|
||
|
}
|
||
|
LocalFree(pSD);
|
||
|
}
|
||
|
|
||
|
// Test for writeability
|
||
|
bReadOnly = !!(m_siObjectInfo.dwFlags & SI_OWNER_READONLY);
|
||
|
} // !m_bAbortPage
|
||
|
|
||
|
//
|
||
|
// Iterate through the groups on this process's token looking for
|
||
|
// the SE_GROUP_OWNER attribute.
|
||
|
//
|
||
|
if (!bReadOnly)
|
||
|
{
|
||
|
HANDLE hProcessToken = NULL;
|
||
|
|
||
|
//
|
||
|
// Wait for the known SIDs to be resolved so we don't try
|
||
|
// to look them up twice.
|
||
|
//
|
||
|
if (m_hSidThread)
|
||
|
{
|
||
|
WaitForSingleObject(m_hSidThread, INFINITE);
|
||
|
CloseHandle(m_hSidThread);
|
||
|
m_hSidThread = NULL;
|
||
|
}
|
||
|
|
||
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken))
|
||
|
{
|
||
|
// Allocate a buffer for the TOKEN_GROUPS information
|
||
|
ULONG cbBuffer = 1024; // start with 1k
|
||
|
LPVOID pBuffer = LocalAlloc(LPTR, cbBuffer);
|
||
|
|
||
|
if (pBuffer)
|
||
|
{
|
||
|
if (!GetTokenInformation(hProcessToken,
|
||
|
TokenGroups,
|
||
|
pBuffer,
|
||
|
cbBuffer,
|
||
|
&cbBuffer))
|
||
|
{
|
||
|
LocalFree(pBuffer);
|
||
|
pBuffer = NULL;
|
||
|
|
||
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
pBuffer = LocalAlloc(LPTR, cbBuffer);// size returned above
|
||
|
if (pBuffer && !GetTokenInformation(hProcessToken,
|
||
|
TokenGroups,
|
||
|
pBuffer,
|
||
|
cbBuffer,
|
||
|
&cbBuffer))
|
||
|
{
|
||
|
LocalFree(pBuffer);
|
||
|
pBuffer = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pBuffer)
|
||
|
{
|
||
|
PTOKEN_GROUPS ptg = (PTOKEN_GROUPS)pBuffer;
|
||
|
for (ULONG i = 0; i < ptg->GroupCount; i++)
|
||
|
{
|
||
|
DWORD dwAttr = ptg->Groups[i].Attributes;
|
||
|
if ((dwAttr & SE_GROUP_OWNER) && !(dwAttr & SE_GROUP_LOGON_ID))
|
||
|
{
|
||
|
AddSid(hOwner, ptg->Groups[i].Sid, m_siObjectInfo.pszServerName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (pBuffer != NULL)
|
||
|
LocalFree(pBuffer);
|
||
|
}
|
||
|
CloseHandle(hProcessToken);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now add in the additional possible sids
|
||
|
//
|
||
|
for (int i = 0; i < ARRAYSIZE(g_uiTokenSids); i++)
|
||
|
AddSid(hOwner, QueryTokenSid(g_uiTokenSids[i]));
|
||
|
|
||
|
AddSid(hOwner, m_psidNetID, m_siObjectInfo.pszServerName);
|
||
|
}
|
||
|
|
||
|
if (!m_bAbortPage)
|
||
|
{
|
||
|
PUSER_LIST pUserList = NULL;
|
||
|
|
||
|
LoadString(::hModule, IDS_OWNER_CANT_DISPLAY, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
|
||
|
// Finally, look up a name for the original SID.
|
||
|
if (m_psidOriginal)
|
||
|
{
|
||
|
LPTSTR pszName = NULL;
|
||
|
|
||
|
// Get the "S-1-5-blah" form of the SID in case the lookup fails
|
||
|
if (ConvertSidToStringSid(m_psidOriginal, &pszName))
|
||
|
{
|
||
|
lstrcpyn(szBuffer, pszName, ARRAYSIZE(szBuffer));
|
||
|
LocalFreeString(&pszName);
|
||
|
}
|
||
|
|
||
|
if (LookupSid(m_psidOriginal, m_siObjectInfo.pszServerName, m_psi2, &pUserList))
|
||
|
{
|
||
|
TraceAssert(NULL != pUserList);
|
||
|
TraceAssert(1 == pUserList->cUsers);
|
||
|
|
||
|
if (BuildUserDisplayName(&pszName, pUserList->rgUsers[0].pszName, pUserList->rgUsers[0].pszLogonName))
|
||
|
{
|
||
|
lstrcpyn(szBuffer, pszName, ARRAYSIZE(szBuffer));
|
||
|
LocalFreeString(&pszName);
|
||
|
}
|
||
|
LocalFree(pUserList);
|
||
|
}
|
||
|
}
|
||
|
SetDlgItemText(hDlg, IDC_OWN_CURRENTOWNER, szBuffer);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the current user cannot change owners, gray out the list box.
|
||
|
//
|
||
|
if (bReadOnly)
|
||
|
{
|
||
|
// Disable the list and notify the user that it's read-only.
|
||
|
EnableWindow(hOwner, FALSE);
|
||
|
EnableWindow(GetDlgItem(hDlg, IDC_OWN_RESET), FALSE);
|
||
|
EnableWindow(GetDlgItem(hDlg, IDC_OWN_RECURSE), FALSE);
|
||
|
|
||
|
//
|
||
|
// If we're aborting, then the user should have been notified
|
||
|
// during the propsheetpage callback. Don't put up another
|
||
|
// message here.
|
||
|
//
|
||
|
if (S_OK == m_hrLastPSPCallbackResult)
|
||
|
{
|
||
|
MsgPopup(hDlg,
|
||
|
MAKEINTRESOURCE(IDS_OWNER_READONLY),
|
||
|
MAKEINTRESOURCE(IDS_SECURITY),
|
||
|
MB_OK | MB_ICONINFORMATION,
|
||
|
::hModule,
|
||
|
m_siObjectInfo.pszObjectName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetCursor(hcur);
|
||
|
|
||
|
TraceLeaveVoid();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
COwnerPage::OnApply(HWND hDlg, BOOL bClose)
|
||
|
{
|
||
|
int iSelected = -1;
|
||
|
HWND hwndOwnerList;
|
||
|
PSID psid;
|
||
|
BOOL bRecurse = FALSE;
|
||
|
SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION;
|
||
|
BOOL bEqualSid = FALSE;
|
||
|
|
||
|
TraceEnter(TRACE_OWNER, "COwnerPage::OnApply");
|
||
|
|
||
|
hwndOwnerList = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
|
||
|
psid = (PSID)GetSelectedItemData(hwndOwnerList, &iSelected);
|
||
|
|
||
|
// If there is no selection, use the original
|
||
|
if (!psid)
|
||
|
psid = m_psidOriginal;
|
||
|
|
||
|
// If no selection and no original, then we can't do anything
|
||
|
if (!psid)
|
||
|
TraceLeaveVoid();
|
||
|
|
||
|
|
||
|
if ((m_siObjectInfo.dwFlags & SI_OWNER_RECURSE)
|
||
|
&& IsDlgButtonChecked(hDlg, IDC_OWN_RECURSE) == BST_CHECKED)
|
||
|
{
|
||
|
bRecurse = TRUE;
|
||
|
}
|
||
|
|
||
|
// Has anything changed?
|
||
|
if (m_psidOriginal
|
||
|
&& ( (m_psidOriginal == psid) || EqualSid(m_psidOriginal, psid) )
|
||
|
&& !bRecurse)
|
||
|
{
|
||
|
// Nothing has changed
|
||
|
TraceLeaveVoid();
|
||
|
}
|
||
|
|
||
|
SECURITY_DESCRIPTOR sd = {0};
|
||
|
DWORD dwPriv = SE_TAKE_OWNERSHIP_PRIVILEGE;
|
||
|
HANDLE hToken = INVALID_HANDLE_VALUE;
|
||
|
HRESULT hr;
|
||
|
|
||
|
TraceAssert(!m_bAbortPage);
|
||
|
|
||
|
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
|
||
|
SetSecurityDescriptorOwner(&sd, psid, FALSE);
|
||
|
|
||
|
//
|
||
|
// ISecurityInformation::SetSecurity doesn't have a parameter to indicate
|
||
|
// that the owner should be recursively applied. We could add a parameter,
|
||
|
// but for now, just use one of the unused SECURITY_INFORMATION bits.
|
||
|
// The security descriptor structure is unlikely to change so this should
|
||
|
// be ok for now.
|
||
|
if (bRecurse)
|
||
|
si |= SI_OWNER_RECURSE;
|
||
|
|
||
|
hToken = EnablePrivileges(&dwPriv, 1);
|
||
|
|
||
|
hr = m_psi->SetSecurity(si, &sd);
|
||
|
|
||
|
ReleasePrivileges(hToken);
|
||
|
|
||
|
if (S_FALSE == hr)
|
||
|
{
|
||
|
// S_FALSE is silent failure (the client should put up UI
|
||
|
// during SetSecurity before returning S_FALSE).
|
||
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
|
||
|
}
|
||
|
else if (S_OK == hr && !bClose)
|
||
|
{
|
||
|
|
||
|
//Inform the Effective Permission tab that
|
||
|
//Permissions are changed
|
||
|
PropSheet_QuerySiblings(GetParent(hDlg),0,0);
|
||
|
|
||
|
UINT iLength = GetLengthSid(psid);
|
||
|
|
||
|
if (-1 != iSelected)
|
||
|
{
|
||
|
TCHAR szName[MAX_PATH];
|
||
|
szName[0] = TEXT('\0');
|
||
|
ListView_GetItemText(hwndOwnerList, iSelected, 0, szName, ARRAYSIZE(szName));
|
||
|
SetDlgItemText(hDlg, IDC_OWN_CURRENTOWNER, szName);
|
||
|
}
|
||
|
|
||
|
if (!(m_psidOriginal &&
|
||
|
((m_psidOriginal == psid) || EqualSid(m_psidOriginal, psid))))
|
||
|
{
|
||
|
if (m_psidOriginal)
|
||
|
{
|
||
|
UINT iLengthOriginal = (UINT)LocalSize(m_psidOriginal);
|
||
|
if (iLengthOriginal < iLength)
|
||
|
{
|
||
|
LocalFree(m_psidOriginal);
|
||
|
m_psidOriginal = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ZeroMemory(m_psidOriginal, iLengthOriginal);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!m_psidOriginal)
|
||
|
m_psidOriginal = LocalAlloc(LPTR, iLength);
|
||
|
|
||
|
if (m_psidOriginal)
|
||
|
{
|
||
|
CopyMemory(m_psidOriginal, psid, iLength);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
if (m_siObjectInfo.dwFlags & SI_OWNER_RECURSE)
|
||
|
CheckDlgButton(hDlg, IDC_OWN_RECURSE, BST_UNCHECKED);
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
SysMsgPopup(hDlg,
|
||
|
MAKEINTRESOURCE(IDS_OWNER_WRITE_FAILED),
|
||
|
MAKEINTRESOURCE(IDS_SECURITY),
|
||
|
MB_OK | MB_ICONERROR,
|
||
|
::hModule,
|
||
|
hr,
|
||
|
m_siObjectInfo.pszObjectName);
|
||
|
}
|
||
|
|
||
|
TraceLeaveVoid();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
COwnerPage::OnReset(HWND hDlg)
|
||
|
{
|
||
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
||
|
HWND hOwner;
|
||
|
PSID psid;
|
||
|
HRESULT hr;
|
||
|
|
||
|
TraceEnter(TRACE_OWNER, "COwnerPage::OnReset");
|
||
|
TraceAssert(!m_bAbortPage);
|
||
|
|
||
|
hOwner = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
|
||
|
psid = (PSID)GetSelectedItemData(hOwner, NULL);
|
||
|
|
||
|
hr = m_psi->GetSecurity(OWNER_SECURITY_INFORMATION, &pSD, TRUE);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
PSID psidDefault = NULL;
|
||
|
BOOL bDefaulted;
|
||
|
|
||
|
if (pSD)
|
||
|
GetSecurityDescriptorOwner(pSD, &psidDefault, &bDefaulted);
|
||
|
|
||
|
if (psidDefault && !EqualSid(psidDefault, psid))
|
||
|
{
|
||
|
int iSel = AddSid(hOwner, psidDefault, m_siObjectInfo.pszServerName);
|
||
|
|
||
|
if (iSel != -1)
|
||
|
{
|
||
|
ListView_SetItemState(hOwner, iSel, LVIS_SELECTED, LVIS_SELECTED);
|
||
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
||
|
}
|
||
|
}
|
||
|
LocalFree(pSD);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SysMsgPopup(hDlg,
|
||
|
MAKEINTRESOURCE(IDS_OPERATION_FAILED),
|
||
|
MAKEINTRESOURCE(IDS_SECURITY),
|
||
|
MB_OK | MB_ICONERROR,
|
||
|
::hModule,
|
||
|
hr);
|
||
|
}
|
||
|
|
||
|
TraceLeaveVoid();
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
COwnerPage::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
BOOL bResult = TRUE;
|
||
|
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
InitDlg(hDlg);
|
||
|
break;
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
{
|
||
|
LPNM_LISTVIEW pnmlv = (LPNM_LISTVIEW)lParam;
|
||
|
|
||
|
switch (((LPNMHDR)lParam)->code)
|
||
|
{
|
||
|
case LVN_ITEMCHANGED:
|
||
|
if (pnmlv->uChanged & LVIF_STATE)
|
||
|
{
|
||
|
// item *gaining* selection
|
||
|
if ((pnmlv->uNewState & LVIS_SELECTED) &&
|
||
|
!(pnmlv->uOldState & LVIS_SELECTED))
|
||
|
{
|
||
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case LVN_DELETEITEM:
|
||
|
if (pnmlv->lParam)
|
||
|
LocalFree((PSID)pnmlv->lParam);
|
||
|
break;
|
||
|
|
||
|
case NM_SETFOCUS:
|
||
|
if (((LPNMHDR)lParam)->idFrom == IDC_OWN_OWNERLIST)
|
||
|
{
|
||
|
// Make sure the listview is always focused on something,
|
||
|
// otherwise you can't tab into the control.
|
||
|
HWND hwndLV = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
|
||
|
if (-1 == ListView_GetNextItem(hwndLV, -1, LVNI_FOCUSED))
|
||
|
ListView_SetItemState(hwndLV, 0, LVIS_FOCUSED, LVIS_FOCUSED);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PSN_QUERYINITIALFOCUS:
|
||
|
{
|
||
|
// Set initial focus to the list of potential owners
|
||
|
HWND hwndLV = GetDlgItem(hDlg, IDC_OWN_OWNERLIST);
|
||
|
if (IsWindowEnabled(hwndLV))
|
||
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LONG_PTR)hwndLV);
|
||
|
else
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PSN_APPLY:
|
||
|
OnApply(hDlg, (BOOL)(((LPPSHNOTIFY)lParam)->lParam));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||
|
{
|
||
|
case IDC_OWN_RECURSE:
|
||
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
|
||
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
||
|
break;
|
||
|
|
||
|
case IDC_OWN_RESET:
|
||
|
OnReset(hDlg);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_HELP:
|
||
|
if (IsWindowEnabled(hDlg))
|
||
|
{
|
||
|
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
|
||
|
c_szAcluiHelpFile,
|
||
|
HELP_WM_HELP,
|
||
|
(DWORD_PTR)aOwnerHelpIDs);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
if (IsWindowEnabled(hDlg))
|
||
|
{
|
||
|
WinHelp(hDlg,
|
||
|
c_szAcluiHelpFile,
|
||
|
HELP_CONTEXTMENU,
|
||
|
(DWORD_PTR)aOwnerHelpIDs);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
|
||
|
return bResult;
|
||
|
}
|