WindowsXP-SP1/admin/snapin/dsadmin/dsutil.h
2020-09-30 16:53:49 +02:00

629 lines
19 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: dsutil.h
//
//--------------------------------------------------------------------------
#ifndef __DSUTIL_H_
#define __DSUTIL_H_
#include "util.h"
#include "uiutil.h"
#include "dssnap.h"
#include "query.h"
//
// Common DS strings
//
extern PCWSTR g_pszAllowedAttributesEffective;
extern PCWSTR g_pszPwdLastSet;
HRESULT DSAdminOpenObject(PCWSTR pszPath,
REFIID refIID,
PVOID* ppInterface,
BOOL bServer = FALSE);
/////////////////////////////////////////////////////////////////////////////////
// ADSI path helpers
//
HRESULT GetServerFromLDAPPath(IN LPCWSTR lpszLdapPath, OUT BSTR* pbstrServerName);
BOOL StripADsIPath(LPCWSTR lpszPath, CString& strref, bool bUseEscapedMode = true);
// remove escape characters from a path
// Arguments:
// lpszPath = path to be escaped
// bDN = if TRUE, the path os a distinguished name, if FALSE is an LDAP path
// bstrUnescaped = returned unescaped path
//
inline HRESULT UnescapePath(IN LPCWSTR lpszPath, IN BOOL bDN, OUT CComBSTR& bstrUnescaped)
{
CPathCracker pathCracker;
pathCracker.Set((LPWSTR)lpszPath, bDN ? ADS_SETTYPE_DN : ADS_SETTYPE_FULL);
pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF);
bstrUnescaped = (LPCWSTR)NULL;
HRESULT hr = pathCracker.Retrieve(bDN ? ADS_FORMAT_X500_DN : ADS_FORMAT_X500, &bstrUnescaped);
return hr;
}
class CObjectNamesFormatCracker; // fwd decl
HRESULT AddDataObjListToGroup(CObjectNamesFormatCracker * pNames,
HWND hwnd,
CDSComponentData* pComponentData);
HRESULT AddDataObjListToGivenGroup(CObjectNamesFormatCracker * pNames,
LPCWSTR lpszGroup,
LPCWSTR lpszGroupName,
HWND hwnd,
CDSComponentData* pComponentData);
BOOL IsValidSiteName( LPCTSTR lpctszSiteName, BOOL* pfNonRfc = NULL );
BOOL IsLocalLogin( void );
BOOL IsThisUserLoggedIn( LPCTSTR pwszUserDN );
BOOL CALLBACK AddPageProc(HPROPSHEETPAGE hPage, LPARAM pCall);
BOOL IsHomogenousDSSelection(LPDATAOBJECT pDataObject, CString& szClassName);
BOOL CALLBACK AddPageProc(HPROPSHEETPAGE hPage, LPARAM pCall);
HRESULT GetDisplaySpecifierProperty(PCWSTR pszClassName,
PCWSTR pszDisplayProperty,
MyBasePathsInfo* pBasePathsInfo,
CStringList& strListRef,
bool bEnglishOnly = false);
HRESULT TabCollect_GetDisplayGUIDs(LPCWSTR lpszClassName,
LPCWSTR lpszDisplayProperty,
MyBasePathsInfo* pBasePathsInfo,
UINT* pnCount,
GUID** ppGuids);
BOOL FindCookieInSubtree(IN CUINode* pContainerNode,
IN LPCWSTR lpszCookieDN,
IN SnapinType snapinType,
OUT CUINode** ppUINode);
bool CanUserChangePassword(IN IDirectoryObject* pDirObject);
/////////////////////////////////////////////////////////////////////
// CChangePasswordPrivilegeAction
// helper class to handle the revoking and the reading of the
// change password control right on user objects
class CChangePasswordPrivilegeAction
{
public:
CChangePasswordPrivilegeAction() : m_pDacl(NULL)
{
}
HRESULT Load(IADs * pIADs);
HRESULT Read(BOOL* pbPasswordCannotChange);
HRESULT Revoke();
private:
HRESULT _SetSids();
CComBSTR m_bstrObjectLdapPath;
CSimpleSecurityDescriptorHolder m_SDHolder;
PACL m_pDacl;
CSidHolder m_SelfSid;
CSidHolder m_WorldSid;
};
/////////////////////////////////////////////////////////////////////
// CDSNotifyHandlerTransaction
class CDSNotifyHandlerManager; // fwd decl
class CDSComponentData;
class CDSNotifyHandlerTransaction
{
public:
CDSNotifyHandlerTransaction(CDSComponentData* pCD);
~CDSNotifyHandlerTransaction()
{
if (m_bStarted)
End();
}
void SetEventType(ULONG uEvent)
{
ASSERT(m_uEvent == 0);
ASSERT(uEvent != 0);
m_uEvent = uEvent;
}
// state veriables check
UINT NeedNotifyCount();
// handlers for visualization in confirnation dialog
void SetCheckListBox(CCheckListBox* pCheckListBox);
void ReadFromCheckListBox(CCheckListBox* pCheckListBox);
// interfaces for transacted protocol
HRESULT Begin(LPCWSTR lpszArg1Path, LPCWSTR lpszArg1Class, BOOL bArg1Cont,
LPCWSTR lpszArg2Path, LPCWSTR lpszArg2Class, BOOL bArg2Cont);
HRESULT Begin(CDSCookie* pArg1Cookie,
LPCWSTR lpszArg2Path, LPCWSTR lpszArg2Class, BOOL bArg2Cont);
HRESULT Begin(IDataObject* pArg1,
LPCWSTR lpszArg2Path, LPCWSTR lpszArg2Class, BOOL bArg2Cont);
void Notify(ULONG nItem);
void End();
static HRESULT BuildTransactionDataObject(LPCWSTR lpszArgPath,
LPCWSTR lpszArgClass,
BOOL bContainer,
CDSComponentData* pCD,
IDataObject** ppArg);
private:
HRESULT _BuildDataObject(LPCWSTR lpszArgPath,
LPCWSTR lpszArgClass,
BOOL bContainer,
IDataObject** ppArg);
BOOL m_bStarted;
CDSComponentData* m_pCD;
CDSNotifyHandlerManager* m_pMgr;
ULONG m_uEvent;
CComPtr<IDataObject> m_spArg1;
CComPtr<IDataObject> m_spArg2;
};
///////////////////////////////////////////////////////////////////////////
// CUIOperationHandlerBase
class CUIOperationHandlerBase
{
public:
CUIOperationHandlerBase(CDSComponentData* pComponentData, HWND hwnd)
: m_transaction(pComponentData)
{
m_pComponentData = pComponentData;
m_hWndFrame = m_hWndParent = hwnd;
}
virtual ~CUIOperationHandlerBase(){}
protected:
// accessor functions
HWND GetParentHwnd() { return m_hWndParent;}
void SetParentHwnd(HWND hwnd) { m_hWndParent = hwnd;}
CDSComponentData* GetComponentData() { return m_pComponentData;}
CDSNotifyHandlerTransaction* GetTransaction() { return &m_transaction;}
// JonN 6/2/00 99382
// SITEREPL: Run interference when administrator attempts to
// delete critical object (NTDS Settings)
// reports own errors, returns true iff deletion should proceed
/* bool CheckForNTDSDSAInSubtree(
LPCTSTR lpszX500Path,
LPCTSTR lpszItemName);
*/
//
// JeffJon 8/10/00 27377
// Check for critical system objects in the subtree before
// attempting a subtree delete. This includes objects with
// isCriticalSystemObject=TRUE and NTDS Settings objects
//
bool CheckForCriticalSystemObjectInSubtree(
LPCTSTR lpszX500Path,
LPCTSTR lpszItemName);
// JonN 6/15/00 13574
// Centralizes the checks to make sure this is an OK object to delete
// returns HRESULT_FROM_WIN32(ERROR_CANCELLED) on cancellation
// returns fAlternateDeleteMethod=true iff ObjectDeletionCheck already
// attempted an alternate deletion method (e.g. DsRemoveDsServer).
HRESULT ObjectDeletionCheck(
LPCTSTR lpszADsPath,
LPCTSTR lpszName, // shortname to display to user, may be NULL
LPCTSTR lpszClass,
bool& fAlternateDeleteMethod );
private:
CDSComponentData* m_pComponentData;
CDSNotifyHandlerTransaction m_transaction;
HWND m_hWndFrame; // MMC frame window
HWND m_hWndParent; // window to parent any UI created in the handler
};
///////////////////////////////////////////////////////////////////////////
// CSingleDeleteHandlerBase
class CSingleDeleteHandlerBase : public CUIOperationHandlerBase
{
public:
CSingleDeleteHandlerBase(CDSComponentData* pComponentData, HWND hwnd)
: CUIOperationHandlerBase(pComponentData, hwnd)
{
GetTransaction()->SetEventType(DSA_NOTIFY_DEL);
}
HRESULT Delete();
protected:
// hooks for customization
virtual HRESULT BeginTransaction() = 0;
virtual HRESULT DeleteObject() = 0;
virtual HRESULT DeleteSubtree() = 0;
virtual void GetItemName(OUT CString& szName) = 0;
virtual LPCWSTR GetItemClass() = 0;
virtual LPCWSTR GetItemPath() = 0;
};
///////////////////////////////////////////////////////////////////////////
// CMultipleDeleteHandlerBase
class CMultipleDeleteHandlerBase : public CUIOperationHandlerBase
{
public:
CMultipleDeleteHandlerBase(CDSComponentData* pComponentData, HWND hwnd)
: CUIOperationHandlerBase(pComponentData, hwnd)
{
GetTransaction()->SetEventType(DSA_NOTIFY_DEL);
}
void Delete();
protected:
// hooks for customization
virtual UINT GetItemCount() = 0;
virtual HRESULT BeginTransaction() = 0;
virtual HRESULT DeleteObject(UINT i) = 0;
virtual HRESULT DeleteSubtree(UINT i) = 0;
virtual void OnItemDeleted(UINT) {}
virtual void GetItemName(IN UINT i, OUT CString& szName) = 0;
virtual void GetItemPath(UINT i, CString& szPath) = 0;
virtual PCWSTR GetItemClass(UINT i) = 0;
private:
CMultipleDeletionConfirmationUI m_confirmationUI;
void OnStart(HWND hwnd);
HRESULT OnDeleteStep(UINT i,
BOOL* pbContinue,
CString& strrefPath,
CString& strrefClass,
BOOL bSilent = TRUE);
friend class CMultipleDeleteProgressDialog; // for m_confirmationUI
};
///////////////////////////////////////////////////////////////////////////
// CMoveHandlerBase
class CMultipleMoveProgressDialog; // fwd decl
class CMoveHandlerBase : public CUIOperationHandlerBase
{
public:
CMoveHandlerBase(CDSComponentData* pComponentData, HWND hwnd,
LPCWSTR lpszBrowseRootPath)
: CUIOperationHandlerBase(pComponentData, hwnd)
{
m_lpszBrowseRootPath = lpszBrowseRootPath;
GetTransaction()->SetEventType(DSA_NOTIFY_MOV);
}
HRESULT Move(LPCWSTR lpszDestinationPath = NULL);
protected:
// hooks for customization
virtual UINT GetItemCount() = 0;
virtual HRESULT BeginTransaction() = 0;
virtual void GetNewPath(UINT i, CString& szNewPath) = 0;
virtual void GetName(UINT i, CString& strref) = 0;
virtual HRESULT OnItemMoved(UINT i, IADs* pIADs) = 0;
virtual void GetClassOfMovedItem(CString& szClass) = 0;
virtual void GetItemPath(UINT i, CString& szPath) = 0;
virtual PCWSTR GetItemClass(UINT i) = 0;
LPCWSTR GetDestPath() { return m_szDestPath;}
LPCWSTR GetDestClass() { return m_szDestClass;}
BOOL IsDestContainer() { return m_bDestContainer; }
private:
LPCWSTR m_lpszBrowseRootPath; // LDAP path where to point the browser dialog
CComPtr<IADsContainer> m_spDSDestination;
CString m_szDestPath;
CString m_szDestClass;
BOOL m_bDestContainer;
BOOL _ReportFailure(BOOL bLast, HRESULT hr, LPCWSTR lpszName);
HRESULT _BrowseForDestination(LPCWSTR lpszDestinationPath);
BOOL _BeginTransactionAndConfirmOperation();
HRESULT _MoveSingleSel(PCWSTR pszNewName);
HRESULT _MoveMultipleSel();
HRESULT _OnMoveStep(IN UINT i,
OUT BOOL* pbCanContinue,
OUT CString& strrefPath,
OUT CString& strrefClass);
friend class CMultipleMoveProgressDialog;
};
///////////////////////////////////////////////////////////////////////////
// CMultiselectMoveHandler
class CMultiselectMoveHandler : public CMoveHandlerBase
{
private:
struct CMovedState
{
CMovedState()
{
m_bMoved = FALSE;
}
BOOL m_bMoved;
CString m_szNewPath;
};
public:
CMultiselectMoveHandler(CDSComponentData* pComponentData, HWND hwnd,
LPCWSTR lpszBrowseRootPath)
: CMoveHandlerBase(pComponentData, hwnd, lpszBrowseRootPath)
{
m_pMovedArr = NULL;
}
virtual ~CMultiselectMoveHandler()
{
if (m_pMovedArr != NULL)
delete[] m_pMovedArr;
}
BOOL WasItemMoved(UINT i)
{
ASSERT(i < GetItemCount());
return m_pMovedArr[i].m_bMoved;
}
LPCWSTR GetNewItemPath(UINT i)
{
ASSERT(WasItemMoved(i));
return m_pMovedArr[i].m_szNewPath;
}
HRESULT Initialize(IDataObject* pDataObject,
CObjectNamesFormatCracker* pObjectNamesFormatCracker,
CInternalFormatCracker* pInternalFormatCracker)
{
if ((pDataObject == NULL) || (pObjectNamesFormatCracker == NULL))
{
ASSERT(FALSE);
return E_INVALIDARG;
}
m_pDataObject = pDataObject;
m_pInternalFormatCracker = pInternalFormatCracker;
m_pObjectNamesFormatCracker = pObjectNamesFormatCracker;
if (m_pObjectNamesFormatCracker->GetCount() < 1)
{
ASSERT(FALSE); // something is just wrong...
return E_INVALIDARG;
}
// allocate an array of CMovedState structs to keep track of what actually got moved
// and what the new name is
m_pMovedArr = new CMovedState[GetItemCount()];
return S_OK;
}
protected:
virtual UINT GetItemCount() { return m_pObjectNamesFormatCracker->GetCount();}
virtual HRESULT BeginTransaction()
{
return GetTransaction()->Begin(m_pDataObject,
GetDestPath(), GetDestClass(), IsDestContainer());
}
virtual void GetNewPath(UINT i, CString& szNewPath)
{
szNewPath = m_pObjectNamesFormatCracker->GetName(i);
}
virtual void GetName(UINT i, CString& strref)
{
HRESULT hr = S_OK;
if ((m_pInternalFormatCracker != NULL) && m_pInternalFormatCracker->HasData())
{
CUINode* pUINode = m_pInternalFormatCracker->GetCookie(i);
CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
strref = pCookie->GetName();
}
else
{
// REVIEW_MARCOC_PORT: this might be inefficent, need to make a member variable
CPathCracker pathCracker;
hr = pathCracker.Set((LPWSTR)m_pObjectNamesFormatCracker->GetName(i),
ADS_SETTYPE_FULL);
hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
CComBSTR DestName;
hr = pathCracker.GetElement( 0, &DestName );
strref = DestName;
}
}
virtual void GetItemPath(UINT i, CString& szPath)
{
szPath = m_pObjectNamesFormatCracker->GetName(i);
}
virtual PCWSTR GetItemClass(UINT i)
{
return m_pObjectNamesFormatCracker->GetClass(i);
}
virtual HRESULT OnItemMoved(UINT i, IADs* pIADs)
{
HRESULT hr = S_OK;
m_pMovedArr[i].m_bMoved = TRUE;
CComBSTR bsPath;
hr = pIADs->get_ADsPath(&bsPath);
if (SUCCEEDED(hr))
{
// save the new LDAP path in the array
m_pMovedArr[i].m_szNewPath = bsPath;
}
if ((m_pInternalFormatCracker != NULL) && m_pInternalFormatCracker->HasData())
{
CUINode* pUINode = m_pInternalFormatCracker->GetCookie(i);
CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
pUINode->SetExtOp(OPCODE_MOVE);
if (SUCCEEDED(hr))
{
CUINode* pParentNode = pUINode->GetParent();
if (pParentNode != NULL)
{
if (!IS_CLASS(*pParentNode, CSavedQueryNode))
{
//
// set the new DN in the cookie
//
CString szPath;
StripADsIPath(bsPath, szPath);
pCookie->SetPath(szPath);
}
}
}
}
return hr;
}
virtual void GetClassOfMovedItem(CString& szClass)
{
szClass.Empty();
if (NULL == m_pObjectNamesFormatCracker)
return;
UINT nCount = GetItemCount();
if (0 == nCount)
return;
szClass = m_pObjectNamesFormatCracker->GetClass(0);
for (UINT i = 1; i < nCount; i++)
{
if (0 != szClass.CompareNoCase( m_pObjectNamesFormatCracker->GetClass(i) ))
{
szClass.Empty();
return;
}
}
}
protected:
CMovedState* m_pMovedArr;
CInternalFormatCracker* m_pInternalFormatCracker;
private:
IDataObject* m_pDataObject;
CObjectNamesFormatCracker* m_pObjectNamesFormatCracker;
};
///////////////////////////////////////////////////////////////////////////
// CMultiselectMoveDataObject
class CMultiselectMoveDataObject : public IDataObject, public CComObjectRoot
{
// ATL Maps
DECLARE_NOT_AGGREGATABLE(CMultiselectMoveDataObject)
BEGIN_COM_MAP(CMultiselectMoveDataObject)
COM_INTERFACE_ENTRY(IDataObject)
END_COM_MAP()
// Construction/Destruction
CMultiselectMoveDataObject()
{
m_pDSObjCached = NULL;
m_nDSObjCachedBytes = 0;
}
~CMultiselectMoveDataObject()
{
_Clear();
}
// Standard IDataObject methods
public:
// Implemented
STDMETHOD(GetData)(FORMATETC * pformatetcIn, STGMEDIUM * pmedium);
// Not Implemented
private:
STDMETHOD(GetDataHere)(FORMATETC*, STGMEDIUM*) { return E_NOTIMPL; };
STDMETHOD(EnumFormatEtc)(DWORD, IEnumFORMATETC**) { return E_NOTIMPL; };
STDMETHOD(SetData)(FORMATETC*, STGMEDIUM*,BOOL) { return E_NOTIMPL; };
STDMETHOD(QueryGetData)(FORMATETC*) { return E_NOTIMPL; };
STDMETHOD(GetCanonicalFormatEtc)(FORMATETC*, FORMATETC*) { return E_NOTIMPL; };
STDMETHOD(DAdvise)(FORMATETC*, DWORD, IAdviseSink*, DWORD*) { return E_NOTIMPL; };
STDMETHOD(DUnadvise)(DWORD) { return E_NOTIMPL; };
STDMETHOD(EnumDAdvise)(IEnumSTATDATA**) { return E_NOTIMPL; };
public:
// Property Page Clipboard formats
static CLIPFORMAT m_cfDsObjectNames;
static HRESULT BuildPastedDataObject(
IN CObjectNamesFormatCracker* pObjectNamesFormatPaste,
IN CMultiselectMoveHandler* pMoveHandler,
IN CDSComponentData* pCD,
OUT IDataObject** ppSuccesfullyPastedDataObject);
protected:
// initialization
HRESULT Init(IN CObjectNamesFormatCracker* pObjectNamesFormatPaste,
IN CMultiselectMoveHandler* pMoveHandler,
IN CDSComponentData* pCD);
// Implementation
private:
void _Clear()
{
if (m_pDSObjCached != NULL)
{
::free(m_pDSObjCached);
m_pDSObjCached = NULL;
m_nDSObjCachedBytes = 0;
}
}
// chunk of memory with the clpboard format already computed
LPDSOBJECTNAMES m_pDSObjCached;
DWORD m_nDSObjCachedBytes;
};
////////////////////////////////////////////////////////////////////////
void EscapeFilterElement(PCWSTR pszElement, CString& refszEscapedElement);
#endif // __DSUTIL_H_