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.
668 lines
18 KiB
668 lines
18 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Windows NT Directory Service Administration SnapIn
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1999
|
|
//
|
|
// File: toolbar.cpp
|
|
//
|
|
// Contents: DS App
|
|
//
|
|
// History: 30-apr-98 jimharr Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "resource.h"
|
|
|
|
#include "dsutil.h"
|
|
|
|
#include "DSEvent.h"
|
|
|
|
#include "DSdirect.h"
|
|
#include "dsfilter.h"
|
|
#include "dssnap.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
MMCBUTTON g_DSAdmin_SnapinButtons[] =
|
|
{
|
|
{ 2, dsNewUser, !TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
|
|
{ 3, dsNewGroup, !TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
|
|
{ 4, dsNewOU, !TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
|
|
{ 1, dsFilter, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
|
|
{ 0, dsFind, !TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
|
|
{ 5, dsAddMember, !TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
|
|
};
|
|
|
|
|
|
class CButtonStringsHolder
|
|
{
|
|
public:
|
|
CButtonStringsHolder()
|
|
{
|
|
m_astr = NULL;
|
|
}
|
|
~CButtonStringsHolder()
|
|
{
|
|
if (m_astr != NULL)
|
|
delete[] m_astr;
|
|
}
|
|
CString* m_astr; // dynamic array of CStrings
|
|
};
|
|
|
|
CButtonStringsHolder g_astrButtonStrings;
|
|
|
|
CONST INT cButtons = sizeof(g_DSAdmin_SnapinButtons)/sizeof(MMCBUTTON);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// IExtendControlbar
|
|
|
|
HRESULT CDSEvent::SetControlbar (LPCONTROLBAR pControlbar)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// we are shutting down (get passed NULL)
|
|
//
|
|
if (pControlbar == NULL)
|
|
{
|
|
if (m_pControlbar != NULL)
|
|
{
|
|
//
|
|
// assign to a variable on the stack to avoid
|
|
// reentrancy problem: the Release() call might
|
|
// cause another call in this function with null argument
|
|
//
|
|
LPCONTROLBAR pControlbarTemp = m_pControlbar;
|
|
m_pControlbar = NULL;
|
|
pControlbarTemp->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
CBitmap bm;
|
|
if (m_pComponentData->QuerySnapinType() == SNAPINTYPE_DS)
|
|
{
|
|
//
|
|
// Store the control bar interface pointer
|
|
//
|
|
if (m_pControlbar == NULL)
|
|
{
|
|
m_pControlbar = pControlbar;
|
|
TRACE(L"CDSEvent::SetControlbar() m_pControlbar->AddRef()\n",m_pControlbar);
|
|
m_pControlbar->AddRef();
|
|
}
|
|
|
|
//
|
|
// Create the toolbar if necessary
|
|
//
|
|
if (m_pToolbar == NULL)
|
|
{
|
|
hr = m_pControlbar->Create (TOOLBAR,
|
|
this,
|
|
(IUnknown **) &m_pToolbar);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
bm.LoadBitmap (MAKEINTRESOURCE (IDB_BUTTONS));
|
|
LoadToolbarStrings (g_DSAdmin_SnapinButtons);
|
|
hr = m_pToolbar->AddBitmap (cButtons, (HBITMAP)bm, 16, 16, RGB(255,0,255));
|
|
hr = m_pToolbar->AddButtons (cButtons, g_DSAdmin_SnapinButtons);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = m_pControlbar->Attach (TOOLBAR, (IUnknown *) m_pToolbar);
|
|
}
|
|
m_UseSelectionParent = FALSE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDSEvent::LoadToolbarStrings (MMCBUTTON * Buttons)
|
|
{
|
|
if (g_astrButtonStrings.m_astr == NULL )
|
|
{
|
|
// load strings
|
|
g_astrButtonStrings.m_astr = new CString[2*cButtons];
|
|
for (UINT i = 0; i < cButtons; i++)
|
|
{
|
|
UINT iButtonTextId = 0, iTooltipTextId = 0;
|
|
|
|
switch (Buttons[i].idCommand)
|
|
{
|
|
case dsNewUser:
|
|
iButtonTextId = IDS_BUTTON_NEW_USER;
|
|
iTooltipTextId = IDS_TOOLTIP_NEW_USER;
|
|
break;
|
|
case dsNewGroup:
|
|
iButtonTextId = IDS_BUTTON_NEW_GROUP;
|
|
iTooltipTextId = IDS_TOOLTIP_NEW_GROUP;
|
|
break;
|
|
case dsNewOU:
|
|
iButtonTextId = IDS_BUTTON_NEW_OU;
|
|
iTooltipTextId = IDS_TOOLTIP_NEW_OU;
|
|
break;
|
|
case dsFilter:
|
|
iButtonTextId = IDS_BUTTON_FILTER;
|
|
iTooltipTextId = IDS_TOOLTIP_FILTER;
|
|
break;
|
|
case dsFind:
|
|
iButtonTextId = IDS_BUTTON_FIND;
|
|
iTooltipTextId = IDS_TOOLTIP_FIND;
|
|
break;
|
|
case dsAddMember:
|
|
iButtonTextId = IDS_BUTTON_ADD_MEMBER;
|
|
iTooltipTextId = IDS_TOOLTIP_ADD_MEMBER;
|
|
break;
|
|
default:
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
g_astrButtonStrings.m_astr[i*2].LoadString(iButtonTextId);
|
|
Buttons[i].lpButtonText =
|
|
const_cast<BSTR>((LPCTSTR)(g_astrButtonStrings.m_astr[i*2]));
|
|
|
|
g_astrButtonStrings.m_astr[(i*2)+1].LoadString(iTooltipTextId);
|
|
Buttons[i].lpTooltipText =
|
|
const_cast<BSTR>((LPCTSTR)(g_astrButtonStrings.m_astr[(i*2)+1]));
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CDSEvent::ControlbarNotify (MMC_NOTIFY_TYPE event,
|
|
LPARAM arg,
|
|
LPARAM param)
|
|
{
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
CWaitCursor cwait;
|
|
|
|
HRESULT hr = S_OK;
|
|
if (m_pControlbar == NULL)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
BOOL bSelect;
|
|
BOOL bScope;
|
|
LPDATAOBJECT pDO = NULL;
|
|
CDSCookie* pSelectedCookie = NULL;
|
|
CDSCookie* pContainerCookie = NULL;
|
|
CInternalFormatCracker dobjCracker;
|
|
CUINode* pUINode = NULL, *pNode = NULL;
|
|
|
|
switch (event)
|
|
{
|
|
case MMCN_SELECT:
|
|
m_pControlbar->Attach (TOOLBAR,
|
|
(IUnknown *) m_pToolbar);
|
|
bSelect = HIWORD(arg);
|
|
bScope = LOWORD(arg);
|
|
|
|
if (bSelect)
|
|
{
|
|
pDO = (LPDATAOBJECT)param;
|
|
dobjCracker.Extract(pDO);
|
|
pUINode = dobjCracker.GetCookie();
|
|
if (pUINode->IsSnapinRoot())
|
|
{
|
|
m_pToolbar->SetButtonState(dsNewUser,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState(dsNewGroup,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState(dsNewOU,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState(dsFind,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState(dsFilter,
|
|
ENABLED,
|
|
TRUE);
|
|
m_pToolbar->SetButtonState(dsAddMember,
|
|
ENABLED,
|
|
FALSE);
|
|
return hr;
|
|
}
|
|
|
|
if (IS_CLASS(pUINode, DS_UI_NODE))
|
|
{
|
|
pSelectedCookie = GetDSCookieFromUINode(pUINode);
|
|
pContainerCookie = pSelectedCookie;
|
|
pNode = pUINode;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable all buttons for non-DS nodes
|
|
//
|
|
m_pToolbar->SetButtonState (dsNewUser,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsNewGroup,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsNewOU,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsFind,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsFilter,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsAddMember,
|
|
ENABLED,
|
|
FALSE);
|
|
return S_OK;
|
|
}
|
|
|
|
if (bScope)
|
|
{
|
|
pContainerCookie = pSelectedCookie;
|
|
m_UseSelectionParent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pNode = pUINode->GetParent();
|
|
if (IS_CLASS(pNode, DS_UI_NODE))
|
|
{
|
|
pContainerCookie = GetDSCookieFromUINode(pNode);
|
|
}
|
|
m_UseSelectionParent = TRUE;
|
|
}
|
|
|
|
if (pContainerCookie != NULL)
|
|
{
|
|
if (pNode->IsContainer())
|
|
{
|
|
int resultUser = -2, resultGroup = -2, resultOU = -2;
|
|
resultUser = IsCreateAllowed (L"user", pContainerCookie);
|
|
if ( resultUser != -2)
|
|
{
|
|
resultGroup = IsCreateAllowed(L"group", pContainerCookie);
|
|
if (resultGroup != -2)
|
|
{
|
|
resultOU = IsCreateAllowed (L"organizationalUnit", pContainerCookie);
|
|
}
|
|
}
|
|
|
|
m_pToolbar->SetButtonState (dsNewUser,
|
|
ENABLED,
|
|
resultUser >= 0);
|
|
m_pToolbar->SetButtonState (dsNewGroup,
|
|
ENABLED,
|
|
resultGroup >= 0);
|
|
m_pToolbar->SetButtonState (dsNewOU,
|
|
ENABLED,
|
|
resultOU >= 0);
|
|
m_pToolbar->SetButtonState (dsFind,
|
|
ENABLED,
|
|
TRUE);
|
|
m_pToolbar->SetButtonState (dsFilter,
|
|
ENABLED,
|
|
TRUE);
|
|
}
|
|
else
|
|
{
|
|
m_pToolbar->SetButtonState (dsNewUser,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsNewGroup,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsNewOU,
|
|
ENABLED,
|
|
FALSE);
|
|
m_pToolbar->SetButtonState (dsFind,
|
|
ENABLED,
|
|
FALSE);
|
|
}
|
|
|
|
if ((wcscmp(pSelectedCookie->GetClass(), L"contact")==0) ||
|
|
(wcscmp(pSelectedCookie->GetClass(), L"user")==0))
|
|
{
|
|
m_pToolbar->SetButtonState (dsAddMember,
|
|
ENABLED,
|
|
TRUE);
|
|
}
|
|
else
|
|
{
|
|
m_pToolbar->SetButtonState (dsAddMember,
|
|
ENABLED,
|
|
FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_UseSelectionParent = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MMCN_BTN_CLICK:
|
|
TRACE(_T("Button clicked. param is %d. pDataObj is %lx.\n"),
|
|
param, arg);
|
|
switch (param)
|
|
{
|
|
case dsNewUser:
|
|
ToolbarCreateObject (CString (L"user"),
|
|
(LPDATAOBJECT) arg);
|
|
break;
|
|
|
|
case dsNewGroup:
|
|
ToolbarCreateObject (CString (L"group"),
|
|
(LPDATAOBJECT) arg);
|
|
break;
|
|
|
|
case dsNewOU:
|
|
ToolbarCreateObject (CString (L"organizationalUnit"),
|
|
(LPDATAOBJECT) arg);
|
|
break;
|
|
|
|
case dsFilter:
|
|
ToolbarFilter();
|
|
break;
|
|
|
|
case dsFind:
|
|
ToolbarFind ((LPDATAOBJECT) arg);
|
|
break;
|
|
|
|
case dsAddMember:
|
|
ToolbarAddMember((LPDATAOBJECT)arg);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
bool CDSEvent::_ShouldUseParentContainer(CUINode* pUINode,
|
|
CDSCookie* pDSNodeData)
|
|
{
|
|
bool result = false;
|
|
|
|
// pUINode should never be NULL at this point or else we would
|
|
// have had a failure by now
|
|
ASSERT(pUINode);
|
|
|
|
if (!pDSNodeData)
|
|
{
|
|
ASSERT(pDSNodeData);
|
|
return result;
|
|
}
|
|
|
|
PCWSTR pszClass = pDSNodeData->GetClass();
|
|
|
|
if (!pszClass)
|
|
{
|
|
ASSERT(pszClass);
|
|
return result;
|
|
}
|
|
|
|
// NTRAID#NTBUG9-755184-2002/12/16-JeffJon
|
|
// We need to have the same behavior whether or
|
|
// not users, groups, and computers are shown as containers
|
|
|
|
if (((!wcscmp(pszClass, L"computer")) ||
|
|
(!wcscmp(pszClass, L"user")) ||
|
|
#ifdef INETORGPERSON
|
|
(!wcscmp(pszClass, L"inetOrgPerson")) ||
|
|
#endif
|
|
(!wcscmp(pszClass,L"group"))) &&
|
|
m_pComponentData->ExpandComputers())
|
|
{
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
if (!pUINode->IsContainer() &&
|
|
m_UseSelectionParent)
|
|
{
|
|
result = true;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
HRESULT CDSEvent::ToolbarCreateObject (CString csClass,
|
|
LPDATAOBJECT lpDataObj)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CUINode* pSelectedUINode = NULL;
|
|
CUINode* pUINode = NULL;
|
|
CDSUINode* pDSUINode = NULL;
|
|
CDSCookie * pCookie = NULL;
|
|
int objIndex = 0;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
if (lpDataObj)
|
|
{
|
|
CInternalFormatCracker dobjCracker;
|
|
VERIFY(SUCCEEDED(dobjCracker.Extract(lpDataObj)));
|
|
pUINode = dobjCracker.GetCookie();
|
|
}
|
|
else
|
|
{
|
|
pUINode = m_pSelectedFolderNode;
|
|
}
|
|
|
|
//
|
|
// Hold on to this so we can unselect it when we
|
|
// create the new object
|
|
//
|
|
pSelectedUINode = pUINode;
|
|
|
|
if (IS_CLASS(pUINode, DS_UI_NODE))
|
|
{
|
|
pCookie = GetDSCookieFromUINode(pUINode);
|
|
pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
|
|
}
|
|
|
|
ASSERT(pCookie != NULL && pDSUINode != NULL);
|
|
if (pCookie == NULL || pDSUINode == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// If the selected node is a leaf, then we need to
|
|
// use the parent container to create the new object
|
|
// If "users, groups, and computers as containers" is
|
|
// set, we need to use the parent container as well.
|
|
// ShouldUserParentContainer() makes these decisions
|
|
|
|
bool bUsingParent = false;
|
|
if (_ShouldUseParentContainer(pUINode, pCookie))
|
|
{
|
|
// Set the UI node to be the parent container
|
|
// and recalculate the DS node a cookie
|
|
|
|
pUINode = pUINode->GetParent();
|
|
bUsingParent = true;
|
|
|
|
if (IS_CLASS(pUINode, DS_UI_NODE))
|
|
{
|
|
pCookie = GetDSCookieFromUINode(pUINode);
|
|
pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
|
|
}
|
|
|
|
ASSERT(pCookie != NULL && pDSUINode != NULL);
|
|
if (pCookie == NULL || pDSUINode == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
// Now go on with the creation
|
|
|
|
objIndex = IsCreateAllowed(csClass, pCookie);
|
|
if (objIndex >= 0)
|
|
{
|
|
CDSUINode * pNewNode= NULL;
|
|
hr = m_pComponentData->_CreateDSObject (pDSUINode,
|
|
pCookie->GetChildListEntry(objIndex),
|
|
NULL,
|
|
&pNewNode);
|
|
if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewNode != NULL))
|
|
{
|
|
m_pFrame->UpdateAllViews(lpDataObj,
|
|
(LPARAM)pNewNode,
|
|
(bUsingParent)
|
|
? DS_CREATE_OCCURRED_RESULT_PANE :
|
|
DS_CREATE_OCCURRED);
|
|
m_pFrame->UpdateAllViews(lpDataObj, (LPARAM)pSelectedUINode, DS_UNSELECT_OBJECT);
|
|
}
|
|
m_pFrame->UpdateAllViews(NULL, NULL, DS_UPDATE_OBJECT_COUNT);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDSEvent::ToolbarAddMember(LPDATAOBJECT pDataObj)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CObjectNamesFormatCracker objectNamesFormat;
|
|
CInternalFormatCracker internalFormat;
|
|
LPDATAOBJECT pDO = NULL;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
if (pDataObj)
|
|
{
|
|
pDO = internalFormat.ExtractMultiSelect(pDataObj);
|
|
if (pDO == NULL)
|
|
{
|
|
pDO = pDataObj;
|
|
}
|
|
hr = objectNamesFormat.Extract(pDO);
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// we need at least one object in the selection
|
|
//
|
|
ASSERT(objectNamesFormat.HasData());
|
|
if (objectNamesFormat.GetCount() == 0)
|
|
{
|
|
TRACE (_T("DSToolbar::AddMember: can't find path\n"));
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
hr = AddDataObjListToGroup (&objectNamesFormat, m_hwnd, m_pComponentData);
|
|
TRACE (_T("AddDataObjListToGroup returned hr = %lx\n"), hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDSEvent::ToolbarFilter()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
if (m_pComponentData->CanRefreshAll())
|
|
{
|
|
if (m_pComponentData->m_pQueryFilter->EditFilteringOptions())
|
|
{
|
|
m_pComponentData->m_bDirty = TRUE;
|
|
m_pComponentData->RefreshAll();
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CDSEvent::ToolbarFind(LPDATAOBJECT lpDataObj)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CUINode* pUINode = NULL;
|
|
CDSCookie * pCookie = NULL;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
if (lpDataObj)
|
|
{
|
|
CInternalFormatCracker dobjCracker;
|
|
VERIFY(SUCCEEDED(dobjCracker.Extract(lpDataObj)));
|
|
pUINode = dobjCracker.GetCookie();
|
|
}
|
|
else
|
|
{
|
|
pUINode = m_pSelectedFolderNode;
|
|
}
|
|
|
|
if (m_UseSelectionParent)
|
|
{
|
|
pUINode = pUINode->GetParent();
|
|
}
|
|
|
|
if (IS_CLASS(pUINode, DS_UI_NODE))
|
|
{
|
|
pCookie = GetDSCookieFromUINode(pUINode);
|
|
}
|
|
ASSERT(pCookie != NULL);
|
|
if (pCookie == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
m_pComponentData->m_ActiveDS->DSFind(m_pComponentData->GetHWnd(), pCookie->GetPath());
|
|
return hr;
|
|
}
|
|
|
|
|
|
INT
|
|
CDSEvent::IsCreateAllowed(CString csClass,
|
|
CDSCookie * pContainer)
|
|
{
|
|
WCHAR ** ppChildren = NULL;
|
|
HRESULT hr = S_OK;
|
|
ppChildren = pContainer->GetChildList();
|
|
if (ppChildren == NULL)
|
|
{
|
|
hr = m_pComponentData->FillInChildList(pContainer);
|
|
if (hr == ERROR_DS_SERVER_DOWN)
|
|
{
|
|
return -2;
|
|
}
|
|
ppChildren = pContainer->GetChildList();
|
|
}
|
|
INT cChildClasses = pContainer->GetChildCount();
|
|
INT i = 0;
|
|
|
|
//
|
|
// needs finishing
|
|
//
|
|
while (i < cChildClasses)
|
|
{
|
|
if (csClass == CString(ppChildren[i]))
|
|
{
|
|
return i;
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
if (i == cChildClasses)
|
|
{
|
|
return -1;
|
|
}
|
|
return i;
|
|
}
|
|
|