644 lines
16 KiB
C++
644 lines
16 KiB
C++
//----------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|