//--------------------------------------------------------------------------- // // 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); }