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

442 lines
11 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cenumGroupCollection.cxx
//
// Contents: Windows NT 3.5 GroupCollection Enumeration Code
//
// History:
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
#define BASE_BUFFER_SIZE (4096 * sizeof(WCHAR))
CWinNTUserGroupsCollectionEnum::CWinNTUserGroupsCollectionEnum():
_ParentType(0),
_ParentADsPath(NULL),
_DomainName(NULL),
_ServerName(NULL),
_UserName(NULL),
_pGlobalBuffer(NULL),
_pLocalBuffer(NULL),
_dwCurrent(0),
_dwTotal(0),
_dwGlobalTotal(0),
_dwLocalTotal(0),
_fIsDomainController(FALSE)
{
VariantInit(&_vFilter);
}
CWinNTUserGroupsCollectionEnum::~CWinNTUserGroupsCollectionEnum()
{
if (_ParentADsPath)
ADsFreeString(_ParentADsPath);
if (_DomainName)
ADsFreeString(_DomainName);
if (_ServerName)
ADsFreeString(_ServerName);
if (_UserName)
ADsFreeString(_UserName);
if (_pGlobalBuffer)
NetApiBufferFree(_pGlobalBuffer);
if (_pLocalBuffer)
NetApiBufferFree(_pLocalBuffer);
VariantClear(&_vFilter);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTEnumVariant::Create
//
// Synopsis:
//
// Arguments: [pCollection]
// [ppEnumVariant]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
CWinNTUserGroupsCollectionEnum::Create(
CWinNTUserGroupsCollectionEnum FAR* FAR* ppenumvariant,
ULONG ParentType,
BSTR ParentADsPath,
BSTR DomainName,
BSTR ServerName,
BSTR UserName,
VARIANT vFilter,
CWinNTCredentials& Credentials
)
{
HRESULT hr = NOERROR;
CWinNTUserGroupsCollectionEnum FAR* penumvariant = NULL;
LPSERVER_INFO_101 lpServerInfo =NULL;
NET_API_STATUS nasStatus;
WCHAR szServer[MAX_PATH];
//
// Should the checks below be assertions?
//
if (!ppenumvariant)
return E_FAIL;
if (ParentType != WINNT_DOMAIN_ID &&
ParentType != WINNT_COMPUTER_ID)
return E_FAIL;
*ppenumvariant = NULL;
penumvariant = new CWinNTUserGroupsCollectionEnum();
if (!penumvariant) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
penumvariant->_ParentType = ParentType;
hr = ADsAllocString(ParentADsPath , &penumvariant->_ParentADsPath);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(DomainName, &penumvariant->_DomainName);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(ServerName, &penumvariant->_ServerName);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(UserName, &penumvariant->_UserName);
BAIL_ON_FAILURE(hr);
//
// We currently copy the filter but do nothing with it!!!
//
hr = VariantCopy(&penumvariant->_vFilter, &vFilter);
BAIL_ON_FAILURE(hr);
// check if the server is a DC
MakeUncName(ServerName, szServer);
nasStatus = NetServerGetInfo(
szServer,
101,
(LPBYTE *)&lpServerInfo
);
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
if( (lpServerInfo->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
(lpServerInfo->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ) {
penumvariant->_fIsDomainController = TRUE;
}
else
penumvariant->_fIsDomainController = FALSE;
hr = penumvariant->DoEnumeration();
BAIL_ON_FAILURE(hr);
penumvariant->_Credentials = Credentials;
hr = penumvariant->_Credentials.Ref(ServerName, DomainName, ParentType);
BAIL_ON_FAILURE(hr);
*ppenumvariant = penumvariant;
RRETURN(hr);
error:
delete penumvariant;
if(lpServerInfo)
NetApiBufferFree(lpServerInfo);
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTUserGroupsCollectionEnum::DoEnumeration()
{
HRESULT hr;
if (_ParentType == WINNT_DOMAIN_ID) {
hr = DoGlobalEnumeration();
BAIL_ON_FAILURE(hr);
hr = DoLocalEnumeration();
} else if (_ParentType == WINNT_COMPUTER_ID) {
// We also want to try and get the global groups,
// as this will be empty if the user does not belong to
// any global groups.
// We need to be careful on where we fail as we should
// continue enumerating local groups for lots of cases.
hr = DoGlobalEnumeration();
if ((hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
|| (hr == HRESULT_FROM_WIN32(NERR_InvalidComputer))
|| (hr == HRESULT_FROM_WIN32(NERR_UserNotFound))
|| (hr == E_FAIL)) {
hr = S_OK;
_dwGlobalTotal = 0;
}
BAIL_ON_FAILURE(hr);
hr = DoLocalEnumeration();
} else {
hr = E_FAIL;
}
error:
_dwTotal = _dwGlobalTotal + _dwLocalTotal;
RRETURN(hr);
}
HRESULT
CWinNTUserGroupsCollectionEnum::DoGlobalEnumeration()
{
HRESULT hr;
DWORD dwStatus;
DWORD dwRead = 0;
WCHAR szServer[MAX_PATH];
LPGROUP_USERS_INFO_0 pGroupUserInfo = NULL;
GROUP_INFO_2 *pGroupInfo2 = NULL;
NET_API_STATUS nasStatus;
MakeUncName(_ServerName, szServer);
dwStatus = NetUserGetGroups(szServer,
_UserName,
0,
(LPBYTE*)&_pGlobalBuffer,
MAX_PREFERRED_LENGTH,
&dwRead,
&_dwGlobalTotal);
hr = HRESULT_FROM_WIN32(dwStatus);
BAIL_ON_FAILURE(hr);
if (dwRead != _dwGlobalTotal)
hr = E_FAIL;
if (dwRead == 1) {
//
// Check if it is the none group - dont want that
//
pGroupUserInfo = (LPGROUP_USERS_INFO_0)_pGlobalBuffer;
if ( pGroupUserInfo->grui0_name && (FALSE == _fIsDomainController) &&
(1 == _dwGlobalTotal) ) {
// check if this the none group. Only non-DCs will return this group.
nasStatus = NetGroupGetInfo(
szServer,
pGroupUserInfo->grui0_name,
2,
(LPBYTE *) &pGroupInfo2
);
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
if (pGroupInfo2->grpi2_group_id == DOMAIN_GROUP_RID_USERS) {
//
// Set the global total to zero - destructor will dealloc.
//
_dwGlobalTotal = 0;
}
}
}
error:
if(pGroupInfo2)
NetApiBufferFree(pGroupInfo2);
RRETURN(hr);
}
HRESULT
CWinNTUserGroupsCollectionEnum::DoLocalEnumeration()
{
HRESULT hr;
DWORD dwStatus;
DWORD dwRead = 0;
WCHAR szServer[MAX_PATH];
MakeUncName(_ServerName, szServer);
dwStatus = NetUserGetLocalGroups(szServer,
_UserName,
0,
0,
(LPBYTE*)&_pLocalBuffer,
MAX_PREFERRED_LENGTH,
&dwRead,
&_dwLocalTotal);
hr = HRESULT_FROM_WIN32(dwStatus);
BAIL_ON_FAILURE(hr);
if (dwRead != _dwLocalTotal)
hr = E_FAIL;
error:
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTUserGroupsCollectionEnum::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
CWinNTUserGroupsCollectionEnum::Next(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
ULONG cElementFetched = 0;
HRESULT hr = S_OK;
hr = EnumUserGroups(
cElements,
pvar,
&cElementFetched
);
if (pcElementFetched) {
*pcElementFetched = cElementFetched;
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTUserGroupsCollectionEnum::Skip(ULONG cElements)
{
//
// Note: we better not wrap around when we add!
//
_dwCurrent += cElements;
_dwCurrent = min(_dwTotal, _dwCurrent);
if (_dwCurrent < _dwTotal)
return S_OK;
return S_FALSE;
}
STDMETHODIMP
CWinNTUserGroupsCollectionEnum::Reset()
{
_dwCurrent = 0;
return S_OK;
}
HRESULT
CWinNTUserGroupsCollectionEnum::EnumUserGroups(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
HRESULT hr = S_FALSE;
IDispatch *pDispatch = NULL;
DWORD i = 0;
while (i < cElements) {
hr = GetNextUserGroup(&pDispatch);
if (hr == S_FALSE) {
break;
}
VariantInit(&pvar[i]);
pvar[i].vt = VT_DISPATCH;
pvar[i].pdispVal = pDispatch;
(*pcElementFetched)++;
i++;
}
RRETURN(hr);
}
HRESULT
CWinNTUserGroupsCollectionEnum::GetNextUserGroup(
IDispatch ** ppDispatch
)
{
HRESULT hr;
LPGROUP_USERS_INFO_0 lpInfo;
LPWSTR GroupName;
ULONG GroupType;
if (_dwCurrent >= _dwTotal)
return S_FALSE;
if (_dwCurrent < _dwGlobalTotal) {
lpInfo = (LPGROUP_USERS_INFO_0)_pGlobalBuffer + _dwCurrent;
GroupType = WINNT_GROUP_GLOBAL;
} else {
lpInfo = (LPGROUP_USERS_INFO_0)_pLocalBuffer + _dwCurrent -
_dwGlobalTotal;
GroupType = WINNT_GROUP_LOCAL;
}
_dwCurrent++;
GroupName = lpInfo->grui0_name;
//
// On an error, should we try to keep going?
//
if (GroupType == WINNT_GROUP_GLOBAL) {
hr = CWinNTGroup::CreateGroup(_ParentADsPath,
_ParentType,
_DomainName,
_ServerName,
GroupName,
GroupType,
ADS_OBJECT_BOUND,
IID_IDispatch,
_Credentials,
(void **)ppDispatch
);
}
else {
hr = CWinNTGroup::CreateGroup(_ParentADsPath,
_ParentType,
_DomainName,
_ServerName,
GroupName,
GroupType,
ADS_OBJECT_BOUND,
IID_IDispatch,
_Credentials,
(void **)ppDispatch
);
}
if (FAILED(hr))
return S_FALSE;
return S_OK;
}