Visual Basic Network Services
NetWkstaUserEnum: Workstation Logon Information
     
Posted:   Monday June 25, 2001
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows 2000
OS restrictions:   Windows NT3.1, Windows NT4, Windows 2000, Windows XP
Author:   VBnet - Randy Birch
     

Related:  

NetServerEnum: Obtain Domain/Workgroup Servers and Machines
NetServerEnum: Get Version Info for Domain/Workgroup Servers and Machines

NetWkstaGetInfo: Workstation Configuration Information
 
NetWkstaGetInfo: Workstation Configuration and Current User 
NetWkstaGetInfo: Workstation Configuration and Logon Information 

     
 Prerequisites
For this demo, one of the operating systems listed under OS Restrictions above.

NetWkstaUserEnum lists information about all users currently logged on to the workstation, including service and batch logons, as well as interactive user logons. No flag is provided in the returned WKSTA_USER_INFO_0 or WKSTA_USER_INFO_1 data that specifies what a particular entry type is. 

As the illustration shows, NetWkstaUserEnum lists currently logged users to the specified workstation showing the username, logon domain, logon server and, where applicable, additional domains (returned in a single string separated by spaces). On my machine, set up only as a workgroup (no logon domain internally), the call returns (quite correctly) my primary Win2000 development computer's name as both the logon server and domain as the illustration reflects. NetWkstaUserEnum requires NT or later, and is unsupported on Win9x. 

On Windows NT, only members of the Administrators local group can successfully execute NetWkstaUserEnum function both locally and on a remote server.

On Windows 2000 or later, on servers running Active Directory, access is allowed or denied based on the access-control list (ACL) for the securable object. By default, the ACL permits all authenticated users and members of the "Pre-Windows 2000 compatible access" group to view the information, which includes Everyone as a default members. This functionality enables anonymous access to the information if the system allows anonymous access. Calling NetWkstaUserEnum on a Windows 2000 member server or workstation not running Active Directory allows all authenticated users can view the information. Anonymous access is also permitted if the RestrictAnonymous policy setting allows anonymous access.

In addition, because entries for service, batch and user logons are all returned, the function may return entries for users who have since logged off a workstation. This can occur, for example, when a user calls a service that impersonates the user. In this instance, NetWkstaUserEnum returns an entry for the user until the service stops impersonating the user.

NetWkstaUserEnum is designed to list all users logged onto a specific machine. What is unclear from the MSDN documentation, and something I am not able to test, is whether NetWkstaUserEnum would be the correct API to use to obtain a listing of all local and remote users who have logged on to the domain by specifying the PDC as servername, or whether to obtain this information would require the developer to first enumerate the network for computers, and then use the machines returned in individual calls to NetWkstaUserEnum. I'd like to know so as to update this page with definitive information.

 BAS Module Code
None.

 Form Code
To a form add a command button (Command1), list box (List1), and two labels (Label1, Label2). A third set of labels in a control array can be used for the list item captions. Add the following to the form:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const NERR_SUCCESS As Long = 0&
Private Const MAX_PREFERRED_LENGTH As Long = -1
Private Const ERROR_MORE_DATA As Long = 234&
Private Const LB_SETTABSTOPS As Long = &H192

'for use on Win NT/2000 only
Private Type WKSTA_USER_INFO_0
  wkui0_username  As Long
End Type

Private Type WKSTA_USER_INFO_1
  wkui1_username As Long
  wkui1_logon_domain As Long
  wkui1_oth_domains As Long
  wkui1_logon_server As Long
End Type

Private Declare Function NetWkstaUserEnum Lib "netapi32" _
  (ByVal servername As Long, _
   ByVal level As Long, _
   bufptr As Long, _
   ByVal prefmaxlen As Long, _
   entriesread As Long, _
   totalentries As Long, _
   resume_handle As Long) As Long
        
Private Declare Function NetApiBufferFree Lib "netapi32" _
   (ByVal Buffer As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" _
   Alias "RtlMoveMemory" _
  (pTo As Any, uFrom As Any, _
   ByVal lSize As Long)
   
Private Declare Function lstrlenW Lib "kernel32" _
  (ByVal lpString As Long) As Long

Private Declare Function SendMessage Lib "user32" _
   Alias "SendMessageA" _
  (ByVal hwnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   lParam As Any) As Long
   

Private Sub Form_Load()

   ReDim TabArray(0 To 3) As Long
   
   TabArray(0) = 58
   TabArray(1) = 140
   TabArray(2) = 171
   TabArray(3) = 217
   
  'Clear existing tabs and set list tabstops
   Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 0&, ByVal 0&)
   Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 4&, TabArray(0))
   List1.Refresh

   Command1.Caption = "NetWkstaUserEnum 1"
   
   Label1.Caption = "call success (0) or error :"
   Label2.Caption = ""
      
End Sub


Private Sub Command1_Click()

   Dim bufptr          As Long
   Dim dwServer        As Long
   Dim dwEntriesread   As Long
   Dim dwTotalentries  As Long
   Dim dwResumehandle  As Long
   Dim nStatus         As Long
   Dim nStructSize     As Long
   Dim cnt             As Long
   Dim bServer         As String
   Dim wui1            As WKSTA_USER_INFO_1
     
   bServer = "\\" & Environ$("COMPUTERNAME") & vbNullString
   dwServer = StrPtr(bServer)
   
   List1.Clear
   
  'begin do
   Do
   
     'call NetWkstaUserEnum function,
     'specifying level 1 data
      nStatus = NetWkstaUserEnum(dwServer, _
                                 1, _
                                 bufptr, _
                                 MAX_PREFERRED_LENGTH, _
                                 dwEntriesread, _
                                 dwTotalentries, _
                                 dwResumehandle)

      Label2.Caption = nStatus
   
     'Does the call succeed? Only members of the
     'Administrators local group can successfully
     'execute NetWkstaUserEnum locally and on
     'a remote server.
      If nStatus = NERR_SUCCESS Or _
         nStatus = ERROR_MORE_DATA Then
         
         If dwEntriesread > 0 Then
         
            nStructSize = LenB(wui1)
         
           'Loop through the entries
            For cnt = 0 To dwEntriesread - 1
            
              'cast data into a WKSTA_USER_INFO_1
              'type and add the data to a list
               CopyMemory wui1, ByVal bufptr + (nStructSize * cnt), nStructSize
   
               List1.AddItem GetPointerToByteStringW(wui1.wkui1_username) & vbTab & _
                             GetPointerToByteStringW(wui1.wkui1_logon_domain) & vbTab & _
                             GetPointerToByteStringW(wui1.wkui1_logon_server) & vbTab & _
                             GetPointerToByteStringW(wui1.wkui1_oth_domains)
                             
   
            Next
            
         Else
         
           'error: this will fire if the call
           'succeeded, but no data was returned,
           'such as when interrogating a Win9x machine.
            List1.AddItem "No data returned - possible Win9x machine  "
            
         End If
      
      Else  'error
         
         List1.AddItem "Call failed - error " & nStatus
      
      End If
   
  'continue to call NetWkstaUserEnum while
  'there are more entries.
   Loop While nStatus = ERROR_MORE_DATA
   
  'clean up
   Call NetApiBufferFree(bufptr)

End Sub


Private Function GetPointerToByteStringW(ByVal dwData As Long) As String
  
   Dim tmp() As Byte
   Dim tmplen As Long
   
   If dwData <> 0 Then
   
      tmplen = lstrlenW(dwData) * 2
      
      If tmplen <> 0 Then
      
         ReDim tmp(0 To (tmplen - 1)) As Byte
         CopyMemory tmp(0), ByVal dwData, tmplen
         GetPointerToByteStringW = tmp
         
     End If
     
   End If
    
End Function
 Comments

 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter