windows-nt/Source/XPSP1/NT/ds/adsi/nwnds/cenumns.cxx

461 lines
11 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cenumvar.cxx
//
// Contents: Windows NT 3.5 Enumerator Code
//
// CNDSNamespaceEnum::Create
// CNDSNamespaceEnum::CNDSNamespaceEnum
// CNDSNamespaceEnum::~CNDSNamespaceEnum
// CNDSNamespaceEnum::Next
// CNDSNamespaceEnum::FetchObjects
// CNDSNamespaceEnum::FetchNextObject
// CNDSNamespaceEnum::PrepBuffer
//
// History:
//----------------------------------------------------------------------------
#include "NDS.hxx"
#pragma hdrstop
#define ENUM_BUFFER_SIZE (1024 * 16)
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::Create
//
// Synopsis:
//
// Arguments: [pCollection]
// [ppEnumVariant]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
CNDSNamespaceEnum::Create(
CNDSNamespaceEnum FAR* FAR* ppenumvariant,
VARIANT var,
CCredentials& Credentials
)
{
HRESULT hr = S_OK;
CNDSNamespaceEnum FAR* penumvariant = NULL;
DWORD dwStatus;
penumvariant = new CNDSNamespaceEnum();
if (penumvariant == NULL){
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
penumvariant->_Credentials = Credentials;
*ppenumvariant = penumvariant;
RRETURN(hr);
error:
if (penumvariant) {
delete penumvariant;
}
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::CNDSNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CNDSNamespaceEnum::CNDSNamespaceEnum()
{
_dwEntriesRead = 0;
_dwCurrentEntry = 0;
_pBuffer = NULL;
}
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::~CNDSNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CNDSNamespaceEnum::~CNDSNamespaceEnum()
{
if (_pBuffer)
FreeADsMem(_pBuffer);
}
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::Next
//
// Synopsis: Returns cElements number of requested ADs objects in the
// array supplied in pvar.
//
// Arguments: [cElements] -- The number of elements requested by client
// [pvar] -- ptr to array of VARIANTs to for return objects
// [pcElementFetched] -- if non-NULL, then number of elements
// -- actually returned is placed here
//
// Returns: HRESULT -- S_OK if number of elements requested are returned
// -- S_FALSE if number of elements is < requested
//
// Modifies:
//
// History:
//
//----------------------------------------------------------------------------
STDMETHODIMP
CNDSNamespaceEnum::Next(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
ULONG cElementFetched = 0;
HRESULT hr = S_OK;
hr = FetchObjects(
cElements,
pvar,
&cElementFetched
);
if (pcElementFetched) {
*pcElementFetched = cElementFetched;
}
RRETURN(hr);
}
HRESULT
CNDSNamespaceEnum::FetchObjects(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
HRESULT hr = S_OK;
IDispatch *pDispatch = NULL;
DWORD i = 0;
while (i < cElements) {
hr = FetchNextObject(&pDispatch);
if (hr == S_FALSE) {
break;
}
VariantInit(&pvar[i]);
pvar[i].vt = VT_DISPATCH;
pvar[i].pdispVal = pDispatch;
(*pcElementFetched)++;
i++;
}
return(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::FetchNextObject
//
// Synopsis: Gets IDispatch pointer of next object in namespace.
//
// Arguments: [ppDispatch] -- Pointer to where to return IDispatch pointer.
//
// Returns: HRESULT -- S_OK if got the next object
// -- S_FALSE if not
//
// Modifies: [*ppDispatch]
//
// History: 31-Jul-96 t-danal Use Multiple Network Provider for enum
//
//----------------------------------------------------------------------------
HRESULT
CNDSNamespaceEnum::FetchNextObject(
IDispatch ** ppDispatch
)
{
HRESULT hr;
DWORD dwStatus;
LPTSTR lpTreeName ;
*ppDispatch = NULL;
//
// Ensure that the buffer is valid
//
hr = PrepBuffer();
BAIL_ON_FAILURE(hr);
//
// Grab next (tree) name out of the buffer
//
lpTreeName = (LPWSTR)_pBuffer + (_dwCurrentEntry++ * OBJ_NAME_SIZE) ;
//
// Now create and send back the current object
//
hr = CNDSTree::CreateTreeObject(
L"NDS:",
lpTreeName,
L"Top",
_Credentials,
ADS_OBJECT_BOUND,
IID_IDispatch,
(void **)ppDispatch
);
BAIL_ON_FAILURE(hr);
error:
RRETURN_ENUM_STATUS(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::PrepBuffer
//
// Synopsis: Ensures that the enumeration buffer has something
//
// Arguments: none
//
// Returns: HRESULT -- S_OK if the buffer is ready to be used
// -- an error if not
//
// Modifies: _pBuffer, _dwCurrentEntry, _dwEntriesRead
//
// History: 31-Jul-96 t-danal Created
//
//----------------------------------------------------------------------------
HRESULT
CNDSNamespaceEnum::PrepBuffer()
{
HRESULT hr = S_OK;
DWORD cb = ENUM_BUFFER_SIZE;
DWORD dwIter = 0, i;
BOOL fFound ;
LPWSTR lpString = NULL;
WCHAR pszObjectName[OBJ_NAME_SIZE];
NWDSCCODE ccode;
nuint32 connRef = 0;
nstr8 aObjectName[OBJ_NAME_SIZE];
nuint32 objectID = 0xFFFFFFFF; /* -1 */
nuint16 objectType;
nuint8 objectHasProperties;
nuint8 objectFlag;
nuint8 objectSecurity;
NWCCConnInfo connInfo;
NWCONN_HANDLE connHandle;
nstr8 searchObjectName[48] = "*";
nuint16 searchObjectType = OT_TREE_NAME;
//
// Fill buffer as need. In theory we can get called to refill.
// But since we need get everything to remove dups in
// th case of TREEs, we dont allow this case. Ie. we get all
// and there should be no more. So if _dwCurrentEntry is not
// 0 and we need read more - then its time to bail.
//
if ( (_dwCurrentEntry < _dwEntriesRead) ) {
//
// Buffer still good
//
ADsAssert(_pBuffer) ;
return(S_OK) ;
}
if (_dwCurrentEntry != 0) {
return (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
}
//
// Allocate buffer, if needed
//
if (!_pBuffer) {
_pBuffer = AllocADsMem(cb);
if (!_pBuffer) {
hr = E_OUTOFMEMORY;
RRETURN(hr);
}
lpString = (LPWSTR) _pBuffer ;
_pBufferEnd = (LPBYTE)_pBuffer + cb ;
}
//
// Get handle
//
ccode = NWCCGetPrimConnRef(
&connRef
);
ccode = NWCCOpenConnByRef(
connRef,
NWCC_OPEN_UNLICENSED,
NWCC_RESERVED,
&connHandle
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWCCGetAllConnInfo(
connHandle,
NWCC_INFO_VERSION_1,
&connInfo
);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
_dwEntriesRead = 0 ;
do {
//
// Scan bindery for NDS tree objects
//
ccode = NWScanObject(connHandle,
searchObjectName,
searchObjectType,
&objectID,
aObjectName,
&objectType,
&objectHasProperties,
&objectFlag,
&objectSecurity);
if ( ccode ) {
if (_dwEntriesRead > 0)
hr = S_OK ;
break ;
}
AnsiToUnicodeString(
aObjectName,
pszObjectName,
NULL_TERMINATED
);
//
// Remove any trailing '_' upto 32 chars. This is standard NDS tree
// naming stuff.
//
dwIter = 31;
while (pszObjectName[dwIter] == L'_' && dwIter > 0 ) {
dwIter--;
}
pszObjectName[dwIter + 1] = L'\0';
//
// Scan for duplicates. We are doing linear everytime, but then again,
// there shouldnt be many trees.
//
fFound = FALSE ;
for (i = 0; i < _dwEntriesRead; i++) {
if (_wcsicmp(
pszObjectName,
(LPWSTR)_pBuffer + (i * OBJ_NAME_SIZE)) == 0) {
fFound = TRUE ;
break ;
}
}
//
// Copy this unique tree name into the buffer
//
if (!fFound) {
//
// Check that we have enough space.
//
if ((lpString + OBJ_NAME_SIZE) >= _pBufferEnd) {
cb = (LPBYTE)_pBufferEnd - (LPBYTE)_pBuffer ;
_pBuffer = ReallocADsMem(
_pBuffer,
cb,
2 * cb
);
if (!_pBuffer) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
lpString = (LPWSTR)_pBuffer + (_dwEntriesRead * OBJ_NAME_SIZE) ;
_pBufferEnd = (LPBYTE) _pBuffer + (2 * cb) ;
}
//
// Assume fixed size (max NW name). Yes, its more than
// we really need but keeps things simpler.
//
wcscpy(lpString, pszObjectName);
lpString += OBJ_NAME_SIZE ;
_dwEntriesRead++ ;
}
} while (TRUE) ;
error:
if (connHandle) {
NWCCCloseConn(
connHandle
);
}
RRETURN(hr);
}