618 lines
14 KiB
C++
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);
|
|
}
|
|
|