|
|
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cenumdom.cxx
//
// Contents: Windows NT 3.5 Domain Enumeration Code
//
// CWinNTDomainEnum::CWinNTDomainEnum()
// CWinNTDomainEnum::CWinNTDomainEnum
// CWinNTDomainEnum::EnumObjects
// CWinNTDomainEnum::EnumObjects
//
// History:
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
//+---------------------------------------------------------------------------
//
// Function: CWinNTEnumVariant::Create
//
// Synopsis:
//
// Arguments: [pCollection]
// [ppEnumVariant]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT CWinNTDomainEnum::Create( CWinNTDomainEnum FAR* FAR* ppenumvariant, LPWSTR ADsPath, LPWSTR DomainName, VARIANT var, CWinNTCredentials& Credentials ) { HRESULT hr = NOERROR; CWinNTDomainEnum FAR* penumvariant = NULL; NET_API_STATUS nasStatus = 0;
*ppenumvariant = NULL;
penumvariant = new CWinNTDomainEnum(); if (!penumvariant) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
penumvariant->_ADsPath = AllocADsStr( ADsPath); if (!penumvariant->_ADsPath) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr);
penumvariant->_DomainName = AllocADsStr( DomainName); if (!penumvariant->_DomainName) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr);
hr = ObjectTypeList::CreateObjectTypeList( var, &penumvariant->_pObjList ); BAIL_ON_FAILURE(hr);
//
// ramv's change. You don't need to do a WinNTGetCachedDCName
// to validate a domain here. You might be dealing with a
// workgroup. If this call succeeds then we keep a BOOL variable
// which tells us next time when it is necessary whether it is a
// domain or workgroup
//
hr = WinNTGetCachedDCName( penumvariant->_DomainName, penumvariant->_szDomainPDCName, Credentials.GetFlags() );
if(SUCCEEDED(hr)){ penumvariant->_fIsDomain = TRUE;
} else { penumvariant->_fIsDomain = FALSE; }
penumvariant->_Credentials = Credentials; hr = penumvariant->_Credentials.RefDomain(DomainName); BAIL_ON_FAILURE(hr);
*ppenumvariant = penumvariant;
RRETURN(S_OK);
error:
delete penumvariant;
RRETURN_EXP_IF_ERR(hr); }
CWinNTDomainEnum::CWinNTDomainEnum(): _ADsPath(NULL), _DomainName(NULL) { _pObjList = NULL; _pBuffer = NULL; _dwObjectReturned = 0; _dwIndex = 0; _dwObjectCurrentEntry = 0; _dwObjectTotal = 0; _dwNetCount = 0;
_hLGroupComputer = NULL; _hGGroupComputer = NULL; _dwGroupArrayIndex = 0;
_dwCompObjectReturned = 0; _dwCompObjectCurrentEntry = 0; _dwCompObjectTotal = 0; _pCompBuffer = 0; _dwCompIndex = 0; _pServerInfo = NULL;
_fSchemaReturned = FALSE;
memset(_szDomainPDCName, 0, sizeof(WCHAR)*MAX_PATH);
}
CWinNTDomainEnum::CWinNTDomainEnum(ObjectTypeList ObjList): _ADsPath(NULL), _DomainName(NULL) { _pObjList = NULL; _pBuffer = NULL; _dwObjectReturned = 0; _dwObjectCurrentEntry = 0; _dwIndex = 0; _dwNetCount = 0;
_hLGroupComputer = NULL; _hGGroupComputer = NULL; _dwGroupArrayIndex = 0;
_dwCompObjectReturned = NULL; _dwCompObjectCurrentEntry = NULL; _dwCompObjectTotal = NULL; _dwCompResumeHandle = 0; _pCompBuffer = NULL; _fIsDomain = FALSE; _pServerInfo = NULL;
_fSchemaReturned = FALSE;
memset(_szDomainPDCName, 0, sizeof(WCHAR)*MAX_PATH);
}
CWinNTDomainEnum::~CWinNTDomainEnum() { if (_hLGroupComputer) { WinNTCloseComputer( _hLGroupComputer ); }
if (_hGGroupComputer) { WinNTCloseComputer( _hGGroupComputer ); }
if (_pCompBuffer) {
NetApiBufferFree(_pCompBuffer); }
if (_DomainName) { FreeADsStr(_DomainName); }
if (_ADsPath) { FreeADsStr(_ADsPath); }
if (_pObjList) {
delete _pObjList; }
}
HRESULT CWinNTDomainEnum::EnumObjects( DWORD ObjectType, ULONG cElements, VARIANT FAR * pvar, ULONG FAR * pcElementFetched ) { HRESULT hr = S_OK; ULONG cElementGlobal = 0; ULONG cElementLocal = 0;
switch (ObjectType) {
case WINNT_COMPUTER_ID: hr = EnumComputers(cElements, pvar, pcElementFetched); break; case WINNT_USER_ID: hr = EnumUsers(cElements, pvar, pcElementFetched); break;
case WINNT_GROUP_ID:
//
// for backward compatabillity, "group" includes "local group" and
// "global group" during enumeration
//
//
// enum all the global groups first
//
hr = EnumGlobalGroups( cElements, pvar, &cElementGlobal );
//
// enum local groups when there is no more global
//
if (hr == S_FALSE) { hr = EnumLocalGroups( cElements-cElementGlobal, // we have reduced buffer size!
pvar+cElementGlobal, &cElementLocal ); }
//
// increment instead of just assingment: for consistency with
// other switch cases
//
(*pcElementFetched) += (cElementGlobal+cElementLocal); break;
case WINNT_LOCALGROUP_ID: hr = EnumLocalGroups(cElements, pvar, pcElementFetched); break;
case WINNT_GLOBALGROUP_ID: hr = EnumGlobalGroups(cElements, pvar, pcElementFetched); break;
case WINNT_SCHEMA_ID: hr = EnumSchema(cElements, pvar, pcElementFetched); break; default: RRETURN(S_FALSE); } RRETURN_EXP_IF_ERR(hr); }
HRESULT CWinNTDomainEnum::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_OK; 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); }
HRESULT CWinNTDomainEnum::EnumSchema( ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched ) { HRESULT hr = S_OK; IDispatch *pDispatch = NULL;
if ( _fSchemaReturned ) RRETURN(S_FALSE);
if ( cElements > 0 ) { hr = CWinNTSchema::CreateSchema( _ADsPath, TEXT("Schema"), ADS_OBJECT_BOUND, IID_IDispatch, _Credentials, (void **)&pDispatch );
if ( hr == S_OK ) { VariantInit(&pvar[0]); pvar[0].vt = VT_DISPATCH; pvar[0].pdispVal = pDispatch; (*pcElementFetched)++; _fSchemaReturned = TRUE; } }
RRETURN(hr); }
HRESULT CWinNTDomainEnum::EnumUsers( ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched ) { HRESULT hr = S_OK; IDispatch *pDispatch = NULL; DWORD i = 0;
if(!_fIsDomain){ RRETURN(S_FALSE); } while (i < cElements) {
hr = GetUserObject(&pDispatch); if (hr == S_FALSE) { break; }
VariantInit(&pvar[i]); pvar[i].vt = VT_DISPATCH; pvar[i].pdispVal = pDispatch; (*pcElementFetched)++; i++; } return(hr); }
HRESULT CWinNTDomainEnum::GetUserObject( IDispatch ** ppDispatch ) { HRESULT hr = S_OK; NTSTATUS Status; PNET_DISPLAY_USER pUserInfo1 = NULL; NET_API_STATUS nasStatus = 0; DWORD dwResumeHandle = 0;
if (!_pBuffer || (_dwObjectCurrentEntry == _dwObjectReturned)) {
if (_pBuffer) { NetApiBufferFree(_pBuffer); _pBuffer = NULL; }
_dwObjectCurrentEntry = 0; _dwObjectReturned = 0;
nasStatus = NetQueryDisplayInformation( _szDomainPDCName, 1, _dwIndex, 1024, MAX_PREFERRED_LENGTH, &_dwObjectReturned, (PVOID *)&_pBuffer ); _dwNetCount++;
//
// 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)) { RRETURN(S_FALSE); }
//
// This one is to handle the termination case - Call completed
// successfully but there is no data to retrieve _pBuffer = NULL
//
if (!_pBuffer) { RRETURN(S_FALSE); }
_dwIndex = (_pBuffer + _dwObjectReturned -1)->usri1_next_index;
}
//
// Now send back the current ovbject
//
pUserInfo1 = (PNET_DISPLAY_USER)_pBuffer; pUserInfo1 += _dwObjectCurrentEntry;
hr = CWinNTUser::CreateUser( _ADsPath, WINNT_DOMAIN_ID, _DomainName, NULL, pUserInfo1->usri1_name, ADS_OBJECT_BOUND, &(pUserInfo1->usri1_flags), pUserInfo1->usri1_full_name, pUserInfo1->usri1_comment, NULL, IID_IDispatch, _Credentials, (void **)ppDispatch ); BAIL_IF_ERROR(hr); _dwObjectCurrentEntry++;
RRETURN(S_OK);
cleanup: *ppDispatch = NULL; RRETURN(S_FALSE); }
HRESULT CWinNTDomainEnum::EnumComputers( ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched ) { HRESULT hr = S_OK; IDispatch *pDispatch = NULL; DWORD i = 0;
while (i < cElements) { if(_fIsDomain == TRUE){ hr = GetComputerObject(&pDispatch); } else { hr = GetComputerObjectInWorkGroup(&pDispatch); }
if (hr == S_FALSE) { break; }
VariantInit(&pvar[i]); pvar[i].vt = VT_DISPATCH; pvar[i].pdispVal = pDispatch; (*pcElementFetched)++; i++; } return(hr); }
HRESULT CWinNTDomainEnum::GetComputerObject( IDispatch ** ppDispatch ) { HRESULT hr = S_OK; NTSTATUS Status; PNET_DISPLAY_MACHINE pDisplayComp = NULL; NET_API_STATUS nasStatus = 0; DWORD dwResumeHandle = 0; DWORD clen = 0;
if (!_pCompBuffer || (_dwCompObjectCurrentEntry == _dwCompObjectReturned)) {
if (_pCompBuffer) { NetApiBufferFree(_pCompBuffer); _pCompBuffer = NULL; }
_dwCompObjectCurrentEntry = 0; _dwCompObjectReturned = 0;
nasStatus = NetQueryDisplayInformation( _szDomainPDCName, 2, _dwCompIndex, 100, MAX_PREFERRED_LENGTH, &_dwCompObjectReturned, (PVOID *)&_pCompBuffer );
// 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)) { RRETURN(S_FALSE); }
//
// This one is to handle the termination case - Call completed
// successfully but there is no data to retrieve _pBuffer = NULL
//
if (!_pCompBuffer) { RRETURN(S_FALSE); }
_dwCompIndex = (_pCompBuffer + _dwCompObjectReturned -1)->usri2_next_index;
}
//
// Now send back the current object
//
pDisplayComp = (PNET_DISPLAY_MACHINE)_pCompBuffer; pDisplayComp += _dwCompObjectCurrentEntry;
//
// The usri2_name is going to be returned back with a
// $ character appended. Null set the $ character.
//
clen = wcslen(pDisplayComp->usri2_name); *(pDisplayComp->usri2_name + clen -1) = L'\0';
hr = CWinNTComputer::CreateComputer( _ADsPath, _DomainName, pDisplayComp->usri2_name, ADS_OBJECT_BOUND, IID_IDispatch, _Credentials, (void **)ppDispatch ); BAIL_IF_ERROR(hr); _dwCompObjectCurrentEntry++;
RRETURN(S_OK);
cleanup: *ppDispatch = NULL; RRETURN(S_FALSE); }
//+---------------------------------------------------------------------------
//
// Function: CWinNTDomainEnum::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 CWinNTDomainEnum::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(hr); }
HRESULT CWinNTDomainEnum::GetComputerObjectInWorkGroup( IDispatch ** ppDispatch ) { HRESULT hr = S_OK; NTSTATUS Status; PSERVER_INFO_100 pServerInfo = NULL; NET_API_STATUS nasStatus = 0; DWORD clen = 0;
if (!_pServerInfo || (_dwCompObjectCurrentEntry == _dwCompObjectReturned)) {
if (_pServerInfo) { NetApiBufferFree(_pServerInfo); _pServerInfo = NULL; }
if(_dwCompObjectTotal == _dwCompObjectReturned && (_dwCompObjectTotal !=0)){ //
// we got all elements already, no need to do another call
//
RRETURN(S_FALSE); }
nasStatus = NetServerEnum( NULL, 100, (LPBYTE *)&_pServerInfo, MAX_PREFERRED_LENGTH, &_dwCompObjectReturned, &_dwCompObjectTotal, SV_TYPE_NT, _DomainName, &_dwCompResumeHandle );
/*
nasStatus = NetQueryDisplayInformation( _szDomainPDCName, 2, _dwCompIndex, 100, MAX_PREFERRED_LENGTH, &_dwCompObjectReturned, (PVOID *)&_pServerInfo );
*/ //
// 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)) { RRETURN(S_FALSE); }
_dwCompObjectCurrentEntry = 0;
//
// This one is to handle the termination case - Call completed
// successfully but there is no data to retrieve _pServerInfo = NULL
//
if (!_dwCompObjectReturned) { _pServerInfo = NULL; RRETURN(S_FALSE); }
}
//
// Now send back the current object
//
pServerInfo = (PSERVER_INFO_100)_pServerInfo; pServerInfo += _dwCompObjectCurrentEntry;
hr = CWinNTComputer::CreateComputer( _ADsPath, _DomainName, pServerInfo->sv100_name, ADS_OBJECT_BOUND, IID_IDispatch, _Credentials, (void **)ppDispatch ); BAIL_IF_ERROR(hr); _dwCompObjectCurrentEntry++;
RRETURN(S_OK);
cleanup: *ppDispatch = NULL; RRETURN(S_FALSE); }
HRESULT CWinNTDomainEnum::GetGlobalGroupObject( IDispatch ** ppDispatch ) { HRESULT hr = S_OK; LPWINNT_GROUP pWinNTGrp = NULL; LPBYTE pBuffer = NULL; DWORD dwReturned = 0; BOOL dwRet = 0;
if (!_hGGroupComputer) { dwRet = WinNTComputerOpen( _DomainName, (_szDomainPDCName + 2), WINNT_DOMAIN_ID, &_hGGroupComputer ); if (!dwRet) { goto error; } }
dwRet = WinNTEnumGlobalGroups( _hGGroupComputer, 1, &pBuffer, &dwReturned ); if (!dwRet) { goto error; }
pWinNTGrp = (LPWINNT_GROUP)pBuffer;
hr = CWinNTGroup::CreateGroup( pWinNTGrp->Parent, WINNT_DOMAIN_ID, pWinNTGrp->Domain, pWinNTGrp->Computer, pWinNTGrp->Name, WINNT_GROUP_GLOBAL, ADS_OBJECT_BOUND, IID_IDispatch, _Credentials, (void **)ppDispatch ); BAIL_ON_FAILURE(hr);
hr = S_OK;
cleanup:
if (pBuffer) {
FreeADsMem(pBuffer); }
RRETURN(hr);
error: *ppDispatch = NULL;
hr = S_FALSE;
goto cleanup; }
HRESULT CWinNTDomainEnum::GetLocalGroupObject( IDispatch ** ppDispatch ) { HRESULT hr = S_OK; LPWINNT_GROUP pWinNTGrp = NULL; LPBYTE pBuffer = NULL; DWORD dwReturned = 0; BOOL dwRet = 0;
if (!_hLGroupComputer) { dwRet = WinNTComputerOpen( _DomainName, (_szDomainPDCName + 2), WINNT_DOMAIN_ID, &_hLGroupComputer ); if (!dwRet) { goto error; } }
dwRet = WinNTEnumLocalGroups( _hLGroupComputer, 1, &pBuffer, &dwReturned ); if (!dwRet) { goto error; }
pWinNTGrp = (LPWINNT_GROUP)pBuffer;
hr = CWinNTGroup::CreateGroup( pWinNTGrp->Parent, WINNT_DOMAIN_ID, pWinNTGrp->Domain, pWinNTGrp->Computer, pWinNTGrp->Name, WINNT_GROUP_LOCAL, ADS_OBJECT_BOUND, IID_IDispatch, _Credentials, (void **)ppDispatch ); BAIL_ON_FAILURE(hr);
hr = S_OK;
cleanup:
if (pBuffer) {
FreeADsMem(pBuffer); }
RRETURN(hr);
error: *ppDispatch = NULL;
hr = S_FALSE;
goto cleanup;
}
HRESULT CWinNTDomainEnum::EnumGroupObjects( DWORD ObjectType, ULONG cElements, VARIANT FAR * pvar, ULONG FAR * pcElementFetched ) { HRESULT hr; switch (ObjectType) {
case WINNT_GROUP_GLOBAL: hr = EnumGlobalGroups(cElements, pvar, pcElementFetched); break;
case WINNT_GROUP_LOCAL: hr = EnumLocalGroups(cElements, pvar, pcElementFetched); break;
default: hr = S_FALSE; break; } RRETURN(hr); }
ULONG GroupTypeArray[] = {WINNT_GROUP_GLOBAL, WINNT_GROUP_LOCAL, 0xFFFFFFFF};
HRESULT CWinNTDomainEnum::EnumGroups( 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_OK; DWORD ObjectType;
if(!_fIsDomain){ RRETURN(S_FALSE); }
for (i = 0; i < cElements; i++) { VariantInit(&pvar[i]); } cRequested = cElements;
while ((GroupTypeArray[_dwGroupArrayIndex] != (ULONG)-1) && ((hr = EnumGroupObjects( GroupTypeArray[_dwGroupArrayIndex], cRequested, pPathvar, &cFetchedByPath)) == S_FALSE )) {
pPathvar += cFetchedByPath; cRequested -= cFetchedByPath; cTotalFetched += cFetchedByPath;
cFetchedByPath = 0;
if (GroupTypeArray[_dwGroupArrayIndex++] == (ULONG)-1){ if (pcElementFetched) *pcElementFetched = cTotalFetched; RRETURN(S_FALSE); }
}
if (pcElementFetched) { *pcElementFetched = cTotalFetched + cFetchedByPath; }
RRETURN(hr); }
HRESULT CWinNTDomainEnum::EnumGlobalGroups( ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched ) { HRESULT hr = S_OK; IDispatch *pDispatch = NULL; DWORD i = 0;
while (i < cElements) {
hr = GetGlobalGroupObject(&pDispatch); if (hr == S_FALSE) { break; }
VariantInit(&pvar[i]); pvar[i].vt = VT_DISPATCH; pvar[i].pdispVal = pDispatch; (*pcElementFetched)++; i++; } return(hr); }
HRESULT CWinNTDomainEnum::EnumLocalGroups( ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched ) { HRESULT hr = S_OK; IDispatch *pDispatch = NULL; DWORD i = 0;
while (i < cElements) {
hr = GetLocalGroupObject(&pDispatch); if (hr == S_FALSE) { break; }
VariantInit(&pvar[i]); pvar[i].vt = VT_DISPATCH; pvar[i].pdispVal = pDispatch; (*pcElementFetched)++; i++; } return(hr); }
|