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

1008 lines
22 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996
//
// File: cenumcom.cxx
//
// Contents: Windows NT 4.0 Enumeration code for computer container
//
// CWinNTComputerEnum::CWinNTComputerEnum()
// CWinNTComputerEnum::CWinNTComputerEnum
// CWinNTComputerEnum::EnumObjects
// CWinNTComputerEnum::EnumObjects
//
// History:
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
#if DBG
DECLARE_INFOLEVEL(EnumComp);
DECLARE_DEBUG(EnumComp);
#define EnumCompDebugOut(x) EnumCompInlineDebugOut x
#endif
//+---------------------------------------------------------------------------
//
// Function: CWinNTEnumVariant::Create
//
// Synopsis:
//
// Arguments: [pCollection]
// [ppEnumVariant]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
CWinNTComputerEnum::Create(
CWinNTComputerEnum FAR* FAR* ppenumvariant,
BSTR ADsPath,
BSTR DomainName,
BSTR ComputerName,
VARIANT var,
CWinNTCredentials& Credentials
)
{
HRESULT hr = NOERROR;
CWinNTComputerEnum FAR* penumvariant = NULL;
*ppenumvariant = NULL;
penumvariant = new CWinNTComputerEnum();
if (!penumvariant) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
hr = ADsAllocString( ADsPath, &penumvariant->_ADsPath);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString( DomainName, &penumvariant->_DomainName);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString( ComputerName, &penumvariant->_ComputerName);
BAIL_ON_FAILURE(hr);
hr = ObjectTypeList::CreateObjectTypeList(
var,
&penumvariant->_pObjList
);
BAIL_ON_FAILURE(hr);
penumvariant->_Credentials = Credentials;
hr = penumvariant->_Credentials.RefServer(ComputerName);
BAIL_ON_FAILURE(hr);
*ppenumvariant = penumvariant;
RRETURN(hr);
error:
delete penumvariant;
RRETURN_EXP_IF_ERR(hr);
}
CWinNTComputerEnum::CWinNTComputerEnum():
_ComputerName(NULL),
_DomainName(NULL),
_ADsPath(NULL)
{
_pObjList = NULL;
_pBuffer = NULL;
_bNoMore = 0;
_dwObjectReturned = 0;
_dwObjectCurrentEntry = 0;
_dwObjectTotal = 0;
_hLGroupComputer = NULL;
_hGGroupComputer = NULL;
_dwGroupArrayIndex = 0;
_pPrinterBuffer = NULL;
_dwPrinterObjectReturned = 0;
_dwPrinterObjectCurrentEntry = 0;
_dwPrinterObjectTotal = 0;
_fPrinterNoMore = 0;
_pServiceBuffer = NULL;
_dwServiceObjectReturned = 0;
_dwServiceObjectCurrentEntry = 0;
_dwServiceObjectTotal = 0;
_fServiceNoMore = 0;
_dwIndex = 0;
}
CWinNTComputerEnum::CWinNTComputerEnum(ObjectTypeList ObjList):
_ComputerName(NULL),
_DomainName(NULL),
_ADsPath(NULL)
{
_pObjList = NULL;
_pBuffer = NULL;
_bNoMore = 0;
_dwObjectReturned = 0;
_dwObjectTotal = 0;
_dwObjectCurrentEntry = 0;
_hLGroupComputer = NULL;
_hGGroupComputer = NULL;
_dwGroupArrayIndex = 0;
_pPrinterBuffer = NULL;
_dwPrinterObjectReturned = 0;
_dwPrinterObjectCurrentEntry = 0;
_dwPrinterObjectTotal = 0;
_fPrinterNoMore = FALSE;
_pServiceBuffer = NULL;
_dwServiceObjectReturned = 0;
_dwServiceObjectCurrentEntry = 0;
_dwServiceObjectTotal = 0;
_fServiceNoMore = FALSE;
_dwIndex = 0;
}
CWinNTComputerEnum::~CWinNTComputerEnum()
{
if (_pServiceBuffer) {
FreeADsMem(_pServiceBuffer);
}
if(_pPrinterBuffer){
FreeADsMem(_pPrinterBuffer);
}
if (_hLGroupComputer) {
WinNTCloseComputer(_hLGroupComputer);
}
if (_hGGroupComputer) {
WinNTCloseComputer(_hGGroupComputer);
}
if (_ComputerName) {
ADsFreeString(_ComputerName);
}
if (_ADsPath) {
ADsFreeString(_ADsPath);
}
if (_DomainName) {
ADsFreeString(_DomainName);
}
if (_pObjList) {
delete _pObjList;
}
}
HRESULT
CWinNTComputerEnum::EnumObjects(
DWORD ObjectType,
ULONG cElements,
VARIANT FAR * pvar,
ULONG FAR * pcElementFetched
)
{
HRESULT hr = S_OK ;
DWORD cElementLocal = 0;
DWORD cElementGlobal = 0;
switch (ObjectType) {
case WINNT_GROUP_ID:
//
// for backward compatabillity, "group" includes "local group" and
// "global group" during enumeration
//
//
// enum local groups first
//
hr = EnumGroupObjects(WINNT_GROUP_LOCAL,
cElements,
pvar,
&cElementLocal
);
if (hr == S_FALSE) {
//
// enum global groups after all local groups have been enumerated
//
hr = EnumGroupObjects(WINNT_GROUP_GLOBAL,
cElements-cElementLocal,
pvar+cElementLocal,
&cElementGlobal
);
}
//
// increment instead of assingn: consistent with other switch cases
//
(*pcElementFetched) += (cElementGlobal+cElementLocal);
break;
case WINNT_LOCALGROUP_ID:
hr = EnumGroupObjects(WINNT_GROUP_LOCAL,
cElements,
pvar,
pcElementFetched);
break;
case WINNT_GLOBALGROUP_ID:
hr = EnumGroupObjects(WINNT_GROUP_GLOBAL,
cElements,
pvar,
pcElementFetched);
break;
case WINNT_USER_ID:
hr = EnumUsers(cElements, pvar, pcElementFetched);
break;
case WINNT_PRINTER_ID:
hr = EnumPrintQueues(cElements, pvar, pcElementFetched);
break;
case WINNT_SERVICE_ID:
hr = EnumServices(cElements, pvar, pcElementFetched);
break;
default:
hr = S_FALSE;
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTComputerEnum::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;
return(ResultFromScode(S_FALSE));
}
}
if (pcElementFetched) {
*pcElementFetched = cTotalFetched + cFetchedByPath;
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTComputerEnum::EnumUsers(ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched)
{
HRESULT hr = S_OK ;
IDispatch *pDispatch = NULL;
DWORD i = 0;
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
CWinNTComputerEnum::GetUserObject(IDispatch ** ppDispatch)
{
HRESULT hr = S_OK;
NTSTATUS Status;
PNET_DISPLAY_USER pUserInfo1 = NULL;
NET_API_STATUS nasStatus = 0;
DWORD dwResumeHandle = 0;
WCHAR szBuffer[MAX_PATH];
if (!_pBuffer || (_dwObjectCurrentEntry == _dwObjectReturned)) {
if (_pBuffer) {
NetApiBufferFree(_pBuffer);
_pBuffer = NULL;
}
_dwObjectCurrentEntry = 0;
_dwObjectReturned = 0;
wcscpy(szBuffer, L"\\\\");
wcscat(szBuffer, _ComputerName);
nasStatus = NetQueryDisplayInformation(
szBuffer,
1,
_dwIndex,
1024,
MAX_PREFERRED_LENGTH,
&_dwObjectReturned,
(PVOID *)&_pBuffer
);
//
// 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 = ((PNET_DISPLAY_USER)_pBuffer + _dwObjectReturned -1)->usri1_next_index;
}
//
// Now send back the current ovbject
//
pUserInfo1 = (PNET_DISPLAY_USER)_pBuffer;
pUserInfo1 += _dwObjectCurrentEntry;
hr = CWinNTUser::CreateUser(
_ADsPath,
WINNT_COMPUTER_ID,
NULL,
_ComputerName,
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
CWinNTComputerEnum::EnumPrintQueues(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
HRESULT hr = S_OK ;
IDispatch *pDispatch = NULL;
DWORD i = 0;
while (i < cElements) {
hr = GetPrinterObject(&pDispatch);
if (hr != S_OK) {
break;
}
VariantInit(&pvar[i]);
pvar[i].vt = VT_DISPATCH;
pvar[i].pdispVal = pDispatch;
(*pcElementFetched)++;
i++;
}
return(hr);
}
HRESULT
CWinNTComputerEnum::GetPrinterObject(IDispatch **ppDispatch)
{
HRESULT hr = S_OK;
NTSTATUS Status;
NET_API_STATUS nasStatus = NERR_Success;
DWORD dwBytesNeeded = 0;
DWORD dwBufLen = 0;
WCHAR szPrintObjectName[MAX_PATH];
BOOL fStatus;
DWORD dwLastError;
LPBYTE pMem = NULL;
PRINTER_INFO_2 * pPrinterInfo2 = NULL;
WCHAR szDomainName[MAX_PATH];
if(!_pPrinterBuffer || (_dwPrinterObjectCurrentEntry == _dwPrinterObjectReturned)){
if (_pPrinterBuffer) {
FreeADsMem(_pPrinterBuffer);
_pPrinterBuffer = NULL;
}
if (_fPrinterNoMore) {
*ppDispatch = NULL;
return(S_FALSE);
}
_dwPrinterObjectCurrentEntry = 0;
_dwPrinterObjectReturned = 0;
wcscpy(szPrintObjectName, TEXT("\\\\"));
wcscat(szPrintObjectName, _ComputerName);
fStatus = WinNTEnumPrinters(
PRINTER_ENUM_NAME| PRINTER_ENUM_SHARED,
szPrintObjectName,
2,
(LPBYTE *)&_pPrinterBuffer,
&_dwPrinterObjectReturned
);
if (!fStatus || !_dwPrinterObjectReturned) {
_fPrinterNoMore = TRUE;
RRETURN(S_FALSE);
}
}
pPrinterInfo2 = (PRINTER_INFO_2 *)_pPrinterBuffer;
pPrinterInfo2 += _dwPrinterObjectCurrentEntry;
hr = CWinNTPrintQueue::CreatePrintQueue(
_ADsPath,
WINNT_COMPUTER_ID,
szDomainName,
_ComputerName,
pPrinterInfo2->pShareName,
ADS_OBJECT_BOUND,
IID_IDispatch,
_Credentials,
(void **)ppDispatch
);
BAIL_IF_ERROR(hr);
_dwPrinterObjectCurrentEntry++;
if(_dwPrinterObjectCurrentEntry == _dwPrinterObjectReturned){
_fPrinterNoMore = TRUE;
}
cleanup:
if(FAILED(hr)){
*ppDispatch = NULL;
#if DBG
EnumCompDebugOut((DEB_TRACE,
"hr Failed with value: %ld \n", hr ));
#endif
hr = S_FALSE; // something else may have failed!
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTComputerEnum::EnumServices(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
HRESULT hr = S_OK ;
IDispatch *pDispatch = NULL;
DWORD i = 0;
while (i < cElements) {
hr = GetServiceObject(&pDispatch);
if (hr != S_OK) {
break;
}
VariantInit(&pvar[i]);
pvar[i].vt = VT_DISPATCH;
pvar[i].pdispVal = pDispatch;
(*pcElementFetched)++;
i++;
}
RRETURN(hr);
}
HRESULT
CWinNTComputerEnum::GetServiceObject(IDispatch **ppDispatch)
{
HRESULT hr = S_OK;
LPBYTE pMem = NULL;
DWORD dwBytesNeeded = 0;
NET_API_STATUS nasStatus = NERR_Success;
WCHAR szBuffer[MAX_PATH];
ENUM_SERVICE_STATUS *pqssBuf;
WCHAR szDomainName[MAX_PATH];
if(!_pServiceBuffer || (_fServiceNoMore == TRUE )){
if(_pServiceBuffer){
FreeADsMem(_pServiceBuffer);
_pServiceBuffer = NULL;
}
if (_fServiceNoMore == TRUE) {
*ppDispatch = NULL;
return(S_FALSE);
}
_dwServiceObjectCurrentEntry = 0;
_dwServiceObjectReturned = 0;
hr = WinNTEnumServices( _ComputerName,
&_dwServiceObjectReturned,
&_pServiceBuffer
);
BAIL_IF_ERROR(hr);
if(hr == S_FALSE){
_fServiceNoMore = TRUE;
*ppDispatch = NULL;
goto cleanup;
}
}
hr = GetDomainFromPath(_ADsPath, szDomainName);
BAIL_IF_ERROR(hr);
pqssBuf = (ENUM_SERVICE_STATUS *)_pServiceBuffer;
pqssBuf += _dwServiceObjectCurrentEntry;
hr = CWinNTService::Create(_ADsPath,
szDomainName,
_ComputerName,
pqssBuf->lpServiceName,
ADS_OBJECT_BOUND,
IID_IDispatch,
_Credentials,
(void **)ppDispatch);
BAIL_IF_ERROR(hr);
_dwServiceObjectCurrentEntry++;
if(_dwServiceObjectCurrentEntry == _dwServiceObjectReturned){
_fServiceNoMore = TRUE;
}
cleanup:
if(FAILED(hr)){
#if DBG
EnumCompDebugOut((DEB_TRACE,
"hr Failed with value: %ld \n", hr ));
#endif
hr = S_FALSE;
}
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTComputerEnum::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: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTComputerEnum::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
CWinNTComputerEnum::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,
_ComputerName,
WINNT_COMPUTER_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_COMPUTER_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
CWinNTComputerEnum::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,
_ComputerName,
WINNT_COMPUTER_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_COMPUTER_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;
//
// We missed a member so return E_FAIL if that was the error
// as we would still like to get at the other groups
//
if (hr != E_FAIL) {
hr = S_FALSE;
}
goto cleanup;
}
HRESULT
CWinNTComputerEnum::EnumGroupObjects(
DWORD ObjectType,
ULONG cElements,
VARIANT FAR * pvar,
ULONG FAR * pcElementFetched
)
{
HRESULT hr = S_OK ;
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;
}
RRETURN(hr);
}
extern ULONG GroupTypeArray[];
HRESULT
CWinNTComputerEnum::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;
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
CWinNTComputerEnum::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
CWinNTComputerEnum::EnumLocalGroups(
ULONG cElements,
VARIANT FAR* pvar,
ULONG FAR* pcElementFetched
)
{
HRESULT hr = S_OK ;
IDispatch *pDispatch = NULL;
DWORD i = 0;
while (i < cElements) {
//
// Need to set it here in case we are getting multiple elements
//
hr = E_FAIL;
//
// We use a while loop in case a get of one of the objects fails
// because it has a long pathname or otherwise
//
while (hr == E_FAIL) {
hr = GetLocalGroupObject(&pDispatch);
}
if (hr == S_FALSE) {
break;
}
VariantInit(&pvar[i]);
pvar[i].vt = VT_DISPATCH;
pvar[i].pdispVal = pDispatch;
(*pcElementFetched)++;
i++;
}
return(hr);
}