603 lines
14 KiB
C++
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);
|
|
}
|
|
|