Environment: NT/W2K
Getting to grips with the standard 32-bit network API calls is a pain to begin with, which is why I wrote this small class to encapsulate two of the network functions I most use: NetSessionEnum() and NetUserGetInfo(). Anyone picking up this code can easily extend its functionality to take in other calls such as NetShareAdd() or NetUserAdd() etc. I will probably do the same when I have cause to use them.
In my development environment, the source files sit in a folder dedicated to various utility classes and are included in the Visual C++ workspace for each project for which I require them via Project->Add To Project->Files and then including the class header where necessary.
Source Code
The comments in the source code are (I hope) self-explanatory.
Header File
/*
NETUTIL.H
Net utilities class headerMichael Pritchard Mar 2001
*/
// 32-bit net API headers
// include them here so the whole application
// can see them
#include <lmcons.h>
#include <lmerr.h>
#include <lmapibuf.h>
#include <lmaccess.h>
#include <lmshare.h>// just a big number to allow a large enough
// buffer for the return from NetSessionEnum()
// because I’m too lazy to call the function twice
#define bigbuff 64000class CNetutil {
public:
// prototypes of member functions
BYTE* get_sessions(CString, DWORD&, DWORD&, DWORD&);
PUSER_INFO_10 get_name(CString, CString, DWORD&);protected:
private:
};
Implementation File
/*
NETUTIL.CPP
Net utilities class source fileMichael Pritchard Mar 2001
This class encapsulates 32-bit network API calls.
Windows NT/W2K only.
Project must be linked with NETAPI32.LIB.
Build with precompiled header use set to automatic.
This class requires the application to be built in unicode. If you
don’t do it this way, you must covert strings to unicode before
applying them to the net API functions and convert the results
back. To build an MFC application in Unicode, you first need to
make sure you have installed Visual Studio with the relevant
Unicode libraries. If you haven’t, you’ll need to re-install. Once
you have done this, create your project via the App Wizard as normal
and then change the project settings as follows:Under Project/Settings/C++/General change the preprocessor directive from
(Debug)
WIN32,_DEBUG,_WINDOWS,_MBCS
to
WIN32,_DEBUG,_WINDOWS,_UNICODE
or (Release)
WIN32,NDEBUG,_WINDOWS,_MBCS
to
WIN32,NDEBUG,_WINDOWS,_UNICODEIf the strings don’t look exactly like this, don’t panic – all you
need to do is change _MBCS to _UNICODEUnder Project/Settings/Link/Output add
wWinMainCRTStartup
to the entry point symbol boxIf you are converting an existing project to Unicode, you will
probably need to change some functions over to the Unicode
versions. This is straight forward and there is plenty of
information in MSDN.All string literals need to be encapsulated in the _T() macro.
*/
#include “afx.h”
#include “NetUtil.h” // don’t forget this, either/*
member function: get_sessions()Uses API: NetSessionEnum()
Arguments: server – name of server on which user database is held
(normally PDC), no preceeding backslashes required
dwErrmsg – reference to DWORD to contain return code from API call
dwRecords – reference to DWORD to contain no. records returned
by API call
dwSessions – reference to DWORD to contain total sessions returned
by API callReturns: BYTE pointer to buffer returned by API call
Sample call to get_sessions():
void CMyClass::MyFunction()
{
CNetutil net;
CString sServer = _T(“myPDC”);DWORD dwError, dwRecords, dwSessions;
BYTE* buffer;
PSESSION_INFO_10 pSession;buffer = net.get_sessions(sServer, dwError, dwRecords, dwSessions);
if( dwError != 0)
{
CString sError;
sError.Format(_T(“get_sessions() failed – error %ld”), dwError);
AfxMessageBox(sError);
return;
}// cast returned buffer to structure
pSession = (PSESSION_INFO_10 )buffer;// move through the BYTE buffer, advancing the pointer
// by length PSESSION_INFO_10 each time
for (DWORD dwCount = 0; dwCount++ < dwRecords; pSession++) { // do something with each instance of the PSESSION_INFO_10 structure
// e.g. CString sUserid = pSession->sesi10_username;
}NetApiBufferFree(buffer);
}Notes: Before processing returned BYTE pointer, value of dwErrmsg MUST be checked.
A return of 0 indicates net API call successful, anything else must be
noted and checked against the error code tables*/
BYTE* CNetutil::get_sessions(CString server,
DWORD& dwErrmsg,
DWORD& dwRecords,
DWORD& dwSessions)
{
// buffer to take return from net API call
BYTE *pBuf;// Build full UNC name for PDC
CString sSer;
sSer = _T(“\\”);
sSer += server;// call net function level 10 (general access)
dwErrmsg = NetSessionEnum (sSer.GetBuffer(0),
NULL,
NULL,
10,
&pBuf,
bigbuff, // see header
&dwRecords,
&dwSessions,
NULL);// if return sucessful, set dwErrmsg to zero
// (confines net function error checking to this class)
if (dwErrmsg == NERR_Success || dwErrmsg == ERROR_MORE_DATA)
dwErrmsg = 0;return pBuf;
}
/*
member function: get_name()Uses API: NetUserGetInfo()
Arguments: userid – individual user ID, or one of buffer returned
by NetSessionEnum()
server – name of server on which user database is held
(normally PDC) no preceeding backslashes required
dwErrmsg – pointer to int to contain return code from API callReturns: pointer to PUSER_INFO_10 structure
Sample call to get_name():
void CMyClass::MyFunction()
{
DWORD dwError;
CNetutil net;
CString sServer = _T(“MyPDC”);
CString sUserid = _T(“AnyValidUserid”);PUSER_INFO_10 pUser;
pUser = net.get_name(sUserid, sServer, dwError);if(dwError == 0)
{
// do something with the PUSER_INFO_10 structure
// e.g. CString sName = pUser->usri10_full_name;
}
else
{
CString sError;
sError.Format(_T(“%ld”), dwError);
AfxMessageBox(sError);
}
}Notes: Before processing returned PUSER_INFO_10 pointer, value of dwErrmsg
MUST be checked. A return of 0 indicates net API call successful,
anything else must be noted and checked against the error code tables*/
PUSER_INFO_10 CNetutil::get_name(CString sUserid,
CString server,
DWORD& dwErrmsg)
{// buffer to take return from net API call
BYTE *pBuf;
PUSER_INFO_10 pUser;// Build full UNC name for PDC
CString sSer;
sSer = _T(“\\”);
sSer += server;// call net function level 10 (general access)
dwErrmsg = NetUserGetInfo( sSer,
sUserid,
10,
&pBuf);// if return successful, set dwErrmsg to zero
// (confines net function error checking to this class)
if (dwErrmsg == NERR_Success || dwErrmsg == ERROR_MORE_DATA)
dwErrmsg = 0;// cast returned BYTE buffer
pUser = (PUSER_INFO_10 ) pBuf;// free the BYTE buffer
NetApiBufferFree(pBuf);return pUser;
}