|
|
//---------------------------------------------------------------------------
//
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1997
//
// File: cdsobj.cxx
//
// Contents: Microsoft ADs LDAP Provider DSObject
//
//
// History: 02-20-97 yihsins Created.
//
//----------------------------------------------------------------------------
#include "ldapc.hxx"
#pragma hdrstop
//
//Hard Coded Support for RootDSE object
//
LPWSTR SpecialSyntaxesTable[] = { LDAP_OPATT_CURRENT_TIME_W, LDAP_OPATT_SUBSCHEMA_SUBENTRY_W, LDAP_OPATT_SERVER_NAME_W, LDAP_OPATT_NAMING_CONTEXTS_W, LDAP_OPATT_DEFAULT_NAMING_CONTEXT_W, LDAP_OPATT_SCHEMA_NAMING_CONTEXT_W, LDAP_OPATT_CONFIG_NAMING_CONTEXT_W, LDAP_OPATT_ROOT_DOMAIN_NAMING_CONTEXT_W, LDAP_OPATT_SUPPORTED_CONTROL_W, LDAP_OPATT_SUPPORTED_LDAP_VERSION_W, L"lowestUncommittedUSN", L"allowedAttributesEffective", L"supportedExtension", L"altServer", NULL };
HRESULT ComputeAttributeBufferSize( PADS_ATTR_INFO pAdsAttributes, DWORD dwNumAttributes, PDWORD pdwSize, PDWORD pdwNumValues );
LPBYTE CopyAttributeName( PADS_ATTR_INFO pThisAdsSrcAttribute, PADS_ATTR_INFO pThisAdsTargAttribute, LPBYTE pDataBuffer );
HRESULT ADsSetObjectAttributes( ADS_LDP *ld, LPTSTR pszLDAPServer, LPTSTR pszLDAPDn, CCredentials Credentials, DWORD dwPort, SECURITY_INFORMATION seInfo, PADS_ATTR_INFO pAttributeEntries, DWORD dwNumAttributes, DWORD *pdwNumAttributesModified ) { HRESULT hr = S_OK;
DWORD i = 0; DWORD j = 0; PADS_ATTR_INFO pThisAttribute = NULL;
LDAPOBJECTARRAY ldapObjectArray; DWORD dwSyntaxId = 0;
LDAPMod **aMods = NULL; LDAPModW *aModsBuffer = NULL; DWORD dwNumAttributesReturn = 0; BOOL fNTSecDescriptor = FALSE; int ldaperr = 0; DWORD dwOptions = 0;
DWORD dwSecDescType = ADSI_LDAPC_SECDESC_NONE; BOOL fModifyDone = FALSE;
BYTE berValue[8];
memset(berValue, 0, 8);
berValue[0] = 0x30; // Start sequence tag
berValue[1] = 0x03; // Length in bytes of following
berValue[2] = 0x02; // Actual value this and next 2
berValue[3] = 0x01; berValue[4] = (BYTE)((ULONG)seInfo);
LDAPControl SeInfoControl = { LDAP_SERVER_SD_FLAGS_OID_W, { 5, (PCHAR) berValue }, TRUE };
LDAPControl ModifyControl = { LDAP_SERVER_PERMISSIVE_MODIFY_OID_W, { 0, NULL }, FALSE };
PLDAPControl ServerControls[2] = { &SeInfoControl, NULL };
PLDAPControl ServerControlsOnlyModify[2] = { &ModifyControl, NULL };
PLDAPControl ServerControlsAll[3] = { &SeInfoControl, &ModifyControl, NULL };
BOOL fServerIsAD = FALSE;
*pdwNumAttributesModified = 0;
//
// Allocate memory to send the modify request
//
aMods = (LDAPModW **) AllocADsMem((dwNumAttributes+1) * sizeof(LDAPModW*)); if ( aMods == NULL ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
aModsBuffer = (LDAPModW *) AllocADsMem( dwNumAttributes * sizeof(LDAPModW)); if ( aModsBuffer == NULL ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
//
// Format the modify request
//
for (i = 0; i < dwNumAttributes; i++) {
BOOL fGenTime = FALSE; LDAPOBJECTARRAY_INIT(ldapObjectArray);
pThisAttribute = pAttributeEntries + i;
if(!pThisAttribute) { hr = E_ADS_BAD_PARAMETER; BAIL_ON_FAILURE(hr); }
if (!fNTSecDescriptor && _wcsicmp(L"ntSecurityDescriptor", pThisAttribute->pszAttrName) == 0) {
{ // we need to use appropriate controls if the operation
// is modify the security descriptor. Specifically we do
// not want to use any control if the operation is a clear
// and default to whatever the server deems fit.
if (pThisAttribute->dwControlCode != ADS_ATTR_CLEAR) { fNTSecDescriptor = TRUE; } } }
if (pThisAttribute->dwControlCode != ADS_ATTR_CLEAR) { //
// If this is a time attribute, see if it is GenTime or
// UTCTime and set the syntax the flag appropriately
//
if (pThisAttribute->dwADsType == ADSTYPE_UTC_TIME) {
hr = LdapGetSyntaxOfAttributeOnServer( pszLDAPServer, pThisAttribute->pszAttrName, &dwSyntaxId, Credentials, dwPort ); if (SUCCEEDED(hr) && (dwSyntaxId == LDAPTYPE_GENERALIZEDTIME)) { //
// Use GenTime conversion
//
fGenTime = TRUE; }
}
}
switch (pThisAttribute->dwControlCode) { case ADS_ATTR_UPDATE: hr = AdsTypeToLdapTypeCopyConstruct( pThisAttribute->pADsValues, pThisAttribute->dwNumValues, &ldapObjectArray, &dwSyntaxId, fGenTime ); BAIL_ON_FAILURE(hr);
aMods[i] = &aModsBuffer[i]; aModsBuffer[i].mod_type = pThisAttribute->pszAttrName;
if ( ldapObjectArray.fIsString ) { aModsBuffer[i].mod_values = (TCHAR **) ldapObjectArray.pLdapObjects; } else { aModsBuffer[i].mod_bvalues = (struct berval **) ldapObjectArray.pLdapObjects; aModsBuffer[i].mod_op = LDAP_MOD_BVALUES; }
aModsBuffer[i].mod_op |= LDAP_MOD_REPLACE; dwNumAttributesReturn++; break;
case ADS_ATTR_APPEND: hr = AdsTypeToLdapTypeCopyConstruct( pThisAttribute->pADsValues, pThisAttribute->dwNumValues, &ldapObjectArray, &dwSyntaxId, fGenTime ); BAIL_ON_FAILURE(hr);
aMods[i] = &aModsBuffer[i]; aModsBuffer[i].mod_type = pThisAttribute->pszAttrName;
if ( ldapObjectArray.fIsString ) { aModsBuffer[i].mod_values = (TCHAR **) ldapObjectArray.pLdapObjects; } else { aModsBuffer[i].mod_bvalues = (struct berval **) ldapObjectArray.pLdapObjects; aModsBuffer[i].mod_op = LDAP_MOD_BVALUES; }
aModsBuffer[i].mod_op |= LDAP_MOD_ADD; dwNumAttributesReturn++; break;
case ADS_ATTR_CLEAR: aMods[i] = &aModsBuffer[i]; aModsBuffer[i].mod_type = pThisAttribute->pszAttrName; aModsBuffer[i].mod_bvalues = NULL; aModsBuffer[i].mod_op |= LDAP_MOD_DELETE; dwNumAttributesReturn++; break;
case ADS_ATTR_DELETE: hr = AdsTypeToLdapTypeCopyConstruct( pThisAttribute->pADsValues, pThisAttribute->dwNumValues, &ldapObjectArray, &dwSyntaxId, fGenTime ); BAIL_ON_FAILURE(hr);
aMods[i] = &aModsBuffer[i]; aModsBuffer[i].mod_type = pThisAttribute->pszAttrName;
if ( ldapObjectArray.fIsString ) { aModsBuffer[i].mod_values = (TCHAR **) ldapObjectArray.pLdapObjects; } else { aModsBuffer[i].mod_bvalues = (struct berval **) ldapObjectArray.pLdapObjects; aModsBuffer[i].mod_op = LDAP_MOD_BVALUES; }
aModsBuffer[i].mod_op |= LDAP_MOD_DELETE; dwNumAttributesReturn++; break;
default: //
// ignore this attribute and move on
//
break;
}
}
//
// Find out if server is AD.
//
hr = ReadServerSupportsIsADControl( pszLDAPServer, &fServerIsAD, Credentials, dwPort ); if (FAILED(hr)) { //
// Assume it is not AD and continue, there is no
// good reason for this to fail on AD.
//
fServerIsAD = FALSE; }
//
// Modify the object with appropriate call
//
if (fNTSecDescriptor) { //
// Check if we are V3
//
ldaperr = ldap_get_option( ld->LdapHandle, LDAP_OPT_VERSION, &dwOptions );
//
// check supported controls and set accordingly
//
if (ldaperr == LDAP_SUCCESS && (dwOptions == LDAP_VERSION3)) {
//
// Read the security descriptor type if applicable
//
hr = ReadSecurityDescriptorControlType( pszLDAPServer, &dwSecDescType, Credentials, dwPort );
if (SUCCEEDED(hr) && (dwSecDescType == ADSI_LDAPC_SECDESC_NT)) {
hr = LdapModifyExtS( ld, pszLDAPDn, aMods, fServerIsAD ? (PLDAPControl *) &ServerControlsAll : (PLDAPControl *) &ServerControls, NULL );
fModifyDone = TRUE;
} } // If Read Version succeeded
}
//
// Perform a simple modify - only if fModifyDone is false
//
if (!fModifyDone) {
if (fServerIsAD) {
//
// Need to send the OID that allows delete on empty attributes
// without sending an error - for clients that have gotten used
// to bad practices.
//
hr = LdapModifyExtS( ld, pszLDAPDn, aMods, (PLDAPControl *)&ServerControlsOnlyModify, NULL ); } else {
//
// Regular calls from most folks not using AD.
//
hr = LdapModifyS( ld, pszLDAPDn, aMods ); } }
BAIL_ON_FAILURE(hr);
*pdwNumAttributesModified = dwNumAttributesReturn;
error:
if ( aModsBuffer ) { for ( j = 0; j < i; j++ ) { if ( aModsBuffer[j].mod_op & LDAP_MOD_BVALUES ) { if ( aModsBuffer[j].mod_bvalues ) { for ( DWORD k = 0; aModsBuffer[j].mod_bvalues[k]; k++ ) FreeADsMem( aModsBuffer[j].mod_bvalues[k] );
FreeADsMem( aModsBuffer[j].mod_bvalues ); } } else if ( aModsBuffer[j].mod_values ) { for ( DWORD k = 0; aModsBuffer[j].mod_values[k]; k++ ) FreeADsMem( aModsBuffer[j].mod_values[k] );
FreeADsMem( aModsBuffer[j].mod_values ); } }
FreeADsMem( aModsBuffer ); }
if ( aMods ) FreeADsMem( aMods );
return hr; }
HRESULT ADsGetObjectAttributes( ADS_LDP *ld, LPTSTR pszLDAPServer, LPTSTR pszLDAPDn, CCredentials Credentials, DWORD dwPort, SECURITY_INFORMATION seInfo, LPWSTR *pAttributeNames, DWORD dwNumberAttributes, PADS_ATTR_INFO *ppAttributeEntries, DWORD * pdwNumAttributesReturned ) { HRESULT hr = S_OK;
DWORD i = 0; DWORD j = 0;
LPWSTR *aStrings = NULL;
LDAPMessage *res = NULL; LDAPMessage *entry = NULL; void *ptr; DWORD dwNumberOfEntries = 0; LPTSTR pszAttrName = NULL; LDAPOBJECTARRAY ldapObjectArray; PADSVALUE pAdsDestValues = NULL; DWORD dwNumAdsValues = 0; DWORD dwAdsType = 0;
DWORD dwSyntaxId = 0;
PADS_ATTR_INFO pAdsAttributes = NULL; PADS_ATTR_INFO pThisAttributeDef = NULL;
LPBYTE pAttributeBuffer = NULL; DWORD dwAttrCount = 0;
DWORD dwMemSize = 0; DWORD dwTotalValues = 0; DWORD dwNumValues = 0; LPBYTE pValueBuffer = NULL; LPBYTE pDataBuffer = NULL; PADS_ATTR_INFO pAttrEntry = NULL; PADSVALUE pAttrValue = NULL;
PADS_ATTR_INFO pThisAdsSrcAttribute = NULL; PADS_ATTR_INFO pThisAdsTargAttribute = NULL; PADSVALUE pThisAdsSrcValue = NULL; PADSVALUE pThisAdsTargValue = NULL;
*ppAttributeEntries = NULL; *pdwNumAttributesReturned = 0;
DWORD ldaperr = 0; DWORD dwOptions = 0;
BOOLEAN getSecDesc = FALSE; DWORD dwSecDescType = ADSI_LDAPC_SECDESC_NONE; BOOLEAN fSearchDone = FALSE;
BYTE berValue[8];
memset(berValue, 0, 8);
berValue[0] = 0x30; // Start sequence tag
berValue[1] = 0x03; // Length in bytes of following
berValue[2] = 0x02; // Actual value this and next 2
berValue[3] = 0x01; berValue[4] = (BYTE)((ULONG)seInfo);
LDAPControl SeInfoControl = { LDAP_SERVER_SD_FLAGS_OID_W, { 5, (PCHAR) berValue }, TRUE };
PLDAPControl ServerControls[2] = { &SeInfoControl, NULL };
LDAPOBJECTARRAY_INIT(ldapObjectArray);
if (dwNumberAttributes != (DWORD)-1) {
if ( dwNumberAttributes == 0 ) return S_OK;
if(!pAttributeNames) { hr = E_ADS_BAD_PARAMETER; BAIL_ON_FAILURE(hr); }
//
// Package attributes
//
aStrings = (LPWSTR *) AllocADsMem( sizeof(LPTSTR) * (dwNumberAttributes + 1));
if ( aStrings == NULL ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
for ( i = 0; i < dwNumberAttributes; i++) { if(!pAttributeNames[i]) { hr = E_ADS_BAD_PARAMETER; BAIL_ON_FAILURE(hr); } aStrings[i] = pAttributeNames[i];
if (!getSecDesc && _wcsicmp(L"ntSecurityDescriptor", pAttributeNames[i]) == 0) { // we need go to get the security descriptor
getSecDesc = TRUE; } } } else { //
// If all attributes are requested, we will mark as read
// security descriptor also. Further down, the decision to
// use or not use a control is made.
//
getSecDesc = TRUE; }
//
// Read the DS Object
//
// modified from LdapSearchS to LdapSearchExtS to get all attributes
// including SecurityDescriptor by one call
if (getSecDesc) {
ldaperr = ldap_get_option( ld->LdapHandle, LDAP_OPT_VERSION, &dwOptions );
if (dwOptions == LDAP_VERSION3) {
//
// Read the security descriptor type if applicable
//
hr = ReadSecurityDescriptorControlType( pszLDAPServer, &dwSecDescType, Credentials, dwPort );
//
// If we could no get the control information for whatever reason,
// just try the SearchS.
//
if (SUCCEEDED(hr) && (dwSecDescType == ADSI_LDAPC_SECDESC_NT)) {
hr = LdapSearchExtS( ld, pszLDAPDn, LDAP_SCOPE_BASE, TEXT("(objectClass=*)"), aStrings, 0, (PLDAPControl *)&ServerControls, NULL, NULL, 10000, &res );
fSearchDone = TRUE;
} } }
//
// Perform just a LdapSearchS if the flag indicates that
// no search has been done. We do not try a second search
// if the first tone failed (saves packets on the wire).
//
if (!fSearchDone) {
hr = LdapSearchS( ld, pszLDAPDn, LDAP_SCOPE_BASE, TEXT("(objectClass=*)"), aStrings, 0, &res );
fSearchDone = TRUE;
BAIL_ON_FAILURE(hr);
}
//
// Should only contain one entry
//
if ( LdapCountEntries( ld, res ) == 0 ) goto error;
hr = LdapFirstEntry( ld, res, &entry ); BAIL_ON_FAILURE(hr);
//
// Compute the number of attributes in the
// read buffer.
//
hr = LdapFirstAttribute( ld, entry, &ptr, &pszAttrName ); BAIL_ON_FAILURE(hr);
while ( pszAttrName != NULL ) { dwNumberOfEntries++; LdapAttributeFree( pszAttrName ); pszAttrName = NULL;
hr = LdapNextAttribute( ld, entry, ptr, &pszAttrName ); if (FAILED(hr)) break; // error occurred, ignore the rest of the attributes
}
//
// Allocate an attribute buffer which is as large as the
// number of attributes present
//
//
// Note that pADsAttributes is inited to Null
if (dwNumberOfEntries != 0) {
pAdsAttributes = (PADS_ATTR_INFO)AllocADsMem( sizeof(ADS_ATTR_INFO) * dwNumberOfEntries ); if (!pAdsAttributes) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } }
dwAttrCount = 0; ptr = NULL; hr = LdapFirstAttribute( ld, entry, &ptr, &pszAttrName );
while ( SUCCEEDED(hr) && ( pszAttrName != NULL ) && ( dwAttrCount < dwNumberOfEntries ) ) { //
// Get the syntax of the attribute. Force only
// if we know that the this is not the RootDSE
// as RootDSE attributes are not in schema.
//
hr = LdapGetSyntaxOfAttributeOnServer( pszLDAPServer, pszAttrName, &dwSyntaxId, Credentials, dwPort, pszLDAPDn ? TRUE : FALSE );
//
// If it failed with errorcode 0x8000500D which is
// E_ADS_PROPERTY_NOT_FOUND,
// see if it is one of the RootDSE syntaxes,
// if so set Syntax to ADSTYPE_CASE_IGNORE_STRING
//
if (hr == E_ADS_PROPERTY_NOT_FOUND) {
//
// search the hardcoded table to see if it is a known entry
//
BOOLEAN valFound = FALSE; DWORD ctr = 0; while (SpecialSyntaxesTable[ctr] && !valFound) { if (!_wcsicmp(pszAttrName, SpecialSyntaxesTable[ctr])) { dwSyntaxId = ADSTYPE_CASE_IGNORE_STRING; hr = S_OK; valFound = TRUE; } ctr++; } }else {
if (!_wcsicmp(pszAttrName, L"ntSecurityDescriptor")) { dwSyntaxId = LDAPTYPE_SECURITY_DESCRIPTOR; } }
if ( hr == E_ADS_PROPERTY_NOT_FOUND ) { //
// We will default to provider specific
//
dwSyntaxId = LDAPTYPE_UNKNOWN; } else if (FAILED(hr)) { //
// Some other failure so skip attribute
//
goto NextAttr; }
//
// Get the values of the current attribute
//
hr = UnMarshallLDAPToLDAPSynID( pszAttrName, ld, entry, dwSyntaxId, &ldapObjectArray );
if ( FAILED(hr)) goto NextAttr;
hr = LdapTypeToAdsTypeCopyConstruct( ldapObjectArray, dwSyntaxId, &pAdsDestValues, &dwNumAdsValues, &dwAdsType );
if (FAILED(hr)) goto NextAttr;
pThisAttributeDef = pAdsAttributes + dwAttrCount; pThisAttributeDef->pszAttrName = AllocADsStr(pszAttrName);
if ( !pThisAttributeDef->pszAttrName ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
pThisAttributeDef->pADsValues = pAdsDestValues; if ( pThisAttributeDef->dwNumValues = ldapObjectArray.dwCount ) pThisAttributeDef->dwADsType = pAdsDestValues[0].dwType; dwAttrCount++;
NextAttr:
if ( pszAttrName ) { LdapAttributeFree( pszAttrName ); pszAttrName = NULL; }
if ( ldapObjectArray.pLdapObjects ) { if ( ldapObjectArray.fIsString ) LdapValueFree( (TCHAR **) ldapObjectArray.pLdapObjects ); else LdapValueFreeLen( (struct berval **) ldapObjectArray.pLdapObjects );
LDAPOBJECTARRAY_INIT(ldapObjectArray); }
if ( hr == E_OUTOFMEMORY ) // break on serious error
break;
hr = LdapNextAttribute( ld, entry, ptr, &pszAttrName ); }
BAIL_ON_FAILURE(hr);
if ( dwAttrCount == 0 ) goto error;
//
// Now package this data into a single contiguous buffer
//
hr = ComputeAttributeBufferSize( pAdsAttributes, dwAttrCount, &dwMemSize, &dwTotalValues ); BAIL_ON_FAILURE(hr);
pAttributeBuffer = (LPBYTE) AllocADsMem( dwMemSize );
if (!pAttributeBuffer) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
pValueBuffer = pAttributeBuffer + dwAttrCount * (sizeof(ADS_ATTR_INFO)); pDataBuffer = pValueBuffer + dwTotalValues * sizeof(ADSVALUE);
pAttrEntry = (PADS_ATTR_INFO) pAttributeBuffer; pAttrValue = (PADSVALUE) pValueBuffer;
for (i = 0; i < dwAttrCount; i++) {
pThisAdsSrcAttribute = pAdsAttributes + i; pThisAdsTargAttribute = pAttrEntry + i;
dwNumValues = pThisAdsSrcAttribute->dwNumValues;
pThisAdsTargAttribute->dwNumValues = dwNumValues; pThisAdsTargAttribute->dwADsType = pThisAdsSrcAttribute->dwADsType; pThisAdsTargAttribute->pADsValues = pAttrValue;
pThisAdsSrcValue = pThisAdsSrcAttribute->pADsValues; pThisAdsTargValue = pAttrValue;
if (!pDataBuffer) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
for ( j = 0; j < dwNumValues; j++) {
pDataBuffer = AdsTypeCopy( pThisAdsSrcValue, pThisAdsTargValue, pDataBuffer ); pAttrValue++; pThisAdsTargValue = pAttrValue; pThisAdsSrcValue++;
}
if (!pDataBuffer) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
pDataBuffer = CopyAttributeName( pThisAdsSrcAttribute, pThisAdsTargAttribute, pDataBuffer );
}
hr = S_OK;
error:
if ( aStrings ) FreeADsMem( aStrings );
if ( res ) LdapMsgFree( res );
//
// Clean up the header based Ods structures
//
if ( pAdsAttributes ) {
for (i = 0; i < dwAttrCount; i++) { pThisAttributeDef = pAdsAttributes + i; FreeADsStr( pThisAttributeDef->pszAttrName );
AdsTypeFreeAdsObjects( pThisAttributeDef->pADsValues, pThisAttributeDef->dwNumValues ); }
FreeADsMem( pAdsAttributes ); }
if (FAILED(hr)) { if ( pAttributeBuffer ) FreeADsMem(pAttributeBuffer);
*ppAttributeEntries = NULL; *pdwNumAttributesReturned = 0; } else { *ppAttributeEntries = (PADS_ATTR_INFO)pAttributeBuffer; *pdwNumAttributesReturned = dwAttrCount; }
return hr; }
HRESULT ADsCreateDSObjectExt( ADS_LDP *ld, LPTSTR ADsPath, LPWSTR pszRDNName, PADS_ATTR_INFO pAttributeEntries, DWORD dwNumAttributes, SECURITY_INFORMATION seInfo, BOOL fSecDesc ) { HRESULT hr = S_OK; LPTSTR pszAbsoluteName = NULL; TCHAR *pszLDAPServer = NULL; LPWSTR pszLDAPDn = NULL; DWORD dwSyntaxId = 0;
DWORD dwPort = 0;
DWORD i = 0; DWORD j = 0; PADS_ATTR_INFO pThisAttribute = NULL;
LDAPOBJECTARRAY ldapObjectArray; LDAPMod **aMods = NULL; LDAPModW *aModsBuffer = NULL;
BYTE berValue[8];
memset(berValue, 0, 8);
berValue[0] = 0x30; // Start sequence tag
berValue[1] = 0x03; // Length in bytes of following
berValue[2] = 0x02; // Actual value this and next 2
berValue[3] = 0x01; berValue[4] = (BYTE)((ULONG)seInfo);
LDAPControl SeInfoControl = { LDAP_SERVER_SD_FLAGS_OID_W, { 5, (PCHAR) berValue }, TRUE };
PLDAPControl ServerControls[2] = { &SeInfoControl, NULL };
//
// Get the LDAP path of the object to create
//
hr = BuildADsPathFromParent( ADsPath, pszRDNName, &pszAbsoluteName ); BAIL_ON_FAILURE(hr);
hr = BuildLDAPPathFromADsPath2( pszAbsoluteName, &pszLDAPServer, &pszLDAPDn, &dwPort ); BAIL_ON_FAILURE(hr);
//
// Allocate memory to store the add request
//
aMods = (LDAPModW **) AllocADsMem((dwNumAttributes+1) * sizeof(LDAPModW*)); if ( aMods == NULL ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
aModsBuffer = (LDAPModW *) AllocADsMem( dwNumAttributes * sizeof(LDAPModW)); if ( aModsBuffer == NULL ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
//
// Format the add request
//
for (i = 0; i < dwNumAttributes; i++) {
BOOL fGenTime = FALSE;
LDAPOBJECTARRAY_INIT(ldapObjectArray);
pThisAttribute = pAttributeEntries + i; if (pThisAttribute->dwControlCode != ADS_ATTR_CLEAR) { //
// If this is a time attribute, see if it is GenTime or
// UTCTime and set the syntax the flag appropriately
//
if (pThisAttribute->dwADsType == ADSTYPE_UTC_TIME) {
hr = LdapGetSyntaxOfAttributeOnServer( pszLDAPServer, pThisAttribute->pszAttrName, &dwSyntaxId, (*ld->pCredentials), ld->PortNumber ); if (SUCCEEDED(hr) && (dwSyntaxId == LDAPTYPE_GENERALIZEDTIME)) { //
// Use GenTime conversion
//
fGenTime = TRUE; }
}
}
hr = AdsTypeToLdapTypeCopyConstruct( pThisAttribute->pADsValues, pThisAttribute->dwNumValues, &ldapObjectArray, &dwSyntaxId, fGenTime ); BAIL_ON_FAILURE(hr);
aMods[i] = &aModsBuffer[i]; aModsBuffer[i].mod_type = pThisAttribute->pszAttrName;
if ( ldapObjectArray.fIsString ) { aModsBuffer[i].mod_values = (TCHAR **) ldapObjectArray.pLdapObjects; } else { aModsBuffer[i].mod_bvalues = (struct berval **) ldapObjectArray.pLdapObjects; aModsBuffer[i].mod_op = LDAP_MOD_BVALUES; }
aModsBuffer[i].mod_op |= LDAP_MOD_REPLACE; }
if (fSecDesc) {
hr = LdapAddExtS( ld, pszLDAPDn, aMods, (PLDAPControl *)&ServerControls, NULL ); } else {
//
// Now, send the add request
//
hr = LdapAddS( ld, pszLDAPDn, aMods ); }
BAIL_ON_FAILURE(hr);
error:
if ( pszAbsoluteName ) { FreeADsStr( pszAbsoluteName ); }
if ( pszLDAPServer ) { FreeADsStr( pszLDAPServer ); }
if (pszLDAPDn) { FreeADsStr( pszLDAPDn); }
if ( aModsBuffer ) { for ( j = 0; j < i; j++ ) { if ( aModsBuffer[j].mod_op & LDAP_MOD_BVALUES ) { if ( aModsBuffer[j].mod_bvalues ) { for ( DWORD k = 0; aModsBuffer[j].mod_bvalues[k]; k++ ) FreeADsMem( aModsBuffer[j].mod_bvalues[k] );
FreeADsMem( aModsBuffer[j].mod_bvalues ); } } else if ( aModsBuffer[j].mod_values ) { for ( DWORD k = 0; aModsBuffer[j].mod_values[k]; k++ ) FreeADsMem( aModsBuffer[j].mod_values[k] );
FreeADsMem( aModsBuffer[j].mod_values ); } }
FreeADsMem( aModsBuffer ); }
if ( aMods ) FreeADsMem( aMods );
return hr; }
HRESULT ADsCreateDSObject( ADS_LDP *ld, LPTSTR ADsPath, LPWSTR pszRDNName, PADS_ATTR_INFO pAttributeEntries, DWORD dwNumAttributes ) {
RRETURN ( ADsCreateDSObjectExt( ld, ADsPath, pszRDNName, pAttributeEntries, dwNumAttributes, 0, // for seInfo since it is ignored
FALSE ) );
}
HRESULT ADsDeleteDSObject( ADS_LDP *ld, LPTSTR ADsPath, LPWSTR pszRDNName ) { HRESULT hr = S_OK; LPTSTR pszAbsoluteName = NULL; TCHAR *pszLDAPServer = NULL; LPWSTR pszLDAPDn = NULL; DWORD dwPort = 0;
//
// Get the LDAP path of the object to delete
//
hr = BuildADsPathFromParent( ADsPath, pszRDNName, &pszAbsoluteName ); BAIL_ON_FAILURE(hr);
hr = BuildLDAPPathFromADsPath2( pszAbsoluteName, &pszLDAPServer, &pszLDAPDn, &dwPort ); BAIL_ON_FAILURE(hr);
//
// Now, send the delete request
//
hr = LdapDeleteS( ld, pszLDAPDn ); BAIL_ON_FAILURE(hr);
error:
if ( pszAbsoluteName ) { FreeADsStr( pszAbsoluteName ); }
if ( pszLDAPServer ) { FreeADsStr( pszLDAPServer ); }
if (pszLDAPDn) { FreeADsStr(pszLDAPDn); }
return hr; }
HRESULT ComputeAttributeBufferSize( PADS_ATTR_INFO pAdsAttributes, DWORD dwNumAttributes, PDWORD pdwSize, PDWORD pdwNumValues ) { PADS_ATTR_INFO pThisAttribute = NULL; PADSVALUE pAdsSrcValues = NULL; DWORD dwNumValues = 0;
DWORD dwSize = 0; DWORD dwTotalNumValues = 0;
for ( DWORD i = 0; i < dwNumAttributes; i++) {
pThisAttribute = pAdsAttributes + i;
dwNumValues = pThisAttribute->dwNumValues;
dwTotalNumValues += dwNumValues;
pAdsSrcValues = pThisAttribute->pADsValues;
for ( DWORD j = 0; j < dwNumValues; j++) dwSize += AdsTypeSize(pAdsSrcValues + j) + sizeof(ADSVALUE);
dwSize += sizeof(ADS_ATTR_INFO); dwSize += ((wcslen(pThisAttribute->pszAttrName) + 1)*sizeof(WCHAR)) + (ALIGN_WORD-1); }
*pdwSize = dwSize; *pdwNumValues = dwTotalNumValues;
return S_OK; }
LPBYTE CopyAttributeName( PADS_ATTR_INFO pThisAdsSrcAttribute, PADS_ATTR_INFO pThisAdsTargAttribute, LPBYTE pDataBuffer ) {
//
// strings should be WCHAR (i.e., WORD) aligned
//
pDataBuffer = (LPBYTE) ROUND_UP_POINTER(pDataBuffer, ALIGN_WORD);
LPWSTR pCurrentPos = (LPWSTR)pDataBuffer;
wcscpy(pCurrentPos, pThisAdsSrcAttribute->pszAttrName);
pThisAdsTargAttribute->pszAttrName = pCurrentPos;
pDataBuffer = pDataBuffer + (wcslen(pThisAdsSrcAttribute->pszAttrName) + 1)*sizeof(WCHAR);
return(pDataBuffer); }
|