#include <windows.h>
#include <lm.h>
#include <stdio.h>
#pragma hdrstop



// 28jul97 felixk   fixed a nasty bug in do_NetQueryDisplayInformation
//                  (next_index was set even if read == 0: accvio)


void print_user( const wchar_t *name, DWORD flags )
{
	// NOTE: capital "S" in a printf format string means "Unicode",
	// if we are an ANSI program

	printf( "%-40.40S ", name ); // display Unicode user name
	if ( flags & UF_NORMAL_ACCOUNT )
		puts( "(domain user)" );
	else if ( flags & UF_TEMP_DUPLICATE_ACCOUNT )
		puts( "(local user)" );
	else if ( flags & UF_WORKSTATION_TRUST_ACCOUNT )
		puts( "(computer account)" );
	else if ( flags & UF_SERVER_TRUST_ACCOUNT )
		puts( "(PDC/BDC computer account)" );
	else if ( flags & UF_INTERDOMAIN_TRUST_ACCOUNT )
		puts( "(trusted domain account)" );
	else
		puts( "(funny account type)" );
}



void do_NetUserEnum( const wchar_t *server )
{
	USER_INFO_1 *buf, *cur;
	DWORD read, totalremaining, resumeh, rc, i;

	resumeh = 0;
	do
	{
		buf = NULL;
		rc = NetUserEnum( server, 1, 0, (BYTE **) &buf, 1024, &read, &totalremaining, &resumeh );
		if ( rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS )
			break;

		printf( "\ngot %lu entries out of %lu\n", read, totalremaining );
		for ( i = 0, cur = buf; i < read; ++ i, ++ cur )
			print_user( cur->usri1_name, cur->usri1_flags );

		if ( buf != NULL )
			NetApiBufferFree( buf );

	} while ( rc == ERROR_MORE_DATA );

	if ( rc != ERROR_SUCCESS )
		printf( "NUE() returned %lu\n", rc );
}



void do_NetQueryDisplayInformation( const wchar_t *server, int level )
{
	void *buf;
	NET_DISPLAY_USER *ndu;
	NET_DISPLAY_MACHINE *ndm;
	NET_DISPLAY_GROUP *ndg;
	DWORD read, next_index, rc, i;

	next_index = 0;
	do
	{
		buf = NULL;
		rc = NetQueryDisplayInformation( server, level, next_index, 10, 1024, &read, &buf );
		if ( rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS )
			break;

		printf( "\ngot %lu entries\n", read );

		switch ( level )
		{
			case 1: // users
				for ( i = 0, ndu = (NET_DISPLAY_USER *) buf; i < read; ++ i, ++ ndu )
					print_user( ndu->usri1_name, ndu->usri1_flags );
				// take the last element's next_index
				if ( read > 0 )
					next_index = ((NET_DISPLAY_USER *)buf)[read - 1].usri1_next_index;
				break;
			case 2: // machines
				for ( i = 0, ndm = (NET_DISPLAY_MACHINE *) buf; i < read; ++ i, ++ ndm )
					print_user( ndm->usri2_name, ndm->usri2_flags );
				// take the last element's next_index
				if ( read > 0 )
					next_index = ((NET_DISPLAY_MACHINE *)buf)[read - 1].usri2_next_index;
				break;
			case 3: // groups
				for ( i = 0, ndg = (NET_DISPLAY_GROUP *) buf; i < read; ++ i, ++ ndg )
					printf( "%-40.40S (group)\n", ndg->grpi3_name );
				// take the last element's next_index
				if ( read > 0 )
					next_index = ((NET_DISPLAY_GROUP *)buf)[read - 1].grpi3_next_index;
				break;
		}

		if ( buf != NULL )
			NetApiBufferFree( buf );

	} while ( rc == ERROR_MORE_DATA );

	if ( rc != ERROR_SUCCESS )
		printf( "NQDI() returned %lu\n", rc );
}



int main( void )
{
	// set this to \\your_domain_controller
	wchar_t *servername = L"\\\\BABYA";

	// get all accounts
	puts( "\n*** Enumerating accounts: NetUserEnum()" );
	do_NetUserEnum( servername );

	// get users
	puts( "\n*** Enumerating users: NetQueryDisplayInformation()" );
	do_NetQueryDisplayInformation( servername, 1 );

	// get machine accounts
	puts( "\n*** Enumerating machine accounts: NetQueryDisplayInformation()" );
	do_NetQueryDisplayInformation( servername, 2 );

	// get groups
	puts( "\n*** Enumerating groups: NetQueryDisplayInformation()" );
	do_NetQueryDisplayInformation( servername, 3 );

	return 0;
}

