windows-nt/Source/XPSP1/NT/net/tapi/skywalker/rend/rndrend.cpp
2020-09-26 16:20:57 +08:00

648 lines
14 KiB
C++

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
rndrend.cpp
Abstract:
This module contains implementation of CRendezvous control.
--*/
#include "stdafx.h"
#include "rndrend.h"
#include "rndcoll.h"
#include "rndreg.h"
#include "rndnt.h"
#include "rndils.h"
#include "rndndnc.h"
#include "rndldap.h"
#include <atlwin.cpp>
CRegistry g_RregistryInfo;
CRendezvous::~CRendezvous()
{
if (m_fWinsockReady)
{
WSACleanup();
}
if ( m_pFTM )
{
m_pFTM->Release();
}
}
HRESULT CRendezvous::FinalConstruct(void)
{
LOG((MSP_TRACE, "CRendezvous::FinalConstruct - enter"));
HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
& m_pFTM );
if ( FAILED(hr) )
{
LOG((MSP_INFO, "CRendezvous::FinalConstruct - "
"create FTM returned 0x%08x; exit", hr));
return hr;
}
LOG((MSP_TRACE, "CRendezvous::FinalConstruct - exit S_OK"));
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Private functions
/////////////////////////////////////////////////////////////////////////////
HRESULT CRendezvous::InitWinsock()
{
Lock();
if (!m_fWinsockReady)
{
WSADATA wsaData;
int err;
// initialize winsock
if (err = WSAStartup(RENDWINSOCKVERSION, &wsaData))
{
Unlock();
return HRESULT_FROM_ERROR_CODE(err);
}
m_fWinsockReady = TRUE;
}
Unlock();
return S_OK;
}
HRESULT CRendezvous::CreateNTDirectory(
OUT ITDirectory **ppDirectory
)
/*++
Routine Description:
Create a object that uses NTDS to support the ITDirectory.
Arguments:
ppDirectory - the object being created.
Return Value:
HRESULT.
--*/
{
HRESULT hr;
// create the NTDS directory, if NTDS exists.
CComObject<CNTDirectory> * pNTDirectory;
hr = CComObject<CNTDirectory>::CreateInstance(&pNTDirectory);
if (NULL == pNTDirectory)
{
LOG((MSP_ERROR, "can't create NT Directory Object."));
return hr;
}
hr = pNTDirectory->_InternalQueryInterface(
IID_ITDirectory,
(void **)ppDirectory
);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CreateNTDirectory:QueryInterface failed: %x", hr));
delete pNTDirectory;
return hr;
}
return S_OK;
}
HRESULT CRendezvous::CreateILSDirectory(
IN const WCHAR * const wstrName,
IN const WORD wPort,
OUT ITDirectory ** ppDirectory
)
/*++
Routine Description:
Create a object that uses ILS to support the ITDirectory.
Arguments:
wstrName - The ILS server name.
wPort - The port that the server is listening on.
ppDirectory - the object being created.
Return Value:
HRESULT.
--*/
{
HRESULT hr;
// create the com object.
CComObject<CILSDirectory> * pILSDirectory;
hr = CComObject<CILSDirectory>::CreateInstance(&pILSDirectory);
if (NULL == pILSDirectory)
{
LOG((MSP_ERROR, "can't create ILS Directory Object."));
return hr;
}
// init the object with the server name and port.
hr = pILSDirectory->Init(wstrName, wPort);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CreateILSDirectory:Init failed: %x", hr));
delete pILSDirectory;
return hr;
}
// get the ITDirectory interface.
hr = pILSDirectory->_InternalQueryInterface(
IID_ITDirectory,
(void **)ppDirectory
);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CreateILSDirectory:QueryInterface failed: %x", hr));
delete pILSDirectory;
return hr;
}
return S_OK;
}
HRESULT CRendezvous::CreateNDNCDirectory(
IN const WCHAR * const wstrName,
IN const WORD wPort,
OUT ITDirectory ** ppDirectory
)
/*++
Routine Description:
Create a object that uses an NDNC to support the ITDirectory.
Arguments:
wstrName - The NDNC server name.
wPort - The port that the server is listening on.
ppDirectory - the object being created.
Return Value:
HRESULT.
--*/
{
LOG((MSP_TRACE, "CRendezvous::CreateNDNCDirectory - enter"));
HRESULT hr;
//
// create the com object.
//
CComObject<CNDNCDirectory> * pNDNCDirectory;
hr = CComObject<CNDNCDirectory>::CreateInstance(&pNDNCDirectory);
if ( NULL == pNDNCDirectory )
{
LOG((MSP_ERROR, "CreateNDNCDirectory - "
"can't create NDNC Directory Object - exit 0x%08x", hr));
return hr;
}
//
// get the ITDirectory interface.
//
hr = pNDNCDirectory->_InternalQueryInterface(
IID_ITDirectory,
(void **)ppDirectory
);
if ( FAILED( hr ) )
{
LOG((MSP_ERROR, "CreateNDNCDirectory - "
"QueryInterface failed - exit 0x%08x", hr));
delete pNDNCDirectory;
return hr;
}
//
// init the object with the server name and port.
// For NDNCs, this also looks around on the server and tries to
// see where on the server the NDNC is supposed to live. If there
// is no TAPI NDNC in the domain, this will fail. Therefore, when
// enumerating default directories, the local DC won't show up as
// an NDNC if there is no NDNC accessible from the local DC.
//
hr = pNDNCDirectory->Init(wstrName, wPort);
if ( FAILED( hr ) )
{
LOG((MSP_ERROR, "CreateNDNCDirectory - "
"Init failed - exit 0x%08x", hr));
(*ppDirectory)->Release();
*ppDirectory = NULL;
return hr;
}
LOG((MSP_TRACE, "CRendezvous::CreateNDNCDirectory - exit S_OK"));
return S_OK;
}
HRESULT CRendezvous::CreateDirectories(
SimpleVector <ITDirectory *> &VDirectory
)
/*++
Routine Description:
Find out all the direcories that are available.
Arguments:
pppDirectory - the array of directories being created.
dwCount - The number of directories.
Return Value:
HRESULT.
--*/
{
HRESULT hr;
LOG((MSP_TRACE, "CreateDirectories: "));
ITDirectory * pDirectory;
//
// First, create the NTDS non-dynamic directory object.
//
if (SUCCEEDED(hr = CreateNTDirectory(&pDirectory)))
{
if (!VDirectory.add(pDirectory))
{
pDirectory->Release();
return E_OUTOFMEMORY;
}
}
else
{
LOG((MSP_WARN, "Cannot create NT directory: 0x%08x", hr));
}
//
// Second, create the NDNC directory object.
//
WCHAR * pDomainControllerName;
//
// The first argument (=0) means we find out all
// objects
//
hr = GetDomainControllerName(0, &pDomainControllerName);
if ( SUCCEEDED(hr) )
{
hr = CreateNDNCDirectory(
pDomainControllerName,
LDAP_PORT,
&pDirectory
);
delete pDomainControllerName;
if ( SUCCEEDED( hr ) )
{
if (!VDirectory.add(pDirectory))
{
pDirectory->Release();
return E_OUTOFMEMORY;
}
}
else
{
LOG((MSP_WARN, "Cannot create NDNC directory: 0x%08x", hr));
}
}
else
{
LOG((MSP_WARN, "Cannot get DC name: 0x%08x", hr));
}
//
// Third, find out if there are any ILS servers published in the NTDS.
//
HANDLE hLookup;
int ret = ::LookupILSServiceBegin(&hLookup);
if (ret != NOERROR)
{
LOG((MSP_WARN, "Lookup ILSservice failed: 0x%08x", ret));
}
else
{
const DWORD MAX_HOST_NAME_LEN = 511;
WCHAR HostName[MAX_HOST_NAME_LEN + 1];
DWORD dwLen = MAX_HOST_NAME_LEN;
WORD wPort;
while (::LookupILSServiceNext(
hLookup,
HostName,
&dwLen,
&wPort
) == NOERROR)
{
LOG((MSP_INFO, "ILS server in NTDS: %S, Port:%d",
HostName, wPort));
hr = CreateILSDirectory(HostName, wPort, &pDirectory);
if (SUCCEEDED(hr))
{
if (!VDirectory.add(pDirectory))
{
pDirectory->Release();
return E_OUTOFMEMORY;
}
}
else
{
LOG((MSP_WARN, "Cannot create ILS directory: 0x%08x", hr));
}
dwLen = MAX_HOST_NAME_LEN;
}
::LookupILSServiceEnd(hLookup);
}
return S_OK;
}
HRESULT CRendezvous::CreateDirectoryEnumerator(
IN ITDirectory ** begin,
IN ITDirectory ** end,
OUT IEnumDirectory ** ppIEnum
)
/*++
Routine Description:
Create a enumerator of directories.
Arguments:
begin - The start iterator.
end - The end iterator.
ppIEnum - The enumerator being created.
Return Value:
HRESULT.
--*/
{
typedef _CopyInterface<ITDirectory> CCopy;
typedef CSafeComEnum<IEnumDirectory, &IID_IEnumDirectory,
ITDirectory *, CCopy> CEnumerator;
HRESULT hr;
CComObject<CEnumerator> *pEnum = NULL;
hr = CComObject<CEnumerator>::CreateInstance(&pEnum);
if (pEnum == NULL)
{
LOG((MSP_ERROR, "Could not create enumerator object, %x", hr));
return hr;
}
hr = pEnum->Init(begin, end, NULL, AtlFlagCopy);
if (FAILED(hr))
{
LOG((MSP_ERROR, "init enumerator object failed, %x", hr));
delete pEnum;
return hr;
}
// query for the IID_IEnumDirectory i/f
hr = pEnum->_InternalQueryInterface(IID_IEnumDirectory, (void**)ppIEnum);
if (FAILED(hr))
{
LOG((MSP_ERROR, "query enum interface failed, %x", hr));
delete pEnum;
return hr;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// ITRendezvous
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CRendezvous::get_DefaultDirectories(
OUT VARIANT * pVariant
)
{
if (BadWritePtr(pVariant))
{
LOG((MSP_ERROR, "bad variant pointer in get_DefaultDirectories"));
return E_POINTER;
}
BAIL_IF_FAIL(InitWinsock(), "Init winsock");
// create the default directories.
SimpleVector <ITDirectory *> VDirectory;
CreateDirectories(VDirectory);
// create the collection.
HRESULT hr = ::CreateInterfaceCollection(VDirectory.size(),
&VDirectory[0],
&VDirectory[VDirectory.size()],
pVariant);
// the collection has its ref count, so release local ones.
for (DWORD i = 0; i < VDirectory.size(); i ++)
{
VDirectory[i]->Release();
}
return hr;
}
STDMETHODIMP CRendezvous::EnumerateDefaultDirectories(
OUT IEnumDirectory ** ppEnumDirectory
)
{
if (BadWritePtr(ppEnumDirectory))
{
LOG((MSP_ERROR, "bad pointer in EnumerateDefaultDirectories"));
return E_POINTER;
}
BAIL_IF_FAIL(InitWinsock(), "Init winsock");
// create the default directories.
SimpleVector <ITDirectory *> VDirectory;
CreateDirectories(VDirectory);
// create the enumerator
HRESULT hr = CreateDirectoryEnumerator(
&VDirectory[0],
&VDirectory[VDirectory.size()],
ppEnumDirectory
);
for (DWORD i = 0; i < VDirectory.size(); i ++)
{
VDirectory[i]->Release();
}
return hr;
}
STDMETHODIMP CRendezvous::CreateDirectory(
IN DIRECTORY_TYPE DirectoryType,
IN BSTR pName,
OUT ITDirectory ** ppDir
)
{
if (BadWritePtr(ppDir))
{
LOG((MSP_ERROR, "bad pointer in CreateDirectory"));
return E_POINTER;
}
//
// We should validate the pName
// If is NULL we should return E_INVALIDARG
//
if( IsBadStringPtr( pName, (UINT)-1))
{
LOG((MSP_ERROR, "bad Name pointer in CreateDirectory"));
return E_INVALIDARG;
}
BAIL_IF_FAIL(InitWinsock(), "Init winsock");
HRESULT hr;
switch (DirectoryType)
{
case DT_NTDS:
hr = CreateNTDirectory(ppDir);
break;
case DT_ILS:
//
// Try NDNC first, as ILS is legacy. The CreateNDNCDirectory actually
// goes on the wire and checks if it looks like an NDNC server; the
// CreateILSDirectory does no such thing. This maintains the ability
// to use custom ports with ILS, and it also preserves the semantics
// of not getting a failure returned for a bad server name until you
// call ITDirectory::Connect.
//
hr = CreateNDNCDirectory(pName, LDAP_PORT, ppDir);
if ( FAILED(hr) )
{
hr = CreateILSDirectory(pName, ILS_PORT, ppDir);
}
break;
default:
LOG((MSP_ERROR, "unknown directory type, %x", DirectoryType));
hr = E_INVALIDARG;
}
return hr;
}
STDMETHODIMP CRendezvous::CreateDirectoryObject(
IN DIRECTORY_OBJECT_TYPE DirectoryObjectType,
IN BSTR pName,
OUT ITDirectoryObject ** ppDirectoryObject
)
{
if (BadWritePtr(ppDirectoryObject))
{
LOG((MSP_ERROR, "bad pointer in CreateDirectoryObject"));
return E_POINTER;
}
BAIL_IF_FAIL(InitWinsock(), "Init winsock");
HRESULT hr;
switch (DirectoryObjectType)
{
case OT_CONFERENCE:
hr = ::CreateEmptyConference(pName, ppDirectoryObject);
break;
case OT_USER:
hr = ::CreateEmptyUser(pName, ppDirectoryObject);
break;
default:
LOG((MSP_ERROR, "unknown directory type, %x", DirectoryObjectType));
hr = E_INVALIDARG;
}
return hr; // ZoltanS fix 6-1-98
}
// eof