|
|
//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: cumicurs.cxx
//
// Contents: Contains the UMI cursor object implementation
//
// History: 03-16-00 SivaramR Created.
//
//----------------------------------------------------------------------------
#include "winnt.hxx"
//----------------------------------------------------------------------------
// Function: CreateCursor
//
// Synopsis: Creates a cursor object. Called by IUmiContainer::CreateEnum().
//
// Arguments:
//
// pCredentials Credentials of the UMI object creating the cursor
// pCont Pointer to container on which CreateEnum was called
// iid Interface requested. Only interface supported is IUmiCursor.
// ppInterface Returns pointer to interface requested
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return a pointer to the interface requested
//
//----------------------------------------------------------------------------
HRESULT CUmiCursor::CreateCursor( CWinNTCredentials *pCredentials, IUnknown *pCont, REFIID iid, LPVOID *ppInterface ) { CUmiCursor *pCursor = NULL; HRESULT hr = S_OK;
ADsAssert(ppInterface != NULL); ADsAssert(pCont != NULL);
pCursor = new CUmiCursor(); if(NULL == pCursor) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
// initialize cursor object
hr = pCursor->FInit(pCont, pCredentials); BAIL_ON_FAILURE(hr);
hr = pCursor->QueryInterface(iid, ppInterface); BAIL_ON_FAILURE(hr);
pCursor->Release();
RRETURN(S_OK);
error:
if(pCursor != NULL) delete pCursor;
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: CUmiCursor
//
// Synopsis: Constructor. Initializes all member variables
//
// Arguments:
//
// None
//
// Returns: Nothing.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
CUmiCursor::CUmiCursor(void) { m_pIUmiPropList = NULL; m_ulErrorStatus = 0; m_pUnkInner = NULL; m_pIID = NULL; m_pEnumerator = NULL; }
//----------------------------------------------------------------------------
// Function: ~CUmiCursor
//
// Synopsis: Destructor. Frees member variables
//
// Arguments:
//
// None
//
// Returns: Nothing.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
CUmiCursor::~CUmiCursor(void) { if(m_pIUmiPropList != NULL) m_pIUmiPropList->Release();
if(m_pUnkInner != NULL) m_pUnkInner->Release();
if(m_pIID != NULL) FreeADsMem(m_pIID);
if(m_pEnumerator != NULL) m_pEnumerator->Release(); }
//----------------------------------------------------------------------------
// Function: FInit
//
// Synopsis: Initializes cursor object.
//
// Arguments:
//
// pCont Pointer to UMI container that created this cursor.
// pCredentials Credentials of UMI object creating the cursor
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
HRESULT CUmiCursor::FInit( IUnknown *pCont, CWinNTCredentials *pCredentials ) { HRESULT hr = S_OK; CUmiPropList *pPropList = NULL;
ADsAssert(pCont != NULL);
pPropList = new CUmiPropList(CursorClass, g_dwCursorTableSize); if(NULL == pPropList) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
hr = pPropList->FInit(NULL, NULL); BAIL_ON_FAILURE(hr);
hr = pPropList->QueryInterface( IID_IUmiPropList, (void **) &m_pIUmiPropList ); BAIL_ON_FAILURE(hr);
// DECLARE_STD_REFCOUNTING initializes the refcount to 1. Call Release()
// on the created object, so that releasing the interface pointer will
// free the object.
pPropList->Release();
m_pUnkInner = pCont; pCont->AddRef();
m_pCreds = pCredentials;
RRETURN(S_OK);
error:
if(m_pIUmiPropList != NULL) { m_pIUmiPropList->Release(); m_pIUmiPropList = NULL; }
if(pPropList != NULL) delete pPropList; RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: QueryInterface
//
// Synopsis: Queries cursor object for supported interfaces. Only
// IUmiCursor is supported.
//
// Arguments:
//
// iid interface requested
// ppInterface Returns pointer to interface requested. NULL if interface
// is not supported.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::QueryInterface( REFIID iid, LPVOID *ppInterface ) { if(NULL == ppInterface) RRETURN(E_INVALIDARG);
*ppInterface = NULL;
if(IsEqualIID(iid, IID_IUnknown)) *ppInterface = (IUmiCursor *) this; else if(IsEqualIID(iid, IID_IUmiCursor)) *ppInterface = (IUmiCursor *) this; else if(IsEqualIID(iid, IID_IUmiBaseObject)) *ppInterface = (IUmiBaseObject *) this; else if(IsEqualIID(iid, IID_IUmiPropList)) *ppInterface = (IUmiPropList *) this; else RRETURN(E_NOINTERFACE);
AddRef(); RRETURN(S_OK); }
//----------------------------------------------------------------------------
// Function: GetLastStatus
//
// 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: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *puSpecificStatus to return status code.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::GetLastStatus( ULONG uFlags, ULONG *puSpecificStatus, REFIID riid, LPVOID *pStatusObj ) { if(pStatusObj != NULL) *pStatusObj = NULL;
if(puSpecificStatus != NULL) *puSpecificStatus = 0;
if(uFlags != 0) RRETURN(UMI_E_INVALID_FLAGS);
if(NULL == puSpecificStatus) RRETURN(UMI_E_INVALIDARG);
*puSpecificStatus = m_ulErrorStatus;
RRETURN(UMI_S_NO_ERROR); }
//----------------------------------------------------------------------------
// Function: GetInterfacePropList
//
// 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: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pPropList to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::GetInterfacePropList( ULONG uFlags, IUmiPropList **pPropList ) { HRESULT hr = UMI_S_NO_ERROR;
SetLastStatus(0);
if(uFlags != 0) BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
if(NULL == pPropList) BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
ADsAssert(m_pIUmiPropList != NULL);
hr = m_pIUmiPropList->QueryInterface(IID_IUmiPropList, (void **)pPropList);
error:
if(FAILED(hr)) SetLastStatus(hr);
RRETURN(MapHrToUmiError(hr)); }
//----------------------------------------------------------------------------
// Function: SetLastStatus
//
// Synopsis: Sets the status of the last operation.
//
// Arguments:
//
// ulStatus Status to be set
//
// Returns: Nothing
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
void CUmiCursor::SetLastStatus(ULONG ulStatus) { m_ulErrorStatus = ulStatus;
return; }
//----------------------------------------------------------------------------
// Function: SetIID
//
// 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(NULL == m_pIID) { m_pIID = (IID *) AllocADsMem(sizeof(IID)); if(NULL == m_pIID) { SetLastStatus(UMI_E_OUT_OF_MEMORY); RRETURN(UMI_E_OUT_OF_MEMORY); } }
memcpy(m_pIID, &riid, sizeof(IID));
RRETURN(UMI_S_NO_ERROR); }
//----------------------------------------------------------------------------
// Function: Reset
//
// Synopsis: Resets the enumerator to start from the beginning
//
// Arguments:
//
// None
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::Reset(void) { HRESULT hr = UMI_S_NO_ERROR;
SetLastStatus(0);
// WinNT doesn't support Reset(). Keep the code below in case WinNT
// Reset() gets implemented in the future.
BAIL_ON_FAILURE(hr = UMI_E_NOTIMPL);
// it is possible that m_pEnumerator may be NULL here if the user
// called Reset before calling Next()
if(NULL == m_pEnumerator) RRETURN(UMI_S_NO_ERROR);
hr = m_pEnumerator->Reset(); BAIL_ON_FAILURE(hr);
RRETURN(UMI_S_NO_ERROR);
error:
SetLastStatus(hr); RRETURN(MapHrToUmiError(hr)); }
//----------------------------------------------------------------------------
// Function: GetFilter
//
// Synopsis: Gets the filter from the interface property cache. If the
// interface property was not set, an emty variant is returned.
//
// Arguments:
//
// pvFilter Returns variant containing the filter
//
// 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 != NULL);
VariantInit(pvFilter);
hr = m_pIUmiPropList->Get( TEXT(CURSOR_INTF_PROP_FILTER), 0, &pUmiProp );
if(UMI_E_PROPERTY_NOT_FOUND == hr) // interface property was not set. Return empty variant.
RRETURN(UMI_S_NO_ERROR);
// check if there was some other error on Get()
BAIL_ON_FAILURE(hr);
ADsAssert(UMI_TYPE_LPWSTR == pUmiProp->pPropArray->uType); ADsAssert(pUmiProp->pPropArray->pUmiValue != NULL);
ppszFilters = pUmiProp->pPropArray->pUmiValue->pszStrValue; dwNumFilters = pUmiProp->pPropArray->uCount;
hr = ADsBuildVarArrayStr(ppszFilters, dwNumFilters, pvFilter); BAIL_ON_FAILURE(hr);
error:
if(pUmiProp != NULL) m_pIUmiPropList->FreeMemory(0, pUmiProp); // ignore error return
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: Next
//
// Synopsis: Returns the next 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
//
// None
//
// 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 = UMI_S_NO_ERROR; VARIANT vFilter, *pvResults = NULL; ULONG ulIndex = 0, uNumReturned = 0, uNumResults = 0; IDispatch *pDisp = NULL; IUnknown **pUnkArr = NULL, *pTmpUnk = NULL; IADsContainer *pIADsContainer = NULL;
SetLastStatus(0);
if( (NULL == puNumReturned) || (NULL == ppObjects) ) BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
*puNumReturned = 0; *ppObjects = NULL;
VariantInit(&vFilter);
if(NULL == m_pEnumerator) { // first call to Next()
ADsAssert(m_pUnkInner != NULL);
hr = m_pUnkInner->QueryInterface( IID_IADsContainer, (void **) &pIADsContainer ); BAIL_ON_FAILURE(hr);
// check if the user set a filter on the cursor
hr = GetFilter(&vFilter); BAIL_ON_FAILURE(hr);
hr = pIADsContainer->put_Filter(vFilter); BAIL_ON_FAILURE(hr);
m_pCreds->SetUmiFlag();
hr = pIADsContainer->get__NewEnum((IUnknown **) &m_pEnumerator);
m_pCreds->ResetUmiFlag();
BAIL_ON_FAILURE(hr); }
// allocate memory for variants to return objects
pvResults = (VARIANT *) AllocADsMem(uNumRequested * sizeof(VARIANT)); if(NULL == pvResults) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
hr = m_pEnumerator->Next( uNumRequested, pvResults, &uNumReturned ); BAIL_ON_FAILURE(hr);
// allocate memory for array of interface pointers to return
pUnkArr = (IUnknown **) AllocADsMem(uNumReturned * sizeof(IUnknown *)); if(NULL == pUnkArr) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
// convert the V_DISPATCH variants to the requested interface properties
for(ulIndex = 0; ulIndex < uNumReturned; ulIndex++) {
pDisp = V_DISPATCH(&pvResults[ulIndex]); ADsAssert(pDisp != NULL);
if(m_pIID != NULL) hr = pDisp->QueryInterface(*m_pIID, (void **) &pTmpUnk); else hr = pDisp->QueryInterface(IID_IUmiObject, (void **) &pTmpUnk);
if(FAILED(hr)) continue;
pUnkArr[uNumResults] = pTmpUnk; uNumResults++; }
*puNumReturned = uNumResults; if(uNumResults > 0) *ppObjects = pUnkArr; else FreeADsMem(pUnkArr); error:
VariantClear(&vFilter);
if(pvResults != NULL) { for(ulIndex = 0; ulIndex < uNumReturned; ulIndex++) VariantClear(&pvResults[ulIndex]);
FreeADsMem(pvResults); }
if(pIADsContainer != NULL) pIADsContainer->Release(); if(FAILED(hr)) SetLastStatus(hr);
RRETURN(MapHrToUmiError(hr)); }
//----------------------------------------------------------------------------
// Function: Count
//
// Synopsis: Counts the number of results returned by the enumerator.
// Not implemented currently.
//
// Arguments:
//
// None
//
// Returns: UMI_E_NOTIMPL for now.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::Count( ULONG *puNumObjects ) { SetLastStatus(UMI_E_NOTIMPL);
RRETURN(UMI_E_NOTIMPL); }
//----------------------------------------------------------------------------
// Function: Previous
//
// Synopsis: Returnss the previous object returned by the enumerator.
// Not implemented currently.
//
// Arguments:
//
// None
//
// Returns: UMI_E_NOTIMPL for now.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
STDMETHODIMP CUmiCursor::Previous( ULONG uFlags, LPVOID *pObj ) { SetLastStatus(UMI_E_NOTIMPL);
RRETURN(UMI_E_NOTIMPL); }
|