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

2649 lines
65 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1997
//
// File: ndsutil.cxx
//
// Contents: Functions that encapsulate NDS API functions for ADSI
//
//
// History:
// Shanksh Created 10/27/97
//----------------------------------------------------------------------------
#include "nds.hxx"
#pragma hdrstop
HRESULT
ADsNdsOpenContext(
LPWSTR pszNDSTreeName,
CCredentials& Credentials,
PNDS_CONTEXT_HANDLE phADsContext
)
{
NWDSCCODE ccode;
NWDSContextHandle context = 0;
BOOL fLoggedIn = FALSE;
HRESULT hr = S_OK;
PNDS_CONTEXT pADsContext = NULL;
PNDS_CONTEXT *ppADsContext = (PNDS_CONTEXT *) phADsContext;
nuint32 flags;
LPWSTR pszUserName = NULL, pszPassword = NULL;
pnstr8 aPassword = NULL;
nstr8 treeName[MAX_DN_CHARS+1];
DWORD dwLenUserName;
LPWSTR pszCanonicalUserName = NULL;
LPWSTR pbCanonicalUserName = NULL;
LPWSTR pszCanonicalPrefix = L".";
WCHAR szCurrentUserName[MAX_DN_CHARS+1];
if (!ppADsContext) {
RRETURN(E_ADS_BAD_PARAMETER);
}
*ppADsContext = NULL;
//
// Try the cache for the passed in credentials.
//
ENTER_BIND_CRITSECT() ;
if (pADsContext = BindCacheLookup(pszNDSTreeName, Credentials)) {
*ppADsContext = pADsContext ;
LEAVE_BIND_CRITSECT() ;
return S_OK;
}
//
// Entry not found in the cache, need to allocate a new one.
//
hr = BindCacheAllocEntry(&pADsContext) ;
if (FAILED(hr)) {
LEAVE_BIND_CRITSECT() ;
RRETURN(hr);
}
ccode = NWDSCreateContextHandle(&context);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
flags &= ~DCV_CANONICALIZE_NAMES;
flags &= ~DCV_XLATE_STRINGS;
flags |= DCV_TYPELESS_NAMES; // for NWDSWhoAmI below
ccode = NWDSSetContext(context, DCK_FLAGS, &flags);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (pszNDSTreeName) {
ccode = NWDSSetContext(
context,
DCK_TREE_NAME,
pszNDSTreeName
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
// Find out who the currently logged-in user (if any) is,
// then reset the DCV_TYPELESS_NAMES flag.
ccode = NWDSWhoAmI(context, (pnstr8)szCurrentUserName);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
flags &= ~DCV_TYPELESS_NAMES;
ccode = NWDSSetContext(context, DCK_FLAGS, &flags);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
hr = Credentials.GetUserName(&pszUserName);
BAIL_ON_FAILURE(hr);
// We want to do the login code if (1) we're not authenticated, or
// (2) we are authenticated, but as a different user. If we're
// doing an ADsGetObject, pszUserName is NULL and case 2 doesn't
// apply.
if ( (!NWDSCanDSAuthenticate(context)) ||
(pszUserName && (_wcsicmp(pszUserName, szCurrentUserName) != 0)) )
{
hr = Credentials.GetPassword(&pszPassword);
BAIL_ON_FAILURE(hr);
if (pszUserName != NULL)
{
//
// If password is NULL, pass a Null string, otherwise Client32 will AV
//
aPassword = AllocateAnsiString(pszPassword);
#if 0
//
// Some builds of the Client32 NDS libraries seem to have a bug in their
// usage of the DCV_CANONICALIZE_NAMES flag, in that they do not behave
// properly when the flag is cleared. The following is a work-around. To
// use it, delete the line above which clears the flag. This code will
// prepend the name with a period (unless it already begins with one),
// achieving the same result.
//
if (*pszUserName == L'.')
{
if (!(pszCanonicalUserName = AllocADsStr(pszUserName)))
BAIL_ON_FAILURE(E_OUTOFMEMORY);
}
else
{
dwLenUserName = wcslen(pszUserName) + 4;
if (!(pbCanonicalUserName = (LPWSTR) AllocADsMem(dwLenUserName * sizeof(WCHAR))))
BAIL_ON_FAILURE(E_OUTOFMEMORY);
wcscpy(pbCanonicalUserName, pszCanonicalPrefix);
wcscat(pbCanonicalUserName, pszUserName);
if (!(pszCanonicalUserName = AllocADsStr(pbCanonicalUserName)))
{
FreeADsMem(pbCanonicalUserName);
BAIL_ON_FAILURE(E_OUTOFMEMORY);
}
FreeADsMem(pbCanonicalUserName);
}
#endif
ccode = NWDSLogin(
context,
0,
pszUserName ? (pnstr8) pszUserName : (pnstr8) L"",
aPassword ? aPassword : "",
0
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
fLoggedIn = TRUE;
}
}
pADsContext->hContext = context;
pADsContext->fLoggedIn = fLoggedIn;
hr = BindCacheAdd(pszNDSTreeName, Credentials, fLoggedIn, pADsContext) ;
BAIL_ON_FAILURE(hr);
*ppADsContext = pADsContext;
if (pszCanonicalUserName)
FreeADsStr(pszCanonicalUserName);
if (pszUserName)
FreeADsStr(pszUserName);
if (pszPassword)
FreeADsStr(pszPassword);
FreeADsMem(aPassword);
LEAVE_BIND_CRITSECT() ;
RRETURN (hr);
error:
if (pszCanonicalUserName)
FreeADsStr(pszCanonicalUserName);
if ( fLoggedIn ) {
NWDSLogout(context);
}
NWDSFreeContext(context);
if (pADsContext) {
FreeADsMem(pADsContext);
}
if (pszUserName)
FreeADsStr(pszUserName);
if (pszPassword)
FreeADsStr(pszPassword);
FreeADsMem(aPassword);
LEAVE_BIND_CRITSECT() ;
RRETURN (hr);
}
HRESULT
ADsNdsCloseContext(
NDS_CONTEXT_HANDLE hADsContext
)
{
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
if (!pADsContext) {
RRETURN(E_FAIL);
}
if (BindCacheDeref(pADsContext) == 0) {
//
// ref count has dropped to zero and its gone from cache.
//
if (pADsContext->fLoggedIn) {
NWDSLogout(pADsContext->hContext);
}
NWDSFreeContext(pADsContext->hContext);
FreeADsMem(pADsContext);
}
RRETURN(S_OK);
}
HRESULT
ADsNdsReadObject(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR pszDn,
DWORD dwInfoType,
LPWSTR *ppszAttrs,
DWORD nAttrs,
pTimeStamp_T pTimeStamp,
PNDS_ATTR_INFO *ppAttrEntries,
DWORD *pAttrsReturned
)
{
NWDSCCODE ccode;
HRESULT hr = S_OK;
nint32 lIterationHandle = NO_MORE_ITERATIONS;
NWDSContextHandle context;
DWORD i, j;
pnstr8 *ppAttrs = NULL, aDn = NULL;
nstr treeName[MAX_DN_CHARS+1];
nuint32 flags;
pBuf_T pInBuf = NULL;
pBuf_T pOutBuf = NULL;
BOOL fAllAttrs = FALSE;
DWORD dwAttrsReturned = 0;
DWORD dwAttrsReturnedCurrIter = 0;
PNDS_ATTR_INFO pAttrEntries = NULL;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
if (!pADsContext || !pAttrsReturned || !ppAttrEntries) {
RRETURN(E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
*ppAttrEntries = NULL;
//
//Allocate the output buffer to hold returned values
//
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pOutBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
if (nAttrs == (DWORD) -1) {
fAllAttrs = TRUE;
pInBuf = NULL;
}
else {
// Allocate and initialize input buffer a directory services
// read operation.
//
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSInitBuf(context, DSV_READ, pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
// To prepare for the read, place the names of the attributes
// into the input buffer
//
for(i = 0; i < nAttrs; i++)
{
ccode = NWDSPutAttrName(context, pInBuf, (pnstr8) ppszAttrs[i]);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
}
do {
// Perform the read. The second arg to NWDSRead specifies that
// attribute values are to be returned. The third attribute, FALSE,
// indicates that only attribute information is desired.
//
//
// To ensure that read/search doesn't collide with GenObjectKeyPair().
// GenObjectKeyPair() changes the context state which will cause read/search
// to return type-less DNs
//
EnterCriticalSection(&g_ContextCritSect);
ccode = NWDSRead(
context,
(pnstr8) (!pszDn || (*pszDn == L'\0') ? L"[Root]" : pszDn),
dwInfoType,
fAllAttrs,
pInBuf,
&lIterationHandle,
pOutBuf
);
LeaveCriticalSection(&g_ContextCritSect);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
// If pAttrEntries == NULL, this is the first iteration and there's
// no previous attr list to append to.
if (!pAttrEntries) {
hr = ADsNdsGetAttrListFromBuffer(
hADsContext,
pOutBuf,
FALSE,
(void **) &pAttrEntries,
&dwAttrsReturnedCurrIter
);
} else {
hr = ADsNdsAppendAttrListFromBuffer(
hADsContext,
pOutBuf,
FALSE,
(void **) &pAttrEntries,
&dwAttrsReturnedCurrIter,
dwAttrsReturned
);
}
BAIL_ON_FAILURE(hr);
dwAttrsReturned += dwAttrsReturnedCurrIter;
} while (lIterationHandle != NO_MORE_ITERATIONS);
*pAttrsReturned = dwAttrsReturned;
*ppAttrEntries = pAttrEntries;
error:
NWDSFreeBuf(pInBuf);
NWDSFreeBuf(pOutBuf);
RRETURN(hr);
}
HRESULT
ADsNdsGetAttrListFromBuffer(
NDS_CONTEXT_HANDLE hADsContext,
pBuf_T pBuf,
BOOL fAttrsOnly,
PVOID *ppAttrEntries,
PDWORD pAttrsReturned
)
{
NWCCODE ccode;
HRESULT hr = S_OK;
NWDSContextHandle context;
nuint32 luAttrCount = 0;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
if (!hADsContext || !ppAttrEntries || !pAttrsReturned) {
RRETURN(E_ADS_BAD_PARAMETER);
}
*pAttrsReturned = 0;
context = pADsContext->hContext;
ccode = NWDSGetAttrCount(context, pBuf, &luAttrCount);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
hr = ADsNdsGetAttrsFromBuffer(
hADsContext,
pBuf,
luAttrCount,
fAttrsOnly,
ppAttrEntries
);
BAIL_ON_FAILURE(hr);
*pAttrsReturned = luAttrCount;
error:
RRETURN (hr);
}
HRESULT
ADsNdsAppendAttrListFromBuffer(
NDS_CONTEXT_HANDLE hADsContext,
pBuf_T pBuf,
BOOL fAttrsOnly,
PVOID *ppAttrEntries, // ptr to list to be appended to
PDWORD pdwNewAttrsReturned, // # of new attribs appended
DWORD dwCurrentAttrs // # of attributes currently in list
)
{
NWCCODE ccode;
HRESULT hr = S_OK;
NWDSContextHandle context;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
DWORD cbOld = 0;
DWORD cbNew = 0;
PNDS_ATTR_INFO pCombinedAttrEntries = NULL;
DWORD dwCombinedCurrentIndex = 0; // index of next unused entry
PVOID pNewAttrEntries = NULL;
nuint32 luAttrCount = 0; //count of new attribs (those in pNewAttrEntries)
DWORD i, j;
if (!hADsContext || !ppAttrEntries || !pdwNewAttrsReturned) {
RRETURN(E_ADS_BAD_PARAMETER);
}
// BUGBUG: Ideally, we should be able to handle both NDS_ATTR_INFO and
// NDS_NAME_ONLY entries.
// However, currently we are always called with fAttrsOnly == FALSE,
// and that is all we support.
if (fAttrsOnly)
RRETURN(E_ADS_BAD_PARAMETER);
*pdwNewAttrsReturned = 0;
context = pADsContext->hContext;
// Build the list of the new attributes in this block
ccode = NWDSGetAttrCount(context, pBuf, &luAttrCount);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
hr = ADsNdsGetAttrsFromBuffer(
hADsContext,
pBuf,
luAttrCount,
fAttrsOnly,
&pNewAttrEntries
);
BAIL_ON_FAILURE(hr);
// Append the list of new attributes (luAttrCount entries pointed to by
// pNewAttrEntries) to the list of old attributes (dwCurrentAttrs entries
// pointed to by *ppAttrEntries)
// Allocate a new list big enough to hold old and new attributes.
// We make the list the maximum possible size, assuming no dupes.
// We may shrink it later if there are dupes.
cbOld = dwCurrentAttrs * sizeof(NDS_ATTR_INFO);
cbNew = cbOld + (luAttrCount * sizeof(NDS_ATTR_INFO));
dwCombinedCurrentIndex = dwCurrentAttrs;
pCombinedAttrEntries = (PNDS_ATTR_INFO) ReallocADsMem(
*ppAttrEntries,
cbOld,
cbNew
);
if (!pCombinedAttrEntries)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
*ppAttrEntries = NULL;
// For each new attrib entry, copy it into the combined list (if not
// a dupe) or merge it into the corresponding old entry (if a dupe)
for (j = 0; j < luAttrCount; j++) {
PNDS_ATTR_INFO pNewEntry = ((PNDS_ATTR_INFO)pNewAttrEntries) + j;
DWORD dwDupeIndex = -1;
// Determine if the new entry is a duplicate of an old entry.
// Note the implicit assumption that there is at most one of any
// given attribute entry in the list of old entries (i.e., there
// are no dupes within the list). This should always hold, since
// a NWDSRead should not yield any dupes in its results, and we take
// care of merging dupes between multiple NWDSRead results.
for (i = 0; i < dwCurrentAttrs; i++) {
PNDS_ATTR_INFO pOldEntry = (pCombinedAttrEntries) + i;
if (!_wcsicmp(pOldEntry->szAttributeName, pNewEntry->szAttributeName)) {
// found a dupe
dwDupeIndex = i;
break;
}
}
if (dwDupeIndex == -1) {
// not a duplicate attribute, so just copy it from the new entries list
// to the next available position in the combined entries list
memcpy(
(BYTE*)(pCombinedAttrEntries + dwCombinedCurrentIndex),
(BYTE*)pNewEntry,
sizeof(NDS_ATTR_INFO)
);
dwCombinedCurrentIndex++;
}
else {
// duplicate, merge attribute values
PNDS_ATTR_INFO pOldEntry = (pCombinedAttrEntries) + dwDupeIndex;
cbOld = pOldEntry->dwNumberOfValues * sizeof(NDSOBJECT);
cbNew = cbOld + pNewEntry->dwNumberOfValues * sizeof(NDSOBJECT);
PNDSOBJECT lpValue = (PNDSOBJECT)ReallocADsMem(
pOldEntry->lpValue,
cbOld,
cbNew
);
if (!lpValue)
BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
pOldEntry->lpValue = lpValue;
// the new NDSOBJECTs will come after the preexisting ones
memcpy(
((BYTE*) pOldEntry->lpValue) + cbOld,
(BYTE*)pNewEntry->lpValue,
cbNew-cbOld
);
pOldEntry->dwNumberOfValues += pNewEntry->dwNumberOfValues;
FreeADsMem(pNewEntry->lpValue);
pNewEntry->lpValue = NULL;
FreeADsMem(pNewEntry->szAttributeName);
pNewEntry->szAttributeName = NULL;
}
}
// We allocated memory for the combined list assuming there were no duplicates. If
// there were duplicates, the combined list is shorter than what we allocated for,
// and we shrink the allocated list down to size.
if (dwCombinedCurrentIndex < luAttrCount + dwCurrentAttrs) {
PNDS_ATTR_INFO pCombinedAttrEntriesResized;
pCombinedAttrEntriesResized = (PNDS_ATTR_INFO)ReallocADsMem(
pCombinedAttrEntries,
(luAttrCount + dwCurrentAttrs) * sizeof(NDS_ATTR_INFO),
dwCombinedCurrentIndex * sizeof(NDS_ATTR_INFO)
);
if (!pCombinedAttrEntriesResized)
BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
pCombinedAttrEntries = pCombinedAttrEntriesResized;
}
*ppAttrEntries = pCombinedAttrEntries;
*pdwNewAttrsReturned = dwCombinedCurrentIndex - dwCurrentAttrs;
FreeADsMem(pNewAttrEntries);
RRETURN (hr);
error:
if (pNewAttrEntries)
FreeNdsAttrInfo((PNDS_ATTR_INFO)pNewAttrEntries, luAttrCount);
if (pCombinedAttrEntries)
FreeNdsAttrInfo((PNDS_ATTR_INFO)pCombinedAttrEntries, dwCombinedCurrentIndex);
if (*ppAttrEntries)
FreeNdsAttrInfo((PNDS_ATTR_INFO)*ppAttrEntries, dwCurrentAttrs);
RRETURN (hr);
}
HRESULT
FreeNdsAttrInfo(
PNDS_ATTR_INFO pAttrEntries,
DWORD dwNumEntries
)
{
DWORD i;
PNDS_ATTR_INFO pThisEntry = NULL;
if (!pAttrEntries) {
RRETURN(S_OK);
}
for (i=0; i < dwNumEntries; i++) {
pThisEntry = pAttrEntries+i;
if (pThisEntry->szAttributeName)
FreeADsMem(pThisEntry->szAttributeName);
if (pThisEntry->lpValue)
NdsTypeFreeNdsObjects( pThisEntry->lpValue,
pThisEntry->dwNumberOfValues );
}
FreeADsMem(pAttrEntries);
RRETURN(S_OK);
}
HRESULT
FreeNdsAttrNames(
PNDS_NAME_ONLY pAttrNames,
DWORD dwNumEntries
)
{
DWORD i;
if (!pAttrNames) {
RRETURN(S_OK);
}
for (i=0; i < dwNumEntries; i++) {
if (pAttrNames[i].szName)
FreeADsMem(pAttrNames[i].szName);
}
FreeADsMem(pAttrNames);
RRETURN(S_OK);
}
HRESULT
ADsNdsListObjects(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR pszDn,
LPWSTR classFilter,
LPWSTR objectFilter,
pTimeStamp_T pTimeStamp,
BOOL fOnlyContainers,
NDS_BUFFER_HANDLE *phBuf
)
{
NWDSCCODE ccode;
HRESULT hr = S_OK;
BOOL fBufAllocated = FALSE;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
if ( !pADsContext || !phBuf) {
RRETURN(E_ADS_BAD_PARAMETER);
}
if( pBufData == NULL) {
pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
if (!pBufData) {
RRETURN(E_OUTOFMEMORY);
}
fBufAllocated = TRUE;
pBufData->lIterationHandle = NO_MORE_ITERATIONS;
pBufData->pOutBuf = NULL;
pBufData->pInBuf = NULL;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBufData->pOutBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
else {
if ( pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
RRETURN (S_ADS_NOMORE_ROWS);
}
}
ccode = NWDSExtSyncList(
pADsContext->hContext,
(pnstr8) (!pszDn || (*pszDn == L'\0') ? L"[Root]" : pszDn),
(pnstr8) classFilter,
(pnstr8) objectFilter,
&pBufData->lIterationHandle,
NULL,
FALSE,
pBufData->pOutBuf
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
hr = S_ADS_NOMORE_ROWS;
}
else {
hr = S_OK;
}
*phBuf = pBufData;
RRETURN(hr);
error:
if (fBufAllocated) {
if (pBufData->pOutBuf) {
NWDSFreeBuf(pBufData->pOutBuf);
}
FreeADsMem(pBufData);
}
RRETURN(hr);
}
HRESULT
ADsNdsGetObjectListFromBuffer(
NDS_CONTEXT_HANDLE hADsContext,
NDS_BUFFER_HANDLE hBufData,
PDWORD pdwObjectsReturned,
PADSNDS_OBJECT_INFO *ppObjects
)
{
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
nuint32 luObjectCount = 0, luAttrCount = 0;
WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
Object_Info_T objectInfo;
DWORD j, i;
PADSNDS_OBJECT_INFO pThisObject = NULL, pObjectInfo = NULL;
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_ATTR_INFO pAttrEntries = NULL, pThisEntry = NULL;
PNDS_NAME_ONLY pAttrNames = NULL, pThisName = NULL;
if (!pADsContext || !pBufData || !pdwObjectsReturned || !ppObjects ||
!pBufData->pOutBuf ) {
RRETURN(E_ADS_BAD_PARAMETER);
}
*ppObjects = NULL;
*pdwObjectsReturned = 0;
ccode = NWDSGetObjectCount(pADsContext->hContext, pBufData->pOutBuf, &luObjectCount);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (luObjectCount) {
pObjectInfo = (PADSNDS_OBJECT_INFO) AllocADsMem(
sizeof(ADSNDS_OBJECT_INFO) *
luObjectCount );
if (!pObjectInfo) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memset (pObjectInfo, 0x0, sizeof(ADSNDS_OBJECT_INFO) * luObjectCount);
}
for (j = 0; j < luObjectCount; j++) {
pThisObject = pObjectInfo + j;
ccode = NWDSGetObjectName(
pADsContext->hContext,
pBufData->pOutBuf,
(pnstr8) pszTemp,
&luAttrCount,
&objectInfo
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisObject->szObjectName = AllocADsStr(pszTemp);
pThisObject->szObjectClass = AllocADsStr( (LPWSTR) objectInfo.baseClass);
pThisObject->dwModificationTime = objectInfo.modificationTime;
pThisObject->dwSubordinateCount = objectInfo.subordinateCount;
pThisObject->dwNumAttributes = luAttrCount;
pThisObject->dwObjectFlags = objectInfo.objectFlags;
//
// Get the attributes if we are doing search
//
if (pBufData->dwOperation == DSV_SEARCH ) {
hr = ADsNdsGetAttrsFromBuffer(
hADsContext,
pBufData->pOutBuf,
luAttrCount,
!pBufData->dwInfoType,
&pThisObject->lpAttribute
);
BAIL_ON_FAILURE(hr);
if (!pBufData->dwInfoType)
pThisObject->fNameOnly = TRUE;
else
pThisObject->fNameOnly = FALSE;
}
}
*pdwObjectsReturned = luObjectCount;
*ppObjects = pObjectInfo;
RRETURN(hr);
error:
ADsNdsFreeNdsObjInfoList(pObjectInfo, luObjectCount);
RRETURN(hr);
}
HRESULT
ADsNdsFreeNdsObjInfoList(
PADSNDS_OBJECT_INFO pObjInfo,
DWORD dwNumEntries
)
{
PADSNDS_OBJECT_INFO pThisObjInfo;
if (!pObjInfo)
RRETURN(S_OK);
for (DWORD i = 0; i < dwNumEntries; i++)
{
pThisObjInfo = pObjInfo + i;
FreeADsStr(pThisObjInfo->szObjectName);
FreeADsStr(pThisObjInfo->szObjectClass);
if (pThisObjInfo->fNameOnly)
FreeNdsAttrNames((PNDS_NAME_ONLY)pThisObjInfo->lpAttribute, pThisObjInfo->dwNumAttributes);
else
FreeNdsAttrInfo((PNDS_ATTR_INFO)pThisObjInfo->lpAttribute, pThisObjInfo->dwNumAttributes);
}
FreeADsMem(pObjInfo);
RRETURN(S_OK);
}
HRESULT
ADsNdsGetAttrsFromBuffer(
NDS_CONTEXT_HANDLE hADsContext,
pBuf_T pBuf,
DWORD luAttrCount,
BOOL fAttrsOnly,
PVOID *ppAttrEntries
)
{
NWCCODE ccode;
HRESULT hr = S_OK;
NWDSContextHandle context;
nuint32 luAttrValCount = 0;
nuint32 luAttrValSize = 0;
nuint32 luSyntax;
nptr attrVal = NULL;
PNDS_ATTR_INFO pAttrEntries = NULL, pThisEntry = NULL;
PNDS_NAME_ONLY pAttrNames = NULL, pThisName = NULL;
nstr pszAttrName[MAX_DN_CHARS+1];
DWORD i, j;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
ADsAssert(pADsContext);
ADsAssert(ppAttrEntries);
context = pADsContext->hContext;
if (fAttrsOnly) {
if (luAttrCount) {
pAttrNames = (PNDS_NAME_ONLY) AllocADsMem(
sizeof(NDS_NAME_ONLY) * luAttrCount );
if (!pAttrNames) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
}
for(i = 0; i < luAttrCount; i++) {
// Initialize this entry so that we can free them if an error
// occurs in building this entry
//
ccode = NWDSGetAttrName(context, pBuf, (pnstr8) pszAttrName,
&luAttrValCount, &luSyntax);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisName->szName = AllocADsStr(pszAttrName);
if (!pThisName->szName) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
}
*ppAttrEntries = pAttrNames;
}
else {
if (luAttrCount) {
pAttrEntries = (PNDS_ATTR_INFO) AllocADsMem(
sizeof(NDS_ATTR_INFO) * luAttrCount );
if (!pAttrEntries) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
}
/* Get the name and value for each attribute */
for(i = 0; i < luAttrCount; i++) {
// Initialize this entry so that we can free them if an error
// occurs in building this entry
//
pThisEntry = pAttrEntries+i;
pThisEntry->szAttributeName = NULL;
pThisEntry->dwNumberOfValues = 0;
pThisEntry->lpValue = NULL;
ccode = NWDSGetAttrName(context, pBuf, (pnstr8) pszAttrName,
&luAttrValCount, &luSyntax);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisEntry->szAttributeName = AllocADsStr(pszAttrName);
if (!pThisEntry->szAttributeName) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pThisEntry->dwNumberOfValues = luAttrValCount;
pThisEntry->dwSyntaxId = luSyntax;
pThisEntry->lpValue = (PNDSOBJECT) AllocADsMem(
luAttrValCount * sizeof(NDSOBJECT)
);
for (j = 0; j < luAttrValCount; j++) {
ccode = NWDSComputeAttrValSize(
context,
pBuf,
luSyntax,
&luAttrValSize
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
attrVal = AllocADsMem(luAttrValSize);
if (!attrVal) {
FreeNdsAttrInfo(pAttrEntries, i);
pAttrEntries = NULL;
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
ccode = NWDSGetAttrVal(context, pBuf, luSyntax, attrVal);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
hr = CopyNdsValueToNdsObject(
(nptr) attrVal,
luAttrValSize,
luSyntax,
(PNDSOBJECT) pThisEntry->lpValue + j
);
if (hr == E_ADS_CANT_CONVERT_DATATYPE) {
hr = S_OK;
}
BAIL_ON_FAILURE(hr);
FreeADsMem(attrVal);
attrVal = NULL;
}
*ppAttrEntries = pAttrEntries;
}
}
RRETURN(S_OK);
error:
// This function frees all the memory related to this array of entries
// for i entries. The ith entry may not have be fully set, but that is ok
// because we have initialized it properly in the beginning of the for loop
//
if (pAttrEntries) {
FreeNdsAttrInfo(pAttrEntries, i);
}
if (pAttrNames) {
FreeNdsAttrNames(pAttrNames, i);
}
if (attrVal) {
FreeADsMem(attrVal);
}
RRETURN (hr);
}
HRESULT
ADsNdsReadClassDef(
NDS_CONTEXT_HANDLE hADsContext,
DWORD dwInfoType,
LPWSTR *ppszClasses,
DWORD nClasses,
NDS_BUFFER_HANDLE *phBuf
)
{
NWDSCCODE ccode;
HRESULT hr = S_OK;
DWORD i;
pBuf_T pInBuf = NULL;
BOOL fAllClasses = FALSE;
BOOL fBufAllocated = FALSE;
NWDSContextHandle context;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
if ( !pADsContext || !phBuf) {
RRETURN(E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
if( pBufData == NULL) {
pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
if (!pBufData) {
RRETURN(E_OUTOFMEMORY);
}
fBufAllocated = TRUE;
pBufData->lIterationHandle = NO_MORE_ITERATIONS;
pBufData->pOutBuf = NULL;
pBufData->dwInfoType = dwInfoType;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN*2, &pBufData->pOutBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
else {
if ( pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
RRETURN (S_ADS_NOMORE_ROWS);
}
}
if (nClasses == (DWORD) -1) {
fAllClasses = TRUE;
pInBuf = NULL;
}
else {
// Allocate and initialize input buffer a directory services
// read operation.
//
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSInitBuf(context, DSV_READ_CLASS_DEF, pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
// To prepare for the read, place the names of the attributes
// into the input buffer
//
for(i = 0; i < nClasses; i++)
{
ccode = NWDSPutClassName(context, pInBuf, (pnstr8) ppszClasses[i]);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
}
ccode = NWDSReadClassDef(
context,
dwInfoType,
fAllClasses,
pInBuf,
&pBufData->lIterationHandle,
pBufData->pOutBuf
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
hr = S_ADS_NOMORE_ROWS;
}
else {
hr = S_OK;
}
*phBuf = pBufData;
if (pInBuf) {
NWDSFreeBuf(pInBuf);
}
RRETURN(hr);
error:
if (pInBuf) {
NWDSFreeBuf(pInBuf);
}
if (fBufAllocated) {
if (pBufData->pOutBuf) {
NWDSFreeBuf(pBufData->pOutBuf);
}
FreeADsMem(pBufData);
}
RRETURN(hr);
}
HRESULT
ADsNdsGetClassDefListFromBuffer(
NDS_CONTEXT_HANDLE hADsContext,
NDS_BUFFER_HANDLE hBufData,
PDWORD pdwNumEntries,
PDWORD pdwInfoType,
PNDS_CLASS_DEF *ppClassDef
)
{
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
nuint32 luClassDefCount = 0, luItemCount = 0;
WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
Class_Info_T classInfo;
DWORD j;
PNDS_CLASS_DEF pThisClassDef = NULL, pClassDef = NULL;
HRESULT hr = S_OK;
NWDSCCODE ccode;
NWDSContextHandle context;
if (!pADsContext || !pBufData || !pdwNumEntries ||
!pdwInfoType || !ppClassDef || !pBufData->pOutBuf) {
RRETURN(E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
*ppClassDef = NULL;
*pdwNumEntries = 0;
*pdwInfoType = pBufData->dwInfoType;
ccode = NWDSGetClassDefCount(context, pBufData->pOutBuf, &luClassDefCount);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (luClassDefCount) {
pClassDef = (PNDS_CLASS_DEF) AllocADsMem(
sizeof(NDS_CLASS_DEF) *
luClassDefCount );
if (!pClassDef) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memset (pClassDef, 0x0, sizeof(NDS_CLASS_DEF) * luClassDefCount);
}
for (j = 0; j < luClassDefCount; j++) {
pThisClassDef = pClassDef + j;
if (pBufData->dwInfoType == DS_CLASS_DEF_NAMES) {
ccode = NWDSGetClassItem(
context,
pBufData->pOutBuf,
(pnstr8) pszTemp
);
if (pszTemp) {
pThisClassDef->szClassName = AllocADsStr( pszTemp );
if (!pThisClassDef->szClassName) {
RRETURN (hr = E_OUTOFMEMORY);
}
}
//
// This is all that is available for this class (only name)
// move to the next class
//
continue;
}
ccode = NWDSGetClassDef(
context,
pBufData->pOutBuf,
(pnstr8) pszTemp,
&classInfo
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisClassDef->dwFlags = classInfo.classFlags;
pThisClassDef->asn1ID = classInfo.asn1ID;
if (pBufData->dwInfoType == DS_INFO_CLASS_DEFS) {
//
// Name won't be there
//
pThisClassDef->szClassName = NULL;
}
else {
pThisClassDef->szClassName = AllocADsStr(pszTemp);
//
// This is for getting superior classes
//
ccode = NWDSGetClassItemCount(
context,
pBufData->pOutBuf,
&luItemCount
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisClassDef->dwNumberOfSuperClasses = luItemCount;
hr = GetItemsToList(
context,
pBufData->pOutBuf,
luItemCount,
&pThisClassDef->lpSuperClasses
);
BAIL_ON_FAILURE(hr);
//
// This is for getting Containment classes
//
ccode = NWDSGetClassItemCount(
context,
pBufData->pOutBuf,
&luItemCount
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisClassDef->dwNumberOfContainmentClasses = luItemCount;
hr = GetItemsToList(
context,
pBufData->pOutBuf,
luItemCount,
&pThisClassDef->lpContainmentClasses
);
BAIL_ON_FAILURE(hr);
//
// This is for getting the Naming Attribute List
//
ccode = NWDSGetClassItemCount(
context,
pBufData->pOutBuf,
&luItemCount
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisClassDef->dwNumberOfNamingAttributes = luItemCount;
hr = GetItemsToList(
context,
pBufData->pOutBuf,
luItemCount,
&pThisClassDef->lpNamingAttributes
);
BAIL_ON_FAILURE(hr);
//
// This is for getting the Mandatory Attribute List
//
ccode = NWDSGetClassItemCount(
context,
pBufData->pOutBuf,
&luItemCount
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisClassDef->dwNumberOfMandatoryAttributes = luItemCount;
hr = GetItemsToList(
context,
pBufData->pOutBuf,
luItemCount,
&pThisClassDef->lpMandatoryAttributes
);
BAIL_ON_FAILURE(hr);
//
// This is for getting the Optional Attribute List
//
ccode = NWDSGetClassItemCount(
context,
pBufData->pOutBuf,
&luItemCount
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisClassDef->dwNumberOfOptionalAttributes = luItemCount;
hr = GetItemsToList(
context,
pBufData->pOutBuf,
luItemCount,
&pThisClassDef->lpOptionalAttributes
);
BAIL_ON_FAILURE(hr);
}
}
*pdwNumEntries = luClassDefCount;
*ppClassDef = pClassDef;
RRETURN(hr);
error:
if (pClassDef) {
ADsNdsFreeClassDefList(pClassDef, luClassDefCount);
}
RRETURN(hr);
}
HRESULT
GetItemsToList(
NWDSContextHandle context,
pBuf_T pBuf,
DWORD luItemCount,
LPWSTR_LIST *ppList
)
{
WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
HRESULT hr = S_OK;
NWDSCCODE ccode;
LPWSTR_LIST pPrevItem = NULL, pCurrItem = NULL, pItems = NULL;
DWORD i;
if (!ppList) {
RRETURN(E_FAIL);
}
*ppList = NULL;
if (luItemCount > 0) {
pItems = (LPWSTR_LIST ) AllocADsMem(sizeof(WSTR_LIST_ELEM) * luItemCount);
if (!pItems) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memset(pItems, 0x0, sizeof(WSTR_LIST_ELEM) * luItemCount);
for (i = 0; i < luItemCount ; i++) {
pCurrItem = pItems + i;
ccode = NWDSGetClassItem(
context,
pBuf,
(pnstr8) &pszTemp
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pCurrItem->szString = AllocADsStr(pszTemp);
if (pPrevItem) {
pPrevItem->Next = pCurrItem;
}
pPrevItem = pCurrItem;
}
pCurrItem->Next = NULL;
}
*ppList = pItems;
RRETURN(hr);
error:
if (pItems) {
FreeItemList(pItems);
}
RRETURN(hr);
}
HRESULT
ADsNdsFreeClassDef(
PNDS_CLASS_DEF pClassDef
)
{
if (!pClassDef) {
RRETURN(S_OK);
}
FreeADsStr(pClassDef->szClassName);
FreeItemList(pClassDef->lpSuperClasses);
FreeItemList(pClassDef->lpContainmentClasses);
FreeItemList(pClassDef->lpNamingAttributes);
FreeItemList(pClassDef->lpMandatoryAttributes);
FreeItemList(pClassDef->lpOptionalAttributes);
FreeADsMem(pClassDef);
RRETURN(S_OK);
}
HRESULT
ADsNdsFreeClassDefList(
PNDS_CLASS_DEF pClassDef,
DWORD dwNumEntries
)
{
PNDS_CLASS_DEF pThisClassDef;
if (!pClassDef) {
RRETURN(S_OK);
}
for (DWORD i = 0; i < dwNumEntries; i++) {
pThisClassDef = pClassDef + i;
FreeADsStr(pThisClassDef->szClassName);
FreeItemList(pThisClassDef->lpSuperClasses);
FreeItemList(pThisClassDef->lpContainmentClasses);
FreeItemList(pThisClassDef->lpNamingAttributes);
FreeItemList(pThisClassDef->lpMandatoryAttributes);
FreeItemList(pThisClassDef->lpOptionalAttributes);
}
FreeADsMem(pClassDef);
RRETURN(S_OK);
}
HRESULT
ADsNdsReadAttrDef(
NDS_CONTEXT_HANDLE hADsContext,
DWORD dwInfoType,
LPWSTR *ppszAttrs,
DWORD nAttrs,
NDS_BUFFER_HANDLE *phBuf
)
{
NWDSCCODE ccode;
HRESULT hr = S_OK;
DWORD i;
pBuf_T pInBuf = NULL;
BOOL fAllAttrs = FALSE;
BOOL fBufAllocated = FALSE;
NWDSContextHandle context;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
if ( !pADsContext || !phBuf) {
RRETURN(E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
if( pBufData == NULL) {
pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
if (!pBufData) {
RRETURN(E_OUTOFMEMORY);
}
fBufAllocated = TRUE;
pBufData->lIterationHandle = NO_MORE_ITERATIONS;
pBufData->pOutBuf = NULL;
pBufData->dwInfoType = dwInfoType;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBufData->pOutBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
else {
if ( pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
RRETURN (S_ADS_NOMORE_COLUMNS);
}
}
if (nAttrs == (DWORD) -1) {
fAllAttrs = TRUE;
pInBuf = NULL;
}
else {
// Allocate and initialize input buffer a directory services
// read operation.
//
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSInitBuf(context, DSV_READ_ATTR_DEF, pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
// To prepare for the read, place the names of the attributes
// into the input buffer
//
for(i = 0; i < nAttrs; i++)
{
ccode = NWDSPutAttrName(context, pInBuf, (pnstr8) ppszAttrs[i]);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
}
ccode = NWDSReadAttrDef(
context,
dwInfoType,
fAllAttrs,
pInBuf,
&pBufData->lIterationHandle,
pBufData->pOutBuf
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
hr = S_ADS_NOMORE_COLUMNS;
}
else {
hr = S_OK;
}
*phBuf = pBufData;
if (pInBuf) {
NWDSFreeBuf(pInBuf);
}
RRETURN(hr);
error:
if (pInBuf) {
NWDSFreeBuf(pInBuf);
}
if (fBufAllocated) {
if (pBufData->pOutBuf) {
NWDSFreeBuf(pBufData->pOutBuf);
}
FreeADsMem(pBufData);
}
RRETURN(hr);
}
HRESULT
ADsNdsGetAttrDefListFromBuffer(
NDS_CONTEXT_HANDLE hADsContext,
NDS_BUFFER_HANDLE hBufData,
PDWORD pdwNumEntries,
PDWORD pdwInfoType,
PNDS_ATTR_DEF *ppAttrDef
)
{
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
nuint32 luAttrDefCount = 0, luItemCount = 0;
WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
Attr_Info_T attrInfo;
DWORD j;
LPNDS_ATTR_DEF pThisAttrDef = NULL, pAttrDef = NULL;
HRESULT hr = S_OK;
NWDSCCODE ccode;
NWDSContextHandle context;
if (!pADsContext || !pBufData || !pdwNumEntries ||
!pdwInfoType || !ppAttrDef || !pBufData->pOutBuf) {
RRETURN(E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
*ppAttrDef = NULL;
*pdwNumEntries = 0;
*pdwInfoType = pBufData->dwInfoType;
ccode = NWDSGetAttrCount(context, pBufData->pOutBuf, &luAttrDefCount);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (luAttrDefCount) {
pAttrDef = (PNDS_ATTR_DEF) AllocADsMem(
sizeof(NDS_ATTR_DEF) *
luAttrDefCount );
if (!pAttrDef) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
memset (pAttrDef, 0x0, sizeof(NDS_ATTR_DEF) * luAttrDefCount);
}
for (j = 0; j < luAttrDefCount; j++) {
pThisAttrDef = pAttrDef + j;
ccode = NWDSGetAttrDef(
context,
pBufData->pOutBuf,
(pnstr8) pszTemp,
&attrInfo
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pThisAttrDef->szAttributeName = AllocADsStr(pszTemp);
if (pBufData->dwInfoType == DS_ATTR_DEFS) {
pThisAttrDef->dwFlags = attrInfo.attrFlags;
pThisAttrDef->dwSyntaxID = attrInfo.attrSyntaxID;
pThisAttrDef->dwLowerLimit = attrInfo.attrLower;
pThisAttrDef->dwUpperLimit = attrInfo.attrUpper;
}
}
*pdwNumEntries = luAttrDefCount;
*ppAttrDef = pAttrDef;
RRETURN(hr);
error:
if (pAttrDef) {
ADsNdsFreeAttrDefList(pAttrDef,luAttrDefCount);
}
RRETURN(hr);
}
HRESULT
ADsNdsFreeAttrDef(
PNDS_ATTR_DEF pAttrDef
)
{
if (!pAttrDef) {
RRETURN(S_OK);
}
FreeADsStr(pAttrDef->szAttributeName);
FreeADsMem(pAttrDef);
RRETURN(S_OK);
}
HRESULT
ADsNdsFreeAttrDefList(
PNDS_ATTR_DEF pAttrDef,
DWORD dwNumEntries
)
{
PNDS_ATTR_DEF pThisAttrDef;
if (!pAttrDef) {
RRETURN(S_OK);
}
for (DWORD i = 0; i < dwNumEntries; i++) {
pThisAttrDef = pAttrDef + i;
FreeADsStr(pThisAttrDef->szAttributeName);
}
FreeADsMem(pAttrDef);
RRETURN(S_OK);
}
//
// Free all the allocated memory in the list and the list itself.
//
HRESULT
FreeItemList(
LPWSTR_LIST pList
)
{
LPWSTR_LIST pCurr = pList;
while (pCurr) {
FreeADsStr(pCurr->szString);
pCurr = pCurr->Next;
}
FreeADsMem(pList);
RRETURN(S_OK);
}
HRESULT
ADsNdsFreeBuffer(
NDS_BUFFER_HANDLE hBuf
)
{
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBuf;
if (pBufData) {
if (pBufData->pOutBuf) {
NWDSFreeBuf(pBufData->pOutBuf);
}
if (pBufData->pInBuf) {
NWDSFreeBuf(pBufData->pInBuf);
}
FreeADsMem(pBufData);
}
RRETURN(S_OK);
}
HRESULT
ADsNdsCreateBuffer(
NDS_CONTEXT_HANDLE hADsContext,
DWORD dwOperation,
NDS_BUFFER_HANDLE *phBufData
)
{
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
if (!hADsContext || !phBufData) {
RRETURN(E_ADS_BAD_PARAMETER);
}
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
if (!pBufData) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pBufData->lIterationHandle = NO_MORE_ITERATIONS;
pBufData->pOutBuf = NULL;
pBufData->dwOperation = dwOperation;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBufData->pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSInitBuf(
pADsContext->hContext,
dwOperation,
pBufData->pInBuf
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
*phBufData = pBufData;
error:
RRETURN(hr);
}
HRESULT
ADsNdsPutInBuffer(
NDS_CONTEXT_HANDLE hADsContext,
NDS_BUFFER_HANDLE hBufData,
LPWSTR szAttributeName,
DWORD dwSyntaxID,
LPNDSOBJECT lpAttributeValues,
DWORD dwValueCount,
DWORD dwChangeType
)
{
LPNDSOBJECT pThisValue = NULL;
NWDSContextHandle context;
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
nptr attrVal = NULL;
DWORD i = 0, luSyntax, luAttrValSize = 0;
if (!hADsContext || !hBufData) {
RRETURN(E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
switch (pBufData->dwOperation) {
case DSV_ADD_ENTRY:
ccode = NWDSPutAttrName (
context,
pBufData->pInBuf,
(pnstr8) szAttributeName
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
break;
default:
ccode = NWDSPutChange (
context,
pBufData->pInBuf,
dwChangeType,
(pnstr8) szAttributeName
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
break;
}
for (i=0; i < dwValueCount; i++) {
pThisValue = lpAttributeValues + i;
hr = CopyNdsObjectToNdsValue(
(PNDSOBJECT) pThisValue,
(nptr *) &attrVal,
&luAttrValSize,
&luSyntax
);
BAIL_ON_FAILURE(hr);
ccode = NWDSPutAttrVal (
context,
pBufData->pInBuf,
luSyntax,
attrVal
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (attrVal) {
FreeNdsValues(luSyntax, attrVal, luAttrValSize);
attrVal = NULL;
}
}
error:
if (attrVal) {
FreeNdsValues(luSyntax, attrVal, luAttrValSize);
}
RRETURN(hr);
}
HRESULT
ADsNdsPutFilter(
NDS_CONTEXT_HANDLE hADsContext,
NDS_BUFFER_HANDLE hBufData,
pFilter_Cursor_T pCur,
void (N_FAR N_CDECL *freeVal)(nuint32 syntax, nptr val)
)
{
NWDSContextHandle context;
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
nstr treeName[MAX_DN_CHARS+1];
nuint32 flags;
if (!hADsContext || !hBufData) {
RRETURN(E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
NWDSPutFilter(
pADsContext->hContext,
pBufData->pInBuf,
pCur,
freeVal
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
error:
RRETURN(hr);
}
HRESULT
ADsNdsModifyObject(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR szObjectName,
NDS_BUFFER_HANDLE hBufData
)
{
NWDSContextHandle context;
nint32 lIterationHandle = NO_MORE_ITERATIONS;
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
if (!hADsContext || !hBufData) {
RRETURN (E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
ccode = NWDSModifyObject(
context,
(pnstr8) szObjectName,
&lIterationHandle,
FALSE,
pBufData->pInBuf
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}
HRESULT
ADsNdsAddObject(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR szObjectName,
NDS_BUFFER_HANDLE hBufData
)
{
NWDSContextHandle context;
nint32 lIterationHandle = NO_MORE_ITERATIONS;
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
if (!hADsContext || !hBufData) {
RRETURN (E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
ccode = NWDSAddObject(
context,
(pnstr8) szObjectName,
&lIterationHandle,
FALSE,
pBufData->pInBuf
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}
HRESULT
ADsNdsGenObjectKey(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR szObjectName
)
{
NWDSContextHandle context;
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
if (!hADsContext) {
RRETURN (E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
//
// To ensure that read/search doesn't collide with GenObjectKeyPair().
// GenObjectKeyPair() changes the context state which will cause read/search
// to return type-less DNs
//
EnterCriticalSection(&g_ContextCritSect);
ccode = NWDSGenerateObjectKeyPair(
context,
(pnstr8) szObjectName,
"",
0);
LeaveCriticalSection(&g_ContextCritSect);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}
HRESULT
ADsNdsRemoveObject(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR szObjectName
)
{
NWDSContextHandle context;
HRESULT hr = S_OK;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
if (!hADsContext) {
RRETURN (E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
ccode = NWDSRemoveObject(
context,
(pnstr8) szObjectName
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}
HRESULT
ADsNdsGetSyntaxID(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR szAttributeName,
PDWORD pdwSyntaxId
)
{
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
HRESULT hr = S_OK;
NWDSCCODE ccode;
if (!pADsContext) {
RRETURN(E_ADS_BAD_PARAMETER);
}
ccode = NWDSGetSyntaxID(
pADsContext->hContext,
(pnstr8) szAttributeName,
pdwSyntaxId
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}
HRESULT
ADsNdsSearch(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR szObjectName,
DWORD scope,
BOOL fSearchAliases,
NDS_BUFFER_HANDLE hFilterBuf,
pTimeStamp_T pTimeStamp,
DWORD dwInfoType,
LPWSTR *ppszAttrs,
DWORD nAttrs,
DWORD nObjectsTobeSearched,
PDWORD pnObjectsSearched,
NDS_BUFFER_HANDLE *phBuf,
pnint32 plIterationHandle
)
{
NWDSContextHandle context;
HRESULT hr = S_OK;
NWDSCCODE ccode;
BOOL fBufAllocated = FALSE;
DWORD i, j;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
PNDS_BUFFER_DATA pFilterBuf = (PNDS_BUFFER_DATA) hFilterBuf;
PNDS_BUFFER_DATA pBuf = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
nstr treeName[MAX_DN_CHARS+1];
nuint32 flags;
if (!hADsContext || !hFilterBuf || !phBuf ) {
RRETURN (E_ADS_BAD_PARAMETER);
}
context = pADsContext->hContext;
ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
//
// Allocate the result buffer if not already done
//
if( pBuf == NULL) {
pBuf = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
if (!pBuf) {
RRETURN(E_OUTOFMEMORY);
}
fBufAllocated = TRUE;
pBuf->pOutBuf = NULL;
pBuf->pInBuf = NULL;
pBuf->dwInfoType = dwInfoType;
pBuf->dwOperation = DSV_SEARCH;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN * 4, &pBuf->pOutBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
if (nAttrs == (DWORD) -1) {
pBuf->fAllAttrs = TRUE;
pBuf->pInBuf = NULL;
}
else {
// Allocate and initialize input buffer a directory services
// read operation.
//
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBuf->pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWDSInitBuf(context, DSV_SEARCH, pBuf->pInBuf);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
// To prepare for the read, place the names of the attributes
// into the input buffer
//
for(i = 0; i < nAttrs; i++)
{
ccode = NWDSPutAttrName(context, pBuf->pInBuf, (pnstr8) ppszAttrs[i]);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
}
}
}
//
// To ensure that read/search doesn't collide with GenObjectKeyPair().
// GenObjectKeyPair() changes the context state which will cause read/search
// to return type-less DNs
//
EnterCriticalSection(&g_ContextCritSect);
if (pTimeStamp) {
ccode = NWDSExtSyncSearch(
context,
(pnstr8) szObjectName,
(nint) scope,
(nbool8) fSearchAliases,
pFilterBuf->pInBuf,
pTimeStamp,
pBuf->dwInfoType,
(nbool8) pBuf->fAllAttrs,
pBuf->pInBuf,
plIterationHandle,
(nint32) nObjectsTobeSearched,
(pnint32) pnObjectsSearched,
pBuf->pOutBuf
);
}
else {
ccode = NWDSSearch(
context,
(pnstr8) szObjectName,
(nint) scope,
(nbool8) fSearchAliases,
pFilterBuf->pInBuf,
pBuf->dwInfoType,
(nbool8) pBuf->fAllAttrs,
pBuf->pInBuf,
plIterationHandle,
(nint32) nObjectsTobeSearched,
(pnint32) pnObjectsSearched,
pBuf->pOutBuf
);
}
LeaveCriticalSection(&g_ContextCritSect);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
*phBuf = pBuf;
RRETURN(hr);
error:
if (fBufAllocated) {
if (pBuf->pOutBuf) {
NWDSFreeBuf(pBuf->pOutBuf);
}
if (pBuf->pInBuf) {
NWDSFreeBuf(pBuf->pInBuf);
}
FreeADsMem(pBuf);
}
RRETURN(hr);
}
HRESULT
ADsNdsMoveObject(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR pszSrcObjectDn,
LPWSTR pszDestContainerDn,
LPWSTR pszNewRDN
)
{
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
HRESULT hr = S_OK;
NWDSCCODE ccode;
if (!pADsContext) {
RRETURN(E_ADS_BAD_PARAMETER);
}
ccode = NWDSMoveObject(
pADsContext->hContext,
(pnstr8) pszSrcObjectDn,
(pnstr8) pszDestContainerDn,
(pnstr8) pszNewRDN
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}
HRESULT
ADsNdsRenameObject(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR pszSrcObjectDn,
LPWSTR pszNewRDN
)
{
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
HRESULT hr = S_OK;
NWDSCCODE ccode;
if (!pADsContext) {
RRETURN(E_ADS_BAD_PARAMETER);
}
ccode = NWDSModifyRDN(
pADsContext->hContext,
(pnstr8) pszSrcObjectDn,
(pnstr8) pszNewRDN,
TRUE
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}
HRESULT
ADsNdsChangeObjectPassword(
NDS_CONTEXT_HANDLE hADsContext,
LPWSTR szObjectName,
NWOBJ_TYPE dwOT_ID,
LPWSTR szOldPassword,
LPWSTR szNewPassword
)
{
NWCCODE ccode = 0;
HRESULT hr = S_OK;
nuint32 connRef = 0;
NWCONN_HANDLE connHandle;
PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
char *szAnsiNewPassword = szNewPassword ? (char *)AllocADsMem(wcslen(szNewPassword)+1) : NULL;
char *szAnsiOldPassword = szOldPassword ? (char *)AllocADsMem(wcslen(szOldPassword)+1) : (char *) AllocADsMem(1);
if ( !szObjectName || !szNewPassword ) {
hr = E_INVALIDARG ;
BAIL_ON_FAILURE(hr);
}
//
// Convert UNICODE into ANSI representation required by NW APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
UnicodeToAnsiString(
szNewPassword,
szAnsiNewPassword,
0
);
//
// If the old password is passed in, we'll call change password
//
if (szOldPassword) {
UnicodeToAnsiString(
szOldPassword,
szAnsiOldPassword,
0
);
ccode = NWDSChangeObjectPassword(
pADsContext->hContext,
0,
(pnstr8) szObjectName, //IMP: send the unicode string itself
szAnsiOldPassword,
szAnsiNewPassword
);
}
//
// Else, we'll set the password to the supplied password
//
else {
szAnsiOldPassword[0] = 0 ;
//
// To ensure that read/search doesn't collide with GenObjectKeyPair().
// GenObjectKeyPair() changes the context state which will cause
// read/search to return type-less DNs
//
EnterCriticalSection(&g_ContextCritSect);
ccode = NWDSGenerateObjectKeyPair(
pADsContext->hContext,
(pnstr8) szObjectName,
szAnsiNewPassword,
0);
LeaveCriticalSection(&g_ContextCritSect);
}
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
FreeADsMem(szAnsiOldPassword);
FreeADsMem(szAnsiNewPassword);
RRETURN(hr);
}
//
// General function to convert variant array to string array
//
HRESULT
ConvertVariantArrayToStringArray(
PVARIANT pVarArray,
PWSTR **pppszStringArray,
DWORD dwNumStrings
)
{
HRESULT hr = S_OK;
PWSTR *ppszStringArray = NULL;
DWORD i = 0;
//
// Start off with a zero-length array.
//
*pppszStringArray = NULL;
ppszStringArray = (PWSTR *)AllocADsMem(dwNumStrings * sizeof(PWSTR));
if (!ppszStringArray)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
for (i = 0; i < dwNumStrings; i++)
{
if (!(V_VT(pVarArray + i) == VT_BSTR))
BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
ppszStringArray[i] = AllocADsStr(V_BSTR(pVarArray + i));
if (!ppszStringArray[i])
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
*pppszStringArray = ppszStringArray;
RRETURN(hr);
error:
if (ppszStringArray)
{
for (DWORD j = 0; j < i; j++)
if (ppszStringArray[i])
FreeADsStr(ppszStringArray[i]);
FreeADsMem(ppszStringArray);
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiOpenPrinter
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiOpenPrinter(
LPWSTR lpszUncPrinterName,
HANDLE *phPrinter,
DWORD dwAccess
)
{
BOOL fStatus = TRUE;
HANDLE hPrinter;
HRESULT hr = S_OK;
PRINTER_DEFAULTS PrinterDefault = {0, 0, dwAccess};
//
// Set desired access right.
//
PrinterDefault.DesiredAccess = dwAccess;
//
// Get a handle to the speccified printer using Win32 API.
//
fStatus = OpenPrinter(
lpszUncPrinterName,
&hPrinter,
&PrinterDefault
);
//
// Convert error code into HRESULT.
//
if (fStatus == FALSE) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
//
// Return.
//
else {
*phPrinter = hPrinter;
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiClosePrinter
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiClosePrinter(
HANDLE hPrinter
)
{
BOOL fStatus = TRUE;
HRESULT hr = S_OK;
//
// Close a printer using Win32 API.
//
fStatus = ClosePrinter(hPrinter);
//
// Convert error code into HRESULT.
//
if (fStatus == FALSE) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
//
// Return.
//
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiSetPrinter
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiSetPrinter(
HANDLE hPrinter,
DWORD dwLevel,
LPBYTE lpbPrinters,
DWORD dwAccess
)
{
BOOL fStatus = FALSE;
HRESULT hr = S_OK;
fStatus = SetPrinter(
hPrinter,
dwLevel,
lpbPrinters,
dwAccess
);
if (!fStatus) {
goto error;
}
RRETURN(S_OK);
error:
hr = HRESULT_FROM_WIN32(GetLastError());
RRETURN(hr);
}