mirror of https://github.com/tongzx/nt5src
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
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;
|
|
}
|
|
|
|
|