Network enumeration

As many plain Win32-API tasks, the network enumeration can be a difficult one. To keep me from implementing such a task over and over again, I wrote a CNetwork class.
The class CNetwork is mainly for enumerating the network and performing different tasks on the resources hit by the enumeration, so the central method of the class is

BOOL  Enumerate(DWORD dwFlags = CNetwork::SEARCHDEFAULT);

This method starts the enumeration of the network resources. The possible values for the <dwFlags> parameter are defined inside CNetwork as follows

#define _BIT(n)  (1<<n)
enum {
	GLOBALNET = _BIT(0),	// search the entire network
	CONNECTED = _BIT(1),	// search only currently connected resources
	REMEMBERED = _BIT(2),	// search only "persistent" connections

	TYPE_ANY = _BIT(3),		// search all types of resources
	TYPE_DISK = _BIT(4),	// search all disk resources
	TYPE_PRINT = _BIT(5),	// search all print resources

#undef _BIT

Every time the Enumerate() method hits a network-resource, it calls an overridable method called

virtual BOOL OnHitResource( NETRESOURCE & ) = 0;

Note that this is a pure virtual in the base class. You have to derive your own class from CNetwork and to override this method.
The function has to return TRUE, if you want to continue enumeration; FALSE to break off.
For every hit you get a reference to a NETRESOURCE object. Not to make it necessary for you to know of this type, there are many helper functions to deal with a NETRESOURCE:

// NOTE: Only one of these functions can return TRUE with the same NETRESOURCE object.
BOOL	IsServer( NETRESOURCE &) const;		// means "Computer", thus clients too
BOOL	IsDomain( NETRESOURCE &) const;
BOOL	IsShare( NETRESOURCE & ) const;
BOOL	IsGeneric( NETRESOURCE &) const;

// The following functions will simplify the NETRESOURCE access:
LPCTSTR	GetLocalName( NETRESOURCE & ) const;
LPCTSTR	GetRemoteName( NETRESOURCE & ) const;
LPCTSTR	GetComment( NETRESOURCE & ) const;
LPCTSTR	GetProvider( NETRESOURCE & ) const;
BOOL	IsConnectable( NETRESOURCE &) const;

You can perform some actions with such a NETRESOURCE

// Add a connection to the network.
// If you want to connect to a local drive ("H:" for instance),
// you have to fill out the "lpLocalName" of <NetRC> (if this
// member is NULL or empty).
// <dwFlags> can be set to "CONNECT_UPDATE_PROFILE" to make the
// connection persistent (i.e. reconnect when the user logs on).
// if <UserName> is NULL, it defaults to the current user.
// if <Password> is NULL, it defaults to the <Username>'s password.
// See WNetAddConnection2() in the online-help for more details
BOOL	AddConnection(
			DWORD Flags = 0,		// can be CONNECT_UPDATE_PROFILE for a persistent connection
			LPTSTR UserName = 0,	// defaults to current user
			LPTSTR Password = 0		// defaults to password of current user

// Cancel a network-connection. Returns TRUE on success; FALSE on
// failure. The NetError() method (see below) will be called on
// failure. For further information see WNetCancelConnection2()
// in the online-help.
BOOL	CancelConnection(
			LPTSTR szName,			// local or remote name of the resource
			BOOL ForceDisconnect = FALSE	// force a disconnect even if the resource is in use
BOOL	CancelConnection(
			BOOL ForceDisconnect = FALSE

As you can see, not many of the WNet*() functions are encapsulated by this class. Remember: this is mainly a network-enumerator! Most of the WNet*() functions are simple enough, so that they don't need a wrapping by this class ...

There is one more virtual method that you might want to override:

virtual BOOL NetError( DWORD dwErrNo, LPCTSTR pszFunction );

Normally, this function will be called from inside the enumeration or one of the operations (Add-/CancelConnection()). The NetError() method will return FALSE, if the occured error is a serious one; otherwise it can return TRUE to indicate a minor error. The default implementation of this method retrieves a human readable error message and stores it in the member

LPTSTR m_pszError;

One can retrieve its content via a call to

LPCTSTR  GetErrorString() const ;

So if you override NetError(), you should call the base-class' implementation too, if you encounter a serious error. The original NetError() returns always FALSE.

Often it is wanted to have a handler for the network-enumeration in another class. For this reason I've derived a template class from CNetwork that does the requiered work. This class is called CNetSearch.
You can use this class as follows:
In the class, where you want to handle the resource hits, insert a member of type CNetSearch<>. For instance:

class CSampleClass {
	// ...
	CNetSearch<CSampleClass>	m_NetWalker;

	BOOL	OnNetResourceHit(NETRESOURCE &);	// handler function for netresource hits
	// ...

In the implementation file of the sample class you have to Create() the CNetSearch<> object:

CSampleClass :: CSampleClass() {
	// ...
	m_NetWalker.Create(this, OnNetResourceHit);
	// ...

BOOL CSampleClass :: OnNetResourceHit(NETRESOURCE & NetRC) {
	// This sample handler lists all known computer names in the output window
	// of the debugger.
	if(m_NetWalker. IsServer(NetRC) ) {
		CString str = m_NetWalker.GetRemoteName(NetRC);
		register int i = 0;
		for( ; str[i] == '\\' ; ++i );
		if( i )
			str = str.Mid(i);
		TRACE1("found computer \"%s\"\n", LPCTSTR(str));
	return TRUE;	// continue enumeration

void CSampleClass :: SomeOperation() {
	// ...
	m_NetWalker.Enumerate();	// start the enumeration. This will (hopefully) lead to subsequent calls
								// to OnNetResourceHit() above
	// ...

Note that CNetSearch overrides the NetError() method. It filters the errors "ERROR_BAD_NETPATH" (the resource contains more resources, but is not accessible at this time) and "ERROR_NO_NETWORK" (there is no network present) as minor errors. Other errors are passed to the base implementation of that method.

You have to turn on exception handling, if you want to use these classes. In VC++ exception handling is on by default.

CNetwork consists of three files:
Download Source 5KB
Download Sample Project 17KB


  • dosn't work in win98 workgroup

    Posted by Legacy on 11/18/2003 12:00am

    Originally posted by: Ali Mostafa

    I compiled the project in VC6 and tested it on win98se but nothing happend. the program freezes.

  • !!!!

    Posted by Legacy on 05/03/2003 12:00am

    Originally posted by: Alex

    Thanks! Works fine.
    You save me a time!

  • Thanks!

    Posted by Legacy on 01/11/2002 12:00am

    Originally posted by: Santiago C.

    once added network.cpp works fine, thanks!

  • You need to include Network.cpp

    Posted by Legacy on 03/10/1999 12:00am

    Originally posted by: Robert Hamilton

    When I compiled the demo project, it had some linking errors. In the end, I had to insert network.cpp into the project to get it to compile. Maybe it's my Version of Visual C++ or something (5.0)

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 17, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Another day, another end-of-support deadline. You've heard enough about the hazards of not migrating to Windows Server 2008 or 2012. What you may not know is that there's plenty in it for you and your business, like increased automation and performance, time-saving technical features, and a lower total cost of ownership. Check out this upcoming eSeminar and join Rich Holmes, Pomeroy's practice director of virtualization, as he discusses the …

  • This ESG study by Mark Peters evaluated a common industry-standard disk VTl deduplication system (with 15:1 reduction ratio) versus a tape library with LTO-5, drives with full nightly backups, over a five-year period.  The scenarios included replicated systems and offsite tape vaults.  In all circumstances, the TCO for VTL with deduplication ranged from about 2 to 4 times more expensive than the LTO-5 tape library TCO. The paper shares recent ESG research and lots more. 

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds