//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: cprops.cxx // // Contents: Property Cache functionality for IIS // // Functions: // CPropertyCache::addproperty // CPropertyCache::updateproperty // CPropertyCache::findproperty // CPropertyCache::getproperty // CPropertyCache::putproperty // CProperyCache::CPropertyCache // CPropertyCache::~CPropertyCache // CPropertyCache::createpropertycache // // History: 17-June-1997 sophiac Created. // cloned off NT property cache code // // //---------------------------------------------------------------------------- #include "iis.hxx" #pragma hdrstop #if DBG DECLARE_INFOLEVEL(IISMarshall); DECLARE_DEBUG(IISMarshall); #define IISMarshallDebugOut(x) IISMarshallInlineDebugOut x #endif //+------------------------------------------------------------------------ // // Function: CPropertyCache::addproperty // // Synopsis: // // // // Arguments: [szPropertyName] -- // [vt] -- // [vaData] -- // // //------------------------------------------------------------------------- HRESULT CPropertyCache:: addproperty( LPWSTR szPropertyName, DWORD dwSyntaxId, DWORD dwNumValues, PIISOBJECT pIISObject ) { HRESULT hr = S_OK; PPROPERTY pNewProperty = NULL; // // extend the property cache by adding a new property entry // PPROPERTY pOrigProperties = _pProperties; _pProperties = (PPROPERTY)ReallocADsMem( _pProperties, _cb, _cb + sizeof(PROPERTY) ); if (!_pProperties) { _pProperties = pOrigProperties; hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pNewProperty = (PPROPERTY)((LPBYTE)_pProperties + _cb); wcscpy(pNewProperty->szPropertyName, szPropertyName); // // Update the index // _dwMaxProperties++; _cb += sizeof(PROPERTY); error: RRETURN(hr); } //+------------------------------------------------------------------------ // // Function: CPropertyCache::updateproperty // // Synopsis: // // // // Arguments: [szPropertyName] -- // [vaData] -- // //------------------------------------------------------------------------- HRESULT CPropertyCache::updateproperty( LPWSTR szPropertyName, DWORD dwSyntaxId, DWORD dwNumValues, PIISOBJECT pIISObject, BOOL fExplicit ) { HRESULT hr; DWORD dwIndex; DWORD dwMetaId; PIISOBJECT pIISTempObject = NULL; PPROPERTY pThisProperty = NULL; hr = LoadSchema(); BAIL_ON_FAILURE(hr); hr = findproperty( szPropertyName, &dwIndex ); BAIL_ON_FAILURE(hr); pThisProperty = _pProperties + dwIndex; if (!fExplicit) { if ((PROPERTY_FLAGS(pThisProperty) == CACHE_PROPERTY_MODIFIED) || (PROPERTY_FLAGS(pThisProperty) == CACHE_PROPERTY_CLEARED)) { hr = S_OK; goto error; } } // // Factor in cases where object state is necessary to // decide on update. // if (PROPERTY_IISOBJECT(pThisProperty)) { IISTypeFreeIISObjects( PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty) ); PROPERTY_IISOBJECT(pThisProperty) = NULL; } PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId; PROPERTY_NUMVALUES(pThisProperty) = dwNumValues; _pSchema->ConvertPropName_To_ID(szPropertyName, &dwMetaId); PROPERTY_METAID(pThisProperty) = dwMetaId; hr = IISTypeCopyConstruct( pIISObject, dwNumValues, &pIISTempObject ); BAIL_ON_FAILURE(hr); PROPERTY_IISOBJECT(pThisProperty) = pIISTempObject; PROPERTY_FLAGS(pThisProperty) = CACHE_PROPERTY_INITIALIZED; error: RRETURN(hr); } //+------------------------------------------------------------------------ // // Function: CPropertyCache::findproperty // // Synopsis: // // // // Arguments: [szPropertyName] -- // [pdwIndex] -- // //------------------------------------------------------------------------- HRESULT CPropertyCache::findproperty( LPWSTR szPropertyName, PDWORD pdwIndex ) { DWORD i = 0; PPROPERTY pThisProperty = NULL; for (i = 0; i < _dwMaxProperties; i++) { pThisProperty = _pProperties + i; ASSERT(pThisProperty); if (!_wcsicmp(pThisProperty->szPropertyName, szPropertyName)) { *pdwIndex = i; RRETURN(S_OK); } } *pdwIndex = 0; RRETURN(E_ADS_PROPERTY_NOT_FOUND); } //+------------------------------------------------------------------------ // // Function: CPropertyCache::getproperty // // Synopsis: // // // // Arguments: [szPropertyName] -- Property to retrieve from the cache // [pvaData] -- Data returned in a variant // //------------------------------------------------------------------------- HRESULT CPropertyCache:: getproperty( LPWSTR szPropertyName, PDWORD pdwSyntaxId, PDWORD pdwNumValues, PIISOBJECT * ppIISObject ) { HRESULT hr; DWORD dwIndex = 0L; PPROPERTY pThisProperty = NULL; DWORD dwInfoLevel = 0; hr = LoadSchema(); BAIL_ON_FAILURE(hr); hr = findproperty( szPropertyName, &dwIndex ); if (hr == E_ADS_PROPERTY_NOT_FOUND) { // // Now call the GetInfo function // if (!_bPropsLoaded) { hr = _pCoreADsObject->GetInfo(FALSE); if (FAILED(hr) && hr != E_ADS_OBJECT_UNBOUND) { BAIL_ON_FAILURE(hr); } hr = findproperty( szPropertyName, &dwIndex ); } } if (hr == E_ADS_PROPERTY_NOT_FOUND) { LPBYTE propvalue; DWORD dwSyntax; DWORD dwNumValues; hr = _pSchema->GetDefaultProperty(szPropertyName, &dwNumValues, &dwSyntax, &propvalue); BAIL_ON_FAILURE(hr); hr = unmarshallproperty( szPropertyName, propvalue, dwNumValues, dwSyntax, 0 ); BAIL_ON_FAILURE(hr); hr = findproperty (szPropertyName, &dwIndex ); } BAIL_ON_FAILURE(hr); pThisProperty = _pProperties + dwIndex; if (PROPERTY_IISOBJECT(pThisProperty)) { *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty); *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty); hr = IISTypeCopyConstruct(PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty), ppIISObject ); BAIL_ON_FAILURE(hr); }else { *ppIISObject = NULL; *pdwNumValues = 0; *pdwSyntaxId = 0; hr = E_ADS_PROPERTY_NOT_SET; } error: RRETURN(hr); } //+------------------------------------------------------------------------ // // Function: CPropertyCache::putproperty // // Synopsis: // // // // Arguments: [szPropertyName] -- Clsid index // [vaData] -- Matching clsid returned in *pclsid // //------------------------------------------------------------------------- HRESULT CPropertyCache::putproperty( LPWSTR szPropertyName, DWORD dwFlags, DWORD dwSyntaxId, DWORD dwNumValues, PIISOBJECT pIISObject ) { HRESULT hr; DWORD dwIndex = 0L; DWORD dwMetaId = 0; PIISOBJECT pIISTempObject = NULL; PPROPERTY pThisProperty = NULL; hr = LoadSchema(); BAIL_ON_FAILURE(hr); hr = findproperty( szPropertyName, &dwIndex ); BAIL_ON_FAILURE(hr); pThisProperty = _pProperties + dwIndex; if (PROPERTY_IISOBJECT(pThisProperty)) { IISTypeFreeIISObjects( PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty) ); PROPERTY_IISOBJECT(pThisProperty) = NULL; } _pSchema->ConvertPropName_To_ID(szPropertyName, &dwMetaId); switch (dwFlags) { case CACHE_PROPERTY_MODIFIED: PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId; PROPERTY_NUMVALUES(pThisProperty) = dwNumValues; PROPERTY_METAID(pThisProperty) = dwMetaId; hr = IISTypeCopyConstruct( pIISObject, dwNumValues, &pIISTempObject ); BAIL_ON_FAILURE(hr); PROPERTY_IISOBJECT(pThisProperty) = pIISTempObject; PROPERTY_FLAGS(pThisProperty) = CACHE_PROPERTY_MODIFIED; break; case CACHE_PROPERTY_CLEARED: PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId; PROPERTY_NUMVALUES(pThisProperty) = 0; PROPERTY_IISOBJECT(pThisProperty) = NULL; PROPERTY_FLAGS(pThisProperty) = CACHE_PROPERTY_CLEARED; break; } error: RRETURN(hr); } //+------------------------------------------------------------------------ // // Function: CPropertyCache // // Synopsis: // // // // Arguments: // // //------------------------------------------------------------------------- CPropertyCache::CPropertyCache(): _pCoreADsObject(NULL), _pSchema(NULL), _bPropsLoaded(FALSE), _dwMaxProperties(0), _dwCurrentIndex(0), _pProperties(NULL), _cb(0), _pDispProperties(NULL), _dwDispMaxProperties(0), _cbDisp(0), _bstrServerName(NULL) { } //+------------------------------------------------------------------------ // // Function: ~CPropertyCache // // Synopsis: // // // // Arguments: // // //------------------------------------------------------------------------- CPropertyCache:: ~CPropertyCache() { DWORD i = 0; PPROPERTY pThisProperty = NULL; PDISPPROPERTY pThisDispProperty = NULL; if (_pProperties) { for (i = 0; i < _dwMaxProperties; i++) { pThisProperty = _pProperties + i; if (PROPERTY_IISOBJECT(pThisProperty)) { IISTypeFreeIISObjects( PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty) ); PROPERTY_IISOBJECT(pThisProperty) = NULL; } } FreeADsMem(_pProperties); } // // Free Dynamic Dispid Table // if (_pDispProperties) { FreeADsMem(_pDispProperties); } if( _bstrServerName ) { ADsFreeString( _bstrServerName ); } } //+------------------------------------------------------------------------ // // Function: // // Synopsis: // // // // Arguments: // // //------------------------------------------------------------------------- HRESULT CPropertyCache::createpropertycache( CCoreADsObject FAR * pCoreADsObject, CPropertyCache FAR *FAR * ppPropertyCache ) { CPropertyCache FAR * pPropertyCache = NULL; BSTR serverName=NULL; HRESULT hr; hr = pCoreADsObject->get_CoreName(&serverName); BAIL_ON_FAILURE(hr); pPropertyCache = new CPropertyCache(); if (!pPropertyCache) { RRETURN(E_OUTOFMEMORY); } pPropertyCache->_pCoreADsObject = pCoreADsObject; *ppPropertyCache = pPropertyCache; RRETURN(S_OK); error : RRETURN(hr); } //+------------------------------------------------------------------------ // // Function: // // Synopsis: // // // // Arguments: // // //------------------------------------------------------------------------- HRESULT CPropertyCache:: unmarshallproperty( LPWSTR szPropertyName, LPBYTE lpValue, DWORD dwNumValues, DWORD dwSyntaxId, BOOL fExplicit ) { DWORD dwIndex = 0; HRESULT hr = S_OK; PIISOBJECT pIISObject = NULL; hr = UnMarshallIISToIISSynId( dwSyntaxId, dwNumValues, lpValue, &pIISObject ); BAIL_ON_FAILURE(hr); // // Find this property in the cache // hr = findproperty( szPropertyName, &dwIndex ); // // If this property does not exist in the // cache, add this property into the cache. // if (FAILED(hr)) { hr = addproperty( szPropertyName, dwSyntaxId, dwNumValues, pIISObject ); // // If the operation fails for some reason // move on to the next property // BAIL_ON_FAILURE(hr); } // // Now update the property in the cache // hr = updateproperty( szPropertyName, dwSyntaxId, dwNumValues, pIISObject, fExplicit ); BAIL_ON_FAILURE(hr); error: if (pIISObject) { IISTypeFreeIISObjects( pIISObject, dwNumValues ); } RRETURN(hr); } HRESULT CPropertyCache:: IISUnMarshallProperties( LPBYTE pBase, LPBYTE pBuffer, DWORD dwMDNumDataEntries, BOOL fExplicit ) { HRESULT hr = S_OK; PMETADATA_GETALL_RECORD pmdgarData = NULL, pTemp = NULL; DWORD i = 0; WCHAR szPropertyName[MAX_PATH]; DWORD dwSyntaxID; DWORD dwNumValues; ZeroMemory(szPropertyName, MAX_PATH); hr = LoadSchema(); BAIL_ON_FAILURE(hr); _bPropsLoaded = TRUE; pmdgarData = (PMETADATA_GETALL_RECORD)pBuffer; for (i = 0; i < dwMDNumDataEntries; i++) { // // unmarshall this property into the // property cache // pTemp = pmdgarData + i; hr = _pSchema->ConvertID_To_PropName(pTemp->dwMDIdentifier, szPropertyName); CONTINUE_ON_FAILURE(hr); hr = _pSchema->LookupSyntaxID(szPropertyName, &dwSyntaxID); CONTINUE_ON_FAILURE(hr); // // find out number of strings within the multi-sz string // if (pTemp->dwMDDataType == MULTISZ_METADATA) { LPWSTR pszStr = (LPWSTR) (pBase + pTemp->dwMDDataOffset); if (*pszStr == 0) { dwNumValues = 1; } else { dwNumValues = 0; } while (*pszStr != L'\0') { while (*pszStr != L'\0') { pszStr++; } dwNumValues++; pszStr++; } } else if (pTemp->dwMDDataType == BINARY_METADATA) { // // if DataType == BINARY, pass the length to dwNumValues // dwNumValues = pTemp->dwMDDataLen; } else { dwNumValues = 1; } hr = unmarshallproperty( szPropertyName, pBase + pTemp->dwMDDataOffset, dwNumValues, dwSyntaxID, fExplicit ); CONTINUE_ON_FAILURE(hr); } error: RRETURN(hr); } HRESULT CPropertyCache:: IISMarshallProperties( PMETADATA_RECORD * ppMetaDataRecords, PDWORD pdwMDNumDataEntries ) { HRESULT hr = S_OK; DWORD i = 0; PPROPERTY pThisProperty = NULL; PMETADATA_RECORD pMetaDataArray = NULL; DWORD dwCount = 0; hr = LoadSchema(); BAIL_ON_FAILURE(hr); pMetaDataArray = (PMETADATA_RECORD) AllocADsMem( _dwMaxProperties * sizeof(METADATA_RECORD)); if (!pMetaDataArray ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } *ppMetaDataRecords = pMetaDataArray; for (i = 0; i < _dwMaxProperties ; i++) { pThisProperty = _pProperties + i; // // Bypass any property that has not been // modified // if (PROPERTY_FLAGS(pThisProperty) == 0 || PROPERTY_FLAGS(pThisProperty) == CACHE_PROPERTY_CLEARED) { continue; } hr = MarshallIISSynIdToIIS( _pSchema, PROPERTY_SYNTAX(pThisProperty), PROPERTY_METAID(pThisProperty), PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty), pMetaDataArray ); CONTINUE_ON_FAILURE(hr); pMetaDataArray++; dwCount++; } *pdwMDNumDataEntries = dwCount; error: RRETURN(hr); } //+------------------------------------------------------------------------ // // Function: ~CPropertyCache // // Synopsis: // // // // Arguments: // // //------------------------------------------------------------------------- void CPropertyCache:: flushpropcache() { DWORD i = 0; PPROPERTY pThisProperty = NULL; if (_pProperties) { for (i = 0; i < _dwMaxProperties; i++) { pThisProperty = _pProperties + i; if (PROPERTY_IISOBJECT(pThisProperty)) { IISTypeFreeIISObjects( PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty) ); PROPERTY_IISOBJECT(pThisProperty) = NULL; } } FreeADsMem(_pProperties); } // // Reset the property cache // _pProperties = NULL; _dwMaxProperties = 0; _cb = 0; } BOOL CPropertyCache:: index_valid( ) { // // need to check separately since a negative DWORD is equal to +ve large # // if (_dwMaxProperties==0) return(FALSE); if (_dwCurrentIndex > _dwMaxProperties - 1) return(FALSE); else return(TRUE); } BOOL CPropertyCache:: index_valid( DWORD dwIndex ) { // // need to check separately since a negative DWORD is equal to +ve large # // if (_dwMaxProperties==0) return(FALSE); if (dwIndex > _dwMaxProperties - 1) return(FALSE); else return(TRUE); } void CPropertyCache:: reset_propindex( ) { _dwCurrentIndex = 0; } HRESULT CPropertyCache:: skip_propindex( DWORD dwElements ) { DWORD newIndex = _dwCurrentIndex + dwElements; if (!index_valid()) RRETURN(E_ADS_BAD_PARAMETER); if (newIndex > _dwMaxProperties) { RRETURN(E_ADS_BAD_PARAMETER); } _dwCurrentIndex = newIndex; RRETURN(S_OK); } HRESULT CPropertyCache:: get_PropertyCount( PDWORD pdwMaxProperties ) { *pdwMaxProperties = _dwMaxProperties; RRETURN(S_OK); } DWORD CPropertyCache:: get_CurrentIndex( ) { return(_dwCurrentIndex); } LPWSTR CPropertyCache:: get_CurrentPropName( ) { PPROPERTY pThisProperty = NULL; if (!_dwMaxProperties) // if !_dwMaxProperties, pThisProperty=NULL, AV return NULL; // in PROPERTY_NAME(pThisProperty) if (!index_valid()) return(PROPERTY_NAME(pThisProperty)); pThisProperty = _pProperties + _dwCurrentIndex; return(PROPERTY_NAME(pThisProperty)); } LPWSTR CPropertyCache:: get_PropName( DWORD dwIndex ) { PPROPERTY pThisProperty = NULL; if (!index_valid(dwIndex)) return(NULL); pThisProperty = _pProperties + dwIndex; return(PROPERTY_NAME(pThisProperty)); } HRESULT CPropertyCache:: deleteproperty( DWORD dwIndex ) { HRESULT hr = S_OK; PPROPERTY pNewProperties = NULL; PPROPERTY pThisProperty = _pProperties + dwIndex; if (!index_valid(dwIndex)) { hr = E_FAIL; BAIL_ON_FAILURE(hr); } if (_dwMaxProperties == 1) { // // Deleting everything // if (PROPERTY_IISOBJECT(pThisProperty)) { IISTypeFreeIISObjects( PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty) ); PROPERTY_IISOBJECT(pThisProperty) = NULL; } FreeADsMem(_pProperties); _pProperties = NULL; _dwMaxProperties = 0; _cb = 0; RRETURN(hr); } pNewProperties = (PPROPERTY)AllocADsMem( _cb - sizeof(PROPERTY) ); if (!pNewProperties) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } // // Copying the memory before the deleted item // if (dwIndex != 0) { memcpy( pNewProperties, _pProperties, dwIndex * sizeof(PROPERTY)); } // // Copying the memory following the deleted item // if (dwIndex != (_dwMaxProperties-1)) { memcpy( pNewProperties + dwIndex, _pProperties + dwIndex + 1, (_dwMaxProperties - dwIndex - 1) * sizeof(PROPERTY)); } if (PROPERTY_IISOBJECT(pThisProperty)) { IISTypeFreeIISObjects( PROPERTY_IISOBJECT(pThisProperty), PROPERTY_NUMVALUES(pThisProperty) ); PROPERTY_IISOBJECT(pThisProperty) = NULL; } FreeADsMem(_pProperties); _pProperties = pNewProperties; _dwMaxProperties--; _cb -= sizeof(PROPERTY); error: RRETURN(hr); } //////////////////////////////////////////////////////////////////////// // // IPropertyCache // HRESULT CPropertyCache:: locateproperty( LPWSTR szPropertyName, PDWORD pdwDispid ) { HRESULT hr; hr = DispatchLocateProperty( szPropertyName, pdwDispid ); RRETURN(hr); } HRESULT CPropertyCache:: putproperty( DWORD dwDispid, VARIANT varValue ) { HRESULT hr; hr = DispatchPutProperty( dwDispid, varValue ); RRETURN(hr); } HRESULT CPropertyCache:: getproperty( DWORD dwDispid, VARIANT * pvarValue ) { HRESULT hr; hr = DispatchGetProperty( dwDispid, pvarValue ); RRETURN(hr); } //////////////////////////////////////////////////////////////////////// // // Dynamic Dispid Table // HRESULT CPropertyCache:: DispatchFindProperty( LPWSTR szPropertyName, PDWORD pdwDispid ) { DWORD i = 0; PDISPPROPERTY pDispProp = NULL; // // use ADs Error codes since this funct'n does not go directly into // the dispatch interface // if (!pdwDispid || !szPropertyName) RRETURN(E_ADS_BAD_PARAMETER); for (i=0; i<_dwDispMaxProperties; i++) { pDispProp = _pDispProperties + i; if (!_wcsicmp(DISPATCH_NAME(pDispProp), szPropertyName)) { *pdwDispid=i; RRETURN(S_OK); } } *pdwDispid = (DWORD)-1; RRETURN(E_ADS_PROPERTY_NOT_FOUND); } HRESULT CPropertyCache:: DispatchAddProperty( LPWSTR szPropertyName, PDWORD pdwDispid /* optional */ ) { HRESULT hr = E_FAIL; DWORD dwDispid = (DWORD)-1; PDISPPROPERTY pNewDispProps = NULL; // // use ADs Error codes since this funct'n does not go directly into // the dispatch interface // if (!szPropertyName) RRETURN(E_ADS_BAD_PARAMETER); hr = DispatchFindProperty( szPropertyName, &dwDispid ); if (hr==E_ADS_PROPERTY_NOT_FOUND) { // // increase the size of Dynamic Dispid Table by 1 property // pNewDispProps = (PDISPPROPERTY) ReallocADsMem( _pDispProperties, _cbDisp, _cbDisp + sizeof(DISPPROPERTY) ); if (!pNewDispProps) BAIL_ON_FAILURE(hr=E_OUTOFMEMORY); // // must succeeded at this pt. okay to change table & indexes // _pDispProperties = pNewDispProps; wcscpy((_pDispProperties+_dwDispMaxProperties)->szPropertyName, szPropertyName); dwDispid = _dwDispMaxProperties++; _cbDisp += sizeof(DISPPROPERTY); hr = S_OK; } // // return valid, or invalid (-1) in case of failure, dispid of // szProperty iff asked for // if (pdwDispid) *pdwDispid = dwDispid; error: RRETURN(hr); } HRESULT CPropertyCache:: DispatchLocateProperty( LPWSTR szPropertyName, PDWORD pdwDispid ) { HRESULT hr; BSTR bstrClassName = NULL; // // - pdwDispid not optional here // - Use DISP_E_ERROR codes since this function directly called by // the dispatch manager // if (!pdwDispid || !szPropertyName) RRETURN(DISP_E_PARAMNOTOPTIONAL); hr = LoadSchema(); BAIL_ON_FAILURE(hr); // // return dispid of property if already in table; // hr = DispatchFindProperty( szPropertyName, pdwDispid ); if (hr==E_ADS_PROPERTY_NOT_FOUND) { // // check if property in schema // - this is necessary; otherwise, property not in schema will // be allowed to be added to cache and will not be given the // chance to be handled by 3rd party extension. // - note that property not in schema but added to the cache // thru' IADsProperty list will not be handled by 3rd // party extension either. // hr = _pCoreADsObject->get_CoreADsClass(&bstrClassName); BAIL_ON_FAILURE(hr); hr = _pSchema->ValidateProperty(bstrClassName, szPropertyName); BAIL_ON_FAILURE(hr); // // Add property that is in the schema but not in the cache to // the dynamic dispid table. That is, property which is in the // schema will always be handled by the cache/server thur ADSI but // will NOT be handled by 3rd party extension. // if (SUCCEEDED(hr)) { hr = DispatchAddProperty( szPropertyName, pdwDispid ); BAIL_ON_FAILURE(hr); } // // Property Not in the schema will nto be added to the dynamic // dispid table and could be handled by 3rd party extension. // else { hr = DISP_E_MEMBERNOTFOUND; BAIL_ON_FAILURE(hr); } } if (bstrClassName) { ADsFreeString(bstrClassName); } RRETURN(hr); error: if (bstrClassName) { ADsFreeString(bstrClassName); } *pdwDispid = (DWORD)DISPID_UNKNOWN; RRETURN(hr); } /* INTRINSA suppress=null_pointers, uninitialized */ HRESULT CPropertyCache:: DispatchGetProperty( DWORD dwDispid, VARIANT * pvarVal ) { HRESULT hr; LPWSTR szPropName = NULL; DWORD dwSyntaxId = (DWORD)-1; DWORD dwSyntax; DWORD dwNumValues = (DWORD)0; PIISOBJECT pIISObjs = NULL; WCHAR wchName[MAX_PATH]; hr = LoadSchema(); BAIL_ON_FAILURE(hr); // // Use DISP_E_ERROR codes since this function directly called by // the dispatch manager // if (!pvarVal) RRETURN(DISP_E_PARAMNOTOPTIONAL); if (!DISPATCH_INDEX_VALID(dwDispid)) RRETURN(DISP_E_MEMBERNOTFOUND); szPropName = DISPATCH_PROPERTY_NAME(dwDispid); // // lookup ADSI IIS syntax Id // hr = _pSchema->LookupSyntaxID(szPropName, &dwSyntax); BAIL_ON_FAILURE(hr); // // check if property is BITMASK type; // if BITMASK type, get corresponding DWORD flag property // if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY) { hr = _pSchema->LookupFlagPropName(szPropName, (LPWSTR)wchName); BAIL_ON_FAILURE(hr); } // // return value in cache for szPropName; retrieve value from server // if not already in cache; fail if none on sever // if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY) { hr = getproperty( wchName, &dwSyntaxId, &dwNumValues, &pIISObjs ); } else { hr = getproperty( szPropName, &dwSyntaxId, &dwNumValues, &pIISObjs ); } BAIL_ON_FAILURE(hr); // // reset it to its syntax id if BITMASK type // pIISObjs->IISType = dwSyntax; // // translate IIS objects into variants // // // always return an array for multisz type // if (dwSyntax == IIS_SYNTAX_ID_BINARY) { hr = IISTypeToVarTypeCopy( _pSchema, szPropName, pIISObjs, pvarVal, TRUE ); } else if (dwNumValues == 1 && dwSyntax != IIS_SYNTAX_ID_MULTISZ && dwSyntax != IIS_SYNTAX_ID_MIMEMAP ) { hr = IISTypeToVarTypeCopy( _pSchema, szPropName, pIISObjs, pvarVal, FALSE ); } else { hr = IISTypeToVarTypeCopyConstruct( _pSchema, szPropName, pIISObjs, dwNumValues, pvarVal, FALSE ); } BAIL_ON_FAILURE(hr); error: if (pIISObjs) { IISTypeFreeIISObjects( pIISObjs, dwNumValues ); } if (FAILED(hr)) { V_VT(pvarVal) = VT_ERROR; } RRETURN(hr); } HRESULT CPropertyCache:: DispatchPutProperty( DWORD dwDispid, VARIANT& varVal ) { HRESULT hr; DWORD dwSyntaxId = (DWORD)-1; DWORD dwIndex = (DWORD)-1; LPIISOBJECT pIISObjs = NULL; DWORD dwNumValues = (DWORD)0; VARIANT * pVarArray = NULL; // to be freed VARIANT * pvProp = NULL; // do not free VARIANT vVar; WCHAR wchName[MAX_PATH]; LPWSTR szPropName = NULL; hr = LoadSchema(); BAIL_ON_FAILURE(hr); // // Use DISP_E_ERROR codes since this function directly called by // the dispatch manager // if (!DISPATCH_INDEX_VALID(dwDispid)) RRETURN(DISP_E_MEMBERNOTFOUND); // // retreive property name from Dynamic Dispatch Table // szPropName = DISPATCH_PROPERTY_NAME(dwDispid); // // lookup its syntax ID // hr = _pSchema->LookupSyntaxID(szPropName, &dwSyntaxId); BAIL_ON_FAILURE(hr); // // Issue: How do we handle multi-valued support // VariantInit(&vVar); hr = VariantCopyInd(&vVar, &varVal); BAIL_ON_FAILURE(hr); if (V_VT(&vVar) == VT_DISPATCH) { hr = ConvertDispatchToVariantArray( vVar, &pVarArray, &dwNumValues ); if (S_OK == hr) { pvProp = pVarArray; } else { // something went wrong converting to a variant array // don't bail - just stuff it in as is dwNumValues = 1; pvProp = &vVar; hr = S_OK; } } else if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) { hr = ConvertArrayToVariantArray( vVar, &pVarArray, &dwNumValues ); BAIL_ON_FAILURE(hr); pvProp = pVarArray; } else { dwNumValues = 1; pvProp = &vVar; } // // Variant Array to IIS Objects // hr = VarTypeToIISTypeCopyConstruct( dwSyntaxId, pvProp, dwNumValues, &pIISObjs, FALSE ); BAIL_ON_FAILURE(hr); // // check if property is BITMASK type; // if BITMASK type, get corresponding DWORD flag property // if (dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) { DWORD dwMask; DWORD dwFlagValue; DWORD Temp; LPIISOBJECT pIISObject = NULL; hr = _pSchema->LookupBitMask(szPropName, &dwMask); BAIL_ON_FAILURE(hr); // // get its corresponding DWORD flag value // hr = _pSchema->LookupFlagPropName(szPropName, (LPWSTR)wchName); BAIL_ON_FAILURE(hr); hr = getproperty(wchName, &Temp, &Temp, &pIISObject); BAIL_ON_FAILURE(hr); dwFlagValue = pIISObject->IISValue.value_1.dwDWORD; if (pIISObjs->IISValue.value_1.dwDWORD) { dwFlagValue |= dwMask; } else { dwFlagValue &= ~dwMask; } pIISObjs->IISValue.value_1.dwDWORD = dwFlagValue; pIISObjs->IISType = IIS_SYNTAX_ID_DWORD; szPropName = wchName; if (pIISObject) { IISTypeFreeIISObjects( pIISObject, 1 ); } } if (dwSyntaxId == IIS_SYNTAX_ID_BINARY) { hr = _pSchema->LookupFlagPropName(szPropName, (LPWSTR)wchName); BAIL_ON_FAILURE(hr); szPropName = wchName; } // // add the property to cache if not already in since DispatchAddProperty // does not addproperty // hr = findproperty( szPropName, &dwIndex ); if (FAILED(hr)) { hr = addproperty( szPropName, dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ? IIS_SYNTAX_ID_DWORD : dwSyntaxId, dwNumValues, pIISObjs ); BAIL_ON_FAILURE(hr); } // // update property value in cache // hr = putproperty( szPropName, CACHE_PROPERTY_MODIFIED, dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ? IIS_SYNTAX_ID_DWORD : dwSyntaxId, dwNumValues, pIISObjs ); BAIL_ON_FAILURE(hr); error: if (pIISObjs) { IISTypeFreeIISObjects( pIISObjs, dwNumValues ); } if (pVarArray) { DWORD i = 0; for (i = 0; i < dwNumValues; i++) { VariantClear(pVarArray + i); } FreeADsMem(pVarArray); } VariantClear(&vVar); RRETURN(hr); }