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

1066 lines
28 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: DSDirect.cpp
//
// Contents: ADSI wrapper object implementation
//
// History: 02-feb-97 jimharr Created
//
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
#include "dsutil.h"
#include "dsdirect.h"
#include "cmnquery.h"
#include "dsquery.h"
#include "dscache.h"
#include "dssnap.h"
#include "dsthread.h"
#include "newobj.h"
#include "querysup.h"
#include <lm.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define BAIL_IF_ERROR(hr) \
if (FAILED(hr)) { \
goto cleanup; \
}\
#define BAIL_ON_FAILURE(hr) \
if (FAILED(hr)) { \
goto error; \
}\
extern inline
BOOL CleanName (LPWSTR pszObjectName)
{
WCHAR * ptr = NULL;
ptr = wcschr (pszObjectName, L'=') + 1;
if (ptr) {
wcscpy (pszObjectName, ptr);
return TRUE;
} else
return FALSE;
}
CDSDirect::CDSDirect()
{
ASSERT (FALSE);
m_pCD = NULL;
}
// WARNING: pCD may still be in its constructor and may not be fully constructed yet
CDSDirect::CDSDirect(CDSComponentData * pCD)
{
m_pCD = pCD;
}
CDSDirect::~CDSDirect()
{
}
HRESULT CDSDirect::DeleteObject(CDSCookie* pCookie,
BOOL raiseUI)
{
CComBSTR strParent;
CComBSTR strThisRDN;
CComPtr<IADsContainer> spDSContainer;
CComPtr<IADs> spDSObject;
// bind to the ADSI object
CString strPath;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(strPath, pCookie->GetPath());
HRESULT hr = DSAdminOpenObject(strPath,
IID_IADs,
(void **) &spDSObject,
TRUE /*bServer*/);
if (FAILED(hr))
{
goto error;
}
// retrieve the parent's path
hr = spDSObject->get_Parent(&strParent);
if (FAILED(hr))
{
goto error;
}
// get the RDN of this object
hr = spDSObject->get_Name (&strThisRDN);
if (FAILED(hr))
{
goto error;
}
// bind to the parent ADSI object
hr = DSAdminOpenObject(strParent,
IID_IADsContainer,
(void **) &spDSContainer,
TRUE /*bServer*/);
if (FAILED(hr))
{
goto error;
}
hr = spDSContainer->Delete((LPWSTR)(LPCWSTR)pCookie->GetClass(),
(LPWSTR)(LPCWSTR)strThisRDN);
error:
if ((!SUCCEEDED(hr)) & raiseUI)
{
HWND hwnd;
m_pCD->m_pFrame->GetMainWindow(&hwnd);
PVOID apv[1] = {(LPWSTR)pCookie->GetName()};
ReportErrorEx( m_pCD->m_hwnd, IDS_12_DELETE_FAILED,
hr, MB_OK | MB_ICONERROR, apv, 1);
}
return hr;
}
HRESULT CDSDirect::GetParentDN(CDSCookie* pCookie, CString& szParentDN)
{
HRESULT hr = S_OK;
CString szObjPath;
CComPtr<IADs> spDSObj;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(szObjPath, pCookie->GetPath());
hr = DSAdminOpenObject(szObjPath,
IID_IADs,
(void **)&spDSObj,
TRUE /*bServer*/);
if (SUCCEEDED(hr))
{
CComBSTR ParentPath;
hr = spDSObj->get_Parent(&ParentPath);
StripADsIPath(ParentPath, szParentDN);
}
return hr;
}
///////////////////////////////////////////////////////////////////////////
// CSnapinMoveHandler
class CSnapinMoveHandler : public CMoveHandlerBase
{
public:
CSnapinMoveHandler(CDSComponentData* pComponentData, HWND hwnd,
LPCWSTR lpszBrowseRootPath, CDSCookie* pCookie)
: CMoveHandlerBase(pComponentData, hwnd, lpszBrowseRootPath)
{
m_pCookie = pCookie;
}
protected:
virtual UINT GetItemCount() { return (UINT)1;}
virtual HRESULT BeginTransaction()
{
return GetTransaction()->Begin(m_pCookie,
GetDestPath(), GetDestClass(), IsDestContainer());
}
virtual void GetNewPath(UINT, CString& szNewPath)
{
GetComponentData()->GetBasePathsInfo()->ComposeADsIPath(szNewPath, m_pCookie->GetPath());
}
virtual void GetName(UINT, CString& strref)
{
strref = m_pCookie->GetName();
return;
}
virtual void GetItemPath(UINT, CString& szPath)
{
szPath = m_pCookie->GetPath();
}
virtual PCWSTR GetItemClass(UINT)
{
return m_pCookie->GetClass();
}
virtual HRESULT OnItemMoved(UINT, IADs* pIADs)
{
CComBSTR bsPath;
HRESULT hr = pIADs->get_ADsPath(&bsPath);
if (SUCCEEDED(hr))
{
CString szPath;
StripADsIPath(bsPath, szPath);
m_pCookie->SetPath(szPath);
}
return hr;
}
virtual void GetClassOfMovedItem(CString& szClass)
{
szClass.Empty();
if (NULL != m_pCookie)
szClass = m_pCookie->GetClass();
}
private:
CDSCookie* m_pCookie;
};
HRESULT
CDSDirect::MoveObject(CDSCookie *pCookie)
{
HWND hwnd;
m_pCD->m_pFrame->GetMainWindow(&hwnd);
HRESULT hr = S_OK;
CString strPartialRootPath = m_pCD->GetRootPath();
if (SNAPINTYPE_SITE == m_pCD->QuerySnapinType())
{
// This is where we correct the root path
CPathCracker pathCracker;
hr = pathCracker.Set(const_cast<BSTR>((LPCTSTR)strPartialRootPath), ADS_SETTYPE_DN);
ASSERT( SUCCEEDED(hr) );
long cRootPathElements = 0;
hr = pathCracker.GetNumElements( &cRootPathElements );
ASSERT( SUCCEEDED(hr) );
CComBSTR bstr = pCookie->GetPath();
hr = pathCracker.Set(bstr, ADS_SETTYPE_DN);
ASSERT( SUCCEEDED(hr) );
long cCookiePathElements = 0;
hr = pathCracker.GetNumElements( &cCookiePathElements );
ASSERT( SUCCEEDED(hr) );
//
// Strip off all but one path element past the base config path
//
for (INT i = cCookiePathElements - cRootPathElements; i > 1; i--)
{
hr = pathCracker.RemoveLeafElement();
ASSERT( SUCCEEDED(hr) );
}
hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
ASSERT( SUCCEEDED(hr) );
hr = pathCracker.Retrieve( ADS_FORMAT_X500_DN, &bstr );
ASSERT( SUCCEEDED(hr) && bstr != NULL );
strPartialRootPath = bstr;
::SysFreeString( bstr );
}
CString strRootPath = m_pCD->GetBasePathsInfo()->GetProviderAndServerName();
strRootPath += strPartialRootPath;
CSnapinMoveHandler moveHandler(m_pCD, hwnd, strRootPath, pCookie);
return moveHandler.Move();
}
HRESULT CDSDirect::RenameObject(CDSCookie* pCookie, LPCWSTR NewName)
{
HRESULT hr = S_OK;
IADs * pDSObject = NULL;
IDispatch * pDispObj = NULL;
IADsContainer * pContainer = NULL;
CComBSTR bsParentPath;
CString szNewAttrName;
CString szNewNamingContext;
CString szClass;
CString szObjectPath, szNewPath;
CString csNewName;
CString szPath;
CDSClassCacheItemBase* pItem = NULL;
CComBSTR bsEscapedName;
CPathCracker pathCracker;
HWND hwnd;
m_pCD->m_pFrame->GetMainWindow(&hwnd);
//
// create a transaction object, the destructor will call End() on it
//
CDSNotifyHandlerTransaction transaction(m_pCD);
transaction.SetEventType(DSA_NOTIFY_REN);
if (pCookie == NULL)
{
return E_INVALIDARG;
}
//
// Retrieve class info from cache
//
szClass = pCookie->GetClass();
BOOL found = m_pCD->m_pClassCache->Lookup ((LPCWSTR)szClass, pItem);
ASSERT (found == TRUE);
csNewName = NewName;
csNewName.TrimLeft();
csNewName.TrimRight();
//
// get the new name in the form "cn=foo" or "ou=foo"
//
szNewAttrName = pItem->GetNamingAttribute();
szNewAttrName += L"=";
szNewAttrName += csNewName;
TRACE(_T("_RenameObject: Attributed name is %s.\n"), szNewAttrName);
//
// bind to object
//
m_pCD->GetBasePathsInfo()->ComposeADsIPath(szObjectPath, pCookie->GetPath());
hr = DSAdminOpenObject(szObjectPath,
IID_IADs,
(void **)&pDSObject,
TRUE /*bServer*/);
if (!SUCCEEDED(hr))
{
goto error;
}
//
// get the path of the object container
//
hr = pDSObject->get_Parent (&bsParentPath);
if (!SUCCEEDED(hr))
{
goto error;
}
pDSObject->Release();
pDSObject = NULL;
//
// bind to the object container
//
hr = DSAdminOpenObject(bsParentPath,
IID_IADsContainer,
(void **)&pContainer,
TRUE /*bServer*/);
if (!SUCCEEDED(hr))
{
goto error;
}
//
// build the new LDAP path
//
szNewNamingContext = szNewAttrName;
szNewNamingContext += L",";
StripADsIPath(bsParentPath, szPath);
szNewNamingContext += szPath;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(szNewPath, szNewNamingContext);
//
// start the transaction
//
// It's ok for containerness to be determined from the cookie since we are concerned
// whether the DS object is a container not whether it is a container in the UI
//
hr = transaction.Begin(pCookie, szNewPath, szClass, pCookie->IsContainerClass());
//
// ask for confirmation
//
if (transaction.NeedNotifyCount() > 0)
{
CString szMessage, szAssocData;
szMessage.LoadString(IDS_CONFIRM_RENAME);
szAssocData.LoadString(IDS_EXTENS_RENAME);
CConfirmOperationDialog dlg(hwnd, &transaction);
dlg.SetStrings(szMessage, szAssocData);
if (IDNO == dlg.DoModal())
{
transaction.End();
hr = S_OK;
goto error;
}
}
hr = pathCracker.GetEscapedElement(0, //reserved
(BSTR)(LPCWSTR)szNewAttrName,
&bsEscapedName);
if (FAILED(hr))
{
goto error;
}
//
// do the actual rename
//
hr = pContainer->MoveHere((LPWSTR)(LPCWSTR)szObjectPath,
(LPWSTR)(LPCWSTR)bsEscapedName,
&pDispObj);
if (SUCCEEDED(hr))
{
transaction.Notify(0); // let extensions know
}
else
{
TRACE(_T("Object Rename Failed with hr: %lx\n"), hr);
goto error;
}
//
// rebuild the naming info for the cookie
//
hr = pDispObj->QueryInterface (IID_IADs,
(void **)&pDSObject);
if (SUCCEEDED(hr))
{
CComBSTR bsPath;
hr = pDSObject->get_ADsPath(&bsPath);
if (SUCCEEDED(hr))
{
StripADsIPath(bsPath, szPath);
pCookie->SetPath(szPath);
//
// remove escaping from name
//
hr = pathCracker.Set((LPWSTR)bsPath, ADS_SETTYPE_FULL);
ASSERT(SUCCEEDED(hr));
hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
ASSERT(SUCCEEDED(hr));
hr = pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX);
ASSERT(SUCCEEDED(hr));
hr = pathCracker.GetElement( 0, &bsPath );
ASSERT(SUCCEEDED(hr));
pCookie->SetName((LPWSTR)bsPath);
}
}
error:
//
// transaction.End() will be called by the transaction's destructor
//
//
// clear pointers
//
if (pDispObj)
{
pDispObj->Release();
}
if (pDSObject)
{
pDSObject->Release();
}
return hr;
}
CDSComponentData* g_pCD = NULL;
HRESULT
CDSDirect::DSFind(HWND hwnd, LPCWSTR lpszBaseDN)
{
HRESULT hr;
DSQUERYINITPARAMS dqip;
OPENQUERYWINDOW oqw;
ZeroMemory(&dqip, sizeof(DSQUERYINITPARAMS));
ZeroMemory(&oqw, sizeof(OPENQUERYWINDOW));
ICommonQuery * pCommonQuery = NULL;
IDataObject * pDataObject = NULL;
hr = CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER,
IID_ICommonQuery, (PVOID *)&pCommonQuery);
if (!SUCCEEDED(hr)) {
ReportErrorEx( (m_pCD) ? m_pCD->m_hwnd : NULL, IDS_1_CANT_CREATE_FIND,
hr, MB_OK | MB_ICONERROR, NULL, 0);
return hr;
}
CString szPath;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(szPath, lpszBaseDN);
LPWSTR pszDefPath = (LPWSTR)(LPCWSTR)szPath;
dqip.cbStruct = sizeof(dqip);
dqip.dwFlags = DSQPF_NOSAVE | DSQPF_SHOWHIDDENOBJECTS |
DSQPF_ENABLEADMINFEATURES;
if (m_pCD->IsAdvancedView()) {
dqip.dwFlags |= DSQPF_ENABLEADVANCEDFEATURES;
}
dqip.pDefaultScope = pszDefPath;
dqip.pUserName = NULL;
dqip.pPassword = NULL;
dqip.pServer = (LPWSTR)(m_pCD->GetBasePathsInfo()->GetServerName());
dqip.dwFlags |= DSQPF_HASCREDENTIALS;
oqw.cbStruct = sizeof(oqw);
oqw.dwFlags = OQWF_SHOWOPTIONAL;
oqw.clsidHandler = CLSID_DsQuery;
oqw.pHandlerParameters = &dqip;
// oqw.clsidDefaultForm = CLSID_NULL;
g_pCD = m_pCD;
HWND hwndHidden = m_pCD->GetHiddenWindow();
SetWindowText(hwndHidden,L"DS Find");
hr = pCommonQuery->OpenQueryWindow(hwnd, &oqw, &pDataObject);
SetWindowText(hwndHidden, NULL);
g_pCD = NULL;
if (FAILED(hr)) {
ReportErrorEx( m_pCD->m_hwnd, IDS_1_FIND_ERROR,
hr, MB_OK | MB_ICONERROR, NULL, 0);
}
pCommonQuery->Release();
if (pDataObject) {
pDataObject->Release();
}
return hr;
}
HRESULT CDSDirect::EnumerateContainer(CDSThreadQueryInfo* pQueryInfo,
CWorkerThread* pWorkerThread)
{
ASSERT(!pQueryInfo->m_bTooMuchData);
ASSERT((pQueryInfo->GetType() == dsFolder) || (pQueryInfo->GetType() == queryFolder));
BEGIN_PROFILING_BLOCK("CDSDirect::EnumerateContainer");
HRESULT hr = S_OK;
CString ADsPath;
UINT nCurrCount = 0;
UINT nMaxCount = pQueryInfo->GetMaxItemCount();
BOOL bOverLimit = FALSE;
//
// This wouldn't normally be the way to use the CPathCracker object
// but for performance reasons we are going to create a single instance
// for enumerating and pass a reference to the SetCookieFromData so
// that we don't do a CoCreateInstance for each cookie
//
CPathCracker specialPerformancePathCracker;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(ADsPath, pQueryInfo->GetPath());
CDSSearch ContainerSrch(m_pCD->m_pClassCache, m_pCD);
CDSColumnSet* pColumnSet = NULL;
CString szPath;
szPath = pQueryInfo->GetPath();
CPathCracker pathCracker;
hr = pathCracker.Set(const_cast<BSTR>((LPCTSTR)szPath), ADS_SETTYPE_DN);
if (SUCCEEDED(hr))
{
CComBSTR bstrLeaf;
hr = pathCracker.GetElement(0, &bstrLeaf);
if (SUCCEEDED(hr))
{
szPath = bstrLeaf;
}
}
if (szPath.Find(_T("ForeignSecurityPrincipals")) != -1)
{
pColumnSet = m_pCD->FindColumnSet(L"ForeignSecurityPrincipals");
}
else
{
pColumnSet = m_pCD->FindColumnSet(pQueryInfo->GetColumnSetID());
}
ASSERT(pColumnSet != NULL);
hr = ContainerSrch.Init (ADsPath);
if (!SUCCEEDED(hr))
goto exiting;
// CODEWORK this redoes the GetColumnsForClass calculation
ContainerSrch.SetAttributeListForContainerClass (pColumnSet);
ContainerSrch.SetFilterString ((LPWSTR)pQueryInfo->GetQueryString());
ContainerSrch.SetSearchScope(pQueryInfo->IsOneLevel() ? ADS_SCOPE_ONELEVEL : ADS_SCOPE_SUBTREE);
hr = ContainerSrch.DoQuery();
if (FAILED(hr))
goto exiting;
hr = ContainerSrch.GetNextRow ();
while ((hr == S_OK) && !bOverLimit ) {
CDSCookie* pNewCookie = new CDSCookie();
HRESULT hr2 = ContainerSrch.SetCookieFromData(pNewCookie,
specialPerformancePathCracker,
pColumnSet);
if (SUCCEEDED(hr2)) {
CDSUINode* pDSUINode = new CDSUINode(NULL);
pDSUINode->SetCookie(pNewCookie);
if (pQueryInfo->GetType() == dsFolder)
{
if (pNewCookie->IsContainerClass())
pDSUINode->MakeContainer();
}
pWorkerThread->AddToQueryResult(pDSUINode);
if (pWorkerThread->MustQuit())
break;
} else {
delete pNewCookie;
}
hr = ContainerSrch.GetNextRow();
if (hr == S_OK) {
nCurrCount++;
if (nCurrCount >= nMaxCount)
bOverLimit = TRUE;
}
}
pQueryInfo->m_bTooMuchData = bOverLimit;
exiting:
END_PROFILING_BLOCK;
return hr;
}
HRESULT CDSDirect::EnumerateRootContainer(CDSThreadQueryInfo* pQueryInfo,
CWorkerThread* pWorkerThread)
{
ASSERT(pQueryInfo->GetType() == rootFolder);
HRESULT hr = S_OK;
m_pCD->Lock();
//
// build the nodes below the root
//
if (m_pCD->QuerySnapinType() == SNAPINTYPE_SITE)
{
hr = CreateRootChild(TEXT("CN=Sites,"), pQueryInfo, pWorkerThread);
if (!pWorkerThread->MustQuit() && m_pCD->ViewServicesNode())
{
hr = CreateRootChild(TEXT("CN=Services,"), pQueryInfo, pWorkerThread);
}
}
else
{
hr = CreateRootChild(TEXT(""), pQueryInfo, pWorkerThread);
}
if (m_pCD->m_CreateInfo.IsEmpty())
{
InitCreateInfo();
}
m_pCD->Unlock();
return hr;
}
HRESULT CDSDirect::CreateRootChild(LPCTSTR lpcszPrefix,
CDSThreadQueryInfo* pQueryInfo,
CWorkerThread* pWorkerThread)
{
TRACE(L"CDSDirect::CreateRootChild(%s)\n", lpcszPrefix);
TRACE(L"pQueryInfo->GetPath() = %s\n", pQueryInfo->GetPath());
CString BasePath = lpcszPrefix;
BasePath += pQueryInfo->GetPath();
CString ADsPath;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(OUT ADsPath, IN BasePath);
// create a search object and bind to it
CDSSearch Search(m_pCD->m_pClassCache, m_pCD);
HRESULT hr = Search.Init(ADsPath);
TRACE(L"Search.Init(%s) returned hr = 0x%x\n", (LPCWSTR)ADsPath, hr);
if (FAILED(hr))
{
return hr;
}
//
// set query parameters
//
// Search for just this object
//
Search.SetSearchScope(ADS_SCOPE_BASE);
CUIFolderInfo* pFolderInfo = m_pCD->GetRootNode()->GetFolderInfo();
if (pFolderInfo == NULL)
{
//
// This shouldn't happen, but just to be on the safe side...
//
ASSERT(FALSE);
Search.SetAttributeList((LPWSTR *)g_pStandardAttributes,
g_nStdCols);
}
else
{
CDSColumnSet* pColumnSet = m_pCD->GetRootNode()->GetColumnSet(m_pCD);
Search.SetAttributeListForContainerClass(pColumnSet);
}
Search.SetFilterString (L"(objectClass=*)");
// execute the query
hr = Search.DoQuery();
TRACE(L"Search.DoQuery() returned hr = 0x%x\n", hr);
if (FAILED(hr))
{
return hr;
}
TRACE(L"Search.GetNextRow() returned hr = 0x%x\n", hr);
hr = Search.GetNextRow();
if (FAILED(hr))
{
return hr;
}
//
// we got a query result, create a new cookie object
// and initialize it from the query result
//
CDSCookie* pNewCookie = new CDSCookie;
Search.SetCookieFromData(pNewCookie,NULL);
TRACE(L"Got cookie, pNewCookie->GetName() = %s\n", pNewCookie->GetName());
//
// special case if it is a domain DNS object,
// we want fo get the canonical name for display
//
if (wcscmp(pNewCookie->GetClass(), L"domainDNS") == 0)
{
ADS_SEARCH_COLUMN Column;
CString csCanonicalName;
int slashLocation;
LPWSTR canonicalNameAttrib = L"canonicalName";
Search.SetAttributeList (&canonicalNameAttrib, 1);
hr = Search.DoQuery();
if (FAILED(hr))
{
return hr;
}
hr = Search.GetNextRow();
if (FAILED(hr))
{
return hr;
}
hr = Search.GetColumn(canonicalNameAttrib, &Column);
if (FAILED(hr))
{
return hr;
}
ColumnExtractString (csCanonicalName, pNewCookie, &Column);
slashLocation = csCanonicalName.Find('/');
if (slashLocation != 0)
{
csCanonicalName = csCanonicalName.Left(slashLocation);
}
//
pNewCookie->SetName(csCanonicalName);
TRACE(L"canonical name pNewCookie->GetName() = %s\n", pNewCookie->GetName());
//
// Free column data
//
Search.FreeColumn(&Column);
}
//
// Add the new node to the result list
CDSUINode* pDSUINode = new CDSUINode(NULL);
pDSUINode->SetCookie(pNewCookie);
if (pNewCookie->IsContainerClass())
pDSUINode->MakeContainer();
pWorkerThread->AddToQueryResult(pDSUINode);
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Method: CDSDirect::InitCreateInfo
//
// Synopsis: read schema and finds all object names that for whom
// defaultHidingValue is TRUE;
//
//-----------------------------------------------------------------------------
HRESULT CDSDirect::InitCreateInfo(void)
{
HRESULT hr = S_OK;
LPWSTR pAttrs[2] = {L"name",
L"lDAPDisplayName"};
CDSSearch Search (m_pCD->GetClassCache(), m_pCD);
ADS_SEARCH_COLUMN Column;
CString csFilter;
CString szSchemaPath;
m_pCD->GetBasePathsInfo()->GetSchemaPath(szSchemaPath);
Search.Init (szSchemaPath);
csFilter = L"(&(objectCategory=CN=Class-Schema,";
csFilter += m_pCD->GetBasePathsInfo()->GetSchemaNamingContext();
csFilter += L")(defaultHidingValue=FALSE))";
Search.SetFilterString((LPWSTR)(LPCWSTR)csFilter);
Search.SetAttributeList (pAttrs, 2);
Search.SetSearchScope(ADS_SCOPE_ONELEVEL);
hr = Search.DoQuery();
if (SUCCEEDED(hr))
{
hr = Search.GetNextRow();
if(FAILED(hr))
{
TRACE(_T("Search::GetNextRow failed \n"));
goto error;
}
while (hr == S_OK)
{
hr = Search.GetColumn (pAttrs[1], &Column);
if (SUCCEEDED(hr))
{
if (!((!wcscmp(Column.pADsValues->CaseIgnoreString, L"builtinDomain")) ||
(!wcscmp(Column.pADsValues->CaseIgnoreString, L"localGroup")) ||
(!wcscmp(Column.pADsValues->CaseIgnoreString, L"domainDNS")) ||
(!wcscmp(Column.pADsValues->CaseIgnoreString, L"domain")) ||
(!wcscmp(Column.pADsValues->CaseIgnoreString, L"organization")) ||
(!wcscmp(Column.pADsValues->CaseIgnoreString, L"locality"))))
{
m_pCD->m_CreateInfo.AddTail (Column.pADsValues->CaseIgnoreString);
TRACE(_T("added to createinfo: %s\n"),
Column.pADsValues->CaseIgnoreString);
}
Search.FreeColumn (&Column);
}
else
{
goto error;
}
hr = Search.GetNextRow();
}
}
error:
if (m_pCD->m_CreateInfo.IsEmpty())
{
ReportErrorEx (m_pCD->m_hwnd,IDS_1_CANT_GET_SCHEMA_CREATE_INFO,hr,
MB_OK | MB_ICONERROR, NULL, 0);
}
return hr;
}
HRESULT CDSDirect::ReadDSObjectCookie(IN CDSUINode* pContainerDSUINode, // IN: container where to create object
IN LPCWSTR lpszLdapPath, // path of the object
OUT CDSCookie** ppNewCookie) // newly created cookie
{
CComPtr<IADs> spADs;
HRESULT hr = DSAdminOpenObject(lpszLdapPath,
IN IID_IADs,
OUT (LPVOID *) &spADs,
TRUE /*bServer*/);
if (FAILED(hr))
{
return hr;
}
return ReadDSObjectCookie(pContainerDSUINode, spADs, ppNewCookie);
}
HRESULT CDSDirect::ReadDSObjectCookie(IN CDSUINode* pContainerDSUINode, // IN: container where to create object
IN IADs* pADs, // pointer to an already bound ADSI object
OUT CDSCookie** ppNewCookie) // newly created cookie
{
ASSERT(pContainerDSUINode != NULL);
ASSERT(pContainerDSUINode->IsContainer());
ASSERT(pADs != NULL);
ASSERT(ppNewCookie != NULL);
// create a new cookie and load data from the DS
CDSCookie * pDsCookieNew = new CDSCookie();
CComPtr<IDirectorySearch> spDirSearch;
CDSColumnSet* pColumnSet = pContainerDSUINode->GetColumnSet(m_pCD);
ASSERT(pColumnSet != NULL);
HRESULT hr = pADs->QueryInterface (IID_IDirectorySearch, (void **)&spDirSearch);
ASSERT (hr == S_OK);
CDSSearch Search(m_pCD->GetClassCache(), m_pCD);
Search.Init(spDirSearch);
Search.SetSearchScope(ADS_SCOPE_BASE);
Search.SetAttributeListForContainerClass(pColumnSet);
Search.SetFilterString (L"(objectClass=*)");
Search.DoQuery();
hr = Search.GetNextRow();
if (SUCCEEDED(hr) && (hr != S_ADS_NOMORE_ROWS))
{
// we got the data, set the cookie
Search.SetCookieFromData(pDsCookieNew, pColumnSet);
*ppNewCookie = pDsCookieNew;
pDsCookieNew = NULL;
}
if (pDsCookieNew != NULL)
{
delete pDsCookieNew;
}
return hr;
}
/////////////////////////////////////////////////////////////////////
// CDSDirect::CreateDSObject()
//
// Create a new ADs object.
//
HRESULT CDSDirect::CreateDSObject(CDSUINode* pContainerDSUINode, // IN: container where to create object
LPCWSTR lpszObjectClass, // IN: class of the object to be created
IN CDSUINode* pCopyFromDSUINode, // IN: (optional) object to be copied
OUT CDSCookie** ppSUINodeNew) // OUT: OPTIONAL: Pointer to new node
{
ASSERT(pContainerDSUINode != NULL);
ASSERT(pContainerDSUINode->IsContainer());
ASSERT(lpszObjectClass != NULL);
ASSERT(ppSUINodeNew != NULL);
CDSCookie* pContainerDsCookie = pContainerDSUINode->GetCookie();
ASSERT(pContainerDsCookie != NULL);
CComPtr<IADsContainer> spIADsContainer;
IADs* pIADs = NULL;
CDSClassCacheItemBase* pDsCacheItem = NULL;
HRESULT hr;
// Data structure to hold temporary attribute information to create object
CNewADsObjectCreateInfo createinfo(m_pCD->GetBasePathsInfo(), lpszObjectClass);
{
CWaitCursor wait;
CString strContainerADsIPath;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(strContainerADsIPath, pContainerDsCookie->GetPath());
hr = DSAdminOpenObject(strContainerADsIPath,
IN IID_IADsContainer,
OUT (LPVOID *) &spIADsContainer,
TRUE /*bServer*/);
if (FAILED(hr))
{
PVOID apv[1] = {(LPWSTR)pContainerDsCookie->GetName()};
ReportErrorEx (m_pCD->m_hwnd,IDS_12_CONTAINER_NOT_FOUND,hr,
MB_OK | MB_ICONERROR, apv, 1);
hr = S_FALSE; // Avoid display another error message to user
goto CleanUp;
}
// Lookup if the object classname is in the cache
pDsCacheItem = m_pCD->GetClassCache()->FindClassCacheItem(m_pCD, lpszObjectClass, NULL);
ASSERT(pDsCacheItem != NULL);
}
createinfo.SetContainerInfo(IN spIADsContainer, IN pDsCacheItem, IN m_pCD);
if (pCopyFromDSUINode != NULL)
{
CDSCookie* pCopyFromDsCookie = pCopyFromDSUINode->GetCookie();
CComPtr<IADs> spIADsCopyFrom;
CString szPath;
m_pCD->GetBasePathsInfo()->ComposeADsIPath(szPath, pCopyFromDsCookie->GetPath());
hr = createinfo.SetCopyInfo(szPath);
if (FAILED(hr))
{
PVOID apv[1] = {(LPWSTR)pCopyFromDsCookie->GetName()};
ReportErrorEx (m_pCD->m_hwnd,IDS_12_COPY_READ_FAILED,hr,
MB_OK | MB_ICONERROR, apv, 1);
hr = S_FALSE; // Avoid display another error message to user
goto CleanUp;
}
}
hr = createinfo.HrLoadCreationInfo();
if (FAILED(hr))
{
goto CleanUp;
}
// launch the creation DS object creation wizard
hr = createinfo.HrDoModal(m_pCD->m_hwnd);
// now examine the results of the call
pIADs = createinfo.PGetIADsPtr();
if (hr != S_OK)
{
// Object was not created because user hit "Cancel" or an error occured.
goto CleanUp;
}
if (pIADs == NULL)
{
TRACE0("ERROR: Inconsistency between return value from HrDoModal() and IADs pointer.\n");
ReportErrorEx (m_pCD->m_hwnd,IDS_ERR_FATAL,S_OK,
MB_OK | MB_ICONERROR, NULL, 0);
hr = S_FALSE; // Avoid display another error message to user
goto CleanUp;
}
// successful creation, we need to create a node object for the UI
if (pContainerDSUINode->GetFolderInfo()->IsExpanded())
{
ReadDSObjectCookie(pContainerDSUINode, pIADs, ppSUINodeNew);
} // if expanded
CleanUp:
if (FAILED(hr))
{
CString Name;
Name = createinfo.GetName();
PVOID apv[1] = {(LPWSTR)(LPCWSTR)Name};
ReportErrorEx (m_pCD->m_hwnd,IDS_12_GENERIC_CREATION_FAILURE,hr,
MB_OK | MB_ICONERROR, apv, 1);
}
if (pIADs != NULL)
pIADs->Release();
return hr;
}