windows-nt/Source/XPSP1/NT/ds/adsi/ldap/putget.cxx
2020-09-26 16:20:57 +08:00

603 lines
14 KiB
C++

//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: putget.cxx
//
// Contents:
//
//
// History: 01-14-97 krishnaG Created.
//
//----------------------------------------------------------------------------
#include "ldap.hxx"
#pragma hdrstop
STDMETHODIMP
CLDAPGenObject::Get(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwStatus = 0;
LDAPOBJECTARRAY ldapSrcObjects;
LDAPOBJECTARRAY_INIT(ldapSrcObjects);
//
// Make sure that the last error is reset
//
Macro_ClearADsLastError(L"LDAP Provider");
//
// In case some person decides to randomize us with a NULL
//
if (!pvProp || !bstrName) {
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
}
//
// retrieve data object from cache; if one exists
//
if ( GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = _pPropertyCache->unboundgetproperty(
bstrName,
&dwSyntaxId,
&dwStatus,
&ldapSrcObjects
);
// For backward compatibility
if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
hr = E_FAIL;
}
} else {
hr = _pPropertyCache->getproperty(
bstrName,
&dwSyntaxId,
&dwStatus,
&ldapSrcObjects
);
// this will make sure we do not break existing code
if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
hr = E_ADS_PROPERTY_NOT_FOUND;
}
}
BAIL_ON_FAILURE(hr);
//
// translate the Ldap objects to variants
//
if ( ldapSrcObjects.dwCount == 1 ) {
hr = LdapTypeToVarTypeCopy(
_pszLDAPServer,
_Credentials,
ldapSrcObjects.pLdapObjects,
dwSyntaxId,
pvProp
);
} else {
hr = LdapTypeToVarTypeCopyConstruct(
_pszLDAPServer,
_Credentials,
ldapSrcObjects,
dwSyntaxId,
pvProp
);
}
BAIL_ON_FAILURE(hr);
error:
LdapTypeFreeLdapObjects( &ldapSrcObjects );
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CLDAPGenObject::Put(
THIS_ BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwIndex = 0;
LDAPOBJECTARRAY ldapDestObjects;
DWORD dwNumValues = 0;
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
BOOL fIndexValid = TRUE;
LDAPOBJECTARRAY_INIT(ldapDestObjects);
//
// Make sure that the last error is reset
//
Macro_ClearADsLastError(L"LDAP Provider");
//
// In case some person decides to randomize us with a NULL
//
if (!bstrName) {
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
}
//
// A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
// We should dereference a VT_BYREF|VT_VARIANT once and see
// what's inside.
//
pvProp = &vProp;
if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) {
pvProp = V_VARIANTREF(&vProp);
}
if ((V_VT(pvProp) & VT_VARIANT) && V_ISARRAY(pvProp) && V_ISBYREF(pvProp)){
hr = ConvertByRefSafeArrayToVariantArray(
*pvProp,
&pVarArray,
&dwNumValues
);
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}else if ((V_VT(pvProp) & VT_VARIANT) && V_ISARRAY(pvProp)) {
hr = ConvertSafeArrayToVariantArray(
*pvProp,
&pVarArray,
&dwNumValues
);
// returns E_FAIL if *pvProp is invalid
if (hr == E_FAIL)
hr = E_ADS_BAD_PARAMETER;
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}
else {
dwNumValues = 1;
}
if (pvProp == NULL) {
dwSyntaxId = LDAPTYPE_UNKNOWN;
}
else {
hr = GetLdapSyntaxFromVariant(
pvProp,
&dwSyntaxId,
_pszLDAPServer,
bstrName,
_Credentials,
_dwPort
);
BAIL_ON_FAILURE(hr);
if ( dwSyntaxId == LDAPTYPE_UNKNOWN )
{
hr = E_ADS_CANT_CONVERT_DATATYPE;
BAIL_ON_FAILURE(hr);
}
}
if (!_wcsicmp(bstrName, L"ntSecurityDescriptor")){
dwSyntaxId = LDAPTYPE_SECURITY_DESCRIPTOR;
}
#if 0
//
// check if this is a legal property for this object,
//
// No Schema??
// mattrim 5/16/00 - doesn't matter if no schema since
// this isn't getting built, it's #if'ed out
//
hr = ValidatePropertyinCache(
szLDAPTreeName,
_ADsClass,
bstrName,
&dwSyntaxId
);
BAIL_ON_FAILURE(hr);
#endif
//
// check if the variant maps to the syntax of this property
//
if ( dwNumValues > 0 )
{
hr = VarTypeToLdapTypeCopyConstruct(
_pszLDAPServer,
_Credentials,
dwSyntaxId,
pvProp,
dwNumValues,
&ldapDestObjects
);
BAIL_ON_FAILURE(hr);
}
//
// Find this property in the cache
//
hr = _pPropertyCache->findproperty(
bstrName,
&dwIndex
);
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) {
hr = _pPropertyCache->addproperty( bstrName );
//
// If dwNumValues == 0 ( delete the property ) but couldn't find
// the property, or if the add operation fails, return the error.
//
BAIL_ON_FAILURE(hr);
// Set the flag as the dwIndex is not valid in this case
fIndexValid = FALSE;
}
//
// Now update the property in the cache
//
if (fIndexValid) {
// do an optimized put
hr = _pPropertyCache->putproperty(
dwIndex,
PROPERTY_UPDATE,
dwSyntaxId,
ldapDestObjects
);
} else {
// Index is not valid so let the cache figure it out.
hr = _pPropertyCache->putproperty(
bstrName,
PROPERTY_UPDATE,
dwSyntaxId,
ldapDestObjects
);
}
BAIL_ON_FAILURE(hr);
error:
LdapTypeFreeLdapObjects( &ldapDestObjects );
if (pVarArray) {
DWORD i = 0;
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
RRETURN(hr);
}
STDMETHODIMP
CLDAPGenObject::GetEx(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwStatus = 0;
LDAPOBJECTARRAY ldapSrcObjects;
LDAPOBJECTARRAY_INIT(ldapSrcObjects);
//
// Make sure that the last error is reset
//
Macro_ClearADsLastError(L"LDAP Provider");
//
// For those who know no not what they do
//
if (!pvProp || !bstrName) {
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
}
//
// retrieve data object from cache; if one exists
//
if ( GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = _pPropertyCache->unboundgetproperty(
bstrName,
&dwSyntaxId,
&dwStatus,
&ldapSrcObjects
);
// this will make sure we do not break existing code
if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
hr = E_FAIL;
}
} else {
hr = _pPropertyCache->getproperty(
bstrName,
&dwSyntaxId,
&dwStatus,
&ldapSrcObjects
);
// this will make sure we do not break existing code
if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
hr = E_ADS_PROPERTY_NOT_FOUND;
}
}
BAIL_ON_FAILURE(hr);
//
// translate the Ldap objects to variants
//
hr = LdapTypeToVarTypeCopyConstruct(
_pszLDAPServer,
_Credentials,
ldapSrcObjects,
dwSyntaxId,
pvProp
);
BAIL_ON_FAILURE(hr);
error:
LdapTypeFreeLdapObjects( &ldapSrcObjects );
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CLDAPGenObject::PutEx(
THIS_ long lnControlCode,
BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwFlags = 0;
DWORD dwIndex = 0;
LDAPOBJECTARRAY ldapDestObjects;
DWORD dwNumValues = 0;
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
BOOL fIndexValid = TRUE;
LDAPOBJECTARRAY_INIT(ldapDestObjects);
//
// Make sure that the last error is reset
//
Macro_ClearADsLastError(L"LDAP Provider");
//
// In case some person decides to randomize us with a NULL
//
if (!bstrName) {
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
}
switch ( lnControlCode ) {
case ADS_PROPERTY_CLEAR:
dwFlags = PROPERTY_DELETE;
break;
case ADS_PROPERTY_UPDATE:
dwFlags = PROPERTY_UPDATE;
break;
case ADS_PROPERTY_APPEND:
dwFlags = PROPERTY_ADD;
break;
case ADS_PROPERTY_DELETE:
dwFlags = PROPERTY_DELETE_VALUE;
break;
default:
RRETURN_EXP_IF_ERR(hr = E_ADS_BAD_PARAMETER);
}
if ( dwFlags != PROPERTY_DELETE )
{
//
// A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
// We should dereference a VT_BYREF|VT_VARIANT once and see
// what's inside.
//
pvProp = &vProp;
if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) {
pvProp = V_VARIANTREF(&vProp);
}
if ((V_VT(pvProp) == (VT_VARIANT|VT_ARRAY|VT_BYREF)) ||
(V_VT(pvProp) == (VT_VARIANT|VT_ARRAY))) {
hr = ConvertSafeArrayToVariantArray(
*pvProp,
&pVarArray,
&dwNumValues
);
// returns E_FAIL if *pvProp is invalid
if (hr == E_FAIL)
hr = E_ADS_BAD_PARAMETER;
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
} else {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
if (pvProp == NULL) {
//
// If array is empty, set dwSyntaxId to Unknown. This value will not be used
//
dwSyntaxId = LDAPTYPE_UNKNOWN;
}
else {
hr = GetLdapSyntaxFromVariant(
pvProp,
&dwSyntaxId,
_pszLDAPServer,
bstrName,
_Credentials,
_dwPort
);
BAIL_ON_FAILURE(hr);
if ( dwSyntaxId == LDAPTYPE_UNKNOWN )
{
//
// If array is empty, set dwSyntaxId to Unknown. This value will
// not be used
//
hr = E_ADS_CANT_CONVERT_DATATYPE;
BAIL_ON_FAILURE(hr);
}
}
//
// check if the variant maps to the syntax of this property
//
if ( dwNumValues > 0 )
{
hr = VarTypeToLdapTypeCopyConstruct(
_pszLDAPServer,
_Credentials,
dwSyntaxId,
pvProp,
dwNumValues,
&ldapDestObjects
);
BAIL_ON_FAILURE(hr);
}
}
//
// Find this property in the cache
//
hr = _pPropertyCache->findproperty(
bstrName,
&dwIndex
);
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) {
hr = _pPropertyCache->addproperty( bstrName );
//
// If dwNumValues == 0 ( delete the property ) but couldn't find
// the property, or if the add operation fails, return the error.
//
BAIL_ON_FAILURE(hr);
fIndexValid = FALSE;
}
//
// Now update the property in the cache
//
if (fIndexValid) {
// do an optimized put property with the index
hr = _pPropertyCache->putproperty(
dwIndex,
dwFlags,
dwSyntaxId,
ldapDestObjects
);
} else {
// we need to use the property name in this case
hr = _pPropertyCache->putproperty(
bstrName,
dwFlags,
dwSyntaxId,
ldapDestObjects
);
}
BAIL_ON_FAILURE(hr);
error:
LdapTypeFreeLdapObjects( &ldapDestObjects );
if (pVarArray) {
DWORD i = 0;
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
RRETURN_EXP_IF_ERR(hr);
}