396 lines
9.4 KiB
C++
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;
|
|
}
|