Encapsulating Standard Network API Functions
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 header Michael 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 64000 class 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 file Michael 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,_UNICODE If the strings don't look exactly like this, don't panic - all you need to do is change _MBCS to _UNICODE Under Project/Settings/Link/Output add wWinMainCRTStartup to the entry point symbol box If 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 call Returns: 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 call Returns: 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; }

Comments
There are no comments yet. Be the first to comment!