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

905 lines
22 KiB
C++

//---------------------------------------------------------------------------
//
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cdsobj.cxx
//
// Contents: Microsoft ADs NDS Provider Generic Object
//
//
// History: 01-10-97 krishnag Created.
//
//----------------------------------------------------------------------------
#include "nds.hxx"
#pragma hdrstop
HRESULT
CNDSGenObject::SetObjectAttributes(
PADS_ATTR_INFO pAttributeEntries,
DWORD dwNumAttributes,
DWORD *pdwNumAttributesModified
)
{
HRESULT hr = S_OK;
NDS_BUFFER_HANDLE hOperationData = NULL;
DWORD i = 0;
PADS_ATTR_INFO pThisAttribute = NULL;
DWORD dwStatus = 0;
PNDSOBJECT pNdsDestObjects = NULL;
DWORD dwNumNdsValues = 0;
DWORD dwSyntaxId = 0;
DWORD dwNumNDSAttributeReturn = 0;
*pdwNumAttributesModified = 0;
if (dwNumAttributes <= 0) {
RRETURN(E_FAIL);
}
hr = ADsNdsCreateBuffer(
_hADsContext,
DSV_MODIFY_ENTRY,
&hOperationData
);
BAIL_ON_FAILURE(hr);
for (i = 0; i < dwNumAttributes; i++) {
pThisAttribute = pAttributeEntries + i;
switch (pThisAttribute->dwControlCode) {
case ADS_ATTR_UPDATE:
hr = AdsTypeToNdsTypeCopyConstruct(
pThisAttribute->pADsValues,
pThisAttribute->dwNumValues,
&pNdsDestObjects,
&dwNumNdsValues,
&dwSyntaxId
);
CONTINUE_ON_FAILURE(hr);
hr = ADsNdsPutInBuffer(
_hADsContext,
hOperationData,
pThisAttribute->pszAttrName,
dwSyntaxId,
NULL,
0,
DS_CLEAR_ATTRIBUTE
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsPutInBuffer(
_hADsContext,
hOperationData,
pThisAttribute->pszAttrName,
dwSyntaxId,
pNdsDestObjects,
dwNumNdsValues,
DS_ADD_ATTRIBUTE
);
BAIL_ON_FAILURE(hr);
dwNumNDSAttributeReturn++;
break;
case ADS_ATTR_APPEND:
hr = AdsTypeToNdsTypeCopyConstruct(
pThisAttribute->pADsValues,
pThisAttribute->dwNumValues,
&pNdsDestObjects,
&dwNumNdsValues,
&dwSyntaxId
);
CONTINUE_ON_FAILURE(hr);
hr = ADsNdsPutInBuffer(
_hADsContext,
hOperationData,
pThisAttribute->pszAttrName,
dwSyntaxId,
pNdsDestObjects,
dwNumNdsValues,
DS_ADD_VALUE
);
BAIL_ON_FAILURE(hr);
dwNumNDSAttributeReturn++;
break;
case ADS_ATTR_DELETE:
hr = AdsTypeToNdsTypeCopyConstruct(
pThisAttribute->pADsValues,
pThisAttribute->dwNumValues,
&pNdsDestObjects,
&dwNumNdsValues,
&dwSyntaxId
);
CONTINUE_ON_FAILURE(hr);
hr = ADsNdsPutInBuffer(
_hADsContext,
hOperationData,
pThisAttribute->pszAttrName,
dwSyntaxId,
pNdsDestObjects,
dwNumNdsValues,
DS_REMOVE_VALUE
);
BAIL_ON_FAILURE(hr);
dwNumNDSAttributeReturn++;
break;
case ADS_ATTR_CLEAR:
hr = ADsNdsPutInBuffer(
_hADsContext,
hOperationData,
pThisAttribute->pszAttrName,
dwSyntaxId,
NULL,
0,
DS_CLEAR_ATTRIBUTE
);
BAIL_ON_FAILURE(hr);
dwNumNDSAttributeReturn++;
break;
default:
//
// Ignore this attribute and move on.
//
break;
}
// Clean-up in preparation for next iteration.
// Need to set pNdsDestObjects to NULL so we
// don't try to free it again in exit code.
if (pNdsDestObjects)
{
NdsTypeFreeNdsObjects(
pNdsDestObjects,
dwNumNdsValues
);
pNdsDestObjects = NULL;
}
}
hr = ADsNdsModifyObject(
_hADsContext,
_pszNDSDn,
hOperationData
);
BAIL_ON_FAILURE(hr);
*pdwNumAttributesModified = dwNumNDSAttributeReturn;
error:
if (pNdsDestObjects) {
NdsTypeFreeNdsObjects(
pNdsDestObjects,
dwNumNdsValues
);
}
if (hOperationData) {
ADsNdsFreeBuffer(hOperationData);
}
RRETURN(hr);
}
HRESULT
CNDSGenObject::GetObjectAttributes(
LPWSTR * pAttributeNames,
DWORD dwNumberAttributes,
PADS_ATTR_INFO *ppAttributeEntries,
DWORD * pdwNumAttributesReturned
)
{
HRESULT hr = S_OK;
DWORD i = 0;
DWORD dwNdsSyntaxId = 0;
DWORD dwNumValues = 0;
NDS_BUFFER_HANDLE hOperationData = NULL;
DWORD dwStatus = 0;
HANDLE hObject = NULL;
LPWSTR * pThisAttributeName = NULL;
PADS_ATTR_INFO pAdsAttributes = NULL;
PADS_ATTR_INFO pThisAttributeDef = NULL;
DWORD dwAttrCount = 0;
DWORD dwNumberOfEntries = 0;
LPNDS_ATTR_INFO lpEntries = NULL;
PADSVALUE pAdsDestValues = NULL;
DWORD j = 0;
PADS_ATTR_INFO pThisAdsSrcAttribute = NULL;
PADS_ATTR_INFO pThisAdsTargAttribute = NULL;
PADS_ATTR_INFO pAttrEntry = NULL;
PADSVALUE pAttrValue = NULL;
DWORD dwMemSize = 0;
LPBYTE pAttributeBuffer = NULL;
LPBYTE pValueBuffer = NULL;
LPBYTE pDataBuffer = NULL;
PADSVALUE pThisAdsSrcValue = NULL;
PADSVALUE pThisAdsTargValue = NULL;
DWORD dwTotalValues = 0;
hr = ADsNdsReadObject(
_hADsContext,
_pszNDSDn,
DS_ATTRIBUTE_VALUES,
pAttributeNames,
dwNumberAttributes,
NULL,
&lpEntries,
&dwNumberOfEntries
);
BAIL_ON_FAILURE(hr);
//
// Allocate an attribute buffer which is as large as the
// number of attributes present
//
//
pAdsAttributes = (PADS_ATTR_INFO)AllocADsMem(
sizeof(ADS_ATTR_INFO)*dwNumberOfEntries
);
if (!pAdsAttributes){
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
for (i = 0; i < dwNumberOfEntries; i++) {
pThisAttributeDef = pAdsAttributes + dwAttrCount;
dwNumValues = lpEntries[i].dwNumberOfValues;
hr = NdsTypeToAdsTypeCopyConstruct(
lpEntries[i].lpValue,
lpEntries[i].dwNumberOfValues,
&pAdsDestValues
);
if (FAILED(hr)){
continue;
}
pThisAttributeDef->pszAttrName =
AllocADsStr(lpEntries[i].szAttributeName);
pThisAttributeDef->pADsValues = pAdsDestValues;
pThisAttributeDef->dwNumValues = dwNumValues;
pThisAttributeDef->dwADsType = g_MapNdsTypeToADsType[lpEntries[i].dwSyntaxId];
dwAttrCount++;
}
//
// Now package this data into a single contiguous buffer
//
hr = ComputeAttributeBufferSize(
pAdsAttributes,
dwAttrCount,
&dwMemSize
);
BAIL_ON_FAILURE(hr);
hr = ComputeNumberofValues(
pAdsAttributes,
dwAttrCount,
&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;
pThisAdsTargAttribute->pADsValues = pAttrValue;
pThisAdsTargAttribute->dwNumValues = pThisAdsSrcAttribute->dwNumValues;
pThisAdsTargAttribute->dwADsType = pThisAdsSrcAttribute->dwADsType;
dwNumValues = pThisAdsSrcAttribute->dwNumValues;
pThisAdsSrcValue = pThisAdsSrcAttribute->pADsValues;
pThisAdsTargValue = pAttrValue;
for (j = 0; j < dwNumValues; j++) {
pDataBuffer = AdsTypeCopy(
pThisAdsSrcValue,
pThisAdsTargValue,
pDataBuffer
);
pAttrValue++;
pThisAdsTargValue = pAttrValue;
pThisAdsSrcValue++;
}
pDataBuffer = AdsCopyAttributeName(
pThisAdsSrcAttribute,
pThisAdsTargAttribute,
pDataBuffer
);
}
hr = S_OK;
*ppAttributeEntries = (PADS_ATTR_INFO)pAttributeBuffer;
*pdwNumAttributesReturned = dwAttrCount;
cleanup:
//
// Clean up the header based Ods structures
//
FreeNdsAttrInfo( lpEntries, dwNumberOfEntries );
if (pAdsAttributes) {
for (i = 0; i < dwAttrCount; i++)
{
pThisAttributeDef = pAdsAttributes + i;
if (pThisAttributeDef->pszAttrName)
FreeADsStr(pThisAttributeDef->pszAttrName);
AdsFreeAdsValues(
pThisAttributeDef->pADsValues,
pThisAttributeDef->dwNumValues
);
FreeADsMem(pThisAttributeDef->pADsValues);
}
FreeADsMem(pAdsAttributes);
}
RRETURN(hr);
error:
if (pAttributeBuffer) {
FreeADsMem(pAttributeBuffer);
}
*ppAttributeEntries = (PADS_ATTR_INFO) NULL;
*pdwNumAttributesReturned = 0;
goto cleanup;
}
HRESULT
CNDSGenObject::CreateDSObject(
LPWSTR pszRDNName,
PADS_ATTR_INFO pAttributeEntries,
DWORD dwNumAttributes,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
WCHAR *pszNDSTreeName = NULL;
WCHAR *pszNDSDn = NULL;
NDS_BUFFER_HANDLE hOperationData = NULL;
DWORD i = 0;
PADS_ATTR_INFO pThisAttribute = NULL;
DWORD dwStatus = 0;
PNDSOBJECT pNdsDestObjects = NULL;
DWORD dwNumNdsValues = 0;
DWORD dwSyntaxId = 0;
IADs *pADs = NULL;
TCHAR szADsClassName[64];
BSTR bstrChildPath = NULL;
hr = BuildADsPath(
_ADsPath,
pszRDNName,
&bstrChildPath
);
BAIL_ON_FAILURE(hr);
hr = BuildNDSPathFromADsPath2(
bstrChildPath,
&pszNDSTreeName,
&pszNDSDn
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsCreateBuffer(
_hADsContext,
DSV_ADD_ENTRY,
&hOperationData
);
BAIL_ON_FAILURE(hr);
for (i = 0; i < dwNumAttributes; i++) {
pThisAttribute = pAttributeEntries + i;
hr = AdsTypeToNdsTypeCopyConstruct(
pThisAttribute->pADsValues,
pThisAttribute->dwNumValues,
&pNdsDestObjects,
&dwNumNdsValues,
&dwSyntaxId
);
CONTINUE_ON_FAILURE(hr);
hr = ADsNdsPutInBuffer(
_hADsContext,
hOperationData,
pThisAttribute->pszAttrName,
dwSyntaxId,
pNdsDestObjects,
dwNumNdsValues,
DS_ADD_ATTRIBUTE
);
BAIL_ON_FAILURE(hr);
if (pNdsDestObjects) {
NdsTypeFreeNdsObjects(
pNdsDestObjects,
dwNumNdsValues
);
pNdsDestObjects = NULL;
}
}
hr = ADsNdsAddObject(
_hADsContext,
pszNDSDn,
hOperationData
);
BAIL_ON_FAILURE(hr);
for (i = 0; i < dwNumAttributes; i++) {
pThisAttribute = pAttributeEntries + i;
if ( _tcsicmp( pThisAttribute->pszAttrName,
TEXT("Object Class")) == 0 ) {
_tcscpy( szADsClassName,
(LPTSTR)pThisAttribute->pADsValues->CaseIgnoreString);
break;
}
}
//
// If the object is a user object, we set the initial password to NULL.
//
if (_wcsicmp(szADsClassName, L"user") == 0) {
hr = ADsNdsGenObjectKey(_hADsContext,
pszNDSDn);
BAIL_ON_FAILURE(hr);
}
hr = CNDSGenObject::CreateGenericObject(
_ADsPath,
pszRDNName,
szADsClassName,
_Credentials,
ADS_OBJECT_BOUND,
IID_IADs,
(void **)&pADs
);
BAIL_ON_FAILURE(hr);
hr = InstantiateDerivedObject(
pADs,
_Credentials,
IID_IDispatch,
(void **)ppObject
);
if (FAILED(hr)) {
hr = pADs->QueryInterface(
IID_IDispatch,
(void **)ppObject
);
BAIL_ON_FAILURE(hr);
}
error:
if (pADs) {
pADs->Release();
}
if (pNdsDestObjects) {
NdsTypeFreeNdsObjects(
pNdsDestObjects,
dwNumNdsValues
);
}
if (pszNDSTreeName) {
FreeADsStr(pszNDSTreeName);
}
if (pszNDSDn) {
FreeADsStr(pszNDSDn);
}
if (bstrChildPath) {
SysFreeString(bstrChildPath);
}
if (hOperationData) {
ADsNdsFreeBuffer(hOperationData);
}
RRETURN(hr);
}
HRESULT
CNDSGenObject::DeleteDSObject(
LPWSTR pszRDNName
)
{
WCHAR *pszNDSTreeName = NULL, *pszNDSDn = NULL ;
HRESULT hr = S_OK;
DWORD dwStatus = 0;
BSTR bstrChildPath = NULL;
hr = BuildADsPath(
_ADsPath,
pszRDNName,
&bstrChildPath
);
BAIL_ON_FAILURE(hr);
hr = BuildNDSPathFromADsPath2(
bstrChildPath,
&pszNDSTreeName,
&pszNDSDn
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsRemoveObject(
_hADsContext,
pszNDSDn
);
BAIL_ON_FAILURE(hr);
error:
if (bstrChildPath) {
SysFreeString(bstrChildPath);
}
if (pszNDSTreeName) {
FreeADsStr(pszNDSTreeName);
}
if (pszNDSDn) {
FreeADsStr(pszNDSDn);
}
RRETURN(hr);
}
HRESULT
ComputeAttributeBufferSize(
PADS_ATTR_INFO pAdsAttributes,
DWORD dwNumAttributes,
PDWORD pdwSize
)
{
DWORD i = 0;
DWORD j = 0;
PADS_ATTR_INFO pThisAttribute = NULL;
PADSVALUE pAdsSrcValues = NULL;
DWORD dwSize = 0;
DWORD dwVarSz = 0;
DWORD dwNumValues = 0;
HRESULT hr = S_OK;
for (i = 0; i < dwNumAttributes; i++) {
pThisAttribute = pAdsAttributes + i;
dwNumValues = pThisAttribute->dwNumValues;
pAdsSrcValues = pThisAttribute->pADsValues;
for (j = 0; j < dwNumValues; j++) {
dwVarSz = AdsTypeSize(pAdsSrcValues + j);
dwSize += dwVarSz;
dwSize += sizeof(ADSVALUE);
}
dwSize += sizeof(ADS_ATTR_INFO);
dwSize += (wcslen(pThisAttribute->pszAttrName) + 1)*sizeof(WCHAR);
}
*pdwSize = dwSize;
RRETURN(S_OK);
}
HRESULT
ComputeNumberofValues(
PADS_ATTR_INFO pAdsAttributes,
DWORD dwNumAttributes,
PDWORD pdwNumValues
)
{
DWORD i = 0;
PADS_ATTR_INFO pThisAttribute = NULL;
DWORD dwNumValues = 0;
DWORD dwTotalNumValues = 0;
for (i = 0; i < dwNumAttributes; i++) {
pThisAttribute = pAdsAttributes + i;
dwNumValues = pThisAttribute->dwNumValues;
dwTotalNumValues += dwNumValues;
}
*pdwNumValues = dwTotalNumValues;
RRETURN(S_OK);
}
DWORD
ComputeObjectInfoSize(
PADS_OBJECT_INFO pObjectInfo
)
{
DWORD dwLen = 0;
dwLen += (wcslen(pObjectInfo->pszRDN) + 1) * sizeof(WCHAR);
dwLen += (wcslen(pObjectInfo->pszObjectDN) + 1) * sizeof(WCHAR);
dwLen += (wcslen(pObjectInfo->pszParentDN) + 1) * sizeof(WCHAR);
dwLen += (wcslen(pObjectInfo->pszSchemaDN) + 1) * sizeof(WCHAR);
dwLen += (wcslen(pObjectInfo->pszClassName) + 1) * sizeof(WCHAR);
dwLen += sizeof(ADS_OBJECT_INFO);
return(dwLen);
}
LPBYTE
PackStrings(
LPWSTR *pSource,
LPBYTE pDest,
DWORD *DestOffsets,
LPBYTE pEnd
);
//
// This assumes that addr is an LPBYTE type.
//
#define WORD_ALIGN_DOWN(addr) \
addr = ((LPBYTE)((DWORD)addr & ~1))
DWORD ObjectInfoStrings[] =
{
FIELD_OFFSET(ADS_OBJECT_INFO, pszRDN),
FIELD_OFFSET(ADS_OBJECT_INFO, pszObjectDN),
FIELD_OFFSET(ADS_OBJECT_INFO, pszParentDN),
FIELD_OFFSET(ADS_OBJECT_INFO, pszSchemaDN),
FIELD_OFFSET(ADS_OBJECT_INFO, pszClassName),
0xFFFFFFFF
};
HRESULT
MarshallObjectInfo(
PADS_OBJECT_INFO pSrcObjectInfo,
LPBYTE pDestObjectInfo,
LPBYTE pEnd
)
{
LPWSTR SourceStrings[sizeof(ADS_OBJECT_INFO)/sizeof(LPWSTR)];
LPWSTR *pSourceStrings=SourceStrings;
memset(SourceStrings, 0, sizeof(ADS_OBJECT_INFO));
*pSourceStrings++ = pSrcObjectInfo->pszRDN;
*pSourceStrings++ = pSrcObjectInfo->pszObjectDN;
*pSourceStrings++ = pSrcObjectInfo->pszParentDN;
*pSourceStrings++ = pSrcObjectInfo->pszSchemaDN;
*pSourceStrings++ = pSrcObjectInfo->pszClassName;
pEnd = PackStrings(
SourceStrings,
pDestObjectInfo,
ObjectInfoStrings,
pEnd
);
RRETURN(S_OK);
}
HRESULT
CNDSGenObject::GetObjectInformation(
THIS_ PADS_OBJECT_INFO * ppObjInfo
)
{
ADS_OBJECT_INFO ObjectInfo;
PADS_OBJECT_INFO pObjectInfo = &ObjectInfo;
LPBYTE pBuffer = NULL;
DWORD dwSize = 0;
HRESULT hr = S_OK;
pObjectInfo->pszRDN = _Name;
pObjectInfo->pszObjectDN = _ADsPath;
pObjectInfo->pszParentDN = _Parent;
pObjectInfo->pszSchemaDN = _Schema;
pObjectInfo->pszClassName = _ADsClass;
dwSize = ComputeObjectInfoSize(pObjectInfo);
pBuffer = (LPBYTE)AllocADsMem(dwSize);
if (!pBuffer) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
hr = MarshallObjectInfo(
pObjectInfo,
pBuffer,
pBuffer + dwSize
);
BAIL_ON_FAILURE(hr);
*ppObjInfo = (PADS_OBJECT_INFO)pBuffer;
error:
RRETURN(hr);
}
LPBYTE
PackStrings(
LPWSTR *pSource,
LPBYTE pDest,
DWORD *DestOffsets,
LPBYTE pEnd
)
{
DWORD cbStr;
WORD_ALIGN_DOWN(pEnd);
while (*DestOffsets != -1) {
if (*pSource) {
cbStr = wcslen(*pSource)*sizeof(WCHAR) + sizeof(WCHAR);
pEnd -= cbStr;
CopyMemory( pEnd, *pSource, cbStr);
*(LPWSTR *)(pDest+*DestOffsets) = (LPWSTR)pEnd;
} else {
*(LPWSTR *)(pDest+*DestOffsets)=0;
}
pSource++;
DestOffsets++;
}
return pEnd;
}
LPBYTE
AdsCopyAttributeName(
PADS_ATTR_INFO pThisAdsSrcAttribute,
PADS_ATTR_INFO pThisAdsTargAttribute,
LPBYTE pDataBuffer
)
{
LPWSTR pCurrentPos = (LPWSTR)pDataBuffer;
wcscpy(pCurrentPos, pThisAdsSrcAttribute->pszAttrName);
pThisAdsTargAttribute->pszAttrName = pCurrentPos;
pDataBuffer = pDataBuffer + (wcslen(pThisAdsSrcAttribute->pszAttrName) + 1)*sizeof(WCHAR);
return(pDataBuffer);
}