|
|
//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: cumiprop.cxx
//
// Contents: Contains the property list implementation for UMI. This will
// be used for both interface properties and object properties.
//
// History: 02-28-00 SivaramR Created.
//
//----------------------------------------------------------------------------
#include "winnt.hxx"
//----------------------------------------------------------------------------
// Function: CUmiPropList
//
// Synopsis: Constructor. Stores off schema (list of available properties,
// their types etc.) and the size of the schema.
//
// Arguments: Self explanatory
//
// Returns: Nothing
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
CUmiPropList::CUmiPropList(PPROPERTYINFO pSchema, DWORD dwSchemaSize) { m_pSchema = pSchema; m_dwSchemaSize = dwSchemaSize; m_pPropCache = NULL; m_fIsIntfPropObj = TRUE; m_ulErrorStatus = 0; m_pszSchema = NULL; m_pClassInfo = NULL; m_fIsNamespaceObj = FALSE; m_fIsClassObj = FALSE; m_fDisableWrites = FALSE; m_ppszUnImpl = NULL; }
//----------------------------------------------------------------------------
// Function: CUmiPropList
//
// Synopsis: Constructor. Stores off schema (list of available properties,
// their types etc.) and the size of the schema.
//
// Arguments: Self explanatory
//
// Returns: Nothing
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
CUmiPropList::~CUmiPropList(void) { if( (m_pPropCache != NULL) && (TRUE == m_fIsIntfPropObj) ) delete m_pPropCache;
if(m_pszSchema != NULL) FreeADsStr(m_pszSchema);
return; }
//----------------------------------------------------------------------------
// Function: QueryInterface
//
// Synopsis: Queries property list object for supported interfaces. Only
// IUmiPropList 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
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::QueryInterface( REFIID iid, LPVOID *ppInterface ) { if(NULL == ppInterface) RRETURN(E_INVALIDARG);
*ppInterface = NULL;
if(IsEqualIID(iid, IID_IUnknown)) *ppInterface = (IUmiPropList *) this; else if(IsEqualIID(iid, IID_IUmiPropList)) *ppInterface = (IUmiPropList *) this; else RRETURN(E_NOINTERFACE);
AddRef(); RRETURN(S_OK); }
//----------------------------------------------------------------------------
// Function: FInit
//
// Synopsis: Initializes the property list object.
//
// Arguments:
//
// pPropCache Pointer to the property cache object. This argument will be
// NULL if this object is for interface properties. In this case,
// a new property cache is allocated by this function. If this
// object is for object properties, then this argument points
// to the property cache of the WinNT object.
// ppszUnImpl Array of standard property names that are not implemented.
// This is used on an interface property object to return E_NOTIMPL
// as the error code.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::FInit(CPropertyCache *pPropCache, LPWSTR *ppszUnImpl) { HRESULT hr = UMI_S_NO_ERROR;
if(NULL == pPropCache) { hr = CPropertyCache::createpropertycache( m_pSchema, m_dwSchemaSize, NULL, // this will ensure that the WinNT property cache
// won't do implicit GetInfo for interface properties
&m_pPropCache);
BAIL_ON_FAILURE(hr);
m_ppszUnImpl = ppszUnImpl; } else { m_fIsIntfPropObj = FALSE; m_pPropCache = pPropCache; } RRETURN(UMI_S_NO_ERROR);
error:
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: SetLastStatus
//
// Synopsis: Sets the status of the last operation.
//
// Arguments:
//
// ulStatus Status to be set
//
// Returns: Nothing
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
void CUmiPropList::SetLastStatus(ULONG ulStatus) { m_ulErrorStatus = ulStatus;
return; }
//----------------------------------------------------------------------------
// 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.
//
// 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.
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::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: Put
//
// Synopsis: Implements IUmiPropList::Put. Writes a property into the cache.
//
// Arguments:
//
// pszName Name of the property
// uFlags Flags for the Put operation. Unused currently.
// pProp Pointer to the structure containing the value
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: Nothing.
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::Put( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES *pProp ) { HRESULT hr = UMI_S_NO_ERROR; DWORD dwSyntaxId = 0, dwIndex = 0; UMI_PROPERTY *pPropArray = NULL; LPNTOBJECT pNtObject = NULL; BOOL fMarkAsClean = FALSE;
SetLastStatus(0);
// fail if we have disabled writes
if( (TRUE == m_fDisableWrites) && (TRUE == m_fIsIntfPropObj) ) BAIL_ON_FAILURE(hr = UMI_E_READ_ONLY);
// check args
hr = ValidatePutArgs( pszName, uFlags, pProp ); BAIL_ON_FAILURE(hr);
// is this a standard interface property that's not implemented?
if(m_ppszUnImpl != NULL) { while(m_ppszUnImpl[dwIndex] != NULL) { if(0 == _wcsicmp(m_ppszUnImpl[dwIndex], pszName)) { BAIL_ON_FAILURE(hr = UMI_E_NOTIMPL); } dwIndex++; } }
// check if the property is in the schema
hr = ValidatePropertyinSchemaClass( m_pSchema, m_dwSchemaSize, (LPWSTR) pszName, &dwSyntaxId ); BAIL_ON_FAILURE(hr); // check if the property is writeable. Do this only if the flags are not
// set to UMI_INTERNAL_FLAG_MARK_AS_CLEAN. Otherwise, the call is from
// Clone() and we want read-only attributes to be succesfully copied
// into the cloned object's cache. This requires that the check below
// for writeable properties should be skipped.
if(uFlags != UMI_INTERNAL_FLAG_MARK_AS_CLEAN) { hr = ValidateIfWriteableProperty( m_pSchema, m_dwSchemaSize, (LPWSTR) pszName ); BAIL_ON_FAILURE(hr); }
pPropArray = pProp->pPropArray;
// convert UMI data into format that can be stored in the cache
hr = UmiToWinNTType( dwSyntaxId, pPropArray, &pNtObject ); BAIL_ON_FAILURE(hr);
// Find the property in the cache. If it doesn't exist, add it.
hr = m_pPropCache->findproperty((LPWSTR) pszName, &dwIndex); if(FAILED(hr)) { hr = m_pPropCache->addproperty( (LPWSTR) pszName, dwSyntaxId, pPropArray->uCount, pNtObject ); BAIL_ON_FAILURE(hr); }
if(UMI_INTERNAL_FLAG_MARK_AS_CLEAN == uFlags) fMarkAsClean = TRUE;
// Update property in cache
hr = m_pPropCache->putproperty( (LPWSTR) pszName, dwSyntaxId, pPropArray->uCount, pNtObject, fMarkAsClean ); BAIL_ON_FAILURE(hr);
error:
if(pNtObject) NTTypeFreeNTObjects(pNtObject, pPropArray->uCount);
if(FAILED(hr)) SetLastStatus(hr);
RRETURN(MapHrToUmiError(hr)); } //----------------------------------------------------------------------------
// Function: ValidatePutArgs
//
// Synopsis: Checks if the arguments to Put() are well-formed.
//
// Arguments:
//
// pszName Name of the property
// uFlags Flags for the Put operation. Unused currently.
// pProp Pointer to the structure containing the value
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::ValidatePutArgs( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES *pProp ) { UMI_PROPERTY *pPropArray = NULL;
if( (NULL == pszName) || (NULL == pProp) ) RRETURN(UMI_E_INVALIDARG);
if( (uFlags != 0) && (uFlags != UMI_INTERNAL_FLAG_MARK_AS_CLEAN) ) RRETURN(UMI_E_INVALID_FLAGS);
if(pProp->uCount != 1) // cannot update multiple properties using Put()
RRETURN(UMI_E_INVALIDARG);
pPropArray = pProp->pPropArray; if(NULL == pPropArray) RRETURN(UMI_E_INVALIDARG);
// WinNT provider supports only property update. Cannot append, clear etc.
if(pPropArray->uOperationType != UMI_OPERATION_UPDATE) RRETURN(UMI_E_UNSUPPORTED_OPERATION);
if(pPropArray->pszPropertyName && _wcsicmp(pPropArray->pszPropertyName, pszName)) RRETURN(UMI_E_INVALID_PROPERTY);
if(NULL == pPropArray->pUmiValue) RRETURN(UMI_E_INVALIDARG);
// all is well
RRETURN(UMI_S_NO_ERROR); }
//----------------------------------------------------------------------------
// Function: Get
//
// Synopsis: Implements IUmiPropList::Get. Reads a property from the cache.
// Since the WinNT provider does not support incremental updates
// using PutEx, Get() will never return
// UMI_E_SYNCHRONIZATION_REQUIRED. If a property is modified in
// cache, Get() returns the modified value from the cache, without
// any error.
//
// Arguments:
//
// pszName Name of the property
// uFlags Flags for the Get operation. Unused currently.
// ppProp Returns pointer to the structure containing the value
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *ppProp to return the address of UMI_PROPERT_VALUES structure.
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::Get( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES **ppProp ) { RRETURN( GetHelper( pszName, uFlags, ppProp, UMI_TYPE_NULL, // no-op
FALSE // not an internal call to GetHelper()
)); }
//----------------------------------------------------------------------------
// Function: GetAs
//
// Synopsis: Implements IUmiPropList::GetAs. Reads a property from the cache.
// The data is converted to the type requested by the caller.
// Since the WinNT provider does not support incremental updates
// using PutEx, GetAs() will never return
// UMI_E_SYNCHRONIZATION_REQUIRED. If a property is modified in
// cache, GetAs() returns the modified value from the cache, without
// any error. This method is not supported for interface properties.
//
// Update: This method will not be supported on WinNT provider.
//
// Arguments:
//
// pszName Name of the property
// uFlags Flags for the GetAs operation. Unused currently.
// uCoercionType UMI type to convert the data to.
// ppProp Returns pointer to the structure containing the value
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *ppProp to return the address of UMI_PROPERT_VALUES structure.
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetAs( LPCWSTR pszName, ULONG uFlags, ULONG uCoercionType, UMI_PROPERTY_VALUES **ppProp ) { SetLastStatus(UMI_E_NOTIMPL); RRETURN(UMI_E_NOTIMPL);
SetLastStatus(0);
if(TRUE == m_fIsIntfPropObj) // GetAs is only supported for object properties
RRETURN(UMI_E_UNSUPPORTED_OPERATION);
RRETURN( GetHelper( pszName, uFlags, ppProp, (UMI_TYPE) uCoercionType, FALSE, // not an internal call to GetHelper()
TRUE )); }
//----------------------------------------------------------------------------
// Function: GetHelper
//
// Synopsis: Implements a helper function for Get() and GetAs().
// Since the WinNT provider does not support incremental updates
// using PutEx, Get()/GetAs() will never return
// UMI_E_SYNCHRONIZATION_REQUIRED. If a property is modified in
// cache, Get()/GetAs() returns the modified value from the cache,
// wthout any error.
//
// Arguments:
//
// pszName Name of the property
// uFlags Flags for the Get operation.
// ppProp Returns pointer to the structure containing the value
// UmiDstType UMI type to convert the NT value to. Used only by GetAs()
// fInternal Flag to indicate if the call is through Get()/GetAs() or if it
// is an internal call to this function from UMI. Difference is
// that internal calls can read passwords from the cache.
// fIsGetAs Flag to indicate if the caller is GetAs (in which case
// UmiType is used). FALSE by default.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *ppProp to return the address of UMI_PROPERT_VALUES structure.
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetHelper( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES **ppProp, UMI_TYPE UmiDstType, BOOL fInternal, BOOL fIsGetAs ) { HRESULT hr = UMI_S_NO_ERROR; DWORD dwSyntaxId = 0, dwNumValues = 0, dwIndex = 0; LPNTOBJECT pNtObject = NULL; UMI_TYPE UmiType = UMI_TYPE_NULL; UMI_PROPERTY_VALUES *pProp = NULL; BOOL fModified = FALSE;
SetLastStatus(0);
hr = ValidateGetArgs( pszName, uFlags, ppProp ); BAIL_ON_FAILURE(hr);
if(UMI_FLAG_PROPERTY_ORIGIN == uFlags) { hr = GetPropertyOrigin(pszName, ppProp); if(FAILED(hr)) goto error; else RRETURN(UMI_S_NO_ERROR); }
// is this a standard interface property that's not implemented?
if(m_ppszUnImpl != NULL) { while(m_ppszUnImpl[dwIndex] != NULL) { if(0 == _wcsicmp(m_ppszUnImpl[dwIndex], pszName)) { BAIL_ON_FAILURE(hr = UMI_E_NOTIMPL); } dwIndex++; } }
*ppProp = NULL;
// __SCHEMA should return a IUmiObject pointer. This property is treated as
// a special case since it is not actually retrieved from the property
// cache. This property will be requested only on an interface property
// object.
if( (TRUE == m_fIsIntfPropObj) && (0 == _wcsicmp((LPWSTR) pszName, TEXT(UMIOBJ_INTF_PROP_SCHEMA))) ) { hr = GetSchemaObject((LPWSTR) pszName, ppProp); BAIL_ON_FAILURE(hr);
RRETURN(hr); }
// make sure that passwords cannot be read by a user
if( (TRUE == m_fIsIntfPropObj) && (FALSE == fInternal) && (0 == _wcsicmp((LPWSTR) pszName, TEXT(CONN_INTF_PROP_PASSWORD))) ) BAIL_ON_FAILURE(hr = UMI_E_FAIL);
// retrieve property from cache. This might result in an implicit GetInfo()
// if this is for object properties. For, interface properties, there is
// no implicit GetInfo().
hr = m_pPropCache->getproperty( (LPWSTR) pszName, &dwSyntaxId, &dwNumValues, &pNtObject, &fModified );
BAIL_ON_FAILURE(hr);
// map the NT type to a UMI type
if(dwSyntaxId >= g_dwNumNTTypes) BAIL_ON_FAILURE(hr = UMI_E_FAIL); // shouldn't happen
if(FALSE == fIsGetAs) // get the UMI type corresponding to this NT type
UmiType = g_mapNTTypeToUmiType[dwSyntaxId]; else // try to convert to the type specified by the caller
UmiType = UmiDstType;
// allocate structure to return values
pProp = (UMI_PROPERTY_VALUES *) AllocADsMem(sizeof(UMI_PROPERTY_VALUES)); if(NULL == pProp) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(pProp, 0, sizeof(UMI_PROPERTY_VALUES));
pProp->pPropArray = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY)); if(NULL == pProp->pPropArray) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(pProp->pPropArray, 0, sizeof(UMI_PROPERTY));
hr = WinNTTypeToUmi( pNtObject, dwNumValues, pProp->pPropArray, NULL, // provider should allocate memory
0, UmiType ); BAIL_ON_FAILURE(hr);
// Get fetches only one property at a time
pProp->uCount = 1;
// Fill in remaining fields of UMI_PROPERTY
if(TRUE == fModified) { // WinNT only allows updates
if( (uFlags != UMI_FLAG_PROVIDER_CACHE) && (FALSE == m_fIsIntfPropObj) ) { // need to return error since cache is dirty
FreeMemory(0, pProp); // ignore error return
pProp = NULL; BAIL_ON_FAILURE(hr = UMI_E_SYNCHRONIZATION_REQUIRED); }
pProp->pPropArray->uOperationType = UMI_OPERATION_UPDATE; } else pProp->pPropArray->uOperationType = 0;
// not critical if this memory allocation fails. Property name doesn't
// have to be returned to the caller.
pProp->pPropArray->pszPropertyName = AllocADsStr(pszName); *ppProp = pProp; error:
if(pNtObject) NTTypeFreeNTObjects(pNtObject, dwNumValues);
if(FAILED(hr)) { if(pProp != NULL) { if(pProp->pPropArray != NULL) FreeADsMem(pProp->pPropArray);
FreeADsMem(pProp); }
SetLastStatus(hr); }
RRETURN(MapHrToUmiError(hr)); }
//----------------------------------------------------------------------------
// Function: ValidateGetArgs
//
// Synopsis: Checks if the arguments to Get() are well-formed.
//
// Arguments:
//
// pszName Name of the property
// uFlags Flags for the Put operation.
// ppProp Returns pointer to the structure containing the value
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::ValidateGetArgs( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES **ppProp ) { if( (NULL == pszName) || (NULL == ppProp) ) RRETURN(UMI_E_INVALIDARG);
// cannot combine UMI_FLAG_PROVIDER_CACHE and UMI_FLAG_PROPERTY_ORIGIN
// since they are on the object property list and interface property list
// respectively. So, don't need to AND with bitmasks to see if those flags
// are set.
if( (uFlags != 0) && (uFlags != UMI_FLAG_PROVIDER_CACHE) && (uFlags != UMI_FLAG_PROPERTY_ORIGIN) ) RRETURN(UMI_E_INVALID_FLAGS);
if( (UMI_FLAG_PROVIDER_CACHE == uFlags) && (TRUE == m_fIsIntfPropObj) ) RRETURN(UMI_E_INVALID_FLAGS);
if(UMI_FLAG_PROPERTY_ORIGIN == uFlags) { // can set this flag only on the interface property object of a class
// object.
if( (FALSE == m_fIsIntfPropObj) || (NULL == m_pClassInfo) ) RRETURN(UMI_E_INVALID_FLAGS); }
// all is well
RRETURN(UMI_S_NO_ERROR); }
//----------------------------------------------------------------------------
// Function: FreeMemory
//
// Synopsis: Implements IUmiPropList::FreeMemory. Frees a UMI_PROPERTY_VALUES
// structure previously returned to the user.
//
// Arguments:
//
// uReserved Unused currently.
// pMem Pointer to UMI_PROPERTY_VALUES structure to be freed.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::FreeMemory( ULONG uReserved, LPVOID pMem ) { UMI_PROPERTY_VALUES *pUmiPropVal = NULL; UMI_PROPERTY *pPropArray = NULL; ULONG i; LPWSTR *pStrArray = NULL; UMI_OCTET_STRING *pOctetStrArray = NULL; PUMI_COM_OBJECT pUmiComObj = NULL;
SetLastStatus(0);
if( (NULL == pMem) || (uReserved != 0) ) { SetLastStatus(UMI_E_INVALIDARG); RRETURN(UMI_E_INVALIDARG); }
// enclose in try/except to handle bad pointers sent in by caller
__try { pUmiPropVal = (UMI_PROPERTY_VALUES *) pMem;
for(i = 0; i < pUmiPropVal->uCount; i++) { pPropArray = pUmiPropVal->pPropArray + i;
if(NULL == pPropArray) RRETURN(UMI_E_INVALID_POINTER);
// GetProps returns a UMI_PROPERTY structure with just the
// property name filled in and all other fields 0, when asked
// for only property names.
if(pPropArray->pszPropertyName != NULL) { FreeADsStr(pPropArray->pszPropertyName); pPropArray->pszPropertyName = NULL; }
if(0 == pPropArray->uCount) continue;
if(NULL == pPropArray->pUmiValue) RRETURN(UMI_E_INVALID_POINTER); // Free individual string values
if(UMI_TYPE_LPWSTR == pPropArray->uType) { pStrArray = pPropArray->pUmiValue->pszStrValue; for(i = 0; i < pPropArray->uCount; i++) { if(pStrArray[i] != NULL) { FreeADsStr(pStrArray[i]); pStrArray[i] = NULL; } } } else if(UMI_TYPE_OCTETSTRING == pPropArray->uType) { pOctetStrArray = pPropArray->pUmiValue->octetStr; for(i = 0; i < pPropArray->uCount; i++) { if(pOctetStrArray[i].lpValue != NULL) { FreeADsMem(pOctetStrArray[i].lpValue); pOctetStrArray[i].lpValue = NULL; } } } else if(UMI_TYPE_IUNKNOWN == pPropArray->uType) { pUmiComObj = pPropArray->pUmiValue->comObject; for(i = 0; i < pPropArray->uCount; i++) { if(pUmiComObj[i].priid != NULL) { FreeADsMem(pUmiComObj[i].priid); pUmiComObj[i].priid = NULL; } if(pUmiComObj[i].pInterface != NULL){ ((IUnknown *) pUmiComObj[i].pInterface)->Release(); pUmiComObj[i].pInterface = NULL; } } }
// Now free the UMI_VALUE structure
FreeADsMem(pPropArray->pUmiValue); pPropArray->pUmiValue = NULL; } // for
if(pUmiPropVal->pPropArray != NULL) FreeADsMem(pUmiPropVal->pPropArray); pUmiPropVal->pPropArray = NULL;
FreeADsMem(pUmiPropVal);
} __except( EXCEPTION_EXECUTE_HANDLER )
{ SetLastStatus(UMI_E_INTERNAL_EXCEPTION);
RRETURN(UMI_E_INTERNAL_EXCEPTION); }
RRETURN(UMI_S_NO_ERROR); }
//----------------------------------------------------------------------------
// Function: GetInterfacePropNames
//
// Synopsis: Returns the names of all interface properties supported.
//
// Arguments:
//
// pProps Returns the names of the properties, without any data
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pProps to return the property names
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetInterfacePropNames( UMI_PROPERTY_VALUES **pProps ) { UMI_PROPERTY_VALUES *pUmiPropVals = NULL; UMI_PROPERTY *pUmiProps = NULL; HRESULT hr = UMI_S_NO_ERROR; ULONG ulIndex = 0, ulCount = 0;
ADsAssert(pProps != NULL); ADsAssert(TRUE == m_fIsIntfPropObj);
pUmiPropVals = (UMI_PROPERTY_VALUES *) AllocADsMem( sizeof(UMI_PROPERTY_VALUES)); if(NULL == pUmiPropVals) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
memset(pUmiPropVals, 0, sizeof(UMI_PROPERTY_VALUES));
if(0 == m_dwSchemaSize) { // no properties in cache
*pProps = pUmiPropVals; RRETURN(UMI_S_NO_ERROR); }
pUmiProps = (UMI_PROPERTY *) AllocADsMem( m_dwSchemaSize * sizeof(UMI_PROPERTY)); if(NULL == pUmiProps) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
memset(pUmiProps, 0, m_dwSchemaSize * sizeof(UMI_PROPERTY));
for(ulIndex = 0; ulIndex < m_dwSchemaSize; ulIndex++) { if( (0 == _wcsicmp((LPWSTR) m_pSchema[ulIndex].szPropertyName, TEXT(UMIOBJ_INTF_PROP_SCHEMA))) || (0 == _wcsicmp((LPWSTR) m_pSchema[ulIndex].szPropertyName, TEXT(UMIOBJ_INTF_PROP_SCHEMAPATH))) ) { if(NULL == m_pszSchema) // must be a schema object, so don't return __SCHEMA and
// __PADS_SCHEMA_CONTAINER_PATH.
continue; }
if(0 == _wcsicmp((LPWSTR) m_pSchema[ulIndex].szPropertyName, TEXT(UMIOBJ_INTF_PROP_SUPERCLASS))) { if(FALSE == m_fIsClassObj) // not a class object. Hence __SUPERCLASS is not exposed.
continue; }
if( (0 == _wcsicmp((LPWSTR) m_pSchema[ulIndex].szPropertyName, TEXT(UMIOBJ_INTF_PROP_KEY))) || (0 == _wcsicmp((LPWSTR) m_pSchema[ulIndex].szPropertyName, TEXT(UMIOBJ_INTF_PROP_PARENT))) ) if(TRUE == m_fIsNamespaceObj) // namespace objects have no key and parent
continue; pUmiProps[ulCount].pszPropertyName = (LPWSTR) AllocADsStr(m_pSchema[ulIndex].szPropertyName); if(NULL == pUmiProps[ulCount].pszPropertyName) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); ulCount++; }
pUmiPropVals->uCount = ulCount; pUmiPropVals->pPropArray = pUmiProps;
*pProps = pUmiPropVals;
RRETURN(UMI_S_NO_ERROR);
error:
if(pUmiProps != NULL) { for(ulIndex = 0; ulIndex < m_dwSchemaSize; ulIndex++) if(pUmiProps[ulIndex].pszPropertyName != NULL) FreeADsStr(pUmiProps[ulIndex].pszPropertyName);
FreeADsMem(pUmiProps); }
if(pUmiPropVals != NULL) FreeADsMem(pUmiPropVals);
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: GetObjectPropNames
//
// Synopsis: Returns the names of all object properties in the cache.
//
// Arguments:
//
// pProps Returns the names of the properties, without any data
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pProps to return the property names
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetObjectPropNames( UMI_PROPERTY_VALUES **pProps ) { ADsAssert(pProps != NULL); ADsAssert(FALSE == m_fIsIntfPropObj);
RRETURN(m_pPropCache->GetPropNames(pProps)); } //----------------------------------------------------------------------------
// Function: GetProps
//
// Synopsis: Implements IUmiPropList::GetProps. Gets multiple properties.
// This method will currently only support retrieving the names
// of the properties supported. For interface property objects,
// the names of all interface properties will be returned. For
// object properties, the names of all properties in the cache will
// be returned.
// This method also supports retrieving class information if
// the underlying object is a class object (in which case
// m_pClassInfo will be non-NULL). This is supported only on an
// interface property object.
//
// Arguments:
//
// pszNames Names of properties to retrieve. Should be NULL if only names
// are requested.
// uNameCount Number of properties in pszNames. Should be 0 if only names
// are requested.
// uFlags Should be UMI_FLAG_GETPROPS_NAMES to retrieve names of properties
// and UMI_FLAG_GETPROPS_SCHEMA to get class information.
// pProps Returns the names of the properties, without any data
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pProps to return the property names
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetProps( LPCWSTR *pszNames, ULONG uNameCount, ULONG uFlags, UMI_PROPERTY_VALUES **pProps ) { HRESULT hr = UMI_S_NO_ERROR;
SetLastStatus(0);
if( (uFlags != ((ULONG) UMI_FLAG_GETPROPS_NAMES)) && (uFlags != ((ULONG) UMI_FLAG_GETPROPS_SCHEMA)) ) BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
if( (pszNames != NULL) || (uNameCount != 0) || (NULL == pProps) ) BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
*pProps = NULL;
if( ((ULONG) UMI_FLAG_GETPROPS_SCHEMA) == uFlags ) { if(NULL == m_pClassInfo) { // this is not a class object. This operation is not supported.
BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_FLAGS); } else hr = GetClassInfo(pProps); } else { if(TRUE == m_fIsIntfPropObj) hr = GetInterfacePropNames(pProps); else hr = GetObjectPropNames(pProps); }
error: if(FAILED(hr)) SetLastStatus(hr);
RRETURN(MapHrToUmiError(hr)); }
//---------------------------------------------------------------------------
// Methods of IUmiPropList that are currently not implemented.
//
//---------------------------------------------------------------------------
HRESULT CUmiPropList::GetAt( LPCWSTR pszName, ULONG uFlags, ULONG uBufferLength, LPVOID pExistingMem ) { SetLastStatus(UMI_E_NOTIMPL);
RRETURN(UMI_E_NOTIMPL); }
HRESULT CUmiPropList::PutProps( LPCWSTR *pszNames, ULONG uNameCount, ULONG uFlags, UMI_PROPERTY_VALUES *pProps ) { SetLastStatus(UMI_E_NOTIMPL);
RRETURN(UMI_E_NOTIMPL); }
HRESULT CUmiPropList::PutFrom( LPCWSTR pszName, ULONG uFlags, ULONG uBufferLength, LPVOID pExistingMem ) { SetLastStatus(UMI_E_NOTIMPL);
RRETURN(UMI_E_NOTIMPL); }
HRESULT CUmiPropList::Delete( LPCWSTR pszName, ULONG uFlags ) { SetLastStatus(UMI_E_NOTIMPL);
RRETURN(UMI_E_NOTIMPL); }
//----------------------------------------------------------------------------
// Function: SetStandardProperties
//
// Synopsis: Sets standard interface properties supported by all UMI objects
// in the cache.
//
// Arguments:
//
// pIADs Pointer to IADs interface on object
// pCoreObj Pointer to core object for this WinNT object
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::SetStandardProperties( IADs *pIADs, CCoreADsObject *pCoreObj ) { HRESULT hr = S_OK; DWORD dwIndex = 0; IDispatch *pDispatch = NULL; DISPID DispId; DISPPARAMS DispParams = {NULL, NULL, 0, 0}; VARIANT var; BSTR bstrADsPath = NULL, bstrClass = NULL; LPWSTR pFullUmiPath = NULL, pShortUmiPath = NULL, pRelUmiPath = NULL; LPWSTR pFullRelUmiPath = NULL, pFullParentPath = NULL; DWORD dwGenus = 0; BSTR bstrName = NULL, bstrParent = NULL; WCHAR *pSlash = NULL; LPWSTR Classes[] = {NULL, L"Schema"}; LPWSTR pUmiSchemaPath = NULL; OBJECTINFO ObjectInfo;
ADsAssert( (pIADs != NULL) && (TRUE == m_fIsIntfPropObj) );
hr = pIADs->QueryInterface( IID_IDispatch, (void **) &pDispatch ); BAIL_ON_FAILURE(hr);
// First, set all properties supported on IADs. The names of these UMI
// properties are not necessarily the same as the IADs properties, so
// map the names appropriately.
for(dwIndex = 0; dwIndex < g_dwIADsProperties; dwIndex++) { hr = pDispatch->GetIDsOfNames( IID_NULL, &g_IADsProps[dwIndex].IADsPropertyName, 1, LOCALE_SYSTEM_DEFAULT, &DispId ); BAIL_ON_FAILURE(hr);
hr = pDispatch->Invoke( DispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &DispParams, &var, NULL, NULL );
if(0 == _wcsicmp(g_IADsProps[dwIndex].IADsPropertyName, L"Schema")) { if(FAILED(hr)) // Not a catastrophic failure. Can't get this property from the
// cache. Only scenario where this should happen is when calling
// get_Schema on a schema/namespace object.
continue; else { // store native path to schema in member variable
m_pszSchema = AllocADsStr(V_BSTR(&var)); VariantClear(&var);
if(NULL == m_pszSchema) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
// walk path backwards and get rid of last '/'
pSlash = wcsrchr(m_pszSchema, L'/'); if(NULL == pSlash) // bad schema path
BAIL_ON_FAILURE(UMI_E_FAIL);
*pSlash = L'\0';
Classes[0] = pCoreObj->_CompClasses[0]; ObjectInfo.DisplayComponentArray[0] = pCoreObj->_ObjectInfo.DisplayComponentArray[0]; ObjectInfo.DisplayComponentArray[1] = SCHEMA_NAME; hr = ADsToUmiPath( m_pszSchema, &ObjectInfo, Classes, 2, FULL_UMI_PATH, &pUmiSchemaPath );
*pSlash = L'/';
BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_SCHEMAPATH), pUmiSchemaPath, TRUE ); BAIL_ON_FAILURE(hr);
continue; } // else
} // if(_wcsicmp...)
BAIL_ON_FAILURE(hr); // if Invoke failed
if(0 == _wcsicmp(g_IADsProps[dwIndex].IADsPropertyName, L"Parent")) { // convert the parent to a full UMI path
if(0 == pCoreObj->_dwNumComponents) { // namespace object has no parent
VariantClear(&var); continue; } else { bstrParent = V_BSTR(&var);
hr = ADsToUmiPath( bstrParent, pCoreObj->_pObjectInfo, pCoreObj->_CompClasses, pCoreObj->_dwNumComponents - 1, FULL_UMI_PATH, &pFullParentPath ); VariantClear(&var);
BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_PARENT), pFullParentPath, TRUE ); BAIL_ON_FAILURE(hr);
continue; } // else
} // if(0 ==
hr = GenericPutPropertyManager( m_pPropCache, m_pSchema, m_dwSchemaSize, g_IADsProps[dwIndex].UMIPropertyName, var, FALSE ); VariantClear(&var);
BAIL_ON_FAILURE(hr); } // Now, set the remaining standard interface properties
hr = pIADs->get_ADsPath(&bstrADsPath); BAIL_ON_FAILURE(hr);
hr = ADsToUmiPath( bstrADsPath, pCoreObj->_pObjectInfo, pCoreObj->_CompClasses, pCoreObj->_dwNumComponents, FULL_UMI_PATH, &pFullUmiPath ); BAIL_ON_FAILURE(hr);
hr = ADsToUmiPath( bstrADsPath, pCoreObj->_pObjectInfo, pCoreObj->_CompClasses, pCoreObj->_dwNumComponents, SHORT_UMI_PATH, &pShortUmiPath ); BAIL_ON_FAILURE(hr);
hr = ADsToUmiPath( bstrADsPath, pCoreObj->_pObjectInfo, pCoreObj->_CompClasses, pCoreObj->_dwNumComponents, RELATIVE_UMI_PATH, &pRelUmiPath ); BAIL_ON_FAILURE(hr);
hr = ADsToUmiPath( bstrADsPath, pCoreObj->_pObjectInfo, pCoreObj->_CompClasses, pCoreObj->_dwNumComponents, FULL_RELATIVE_UMI_PATH, &pFullRelUmiPath ); BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_FULLURL), pFullUmiPath, TRUE ); BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_URL), pShortUmiPath, TRUE ); BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_RELURL), pRelUmiPath, TRUE ); BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_FULLRELURL), pFullRelUmiPath, TRUE ); BAIL_ON_FAILURE(hr);
// Relpath is the same as the full relative URL
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_RELPATH), pFullRelUmiPath, TRUE ); BAIL_ON_FAILURE(hr);
// set the genus based on the class of the object
hr = pIADs->get_Class(&bstrClass); BAIL_ON_FAILURE(hr);
if(IsSchemaObject(bstrClass)) { dwGenus = UMI_GENUS_CLASS;
// WMI requires that the value of __CLASS be the same on instances
// and classes. Thus, on class objects, the value of __CLASS should
// be "user" instead of "class". __SUPERCLASS is exposed only on
// class objects. Its value is always NULL in the WinNT provider
// since there is no class hierarchy.
if(IsClassObj(bstrClass)) { hr = pIADs->get_Name(&bstrName); BAIL_ON_FAILURE(hr);
// overwrite the value of __CLASS already stored in cache above
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_CLASS), bstrName, TRUE ); BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_SUPERCLASS), NULL, TRUE );
m_fIsClassObj = TRUE;
BAIL_ON_FAILURE(hr); } // if(IsClassObj...)
} else dwGenus = UMI_GENUS_INSTANCE;
hr = SetDWORDPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_GENUS), dwGenus, TRUE ); BAIL_ON_FAILURE(hr);
// set the key property. For WinNT, it will always be "Name" except that
// namespace objects have no key (since the UMI path to a namespace object
// is just umi:///winnt - there is no component of the form class.key=val.
if(!IsNamespaceObj(bstrClass)) { hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_KEY), WINNT_KEY_NAME, TRUE );
BAIL_ON_FAILURE(hr); } else { m_fIsNamespaceObj = TRUE; }
// Mark all properties as "not modified", since the client really hasn't
// updated the cache, though we have.
m_pPropCache->ClearModifiedFlags();
error: if(pDispatch != NULL) pDispatch->Release();
if(bstrADsPath != NULL) SysFreeString(bstrADsPath);
if(bstrClass != NULL) SysFreeString(bstrClass);
if(pFullUmiPath != NULL) FreeADsStr(pFullUmiPath);
if(pRelUmiPath != NULL) FreeADsStr(pRelUmiPath);
if(pFullRelUmiPath != NULL) FreeADsStr(pFullRelUmiPath);
if(pShortUmiPath != NULL) FreeADsStr(pShortUmiPath);
if(pFullParentPath != NULL) FreeADsStr(pFullParentPath);
if(bstrName != NULL) SysFreeString(bstrName);
if(pUmiSchemaPath != NULL) FreeADsStr(pUmiSchemaPath);
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: IsSchemaObject
//
// Synopsis: Returns whether an object of a specified class is a schema
// object or not.
//
// Arguments:
//
// bstrClass Class of object
//
// Returns: TRUE if it is a schema object. FALSE otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
BOOL CUmiPropList::IsSchemaObject( BSTR bstrClass ) { ADsAssert(bstrClass != NULL);
if( (!_wcsicmp(bstrClass, L"Schema")) || (!_wcsicmp(bstrClass, L"Class")) || (!_wcsicmp(bstrClass, L"Property")) || (!_wcsicmp(bstrClass, L"Syntax")) || (!_wcsicmp(bstrClass, L"Namespace")) ) RRETURN(TRUE);
RRETURN(FALSE); }
//----------------------------------------------------------------------------
// Function: GetSchemaObject
//
// Synopsis: Returns a IUmiObject pointer pointing to the schema class object
// corresponding to this WinNT object. If there is no class object,
// returns error.
//
// Arguments:
//
// pszName Name of the schema property
// ppProp Returns pointer to the structure containing the IUmiObject
// pointer.
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *ppProp to return the address of UMI_PROPERTY_VALUES structure.
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetSchemaObject( LPWSTR pszName, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = UMI_S_NO_ERROR; IUnknown *pUnknown = NULL; IUmiObject *pUmiObj = NULL; UMI_PROPERTY_VALUES *pProp = NULL;
PUMI_COM_OBJECT pUmiComObj = NULL; // use ADS_AUTH_RESERVED since the call is from UMI
CWinNTCredentials Credentials(NULL, NULL, ADS_AUTH_RESERVED);
ADsAssert( (ppProp != NULL) && (TRUE == m_fIsIntfPropObj) );
*ppProp = NULL;
if(NULL == m_pszSchema) // schema objects don't support __SCHEMA
RRETURN(UMI_E_PROPERTY_NOT_FOUND);
hr = GetObject( m_pszSchema, (LPVOID *) &pUnknown, Credentials ); BAIL_ON_FAILURE(hr);
hr = pUnknown->QueryInterface(IID_IUmiObject, (LPVOID *) &pUmiObj); BAIL_ON_FAILURE(hr);
pUmiComObj = (PUMI_COM_OBJECT) AllocADsMem(sizeof(UMI_COM_OBJECT)); if(NULL == pUmiComObj) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(pUmiComObj, 0, sizeof(UMI_COM_OBJECT));
pUmiComObj->priid = (IID *) AllocADsMem(sizeof(IID)); if(NULL == pUmiComObj->priid) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
memcpy(pUmiComObj->priid, &IID_IUmiObject, sizeof(IID)); pUmiComObj->pInterface = (LPVOID) pUmiObj;
// allocate structure to return values
pProp = (UMI_PROPERTY_VALUES *) AllocADsMem(sizeof(UMI_PROPERTY_VALUES)); if(NULL == pProp) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(pProp, 0, sizeof(UMI_PROPERTY_VALUES));
pProp->pPropArray = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY)); if(NULL == pProp->pPropArray) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(pProp->pPropArray, 0, sizeof(UMI_PROPERTY));
pProp->pPropArray->pUmiValue = (UMI_VALUE *) pUmiComObj;
// Get fetches only one property at a time
pProp->uCount = 1;
// Fill in remaining fields of UMI_PROPERTY
pProp->pPropArray->uOperationType = 0; pProp->pPropArray->uType = UMI_TYPE_IUNKNOWN; pProp->pPropArray->uCount = 1;
// not critical if this memory allocation fails. Property name doesn't
// have to be returned to the caller.
pProp->pPropArray->pszPropertyName = AllocADsStr(pszName);
*ppProp = pProp;
error:
if(pUnknown != NULL) pUnknown->Release();
if(FAILED(hr)) { if(pUmiObj != NULL) pUmiObj->Release();
if(pUmiComObj != NULL) { if(pUmiComObj->priid != NULL) FreeADsMem(pUmiComObj->priid);
FreeADsMem(pUmiComObj); }
if(pProp != NULL) { if(pProp->pPropArray != NULL) { if(pProp->pPropArray->pszPropertyName != NULL) FreeADsStr(pProp->pPropArray->pszPropertyName); FreeADsMem(pProp->pPropArray); }
FreeADsMem(pProp); } } // if(FAILED(hr))
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: SetClassInfo
//
// Synopsis: Initializes class info for this object. Class info will be
// stored only for class schema objects.
//
// Arguments:
//
// pClassInfo Class info for the object (NULL if not a class object)
//
// Returns: Nothing
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
void CUmiPropList::SetClassInfo( CLASSINFO *pClassInfo ) { m_pClassInfo = pClassInfo; return; } //----------------------------------------------------------------------------
// Function: GetClassInfo
//
// Synopsis: Returns the name and UMI type of all attributes in a given
// WinNT class. This method will only be called on the interface
// property object of a class object.
//
// Arguments:
//
// pProps Returns the names and types of the attributes, without any data
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *pProps to return the property names
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetClassInfo( UMI_PROPERTY_VALUES **pProps ) { UMI_PROPERTY_VALUES *pUmiPropVals = NULL; UMI_PROPERTY *pUmiProps = NULL; HRESULT hr = UMI_S_NO_ERROR; ULONG ulIndex = 0; PPROPERTYINFO pClassSchema = NULL; DWORD dwClassSchemaSize = 0;
ADsAssert(pProps != NULL); ADsAssert(TRUE == m_fIsIntfPropObj); ADsAssert(m_pClassInfo != NULL);
pUmiPropVals = (UMI_PROPERTY_VALUES *) AllocADsMem( sizeof(UMI_PROPERTY_VALUES)); if(NULL == pUmiPropVals) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
memset(pUmiPropVals, 0, sizeof(UMI_PROPERTY_VALUES));
pClassSchema = m_pClassInfo->aPropertyInfo; dwClassSchemaSize = m_pClassInfo->cPropertyInfo;
if(0 == dwClassSchemaSize) { // no properties in class
*pProps = pUmiPropVals; RRETURN(UMI_S_NO_ERROR); }
pUmiProps = (UMI_PROPERTY *) AllocADsMem( dwClassSchemaSize * sizeof(UMI_PROPERTY)); if(NULL == pUmiProps) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
memset(pUmiProps, 0, dwClassSchemaSize * sizeof(UMI_PROPERTY));
for(ulIndex = 0; ulIndex < dwClassSchemaSize; ulIndex++) { pUmiProps[ulIndex].pszPropertyName = (LPWSTR) AllocADsStr(pClassSchema[ulIndex].szPropertyName); if(NULL == pUmiProps[ulIndex].pszPropertyName) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
// map the NT type to a UMI type
if(pClassSchema[ulIndex].dwSyntaxId >= g_dwNumNTTypes) BAIL_ON_FAILURE(hr = UMI_E_FAIL); // shouldn't happen
pUmiProps[ulIndex].uType = g_mapNTTypeToUmiType[pClassSchema[ulIndex].dwSyntaxId]; }
pUmiPropVals->uCount = dwClassSchemaSize; pUmiPropVals->pPropArray = pUmiProps;
*pProps = pUmiPropVals;
RRETURN(UMI_S_NO_ERROR);
error:
if(pUmiProps != NULL) { for(ulIndex = 0; ulIndex < dwClassSchemaSize; ulIndex++) if(pUmiProps[ulIndex].pszPropertyName != NULL) FreeADsStr(pUmiProps[ulIndex].pszPropertyName);
FreeADsMem(pUmiProps); }
if(pUmiPropVals != NULL) FreeADsMem(pUmiPropVals);
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: IsNamespaceObj
//
// Synopsis: Returns whether an object of a specified class is a namespace
// object or not.
//
// Arguments:
//
// bstrClass Class of object
//
// Returns: TRUE if it is a namespace object. FALSE otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
BOOL CUmiPropList::IsNamespaceObj( BSTR bstrClass ) { ADsAssert(bstrClass != NULL);
if(!_wcsicmp(bstrClass, L"Namespace")) RRETURN(TRUE);
RRETURN(FALSE); }
//----------------------------------------------------------------------------
// Function: IsClassObj
//
// Synopsis: Returns whether an object of a specified class is a class
// object or not.
//
// Arguments:
//
// bstrClass Class of object
//
// Returns: TRUE if it is a class object. FALSE otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
BOOL CUmiPropList::IsClassObj( BSTR bstrClass ) { ADsAssert(bstrClass != NULL);
if(!_wcsicmp(bstrClass, L"Class")) RRETURN(TRUE);
RRETURN(FALSE); }
//----------------------------------------------------------------------------
// Function: DisableWrites
//
// Synopsis: Disables writes on an interface property object. Used to disable
// modification of connection interface properties after the
// connection is opened.
//
// Arguments:
//
// None
//
// Returns: Nothing
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
void CUmiPropList::DisableWrites(void) { ADsAssert(TRUE == m_fIsIntfPropObj);
m_fDisableWrites = TRUE; }
//----------------------------------------------------------------------------
// Function: SetDefaultConnProps
//
// Synopsis: Sets the default connection interface properties on the
// interface property object of a connection.
//
// Arguments:
//
// None
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::SetDefaultConnProps(void) { HRESULT hr = S_OK;
ADsAssert(TRUE == m_fIsIntfPropObj);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(CONN_INTF_PROP_USERNAME), CONN_INTF_PROP_DEFAULT_USERNAME, TRUE ); BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache( m_pPropCache, TEXT(CONN_INTF_PROP_PASSWORD), CONN_INTF_PROP_DEFAULT_PASSWORD, TRUE ); BAIL_ON_FAILURE(hr);
hr = SetBOOLPropertyInCache( m_pPropCache, TEXT(CONN_INTF_PROP_SECURE_AUTH), CONN_INTF_PROP_DEFAULT_SECURE_AUTH, TRUE ); BAIL_ON_FAILURE(hr);
hr = SetBOOLPropertyInCache( m_pPropCache, TEXT(CONN_INTF_PROP_READONLY_SERVER), CONN_INTF_PROP_DEFAULT_READONLY_SERVER, TRUE ); BAIL_ON_FAILURE(hr);
RRETURN(S_OK);
error:
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: SetPropertyCount
//
// Synopsis: Sets the property count in the interface property object's
// cache. The property count is the number of properties in the
// schema class object. It is exposed on both schema objects and
// instances.
//
// Arguments:
//
// dwPropCount Property count
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::SetPropertyCount(DWORD dwPropCount) { HRESULT hr = S_OK;
hr = SetDWORDPropertyInCache( m_pPropCache, TEXT(UMIOBJ_INTF_PROP_PROPERTY_COUNT), dwPropCount, TRUE ); BAIL_ON_FAILURE(hr);
error:
RRETURN(hr); }
//----------------------------------------------------------------------------
// Function: GetPropertyOrigin
//
// Synopsis: Returns the class in the hierarchy that introduced a
// property. Since WinNT does not have a class hierarchy, this
// will always be the class on which this method is called. If
// the property is not in the class, an error is returned.
//
// Arguments:
//
// pszName Name of the schema property
// ppProp Returns pointer to the structure containing the class name
//
// Returns: UMI_S_NO_ERROR on success. Error code otherwise.
//
// Modifies: *ppProp to return the address of UMI_PROPERTY_VALUES structure.
//
//----------------------------------------------------------------------------
HRESULT CUmiPropList::GetPropertyOrigin( LPCWSTR pszName, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = UMI_S_NO_ERROR; DWORD dwIndex = 0; PPROPERTYINFO pClassSchema = NULL; DWORD dwClassSchemaSize = 0; UMI_PROPERTY_VALUES *pProp = NULL; LPWSTR *ppszClassArray = NULL;
ADsAssert( (pszName != NULL) && (ppProp != NULL) && (TRUE == m_fIsIntfPropObj) && (m_pClassInfo != NULL) );
*ppProp = NULL;
pClassSchema = m_pClassInfo->aPropertyInfo; dwClassSchemaSize = m_pClassInfo->cPropertyInfo;
if(0 == dwClassSchemaSize) // no properties in class
BAIL_ON_FAILURE(hr = UMI_E_PROPERTY_NOT_FOUND);
for(dwIndex = 0; dwIndex < dwClassSchemaSize; dwIndex++) { if(0 == _wcsicmp(pszName, pClassSchema[dwIndex].szPropertyName)) // found the property
break; }
if(dwIndex == dwClassSchemaSize) BAIL_ON_FAILURE(hr = UMI_E_PROPERTY_NOT_FOUND);
// allocate structure to return class name
pProp = (UMI_PROPERTY_VALUES *) AllocADsMem(sizeof(UMI_PROPERTY_VALUES)); if(NULL == pProp) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(pProp, 0, sizeof(UMI_PROPERTY_VALUES));
pProp->pPropArray = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY)); if(NULL == pProp->pPropArray) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(pProp->pPropArray, 0, sizeof(UMI_PROPERTY));
ppszClassArray = (LPWSTR *) AllocADsMem(sizeof(LPWSTR *)); if(NULL == pProp->pPropArray) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); memset(ppszClassArray, 0, sizeof(LPWSTR *));
ppszClassArray[0] = AllocADsStr(m_pClassInfo->bstrName); if(NULL == ppszClassArray[0]) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
pProp->pPropArray->pUmiValue = (UMI_VALUE *) ppszClassArray;
// Get fetches only one property at a time
pProp->uCount = 1;
// Fill in remaining fields of UMI_PROPERTY
pProp->pPropArray->uOperationType = 0; pProp->pPropArray->uType = UMI_TYPE_LPWSTR; pProp->pPropArray->uCount = 1;
// not critical if this memory allocation fails. Property name doesn't
// have to be returned to the caller.
pProp->pPropArray->pszPropertyName = AllocADsStr(pszName);
*ppProp = pProp;
error:
if(FAILED(hr)) { if(pProp != NULL) { if(pProp->pPropArray != NULL) { if(pProp->pPropArray->pszPropertyName != NULL) FreeADsStr(pProp->pPropArray->pszPropertyName); FreeADsMem(pProp->pPropArray); }
FreeADsMem(pProp); }
if(ppszClassArray != NULL) { if(ppszClassArray[0] != NULL) FreeADsStr(ppszClassArray[0]);
FreeADsMem(ppszClassArray); }
} // if(FAILED(hr))
RRETURN(hr); }
|