//---------------------------------------------------------------------------- // // 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); }