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

512 lines
12 KiB
C++

//---------------------------------------------------------------------------
//
// 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);
}
#ifndef WIN95
dwStatus = NPOpenEnum(RESOURCE_GLOBALNET,
RESOURCETYPE_ANY,
0,
NULL,
&penumvariant->_hEnum);
#else
dwStatus = WNetOpenEnumA(RESOURCE_GLOBALNET,
RESOURCETYPE_ANY,
0,
NULL,
&penumvariant->_hEnum);
#endif
if (dwStatus != NO_ERROR) {
hr = HRESULT_FROM_WIN32(dwStatus);
BAIL_ON_FAILURE(hr);
}
hr = ObjectTypeList::CreateObjectTypeList(
var,
&penumvariant->_pObjList
);
BAIL_ON_FAILURE(hr);
penumvariant->_Credentials = Credentials;
*ppenumvariant = penumvariant;
RRETURN(hr);
error:
if (penumvariant) {
delete penumvariant;
}
RRETURN_EXP_IF_ERR(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::CNDSNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CNDSNamespaceEnum::CNDSNamespaceEnum()
{
_pObjList = NULL;
_dwEntriesRead = 0;
_dwCurrentEntry = 0;
_hEnum = NULL;
_pBuffer = NULL;
}
//+---------------------------------------------------------------------------
//
// Function: CNDSNamespaceEnum::~CNDSNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CNDSNamespaceEnum::~CNDSNamespaceEnum()
{
if (_pBuffer)
FreeADsMem(_pBuffer);
if ( _pObjList )
delete _pObjList;
}
//+---------------------------------------------------------------------------
//
// 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 = EnumObjects(
cElements,
pvar,
&cElementFetched
);
if (pcElementFetched) {
*pcElementFetched = cElementFetched;
}
RRETURN_EXP_IF_ERR(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()
{
NWCONN_HANDLE hConn;
NWOBJ_ID dwResumeObjectID = 0xFFFFFFFF;
HRESULT hr = S_OK;
DWORD cb = ENUM_BUFFER_SIZE;
LPWSTR lpString = NULL, pszObjectName = NULL;
DWORD dwIter = 0, i;
BOOL fFound ;
//
// 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
//
hr = NWApiGetAnyBinderyHandle(
&hConn
);
if FAILED(hr) {
return(hr) ;
}
_dwEntriesRead = 0 ;
do {
hr = NWApiObjectEnum(
hConn,
OT_DIRSERVER,
&pszObjectName,
&dwResumeObjectID
);
if (FAILED(hr)) {
if (_dwEntriesRead > 0)
hr = S_OK ;
break ;
}
//
// 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 = (DWORD) ((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++ ;
}
FreeADsStr(pszObjectName) ;
pszObjectName = NULL;
} while (TRUE) ;
error:
if (pszObjectName) {
FreeADsStr(pszObjectName);
}
(void) NWApiReleaseBinderyHandle(hConn);
RRETURN(hr);
}
HRESULT
CNDSNamespaceEnum::EnumObjects(
DWORD ObjectType,
ULONG cElements,
VARIANT FAR * pvar,
ULONG FAR * pcElementFetched
)
{
switch (ObjectType) {
case NDS_TREE_ID:
RRETURN (FetchObjects(cElements, pvar, pcElementFetched));
default:
RRETURN(S_FALSE);
}
}
HRESULT
CNDSNamespaceEnum::EnumObjects(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
DWORD i;
ULONG cRequested = 0;
ULONG cFetchedByPath = 0;
ULONG cTotalFetched = 0;
VARIANT FAR* pPathvar = pvar;
HRESULT hr = E_FAIL;
DWORD ObjectType;
for (i = 0; i < cElements; i++) {
VariantInit(&pvar[i]);
}
cRequested = cElements;
while (SUCCEEDED(_pObjList->GetCurrentObject(&ObjectType)) &&
((hr = EnumObjects(ObjectType,
cRequested,
pPathvar,
&cFetchedByPath)) == S_FALSE )) {
pPathvar += cFetchedByPath;
cRequested -= cFetchedByPath;
cTotalFetched += cFetchedByPath;
cFetchedByPath = 0;
if (FAILED(_pObjList->Next())){
if (pcElementFetched)
*pcElementFetched = cTotalFetched;
RRETURN(S_FALSE);
}
}
if (pcElementFetched) {
*pcElementFetched = cTotalFetched + cFetchedByPath;
}
RRETURN(hr);
}