|
|
//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: cumicurs.cxx
//
// Contents: Contains the UMI cursor object implementation. There are 2
// ways to use this object. One is to initialize with an
// IADsContainer pointer and the other is to use an IUmiQuery obj.
//
// History: 03-16-00 SivaramR Created (in WinNT)
// 03-28-00 AjayR modified for LDAP.
//
//----------------------------------------------------------------------------
#include "ldap.hxx"
//+---------------------------------------------------------------------------
// Function: CUmiCursor::CUmiCursor
//
// Synopsis: Constructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CUmiCursor::CUmiCursor(): _pPropMgr(NULL), _ulErrorStatus(0), _pIID(NULL), _pContainer(NULL), _pEnum(NULL), _pSearchHelper(NULL), _fQuery(FALSE) { }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::~CUmiCursor
//
// Synopsis: Destructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CUmiCursor::~CUmiCursor() { if (_pPropMgr) { delete _pPropMgr; }
if (_pContainer) { _pContainer->Release(); }
if (_pIID){ FreeADsMem(_pIID); }
if (_pEnum) { _pEnum->Release(); }
if (_pSearchHelper) { delete _pSearchHelper; } }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::CreateCursor (static constructor overloaded)
//
// Synopsis: Creats a UmiCursor object in the container mode.
//
// Arguments: *pCont - Pointer to container we are enumerating.
// iid - IID requested on returned object.
// ppInterface - Ptr to return value.
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: ppInterface to point to new cursor object.
//
//----------------------------------------------------------------------------
HRESULT CUmiCursor::CreateCursor( IUnknown *pCont, REFIID iid, LPVOID *ppInterface ) { CUmiCursor *pCursor = NULL; CPropertyManager *pPropMgr = NULL; IADsContainer *pContainer = NULL; HRESULT hr = S_OK;
ADsAssert(ppInterface); ADsAssert(pCont);
pCursor = new CUmiCursor(); if (!pCursor) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Initialize the various params on this object.
//
hr = CPropertyManager::CreatePropertyManager( (IUnknown *) pCursor, NULL, // IADs ptr
NULL, // pCreds
IntfPropsCursor, &pPropMgr ); BAIL_ON_FAILURE(hr);
hr = pCont->QueryInterface( IID_IADsContainer, (void **) &pContainer ); BAIL_ON_FAILURE(hr);
hr = pCursor->QueryInterface(iid, ppInterface); BAIL_ON_FAILURE(hr);
//
// Ref on this object is now 2, release the additional ref.
//
pCursor->Release();
pCursor->_pContainer = pContainer; pCursor->_pPropMgr = pPropMgr; pCursor->_pIID = NULL; pCursor->_ulErrorStatus = 0;
RRETURN(S_OK);
error:
if (pCursor) { delete pCursor; }
if (pPropMgr) { delete pPropMgr; }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::CreateCursor (static constructor overloaded).
//
// Synopsis: Creats a UmiCursor object in the query mode. Most of the
// params are needed for creating the search helper object.
//
// Arguments: pQuery - Query being executed.
// pConnection - Connection being used for query.
// pUnk - ???.
// pszADsPath - Path of object query is being executed on.
// pszLdapServer - Server of object being queried.
// pszLdapDn - Dn of the object being searched.
// cCredentials - Credentials to use for query.
// dwPort - Port being used for connection.
// iid - Cursor iid requested
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: ppInterface to point to new cursor object.
//
//----------------------------------------------------------------------------
HRESULT CUmiCursor::CreateCursor( IUmiQuery *pQuery, IUmiConnection *pConnection, IUnknown *pUnk, LPCWSTR pszADsPath, LPCWSTR pszLdapServer, LPCWSTR pszLdapDn, CCredentials cCredentials, DWORD dwPort, REFIID iid, LPVOID *ppInterface ) { CUmiCursor *pCursor = NULL; CPropertyManager *pPropMgr = NULL; HRESULT hr = S_OK; CUmiSearchHelper *pSearchHelper = NULL;
ADsAssert(ppInterface);
hr = CUmiSearchHelper::CreateSearchHelper( pQuery, pConnection, pUnk, pszADsPath, pszLdapServer, pszLdapDn, cCredentials, dwPort, &pSearchHelper ); BAIL_ON_FAILURE(hr);
pCursor = new CUmiCursor(); if (!pCursor) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Initialize the various params on this object.
//
hr = CPropertyManager::CreatePropertyManager( (IUnknown *) pCursor, NULL, // pIADs
NULL, // pCreds
IntfPropsCursor, &pPropMgr ); BAIL_ON_FAILURE(hr);
hr = pCursor->QueryInterface(iid, ppInterface); BAIL_ON_FAILURE(hr);
//
// Ref on this object is now 2, release the additional ref.
//
pCursor->Release();
pCursor->_pSearchHelper = pSearchHelper; pCursor->_pPropMgr = pPropMgr; pCursor->_pIID = NULL; pCursor->_ulErrorStatus = 0; pCursor->_fQuery = TRUE;
RRETURN(S_OK);
error:
if (pCursor) { delete pCursor; }
if (pSearchHelper) { delete pSearchHelper; }
if (pPropMgr) { delete pPropMgr; }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::QueryInterface (IUnknown interface).
//
// Synopsis: Standard QueryInterface function.
//
// Arguments: Self explanatory.
//
// Returns: S_OK on success or any suitable error code.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::QueryInterface( REFIID iid, LPVOID *ppInterface ) { if (!ppInterface) RRETURN(E_INVALIDARG);
if (IsEqualIID(iid, IID_IUnknown)) { *ppInterface = (IUmiCursor *) this; } else if (IsEqualIID(iid, IID_IUmiBaseObject)) { *ppInterface = (IUmiCursor *) this; } else if (IsEqualIID(iid, IID_IUmiPropList)) { *ppInterface = (IUmiCursor *) this; } else if (IsEqualIID(iid, IID_IUmiCursor)) { *ppInterface = (IUmiCursor *) this; } else { *ppInterface = NULL; RRETURN(E_NOINTERFACE); }
AddRef(); RRETURN(S_OK); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::GetLastStatus (IUmiBaseObject method).
//
// Synopsis: Returns only numeric status code from the last operation.
//
// Arguments: uFlags - Only 0 is supported for now.
// puSpecificStatus - Returns status/error code.
// riid - Not used.
// pStatusObj - NULL, not used currently.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *puSpecificStatus to return appropriate status code.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::GetLastStatus( ULONG uFlags, ULONG *puSpecificStatus, REFIID riid, LPVOID *pStatusObj ) { if (uFlags != 0) { RRETURN(UMI_E_INVALID_FLAGS); }
if (!puSpecificStatus) { RRETURN(E_INVALIDARG); }
if (pStatusObj) { //
// Should we error out ?
//
*pStatusObj = NULL; }
*puSpecificStatus = _ulErrorStatus;
RRETURN(UMI_S_NO_ERROR); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::GetInterfacePropList (IUmiBaseObject method).
//
// Synopsis: Returns a pointer to the interface property list for
// cursor object.
//
// Arguments: uFlags - Flags, only 0 is supported.
// ppPropList - Return value.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pPropList changed to IUmiPropList pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::GetInterfacePropList( ULONG uFlags, IUmiPropList **ppPropList ) { HRESULT hr = UMI_S_NO_ERROR;
SetLastStatus(0);
if (uFlags != 0) { RRETURN(UMI_E_INVALID_FLAGS); }
if (!ppPropList) { RRETURN(E_INVALIDARG); }
hr = _pPropMgr->QueryInterface(IID_IUmiPropList, (void **)ppPropList);
if (FAILED(hr)) { SetLastStatus(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::SetLastStatus (internal private 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: Nothing
//
// Modifies: Internal member status variable.
//
//----------------------------------------------------------------------------
void CUmiCursor::SetLastStatus(ULONG ulStatus) { this->_ulErrorStatus = ulStatus;
return; }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::SetIID (IUmiCursor method).
//
// Synopsis: Sets the interface to be requested off each item returned by
// the enumerator. Default is IID_IUmiObject.
//
// Arguments: riid - IID of interface to request.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::SetIID( REFIID riid ) { SetLastStatus(0);
if (_fQuery) { RRETURN(this->_pSearchHelper->SetIID(riid)); } else { if (!_pIID){ _pIID = (IID *) AllocADsMem(sizeof(IID)); if (!_pIID){ RRETURN(E_OUTOFMEMORY); } }
memcpy(_pIID, &riid, sizeof(IID)); }
RRETURN(UMI_S_NO_ERROR); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::Reset (IUmiCursor method).
//
// Synopsis: Resets the enumerator to restart from begining (this is for
// likely to return an error for the IADsContainer case).
//
// Arguments: N/A.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::Reset(void) { HRESULT hr = E_NOTIMPL; RRETURN(hr);
//
// Rest of the code can be invoked when we have proper support.
//
SetLastStatus(0);
if (!_fQuery) { //
// it is possible that _pEnum may be NULL here if the user
// called Reset before calling Next()
//
if (!_pEnum) { RRETURN(UMI_S_NO_ERROR); } hr = _pEnum->Reset(); BAIL_ON_FAILURE(hr);
hr = S_OK; } else { hr = _pSearchHelper->Reset(); }
error:
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); } RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::GetFilter (internal private helper routine).
//
// Synopsis: Gets the filter from the interface property cache. If the
// interface property was not set, an emty variant is returned.
//
// Arguments: pvFilter - ptr to variant for return value.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pvFilter to return the filter.
//
//----------------------------------------------------------------------------
HRESULT CUmiCursor::GetFilter(VARIANT *pvFilter) { HRESULT hr = UMI_S_NO_ERROR; UMI_PROPERTY_VALUES *pUmiProp = NULL; LPWSTR *ppszFilters = NULL; DWORD dwNumFilters = 0;
ADsAssert(pvFilter);
VariantInit(pvFilter);
hr = _pPropMgr->Get( L"__FILTER", 0, &pUmiProp );
if (hr == UMI_E_NOT_FOUND) { //
// interface property was not set. Return empty variant.
//
RRETURN(hr); }
BAIL_ON_FAILURE(hr);
ADsAssert(pUmiProp->pPropArray->uType == UMI_TYPE_LPWSTR); //
// Make sure we have data back and that it is not just NULL.
// We will not get back a NULL string but instead an array with
// one element that is NULL. That is as good as no filter.
//
if (pUmiProp->pPropArray->uCount && pUmiProp->pPropArray->pUmiValue && pUmiProp->pPropArray->pUmiValue->pszStrValue[0] ) { //
// Valid filter is present.
//
ppszFilters = pUmiProp->pPropArray->pUmiValue->pszStrValue; dwNumFilters = pUmiProp->pPropArray->uCount;
hr = ADsBuildVarArrayStr(ppszFilters, dwNumFilters, pvFilter); BAIL_ON_FAILURE(hr); } else { hr = UMI_E_NOT_FOUND; }
error:
if (pUmiProp) { _pPropMgr->FreeMemory(0, pUmiProp); } RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CUmiCursor::Next (IUmiCursor method).
//
// Synopsis: Returns the next "n" item(s) in the enumeration sequence.
//
// Arguments: uNumRequested - Number of items requested.
// pNumReturned - Returns actual number of objects returned.
// ppObjects - Array of interface pointers of size
// *pNumReturned.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pNumReturned to return the number of objects returned
// *ppObjects to return the interface pointers
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::Next( ULONG uNumRequested, ULONG *puNumReturned, LPVOID *ppObjects ) { HRESULT hr = S_OK;; VARIANT vFilter, *pvResults = NULL; ULONG ulIndex = 0, uNumReturned = 0, uNumResults = 0; IDispatch *pDisp = NULL; IUnknown **pUnkArr = NULL, *pTmpUnk = NULL; VARIANT vOldFilter; BOOL fReplaceFilter = FALSE;
SetLastStatus(0); VariantInit(&vOldFilter);
if ( (!puNumReturned) || (!ppObjects) ){ RRETURN(E_INVALIDARG); }
*puNumReturned = 0; *ppObjects = NULL;
//
// If this is a query then we need to get the results from the
// query object.
//
if (_fQuery) { hr = _pSearchHelper->Next( uNumRequested, puNumReturned, ppObjects ); //
// MapHrToUmiError
//
RRETURN(hr); }
//
// If we get here this is a container enumerate.
//
VariantInit(&vFilter);
if (!_pEnum) { //
// first call to Next()
//
ADsAssert(_pContainer);
//
// check if the user set a filter on the cursor
//
hr = GetFilter(&vFilter); if (SUCCEEDED(hr)) { //
// We need to get the old filter to restore it.
//
hr = _pContainer->get_Filter(&vOldFilter); if (SUCCEEDED(hr)) { fReplaceFilter = TRUE; } //
// We have a valid filter that we need to set.
//
hr = _pContainer->put_Filter(vFilter); } else if (hr == UMI_E_NOT_FOUND) { //
// Reset error as this one is expected, anything else we bail.
//
hr = S_OK; } //
// Catch either GetFilter failure or put_Filter failure.
//
BAIL_ON_FAILURE(hr); hr = _pContainer->get__NewEnum((IUnknown **) &_pEnum); //
// Restore old filter irrespective of ECODE.
//
if (fReplaceFilter) { _pContainer->put_Filter(vOldFilter); } BAIL_ON_FAILURE(hr); }
//
// allocate memory for variants to return objects
//
pvResults = (VARIANT *) AllocADsMem(uNumRequested * sizeof(VARIANT)); if (!pvResults) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
hr = _pEnum->Next( uNumRequested, pvResults, &uNumReturned ); BAIL_ON_FAILURE(hr);
if (!uNumReturned) { //
// This will handle the S_FALSE case.
//
goto error; }
//
// allocate memory for array of interface pointers to return
//
pUnkArr = (IUnknown **) AllocADsMem(uNumReturned * sizeof(IUnknown *)); if (!pUnkArr) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// convert the V_DISPATCH variants to the requested interface properties
//
for(ulIndex = 0; ulIndex < uNumReturned; ulIndex++) {
pDisp = V_DISPATCH(&pvResults[ulIndex]);
if (_pIID) { hr = pDisp->QueryInterface(*_pIID, (void **) &pTmpUnk); } else { hr = pDisp->QueryInterface(IID_IUmiObject, (void **) &pTmpUnk); }
//
// Is this really correct ?
//
if (FAILED(hr)) { continue; }
pUnkArr[uNumResults] = pTmpUnk; uNumResults++; }
*puNumReturned = uNumResults;
if (uNumResults > 0) { *ppObjects = pUnkArr; } else { FreeADsMem(pUnkArr); } error:
VariantClear(&vFilter); VariantClear(&vOldFilter);
if (pvResults) { for(ulIndex = 0; ulIndex < uNumReturned; ulIndex++) { VariantClear(&pvResults[ulIndex]); }
FreeADsMem(pvResults); } if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: Count
//
// Synopsis: Counts the number of results returned by the enumerator.
// Not implemented currently.
//
// Arguments:
//
// None
//
// Returns: E_NOTIMPL for now.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::Count( ULONG *puNumObjects ) { SetLastStatus(0);
RRETURN(E_NOTIMPL); }
//+---------------------------------------------------------------------------
// Function: Previous
//
// Synopsis: Returnss the previous object returned by the enumerator.
// Not implemented currently.
//
// Arguments:
//
// None
//
// Returns: E_NOTIMPL for now.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::Previous( ULONG uFlags, LPVOID *pObj ) { SetLastStatus(0);
RRETURN(E_NOTIMPL); }
|