mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2648 lines
65 KiB
2648 lines
65 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|