|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: cumiobj.cxx
//
// Contents: Contains the implementation of IUmiObject/Container methods.
// Methods are encapsulated in one object but this object holds
// a pointer to the inner unknown of the corresponding LDAP
// object. The methods of IUmiContainer are also implemented on
// this object, but will only be used if the underlying object
// is a container.
//
// History: 03-06-00 SivaramR Created.
// 04-07-00 AjayR modified for LDAP Provider.
//
//----------------------------------------------------------------------------
#include "ldap.hxx"
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::CLDAPUmiObject
//
// Synopsis: Constructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CLDAPUmiObject::CLDAPUmiObject(): _pPropMgr(NULL), _pIntfPropMgr(NULL), _pUnkInner(NULL), _pIADs(NULL), _pIADsContainer(NULL), _ulErrorStatus(0), _pCoreObj(NULL), _pExtMgr(NULL), _fOuterUnkSet(FALSE) { }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::~CLDAPUmiObject
//
// Synopsis: Destructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CLDAPUmiObject::~CLDAPUmiObject(void) { if (_pIntfPropMgr) { delete _pIntfPropMgr; }
if (_pPropMgr) { delete _pPropMgr; }
if (_pUnkInner) { _pUnkInner->Release(); }
if (_pIADsContainer) { _pIADsContainer->Release(); }
if (_pIADs) { _pIADs->Release(); }
//
// We specifically do not release these as they are all just ptrs
// _pCreds, _pszLDAPServer, _pszLDAPDn, _pLdapHandle.
//
}
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::AllocateLDAPUmiObject --- Static constructor.
//
// Synopsis: Static contstructor routine.
//
// Arguments: intfPropTable- Schema information for interface properties.
// pPropCache - Pointer to property cache (shared with IADs).
// pUnkInner - Pointer to inner unknown of underlying obj.
// pExtMgr - Pointer to extension manager of object.
// pCoreObj - Pointer to the core object of underlying object.
// ppUmiObj - Return value.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppUmObj to point to newly created object.
//
//----------------------------------------------------------------------------
HRESULT CLDAPUmiObject::CreateLDAPUmiObject( INTF_PROP_DATA intfPropTable[], CPropertyCache *pPropertyCache, IUnknown *pUnkInner, CCoreADsObject *pCoreObj, IADs *pIADs, CCredentials *pCreds, CLDAPUmiObject **ppUmiObj, DWORD dwPort, // defaulted to -1
PADSLDP pLdapHandle, // defaulted to NULL
LPWSTR pszServerName, // defaulted to NULL
LPWSTR pszLDAPDn, // defaulted to NULL
CADsExtMgr *pExtMgr // defaulted to NULL
) { HRESULT hr = S_OK; CLDAPUmiObject *pUmiObject = NULL; CPropertyManager *pPropMgr = NULL; CPropertyManager *pIntfPropMgr = NULL;
//
// This always has to be there, the extension manager will not
// be there for RootDSE and schema realted objects.
//
ADsAssert(pCoreObj);
pUmiObject = new CLDAPUmiObject(); if (!pUmiObject) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Property cache is not supported on the schema container object alone.
// There will be no support for the propList methods for this object.
//
if (pPropertyCache) { //
// Has to be valid if we have a property cache.
//
ADsAssert(pUnkInner);
//
// Need the standard property manager for Get/Put support.
//
hr = CPropertyManager::CreatePropertyManager( pIADs, (IUmiObject *) pUmiObject, pPropertyCache, pCreds, pszServerName, &pPropMgr );
BAIL_ON_FAILURE(hr); }
if (intfPropTable) { hr = CPropertyManager::CreatePropertyManager( (IUmiObject *) pUmiObject, pUnkInner, // should support IADs.
pCreds, intfPropTable, &pIntfPropMgr ); BAIL_ON_FAILURE(hr); } //
// At this point failures are not catastrophic so we can prepare
// the object for return.
//
pUmiObject->_pUnkInner = pUnkInner; pUmiObject->_pIADs = pIADs; pUmiObject->_pExtMgr = pExtMgr; pUmiObject->_pCoreObj = pCoreObj; pUmiObject->_pCreds = pCreds; pUmiObject->_pPropMgr = pPropMgr; pUmiObject->_pIntfPropMgr = pIntfPropMgr; pUmiObject->_pszLDAPServer = pszServerName; pUmiObject->_pszLDAPDn = pszLDAPDn; pUmiObject->_pLdapHandle = pLdapHandle; pUmiObject->_dwPort = dwPort;
//
// Addref cause we release this in the destructor.
//
pIADs->AddRef();
//
// Get IADsContainer ptr if applicable - can ignore failures.
//
hr = pUnkInner->QueryInterface( IID_IADsContainer, (void **) &(pUmiObject->_pIADsContainer) );
*ppUmiObj = pUmiObject;
RRETURN(S_OK);
error:
if (pUmiObject) { delete pUmiObject; } if (pPropMgr) { delete pPropMgr; }
if (pIntfPropMgr) { delete pIntfPropMgr; } RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::QueryInterface --- IUnknown support.
//
// Synopsis: Standard query interface method.
//
// Arguments: iid - Interface requested.
// ppInterface - Return pointer to interface requested.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::QueryInterface( REFIID iid, LPVOID *ppInterface ) { HRESULT hr = S_OK; IUnknown *pTmpIntfPtr = NULL;
SetLastStatus(0);
if (!ppInterface) { RRETURN(E_INVALIDARG); }
*ppInterface = NULL;
if (IsEqualIID(iid, IID_IUnknown)) { *ppInterface = (IUmiObject *) this; } else if (IsEqualIID(iid, IID_IUmiPropList)) { *ppInterface = (IUmiObject *) this; } else if (IsEqualIID(iid, IID_IUmiBaseObject)) { *ppInterface = (IUmiObject *) this; } else if (IsEqualIID(iid, IID_IUmiObject)) { *ppInterface = (IUmiObject *) this; } else if (IsEqualIID(iid, IID_IUmiContainer)) { //
// Check if underlying LDAP object is a container.
//
if (_pIADsContainer != NULL) { *ppInterface = (IUmiContainer *) this; } else { RRETURN(E_NOINTERFACE); } } else if (IsEqualIID(iid, IID_IUmiCustomInterfaceFactory)) { *ppInterface = (IUmiCustomInterfaceFactory *) this; } else if (IsEqualIID(iid, IID_IADsObjOptPrivate)) { if (_pLdapHandle) { *ppInterface = (IADsObjOptPrivate*) this; } else { RRETURN(E_NOINTERFACE); } } else { RRETURN(E_NOINTERFACE); }
AddRef(); RRETURN(S_OK); } //+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::Clone --- IUmiObject support.
//
// Synopsis: Clones this object. Note that this will do an implicit
// refresh if one has not already been done on the object before
// copying all the attributes. The new object has a state that a
// bound state (rather than unbound).
//
// Arguments: uFlags --- Must be 0 for now.
// riid --- IID requested on the clone.
// pCopy --- The return ptr for the cloned object.
//
// Returns: S_OK or appropriate error code.
//
// Modifies: pCopy to be updated with new UmiObject ptr on success.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::Clone( ULONG uFlags, REFIID riid, LPVOID *pCopy ) { HRESULT hr = S_OK; CCredentials Creds; BSTR bstrPath = NULL; BSTR bstrClass = NULL; LPWSTR pszParent = NULL, pszCommonName = NULL; IUmiObject *pUmiObj = NULL; IUmiObject *pDestUmiObj = NULL; DWORD dwAuthFlags = 0;
SetLastStatus(0);
//
// We cannot clone objects that do not have an underlying IADs ptr.
//
if (!_pIADs) { BAIL_ON_FAILURE(hr = E_FAIL); }
if (_pCreds) { Creds = *_pCreds; }
//
// Need to tag on the ADS_FAST_BIND to prevent the call from
// going on the wire.
//
dwAuthFlags = Creds.GetAuthFlags(); Creds.SetAuthFlags(dwAuthFlags | ADS_FAST_BIND);
//
// Need to call Refresh with the internal flag. Note that using this
// flag means that we will go on the wire only if we have to.
//
hr = this->Refresh( ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED, NULL, NULL ); BAIL_ON_FAILURE(hr);
//
// Next we need to get the destination object.
//
hr = _pIADs->get_ADsPath(&bstrPath); BAIL_ON_FAILURE(hr);
if (_pCoreObj->GetObjectState() == ADS_OBJECT_UNBOUND) { //
// In this case we need to Create the target object.
// The parent path, the common name and the class are needed.
//
hr = BuildADsParentPath( bstrPath, &pszParent, &pszCommonName ); BAIL_ON_FAILURE(hr);
hr = _pIADs->get_Class(&bstrClass); BAIL_ON_FAILURE(hr);
hr = CLDAPGenObject::CreateGenericObject( pszParent, pszCommonName, bstrClass, Creds, ADS_OBJECT_UNBOUND, riid, // this is ignored
(void **) &pUmiObj ); BAIL_ON_FAILURE(hr); } else { //
// In this case we bind to the object.
//
hr = GetObject(bstrPath, Creds, (void **)&pUmiObj); BAIL_ON_FAILURE(hr); }
pUmiObj->QueryInterface(IID_IUmiObject, (void **) &pDestUmiObj); BAIL_ON_FAILURE(hr);
//
// Now we can call the helper to copy the attributes over.
//
hr = this->CopyToHelper( (IUmiObject*) this, pDestUmiObj, 0, FALSE, // do not mark as update
FALSE // do not copy intf props
); BAIL_ON_FAILURE(hr);
//
// Update return value as this means copy was succesful.
//
*pCopy = pDestUmiObj;
error:
if (FAILED(hr)) { if (!_ulErrorStatus) { SetLastStatus(hr); } hr = MapHrToUmiError(hr);
if (pDestUmiObj) { pDestUmiObj->Release(); } }
if (bstrPath) { SysFreeString(bstrPath); }
if (bstrClass) { SysFreeString(bstrClass); } if (pszParent) { FreeADsStr(pszParent); } if (pszCommonName) { FreeADsStr(pszCommonName); }
if (pUmiObj) { pUmiObj->Release(); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::CopyTo --- IUmiObject support.
//
// Synopsis: Copies the object to the new destination.Note that this will
// do an implicit refresh if one has not already been done on the
// object before copying all the attributes. The new objecst state
// is unbound, and the new object will be created on the destination
// directory only when Commit is called. If any of the properties on
// the object being copied are marked as updated/dirty then the call
// will fail.
//
// Arguments: uFlags --- Must be 0 for now.
// pURL --- Url pointing to the destination.
// riid --- IID requested on the clone.
// pCopy --- The return ptr for the copied object.
//
// Returns: S_OK or appropriate error code.
//
// Modifies: pCopy to be updated with new UmiObject ptr on success.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::CopyTo( IN ULONG uFlags, IN IUmiURL *pURL, IN REFIID riid, OUT LPVOID *pCopy ) { HRESULT hr = S_OK; CCredentials Creds; BSTR bstrClass = NULL; LPWSTR pszLdapPath = NULL; LPWSTR pszParent = NULL, pszCommonName = NULL; IUmiObject *pUmiObj = NULL; IUmiObject *pUmiDestObj = NULL; DWORD dwAuthFlags = 0;
SetLastStatus(0);
RRETURN(E_NOTIMPL); //*******************************************************/
// This code is not used currently. /
//*******************************************************/
//
// Has to be 0.
//
if (uFlags) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
//
// All these need to be valid.
//
if (!pURL || !pCopy || (riid != IID_IUmiObject) ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// We cannot copy objects that do not have an underlying IADs ptr.
//
if (!_pIADs) { BAIL_ON_FAILURE(hr = E_FAIL); }
if (_pCreds) { Creds = *_pCreds; }
//
// Need to call Refresh with the internal flag. Note that using this
// flag means that we will go on the wire only if we have to.
//
hr = this->Refresh( ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED, NULL, NULL ); BAIL_ON_FAILURE(hr);
hr = _pIADs->get_Class(&bstrClass); BAIL_ON_FAILURE(hr);
//
// Now we need to convert the UmiPath to LDAPPath that we can use.
//
hr = UrlToLDAPPath( pURL, &pszLdapPath ); BAIL_ON_FAILURE(hr);
//
// We need to split path to parent and common name.
//
hr = BuildADsParentPath( pszLdapPath, &pszParent, &pszCommonName ); BAIL_ON_FAILURE(hr);
hr = CLDAPGenObject::CreateGenericObject( pszParent, pszCommonName, bstrClass, Creds, ADS_OBJECT_UNBOUND, riid, // this is ignored
(void **) &pUmiObj ); BAIL_ON_FAILURE(hr);
hr = pUmiObj->QueryInterface(riid, (void **) &pUmiDestObj); BAIL_ON_FAILURE(hr);
//
// Need to copy the attributes over now.
//
hr = this->CopyToHelper( this, pUmiDestObj, 0, TRUE, // means fail call if property status is not 0
FALSE // do not copy intf props.
); BAIL_ON_FAILURE(hr);
*pCopy = pUmiDestObj;
error:
if (pszLdapPath) { FreeADsStr(pszLdapPath); }
if (pszParent) { FreeADsStr(pszParent); }
if (pszCommonName) { FreeADsStr(pszCommonName); }
if (pUmiObj) { pUmiObj->Release(); }
if (bstrClass) { SysFreeString(bstrClass); }
if (FAILED(hr)) { if (!this->_ulErrorStatus) { SetLastError(hr); }
if (pUmiDestObj) { pUmiDestObj->Release(); } }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::Refresh --- IUmiObject support.
//
// Synopsis: Refreshes the properties of the object. This calls the
// underlying LDAP object for the operation.
//
// Arguments: uFlags - UMI_FLAGS_REFERESH_ALL, PARTIAL supported
// and ADSI internal flag to implicit GetInfo only
// if one is needed (helps clone and copyto).
// uNameCount - Number of attributes to refresh.
// pszNames - Names of attributes to refresh.
//
// Returns: S_OK on success. Error code otherwise
//
// Modifies: Underlying property cache.
//
//----------------------------------------------------------------------------
HRESULT CLDAPUmiObject::Refresh( ULONG uFlags, ULONG uNameCount, LPWSTR *pszNames ) { ULONG i = 0; HRESULT hr = S_OK; BOOL fUseGetInfoEx = FALSE; DWORD dwGetInfoFlag = TRUE;
SetLastStatus(0);
//
// Only all and partial and the special internal flag. Refresh
// partial translates to an implicit getinfo in ADSI.
//
if ((uFlags != UMI_FLAG_REFRESH_ALL) && (uFlags != UMI_FLAG_REFRESH_PARTIAL) && (uFlags != ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED) ) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
if (uFlags == UMI_FLAG_REFRESH_PARTIAL) { //
// Cannot specify list of names in this case.
//
if (uNameCount != 0) { BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_OPERATION); } dwGetInfoFlag = GETINFO_FLAG_IMPLICIT; } else if (uFlags == ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED) { dwGetInfoFlag = GETINFO_FLAG_IMPLICIT_AS_NEEDED; }
if ((uFlags == UMI_FLAG_REFRESH_ALL) && (uNameCount != 0)) { fUseGetInfoEx = TRUE; }
if (fUseGetInfoEx) { //
// Build the variant array of strings.
//
VARIANT vVar; VariantInit(&vVar);
//
// Builds a variant array we can use in GetInfoEx
//
hr = ADsBuildVarArrayStr( pszNames, (DWORD)uNameCount, &vVar); BAIL_ON_FAILURE(hr);
//
// Call GetInfoEx to do the actual work.
//
hr = _pIADs->GetInfoEx(vVar, 0); VariantClear(&vVar); } else { hr = this->_pCoreObj->GetInfo(dwGetInfoFlag); //
// Since schema and few others do not implement the implicit GetInfo.
//
if (FAILED(hr) && hr == E_NOTIMPL) { //
// Should try just an ordinary GetInfo if applicable.
//
if (dwGetInfoFlag == GETINFO_FLAG_EXPLICIT) { hr = _pIADs->GetInfo(); } } }
BAIL_ON_FAILURE(hr);
error:
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::Commit --- IUmiObject support.
//
// Synopsis: Implements IUmiObject::Commit. Calls SetInfo on WinNT
// object to commit changes made to the cache.
//
// Arguments: uFlags - Only 0 for now.
//
// Returns: S_OK on success. Error code otherwise
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::Commit(ULONG uFlags) { HRESULT hr = S_OK; IADsObjOptPrivate *pPrivOpt = NULL; DWORD dwFlags;
SetLastStatus(0);
if (uFlags > UMI_DONT_COMMIT_SECURITY_DESCRIPTOR) { SetLastStatus(UMI_E_INVALID_FLAGS); RRETURN(UMI_E_INVALID_FLAGS); }
//
// If this is set do not commit security descriptor.
//
if (uFlags & UMI_DONT_COMMIT_SECURITY_DESCRIPTOR) { //
// The prop manager has to do this cause it has the prop cache.
//
hr = _pPropMgr->DeleteSDIfPresent(); BAIL_ON_FAILURE(hr); }
if (uFlags & UMI_SECURITY_MASK) { //
// Need to make sure that we update the SD
// flags on the ADSI object if necessary.
//
if (!_pIADs) { BAIL_ON_FAILURE(hr = E_FAIL); } hr = _pIADs->QueryInterface( IID_IADsObjOptPrivate, (void **)&pPrivOpt ); BAIL_ON_FAILURE(hr);
dwFlags = uFlags & UMI_SECURITY_MASK;
hr = pPrivOpt->SetOption( LDAP_SECURITY_MASK, (void *) &dwFlags ); BAIL_ON_FAILURE(hr); }
hr = _pIADs->SetInfo(); BAIL_ON_FAILURE(hr);
error:
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
if (pPrivOpt) { pPrivOpt->Release(); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// IUmiPropList methods
//
// These are implemented by invoking the corresponding method in the
// CUmiPropList object that implements object properties. For a description
// of these methods, refer to cpropmgr.cxx
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::Put( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES *pProp ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->Put( pszName, uFlags, pProp );
if (FAILED(hr)) { IID iid; //
// Need to update the error status on this object.
//
_pPropMgr->GetLastStatus( // ignore error return
0, &ulStatus, iid, NULL ); SetLastStatus(ulStatus); } RRETURN(hr); }
STDMETHODIMP CLDAPUmiObject::Get( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->Get( pszName, uFlags, ppProp );
if (FAILED(hr)) { //
// Update error on this object appropriately.
//
IID iid; _pPropMgr->GetLastStatus( 0, &ulStatus, iid, NULL );
SetLastStatus(ulStatus); }
//
// No need to map the error as the property manager would have
// already done that for us.
//
RRETURN(hr); }
STDMETHODIMP CLDAPUmiObject::GetAs( LPCWSTR pszName, ULONG uFlags, ULONG uCoercionType, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->GetAs( pszName, uFlags, uCoercionType, ppProp );
if (FAILED(hr)) { //
// Update error on this object appropriately.
//
IID iid; _pPropMgr->GetLastStatus( // ignore error return
0, &ulStatus, iid, NULL );
SetLastStatus(ulStatus); }
//
// No need to map hr as property manager would have already done that.
//
RRETURN(hr); }
STDMETHODIMP CLDAPUmiObject::FreeMemory( ULONG uReserved, LPVOID pMem ) { HRESULT hr = S_OK;
if (uReserved) { SetLastStatus(E_INVALIDARG); RRETURN(E_INVALIDARG); }
hr = FreeUmiPropertyValues((PUMI_PROPERTY_VALUES) pMem);
SetLastStatus(hr); RRETURN(hr); }
STDMETHODIMP CLDAPUmiObject::GetAt( LPCWSTR pszName, ULONG uFlags, ULONG uBufferLength, LPVOID pExistingMem ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->GetAt( pszName, uFlags, uBufferLength, pExistingMem );
if (FAILED(hr)) { //
// Update error on this object appropriately.
//
IID iid; _pPropMgr->GetLastStatus( // ignore error return
0, &ulStatus, iid, NULL );
SetLastStatus(ulStatus); }
RRETURN(hr); }
STDMETHODIMP CLDAPUmiObject::GetProps( LPCWSTR *pszNames, ULONG uNameCount, ULONG uFlags, UMI_PROPERTY_VALUES **pProps ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->GetProps( pszNames, uNameCount, uFlags, pProps );
if (FAILED(hr)) { //
// Update error on this object appropriately.
//
IID iid; _pPropMgr->GetLastStatus( // ignore error return
0, &ulStatus, iid, NULL );
SetLastStatus(ulStatus); }
RRETURN(hr); }
STDMETHODIMP CLDAPUmiObject::PutProps( LPCWSTR *pszNames, ULONG uNameCount, ULONG uFlags, UMI_PROPERTY_VALUES *pProps ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->PutProps( pszNames, uNameCount, uFlags, pProps );
if (FAILED(hr)) { //
// Update error on this object appropriately.
//
IID iid; _pPropMgr->GetLastStatus( 0, &ulStatus, iid, NULL );
SetLastStatus(ulStatus); }
RRETURN(hr); }
HRESULT CLDAPUmiObject::PutFrom( LPCWSTR pszName, ULONG uFlags, ULONG uBufferLength, LPVOID pExistingMem ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->PutFrom( pszName, uFlags, uBufferLength, pExistingMem );
if (FAILED(hr)) { //
// Update error on this object appropriately.
//
IID iid;
_pPropMgr->GetLastStatus( 0, &ulStatus, iid, NULL );
SetLastStatus(ulStatus); }
RRETURN(hr); }
STDMETHODIMP CLDAPUmiObject::Delete( LPCWSTR pszName, ULONG uFlags ) { HRESULT hr = S_OK; ULONG ulStatus = 0;
SetLastStatus(0);
if (!_pPropMgr) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
hr = _pPropMgr->Delete( pszName, uFlags );
if (FAILED(hr)) { //
// Update error on this object appropriately.
//
IID iid; _pPropMgr->GetLastStatus( // ignore error return
0, &ulStatus, iid, NULL );
SetLastStatus(ulStatus); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::GetLastStatus --- IUmiBaseObject support.
//
// Synopsis: Returns status or error code from the last operation. Currently
// only numeric status is returned i.e, no error objects are
// returned. Implements IUmiBaseObject::GetLastStatus().
//
// Arguments: uFlags - Reserved. Must be 0 for now.
// puSpecificStatus - Returns status code.
// riid - IID requested. Ignored currently.
// pStatusObj - Returns interface requested.
// Always returns NULL currently.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *puSpecificStatus to return status code.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::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); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::GetInterfacePropList --- IUmiBaseObject method.
//
// Synopsis: Returns a pointer to the interface property list implementation
// for the connection object. Implements
// IUmiBaseObject::GetInterfacePropList().
//
// Arguments: uFlags - Reserved. Must be 0 for now.
// pPropList - Returns pointer to IUmiPropertyList interface
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *pPropList to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::GetInterfacePropList( ULONG uFlags, IUmiPropList **pPropList ) { HRESULT hr = S_OK;
if (uFlags) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
if (!pPropList) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
ADsAssert(_pIntfPropMgr);
//
// The refCounts are tricky here. When this operation is done,
// the ref on this object goes up by one, so you will need to
// releaserefs on the proplist in order to delete this object.
// This is to prevent the case of a proplist existing without
// the underlying object (ok for WinNT not for LDAP).
//
hr = _pIntfPropMgr->QueryInterface(IID_IUmiPropList, (void **) pPropList); error:
if (FAILED(hr)) { SetLastStatus(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::SetLastStatus --- Internal helper routine.
//
// Synopsis: Sets the status of the last operation. If the status is one
// of the pre-defined error codes, then the status is just set to
// 0 since we are not adding any value by returning the same
// status as the error code.
//
// Arguments: ulStatus - Status to be set
//
// Returns: N/A.
//
// Modifies: ulStatus member variable.
//
//----------------------------------------------------------------------------
void CLDAPUmiObject::SetLastStatus(ULONG ulStatus) { _ulErrorStatus = ulStatus;
return; }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::Open --- IUmiContainer support.
//
// Synopsis: Opens the object specified by a URL. URL may be native LDAP
// path or any UMI path.
//
// Arguments: pURL - Pointer to an IUmiURL interface
// uFlags - Reserved. Must be 0 for now.
// TargetIID - Interface requested.
// ppInterface - Returns pointer to interface requested.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::Open( IUmiURL *pURL, ULONG uFlags, REFIID TargetIID, LPVOID *ppInterface ) { HRESULT hr; LONG lGenus = UMI_GENUS_INSTANCE; LPWSTR pszDN = NULL, pszClass = NULL; IDispatch *pDispObj = NULL;
SetLastStatus(0); //
// Get the class name and the dn from the url.
//
if (!pURL || !ppInterface) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (uFlags != 0) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
//
// Helper will split the url txt to useful pieces.
//
hr = UrlToClassAndDn(pURL, &pszClass, &pszDN); BAIL_ON_FAILURE(hr);
//
// At this point if this is a class instance == schema class object,
// then if the dn is of the format name="something", we should just
// pass in "something" to the IADsContainer::Open call.
//
if (pszClass && *pszClass && !_wcsicmp(pszClass, L"Class")) { //
// Want to see if this is a class instance.
//
if (_pIntfPropMgr) { hr = _pIntfPropMgr->GetLongProperty(L"__GENUS", &lGenus); if (FAILED(hr)) { //
// We will assume that this is not a class in this case.
//
hr = S_OK; lGenus = UMI_GENUS_INSTANCE; } }
if (pszDN // should always be true
&& lGenus == UMI_GENUS_CLASS ) { if (!_wcsnicmp(pszDN, L"name=", 5)) { //
// Copy over the new name and replace pszDN with
// the new name.
//
LPWSTR pszReplace; pszReplace = AllocADsStr(pszDN + 5); if (!pszReplace) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
if (pszDN) { FreeADsStr(pszDN); } pszDN = pszReplace; } }
} //
// Call the IADSContaienr::GetObject to do the remaining work.
//
hr = _pIADsContainer->GetObject(pszClass, pszDN, &pDispObj); BAIL_ON_FAILURE(hr);
if (pszClass && *pszClass) { //
// We need to compare the name cause, the GetObject code cannot
// do that for umi calls.
//
hr = VerifyIfClassMatches( pszClass, pDispObj, lGenus ); BAIL_ON_FAILURE(hr); } hr = pDispObj->QueryInterface(TargetIID, ppInterface); BAIL_ON_FAILURE(hr);
error:
if (pDispObj) { pDispObj->Release(); }
if (pszClass) { FreeADsStr(pszClass); }
if (pszDN) { FreeADsStr(pszDN); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::Put --- IUmiContainer support.
//
// Synopsis: Commits an object into the container. Not implemented.
//
// Arguments: uFlags - Reserved. Must be 0 for now.
// TargetIID - IID of interface pointer requesed.
// pInterface - Output interface pointer.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::PutObject( ULONG uFlags, REFIID TargetIID, LPVOID pInterface ) { SetLastStatus(E_NOTIMPL);
RRETURN(E_NOTIMPL); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::DeleteObject --- IUmiContainer support.
//
// Synopsis: Deletes the object specified by the URL. This calls the
// underlying container object to do the delete after preparing
// the arguments suitably. Note that if no class name is specified
// we will pass in NULL to the IADsContainer::Delete call.
//
// Arguments: pURL - Pointer to URL of object to delete (relative).
// uFlags - Reserved. Must be 0 for now.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::DeleteObject( IUmiURL *pURL, ULONG uFlags ) { HRESULT hr; LPWSTR pszClass = NULL, pszDN = NULL;
if (!pURL) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (uFlags != 0) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); } hr = UrlToClassAndDn(pURL, &pszClass, &pszDN); BAIL_ON_FAILURE(hr);
//
// Call the IADsContainer::Delete entry point to do the work.
//
hr = _pIADsContainer->Delete(pszClass, pszDN);
error:
if (pszClass) { FreeADsStr(pszClass); } if (pszDN) { FreeADsStr(pszDN); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::Create --- IUmiContainer support.
//
// Synopsis: Creates the object specified by the URL. There always has
// to be a className for this operation to succeed. The newly
// created object is not yet on the directory, just local (need
// to call Commit to create it on the directory).
//
// Arguments: pURL - Pointer to URL of new object (relative).
// uFlags - Reserved. Must be 0 for now.
// ppNewObj - Return ptr for newly created object.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *pNewObject to return the IUmiObject interface
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::Create( IUmiURL *pURL, ULONG uFlags, IUmiObject **ppNewObj ) { HRESULT hr; LPWSTR pszClass = NULL, pszDN = NULL; IDispatch *pDispObj = NULL;
if (!pURL) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (uFlags != 0) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
hr = UrlToClassAndDn(pURL, &pszClass, &pszDN); BAIL_ON_FAILURE(hr);
hr = _pIADsContainer->Create(pszClass, pszDN, &pDispObj); BAIL_ON_FAILURE(hr);
hr = ((IUnknown *)pDispObj)->QueryInterface( IID_IUmiObject, (void **) ppNewObj );
error:
if (pDispObj) { pDispObj->Release(); }
if (pszClass) { FreeADsStr(pszClass); }
if (pszDN) { FreeADsStr(pszDN); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::Move --- IUmiContainer support.
//
// Synopsis: Moves a specified object into the container.
//
// Arguments: uFlags - Reserved. Must be 0 for now.
// pOldURL - URL of the object to be moved.
// pNewURL - New URL of the object within the container.
// If NULL, then no name change is needed.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::Move( ULONG uFlags, IUmiURL *pOldURL, IUmiURL *pNewURL ) { HRESULT hr; LPWSTR pszOldPath = NULL, pszNewPath = NULL, pszClass = NULL; ULONGLONG ullPathType = 0; IDispatch *pDispObj = NULL;
if (!_pIADsContainer) { BAIL_ON_FAILURE(hr = E_NOTIMPL); }
if (!pOldURL) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// What flags should we support here ?
//
if (uFlags) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
hr = UrlToLDAPPath( pOldURL, &pszOldPath ); BAIL_ON_FAILURE(hr);
if (pNewURL) { //
// Update code based on the path type.
//
hr = pNewURL->GetPathInfo(0, &ullPathType); BAIL_ON_FAILURE(hr);
if (ullPathType == UMIPATH_INFO_RELATIVE_PATH) { hr = UrlToClassAndDn( pNewURL, &pszClass, &pszNewPath ); BAIL_ON_FAILURE(hr); } else { //
// Does this even make sense on a move ???
//
hr = UrlToLDAPPath( pNewURL, &pszNewPath ); BAIL_ON_FAILURE(hr); } }
//
// At this point both the new and old path will be set correctly.
//
hr = _pIADsContainer->MoveHere( pszOldPath, pszNewPath, &pDispObj ); BAIL_ON_FAILURE(hr);
error: if (pszOldPath) { FreeADsStr(pszOldPath); }
if (pszNewPath) { FreeADsStr(pszNewPath); }
if (pszClass) { FreeADsStr(pszClass); }
if (pDispObj) { pDispObj->Release(); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::CreateEnum --- IUmiContainer support.
//
// Synopsis: Creates an enumerator within a container. The enumerator is
// an IUmiCursor interface pointer. The caller can optionally set
// a filter on the cursor and then enumerate the contents of the
// container. The actual enumeration of the container does
// not happen in this function. It is deferred to the point
// when the cursor is used to enumerate the results.
//
// Arguments: pszEnumContext - Not used. Must be NULL.
// uFlags - Reserved. Must be 0 for now.
// TargetIID - Interface requested on enum has to be
// IUmiCursor for now.
// ppInterface - Return value for new enurator.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return the IUmiCursor interface
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::CreateEnum( IUmiURL *pszEnumContext, ULONG uFlags, REFIID TargetIID, LPVOID *ppInterface ) { HRESULT hr;
SetLastStatus(0); //
// Validate args.
//
if (pszEnumContext || uFlags) { //
// We do not support contexts currently.
//
BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (!(TargetIID == IID_IUmiCursor)) { //
// Type of cursor we do not support.
//
BAIL_ON_FAILURE(hr = E_INVALIDARG); }
hr = CUmiCursor::CreateCursor( _pIADsContainer, TargetIID, ppInterface ); error:
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::ExecQuery --- IUmiContainer support.
//
// Synopsis: Executes a query on this container.
//
// Arguments: pQuery - Pointer to the query to execute.
// uFlags - Reserved. Must be 0 for now.
// TargetIID - Interface requested.
// ppInterface - Return value for the cursor requested.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::ExecQuery( IUmiQuery *pQuery, ULONG uFlags, REFIID TargetIID, LPVOID *ppResult ) { HRESULT hr = S_OK; CLDAPConObject *pConnection = NULL; BSTR bstrADsPath = NULL;
SetLastStatus(0);
if (!ppResult || !pQuery || !(TargetIID == IID_IUmiCursor) ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } *ppResult = NULL;
if (uFlags != 0) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
hr = this->_pIADs->get_ADsPath(&bstrADsPath); BAIL_ON_FAILURE(hr);
//
// We want to pre-process this query and verify that it is
// valid if this is a SQL/WQL style query. This is a little
// bit of double effort but provides a much easier usage
// paradigm.
//
hr = VerifyIfQueryIsValid(pQuery); BAIL_ON_FAILURE(hr);
hr = CLDAPConObject::CreateConnectionObject( &pConnection, this->_pLdapHandle ); BAIL_ON_FAILURE(hr);
hr = CUmiCursor::CreateCursor( pQuery, pConnection, (IUmiObject *) this, bstrADsPath, _pszLDAPServer, _pszLDAPDn, *_pCreds, _dwPort, TargetIID, ppResult );
BAIL_ON_FAILURE(hr);
error :
if (FAILED(hr)) { if (*ppResult) { ((IUnknown*)(*ppResult))->Release(); } SetLastStatus(hr); hr = MapHrToUmiError(hr); } if (bstrADsPath) { SysFreeString(bstrADsPath); }
if (pConnection) { pConnection->Release(); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CLDAPUmiObject::GetCLSIDForIID --- ICustomInterfaceFactory.
//
// Synopsis: Returns the CLSID corresponding to a given interface IID. If
// the interface is one of the interfaces implemented by the
// underlying LDAP object, then CLSID_LDAPObject is returned.
// If the IID is one of the interfaces implemented by an
// extension object, then the extension's CLSID is returned.
//
// Arguments: riid - Interface ID for which we want to find the CLSID.
// lFlags - Reserved. Must be 0.
// pCLSID - Returns the CLSID corresponding to the IID.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *pCLSID to return CLSID.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::GetCLSIDForIID( REFIID riid, long lFlags, CLSID *pCLSID ) { HRESULT hr = S_OK; IUnknown *pUnknown = NULL;
SetLastStatus(0);
if ( (lFlags) || (!pCLSID) ) { SetLastStatus(E_INVALIDARG); RRETURN(E_INVALIDARG); }
if (_pExtMgr) { //
// Check if there is any extension that supports this IID.
//
hr = _pExtMgr->GetCLSIDForIID( riid, lFlags, pCLSID );
if (SUCCEEDED(hr)) { RRETURN(S_OK); } }
//
// check if the underlying LDAP object supports this IID
//
hr = _pUnkInner->QueryInterface(riid, (void **) &pUnknown);
if (SUCCEEDED(hr)) { pUnknown->Release();
memcpy(pCLSID, &CLSID_LDAPObject, sizeof(GUID));
RRETURN(S_OK); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); } //+---------------------------------------------------------------------------
// Function: GetObjectByCLSID --- IUmiCustomInterfaceFactory support.
//
// Synopsis: Returns a pointer to a requested interface on the object
// specified by a CLSID. The object specified by the CLSID is
// aggregated by the specified outer unknown. The interface
// returned is a non-delegating interface on the object.
//
// Arguments: clsid - CLSID of object supporting requested interface.
// pUnkOuter - Aggregating outer unknown.
// dwClsContext - Context for running executable code.
// riid - Interface requested.
// lFlags - Reserved. Must be 0.
// ppInterface - Returns requested interface.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return requested interface
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::GetObjectByCLSID( CLSID clsid, IUnknown *pUnkOuter, DWORD dwClsContext, REFIID riid, long lFlags, void **ppInterface ) { HRESULT hr = S_OK; IUnknown *pCurOuterUnk = NULL;
SetLastStatus(0);
if ( (lFlags != 0) || (!pUnkOuter) || (!ppInterface) || (dwClsContext != CLSCTX_INPROC_SERVER) ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// ensure outer unknown specified is same as what is on the LDAP object
//
if (_fOuterUnkSet) { pCurOuterUnk = _pCoreObj->GetOuterUnknown();
if (pCurOuterUnk != pUnkOuter) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } }
//
// The interface requested has to be IUnknown if there is
// an outer uknown ptr.
//
if (!IsEqualIID(riid, IID_IUnknown)) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (!IsEqualCLSID(clsid, CLSID_LDAPObject)) { //
// has to be a CLSID of an extension object
//
if (_pExtMgr) {
hr = _pExtMgr->GetObjectByCLSID( clsid, pUnkOuter, riid, ppInterface ); BAIL_ON_FAILURE(hr);
//
// successfully got the interface
//
_pCoreObj->SetOuterUnknown(pUnkOuter); _fOuterUnkSet = TRUE;
RRETURN(S_OK); } else { BAIL_ON_FAILURE(hr = E_INVALIDARG); // bad CLSID
} }
//
// CLSID == CLSID_LDAPObject. This has to be an interface on the
// underlying LDAP object. Check if the LDAP object supports this IID.
//
hr = _pUnkInner->QueryInterface(riid, ppInterface);
if (SUCCEEDED(hr)) { //
// successfully got the interface
//
_pCoreObj->SetOuterUnknown(pUnkOuter); _fOuterUnkSet = TRUE;
RRETURN(S_OK); }
error:
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: GetCLSIDForNames --- ICustomInterfaceFactory support.
//
// Synopsis: Returns the CLSID of the object that supports a specified
// method/property. Also returns DISPIDs for the property/method.
//
// Arguments: rgszNames - Names to be mapped.
// cNames - Number of names to be mapped.
// lcid - Locale in which to interpret the names.
// rgDispId - Returns DISPID.
// lFlags - Reserved. Must be 0.
// pCLSID - Returns CLSID of object supporting this
// property/method.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *pCLSID to return the CLSID.
// *rgDispId to return the DISPIDs.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::GetCLSIDForNames( LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId, long lFlags, CLSID *pCLSID ) { HRESULT hr = S_OK; IDispatch *pDispatch = NULL;
SetLastStatus(0);
if ( (lFlags != 0) || (!pCLSID) ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (cNames == 0) { RRETURN(S_OK); }
if ( (!rgszNames) || (!rgDispId) ) { RRETURN(S_OK); }
if (_pExtMgr) { //
// check if there is any extension which supports this IID
//
hr = _pExtMgr->GetCLSIDForNames( rgszNames, cNames, lcid, rgDispId, lFlags, pCLSID ); if (SUCCEEDED(hr)) { //
// successfully got the CLSID and DISPIDs
//
RRETURN(S_OK); } }
//
// Check if the underlying LDAP object supports this name
//
hr = _pUnkInner->QueryInterface(IID_IDispatch, (void **) &pDispatch); if (FAILED(hr)) { BAIL_ON_FAILURE(hr = E_FAIL); }
hr = pDispatch->GetIDsOfNames( IID_NULL, rgszNames, cNames, lcid, rgDispId ); if (SUCCEEDED(hr)) { pDispatch->Release(); memcpy(pCLSID, &CLSID_LDAPObject, sizeof(GUID));
RRETURN(S_OK); }
error:
if (pDispatch) { pDispatch->Release(); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: GetOption --- IADsObjOptPrivate support.
//
// Synopsis: Private interface for internal use, this function is used to
// return the ldap handle if applicable.
//
// Arguments: dwOption - Option being read.
// pValue - Return pointer to hold value of option.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: pValue to return requested option.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::GetOption( DWORD dwOption, void *pValue ) { if (dwOption != LDP_CACHE_ENTRY) { RRETURN(E_FAIL); } else { *((PADSLDP *) pValue) = _pLdapHandle; RRETURN(S_OK); } }
//+---------------------------------------------------------------------------
// Function: SetOption --- IADsObjOptPrivate support.
//
// Synopsis: Private interface for internal use - NOTIMPL.
//
// Arguments: dwOption - Option being set
// pValue - Value of option being set.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: pValue to return requested option.
//
//----------------------------------------------------------------------------
STDMETHODIMP CLDAPUmiObject::SetOption( DWORD dwOption, void *pValue ) { RRETURN(E_NOTIMPL); }
//+---------------------------------------------------------------------------
// Function: CopyToHelper --- Helper routine protected scope.
//
// Synopsis: Copies the attributes on the source object over to the
// destination object.
//
// Arguments: pUmiObjSr --- Source object.
// pUmiObjDest --- Destination object to copy attributes to.
// uFlags --- Only 0 is supported currently.
// fMarkAsUpdate --- Flag indicating if we should mark the
// attributes on dest as update rather than 0.
// fCopyIntfProps --- Only false is supported currently.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: pUmiObjDest
//
//----------------------------------------------------------------------------
HRESULT CLDAPUmiObject::CopyToHelper( IUmiObject *pUmiSrcObj, IUmiObject *pUmiDestObj, ULONG uFlags, BOOL fMarkAsUpdate, // default is TRUE
BOOL fCopyIntfProps // default is FALSE
) { HRESULT hr = S_OK; ULONG ulLastError = S_OK; PUMI_PROPERTY_VALUES pUmiPropValsList = NULL; DWORD dwCount;
if (!pUmiSrcObj || !pUmiDestObj || uFlags) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// We need to get the list of properties from the src object.
//
hr = pUmiSrcObj->GetProps( NULL, 0, UMI_FLAG_GETPROPS_NAMES, &pUmiPropValsList ); BAIL_ON_FAILURE(hr);
for (dwCount = 0; dwCount < pUmiPropValsList->uCount; dwCount++) { //
// We need to walk the list, get each properties name and then
// for each property get its values from the source and put them
// on the destination.
//
LPWSTR pszTempStr = pUmiPropValsList->pPropArray[dwCount].pszPropertyName; PUMI_PROPERTY_VALUES pCurProp = NULL;
if (!pszTempStr) { //
// Name should never be NULL.
//
BAIL_ON_FAILURE(hr = E_FAIL); }
//
// We need to add a check for the SD cause we want to copy that over
// as a binary blob to prevent unnecessary traffic.
//
// Should change the get to use the force flag once it is done.
//
hr = pUmiSrcObj->Get( pszTempStr, 0, &pCurProp ); if (FAILED(hr)) { pUmiSrcObj->GetLastStatus(0, &ulLastError, IID_IUnknown, NULL); BAIL_ON_FAILURE(hr); }
hr = pUmiDestObj->Put( pszTempStr, 0x8000000, pCurProp );
//
// Irrespective of this operation success/failure we need to free
// the contents of pCurProp.
//
pUmiSrcObj->FreeMemory(0, (void *) pCurProp);
if (FAILED(hr)) { pUmiDestObj->GetLastStatus(0, &ulLastError, IID_IUnknown, NULL); BAIL_ON_FAILURE(hr); }
} // for each property in the source object.
error:
if (pUmiPropValsList) { pUmiSrcObj->FreeMemory(0, (void *) pUmiPropValsList); }
if (FAILED(hr)) { if (ulLastError) { SetLastStatus(ulLastError); } else { SetLastStatus(hr); }
hr = MapHrToUmiError(hr); } RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: VerifyifQueryIsValid --- Helper routine protected scope.
//
// Synopsis: Copies the attributes on the source object over to the
// destination object.
//
// Arguments: pUmiQeury --- Query object to validate.
//
// Returns: S_OK on success. Error code from parser otherwise.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT CLDAPUmiObject::VerifyIfQueryIsValid( IUmiQuery *pUmiQuery ) { HRESULT hr = S_OK; ULONG ulLangBufSize = 100 * sizeof(WCHAR); ULONG ulQueryBufSize = MAX_PATH * sizeof(WCHAR); WCHAR pszLangBuf[100]; WCHAR szQueryText[MAX_PATH]; LPWSTR pszQueryText = szQueryText; IWbemQuery *pQueryParser = NULL; ULONG ulFeatures[] = { WMIQ_LF1_BASIC_SELECT, WMIQ_LF2_CLASS_NAME_IN_QUERY, WMIQ_LF6_ORDER_BY, WMIQ_LF24_UMI_EXTENSIONS };
//
// We need to look at the query language if the language is SQL,
// then we need to go through and convert the SQL settings to
// properties on the intfPropList of the query.
//
hr = pUmiQuery->GetQuery( &ulLangBufSize, pszLangBuf, &ulQueryBufSize, pszQueryText );
if (hr == E_OUTOFMEMORY ) { //
// Means there was insufficient length in the buffers.
//
if (ulQueryBufSize > (MAX_PATH * sizeof(WCHAR))) { pszQueryText = (LPWSTR) AllocADsMem( ulQueryBufSize + sizeof(WCHAR) ); if (pszQueryText) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } }
hr = pUmiQuery->GetQuery( &ulLangBufSize, pszLangBuf, &ulQueryBufSize, pszQueryText ); } BAIL_ON_FAILURE(hr);
if (*pszLangBuf) { if (!_wcsicmp(L"SQL", pszLangBuf) || !_wcsicmp(L"WQL", pszLangBuf) ) { //
// Create the WBEM parser object and verify the query is valid.
//
hr = CoCreateInstance( CLSID_WbemQuery, NULL, CLSCTX_INPROC_SERVER, IID_IWbemQuery, (LPVOID *) &pQueryParser ); BAIL_ON_FAILURE(hr);
//
// Set the query into the parser and try and parse the query.
//
hr = pQueryParser->SetLanguageFeatures( 0, sizeof(ulFeatures)/sizeof(ULONG), ulFeatures ); BAIL_ON_FAILURE(hr);
hr = pQueryParser->Parse(L"SQL", pszQueryText, 0); BAIL_ON_FAILURE(hr); } // if the language is SQL
} // if the language has been set
else { //
// No language ???.
//
BAIL_ON_FAILURE(hr = E_INVALIDARG); }
error:
if (FAILED(hr)) { SetLastStatus(hr); //
// For now do not map error as we want error from parser
// until such time as new error codes are added to umi.
// hr = MapHrToUmiError(hr);
}
if (pQueryParser) { pQueryParser->Release(); }
if (pszQueryText && pszQueryText != szQueryText) { FreeADsMem(pszQueryText); }
return hr; }
//+---------------------------------------------------------------------------
// Function: VerifyIfClassMatches --- Helper routine protected scope.
//
// Synopsis: Makes sure the class name of the object matches the class
// asked for.
//
// Arguments: pszClass --- Class requested.
// pUnk --- Ptr to IUnk of Umi Object.
// lGenus --- Is the parent a schema object or not ?
//
// Returns: S_OK on success. Any failure error code or E_INVALIDARG.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT CLDAPUmiObject::VerifyIfClassMatches( LPWSTR pszClass, IUnknown * pUnk, LONG lGenus ) { HRESULT hr = S_OK; IUmiObject *pUmiObject = NULL; IUmiPropList *pPropList = NULL; UMI_PROPERTY_VALUES *pPropVals = NULL;
//
// For now the schema will always succeed cause we have no
// way to verify the parent class. We will fail the GetObject
// calls on the schema objects with bad paths.
//
if (lGenus == UMI_GENUS_CLASS) { RRETURN(hr); }
//
// Get hold of the IUmiObject and then the proplist from it.
//
hr = pUnk->QueryInterface( IID_IUmiObject, (void **) &pUmiObject ); BAIL_ON_FAILURE(hr);
hr = pUmiObject->GetInterfacePropList( 0, &pPropList ); BAIL_ON_FAILURE(hr);
hr = pPropList->Get(L"__CLASS", 0, &pPropVals); BAIL_ON_FAILURE(hr);
//
// Should have one value that we need to compare
//
if (!pPropVals || (pPropVals->uCount != 1) || !pPropVals->pPropArray || !pPropVals->pPropArray[0].pUmiValue || !pPropVals->pPropArray[0].pUmiValue->pszStrValue || !pPropVals->pPropArray[0].pUmiValue->pszStrValue[0] ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// Failure if the names do not match.
//
if (_wcsicmp( pPropVals->pPropArray[0].pUmiValue->pszStrValue[0], pszClass ) ) { hr = E_INVALIDARG; } error:
if (pUmiObject) { pUmiObject->Release(); }
if (pPropList) { pPropList->Release(); }
if (pPropVals) { FreeMemory(0, (void*)pPropVals); }
RRETURN(hr); }
|