512 lines
12 KiB
C++
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);
|
||
|
}
|