1184 lines
26 KiB
C++
1184 lines
26 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: cprops.cxx
|
|
//
|
|
// Contents: Property Cache functionality for NW
|
|
//
|
|
// Functions:
|
|
// CPropertyCache::addproperty
|
|
// CPropertyCache::updateproperty
|
|
// CPropertyCache::findproperty
|
|
// CPropertyCache::getproperty
|
|
// CPropertyCache::putproperty
|
|
// CProperyCache::CPropertyCache
|
|
// CPropertyCache::~CPropertyCache
|
|
// CPropertyCache::createpropertycache
|
|
//
|
|
// History: 17-June-1996 KrishnaG Created.
|
|
// cloned off NDS property cache code
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "nwcompat.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: CPropertyCache::addproperty
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments: [szPropertyName] --
|
|
// [vt] --
|
|
// [vaData] --
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CPropertyCache::
|
|
addproperty(
|
|
LPWSTR szPropertyName,
|
|
DWORD dwSyntaxId,
|
|
DWORD dwNumValues,
|
|
PNTOBJECT pNtObject
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PPROPERTY pNewProperty = NULL;
|
|
LPWSTR tempString = NULL;
|
|
|
|
//
|
|
// Allocate the string first
|
|
//
|
|
tempString = AllocADsStr(szPropertyName);
|
|
|
|
if (!tempString)
|
|
BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
|
|
|
|
|
|
//
|
|
// extend the property cache by adding a new property entry
|
|
//
|
|
|
|
_pProperties = (PPROPERTY)ReallocADsMem(
|
|
_pProperties,
|
|
_cb,
|
|
_cb + sizeof(PROPERTY)
|
|
);
|
|
if (!_pProperties) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
|
|
pNewProperty = (PPROPERTY)((LPBYTE)_pProperties + _cb);
|
|
|
|
if (pNewProperty->szPropertyName) {
|
|
FreeADsStr(pNewProperty->szPropertyName);
|
|
pNewProperty->szPropertyName = NULL;
|
|
}
|
|
|
|
//
|
|
// Since the memory has already been allocated in tempString
|
|
// just set the value/pointer now.
|
|
//
|
|
pNewProperty->szPropertyName = tempString;
|
|
|
|
//
|
|
// BugBug - add in the NDSOBJECT code
|
|
//
|
|
|
|
|
|
//
|
|
// Update the index
|
|
//
|
|
|
|
_dwMaxProperties++;
|
|
_cb += sizeof(PROPERTY);
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
if (tempString)
|
|
FreeADsStr(tempString);
|
|
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: CPropertyCache::updateproperty
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments: [szPropertyName] --
|
|
// [vaData] --
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CPropertyCache::updateproperty(
|
|
LPWSTR szPropertyName,
|
|
DWORD dwSyntaxId,
|
|
DWORD dwNumValues,
|
|
PNTOBJECT pNtObject,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwIndex;
|
|
PNTOBJECT pNtTempObject = NULL;
|
|
PPROPERTY pThisProperty = NULL;
|
|
|
|
hr = findproperty(
|
|
szPropertyName,
|
|
&dwIndex
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pThisProperty = _pProperties + dwIndex;
|
|
|
|
|
|
if (!fExplicit) {
|
|
if (PROPERTY_IS_MODIFIED(pThisProperty)) {
|
|
hr = S_OK;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Factor in cases where object state is necessary to
|
|
// decide on update.
|
|
//
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
NTTypeFreeNTObjects(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty)
|
|
);
|
|
PROPERTY_NTOBJECT(pThisProperty) = NULL;
|
|
}
|
|
|
|
PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
|
|
PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
|
|
|
|
hr = NtTypeCopyConstruct(
|
|
pNtObject,
|
|
dwNumValues,
|
|
&pNtTempObject
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
PROPERTY_NTOBJECT(pThisProperty) = pNtTempObject;
|
|
|
|
PROPERTY_FLAGS(pThisProperty) &= ~CACHE_PROPERTY_MODIFIED;
|
|
|
|
error:
|
|
|
|
NW_RRETURN_EXP_IF_ERR(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;
|
|
|
|
if (!_wcsicmp(pThisProperty->szPropertyName, szPropertyName)) {
|
|
*pdwIndex = i;
|
|
RRETURN(S_OK);
|
|
}
|
|
}
|
|
*pdwIndex = 0;
|
|
NW_RRETURN_EXP_IF_ERR(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,
|
|
PNTOBJECT * ppNtObject
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwIndex = 0L;
|
|
PPROPERTY pThisProperty = NULL;
|
|
DWORD dwResult;
|
|
DWORD dwInfoLevel = 0;
|
|
|
|
hr = findproperty(
|
|
szPropertyName,
|
|
&dwIndex
|
|
);
|
|
if (hr == E_ADS_PROPERTY_NOT_FOUND) {
|
|
|
|
hr = GetPropertyInfoLevel(
|
|
szPropertyName,
|
|
_pSchemaClassProps,
|
|
_dwNumProperties,
|
|
&dwInfoLevel
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Now call the GetInfo function
|
|
//
|
|
|
|
hr = _pCoreADsObject->GetInfo(
|
|
dwInfoLevel,
|
|
FALSE
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = findproperty(
|
|
szPropertyName,
|
|
&dwIndex
|
|
);
|
|
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
|
|
|
|
pThisProperty = _pProperties + dwIndex;
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
*pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
|
|
*pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
|
|
|
|
hr = NtTypeCopyConstruct(PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty),
|
|
ppNtObject );
|
|
BAIL_ON_FAILURE(hr);
|
|
}else {
|
|
|
|
*ppNtObject = NULL;
|
|
*pdwNumValues = 0;
|
|
*pdwSyntaxId = 0;
|
|
hr = E_FAIL;
|
|
|
|
}
|
|
|
|
error:
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: CPropertyCache::marshallgetproperty
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments: [szPropertyName] -- Property to retrieve from the cache
|
|
// [pvaData] -- Data returned in a variant
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CPropertyCache::
|
|
marshallgetproperty(
|
|
LPWSTR szPropertyName,
|
|
PDWORD pdwSyntaxId,
|
|
PDWORD pdwNumValues,
|
|
PNTOBJECT * ppNtObject
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwIndex = 0L;
|
|
PPROPERTY pThisProperty = NULL;
|
|
DWORD dwResult;
|
|
DWORD dwInfoLevel = 0;
|
|
|
|
hr = findproperty(
|
|
szPropertyName,
|
|
&dwIndex
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pThisProperty = _pProperties + dwIndex;
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
*pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
|
|
*pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
|
|
|
|
hr = NtTypeCopyConstruct(PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty),
|
|
ppNtObject );
|
|
BAIL_ON_FAILURE(hr);
|
|
}else {
|
|
|
|
*ppNtObject = NULL;
|
|
*pdwNumValues = 0;
|
|
*pdwSyntaxId = 0;
|
|
hr = E_FAIL;
|
|
|
|
}
|
|
|
|
error:
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: CPropertyCache::putproperty
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments: [szPropertyName] -- Clsid index
|
|
// [vaData] -- Matching clsid returned in *pclsid
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CPropertyCache::putproperty(
|
|
LPWSTR szPropertyName,
|
|
DWORD dwSyntaxId,
|
|
DWORD dwNumValues,
|
|
PNTOBJECT pNtObject
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwIndex = 0L;
|
|
PNTOBJECT pNtTempObject = NULL;
|
|
PPROPERTY pThisProperty = NULL;
|
|
|
|
hr = findproperty(
|
|
szPropertyName,
|
|
&dwIndex
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pThisProperty = _pProperties + dwIndex;
|
|
|
|
|
|
//
|
|
// AccountLocked is "half writable" -> need special care
|
|
//
|
|
|
|
if (_wcsicmp(szPropertyName, TEXT("IsAccountLocked"))==0 ) {
|
|
|
|
if (pNtObject->NTType != NT_SYNTAX_ID_BOOL) {
|
|
hr = E_ADS_BAD_PARAMETER;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// canNOT just disallow user to set cache to TRUE since
|
|
// user may have accidentally set cache to FALSE (unlock) and
|
|
// want to set the cache back to TRUE (do not unlock) without
|
|
// GetInfo to affect other changes in cache. It will be a major
|
|
// mistake if cuser cannot set the cache back to TRUE after
|
|
// changing it to FALSE accidentally and thus unlocking the
|
|
// account even if the user does not want to.
|
|
//
|
|
// If cache value on IsAccountLocked is changed from FALSE to TRUE,
|
|
// cached value will be automatically changed back to FALSE upon
|
|
// SetInfo since user cannot lock an account thru' ADSI. (NW server
|
|
// wont' allow. Ref: SysCon)
|
|
//
|
|
// Should: If new value == value already in cache, do nothing.
|
|
// That is, do not try to set the cache_property_modified flag.
|
|
// This is to prevent
|
|
// 1) the side effect of setting BadLogins to 0 when a
|
|
// user set the cached property IsAccountLocked
|
|
// from FALSE to FALSE (no change really) and call SetInfo.
|
|
// 2) the side effect of changing the cache value to 0 (not
|
|
// consistent with server or original cached value) when
|
|
// a user set the cache property IsAccontLocked
|
|
// from TRUE to TRUE (no change really) and call SetInfo.
|
|
//
|
|
// If user set IsAccountLocked from FALSE to TRUE and then
|
|
// back to FALSE, or from TRUE to FALSE and then back to TURE,
|
|
// side effect 1) or 2) will happen.
|
|
// Both side effect not critical.
|
|
//
|
|
// We first check whether the object has been set previously, if not,
|
|
// NTOBJECT will be NULL
|
|
//
|
|
if (PROPERTY_NTOBJECT(pThisProperty) &&
|
|
(pNtObject->NTValue.fValue==
|
|
PROPERTY_NTOBJECT(pThisProperty)->NTValue.fValue)) {
|
|
RRETURN(S_OK);
|
|
}
|
|
}
|
|
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
NTTypeFreeNTObjects(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty)
|
|
);
|
|
PROPERTY_NTOBJECT(pThisProperty) = NULL;
|
|
}
|
|
|
|
PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
|
|
PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
|
|
|
|
hr = NtTypeCopyConstruct(
|
|
pNtObject,
|
|
dwNumValues,
|
|
&pNtTempObject
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
PROPERTY_NTOBJECT(pThisProperty) = pNtTempObject;
|
|
|
|
PROPERTY_FLAGS(pThisProperty) |= CACHE_PROPERTY_MODIFIED;
|
|
|
|
error:
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: CPropertyCache
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
CPropertyCache::CPropertyCache():
|
|
_pCoreADsObject(NULL),
|
|
_pSchemaClassProps(NULL),
|
|
_dwMaxProperties(0),
|
|
_pProperties(NULL),
|
|
_dwCurrentIndex(0),
|
|
_cb(0)
|
|
{
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: ~CPropertyCache
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
CPropertyCache::
|
|
~CPropertyCache()
|
|
{
|
|
DWORD i = 0;
|
|
PPROPERTY pThisProperty = NULL;
|
|
|
|
if (_pProperties) {
|
|
|
|
for (i = 0; i < _dwMaxProperties; i++) {
|
|
|
|
pThisProperty = _pProperties + i;
|
|
|
|
if (pThisProperty->szPropertyName) {
|
|
FreeADsStr(pThisProperty->szPropertyName);
|
|
pThisProperty->szPropertyName = NULL;
|
|
}
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
NTTypeFreeNTObjects(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty)
|
|
);
|
|
PROPERTY_NTOBJECT(pThisProperty) = NULL;
|
|
}
|
|
}
|
|
FreeADsMem(_pProperties);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CPropertyCache::
|
|
createpropertycache(
|
|
PPROPERTYINFO pSchemaClassProps,
|
|
DWORD dwNumProperties,
|
|
CCoreADsObject FAR * pCoreADsObject,
|
|
CPropertyCache FAR *FAR * ppPropertyCache
|
|
)
|
|
{
|
|
CPropertyCache FAR * pPropertyCache = NULL;
|
|
|
|
pPropertyCache = new CPropertyCache();
|
|
|
|
if (!pPropertyCache) {
|
|
NW_RRETURN_EXP_IF_ERR(E_OUTOFMEMORY);
|
|
}
|
|
|
|
pPropertyCache->_pCoreADsObject = pCoreADsObject;
|
|
pPropertyCache->_pSchemaClassProps = pSchemaClassProps;
|
|
pPropertyCache->_dwNumProperties = dwNumProperties;
|
|
|
|
*ppPropertyCache = pPropertyCache;
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CPropertyCache::
|
|
unmarshallproperty(
|
|
LPWSTR szPropertyName,
|
|
LPBYTE lpValue,
|
|
DWORD dwNumValues,
|
|
DWORD dwSyntaxId,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
|
|
DWORD dwIndex = 0;
|
|
HRESULT hr = S_OK;
|
|
PNTOBJECT pNTObject = NULL;
|
|
|
|
hr = UnMarshallNTToNTSynId(
|
|
dwSyntaxId,
|
|
dwNumValues,
|
|
lpValue,
|
|
&pNTObject
|
|
);
|
|
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,
|
|
pNTObject
|
|
);
|
|
|
|
//
|
|
// 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,
|
|
pNTObject,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
if (pNTObject) {
|
|
NTTypeFreeNTObjects(
|
|
pNTObject,
|
|
dwNumValues
|
|
);
|
|
|
|
}
|
|
|
|
|
|
error:
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
ValidatePropertyinSchemaClass(
|
|
PPROPERTYINFO pSchemaClassProps,
|
|
DWORD dwNumProperties,
|
|
LPWSTR pszPropName,
|
|
PDWORD pdwSyntaxId
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
|
|
PPROPERTYINFO pThisSchProperty = NULL;
|
|
|
|
for (i = 0; i < dwNumProperties; i++) {
|
|
|
|
pThisSchProperty = (pSchemaClassProps + i);
|
|
|
|
if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
|
|
*pdwSyntaxId = pThisSchProperty->dwSyntaxId;
|
|
RRETURN (S_OK);
|
|
}
|
|
}
|
|
|
|
RRETURN(E_ADS_SCHEMA_VIOLATION);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
ValidateIfWriteableProperty(
|
|
PPROPERTYINFO pSchemaClassProps,
|
|
DWORD dwNumProperties,
|
|
LPWSTR pszPropName
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
|
|
PPROPERTYINFO pThisSchProperty = NULL;
|
|
|
|
for (i = 0; i < dwNumProperties; i++) {
|
|
|
|
pThisSchProperty = (pSchemaClassProps + i);
|
|
|
|
if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
|
|
|
|
RRETURN((pThisSchProperty->dwFlags & PROPERTY_WRITEABLE)
|
|
? S_OK : E_ADS_SCHEMA_VIOLATION);
|
|
}
|
|
}
|
|
|
|
RRETURN(E_ADS_SCHEMA_VIOLATION);
|
|
|
|
// for winnt & nw312, return E_ADS_SCHEMA_VIOLATION if not ok even
|
|
// attempt to write to cache only
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
GetPropertyInfoLevel(
|
|
LPWSTR pszPropName,
|
|
PPROPERTYINFO pSchemaClassProps,
|
|
DWORD dwNumProperties,
|
|
PDWORD pdwInfoLevel
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
|
|
PPROPERTYINFO pThisSchProperty = NULL;
|
|
|
|
for (i = 0; i < dwNumProperties; i++) {
|
|
|
|
pThisSchProperty = (pSchemaClassProps + i);
|
|
|
|
if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
|
|
|
|
*pdwInfoLevel = pThisSchProperty->dwInfoLevel;
|
|
RRETURN(S_OK);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Returning E_ADS_PROPERTY_NOT_FOUND so that implicit
|
|
// GetInfo fails gracefully
|
|
//
|
|
NW_RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_FOUND);
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// 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 (pThisProperty->szPropertyName) {
|
|
FreeADsStr(pThisProperty->szPropertyName);
|
|
pThisProperty->szPropertyName = NULL;
|
|
}
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
NTTypeFreeNTObjects(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty)
|
|
);
|
|
PROPERTY_NTOBJECT(pThisProperty) = NULL;
|
|
}
|
|
}
|
|
|
|
FreeADsMem(_pProperties);
|
|
}
|
|
|
|
//
|
|
// Reset the property cache
|
|
//
|
|
|
|
_pProperties = NULL;
|
|
_dwMaxProperties = 0;
|
|
_cb = 0;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: CPropertyCache::getproperty
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments: [szPropertyName] -- Property to retrieve from the cache
|
|
// [pvaData] -- Data returned in a variant
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CPropertyCache::
|
|
unboundgetproperty(
|
|
LPWSTR szPropertyName,
|
|
PDWORD pdwSyntaxId,
|
|
PDWORD pdwNumValues,
|
|
PNTOBJECT * ppNtObject
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwIndex = 0L;
|
|
PPROPERTY pThisProperty = NULL;
|
|
|
|
hr = findproperty(
|
|
szPropertyName,
|
|
&dwIndex
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pThisProperty = _pProperties + dwIndex;
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
*pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
|
|
*pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
|
|
|
|
hr = NtTypeCopyConstruct(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty),
|
|
ppNtObject
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else {
|
|
|
|
*ppNtObject = NULL;
|
|
*pdwNumValues = 0;
|
|
*pdwSyntaxId = 0;
|
|
hr = E_FAIL;
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: CPropertyCache::getproperty
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//
|
|
//
|
|
// Arguments: [szPropertyName] -- Property to retrieve from the cache
|
|
// [pvaData] -- Data returned in a variant
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CPropertyCache::
|
|
unboundgetproperty(
|
|
DWORD dwIndex,
|
|
PDWORD pdwSyntaxId,
|
|
PDWORD pdwNumValues,
|
|
PNTOBJECT * ppNtObject
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
PPROPERTY pThisProperty = NULL;
|
|
|
|
if (!index_valid(dwIndex)) {
|
|
RRETURN(E_ADS_BAD_PARAMETER); // better if E_ADS_INDEX or sth
|
|
}
|
|
|
|
pThisProperty = _pProperties + dwIndex;
|
|
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
|
|
*pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
|
|
*pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
|
|
|
|
hr = NtTypeCopyConstruct(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty),
|
|
ppNtObject
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else {
|
|
|
|
*ppNtObject = NULL;
|
|
*pdwNumValues = 0;
|
|
*pdwSyntaxId = 0;
|
|
hr = E_FAIL;
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
BOOL
|
|
CPropertyCache::
|
|
index_valid(
|
|
)
|
|
{
|
|
// _dwMaxProperties =0 -> dwMaxProperties -1 = -1 -> converted to
|
|
// unsigned during comparision with unsigned _dwCurrentIndex ->
|
|
// comparision does not work. So need to check if _dwMaxProperties==0 1st
|
|
if (_dwMaxProperties ==0)
|
|
return (FALSE);
|
|
|
|
if (_dwCurrentIndex < 0 || _dwCurrentIndex > _dwMaxProperties - 1)
|
|
return(FALSE);
|
|
else
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CPropertyCache::
|
|
index_valid(
|
|
DWORD dwIndex
|
|
)
|
|
{
|
|
// _dwMaxProperties =0 -> dwMaxProperties -1 = -1 -> converted to
|
|
// unsigned during comparision with unsigned _dwCurrentIndex ->
|
|
// comparision does not work. So need to check if _dwMaxProperties==0 1st
|
|
if (_dwMaxProperties ==0)
|
|
return (FALSE);
|
|
|
|
if (dwIndex < 0 || 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() || !_dwMaxProperties)
|
|
NW_RRETURN_EXP_IF_ERR(E_FAIL);
|
|
|
|
//
|
|
// BugBug it will be better to return IndexOutOfRange or something like that
|
|
//
|
|
|
|
if (_dwCurrentIndex < 0 || _dwCurrentIndex > _dwMaxProperties-1)
|
|
NW_RRETURN_EXP_IF_ERR(E_FAIL);
|
|
|
|
if ( newIndex < 0 || newIndex > _dwMaxProperties )
|
|
NW_RRETURN_EXP_IF_ERR(E_FAIL);
|
|
|
|
|
|
_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 (!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)) {
|
|
RRETURN(E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
if (_dwMaxProperties == 1) {
|
|
//
|
|
// Deleting everything
|
|
//
|
|
if (PROPERTY_NTOBJECT(pThisProperty)) {
|
|
NTTypeFreeNTObjects(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty)
|
|
);
|
|
PROPERTY_NTOBJECT(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_NTOBJECT(pThisProperty)) {
|
|
NTTypeFreeNTObjects(
|
|
PROPERTY_NTOBJECT(pThisProperty),
|
|
PROPERTY_NUMVALUES(pThisProperty)
|
|
);
|
|
PROPERTY_NTOBJECT(pThisProperty) = NULL;
|
|
}
|
|
FreeADsMem(_pProperties);
|
|
_pProperties = pNewProperties;
|
|
_dwMaxProperties--;
|
|
_cb -= sizeof(PROPERTY);
|
|
error:
|
|
|
|
NW_RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CPropertyCache::
|
|
propertyismodified(
|
|
LPWSTR szPropertyName,
|
|
BOOL * pfModified
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwIndex = 0L;
|
|
PPROPERTY pThisProperty = NULL;
|
|
|
|
if (!szPropertyName || !pfModified) {
|
|
RRETURN(E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
hr = findproperty(
|
|
szPropertyName,
|
|
&dwIndex
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pThisProperty = _pProperties + dwIndex;
|
|
|
|
*pfModified=PROPERTY_IS_MODIFIED(pThisProperty);
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|