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

396 lines
9.4 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cenumvar.cxx
//
// Contents: Windows NT 3.5 Enumerator Code
//
// CWinNTNamespaceEnum::Create
// CWinNTNamespaceEnum::CWinNTNamespaceEnum
// CWinNTNamespaceEnum::~CWinNTNamespaceEnum
// CWinNTNamespaceEnum::QueryInterface
// CWinNTNamespaceEnum::AddRef
// CWinNTNamespaceEnum::Release
// CWinNTNamespaceEnum::Next
// CWinNTNamespaceEnum::Skip
// CWinNTNamespaceEnum::Clone
//
// History:
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
//+---------------------------------------------------------------------------
//
// Function: CWinNTNamespaceEnum::Create
//
// Synopsis:
//
// Arguments: [pCollection]
// [ppEnumVariant]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
CWinNTNamespaceEnum::Create(
CWinNTNamespaceEnum FAR* FAR* ppenumvariant,
VARIANT var,
CWinNTCredentials& Credentials
)
{
HRESULT hr = S_OK;
CWinNTNamespaceEnum FAR* penumvariant = NULL;
penumvariant = new CWinNTNamespaceEnum();
if (penumvariant == NULL){
hr = E_OUTOFMEMORY;
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: CWinNTNamespaceEnum::CWinNTNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CWinNTNamespaceEnum::CWinNTNamespaceEnum()
{
_pObjList = NULL;
_pBuffer = 0;
_dwObjectReturned = 0;
_dwObjectCurrentEntry = 0;
_dwObjectTotal = 0;
_dwResumeHandle = 0;
_bNoMore = FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTNamespaceEnum::~CWinNTNamespaceEnum
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
CWinNTNamespaceEnum::~CWinNTNamespaceEnum()
{
if (_pBuffer) {
NetApiBufferFree(_pBuffer);
}
if ( _pObjList )
delete _pObjList;
}
HRESULT
CWinNTNamespaceEnum::EnumObjects(
DWORD ObjectType,
ULONG cElements,
VARIANT FAR * pvar,
ULONG FAR * pcElementFetched
)
{
HRESULT hr = S_OK;
switch (ObjectType) {
case WINNT_DOMAIN_ID:
hr = EnumDomains(cElements, pvar, pcElementFetched);
RRETURN(hr);
default:
RRETURN(S_FALSE);
}
}
HRESULT
CWinNTNamespaceEnum::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 = S_FALSE;
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_EXP_IF_ERR(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTNamespaceEnum::Next
//
// Synopsis: Returns cElements number of requested NetOle 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: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTNamespaceEnum::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
CWinNTNamespaceEnum::EnumDomains(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
HRESULT hr = S_FALSE;
IDispatch *pDispatch = NULL;
DWORD i = 0;
BOOL fRepeat = FALSE;
DWORD dwFailureCount = 0;
DWORD dwPermitFailure = 1000;
while (i < cElements) {
hr = GetDomainObject(&pDispatch);
if (hr == S_FALSE) {
break;
}
else if (FAILED(hr)) {
//
// Got an error while retrieving the object, ignore the
// error and continue with the next object.
// If continuously getting error more than dwPermitFailure,
// make the return value S_FALSE, leave the loop.
//
if (fRepeat) {
dwFailureCount++;
if(dwFailureCount > dwPermitFailure) {
hr = S_FALSE;
break;
}
}
else {
fRepeat = TRUE;
dwFailureCount = 1;
}
// we need to move the _dwObjectCurrentEntry
_dwObjectCurrentEntry++;
hr = S_OK;
continue;
}
if (fRepeat) {
fRepeat = FALSE;
}
VariantInit(&pvar[i]);
pvar[i].vt = VT_DISPATCH;
pvar[i].pdispVal = pDispatch;
(*pcElementFetched)++;
i++;
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTNamespaceEnum::GetDomainObject(
IDispatch ** ppDispatch
)
{
HRESULT hr = S_OK;
PSERVER_INFO_100 pServerInfo100 = NULL;
NET_API_STATUS nasStatus = 0;
if (!_pBuffer || (_dwObjectCurrentEntry == _dwObjectReturned)) {
if (_pBuffer) {
NetApiBufferFree(_pBuffer);
_pBuffer = NULL;
}
_dwObjectCurrentEntry = 0;
_dwObjectReturned = 0;
if (_bNoMore) {
RRETURN(S_FALSE);
}
nasStatus = NetServerEnum(
NULL,
100,
(LPBYTE *)&_pBuffer,
MAX_PREFERRED_LENGTH,
&_dwObjectReturned,
&_dwObjectTotal,
SV_TYPE_DOMAIN_ENUM,
NULL,
&_dwResumeHandle
);
//
// The following if clause is to handle real errors; anything
// other than ERROR_SUCCESS and ERROR_MORE_DATA
//
if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
hr =S_FALSE;
goto cleanup;
}
if (nasStatus == ERROR_SUCCESS) {
_bNoMore = TRUE;
}
}
//
// Now send back the current object
//
//
// There is a scenario where NetServerEnum returns ERROR_SUCCESS
// when there is no data to send back. However the field
// _dwObjectsReturned will also be 0. We need to check that and
// bail out if necessary
//
if ((nasStatus == ERROR_SUCCESS) && _dwObjectReturned == 0){
RRETURN(S_FALSE);
}
pServerInfo100 = (LPSERVER_INFO_100)_pBuffer;
pServerInfo100 += _dwObjectCurrentEntry;
//
// We couldn't have any credentials coming in from a Namespace
// enumeration, since you can't have credentials coming in from
// a Namespace. So we use null credentials.
//
hr = CWinNTDomain::CreateDomain(
L"WinNT:",
pServerInfo100->sv100_name,
ADS_OBJECT_BOUND,
IID_IDispatch,
_Credentials,
(void **) ppDispatch
);
BAIL_IF_ERROR(hr);
_dwObjectCurrentEntry++;
RRETURN(S_OK);
cleanup:
*ppDispatch = NULL;
return hr;
}