windows-nt/Source/XPSP1/NT/ds/adsi/ldap/cconnect.cxx
2020-09-26 16:20:57 +08:00

618 lines
14 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: cconnect.cxx
//
// Contents: LDAP Connection object - this object implements the
// IUmiConnection interface.
//
// Functions: TBD.
//
// History: 03-03-00 AjayR Created.
//
//----------------------------------------------------------------------------
#include "ldap.hxx"
//+---------------------------------------------------------------------------
// Function: CLDAPConObject::CLDAPConObject
//
// Synopsis: Constructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CLDAPConObject::CLDAPConObject():
_pPropMgr(NULL),
_fConnected(FALSE),
_pLdapHandle(NULL),
_ulErrorStatus(0)
{
}
//+---------------------------------------------------------------------------
// Function: CLDAPConObject::~CLDAPConObject
//
// Synopsis: Destructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CLDAPConObject::~CLDAPConObject()
{
delete _pPropMgr;
//
// Close the handle if needed - this will deref and free if appropriate.
//
if (_pLdapHandle) {
LdapCloseObject(_pLdapHandle);
_pLdapHandle = NULL;
}
}
//+---------------------------------------------------------------------------
// Function: CLDAPConObject::CreateConnectionObject
//
// Synopsis: Static allocation routine for connection object.
//
// Arguments: CLDAPConObject * --- contains new connection object
// PADSLDP --- ldap handle defaulted NULL.
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: CLDAPConObject ** - ptr to newly created object.
//
//----------------------------------------------------------------------------
HRESULT
CLDAPConObject::CreateConnectionObject(
CLDAPConObject FAR * FAR * ppConnectionObject,
PADSLDP pLdapHandle // defaulted to NULL
)
{
HRESULT hr = S_OK;
CLDAPConObject FAR * pConObj = NULL;
CPropertyManager FAR * pIntfPropMgr = NULL;
pConObj = new CLDAPConObject();
if (!pConObj) {
RRETURN_EXP_IF_ERR(E_OUTOFMEMORY);
}
//
// Add a ref to the ldap handle if one was passed in.
//
if (pLdapHandle) {
pConObj->_pLdapHandle = pLdapHandle;
pConObj->_fConnected = TRUE;
LdapCacheAddRef(pConObj->_pLdapHandle);
}
hr = CPropertyManager::CreatePropertyManager(
(IUmiConnection *) pConObj,
NULL, // outer unk
NULL, // credentials
IntfPropsConnection,
&pIntfPropMgr
);
BAIL_ON_FAILURE(hr);
pConObj->_pPropMgr = pIntfPropMgr;
*ppConnectionObject = pConObj;
RRETURN(S_OK);
error:
//
// If we get here, we likely could not create the property manager.
//
if (pConObj) {
delete pConObj;
}
RRETURN(hr);
}
STDMETHODIMP
CLDAPConObject::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
HRESULT hr = S_OK;
SetLastStatus(0);
if (ppv == NULL) {
RRETURN(E_POINTER);
}
if (IsEqualIID(iid, IID_IUnknown)){
*ppv = (IUnknown FAR *) this;
}
else if (IsEqualIID(iid, IID_IUmiPropList)) {
*ppv = (IUmiConnection FAR *) this;
}
else if (IsEqualIID(iid, IID_IUmiBaseObject)) {
*ppv = (IUmiConnection FAR *) this;
}
else if (IsEqualIID(iid, IID_IUmiConnection)) {
*ppv = (IUmiConnection FAR *) this;
}
else {
*ppv = NULL;
SetLastStatus(E_NOINTERFACE);
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
//
// IUmiConnection methods.
//
//+---------------------------------------------------------------------------
// Function: CLDAPConObject::Open
//
// Synopsis: Opens a connection to the server (either implicityly
// specified in the url or explicitly in the interface
// properties. If there is already an underlyng ldap connection,
// subsequent open operations will fail if they do not use the same
// underlying connection.
//
// Arguments: pUrl - IUmiUrl object pointing to object to be fetched.
// uFlags - Flags for the operation (currently on 0).
// TargetIID - IID requested on the target object.
// ppvRes - ptr to return the target object.
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: The status of the object and underlying ldap handle ptr.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CLDAPConObject::Open(
IUmiURL *pURL,
ULONG uFlags,
REFIID TargetIID,
void ** ppvRes
)
{
HRESULT hr = S_OK;
LPWSTR pszUrl = NULL;
IUnknown *pUnk = NULL;
IADsObjOptPrivate * pPrivOpt = NULL;
PADSLDP pLdapTmpHandle = NULL;
//
// Default values for credentials.
//
LPWSTR pszUserName = NULL;
LPWSTR pszPassword = NULL;
LPWSTR pszLdapPath = NULL;
DWORD dwFlags = 0;
BOOL fFlag;
SetLastStatus(0);
if (!ppvRes || !pURL) {
BAIL_ON_FAILURE(hr = E_INVALIDARG);
}
if (uFlags != 0) {
BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
}
*ppvRes = NULL;
//
// UrlToLDAPPath can handle both native and umi paths.
//
hr = UrlToLDAPPath(
pURL,
&pszLdapPath
);
BAIL_ON_FAILURE(hr);
//
// Prepare the credentials if applicable.
//
if (!_pCredentials) {
//
// Get the params from the property mgr.
//
hr = _pPropMgr->GetStringProperty(L"__UserId", &pszUserName);
if (hr == E_OUTOFMEMORY) {
BAIL_ON_FAILURE(hr);
}
hr = _pPropMgr->GetStringProperty(L"__Password", &pszPassword);
if (hr == E_OUTOFMEMORY) {
BAIL_ON_FAILURE(hr);
}
hr = _pPropMgr->GetBoolProperty(
L"__SECURE_AUTHENTICATION",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_SECURE_AUTHENTICATION;
}
hr = _pPropMgr->GetBoolProperty(
L"__NO_AUTHENTICATION",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_NO_AUTHENTICATION;
}
hr = _pPropMgr->GetBoolProperty(
L"__PADS_READONLY_SERVER",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_READONLY_SERVER;
}
hr = _pPropMgr->GetBoolProperty(
L"__PADS_PROMPT_CREDENTIALS",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_PROMPT_CREDENTIALS;
}
hr = _pPropMgr->GetBoolProperty(
L"__PADS_SERVER_BIND",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_SERVER_BIND;
}
hr = _pPropMgr->GetBoolProperty(
L"__PADS_FAST_BIND",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_FAST_BIND;
}
hr = _pPropMgr->GetBoolProperty(
L"__PADS_USE_SIGNING",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_USE_SIGNING;
}
hr = _pPropMgr->GetBoolProperty(
L"__PADS_USE_SEALING",
&fFlag
);
BAIL_ON_FAILURE(hr);
if (fFlag) {
dwFlags |= ADS_USE_SEALING;
}
// hr = _pPropMgr->GetLongProperty(L"__USE_ENCRYPTION", &lVal);
// BAIL_ON_FAILURE(hr);
// Spec needs to be resolved before we can do this.
//
// Always do this as this is what tells us we are in UMI mode.
//
dwFlags |= ADS_AUTH_RESERVED;
_pCredentials = new CCredentials(
pszUserName,
pszPassword,
dwFlags
);
if (!_pCredentials) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
}
//
// In the future we might want to add some sanity check before
// making this call. That might save some network traffic in the
// rare cases.
// Note that currently, we always get the object and then we compare
// the handles to see if we have inded got an object on the same
// connection (and fail appropriately if not).
//
hr = ::GetObject(
pszLdapPath,
*_pCredentials,
(LPVOID *) &pUnk
) ;
BAIL_ON_FAILURE(hr);
//
// By default we get back IADs, so we need to QI for intf.
//
hr = pUnk->QueryInterface(TargetIID, ppvRes);
BAIL_ON_FAILURE(hr);
//
// At this point copy over the handle if applicable. If the handle is
// already set, then we need to make sure we are using the same
// connection.
// If do not get the handle for whatever reason, we will use the
// defaulted NULL value and in that case we wont save the handle or
// compare the value.
//
hr = pUnk->QueryInterface(IID_IADsObjOptPrivate, (LPVOID *) &pPrivOpt);
if (SUCCEEDED(hr)) {
//
// If we succeeded then we want to try and compare handles.
//
hr = pPrivOpt->GetOption(
LDP_CACHE_ENTRY,
(void*) &pLdapTmpHandle
);
}
//
// Reset hr just in case the above failed.
//
hr = S_OK;
if (_fConnected) {
//
// Verify that the handles are the same.
//
if (_pLdapHandle
&& pLdapTmpHandle
&& (_pLdapHandle != pLdapTmpHandle)) {
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
}
}
else {
//
// New connection.
//
if (pLdapTmpHandle) {
_pLdapHandle = pLdapTmpHandle;
_fConnected = TRUE;
LdapCacheAddRef(_pLdapHandle);
}
}
error:
//
// Release the ref in all cases. If QI failed that will del the obj.
//
if (pUnk) {
pUnk->Release();
}
if (pPrivOpt) {
pPrivOpt->Release();
}
if (FAILED(hr)) {
//
// Update the error status.
//
SetLastStatus(hr);
hr = MapHrToUmiError(hr);
if (*ppvRes) {
//
// We got the object but a subsequent operation failed.
//
*ppvRes = NULL;
pUnk->Release();
}
}
if (pszUserName) {
FreeADsStr(pszUserName);
}
if (pszPassword) {
FreeADsStr(pszPassword);
}
if (pszLdapPath) {
FreeADsMem(pszLdapPath);
}
RRETURN(hr);
}
//
// IUmiBaseObject methods.
//
STDMETHODIMP
CLDAPConObject::GetLastStatus(
ULONG uFlags,
ULONG *puSpecificStatus,
REFIID riid,
LPVOID *pStatusObj
)
{
if (pStatusObj) {
*pStatusObj = NULL;
}
if (puSpecificStatus) {
*puSpecificStatus = 0;
}
else {
RRETURN(E_INVALIDARG);
}
if (uFlags) {
RRETURN(UMI_E_INVALID_FLAGS);
}
*puSpecificStatus = _ulErrorStatus;
RRETURN(S_OK);
}
STDMETHODIMP
CLDAPConObject::GetInterfacePropList(
ULONG uFlags,
IUmiPropList **pPropList
)
{
RRETURN(_pPropMgr->QueryInterface(IID_IUmiPropList, (void **) pPropList));
}
//
// Methods defined on the proplist interface - none are implemented.
// All the properties need to be set on the interface property list.
//
STDMETHODIMP
CLDAPConObject::Put(
IN LPCWSTR pszName,
IN ULONG uFlags,
IN UMI_PROPERTY_VALUES *pProp
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CLDAPConObject::Get(
IN LPCWSTR pszName,
IN ULONG uFlags,
OUT UMI_PROPERTY_VALUES **pProp
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CLDAPConObject::GetAt(
IN LPCWSTR pszName,
IN ULONG uFlags,
IN ULONG uBufferLength,
OUT LPVOID pExisitingMem
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CLDAPConObject::Delete(
IN LPCWSTR pszName,
IN ULONG ulFlags
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CLDAPConObject::GetAs(
IN LPCWSTR pszName,
IN ULONG uFlags,
IN ULONG uCoercionType,
IN OUT UMI_PROPERTY_VALUES **pProp
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CLDAPConObject::FreeMemory(
ULONG uReserved,
LPVOID pMem
)
{
if (pMem) {
//
// At this time this has to be a pUmiProperty. Ideally we should
// tag this in some way so that we can check to make sure.
//
RRETURN(FreeUmiPropertyValues((UMI_PROPERTY_VALUES *)pMem));
}
RRETURN(S_OK);
}
STDMETHODIMP
CLDAPConObject::GetProps(
IN LPCWSTR* pszNames,
IN ULONG uNameCount,
IN ULONG uFlags,
OUT UMI_PROPERTY_VALUES **pProps
)
{
RRETURN(E_NOTIMPL);
}
HRESULT
CLDAPConObject::PutProps(
IN LPCWSTR* pszNames,
IN ULONG uNameCount,
IN ULONG uFlags,
IN UMI_PROPERTY_VALUES *pProps
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CLDAPConObject::PutFrom(
IN LPCWSTR pszName,
IN ULONG uFlags,
IN ULONG uBufferLength,
IN LPVOID pExistingMem
)
{
RRETURN(E_NOTIMPL);
}