Click here to Skip to main content
15,900,254 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I'm trying to get list of users of local group using C++. So far so good. But can I get the same for domain user groups? The following works well for groupName parameter set to "Administrators" but not for "DOMAIN\\Domain Admin".

There's a sentence in doc: "The NetLocalGroupGetMembers function retrieves a list of the members of a particular local group in the security database, which is the security accounts manager (SAM) database or, in the case of domain controllers, the Active Directory. Local group members can be users or global groups.", but I admit I do not understand it yet:)

#include <Lm.h>

#pragma comment (lib,"Netapi32.lib")

void WalkGroup(LPCTSTR computerName,LPCTSTR groupName)
{
	NET_API_STATUS stat;
	LOCALGROUP_MEMBERS_INFO_2 *buff;
	DWORD entriesread=0;
	DWORD totalentries=0;
	DWORD resume=0;
	do
	{
		stat= NetLocalGroupGetMembers(computerName,groupName,2,(LPBYTE *)&buff,MAX_PREFERRED_LENGTH,&entriesread,&totalentries,&resume);
		switch(stat)
		{
		case ERROR_MORE_DATA:
		case ERROR_SUCCESS:
			{
				for(int i=0;i<entriesread;i++)
				{
					switch(buff[i].lgrmi2_sidusage)
					{
					case SidTypeUser:
						KINFO(TEXT("User: %s\r\n"),buff[i].lgrmi2_domainandname);
						break;
					case SidTypeGroup:
						KINFO(TEXT("Group: %s\r\n"),buff[i].lgrmi2_domainandname);
						//doesn't work on domain groups and well known groups, local groups cannot be nested
						//nice try, but not working
						WalkGroup1(computerName,buff[i].lgrmi2_domainandname);
						break;
					case SidTypeWellKnownGroup:
						KINFO(TEXT("WellKnownGroup: %s\r\n"),buff[i].lgrmi2_domainandname);
						break;
					case SidTypeDeletedAccount:
						KINFO(TEXT("Deleted: %s\r\n"),buff[i].lgrmi2_domainandname);
						break;
					case SidTypeUnknown:
						KINFO(TEXT("Unknown: %s\r\n"),buff[i].lgrmi2_domainandname);
						break;
					}
				}
			}
			break;
		}
	}while(stat==ERROR_MORE_DATA);
}
Posted

It is probably a access rights issue.
Try running the program after logging in as a domain administrator.
 
Share this answer
 
Comments
jan.mach71 4-May-12 9:24am    
This did not help. Must be something with the name of a group or I'm supposed to call different function. I have solved it using ActiveDs library (where I have to be logged on as domain user to list group members). I can post code here if anybody is interested but I'd like to understand this procedural interface as well.
The following seems to work OK supposing I'm logged on as domain user (or that I inpersonalize one). I'm still interested if it is possible to get the same using NetLocalGroupGetMembers or something else from LM.h

#include <string>
#include <iads.h>
#include <adshlp.h>

#pragma comment (lib,"Activeds.lib")
#pragma comment (lib,"ADSIid.lib")

void WalkGroup(int level,LPCTSTR objectName);

HRESULT EnumMembers(int level,IADsMembers *pMembers)
{
    IUnknown *pUnk;
    HRESULT hr;
    hr = pMembers->get__NewEnum(&pUnk);
    if(FAILED(hr))
	{
		KINFO(TEXT("Cannot get enum object\r\n"));
		goto Cleanup;
	}

    IEnumVARIANT *pEnum;
    hr = pUnk->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
    if(FAILED(hr))
	{
		KINFO(TEXT("Cannot get enum variant\r\n"));
		goto Cleanup;
	}
    // Now Enumerate
    VARIANT var;
    IADs *pADs;
    ULONG lFetch;
    IDispatch *pDisp;

    VariantInit(&var);
    hr = pEnum->Next(1, &var, &lFetch);
    if(FAILED(hr))
	{
		KINFO(TEXT("Cannot get next member\r\n"));
		goto Cleanup;
	}
	while(hr == S_OK)
	{
		if (lFetch == 1)
		{
			BSTR bstrName=NULL;
			BSTR bstrClass=NULL;
			BSTR bstrPath=NULL;
			pDisp = V_DISPATCH(&var);
			pDisp->QueryInterface(IID_IADs, (void**)&pADs);
			pADs->get_Name(&bstrName);
			pADs->get_Class(&bstrClass);
			pADs->get_ADsPath(&bstrPath);
			KINFO(TEXT("%d %s %s %s\n"),level,bstrClass, bstrName, bstrPath);
			if(!_tcscmp(bstrClass,TEXT("Group")))
			{
				WalkGroup(level+1,bstrPath);
			}
			SysFreeString(bstrName);
			SysFreeString(bstrClass);
			SysFreeString(bstrPath);
		}
		VariantClear(&var);
		pDisp=NULL;
		hr = pEnum->Next(1, &var, &lFetch);
		if(FAILED(hr))
		{
			KINFO(TEXT("Cannot get next member\r\n"));
			goto Cleanup;
		}
	};

Cleanup:
    if(pADs) pADs->Release();
    if(pDisp) pDisp->Release();
    if(pUnk) pUnk->Release();
    if(pEnum) pEnum->Release();
    VariantClear(&var);
    return hr;
}


void WalkGroup(int level,LPCTSTR objectName)
{
	HRESULT hr;
	IADsGroup *pGroup=NULL;
	IADsMembers *pMembers=NULL;
	hr = ADsGetObject(objectName,IID_IADsGroup,(void**)&pGroup);
	if(FAILED(hr))
	{
		KINFO(TEXT("Cannot get object %s. Priviledges? Domain?\r\n"),objectName);
		goto Cleanup;
	}
	hr = pGroup->Members(&pMembers);
		if(FAILED(hr))
	{
		KINFO(TEXT("Cannot get members\r\n"));
		goto Cleanup;
	}
	EnumMembers(level,pMembers);
Cleanup:
	if(pMembers)
		pMembers->Release();
	if(pGroup)
		pGroup->Release();
}

int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
	CoInitialize(NULL);

	TCHAR computerName[MAX_COMPUTERNAME_LENGTH + 1];
	TCHAR objectName[MAX_COMPUTERNAME_LENGTH + 256];
	DWORD computerNameSize=MAX_COMPUTERNAME_LENGTH + 1;
	GetComputerName(computerName,&computerNameSize);

	swprintf_s( objectName,MAX_COMPUTERNAME_LENGTH + 256,_T("WinNT://%s/Administrators"),computerName);
	
	WalkGroup(0,objectName);

	CoUninitialize();
	return (0);
}


</adshlp.h></iads.h></string>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900