Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

425 lines
9.0 KiB

// Copyright (C) 1997 Microsoft Corporation
//
// UserMemberPage class
//
// 9-11-97 sburns
#include "headers.hxx"
#include "UserMemberPage.hpp"
#include "resource.h"
#include "lsm.h"
#include "adsi.hpp"
#include "MemberVisitor.hpp"
#include "dlgcomm.hpp"
static const DWORD HELP_MAP[] =
{
IDC_GROUPS, idh_memberof_list,
IDC_ADD, idh_memberof_add,
IDC_REMOVE, idh_memberof_remove,
0, 0
};
UserMemberPage::UserMemberPage(
MMCPropertyPage::NotificationState* state,
const String& userADSIPath)
:
ADSIPage(
IDD_USER_MEMBER,
HELP_MAP,
state,
userADSIPath)
{
LOG_CTOR2(UserMemberPage, userADSIPath);
}
UserMemberPage::~UserMemberPage()
{
LOG_DTOR2(UserMemberPage, GetADSIPath());
}
void
UserMemberPage::OnInit()
{
LOG_FUNCTION(UserMemberPage::OnInit);
// Setup the controls
listview =
new MembershipListView(
Win::GetDlgItem(hwnd, IDC_GROUPS),
GetMachineName(),
MembershipListView::USER_MEMBERSHIP);
// load the group properties into the dialog.
HRESULT hr = S_OK;
do
{
SmartInterface<IADsUser> user(0);
hr = ADSI::GetUser(GetADSIPath(), user);
BREAK_ON_FAILED_HRESULT(hr);
// populate the list with group membership
MemberVisitor
visitor(original_groups, hwnd, GetObjectName(), GetMachineName());
hr = ADSI::VisitGroups(user, visitor);
BREAK_ON_FAILED_HRESULT(hr);
listview->SetContents(original_groups);
}
while (0);
if (FAILED(hr))
{
popup.Error(
hwnd,
hr,
String::format(IDS_ERROR_READING_USER, GetObjectName().c_str()));
Win::PostMessage(Win::GetParent(hwnd), WM_CLOSE, 0, 0);
}
ClearChanges();
enable();
}
void
UserMemberPage::enable()
{
// LOG_FUNCTION(UserMemberPage::enable);
bool selected =
Win::ListView_GetSelectedCount(
Win::GetDlgItem(hwnd, IDC_GROUPS)) > 0;
HWND removeButton = Win::GetDlgItem(hwnd, IDC_REMOVE);
if (!selected)
{
// If we're about to disable the remove button, check to see if it
// has focus first. If it does, we need to move focus to another
// control. Similarly for default pushbutton style.
// NTRAID#NTBUG9-435045-2001/07/13-sburns
if (removeButton == ::GetFocus())
{
HWND addButton = Win::GetDlgItem(hwnd, IDC_ADD);
Win::SetFocus(addButton);
Win::Button_SetStyle(addButton, BS_DEFPUSHBUTTON, true);
Win::Button_SetStyle(removeButton, BS_PUSHBUTTON, true);
}
}
Win::EnableWindow(removeButton, selected);
}
bool
UserMemberPage::OnNotify(
HWND /* windowFrom */ ,
UINT_PTR controlIDFrom,
UINT code,
LPARAM lparam)
{
LOG_FUNCTION(UserMemberPage::OnNotify);
switch (controlIDFrom)
{
case IDC_GROUPS:
{
switch (code)
{
case LVN_ITEMCHANGED:
{
ASSERT(lparam);
if (lparam)
{
NMLISTVIEW* lv = reinterpret_cast<NMLISTVIEW*>(lparam);
if (lv->uChanged & LVIF_STATE)
{
// a list item changed state
enable();
}
}
break;
}
case LVN_KEYDOWN:
{
ASSERT(lparam);
if (lparam)
{
NMLVKEYDOWN* kd = reinterpret_cast<NMLVKEYDOWN*>(lparam);
if (kd->wVKey == VK_INSERT)
{
listview->OnAddButton();
}
else if (kd->wVKey == VK_DELETE)
{
listview->OnRemoveButton();
}
}
break;
}
case LVN_INSERTITEM:
case LVN_DELETEITEM:
{
SetChanged(controlIDFrom);
Win::PropSheet_Changed(Win::GetParent(hwnd), hwnd);
break;
}
default:
{
break;
}
}
break;
}
default:
{
}
}
return true;
}
void
UserMemberPage::OnDestroy()
{
LOG_FUNCTION(UserMemberPage::OnDestroy);
delete listview;
listview = 0;
}
bool
UserMemberPage::OnCommand(
HWND /* windowFrom */ ,
unsigned controlIDFrom,
unsigned code)
{
// LOG_FUNCTION(UserMemberPage::OnCommand);
switch (controlIDFrom)
{
case IDC_ADD:
{
if (code == BN_CLICKED)
{
listview->OnAddButton();
}
break;
}
case IDC_REMOVE:
{
if (code == BN_CLICKED)
{
listview->OnRemoveButton();
}
break;
}
default:
{
break;
}
}
return true;
}
bool
UserMemberPage::OnApply(bool isClosing)
{
LOG_FUNCTION(UserMemberPage::OnApply);
if (WasChanged(IDC_GROUPS))
{
// save the changes thru ADSI
HRESULT hr = S_OK;
do
{
SmartInterface<IADsUser> user(0);
hr = ADSI::GetUser(GetADSIPath(), user);
BREAK_ON_FAILED_HRESULT(hr);
SmartInterface<IADs> iads(0);
hr = iads.AcquireViaQueryInterface(user);
BREAK_ON_FAILED_HRESULT(hr);
String sidPath;
hr = ADSI::GetSidPath(iads, sidPath);
BREAK_ON_FAILED_HRESULT(hr);
MemberList new_groups;
listview->GetContents(new_groups);
hr =
ReconcileMembershipChanges(
sidPath,
original_groups,
new_groups);
BREAK_ON_FAILED_HRESULT(hr);
if (!isClosing)
{
// refresh the listview
original_groups.clear();
MemberVisitor
visitor(
original_groups,
hwnd,
GetObjectName(),
GetMachineName());
hr = ADSI::VisitGroups(user, visitor);
BREAK_ON_FAILED_HRESULT(hr);
listview->SetContents(original_groups);
}
SetChangesApplied();
ClearChanges();
}
while (0);
if (FAILED(hr))
{
popup.Error(
hwnd,
hr,
String::format(
IDS_ERROR_SETTING_USER_PROPERTIES,
GetObjectName().c_str(),
GetMachineName().c_str()));
}
}
return true;
}
HRESULT
UserMemberPage::ReconcileMembershipChanges(
const String& userADSIPath,
MemberList originalGroups, // a copy
const MemberList& newGroups)
{
LOG_FUNCTION2(UserMemberPage::ReconcileMembershipChanges, userADSIPath);
ASSERT(!userADSIPath.empty());
bool successful = true; // be optimistic!
HRESULT hr = S_OK;
for (
MemberList::iterator i = newGroups.begin();
i != newGroups.end();
i++)
{
MemberInfo& info = *i;
MemberList::iterator f =
std::find(originalGroups.begin(), originalGroups.end(), info);
if (f != originalGroups.end())
{
// found. remove the matching node in the original list
originalGroups.erase(f);
}
else
{
// not found. Add the user as a member of the group
SmartInterface<IADsGroup> group(0);
hr = ADSI::GetGroup(info.path, group);
if (SUCCEEDED(hr))
{
hr = group->Add(AutoBstr(userADSIPath));
if (hr == Win32ToHresult(ERROR_MEMBER_IN_ALIAS))
{
// already a member: pop up a warning but don't consider this
// a real error. 6791
hr = S_OK;
String name = GetObjectName();
BSTR groupName;
HRESULT anotherHr = group->get_Name(&groupName);
if (SUCCEEDED(anotherHr))
{
popup.Info(
hwnd,
String::format(
IDS_ALREADY_MEMBER,
name.c_str(),
groupName));
::SysFreeString(groupName);
}
}
}
if (FAILED(hr))
{
LOG_HRESULT(hr);
successful = false;
}
}
}
// at this point, the original list contains only those nodes which are
// not in the new list. Remove these from the group membership
for (
i = originalGroups.begin();
i != originalGroups.end();
i++)
{
SmartInterface<IADsGroup> group(0);
hr = ADSI::GetGroup(i->path, group);
if (SUCCEEDED(hr))
{
hr = group->Remove(AutoBstr(userADSIPath));
// CODEWORK: what if the member is not part of the group?
}
if (FAILED(hr))
{
LOG_HRESULT(hr);
successful = false;
}
}
if (!successful)
{
popup.Error(
hwnd,
0,
String::format(
IDS_ERROR_CHANGING_MEMBERSHIP,
GetObjectName().c_str()));
}
return hr;
}