Leaked source code of windows server 2003
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.
 
 
 
 
 
 

860 lines
24 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: connection.cpp
//
//--------------------------------------------------------------------------
#include "pch.h"
#include <SnapBase.h>
#include "resource.h"
#include "createwiz.h"
#include "connection.h"
#include "connectionui.h"
#include "editorui.h"
#include "filterui.h"
#include "credui.h"
#include "queryui.h"
#ifdef DEBUG_ALLOCATOR
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
extern LPCWSTR g_lpszRootDSE;
///////////////////////////////////////////////////////////////////////////////
// {5C225203-CFF7-11d2-8801-00C04F72ED31}
const GUID CADSIEditConnectionNode::NodeTypeGUID =
{ 0x5c225203, 0xcff7, 0x11d2, { 0x88, 0x1, 0x0, 0xc0, 0x4f, 0x72, 0xed, 0x31 } };
CADSIEditConnectionNode::~CADSIEditConnectionNode()
{
RemoveAndDeleteAllQueriesFromList();
delete m_pConnectData;
HRESULT hr = m_SchemaCache.Destroy();
ASSERT(SUCCEEDED(hr));
}
bool CADSIEditConnectionNode::IsClassAContainer(CCredentialObject* pCredObject,
PCWSTR pszClass,
PCWSTR pszSchemaPath)
{
bool bContainer = false;
do // false loop
{
if (!pCredObject ||
!pszClass ||
!pszSchemaPath)
{
ASSERT(pCredObject);
ASSERT(pszClass);
ASSERT(pszSchemaPath);
bContainer = false;
break;
}
CADSIEditClassCacheItemBase* pSchemaCacheItem = m_SchemaCache.FindClassCacheItem(pCredObject,
pszClass,
pszSchemaPath);
if (pSchemaCacheItem)
{
bContainer = pSchemaCacheItem->IsContainer();
}
} while (false);
return bContainer;
}
BOOL CADSIEditConnectionNode::OnEnumerate(CComponentDataObject* pComponentData, BOOL bAsync)
{
CString path, basePath;
GetADsObject()->GetPath(path);
m_pConnectData->GetBasePath(basePath);
CComPtr<IDirectoryObject> spDirectoryObject;
HRESULT hr, hCredResult;
CADsObject* pObject = new CADsObject();
if (pObject)
{
if (m_pConnectData->IsRootDSE())
{
pObject->SetContainer(TRUE);
pObject->SetName(g_lpszRootDSE);
pObject->SetPath(path);
pObject->SetClass(g_lpszRootDSE);
pObject->SetConnectionNode(this);
pObject->SetIntermediateNode(TRUE);
pObject->SetComplete(TRUE);
CADSIEditContainerNode *pNewContNode = new CADSIEditContainerNode(pObject);
if (pNewContNode)
{
pNewContNode->SetDisplayName(g_lpszRootDSE);
VERIFY(AddChildToList(pNewContNode));
}
pComponentData->SetDescriptionBarText(this);
}
else
{
hr = OpenObjectWithCredentials(
m_pConnectData,
m_pConnectData->GetCredentialObject()->UseCredentials(),
path,
IID_IDirectoryObject,
(LPVOID*) &spDirectoryObject,
NULL,
hCredResult
);
if ( FAILED(hr) )
{
if (SUCCEEDED(hCredResult))
{
ADSIEditErrorMessage(hr);
}
if (pObject)
{
delete pObject;
pObject = 0;
}
return FALSE;
}
ADS_OBJECT_INFO* pInfo = 0;
hr = spDirectoryObject->GetObjectInformation(&pInfo);
if (FAILED(hr))
{
ADSIEditErrorMessage(hr);
if (pObject)
{
delete pObject;
pObject = 0;
}
return FALSE;
}
// Name
pObject->SetName(basePath);
pObject->SetDN(basePath);
pObject->SetPath(path);
// Make sure the prefix is uppercase
CString sBasePath(basePath);
int idx = sBasePath.Find(L'=');
if (idx != -1)
{
CString sPrefix, sRemaining;
sPrefix = sBasePath.Left(idx);
sPrefix.MakeUpper();
int iCount = sBasePath.GetLength();
sRemaining = sBasePath.Right(iCount - idx);
sBasePath = sPrefix + sRemaining;
}
// Class
pObject->SetClass(pInfo->pszClassName);
pObject->SetIntermediateNode(TRUE);
pObject->SetContainer(TRUE);
pObject->SetComplete(TRUE);
CADSIEditContainerNode *pNewContNode = new CADSIEditContainerNode(pObject);
if (pNewContNode)
{
CString sName;
pNewContNode->SetDisplayName(sBasePath);
GetConnectionData()->SetIDirectoryInterface(spDirectoryObject);
pNewContNode->GetADsObject()->SetConnectionNode(this);
VERIFY(AddChildToList(pNewContNode));
pComponentData->SetDescriptionBarText(this);
FreeADsMem(pInfo);
}
}
EnumerateQueries();
}
return TRUE;
}
void CADSIEditConnectionNode::EnumerateQueries()
{
POSITION pos = m_queryList.GetHeadPosition();
while(pos != NULL)
{
CADSIEditQueryData* pQueryData = m_queryList.GetNext(pos);
CADsObject* pObject = new CADsObject();
if (pObject)
{
CString sPath, sName;
pQueryData->GetName(sName);
pObject->SetName(sName);
pQueryData->GetRootPath(sPath);
pObject->SetPath(sPath);
pObject->SetComplete(TRUE);
pObject->SetConnectionNode(this);
pObject->SetContainer(TRUE);
pObject->SetIntermediateNode(TRUE);
CADSIEditQueryNode* pNewQuery = new CADSIEditQueryNode(pObject, pQueryData);
if (pNewQuery)
{
CString sDisplayName;
pQueryData->GetDisplayName(sDisplayName);
pNewQuery->SetDisplayName(sDisplayName);
VERIFY(AddChildToList(pNewQuery));
}
}
}
}
BOOL CADSIEditConnectionNode::HasPropertyPages(DATA_OBJECT_TYPES type,
BOOL* pbHideVerb,
CNodeList* pNodeList)
{
*pbHideVerb = TRUE; // always hide the verb
return FALSE;
}
BOOL CADSIEditConnectionNode::FindNode(LPCWSTR lpszPath, CList<CTreeNode*, CTreeNode*>& foundNodeList)
{
// NOTICE-NTRAID#NTBUG9-561513-2002/03/01-artm Validate lpszPath before using.
if (!lpszPath)
{
// This should never happen.
ASSERT(false);
return FALSE;
}
CString szPath;
GetADsObject()->GetPath(szPath);
if (wcscmp(lpszPath, (LPCWSTR)szPath) == 0)
{
foundNodeList.AddHead(this);
return TRUE;
}
BOOL bFound = FALSE;
POSITION pos;
for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
{
CTreeNode* pNode = m_containerChildList.GetNext(pos);
CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(pNode);
if (pContNode != NULL)
{
BOOL bTemp;
bTemp = pContNode->FindNode(lpszPath, foundNodeList);
if (!bFound)
{
bFound = bTemp;
}
}
}
return bFound;
}
int CADSIEditConnectionNode::GetImageIndex(BOOL bOpenImage)
{
int nIndex = 0;
switch (m_nState)
{
case notLoaded:
nIndex = SERVER_IMAGE_NOT_LOADED;
break;
case loading:
nIndex = SERVER_IMAGE_LOADING;
break;
case loaded:
nIndex = SERVER_IMAGE_LOADED;
break;
case unableToLoad:
nIndex = SERVER_IMAGE_UNABLE_TO_LOAD;
break;
case accessDenied:
nIndex = SERVER_IMAGE_ACCESS_DENIED;
break;
default:
ASSERT(FALSE);
}
return nIndex;
}
void CADSIEditConnectionNode::OnChangeState(CComponentDataObject* pComponentDataObject)
{
switch (m_nState)
{
case notLoaded:
case loaded:
case unableToLoad:
case accessDenied:
{
m_nState = loading;
m_dwErr = 0;
}
break;
case loading:
{
if (m_dwErr == 0)
m_nState = loaded;
else if (m_dwErr == ERROR_ACCESS_DENIED)
m_nState = accessDenied;
else
m_nState = unableToLoad;
}
break;
default:
ASSERT(FALSE);
}
VERIFY(SUCCEEDED(pComponentDataObject->ChangeNode(this, CHANGE_RESULT_ITEM_ICON)));
VERIFY(SUCCEEDED(pComponentDataObject->UpdateVerbState(this)));
}
BOOL CADSIEditConnectionNode::OnRefresh(CComponentDataObject* pComponentData,
CNodeList* pNodeList)
{
BOOL bRet = FALSE;
DWORD dwCount = 0;
if (pNodeList == NULL)
{
dwCount = 1;
}
else
{
dwCount = pNodeList->GetCount();
}
if (dwCount > 1) // multiple selection
{
POSITION pos = pNodeList->GetHeadPosition();
while (pos != NULL)
{
CTreeNode* pNode = pNodeList->GetNext(pos);
ASSERT(pNode != NULL);
CNodeList nodeList;
nodeList.AddTail(pNode);
if (!pNode->OnRefresh(pComponentData, &nodeList))
{
bRet = FALSE;
}
}
}
else if (dwCount == 1) // single selection
{
if(CContainerNode::OnRefresh(pComponentData, pNodeList))
{
CADSIEditContainerNode * pNextNode;
POSITION pos = m_containerChildList.GetHeadPosition();
while (pos != NULL)
{
pNextNode = dynamic_cast<CADSIEditContainerNode*>(m_containerChildList.GetNext(pos));
ASSERT(pNextNode != NULL);
CNodeList nodeList;
nodeList.AddTail(pNextNode);
pNextNode->OnRefresh(pComponentData, &nodeList);
}
return TRUE;
}
}
return FALSE;
}
HRESULT CADSIEditConnectionNode::OnCommand(long nCommandID,
DATA_OBJECT_TYPES type,
CComponentDataObject* pComponentData,
CNodeList* pNodeList)
{
ASSERT (pNodeList->GetCount() == 1); // should only be a single selection
switch (nCommandID)
{
case IDM_SETTINGS_CONNECTION :
OnSettings(pComponentData);
break;
case IDM_REMOVE_CONNECTION :
OnRemove(pComponentData);
break;
case IDM_NEW_OBJECT :
OnCreate(pComponentData);
break;
case IDM_FILTER :
OnFilter(pComponentData);
break;
case IDM_UPDATE_SCHEMA :
OnUpdateSchema();
break;
case IDM_NEW_QUERY :
OnNewQuery(pComponentData);
break;
default:
ASSERT(FALSE); // Unknown command!
return E_FAIL;
}
return S_OK;
}
void CADSIEditConnectionNode::OnUpdateSchema()
{
// Force an update of the schema cache
CString szRootDSE;
CConnectionData* pConnectData = GetConnectionData();
CComPtr<IADs> spDirObject;
HRESULT hr = GetRootDSEObject(pConnectData, &spDirObject);
if (FAILED(hr))
{
ADSIEditErrorMessage(hr);
return;
}
VARIANT var;
var.vt = VT_I4;
var.lVal = 1;
hr = spDirObject->Put(CComBSTR(L"updateSchemaNow"), var);
if (FAILED(hr))
{
ADSIEditErrorMessage(hr);
return;
}
CString szSchema;
pConnectData->GetAbstractSchemaPath(szSchema);
szSchema = szSchema.Left(szSchema.GetLength()- 1);
CComPtr<IADs> spSchemaObject;
HRESULT hCredResult;
hr = OpenObjectWithCredentials(
pConnectData,
pConnectData->GetCredentialObject()->UseCredentials(),
szSchema,
IID_IADs,
(LPVOID*) &spSchemaObject,
NULL,
hCredResult
);
if ( FAILED(hr) )
{
if (SUCCEEDED(hCredResult))
{
ADSIEditErrorMessage(hr);
}
return;
}
hr = spSchemaObject->GetInfo();
if (FAILED(hr))
{
ADSIEditErrorMessage(hr);
}
//
// Now clear the schema cache
//
m_SchemaCache.Clear();
ADSIEditMessageBox(IDS_SCHEMA_UPDATE_SUCCESSFUL, MB_OK);
}
void CADSIEditConnectionNode::OnNewQuery(CComponentDataObject* pComponentData)
{
CThemeContextActivator activator;
CString sConnectPath;
GetADsObject()->GetPath(sConnectPath);
CConnectionData* pConnectData = GetConnectionData();
CCredentialObject* pCredObject = pConnectData->GetCredentialObject();
CString szServer;
pConnectData->GetDomainServer(szServer);
CADSIEditQueryDialog queryDialog(szServer, sConnectPath, pCredObject);
if (queryDialog.DoModal() == IDOK)
{
BOOL bOneLevel;
CString sQueryString, sName, sPath;
queryDialog.GetResults(sName, sQueryString, sPath, &bOneLevel);
CADSIEditConnectionNode* pConnectNode = GetADsObject()->GetConnectionNode();
CADsObject* pObject = new CADsObject();
if (pObject)
{
CADSIEditQueryData *pQueryData = new CADSIEditQueryData();
if (pQueryData)
{
// Name
pObject->SetName(sName);
pQueryData->SetName(sName);
// Set the root path of the query string
pObject->SetPath(sPath);
pQueryData->SetRootPath(sPath);
// Set the query string
pQueryData->SetFilter(sQueryString);
pObject->SetIntermediateNode(TRUE);
pObject->SetContainer(TRUE);
pObject->SetComplete(TRUE);
pObject->SetConnectionNode(pConnectNode);
// Set the scope of the query
ADS_SCOPEENUM scope;
scope = (bOneLevel) ? ADS_SCOPE_ONELEVEL : ADS_SCOPE_SUBTREE;
pQueryData->SetScope(scope);
// Create the query node with imbedded objects
CADSIEditQueryNode* pNewQueryNode = new CADSIEditQueryNode(pObject, pQueryData);
if (pNewQueryNode)
{
//
// Set the display name
//
CString sDisplayName;
pQueryData->GetDisplayName(sDisplayName);
pNewQueryNode->SetDisplayName(sDisplayName);
//
// Add to connection node's list of queries
//
pConnectNode->AddQueryToList(pQueryData);
if (pConnectNode->IsExpanded())
{
VERIFY(pConnectNode->AddChildToListAndUI(pNewQueryNode, pComponentData));
pComponentData->SetDescriptionBarText(this);
}
}
else
{
delete pObject;
pObject = 0;
delete pQueryData;
pQueryData = 0;
}
}
else
{
delete pObject;
pObject = 0;
}
}
}
}
void CADSIEditConnectionNode::OnFilter(CComponentDataObject* pComponentData)
{
CThemeContextActivator activator;
CADSIFilterDialog filterDialog(m_pConnectData);
if (filterDialog.DoModal() == IDOK)
{
CNodeList nodeList;
nodeList.AddTail(this);
OnRefresh(pComponentData, &nodeList);
}
}
void CADSIEditConnectionNode::OnCreate(CComponentDataObject* pComponentData)
{
CThemeContextActivator activator;
CCreatePageHolder* pHolder = new CCreatePageHolder(GetContainer(), this, pComponentData);
ASSERT(pHolder != NULL);
pHolder->SetSheetTitle(IDS_PROP_CONTAINER_TITLE, this);
pHolder->DoModalWizard();
}
BOOL CADSIEditConnectionNode::OnSetDeleteVerbState(DATA_OBJECT_TYPES type,
BOOL* pbHideVerb,
CNodeList* pNodeList)
{
*pbHideVerb = TRUE; // always hid the verb
return FALSE;
}
BOOL CADSIEditConnectionNode::OnAddMenuItem(LPCONTEXTMENUITEM2 pContextMenuItem,
long *pInsertionAllowed)
{
if (IsThreadLocked() || IsSheetLocked())
{
pContextMenuItem->fFlags = MF_GRAYED;
return TRUE;
}
if (GetConnectionData()->GetFilter()->InUse())
{
pContextMenuItem->fFlags = MF_CHECKED;
return TRUE;
}
return TRUE;
}
HRESULT CADSIEditConnectionNode::OnRename(CComponentDataObject* pComponentData,
LPWSTR lpszNewName)
{
HRESULT hr = S_OK;
BOOL bLocked = IsThreadLocked();
ASSERT(!bLocked); // cannot do refresh on locked node, the UI should prevent this
if (bLocked)
{
return hr;
}
if (!lpszNewName)
{
return E_INVALIDARG;
}
CString szDisplayExtra;
m_pConnectData->GetDomainServer(szDisplayExtra);
szDisplayExtra = L" [" + szDisplayExtra + L"]";
m_pConnectData->SetName(lpszNewName);
SetDisplayName(lpszNewName + szDisplayExtra);
return hr;
}
void CADSIEditConnectionNode::OnRemove(CComponentDataObject* pComponentData)
{
CString sLoadString, sCaption;
// NOTICE-2002/03/01-artm CString can throw out of memory exception,
// but that needs to be handled at a higher level so don't worry about
// it here.
if (sLoadString.LoadString(IDS_MSG_REMOVE_CONNECTION))
{
sCaption.Format((LPWSTR)(LPCWSTR)sLoadString, GetDisplayName());
}
if (ADSIEditMessageBox(sCaption, MB_YESNO | MB_DEFBUTTON2) == IDYES)
{
if (IsSheetLocked())
{
if (!CanCloseSheets())
return;
pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
}
ASSERT(!IsSheetLocked());
// now remove from the UI
DeleteHelper(pComponentData);
pComponentData->SetDescriptionBarText(GetContainer());
pComponentData->UpdateResultPaneView(GetContainer());
delete this; // gone
}
}
void CADSIEditConnectionNode::OnSettings(CComponentDataObject* pComponentData)
{
CWaitCursor cursor;
CThemeContextActivator activator;
CComponentDataObject* pComponentDataObject =
((CRootData*)(GetContainer()->GetRootContainer()))->GetComponentDataObject();
ASSERT(pComponentDataObject != NULL);
CContainerNode* pContNode = dynamic_cast<CContainerNode*>(GetContainer());
ASSERT(pContNode != NULL);
CADSIEditConnectDialog ConnectDialog(pContNode,
this,
pComponentDataObject,
m_pConnectData);
if (ConnectDialog.DoModal() == IDOK)
{
cursor.Restore();
if (HasQueries())
{
if (AfxMessageBox(IDS_MSG_EXISTING_QUERIES, MB_YESNO) == IDYES)
{
RemoveAllQueriesFromList();
}
}
CNodeList nodeList;
nodeList.AddTail(this);
OnRefresh(pComponentData, &nodeList);
}
}
BOOL CADSIEditConnectionNode::OnSetRefreshVerbState(DATA_OBJECT_TYPES type,
BOOL* pbHide,
CNodeList* pNodeList)
{
ASSERT(pNodeList->GetCount() == 1);
*pbHide = FALSE;
return !IsThreadLocked();
}
HRESULT CADSIEditConnectionNode::CreateFromStream(IStream* pStm, CADSIEditConnectionNode** ppConnectionNode)
{
WCHAR szBuffer[MAX_CONNECT_NAME_LENGTH + 1];
ULONG nLen; // WCHAR counting NULL
ULONG cbRead;
VERIFY(SUCCEEDED(pStm->Read((void*)&nLen,sizeof(UINT), &cbRead)));
ASSERT(cbRead == sizeof(UINT));
VERIFY(SUCCEEDED(pStm->Read((void*)szBuffer,sizeof(WCHAR)*nLen, &cbRead)));
ASSERT(cbRead == sizeof(WCHAR)*nLen);
CConnectionData* pConnect = CConnectionData::Load(pStm);
*ppConnectionNode = new CADSIEditConnectionNode(pConnect);
ASSERT(*ppConnectionNode != NULL);
CString szDisplayExtra, szDisplay;
pConnect->GetDomainServer(szDisplayExtra);
szDisplay = CString(szBuffer) + L" [" + szDisplayExtra + L"]";
(*ppConnectionNode)->SetDisplayName(szDisplay);
(*ppConnectionNode)->SetConnectionNode(*ppConnectionNode);
(*ppConnectionNode)->LoadQueryListFromStream(pStm);
return S_OK;
}
HRESULT CADSIEditConnectionNode::SaveToStream(IStream* pStm)
{
// for each connection name, write # of chars+NULL, and then the name
ULONG cbWrite;
CString szName;
m_pConnectData->GetName(szName);
SaveStringToStream(pStm, szName);
m_pConnectData->Save(pStm);
SaveQueryListToStream(pStm);
return S_OK;
}
void CADSIEditConnectionNode::LoadQueryListFromStream(IStream* pStm)
{
ULONG cbRead;
int iCount;
VERIFY(SUCCEEDED(pStm->Read((void*)&iCount,sizeof(int), &cbRead)));
ASSERT(cbRead == sizeof(int));
for (int idx = 0; idx < iCount; idx++)
{
CADSIEditQueryData* pQueryData = new CADSIEditQueryData();
CString sName, sQueryString, sPath;
// FUTURE-2002/03/01-artm Function LoadStringFromStream() should return
// success/error code and this function should call it.
// Who knows what kind of stream we've been given and how it could
// fail????
LoadStringFromStream(pStm, sName);
LoadStringFromStream(pStm, sQueryString);
LoadStringFromStream(pStm, sPath);
pQueryData->SetName(sName);
pQueryData->SetFilter(sQueryString);
CString sRootPath;
BuildQueryPath(sPath, sRootPath);
pQueryData->SetRootPath(sRootPath);
ADS_SCOPEENUM scope;
VERIFY(SUCCEEDED(pStm->Read((void*)&scope, sizeof(ADS_SCOPEENUM), &cbRead)));
ASSERT(cbRead == sizeof(ADS_SCOPEENUM));
pQueryData->SetScope(scope);
AddQueryToList(pQueryData);
}
}
void CADSIEditConnectionNode::BuildQueryPath(const CString& sPath, CString& sRootPath)
{
CConnectionData* pConnectData = GetConnectionData();
CString sServer, sLDAP, sPort, sTemp;
pConnectData->GetDomainServer(sServer);
pConnectData->GetLDAP(sLDAP);
pConnectData->GetPort(sPort);
if (sServer != _T(""))
{
sTemp = sLDAP + sServer;
if (sPort != _T(""))
{
sTemp = sTemp + _T(":") + sPort + _T("/");
}
else
{
sTemp = sTemp + _T("/");
}
sRootPath = sTemp + sPath;
}
else
{
sRootPath = sLDAP + sPath;
}
}
void CADSIEditConnectionNode::SaveQueryListToStream(IStream* pStm)
{
ULONG cbWrite;
int iCount = m_queryList.GetCount();
VERIFY(SUCCEEDED(pStm->Write((void*)&iCount, sizeof(int),&cbWrite)));
ASSERT(cbWrite == sizeof(int));
POSITION pos = m_queryList.GetHeadPosition();
while (pos != NULL)
{
CADSIEditQueryData* pQueryData = m_queryList.GetNext(pos);
ASSERT(pQueryData != NULL);
ADS_SCOPEENUM scope;
CString sName, sQueryString, sRootPath;
pQueryData->GetName(sName);
pQueryData->GetFilter(sQueryString);
pQueryData->GetDisplayPath(sRootPath);
scope = pQueryData->GetScope();
// save the query info to stream
SaveStringToStream(pStm, sName);
SaveStringToStream(pStm, sQueryString);
SaveStringToStream(pStm, sRootPath);
// Save the scope
VERIFY(SUCCEEDED(pStm->Write((void*)&scope, sizeof(ADS_SCOPEENUM),&cbWrite)));
ASSERT(cbWrite == sizeof(ADS_SCOPEENUM));
}
}