Beruflich Dokumente
Kultur Dokumente
Your Network’
s Who’
s Who:
Patrick Long
patl@themandelbrotset.com
Introduction
The first component, a local ActiveX DLL, gives you read-only access to
local network information such as the logged-on user’ s name and the
logon server (see Figure 1). This component provides limited functionality
on Win9x machines, due to the operating system’ s lack of Unicode support
and consequently lack of support for this API. The second component, an
ActiveX EXE, returns a collection of users with the ability to add and delete
them. Although this component runs only on NT machines, you can call it
remotely using the Distributed Component Object Model (DCOM) from a
Win9x machine. Later I’ ll cover FormatMessage, a function which allows
you to get the error descriptions for the errors returned by the API.
Who’ s Currently Logged On?
Page 1 of 1
Copyright © 1999, The Mandelbrot Set (International) Limited
The UDT, like all the UDTs returned by this API, contains the memory
addresses (pointers) of the Unicode strings instead of the actual strings.
You can convert these pointers to VB strings using the PointerToStringW
function:
If lpStringW Then
lLen = lstrlenW(lpStringW) * 2
If lLen Then
ReDim yBuffer _
(0 To (lLen - 1)) As Byte
CopyMem yBuffer(0), ByVal _
lpStri ngW, lLen
PointerToStringW = yBuffer
End If
End If
End Function
After receiving data from the function, you need to use the
NetApiBufferFree function to clear up the memory allocated to it. You need
to clear up memory, using NetApiBufferFree, after calling any of this API’
s
functions that return data.
You can handle and/or return other non-zero codes to the client. The
message table file netmsg.dll, found in %systemroot%system32, holds
the text for these errors. Use this file, along with the return codes with the
Win32 API function FormatMessage, to return the respective text (see
Listing 2). The FormatMessage function needs a message table resource
to search. The function can either have the table passed into it; search the
system’ s own table; or, as in our code, accept the handle of an already
loaded module.
Page 2 of 2
Copyright © 1999, The Mandelbrot Set (International) Limited
Visual Studio now ships with a small app that acts as a user interface to
the FormatMessage function. It’ s called Error Lookup and it can be found
under Microsoft Visual Studio 6 Tools in your Start menu. It’s the ideal
companion for any API programmer, because it provides you the
description for any API error code.
For the sake of space, I have hard-coded the code in this article to use the
netmsg.dll module. You may want to create a COM wrapper around
FormatMessage that all your apps could call, loading whatever module
they liked.
The Network API function to get all the users is called NetUserEnum. As its
name suggests, this function enumerates through all user accounts on a
computer. The function NetServerEnum works in the same way for
machines in a domain.
The function’s first argument is the machine to run the function on. This
means that although the code is executing on your machine, you can tell
the API to run against another machine. The argument expects a pointer
to a Unicode string. See the sidebar “Tackle Unicode in Byte-Sized Pieces”
for information on how to deal with the Unicode strings.
To get a domain listing of all users on a domain, you must run the
function against a Primary or Backup domain controller. These server
types hold the domain’ s user database. To get a domain controller name,
call the NetGetDCName. The Machine name to run on argument is a
Unicode string. If a Null pointer such as vbNullChar, ByVal 0&, is passed
for the “machine to run on”argument, the function is run on the local
Page 3 of 3
Copyright © 1999, The Mandelbrot Set (International) Limited
machine. This rule is the same for all Network API functions with this
parameter.
In this example of the code needed to call a NetAPI function, note the
appended vbNullChar and the passing of the first element:
Page 4 of 4
Copyright © 1999, The Mandelbrot Set (International) Limited
Getting the user’ s groups requires a bit more work. First, you need to call
either NetUserGetGroups or NetUserGetLocalGroups. The code needed to
call these functions is similar to NetUserEnum except you don’ t need to
loop around getting the data; it’ s all returned at the same time.
Unfortunately neither of these functions returns the group’ s description.
The functions to return this information are NetGroupGetInfo and
NetLocalGroupGetInfo. Both are called with level 1 information. The code
online (see the Download Free Code box for details) shows the full
implementation.
This article has only scratched the surface of an API with which, if you
were crazy enough, you could replace NT’ s User Manager with your own.
The code and techniques shown in these components is an ideal starting
place from which to explore the rest of the Network API.
Figure 1
Get Local Network Information. The local DLL returns this information on an NT workstation.
Listing 1
VB4/32, VB5, VB6
Get the Local User Information. The RefreshLocalUser Sub is called on Class_Initialize. If you’re
running on a non-NT Machine, just get the username.
' In Declarations
Public oOSInfo As OpSysInfo
Private oPiErrLookUp As ErrLookup
Page 5 of 5
Copyright © 1999, The Mandelbrot Set (International) Limited
If oOSInfo.IsWinNT Then
lAPIReturnCode = NetWkstaUserGetInfo(0, _
InformationLevel, lpBuffer)
If lpBuffer Then
Call NetApiBufferFree(lpBuffer)
End If
Else
On Error GoTo 0
Err.Raise lAPIReturnCode, _
TypeName(Me) & PROC_NAME, _
oPiErrLookUp.LookUp(CStr(lAPIReturnCode))
End If
Else
Dim sBuffer As String
Dim lSize As Long
lSize = 16
sBuffer = String$(lSize, 0)
End If
Listing 2
VB4/32, VB5, VB6
Call FormatMessage. FormatMessage accepts the handle of a loaded module as an extra place to
search for the message.
Page 6 of 6
Copyright © 1999, The Mandelbrot Set (International) Limited
lErrorID = Val(ErrorID)
sErrMessage = String$(256, 0)
lRC = FormatMessage( _
FORMAT_MESSAGE_FROM_SYSTEM Or _
FORMAT_MESSAGE_IGNORE_INSE RTS, _
0&, lErrorID, 0&, sErrMessage, _
Len(sErrMessage), ByVal 0&)
If lRC = 0 Then
hModule = _
LoadLibraryEx(asPiModules(iModuleIndex), _
ByVal 0&, LOAD_LIBRARY_AS_DATAFILE)
If hModule Then
'Module loaded so let’s have a look
sErrMessage = String$(256, 0)
lRC = FormatMessage( _
FORMAT_MESSAGE_FROM_SYSTEM Or _
FORMAT_MESSAGE_IGNORE_INSERTS Or _
FORMAT_MESSAGE_FROM_HMODULE, _
ByVal hModule, lErrorID, 0&, _
sErrMessage, Len(sErrMessage), _
ByVal 0&)
Call FreeLibrary(hModule)
End If
Next iModuleIndex
Page 7 of 7
Copyright © 1999, The Mandelbrot Set (International) Limited
End Function
Patrick Long is a Senior Developer with The Mandelbrot Set (International) Limited
(TMS).
Page 8 of 8