|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: cpropmgr.cxx
//
// Contents: Property manager - object that implements/helps implement
// IUMIPropList functions.
// The property manager needs to be initialized in one of 2 modes
// 1) PropertyCache mode in which case it uses the objects existing
// to provide IUMIPropList support and
// 2) Interface property mode in which case ???
//
// Functions: TBD.
//
// History: 02-07-00 AjayR Created.
//
//----------------------------------------------------------------------------
#include "ldap.hxx"
//
// These are global utility fucntions. Might be worth moving to a
// better location subsequently.
//
//+---------------------------------------------------------------------------
// Function: FreeOneUmiProperty -- Global scope.
//
// Synopsis: Walk through and free all information being pointed to
// including the values.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT FreeOneUmiProperty(UMI_PROPERTY umiProperty) { //
// Free the name now if we can
//
if (umiProperty.pszPropertyName) { FreeADsStr(umiProperty.pszPropertyName); umiProperty.pszPropertyName = NULL; }
if (!umiProperty.pUmiValue) { //
// We are done if count is 0
//
if (umiProperty.uCount == 0) { RRETURN(S_OK); } else { RRETURN(E_ADS_BAD_PARAMETER); } }
//
// Must have valid umiValues at this point.
//
for (ULONG ulCtr = 0; ulCtr < umiProperty.uCount; ulCtr++) {
switch (umiProperty.uType) {
case UMI_TYPE_LPWSTR: //
// Go through and free each of the values.
//
if (umiProperty.pUmiValue->pszStrValue[ulCtr]) { FreeADsStr(umiProperty.pUmiValue->pszStrValue[ulCtr]); umiProperty.pUmiValue->pszStrValue[ulCtr] = NULL; } break;
case UMI_TYPE_BOOL: case UMI_TYPE_I4: case UMI_TYPE_FILETIME: case UMI_TYPE_SYSTEMTIME: case UMI_TYPE_I8: //
// In all these cases nothing much to free except the value array
//
break;
case UMI_TYPE_OCTETSTRING: //
// Go through and free each of the values.
//
if (umiProperty.pUmiValue->octetStr[ulCtr].lpValue) { FreeADsMem(umiProperty.pUmiValue->octetStr[ulCtr].lpValue); umiProperty.pUmiValue->octetStr[ulCtr].lpValue = NULL; } break;
case UMI_TYPE_IUNKNOWN: //
// Need to release the ptr and Free the riid.
//
UMI_COM_OBJECT ComObject;
if (umiProperty.pUmiValue->comObject) { ComObject = umiProperty.pUmiValue->comObject[ulCtr]; if (ComObject.pInterface) { ((IUnknown*)ComObject.pInterface)->Release(); ComObject.pInterface = NULL; }
if (ComObject.priid) { FreeADsMem((void *)ComObject.priid); ComObject.priid = NULL; } }
break;
default: //
// UmiType that we do not know anything about ??
//
ADsAssert(!"Unknown umitype in free memory"); RRETURN(E_ADS_BAD_PARAMETER); break; } // end of case
} // end of for
//
// Free the array of values now
//
if (umiProperty.pUmiValue) { FreeADsMem( (void *)umiProperty.pUmiValue); umiProperty.pUmiValue = NULL; }
RRETURN(S_OK); }
//+---------------------------------------------------------------------------
// Function: FreeUmiPropertyValues -- Global scope.
//
// Synopsis: Walk through and free all information being pointed to
// including the values.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT FreeUmiPropertyValues(UMI_PROPERTY_VALUES *pUmiProps) { HRESULT hr = S_OK;
if (pUmiProps) { __try { //
// Go through and free each property in the list
//
for (ULONG ulCtr = 0; ulCtr < pUmiProps->uCount; ulCtr++) {
hr = FreeOneUmiProperty(pUmiProps->pPropArray[ulCtr]);
}
//
// Free the inner array.
//
if (pUmiProps->pPropArray) { FreeADsMem(pUmiProps->pPropArray); }
//
// Free the array itself.
//
FreeADsMem( (LPVOID) pUmiProps); } __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_INVALIDARG; } } else { hr = E_INVALIDARG; }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertUmiPropCodeToLdapCode -- Global scope.
//
// Synopsis: Convert the property code appropriately.
//
// Arguments: umiFlags - the umiPropCode,
// dwLdapOpCode& - byRef return value.
//
// Returns: HRESULT - S_OK or E_ADS_BAD_PARAMETER
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT ConvertUmiPropCodeToLdapCode(ULONG umiFlags, DWORD& dwLdapOpCode) { HRESULT hr = S_OK;
switch (umiFlags) { case UMI_OPERATION_APPEND: dwLdapOpCode = PROPERTY_ADD; break; case UMI_OPERATION_UPDATE: dwLdapOpCode = PROPERTY_UPDATE; break;
case UMI_OPERATION_EMPTY: dwLdapOpCode = PROPERTY_DELETE; break; case UMI_OPERATION_DELETE_ALL_MATCHES: dwLdapOpCode = PROPERTY_DELETE_VALUE; break;
default: //
// we do not handle these values.
// UMI_OPERATION_INSERT_AT
// UMI_OPERATION_REMOVE_AT
// UMI_OPERATION_DELETE_AT
// UMI_OPERATION_DELETE_FIRST_MATCH
// UMI_OPERATION_DELETE_ALL_MATCHES
//
hr = UMI_E_UNSUPPORTED_OPERATION; break; }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertLdapCodeToUmiPropCode -- Global scope.
//
// Synopsis: Convert the property code appropriately.
//
// Arguments: dwLdapOpCode& - property cache operation code.
// umiFlags& - byRef return value.
//
// Returns: HRESULT - S_OK or E_ADS_BAD_PARAMETER
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT ConvertLdapCodeToUmiPropCode( DWORD dwLdapCode, ULONG &uUmiFlags ) {
HRESULT hr = S_OK;
switch (dwLdapCode) { case PROPERTY_ADD: uUmiFlags = UMI_OPERATION_APPEND; break; case PROPERTY_UPDATE: uUmiFlags = UMI_OPERATION_UPDATE; break;
case PROPERTY_DELETE: uUmiFlags = UMI_OPERATION_EMPTY; break; case PROPERTY_DELETE_VALUE: uUmiFlags = UMI_OPERATION_DELETE_ALL_MATCHES; break;
case 0: //
// special case values that are just in the cache.
//
uUmiFlags = 0; break;
default: hr = E_ADS_BAD_PARAMETER; break; }
RRETURN(hr); }
//****************************************************************************
//
//Internal helpers - restricted scope
//
//****************************************************************************
//+---------------------------------------------------------------------------
// Function: ConvertVariantLongToUmiProp.
//
// Synopsis: Convert the variant to a corresponding UmiProp.
//
// Arguments: vVariant - variant containg long val to convert.
// ppProp - Output UmiPropertyValues.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *pProp to point to valid UMI_PROPERTY_VALUES.
//
//----------------------------------------------------------------------------
HRESULT ConvertVariantLongToUmiProp( VARIANT vVariant, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = S_OK; LONG *pLArray = NULL;
*ppProp = (PUMI_PROPERTY_VALUES) AllocADsMem(sizeof(UMI_PROPERTY_VALUES));
if (!*ppProp) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
(*ppProp)->pPropArray = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY));
if (!((*ppProp)->pPropArray)) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
(*ppProp)->uCount = 1;
(*ppProp)->pPropArray[0].uType = UMI_TYPE_I4; (*ppProp)->pPropArray[0].uCount = 1; pLArray = (LONG *) AllocADsMem(sizeof(LONG) * 1);
if (!pLArray) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
pLArray[0] = vVariant.lVal;
(*ppProp)->pPropArray[0].pUmiValue = (UMI_VALUE *)(void *)pLArray;
error :
if (FAILED(hr)) { if (pLArray) { FreeADsMem( (void*) pLArray); } FreeUmiPropertyValues(*ppProp); }
RRETURN(hr); }
HRESULT GetEmptyLPWSTRProp(UMI_PROPERTY_VALUES **ppProp) { HRESULT hr = S_OK; *ppProp = (PUMI_PROPERTY_VALUES) AllocADsMem(sizeof(UMI_PROPERTY_VALUES));
if (!*ppProp) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
(*ppProp)->pPropArray = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY));
if (!((*ppProp)->pPropArray)) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
(*ppProp)->uCount = 1;
(*ppProp)->pPropArray[0].uType = UMI_TYPE_LPWSTR; (*ppProp)->pPropArray[0].uCount = 0; (*ppProp)->pPropArray[0].pUmiValue = NULL;
error :
if (FAILED(hr)) { FreeUmiPropertyValues(*ppProp); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertBSTRToUmiProp.
//
// Synopsis: Convert the bstr to a corresponding UmiProp.
//
// Arguments: bstrStringVal - String to convert to umi values.
// ppProp - Output UmiPropertyValues.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *pProp to point to valid UMI_PROPERTY_VALUES.
//
//----------------------------------------------------------------------------
HRESULT ConvertBSTRToUmiProp( BSTR bstrStringVal, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = S_OK; LPWSTR * pszStrArray = NULL; LPWSTR pszTmpStr = NULL;
*ppProp = (PUMI_PROPERTY_VALUES) AllocADsMem(sizeof(UMI_PROPERTY_VALUES));
if (!*ppProp) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
(*ppProp)->pPropArray = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY));
if (!((*ppProp)->pPropArray)) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } (*ppProp)->uCount = 1;
(*ppProp)->pPropArray[0].uType = UMI_TYPE_LPWSTR; (*ppProp)->pPropArray[0].uCount = 1; pszStrArray = (LPWSTR *) AllocADsMem(sizeof(LPWSTR) * 1);
if (!pszStrArray) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// If the value is NULL, then we return an array with a NULL
// value as the result.
//
if (bstrStringVal) { pszStrArray[0] = AllocADsStr(bstrStringVal); if (!pszStrArray[0]) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } }
(*ppProp)->pPropArray[0].pUmiValue = (UMI_VALUE *)(void *)pszStrArray;
error :
if (FAILED(hr)) { if (pszStrArray) { FreeADsMem( (void*) pszStrArray); } FreeUmiPropertyValues(*ppProp); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertIUnkToUmiProp.
//
// Synopsis: Convert the IUnk to a corresponding UmiProp.
//
// Arguments: pUnk - IUnk ptr.
// iid - iid of the ptr.
// ppProp - Output UmiPropertyValues.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *pProp to point to valid UMI_PROPERTY_VALUES.
//
//----------------------------------------------------------------------------
HRESULT ConvertIUnkToUmiProp( IUnknown * pUnk, IID iid, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = S_OK; PUMI_COM_OBJECT pComObjArray = NULL;
*ppProp = (PUMI_PROPERTY_VALUES) AllocADsMem(sizeof(UMI_PROPERTY_VALUES));
if (!*ppProp) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
(*ppProp)->pPropArray = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY));
if (!((*ppProp)->pPropArray)) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } (*ppProp)->uCount = 1;
(*ppProp)->pPropArray[0].uType = UMI_TYPE_IUNKNOWN; (*ppProp)->pPropArray[0].uCount = 1; pComObjArray = (PUMI_COM_OBJECT) AllocADsMem(sizeof(UMI_COM_OBJECT) * 1);
if (!pComObjArray) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
hr = pUnk->QueryInterface( iid, (void **) &(pComObjArray[0].pInterface) ); BAIL_ON_FAILURE(hr);
pComObjArray[0].priid = (IID *) AllocADsMem(sizeof(IID)); if (!pComObjArray[0].priid) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
memcpy(pComObjArray[0].priid, &iid, sizeof(IID));
(*ppProp)->pPropArray[0].pUmiValue = (UMI_VALUE *)(void *)pComObjArray;
error :
if (FAILED(hr)) { if (pComObjArray) { if (pComObjArray[0].pInterface) { ((IUnknown *)pComObjArray[0].pInterface)->Release(); } FreeADsMem( (void*) pComObjArray); } FreeUmiPropertyValues(*ppProp); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: HelperGetUmiRelUrl.
//
// Synopsis: Gets the __RELURL property for the object. This routine
// combines the IADs::get_Name and IADs::get_Class
//
// Arguments: pIADs - Pointer to obj implementing IADs.
// bstrRetVal - Pointer for retrun bstr value.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *pProp to point to valid UMI_PROPERTY_VALUES.
//
//----------------------------------------------------------------------------
HRESULT HelperGetUmiRelUrl( IADs * pIADs, BSTR * bstrRetVal ) { HRESULT hr = S_OK; BSTR bstrName = NULL, bstrClass = NULL; LPWSTR pszTempVal = NULL; BOOL fSchemaObject = FALSE;
hr = pIADs->get_Name(&bstrName); BAIL_ON_FAILURE(hr);
hr = pIADs->get_Class(&bstrClass); BAIL_ON_FAILURE(hr);
//
// See if this is a schema object.
//
if (!_wcsicmp(bstrClass, L"Schema") || !_wcsicmp(bstrClass, L"Class") || !_wcsicmp(bstrClass, L"Property") ) { LPWSTR pszTemp; //
// If this is indeed a schema object then the name
// wont have any = sign in it. Equal is not allowed
// in the names of schema objects.
//
if ((pszTemp = wcschr(bstrName, L'=')) == NULL) fSchemaObject = TRUE; }
//
// Add 2 as we need 1 for the \0 and the other for the .
// in class.name
//
DWORD dwLen; dwLen = wcslen(bstrName) + wcslen(bstrClass) + 2;
if (fSchemaObject) { //
// Need to add space for .Name
//
dwLen = dwLen + 6;
}
pszTempVal = (LPWSTR) AllocADsMem(dwLen * sizeof(WCHAR));
if (!pszTempVal) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
if (!fSchemaObject) { wsprintf(pszTempVal, L"%s.%s", bstrClass, bstrName); } else { wsprintf(pszTempVal, L"%s.Name=%s", bstrClass, bstrName); }
hr = ADsAllocString(pszTempVal, bstrRetVal);
BAIL_ON_FAILURE(hr);
error:
if (bstrName) { SysFreeString(bstrName); }
if (bstrClass) { SysFreeString(bstrClass); }
if (pszTempVal) { FreeADsStr(pszTempVal); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: HelperGetUmiSchemaContainerPath.
//
// Synopsis: Gets the Umi path to the schema container for this object.
//
// Arguments: pIADs - Pointer to obj implementing IADs.
// bstrRetVal - Pointer for retrun bstr value.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *bstrRetVal points to the correct schema path.
//
//----------------------------------------------------------------------------
HRESULT HelperGetUmiSchemaContainerPath( IADs * pIADs, BSTR * bstrRetVal ) { HRESULT hr = S_OK; BSTR bstrSchema = NULL; LPWSTR pszParent = NULL, pszCN = NULL, pszUmiSchema = NULL;
//
// First we need the path of the schema object itslef.
//
hr = pIADs->get_Schema(&bstrSchema); BAIL_ON_FAILURE(hr);
//
// Now we can build the path to the schema container from the path.
//
hr = BuildADsParentPath( bstrSchema, &pszParent, &pszCN ); BAIL_ON_FAILURE(hr);
hr = ADsPathToUmiURL(pszParent, &pszUmiSchema);
BAIL_ON_FAILURE(hr); hr = ADsAllocString(pszUmiSchema, bstrRetVal);
BAIL_ON_FAILURE(hr);
error:
if (bstrSchema) { SysFreeString(bstrSchema); }
if (pszCN) { FreeADsStr(pszCN); }
if (pszParent) { FreeADsStr(pszParent); }
if (pszUmiSchema) { FreeADsStr(pszUmiSchema); } RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: HelperGetUmiDerivedFrom.
//
// Synopsis: Gets the value of the class that the current class object
// is derived from.
//
// Arguments: pIADs - Pointer to obj implementing IADs.
// bstrRetVal - Pointer for retrun bstr value.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *bstrRetVal points to the correct schema path.
//
//----------------------------------------------------------------------------
HRESULT HelperGetUmiDerivedFrom( IADs * pIADs, BSTR * pbstrRetVal ) { HRESULT hr = S_OK; IADsClass *pClass = NULL; BSTR bstrName = NULL; VARIANT vVariant;
VariantInit(&vVariant); *pbstrRetVal = NULL;
hr = pIADs->get_Name(&bstrName); BAIL_ON_FAILURE(hr);
//
// If the class is Top then we just return NULL.
//
if (_wcsicmp(bstrName, L"Top")) { //
// Get the IADsClass interface, this is done because IADs::Get
// will need to ask for different attributes based on the server.
// IADsClass encapsulates this difference for us.
//
hr = pIADs->QueryInterface(IID_IADsClass, (void **) &pClass); if (FAILED(hr)) { BAIL_ON_FAILURE(hr = E_FAIL); } hr = pClass->get_DerivedFrom(&vVariant); BAIL_ON_FAILURE(hr); ADsAssert(vVariant.vt == VT_BSTR); hr = ADsAllocString(vVariant.bstrVal, pbstrRetVal); } BAIL_ON_FAILURE(hr);
error:
VariantClear(&vVariant);
if (bstrName) { SysFreeString(bstrName); }
if (pClass) { pClass->Release(); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: HelperConvertNameToKey.
//
// Synopsis: Converts the value of the BSTR (of the form cn=test) to cn
// as required by UMI.
//
// Arguments: bstrName - Value to get the key from.
// pszUmiKey - Return value for the key.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *pszUmiUrl points to the key.
//
//----------------------------------------------------------------------------
HRESULT HelperConvertNameToKey( BSTR bstrName, LPWSTR * pszUmiUrl ) { HRESULT hr = S_OK; LPWSTR pszTemp = bstrName; BOOL fEqualFound = FALSE; DWORD dwCount = 0;
ADsAssert(bstrName && pszTemp && *pszTemp);
while (pszTemp && *pszTemp && (!fEqualFound) ) { if (*pszTemp == L'=') { fEqualFound = TRUE; } dwCount++; pszTemp++; }
if (!fEqualFound) { BAIL_ON_FAILURE(hr = E_ADS_PROPERTY_NOT_FOUND); }
*pszUmiUrl = (LPWSTR) AllocADsMem(dwCount * sizeof(WCHAR)); if (!*pszUmiUrl) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
wcsncpy(*pszUmiUrl, bstrName, (dwCount-1));
error:
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: HelperUpdateSDFlags.
//
// Synopsis: On put/get calls updates the security flags appropriately.
//
// Arguments: pIADs - IADs pointer to use to update sd.
// uFlags - Flags to use for getting SD.
// pfUpdated - Return boolean value.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: Underlying property cache and pfUpdated to TRUE if the
// flags on the object had to be changed and FALSE otherwise.
//
//----------------------------------------------------------------------------
HRESULT HelperUpdateSDFlags( IADs *pIADs, ULONG uFlags, BOOL *pfUpdated = NULL ) { HRESULT hr = S_OK; IADsObjOptPrivate *pPrivOpt = NULL; SECURITY_INFORMATION secInfo;
ADsAssert(pIADs);
if (pfUpdated) { *pfUpdated = FALSE; }
//
// Get the objOpt intf and make sure the flags are right.
//
hr = pIADs->QueryInterface(IID_IADsObjOptPrivate, (void **) &pPrivOpt); BAIL_ON_FAILURE(hr);
hr = pPrivOpt->GetOption( LDAP_SECURITY_MASK, (void *) &secInfo ); BAIL_ON_FAILURE(hr);
if (secInfo != uFlags) { //
// We need to update the security mask on the object.
//
hr = pPrivOpt->SetOption( LDAP_SECURITY_MASK, (void **) &uFlags ); BAIL_ON_FAILURE(hr); //
// Need to let caller know that the flags have changed.
//
if (pfUpdated) { *pfUpdated = TRUE; } }
error:
if (pPrivOpt) { pPrivOpt->Release(); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: HelperGetSDIntoCache.
//
// Synopsis: Reads the sd into the property cache using the appropriate
// flags as needed.
//
// Arguments: pIADs - IADs pointer to use to update sd.
// uFlags - Flags to use for getting SD.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: Underlying property cache.
//
//----------------------------------------------------------------------------
HRESULT HelperGetSDIntoCache( IADs * pIADs, ULONG uFlags ) { HRESULT hr = S_OK; VARIANT vVar; BOOL fUpdated = FALSE; LPWSTR szSecDesc[] = {L"ntSecurityDescriptor"};
VariantInit(&vVar);
hr = HelperUpdateSDFlags( pIADs, (uFlags & UMI_SECURITY_MASK), &fUpdated ); BAIL_ON_FAILURE(hr);
if (fUpdated) { //
// Update just the SD by calling GetInfoEx.
//
hr = ADsBuildVarArrayStr( szSecDesc, 1, &vVar ); BAIL_ON_FAILURE(hr);
hr = pIADs->GetInfoEx(vVar, 0); BAIL_ON_FAILURE(hr); }
error :
VariantClear(&vVar);
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: HelperGetOrigin.
//
// Synopsis: Gets the originating class for the property in question.
//
// Arguments: pIADs - IADs pointer to backing object.
// pszName - Name of the property whose origin is needed.
// ppProp - Return value.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT HelperGetOrigin( IADs *pIADs, LPCWSTR pszName, UMI_PROPERTY_VALUES **ppProp ) { HRESULT hr = S_OK; IADsUmiHelperPrivate *pHelper = NULL; BSTR bstrVal = NULL;
hr = pIADs->QueryInterface( IID_IADsUmiHelperPrivate, (void **) &pHelper ); if (FAILED(hr)) { //
// This object does not support this property as it is not
// a class object.
//
BAIL_ON_FAILURE(hr = E_ADS_PROPERTY_NOT_FOUND); }
hr = pHelper->GetOriginHelper( pszName, &bstrVal ); BAIL_ON_FAILURE(hr);
hr = ConvertBSTRToUmiProp( bstrVal, ppProp ); error: if (bstrVal) { SysFreeString(bstrVal); }
if (pHelper) { pHelper->Release(); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CopyUmiProperty.
//
// Synopsis: Copy the input value into a newly allocated output buffer.
// Note that since this is an internal routine assumptions are made
// as to the data. Currently handles only UMI_TYPE_LPWSTR,
// UMI_TYPE_I4 and UMI_TYPE_BOOL. If multivalued, we can only copy
// strings (things like filter on enum can be multi-valued).
//
// Arguments: umiProp - Umi property value to copy.
// ppUmiProp - Return value for new umi property.
//
// Returns: HRESULT - S_OK or any failure ecode.
//
// Modifies: *ppUmiProp to point to valid UMI_PROPERTY.
//
//----------------------------------------------------------------------------
HRESULT CopyUmiProperty( UMI_PROPERTY umiProp, PUMI_PROPERTY *ppUmiProp ) { HRESULT hr = S_OK; UMI_PROPERTY *pUmiPropLocal = NULL; ULONG ulUmiType = umiProp.uType; ULONG ulPropCount = umiProp.uCount;
*ppUmiProp = NULL;
//
// Multi valued has to be string.
//
if ((ulPropCount > 1) && (ulUmiType != UMI_TYPE_LPWSTR)) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
pUmiPropLocal = (UMI_PROPERTY *) AllocADsMem(sizeof(UMI_PROPERTY));
if (!pUmiPropLocal) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
pUmiPropLocal->pszPropertyName = AllocADsStr(umiProp.pszPropertyName); if (!pUmiPropLocal->pszPropertyName) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
pUmiPropLocal->uOperationType = umiProp.uOperationType; pUmiPropLocal->uType = umiProp.uType;
switch (umiProp.uType) { case UMI_TYPE_LPWSTR : LPWSTR *pszTmpArray; pszTmpArray = (LPWSTR *) AllocADsMem(sizeof(LPWSTR) * ulPropCount); if (!pszTmpArray) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
for (DWORD dwCtr = 0; dwCtr < ulPropCount; dwCtr++) { pszTmpArray[dwCtr] = AllocADsStr( umiProp.pUmiValue->pszStrValue[dwCtr] ); if (!pszTmpArray[dwCtr]) { //
// NULL is allowed as a value only if it is the
// only value being set.
//
if (ulPropCount != 1 || umiProp.pUmiValue->pszStrValue[dwCtr] ) { //
// Cleanup and exit.
//
for (DWORD dwCtr2 = 0; dwCtr2 < dwCtr; dwCtr2++) { if (pszTmpArray[dwCtr2]) { FreeADsStr(pszTmpArray[dwCtr2]); pszTmpArray[dwCtr2] = NULL; } } FreeADsMem(pszTmpArray); pszTmpArray = NULL; BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } } // if alloc failed in middle of array.
} pUmiPropLocal->pUmiValue = (PUMI_VALUE) (void *) pszTmpArray; break;
case UMI_TYPE_I4: LONG *pLongArray;
pLongArray = (LONG *) AllocADsMem(sizeof(LONG) * 1); if (!pLongArray) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
pLongArray[0] = umiProp.pUmiValue->lValue[0]; pUmiPropLocal->pUmiValue = (PUMI_VALUE) (void *) pLongArray; break;
case UMI_TYPE_BOOL: BOOL *pBoolArray;
pBoolArray = (BOOL *) AllocADsMem(sizeof(BOOL) * 1); if (!pBoolArray) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
pBoolArray[0] = umiProp.pUmiValue->bValue[0]; pUmiPropLocal->pUmiValue = (PUMI_VALUE) (void *) pBoolArray; break;
default: BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); break;
}
pUmiPropLocal->uCount = ulPropCount; *ppUmiProp = pUmiPropLocal;
RRETURN(hr);
error: //
// Cleanup cause we hit an error.
//
if (pUmiPropLocal) { FreeOneUmiProperty(*pUmiPropLocal); FreeADsMem( (void*) pUmiPropLocal); }
RRETURN(hr); }
//****************************************************************************
//
//CPropertyManager Methods.
//
//****************************************************************************
//+---------------------------------------------------------------------------
// Function: CPropertyManager::CPropertyManager
//
// Synopsis: Constructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CPropertyManager::CPropertyManager(): _dwMaxProperties(0), _pPropCache(NULL), _pIntfProperties(NULL), _dwMaxLimit(0), _fPropCacheMode(TRUE), _pStaticPropData(NULL), _ulStatus(0), _pIADs(NULL), _pUnk(NULL), _pCreds(NULL), _pszServerName(NULL) { }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::~CPropertyManager
//
// Synopsis: Destructor
//
// Arguments: None
//
// Returns: N/A
//
// Modifies: N/A
//
//----------------------------------------------------------------------------
CPropertyManager::~CPropertyManager() { //
// Need to cleanup inftProps table
//
if (_pIntfProperties) { DWORD dwCtr; for (dwCtr = 0; dwCtr < _dwMaxProperties; dwCtr++) { //
// Free each of the entries and their contents.
//
PINTF_PROPERTY pIntfProp = &(_pIntfProperties[dwCtr]);
if (pIntfProp->pszPropertyName) { FreeADsStr(pIntfProp->pszPropertyName); pIntfProp->pszPropertyName = NULL; }
if (pIntfProp->pUmiProperty) { FreeOneUmiProperty(*(pIntfProp->pUmiProperty)); FreeADsMem(pIntfProp->pUmiProperty); pIntfProp->pUmiProperty = NULL; } } FreeADsMem(_pIntfProperties); }
_pIntfProperties = NULL;
//
// The rest of the stuff is taken care of when the
// destructor to the IADs obj is called. This object
// itself will be released only in the destructor of the
// IADs object is called.
//
_pPropCache = NULL; if (_pIADs) { _pIADs->Release(); }
_pIADs = NULL; _dwMaxProperties = 0;
//
// Do not free as these are owned by the owning object.
//
_pszServerName = NULL; _pCreds = NULL; _pUnk = NULL;
}
//+---------------------------------------------------------------------------
// Function: CPropertyManager::CreatePropertyManager (overloaded)
//
// Synopsis: Static allocation routine (property cache mode).
//
// Arguments: IADs* - pointer to IADs implementor object.
// pUnk - owning object unknown.
// pPropCache - pointer to propertyCache used by object.
// pCredentials - pointer to credentials.
// pszServerName - pointer to servername.
// ppPropertyManager - return ptr for new prop mgr.
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: CPropertyManager ** - ptr to newly created object.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::CreatePropertyManager( IADs *pADsObj, IUnknown *pUnk, CPropertyCache *pPropCache, CCredentials *pCredentials, LPWSTR pszServerName, CPropertyManager FAR * FAR * ppPropertyManager ) { CPropertyManager FAR * pPropMgr = NULL;
pPropMgr = new CPropertyManager();
if (!pPropMgr) { RRETURN_EXP_IF_ERR(E_OUTOFMEMORY); }
if (pADsObj) { pADsObj->QueryInterface(IID_IADs, (void**) &(pPropMgr->_pIADs)); }
pPropMgr->_pUnk = pUnk; pPropMgr->_pPropCache = pPropCache; pPropMgr->_fPropCacheMode = TRUE; pPropMgr->_pIntfProperties = NULL; pPropMgr->_pszServerName = pszServerName; pPropMgr->_pCreds = pCredentials;
*ppPropertyManager = pPropMgr;
RRETURN(S_OK); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::CreatePropertyManager (overloaded)
//
// Synopsis: Static allocation routine (interface properties mode).
//
// Arguments: pUnk - pointer to owner (umi) object.
// pIADs - pointer to IADs implementor.
// pCredentials - pointer to credentials.
// pTable - property table.
// ppPropertyManager - return value for new prop mgr.
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: CPropertyManager ** - ptr to newly created object.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::CreatePropertyManager( IUnknown *pUnk, IUnknown *pIADs, CCredentials *pCredentials, INTF_PROP_DATA pTable[], CPropertyManager FAR * FAR * ppPropertyManager ) { CPropertyManager FAR * pPropMgr = NULL;
pPropMgr = new CPropertyManager();
if (!pPropMgr) { RRETURN_EXP_IF_ERR(E_OUTOFMEMORY); }
pPropMgr->_pUnk = pUnk; //
// We can ignore any failures here.
//
if (pIADs) { pIADs->QueryInterface(IID_IADs, (void**) &(pPropMgr->_pIADs)); }
pPropMgr->_pPropCache = NULL; pPropMgr->_fPropCacheMode = FALSE; pPropMgr->_pIntfProperties = NULL; pPropMgr->_pCreds = pCredentials; pPropMgr->_pStaticPropData = pTable;
*ppPropertyManager = pPropMgr;
RRETURN(S_OK); }
STDMETHODIMP CPropertyManager::QueryInterface(REFIID iid, LPVOID FAR* ppv) { HRESULT hr = S_OK;
SetLastStatus(0); if (ppv == NULL) { RRETURN(E_POINTER); }
if (IsEqualIID(iid, IID_IUnknown)){ *ppv = (IUnknown FAR *) this; } else if (IsEqualIID(iid, IID_IUmiPropList)) { *ppv = (IUmiPropList FAR *) this; } else { *ppv = NULL; SetLastStatus(E_NOINTERFACE); return E_NOINTERFACE; } AddRef(); return NOERROR; }
//
// Methods defined on the proplist interface.
//
//+---------------------------------------------------------------------------
// Function: CPropertyManager::Put (IUmiPropList support).
//
// Synopsis: Sets the value for the attribute in the cache.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: PropertyCache or internal interface property list.
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::Put( IN LPCWSTR pszName, IN ULONG uFlags, IN UMI_PROPERTY_VALUES *pProp ) { HRESULT hr = S_OK; LDAPOBJECTARRAY ldapDestObjects; DWORD dwOperationFlags = 0; BOOL fSecurityFlags = FALSE; IUmiObject *pUmiObj = NULL; BOOL fInternalPut = FALSE;
SetLastStatus(0);
//
// Initialize so that we are not trying to free junk.
//
if (_fPropCacheMode) { LDAPOBJECTARRAY_INIT(ldapDestObjects); }
//
// Pre process and pull out the highest flag, all these
// because we are not allowed to support Put with 0.
//
if (uFlags & 0x8000000) { uFlags &= 0x4000000; fInternalPut = TRUE; }
if (uFlags > UMI_SECURITY_MASK) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); } if (!pProp || !pszName) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
if (uFlags & UMI_SECURITY_MASK) { fSecurityFlags = TRUE; }
//
// We support only putting one property at a time.
//
if (pProp->uCount != 1) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
//
// Make sure that the data passed in is correct.
//
if (!pProp->pPropArray || !pProp->pPropArray[0].pszPropertyName) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (_fPropCacheMode) { DWORD dwLdapSyntaxId = 1;
if (fInternalPut && pProp->pPropArray[0].uOperationType == 0) { dwOperationFlags = 0; } else { //
// Verify that the operationType is something we support.
//
hr = ConvertUmiPropCodeToLdapCode( pProp->pPropArray[0].uOperationType, dwOperationFlags ); BAIL_ON_FAILURE(hr); }
if (fSecurityFlags) { //
// Only this ntSecurityDescriptor can use the security flags.
//
if (_wcsicmp(L"ntSecurityDescriptor", pszName)) { BAIL_ON_FAILURE(hr = E_FAIL); } hr = HelperUpdateSDFlags( _pIADs, uFlags & UMI_SECURITY_MASK ); BAIL_ON_FAILURE(hr); }
//
// In this case we need to convert data to ldap values and
// store in cache.
//
hr = UmiTypeToLdapTypeCopy( *pProp, uFlags, &ldapDestObjects, dwLdapSyntaxId, // byRef
_pCreds, _pszServerName ); BAIL_ON_FAILURE(hr);
//
// PutpropertyExt will add to the cache if needed.
//
hr = _pPropCache->putpropertyext( (LPWSTR)pszName, dwOperationFlags, dwLdapSyntaxId, ldapDestObjects ); BAIL_ON_FAILURE(hr); } else { //
// Local cache for interface properties. Verify property is
// legal and update the local information accordingly.
//
if (VerifyIfValidProperty( pProp->pPropArray[0].pszPropertyName, pProp->pPropArray[0] ) ) {
if (fSecurityFlags || !_wcsicmp(pszName, L"__SECURITY_DESCRIPTOR") ) { //
// Make sure name is correct.
//
if (_wcsicmp(L"__SECURITY_DESCRIPTOR", pszName)) { BAIL_ON_FAILURE(hr = E_FAIL); } //
// We need turn around and call put on the owning object.
// This means we need to package the UMI_PROPERTY_VALUES
// accordingly.
//
UMI_PROPERTY pUmiProperty[] = { pProp->pPropArray[0].uType, pProp->pPropArray[0].uCount, pProp->pPropArray[0].uOperationType, L"ntSecurityDescriptor", pProp->pPropArray[0].pUmiValue };
UMI_PROPERTY_VALUES pUmiProp[] = {1, pUmiProperty};
hr = _pUnk->QueryInterface( IID_IUmiObject, (void **) &pUmiObj ); BAIL_ON_FAILURE(hr);
hr = pUmiObj->Put( L"ntSecurityDescriptor", uFlags, pUmiProp ); BAIL_ON_FAILURE(hr); } else { //
// We need to update this value in our cache
//
hr = AddProperty( pszName, pProp->pPropArray[0] ); BAIL_ON_FAILURE(hr); } } // not valid property.
else { BAIL_ON_FAILURE(hr = E_FAIL); } }
error :
//
// Free ldapDestObjects if applicable.
//
if (_fPropCacheMode) { LdapTypeFreeLdapObjects( &ldapDestObjects ); }
if (pUmiObj) { pUmiObj->Release(); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::Get (IUmiPropList support).
//
// Synopsis: Gets the value for the attribute. This will read data
// from the server as needed.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: UMI_PROPERTY_VALUES* has the values of the attribute.
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::Get( IN LPCWSTR pszName, IN ULONG uFlags, OUT UMI_PROPERTY_VALUES **pProp ) { HRESULT hr = S_OK; ULONG uUmiFlag; LDAPOBJECTARRAY ldapSrcObjects; BOOL fSecurityFlag = FALSE; BOOL fSchemaFlag = FALSE; IADsObjOptPrivate *pPrivOpt = NULL;
SetLastStatus(0);
LDAPOBJECTARRAY_INIT(ldapSrcObjects);
if (!pProp) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
*pProp = NULL; //
// Currently this is the highest flag we support.
//
if (uFlags > UMI_FLAG_PROPERTY_ORIGIN) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); } else if (uFlags & UMI_SECURITY_MASK) { fSecurityFlag = TRUE; } else if (uFlags == UMI_FLAG_PROPERTY_ORIGIN) { fSchemaFlag = TRUE; }
if (fSchemaFlag && fSecurityFlag) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } //
// Name cannot be NULL.
//
if (!pszName) { BAIL_ON_FAILURE(hr = E_INVALIDARG) }
//
// If this is Property Manager is for server properties.
//
if (_fPropCacheMode) {
DWORD dwSyntaxId; DWORD dwStatus; DWORD dwSecOptions; if (fSchemaFlag) { BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_FLAGS); } if (fSecurityFlag) { if (_wcsicmp(L"ntSecurityDescriptor", pszName)) { //
// Security flag used and attrib not securityDescriptor.
//
BAIL_ON_FAILURE(hr = E_FAIL); } else { //
// Valid flag we need to process the flags.
//
hr = HelperGetSDIntoCache( _pIADs, uFlags ); BAIL_ON_FAILURE(hr); } } //
// Object maybe unbound, so we should return no such prop if
// we get back E_ADS_OBJECT_UNBOUND.
//
hr = _pPropCache->getproperty( (LPWSTR)pszName, &dwSyntaxId, &dwStatus, &ldapSrcObjects ); if (hr == E_ADS_OBJECT_UNBOUND) { hr = E_ADS_PROPERTY_NOT_FOUND; }
BAIL_ON_FAILURE(hr);
hr = ConvertLdapCodeToUmiPropCode(dwStatus, uUmiFlag); BAIL_ON_FAILURE(hr); //
// Return error if provider cache is not set and
// the cache is dirty.
//
if (uUmiFlag && !(uFlags & UMI_FLAG_PROVIDER_CACHE)) { BAIL_ON_FAILURE(hr = UMI_E_SYNCHRONIZATION_REQUIRED); }
//
// At this point we might have ldapSrcObjects.pLdapObjects == NULL.
// Typically that would be for property delete operations.
//
hr = LdapTypeToUmiTypeCopy( ldapSrcObjects, pProp, dwStatus, dwSyntaxId, _pCreds, _pszServerName, uUmiFlag );
} else { //
// Property Manager is for interface properties.
//
DWORD dwIndex;
//
// If the schema flag is set then we need to get the origin
// and not the property itself.
//
if (fSchemaFlag) { hr = HelperGetOrigin( _pIADs, pszName, pProp );
} else { //
// Make sure this property is valid.
//
hr = GetIndexInStaticTable(pszName, dwIndex); // dwIndex is byRef
BAIL_ON_FAILURE(hr);
hr = GetInterfaceProperty( pszName, uFlags, pProp, dwIndex ); } }
BAIL_ON_FAILURE(hr);
//
// Stuff the name in the return value.
//
if (pProp && *pProp) { (*pProp)->pPropArray[0].pszPropertyName = AllocADsStr(pszName);
if (!(*pProp)->pPropArray[0].pszPropertyName) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } }
error:
if (_fPropCacheMode) { LdapTypeFreeLdapObjects(&ldapSrcObjects); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr);
if (pProp && *pProp) { this->FreeMemory(0, (void *) *pProp); *pProp = NULL; } }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetAt (IUmiPropList support).
//
// Synopsis: Used to get the value by index ???
//
// Arguments: Not implemented
//
//
// Returns: E_NOTIMPL
//
// Modifies: Not implemented
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::GetAt( IN LPCWSTR pszName, IN ULONG uFlags, IN ULONG uBufferLength, OUT LPVOID pExisitingMem ) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetAs (IUmiPropList support).
//
// Synopsis: Gets the value for the attribute in the specified format.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: UMI_PROPERTY_VALUES* has the values of the attribute.
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::GetAs( IN LPCWSTR pszName, IN ULONG uFlags, IN ULONG uCoercionType, IN OUT UMI_PROPERTY_VALUES **pProp ) { HRESULT hr = S_OK; LDAPOBJECTARRAY ldapSrcObjects; LDAPOBJECTARRAY ldapSrcObjectsTmp; LDAPOBJECTARRAY * pldapObjects = NULL; ULONG uUmiFlag; DWORD dwSyntaxId, dwStatus, dwRequestedSyntax; DWORD dwCachedSyntax, dwUserSyntax;
SetLastStatus(0);
LDAPOBJECTARRAY_INIT(ldapSrcObjects); LDAPOBJECTARRAY_INIT(ldapSrcObjectsTmp);
if (!pszName || !pProp) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// Has to be in prop cache mode.
//
if (!_fPropCacheMode || !_pPropCache) { BAIL_ON_FAILURE(hr = E_NOTIMPL); }
if (uFlags > UMI_SECURITY_MASK) { BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_FLAGS); }
if (uFlags & UMI_SECURITY_MASK) { //
// Make sure it is the SD they are interested in.
//
if (_wcsicmp(L"ntSecurityDescriptor", pszName)) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } //
// At this point we need to get the SD in the cache.
//
hr = HelperGetSDIntoCache(_pIADs, uFlags); BAIL_ON_FAILURE(hr); }
//
// Object maybe unbound, so we should return no such prop if
// we get back E_ADS_OBJECT_UNBOUND.
//
hr = _pPropCache->getproperty( (LPWSTR)pszName, &dwSyntaxId, &dwStatus, &ldapSrcObjects );
if (hr == E_ADS_OBJECT_UNBOUND) { hr = E_ADS_PROPERTY_NOT_FOUND; } BAIL_ON_FAILURE(hr);
//
// Get the appropriate umi code for the status.
//
hr = ConvertLdapCodeToUmiPropCode(dwStatus, uUmiFlag); BAIL_ON_FAILURE(hr);
//
// At this point we need to see if we can convert the data
// to the format requested. This code is similar to that in
// proplist.cxx GetPropertyItem but there appears to be no
// easy way to avoid this duplication.
//
dwCachedSyntax = dwSyntaxId;
//
// Need to take the requested type to ADs types and from there to
// ldap types.
//
hr = UmiTypeToLdapTypeEnum(uCoercionType, &dwUserSyntax); BAIL_ON_FAILURE(hr);
//
// We can convert to any requested type only if it is unknown.
//
if (dwCachedSyntax == LDAPTYPE_UNKNOWN) { dwRequestedSyntax = dwUserSyntax; } else if (dwCachedSyntax == dwUserSyntax) { //
// Easy one !
//
dwRequestedSyntax = dwCachedSyntax; } else { //
// This means we already have a type. In this case the only
// coercion we allows is SD to binary blob and vice-versa.
//
if ((dwCachedSyntax == LDAPTYPE_SECURITY_DESCRIPTOR) && (dwUserSyntax == LDAPTYPE_OCTETSTRING) ) { dwRequestedSyntax = dwUserSyntax; } else if ((dwCachedSyntax == LDAPTYPE_OCTETSTRING) && (dwUserSyntax == LDAPTYPE_SECURITY_DESCRIPTOR) ) { dwRequestedSyntax = dwUserSyntax; } else { BAIL_ON_FAILURE(hr = E_FAIL); } }
//
// If the data is in a state that needs conversion the fn will
// take care - note that if the source is already in the correct
// format then the HR will S_FALSE.
//
hr = LdapTypeBinaryToString( dwRequestedSyntax, &ldapSrcObjects, &ldapSrcObjectsTmp ); BAIL_ON_FAILURE(hr);
if (hr == S_OK) { pldapObjects = &ldapSrcObjectsTmp; } else { //
// We already have the data in the right format.
//
pldapObjects = &ldapSrcObjects; hr = S_OK; }
//
// Now that we have the correct data in pLdapObjects, we need
// to convert that to Umi Properties.
//
hr = LdapTypeToUmiTypeCopy( *pldapObjects, pProp, dwStatus, dwRequestedSyntax, _pCreds, _pszServerName, uUmiFlag ); BAIL_ON_FAILURE(hr);
//
// Stuff the name in the return value.
//
if (pProp) { (*pProp)->pPropArray[0].pszPropertyName = AllocADsStr(pszName);
if (!(*pProp)->pPropArray[0].pszPropertyName) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } }
error:
if (_fPropCacheMode) { LdapTypeFreeLdapObjects(&ldapSrcObjects); LdapTypeFreeLdapObjects(&ldapSrcObjectsTmp); }
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr);
if (pProp) { this->FreeMemory(0, (void *)*pProp); *pProp = NULL; } }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::FreeMemory (IUmiPropList support).
//
// Synopsis: Free memory pointed to. Note that the pointer should have
// originally come from a Get/GetAs call.
//
// Arguments: Ptr to data to be freed.
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: *pMem is of course freed.
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::FreeMemory( ULONG uReserved, LPVOID pMem ) { HRESULT hr = S_OK;
SetLastStatus(0);
if (uReserved) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (pMem) { //
// At this time this has to be a pUmiProperty. Ideally we should
// tag this in some way so that we can check to make sure.
//
hr = FreeUmiPropertyValues((UMI_PROPERTY_VALUES *)pMem); } else { hr = E_INVALIDARG; }
error:
if (FAILED(hr)) { SetLastStatus(hr); hr = MapHrToUmiError(hr); }
RRETURN(hr); } //+---------------------------------------------------------------------------
// Function: CPropertyManager::Delete (IUmiPropList support).
//
// Synopsis: Delete the named property from the cache.
//
// Arguments: pszName - Name of property to delete.
// uFlags - Standard flags parameter.
//
// Returns: E_NOTIMPL.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::Delete( IN LPCWSTR pszName, IN ULONG uFlags ) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetProps (IUmiPropList support).
//
// Synopsis: Gets the values for the attributes. This will read data
// from the server as needed.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: UMI_PROPERTY_VALUES* has the an array of values for the
// attributes. Note that there is no ordering specified
// for the return values.
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::GetProps( IN LPCWSTR* pszNames, IN ULONG uNameCount, IN ULONG uFlags, OUT UMI_PROPERTY_VALUES **pProps ) { HRESULT hr = S_OK;
if ((uFlags != UMI_FLAG_GETPROPS_NAMES) && (uFlags != UMI_FLAG_GETPROPS_SCHEMA) ) { BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS); }
//
// Currently we support only getting the names of all the properties.
//
if (pszNames || uNameCount || !pProps ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
*pProps = NULL;
if (_fPropCacheMode) { //
// Only UMI_FLAG_GETPROPS_NAMES is valid in this case.
//
if (uFlags != UMI_FLAG_GETPROPS_NAMES) { BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_FLAGS); }
hr = _pPropCache->GetPropertyNames(pProps); } else { //
// Need to see what type of flag it is and extra check needed,
// if this is UMI_FLAGS_GETPROPS_SCHEMA.
//
if (uFlags == UMI_FLAG_GETPROPS_SCHEMA) { LONG lVal; hr = GetLongProperty(L"__GENUS", &lVal); BAIL_ON_FAILURE(hr);
if (lVal != UMI_GENUS_CLASS) { BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_FLAGS); }
hr = GetPropertyNamesSchema(pProps); } else { //
// Need to do get our static list.
//
hr = this->GetPropertyNames(pProps); } } // else for !propertyCacheMode.
error:
RRETURN(hr);
}
//+---------------------------------------------------------------------------
// Function: CPropertyManager::PutProps (IUmiPropList support).
//
// Synopsis: Puts the value for the attributes in the cache.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: Property cache for the object.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::PutProps( IN LPCWSTR* pszNames, IN ULONG uNameCount, IN ULONG uFlags, IN UMI_PROPERTY_VALUES *pProps ) { HRESULT hr = S_OK; //
// When done - should get and put multiple work directly of the server ?
// That would take care off problems like 5 can be put in the cache
// but sixth cannot ...
//
SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::PutFrom (IUmiPropList support).
//
// Synopsis: Clarify exactly what this is supposed to do ?
//
// Arguments: self explanatory
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: Property cache for the object.
//
//----------------------------------------------------------------------------
STDMETHODIMP CPropertyManager::PutFrom( IN LPCWSTR pszName, IN ULONG uFlags, IN ULONG uBufferLength, IN LPVOID pExistingMem ) { SetLastStatus(E_NOTIMPL); RRETURN(E_NOTIMPL); }
//
// PropertyManager methods that are not part of the IUmiPropList interface.
//
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetLastStatus
//
// Synopsis: Returns the error from the last operation on this object.
// For now only the status code is supported.
//
// Arguments: uFlags - Must be 0 for now.
// puSpecificStatus - Status is returned in this value.
// riid - IID requested on status obj.
// pStatusObj - Must be NULL for now.
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: *puSpecificStatus with last status code.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetLastStatus( ULONG uFlags, ULONG *puSpecificStatus, REFIID riid, LPVOID *pStatusObj ) { if (!puSpecificStatus || pStatusObj) { RRETURN(E_INVALIDARG); }
if (uFlags) { RRETURN(UMI_E_INVALID_FLAGS); }
*puSpecificStatus = _ulStatus;
RRETURN(S_OK);
}
//+---------------------------------------------------------------------------
// Function: CPropertyManager::AddProperty.
//
// Synopsis: Updates the value of the property to the interface
// property cache. This fn is called only in interface mode.
// If necessary the property will be added to the cache.
//
// Arguments: self explanatory
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: Changes the internal property table.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::AddProperty( LPCWSTR szPropertyName, UMI_PROPERTY umiProperty ) { HRESULT hr = S_OK; DWORD dwIndex = (DWORD) -1; BOOL fAddedName = FALSE;
//
// Make sure we do not have property in the cache.
//
hr = FindProperty(szPropertyName, &dwIndex);
if (FAILED(hr)) { //
// We actually need to add this property in our list.
//
hr = AddToTable(szPropertyName, &dwIndex);
fAddedName = TRUE; }
BAIL_ON_FAILURE(hr);
//
// At this point we can just dump the value into the cache.
//
hr = UpdateProperty( dwIndex, umiProperty );
BAIL_ON_FAILURE(hr);
error:
if (FAILED(hr) && fAddedName) { //
// Do we delete the name from the cache.
//
DeleteProperty(dwIndex); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::UpdateProperty.
//
// Synopsis: Updates the value of an interface property in the local cache.
// The assumption is that this function is only called with from
// AddProperty (or anywhere else where we have the correct index).
//
// Arguments: dwIndex - index in our table of the property to update
// UMI_PROPERTY - the value to add to our table, note that
// if the operation is delete we should remove the element
// from our table (value returned if any will be default value
// for subsequent get calls).
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: Underlying data in the cache is changed
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::UpdateProperty( DWORD dwIndex, UMI_PROPERTY umiProp ) { HRESULT hr = E_NOTIMPL; DWORD dwFlags, dwCacheSyntaxId, dwNumElements; PUMI_PROPERTY pUmiProperty = NULL;
if (!_pIntfProperties) { //
// Should we check the index ? It is after all an internal
// value, so it should not be wrong.
//
BAIL_ON_FAILURE(hr = E_FAIL); }
//
// Only update and delete are really supported.
//
if ((umiProp.uOperationType != UMI_OPERATION_UPDATE) && (umiProp.uOperationType != UMI_OPERATION_DELETE_ALL_MATCHES)) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (_pIntfProperties[dwIndex].pUmiProperty) { //
// Free the current data in the table and set initial values.
//
hr = FreeOneUmiProperty(*(_pIntfProperties[dwIndex].pUmiProperty)); BAIL_ON_FAILURE(hr);
FreeADsMem(_pIntfProperties[dwIndex].pUmiProperty);
_pIntfProperties[dwIndex].pUmiProperty = NULL; _pIntfProperties[dwIndex].dwFlags = 0; _pIntfProperties[dwIndex].dwSyntaxId = 0; }
//
// Copy the value to temp variable, so we can handle failures gracefully.
//
hr = CopyUmiProperty( umiProp, &pUmiProperty ); BAIL_ON_FAILURE(hr);
_pIntfProperties[dwIndex].pUmiProperty = pUmiProperty;
error:
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::FindProperty.
//
// Synopsis: Searches for the specified property in the local cache.
//
// Arguments: szPropertyName, name of property.
// pdwIndex - pointer to DWORD with index in table.
//
// Returns: HRESULT - S_OK or E_ADS_PROPERTY_NOT_FOUND.
//
// Modifies: *pdwIndex to.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::FindProperty( LPCWSTR szPropertyName, PDWORD pdwIndex ) { DWORD dwIndex;
if (!_pIntfProperties) { RRETURN(E_ADS_PROPERTY_NOT_FOUND); } for (dwIndex = 0; dwIndex < _dwMaxProperties; dwIndex++) { if (_wcsicmp( _pIntfProperties[dwIndex].pszPropertyName, szPropertyName ) == 0) { *pdwIndex = dwIndex; RRETURN(S_OK); } }
RRETURN(E_ADS_PROPERTY_NOT_FOUND); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::DeleteProperty.
//
// Synopsis: Deletes the property specified from the cahce.
//
// Arguments: Index to element to delete.
//
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: Underlying data in the cache is changed.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::DeleteProperty( DWORD dwIndex ) { HRESULT hr = S_OK; INTF_PROPERTY* pIntfProp = NULL;
if (_pIntfProperties && ((_dwMaxProperties-1) < dwIndex)) { //
// Valid property in cache.
//
pIntfProp = _pIntfProperties + dwIndex; ADsAssert(pIntfProp); if (pIntfProp->pszPropertyName) { FreeADsStr(pIntfProp->pszPropertyName); pIntfProp->pszPropertyName = NULL; } //
// Now Copy over the rest of the data here.
//
} else { hr = E_FAIL; }
RRETURN (hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::FlushPropertyCache.
//
// Synopsis: Clear all internal data in the property cache.
//
// Arguments:
//
// Returns: N/A
//
// Modifies: Underlying data in the cache is changed
//
//----------------------------------------------------------------------------
VOID CPropertyManager::flushpropertycache() { //
// Free any data in our table
if (_pIntfProperties) { for (DWORD dwCtr = 0; (dwCtr < _dwMaxProperties); dwCtr++) { INTF_PROPERTY *pIntfProp = (PINTF_PROPERTY)_pIntfProperties+ dwCtr; if (pIntfProp) { if (pIntfProp->pszPropertyName) { FreeADsStr(pIntfProp->pszPropertyName); pIntfProp->pszPropertyName = NULL; } } } //
// Now free the array of pointers.
//
FreeADsMem((void *) _pIntfProperties); _pIntfProperties = NULL; } }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::ClearAllPropertyFlags.
//
// Synopsis: Resets all property flags to zero.
//
// Arguments: None.
//
// Returns: HRESULT - S_OK or any failure error code.
//
// Modifies: Underlying data in the cache is changed.
//
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::ClearAllPropertyFlags( VOID ) { RRETURN(E_NOTIMPL); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetPropertyNames.
//
// Synopsis: Returns list of names of interface properties available.
//
// Arguments: out params only
//
// Returns: HRESULT - S_OK or any failure error code
//
// Modifies: ppStringsNames to point to valid array of strings.
// pUlCount to point to number of strings in the array.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetPropertyNames( PUMI_PROPERTY_VALUES *pUmiProps ) { HRESULT hr = S_OK; PUMI_PROPERTY_VALUES pUmiPropVals = NULL; PUMI_PROPERTY pUmiProperties = NULL; DWORD dwCtr, dwPropCount = 0;
pUmiPropVals = (PUMI_PROPERTY_VALUES) AllocADsMem( sizeof(UMI_PROPERTY_VALUES) );
if (!pUmiPropVals) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Need to count the properties.
//
while (_pStaticPropData[dwPropCount].pszPropertyName) { dwPropCount++; } if (!dwPropCount) { *pUmiProps = pUmiPropVals; RRETURN(S_OK); }
pUmiProperties = (PUMI_PROPERTY) AllocADsMem( sizeof(UMI_PROPERTY) * dwPropCount );
if (!pUmiProperties) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Need to go through the table and alloc the values.
//
for (dwCtr = 0; dwCtr < dwPropCount; dwCtr++) { pUmiProperties[dwCtr].pszPropertyName = AllocADsStr(_pStaticPropData[dwCtr].pszPropertyName);
if (!pUmiProperties[dwCtr].pszPropertyName) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } pUmiProperties[dwCtr].uType = UMI_TYPE_NULL; }
pUmiPropVals->pPropArray = pUmiProperties; pUmiPropVals->uCount = dwPropCount;
*pUmiProps = pUmiPropVals;
RRETURN(S_OK);
error :
if (pUmiProperties) { for (dwCtr = 0; dwCtr < dwPropCount; dwCtr++) { if (pUmiProperties[dwCtr].pszPropertyName) { FreeADsStr(pUmiProperties[dwCtr].pszPropertyName); } } FreeADsMem(pUmiProperties); }
if (pUmiPropVals) { FreeADsMem(pUmiPropVals); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetPropertyNamesSchema
//
// Synopsis: Returns list of the names and types of the properties this
// object can contain. Note that this method is valid only if the
// underlying object is an instance of class Class (schema class).
//
// Arguments: out params only
//
// Returns: HRESULT - S_OK or any failure error code
//
// Modifies:
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetPropertyNamesSchema( PUMI_PROPERTY_VALUES *pUmiProps ) { HRESULT hr = S_OK; IADsUmiHelperPrivate *pIADsUmiPriv = NULL; // Array of ptr to PROPERTYINFO
PPROPERTYINFO *pPropArray = NULL; DWORD dwPropCount = 0; PUMI_PROPERTY_VALUES pUmiPropVals = NULL; PUMI_PROPERTY pUmiProperties = NULL;
//
// Need a ptr to the helper routine.
//
hr = this->_pIADs->QueryInterface( IID_IADsUmiHelperPrivate, (void **) &pIADsUmiPriv );
if (hr == E_NOINTERFACE) { BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_FLAGS); }
hr = pIADsUmiPriv->GetPropertiesHelper( (void**) &pPropArray, &dwPropCount ); BAIL_ON_FAILURE(hr);
//
// Need to prepare the return values.
//
pUmiPropVals = (PUMI_PROPERTY_VALUES) AllocADsMem( sizeof(UMI_PROPERTY_VALUES) );
if (!pUmiPropVals) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
if (!dwPropCount) { *pUmiProps = pUmiPropVals; RRETURN(S_OK); }
pUmiProperties = (PUMI_PROPERTY) AllocADsMem( sizeof(UMI_PROPERTY) * dwPropCount );
if (!pUmiProperties) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } for (DWORD dwCtr = 0; dwCtr < dwPropCount; dwCtr++) { DWORD dwSyntaxId = 0; pUmiProperties[dwCtr].pszPropertyName = AllocADsStr(pPropArray[dwCtr]->pszPropertyName);
if (!pUmiProperties[dwCtr].pszPropertyName) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Need to update the type with the type from the schema.
//
dwSyntaxId = LdapGetSyntaxIdOfAttribute( pPropArray[dwCtr]->pszSyntax );
//
// If we get dwSyntaxId == -1 we could not find the entry in
// our table.
//
if (dwSyntaxId == -1) { pUmiProperties[dwCtr].uType = UMI_TYPE_UNDEFINED; } else { hr = ConvertLdapSyntaxIdToUmiType( dwSyntaxId, (pUmiProperties[dwCtr].uType) ); if (FAILED(hr)) { hr = S_OK; //
// Cannot do anything about this.
//
pUmiProperties[dwCtr].uType = UMI_TYPE_UNDEFINED; }
//
// If this property is multivalued.
//
if (!pPropArray[dwCtr]->fSingleValued) { pUmiProperties[dwCtr].uType |= UMI_TYPE_ARRAY_FLAG; } } } // for each property.
pUmiPropVals->pPropArray = pUmiProperties; pUmiPropVals->uCount = dwPropCount;
*pUmiProps = pUmiPropVals;
error:
if (pIADsUmiPriv) { pIADsUmiPriv->Release(); }
//
// Need to free the array not the elements which are ptrs into
// the global parsed schema's we hold.
//
if (pPropArray) { FreeADsMem(pPropArray); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetInterfaceProperty
//
// Synopsis: Gets the interface property from the owning object or the
// default value and packages the value as an UMI_PROPERTY_VALUE.
//
// Arguments: pszName - name of property to get.
// uFlags - flags has to be zero for now.
// ppProp - value is returned in this ptr.
// dwTableIndex - index to entry in table describing this item.
//
// Returns: HRESULT - S_OK or any failure error code
//
// Modifies: ppProp which will point to return value if the fn succeeds.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetInterfaceProperty( LPCWSTR pszName, ULONG uFlags, UMI_PROPERTY_VALUES **ppProp, DWORD dwTableIndex ) { HRESULT hr; ULONG ulOperationAllowed = _pStaticPropData[dwTableIndex].ulOpCode; ULONG ulVal; LONG lGenus; LPWSTR pszStringVal = NULL; BSTR bstrRetVal = NULL, bstrTempVal = NULL; LPWSTR pszUmiUrl = NULL; IADsObjectOptions *pObjOpt = NULL; VARIANT vVariant; DWORD dwIndex; PUMI_PROPERTY pUmiPropLocal = NULL; IUnknown *pUnk = NULL; IUmiObject *pUmiObj = NULL; BOOL fUnkPtr = FALSE; BOOL fClassInstance = FALSE;
VariantInit(&vVariant);
if (!_pUnk) { BAIL_ON_FAILURE(hr = E_FAIL); } //
// If the property is READ/WRITE, we need to see if there is a value
// in the propCache. If yes, return that. If not return the default
// value.
//
if (ulOperationAllowed == OPERATION_CODE_READWRITE) {
hr = FindProperty(pszName, &dwIndex); //
// If it succeeded it was updated in the cache.
//
if (SUCCEEDED(hr)) { hr = CopyUmiProperty( *(_pIntfProperties[dwIndex].pUmiProperty), &pUmiPropLocal ); BAIL_ON_FAILURE(hr);
//
// We need to free the name of the first property cause
// that is allocated again by the Get call.
//
if (pUmiPropLocal && pUmiPropLocal->pszPropertyName) { FreeADsStr(pUmiPropLocal->pszPropertyName); pUmiPropLocal->pszPropertyName = NULL; }
//
// Got the property need to package in umi property values.
//
*ppProp = (PUMI_PROPERTY_VALUES) AllocADsMem( sizeof(UMI_PROPERTY_VALUES) ); if (!*ppProp) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
(*ppProp)->pPropArray = pUmiPropLocal; (*ppProp)->uCount = 1; RRETURN(hr); } // value found in cache
else { //
// Setting this should trigger a read of the default
// value for this property.
//
ulOperationAllowed = OPERATION_CODE_READABLE; } }
//
// We need to check for the securityDescriptor as that needs
// some special handling.
//
if (!_wcsicmp(pszName, L"__SECURITY_DESCRIPTOR")) { //
// Need to read this from the actual object.
//
hr = _pUnk->QueryInterface(IID_IUmiObject, (void **) &pUmiObj); BAIL_ON_FAILURE(hr);
hr = pUmiObj->GetAs( L"ntSecurityDescriptor", uFlags, UMI_TYPE_OCTETSTRING, ppProp ); if (SUCCEEDED(hr)) { //
// Need to make sure that we do not set name twice.
//
if (*ppProp && (*ppProp)[0].pPropArray && (*ppProp)[0].pPropArray[0].pszPropertyName ) { FreeADsStr((*ppProp)[0].pPropArray[0].pszPropertyName); (*ppProp)[0].pPropArray[0].pszPropertyName = NULL; } } //
// This seems the cleanest ...
//
goto error; }
//
// If the property is only readable, then get it from owning object.
// If not get the value from cache or use defualt value as appropriate.
//
if (ulOperationAllowed == OPERATION_CODE_READABLE) { hr = GetLongProperty(L"__GENUS", &lGenus); if (FAILED(hr)) { //
// There was no genus property = connection for example.
//
fClassInstance = FALSE; } else if (lGenus == UMI_GENUS_CLASS) { fClassInstance = TRUE; }
//
// The value can be a string/long for now and it has to
// be either the default value or the value from the owning object.
//
switch (_pStaticPropData[dwTableIndex].ulDataType) { case UMI_TYPE_I4: //
// Use default value from the static table.
//
vVariant.lVal = _pStaticPropData[dwTableIndex].umiVal.lValue[0];
hr = ConvertVariantLongToUmiProp(vVariant, ppProp); break; case UMI_TYPE_BOOL: //
// Use default value from table.
//
vVariant.lVal = _pStaticPropData[dwTableIndex].umiVal.bValue[0]; hr = ConvertVariantLongToUmiProp(vVariant, ppProp); (*ppProp)[0].pPropArray[0].uType = UMI_TYPE_BOOL; break;
case UMI_TYPE_LPWSTR: //
// In this case it has to be NULL.
//
hr = GetEmptyLPWSTRProp(ppProp); break;
case 9999: if (!_pIADs) { //
// Nothing we can do here !
//
BAIL_ON_FAILURE(hr = E_FAIL); }
if (!_wcsicmp(pszName, L"__Path")) { hr = _pIADs->get_ADsPath(&bstrRetVal); } else if (!_wcsicmp(pszName, L"__Class")) { if (fClassInstance) { //
// For classes, the class is the name,
// not "class" itself.
//
hr = _pIADs->get_Name(&bstrRetVal); } else { hr = _pIADs->get_Class(&bstrRetVal); } } else if (!_wcsicmp(pszName, L"__KEY")) { hr = _pIADs->get_Name(&bstrRetVal); BAIL_ON_FAILURE(hr);
if (SUCCEEDED(hr)) { hr = HelperConvertNameToKey(bstrRetVal, &pszUmiUrl); } } else if (!_wcsicmp(pszName, L"__GUID")) { hr = _pIADs->get_GUID(&bstrRetVal); } else if (!_wcsicmp(pszName, L"__Parent")) { hr = _pIADs->get_Parent(&bstrRetVal); if (SUCCEEDED(hr)) { hr = ADsPathToUmiURL(bstrRetVal, &pszUmiUrl); } } else if (!_wcsicmp(pszName, L"__Schema")) { hr = _pIADs->get_Schema(&bstrRetVal); //
// Now need to bind to this object.
//
if (SUCCEEDED(hr)) { hr = GetObject( bstrRetVal, *_pCreds, (void **) &pUnk ); BAIL_ON_FAILURE(hr); fUnkPtr = TRUE; } } else if (!_wcsicmp(pszName, L"__URL")) { hr = _pIADs->get_ADsPath(&bstrTempVal); if (SUCCEEDED(hr)) { hr = ADsPathToUmiURL(bstrTempVal, &pszUmiUrl); } } else if (!_wcsicmp(pszName, L"__Name")) { if (fClassInstance) { hr = _pIADs->get_Name(&bstrRetVal); } else { hr = HelperGetUmiRelUrl(_pIADs, &bstrRetVal); } } else if (!_wcsicmp(pszName, L"__RELURL")) { hr = HelperGetUmiRelUrl(_pIADs, &bstrRetVal); } else if (!_wcsicmp(pszName, L"__RELPATH")) { hr = HelperGetUmiRelUrl(_pIADs, &bstrRetVal); } else if (!_wcsicmp(pszName, L"__FULLRELURL")) { //
// Same as __RELURL, __NAME and __RELPATH
//
hr = HelperGetUmiRelUrl(_pIADs, &bstrRetVal); } else if (!_wcsicmp(pszName, L"__PADS_SCHEMA_CONTAINER_PATH")) { hr = HelperGetUmiSchemaContainerPath(_pIADs, &bstrRetVal); } else if (!_wcsicmp(pszName, L"__SUPERCLASS")) { if (!fClassInstance) { //
// Only supported if this is a class.
//
hr = E_FAIL; } else { hr = HelperGetUmiDerivedFrom(_pIADs, &bstrRetVal); } } else { hr = E_FAIL; }
BAIL_ON_FAILURE(hr);
//
// If not schema then it has to be a string.
//
if (!fUnkPtr) { hr = ConvertBSTRToUmiProp( pszUmiUrl ? pszUmiUrl:bstrRetVal, ppProp ); } else { hr = ConvertIUnkToUmiProp( pUnk, IID_IUmiObject, ppProp ); } break; default: hr = E_FAIL; } // end of switch
BAIL_ON_FAILURE(hr); } // opeartion code is READABLE.
else { hr = E_FAIL; }
error:
if (pObjOpt) { pObjOpt->Release(); }
VariantClear(&vVariant); if (bstrRetVal) { SysFreeString(bstrRetVal); }
if (bstrTempVal) { SysFreeString(bstrTempVal); }
if (pszUmiUrl) { FreeADsStr(pszUmiUrl); }
if (pUnk) { pUnk->Release(); }
if (pUmiObj) { pUmiObj->Release(); } RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::DeleteSDIfPresent --- Helper method.
//
// Synopsis: Helps remove the SD from the property cache so that we do not
// set it when we Commit the changes.
//
// Arguments: N/A.
//
// Returns: HRESULT - S_OK or any failure error code
//
// Modifies: Underlying property cache.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::DeleteSDIfPresent() { HRESULT hr = S_OK; DWORD dwIndex = 0;
if (!_fPropCacheMode) { //
// Sanity check, should never be here.
//
RRETURN(S_OK); }
if (!_pPropCache) { //
// Want to delete SD when we do not have a cache - weird.
//
RRETURN(S_OK); }
hr = _pPropCache->findproperty(L"ntSecurityDescriptor", &dwIndex); if (FAILED(hr)) { RRETURN(S_OK); } else { //
// Get rid of this from the cache.
//
_pPropCache->deleteproperty(dwIndex); }
RRETURN(S_OK); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetIndexInStaticTable
//
// Synopsis: Verifies that the named property can be found in the list of
// valid properties and returns the index.
//
// Arguments: Self explanatory.
//
// Returns: S_OK or E_ADS_PROPERTY_NOT_FOUND as appropriate.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetIndexInStaticTable( LPCWSTR pszName, DWORD &dwIndex ) { for (DWORD dwCtr = 0; _pStaticPropData[dwCtr].pszPropertyName; dwCtr++ ) { if (!_wcsicmp( pszName, _pStaticPropData[dwCtr].pszPropertyName )) { dwIndex = dwCtr; RRETURN(S_OK); } }
RRETURN(E_ADS_PROPERTY_NOT_FOUND); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::VerifyIfValidProperty.
//
// Synopsis: Makes sure that a valid interface property is being set. This
// function is called internally if we know we are not in the
// property cache mode. The internal static table pointer is used to
// verify the property.
//
// Arguments: Self explanatory.
//
// Returns: Bool - True or False as appropriate.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
BOOL CPropertyManager::VerifyIfValidProperty( LPCWSTR pszPropertyName, UMI_PROPERTY umiProperty ) { DWORD dwIndex; //
// if _pStaticPropData is NULL then there are no interface properties.
// If the count is zero, then the only operation is delete.
//
if ((!_pStaticPropData) || ((umiProperty.uCount == 0) && (umiProperty.uOperationType != UMI_OPERATION_DELETE_ALL_MATCHES) ) ) { return FALSE; }
if (SUCCEEDED(GetIndexInStaticTable( pszPropertyName, dwIndex )) ) { //
// Verify type and if property can be changed.
// If the types do not match we should still allow 9999 for
// things like __SECURITY_DESCRIPTOR that can be changed.
// If the attribute cannot be written, then the next part of
// the check will fail, so you still wont be able to write
// things the __URL property.
//
if (((_pStaticPropData[dwIndex].ulDataType == umiProperty.uType) || (_pStaticPropData[dwIndex].ulDataType == 9999)) && (_pStaticPropData[dwIndex].ulOpCode != OPERATION_CODE_READABLE) ) { //
// Need to make sure count is correct.
//
if ((umiProperty.uCount > 1) && (!_pStaticPropData[dwIndex].fMultiValued) ) { return FALSE; } return TRUE; }
}
//
// Either we did not satisfy requirements or not found
//
return FALSE; }
HRESULT CPropertyManager::AddToTable( LPCWSTR pszPropertyName, PDWORD pdwIndex ) { HRESULT hr = S_OK; PINTF_PROPERTY pNewProperty = NULL; //
// Check to see if the table is already there. If not create
// the table with potential to store upto 10 entries. This should
// suffice unless we have more properties. Set the current pointer
// and current top appropriately.
//
if (!_pIntfProperties) { _pIntfProperties = (PINTF_PROPERTY) AllocADsMem( sizeof(INTF_PROPERTY) * MAX_PROPMGR_PROP_COUNT );
if (!_pIntfProperties) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
_dwMaxProperties = 0; _dwMaxLimit = MAX_PROPMGR_PROP_COUNT; }
if ((_dwMaxProperties+1) < _dwMaxLimit) { //
// We can add this property to the table.
//
DWORD dwTop; dwTop = _dwMaxProperties++;
_pIntfProperties[dwTop].pszPropertyName = AllocADsStr(pszPropertyName);
if (!_pIntfProperties[dwTop].pszPropertyName) { //
// Reset the count.
//
_dwMaxProperties--; BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
*pdwIndex = dwTop; } else { //
// We do not have space in the table - return an error.
//
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
error:
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetStringProperty.
//
// Synopsis: Retrieves the string property if one is set in the cache or
// returns NULL if the property is not in the cache. The assumption
// here is that string properties are defaulted to NULL always.
//
// Arguments: Self explanatory.
//
// Returns: S_OK, UMI_E_NOT_FOUND, E_FAIL.
//
// Modifies: pszRetVal to point to the appropriate value.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetStringProperty( LPCWSTR pszPropName, LPWSTR *ppszRetStrVal ) { DWORD dwIndex; HRESULT hr = FindProperty(pszPropName, &dwIndex); PUMI_PROPERTY pUmiProp;
if (FAILED(hr)) { //
// Do we lookup the static table ? The table wont have strings in
// it though cause the union assumes chars.
//
*ppszRetStrVal = NULL; RRETURN(S_OK); }
pUmiProp = _pIntfProperties[dwIndex].pUmiProperty; //
// Make sure that this is a string.
//
if (pUmiProp->uType != UMI_TYPE_LPWSTR) { BAIL_ON_FAILURE(hr = E_FAIL); }
if (pUmiProp->pUmiValue && pUmiProp->pUmiValue->pszStrValue[0]) {
*ppszRetStrVal = AllocADsStr(pUmiProp->pUmiValue->pszStrValue[0]);
if (!*ppszRetStrVal) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } }
error:
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetLongProperty - Helper method.
//
// Synopsis: Retrieves the long property if one is set in the cache or
// returns the defaulted value if the property is not in the cache.
//
// Arguments: pszPropName --- Name of property being retrieved.
// plVal --- Ptr for return value.
//
// Returns: S_OK, UMI_E_NOT_FOUND or E_FAIL.
//
// Modifies: *plVal with appropriate value.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetLongProperty( LPCWSTR pszPropName, LONG *plVal ) { DWORD dwIndex; HRESULT hr = FindProperty(pszPropName, &dwIndex); PUMI_PROPERTY pUmiProp;
*plVal = 0;
if (FAILED(hr)) { //
// We need to look for the property in the static table.
//
hr = GetIndexInStaticTable(pszPropName, dwIndex); if (SUCCEEDED(hr) && (_pStaticPropData[dwIndex].ulDataType == UMI_TYPE_I4) ) { //
// Get the correct value from the table.
//
*plVal = _pStaticPropData[dwIndex].umiVal.lValue[0];
} else { hr = UMI_E_NOT_FOUND; }
RRETURN(hr); }
pUmiProp = _pIntfProperties[dwIndex].pUmiProperty; //
// Make sure that this is a long.
//
if (pUmiProp->uType != UMI_TYPE_I4) { BAIL_ON_FAILURE(hr = E_FAIL); }
if (pUmiProp->pUmiValue) { *plVal = pUmiProp->pUmiValue->lValue[0]; }
error:
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CPropertyManager::GetBoolProperty - Helper method.
//
// Synopsis: Retrieves the bool property if one is set in the cache or
// returns the defaulted value if the property is not in the cache.
//
// Arguments: pszPropName --- Name of property being retrieved.
// pfFlag --- Ptr for return value.
//
// Returns: S_OK, UMI_E_NOT_FOUND or E_FAIL.
//
// Modifies: ofFlag with appropriate value of the property.
//
//----------------------------------------------------------------------------
HRESULT CPropertyManager::GetBoolProperty( LPCWSTR pszPropName, BOOL *pfFlag ) { DWORD dwIndex; HRESULT hr = FindProperty(pszPropName, &dwIndex); PUMI_PROPERTY pUmiProp;
*pfFlag = FALSE;
if (FAILED(hr)) { //
// We need to look for the property in the static table.
//
hr = GetIndexInStaticTable(pszPropName, dwIndex); if (SUCCEEDED(hr) && (_pStaticPropData[dwIndex].ulDataType == UMI_TYPE_BOOL) ) { //
// Get the correct value from the table.
//
*pfFlag = _pStaticPropData[dwIndex].umiVal.bValue[0];
} else { hr = E_FAIL; } RRETURN(hr); }
pUmiProp = _pIntfProperties[dwIndex].pUmiProperty; //
// Make sure that this is a long.
//
if (pUmiProp->uType != UMI_TYPE_BOOL) { BAIL_ON_FAILURE(hr = E_FAIL); }
if (pUmiProp->pUmiValue) { *pfFlag = pUmiProp->pUmiValue->bValue[0]; }
error:
RRETURN(hr); }
|