KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q316318: HOWTO: Use NetQueryDisplayInformation() in Visual Basic

Article: Q316318
Product(s): Microsoft Visual Basic for Windows
Version(s): 4.0
Operating System(s): 
Keyword(s): kbAPI kbSDKPlatform kbNetAPI kbDSupport kbGrpDSNet
Last Modified: 26-APR-2002

-------------------------------------------------------------------------------
The information in this article applies to:

- Microsoft Visual Basic Enterprise Edition, 32-bit, for Windows, version 4.0, used with:
   - the operating system: Microsoft Windows XP 
   - the operating system: Microsoft Windows 2000 
   - the operating system: Microsoft Windows NT 4.0 
- Microsoft Visual Basic Professional Edition, 32-bit, for Windows, version 4.0, used with:
   - the operating system: Microsoft Windows XP 
   - the operating system: Microsoft Windows 2000 
   - the operating system: Microsoft Windows NT 4.0 
-------------------------------------------------------------------------------

SUMMARY
=======

The sample code in this article demonstrates how to use the
NetQueryDisplayInformation function to enumerate users, machines, and groups
that are available in the specified domain in a 32-bit Visual Basic
application.

NOTE: The 32-bit version of the NetQueryDisplayInformation function is only
supported in Microsoft Windows NT or later. This function uses Unicode for its
string parameters.

MORE INFORMATION
================

When you call C functions in Visual Basic, you must redefine or declare the
relevant constants, structures(types), and functional prototypes. The sample
code in this article demonstrates how to use NetQueryDisplayInformation at the
following levels:

- Level 1 (NET_DISPLAY_USER) to enumerate all of the users in the specified
  domain.

- Level 2 (NET_DISPLAY_MACHINE) to enumerate all of the servers that are
  present in the specified domain.

- Level 3 (NET_DISPLAY_GROUP) to enumerate all of the groups that are present
  in the specified domain.

You must also declare the prototypes for NetQueryDisplayInformation and the
memory management functions, such as the NetApiBufferFree, the RtlMoveMemory,
and the lstrcpyW functions.

Use this Visual Basic code sample to create a Visual Basic form that includes the
following components:

- One list box named List1. List1 displays the list of users, servers, or
  groups.

- Two text boxes named txtPageSize and txtTotal. The txtPageSize text box
  displays the number of data per page, and the txtTotal text box displays the
  total number of items in the list.

- Two command buttons named btnRun and btnExit. The btnRun button executes the
  NetQueryDisplayInformation function, and the btnExit button closes the
  application.

- One frame named Frame1. In Frame1, you can select whether you want to display
  users, machines, or groups.

  '/* definitions and declarations
  Private Declare Function NetQueryDisplayInformation Lib "netapi32.dll" _
          (ByVal lpwServername As String, _
          ByVal dwLevel As Long, _
          ByVal dwIndex As Long, _
          ByVal dwReqEntries As Long, _
          ByVal dwMaxLength As Long, _
          pdwNumEntries As Long, _
          pBuffer As Any) As Long

  Private Declare Function NetApiBufferFree Lib "netapi32.dll" (BufPtr As Any) As Long

  Private Declare Sub CopyMem Lib "KERNEL32" Alias "RtlMoveMemory" ( _
          hpvDest As Any, ByVal hpvSource As Long, ByVal cbCopy As Long)

  Private Declare Function CopyString Lib "KERNEL32" Alias "lstrcpyW" ( _
          ByVal NewString As String, ByVal OldString As Long) As Long
          

  Private Const NET_USER = 1
  Private Const NET_MACHINE = 2
  Private Const NET_GROUP = 3
  Private Const ERROR_MORE_DATA = 234
  Private Const REQUESTED_ENTRIES = 5
  Private Const MAX_PREFERRED_LENGTH = &HFFFF

  Private Type NET_DISPLAY_USER
      usri1_name As Long      'lpwstr
      usri1_comment As Long   'lpwstr
      usri1_flags As Long
      usri1_full_name As Long 'lpwstr
      usri1_user_id As Long
      usri1_next_index As Long
  End Type

  Private Type NET_DISPLAY_GROUP
      grpi3_name As Long      'lpwstr
      grpi3_comment As Long   'lpwstr
      grpi3_group_id As Long
      grpi3_attributes As Long
      grpi3_next_index As Long
  End Type

  Private Type NET_DISPLAY_MACHINE
      usri2_name As Long      'lpwstr
      usri2_comment As Long   'lpwstr
      usri2_flags As Long
      usri2_user_id As Long
      usri2_next_index As Long
  End Type

  Private Sub btnExit_Click()
      Unload Me
  End Sub

  Private Sub btnRun_Click()
      '/* This code enumerates domain users.
      Dim pndu() As NET_DISPLAY_USER
      Dim pndm() As NET_DISPLAY_MACHINE
      Dim pndg() As NET_DISPLAY_GROUP
      Dim pszTemp As String, pszServer As String
      Dim pBuffer As Long
      Dim lLevel As Long
      Dim lResult As Long
      Dim lIndex As Long
      Dim lNumEntries As Long
      Dim lTotalEntries As Long
      
      List1.Clear
      
      ' Get the domain controller name. It can be a null string.
      pszTemp = Chr(0)
      pszTemp = InputBox("Enter domain controller name: (eg. \\domain-01)", "DC Name")
      If Len(pszTemp) = 0 Then
          pszServer = vbNullString
      Else
          pszServer = StrConv(pszTemp, vbUnicode)
      End If
      
      lIndex = 0
      lTotalEntries = 0
      lNumEntries = 0
      lResult = ERROR_MORE_DATA
      
      If (txtPageSize < 1) Then
          txtPageSize = REQUESTED_ENTRIES
      End If
      
      If (optUser = True) Then
          While lResult = ERROR_MORE_DATA
              List1.AddItem "---------------"
              lResult = NetQueryDisplayInformation(pszServer, NET_USER, lIndex, _
                          txtPageSize, MAX_PREFERRED_LENGTH, lNumEntries, pBuffer)
           
              If lResult = 0 Or lResult = ERROR_MORE_DATA Then
                  If lNumEntries > 0 Then
                      ReDim pndu(lNumEntries - 1)
                      '/* Copy information to VB friendly structure
                      CopyMem pndu(0), ByVal pBuffer, Len(pndu(0)) * lNumEntries
                      
                      For i = 0 To lNumEntries - 1
                          List1.AddItem PointerToString(pndu(i).usri1_name)
                      Next
                      
                      '/* Get index for next iteration
                      lIndex = pndu(i - 1).usri1_next_index
                  End If
              Else
                  MsgBox "Error: " & lResult
              End If
              
              If pBuffer Then
                  '/* Release NetAPI buffer
                  NetApiBufferFree (pBuffer)
              End If
              
              lTotalEntries = lNumEntries + lTotalEntries
          Wend
      ElseIf (optMachine = True) Then
          While lResult = ERROR_MORE_DATA
              List1.AddItem "---------------"
              lResult = NetQueryDisplayInformation(pszServer, NET_MACHINE, lIndex, _
                          txtPageSize, MAX_PREFERRED_LENGTH, lNumEntries, pBuffer)
           
              If lResult = 0 Or lResult = ERROR_MORE_DATA Then
                  If lNumEntries > 0 Then
                      ReDim pndm(lNumEntries - 1)
                      '/* Copy information to VB friendly structure
                      CopyMem pndm(0), ByVal pBuffer, Len(pndm(0)) * lNumEntries
                      
                      For i = 0 To lNumEntries - 1
                          List1.AddItem PointerToString(pndm(i).usri2_name)
                      Next
                      
                      '/* Get index for next iteration
                      lIndex = pndm(i - 1).usri2_next_index
                  End If
              Else
                  MsgBox "Error: " & lResult
              End If
              
              If pBuffer Then
                  '/* Release NetAPI buffer.
                  NetApiBufferFree (pBuffer)
              End If
              
              lTotalEntries = lNumEntries + lTotalEntries
          Wend
      ElseIf (optGroup = True) Then
          While lResult = ERROR_MORE_DATA
              List1.AddItem "---------------"
              lResult = NetQueryDisplayInformation(pszServer, NET_GROUP, lIndex, _
                          txtPageSize, MAX_PREFERRED_LENGTH, lNumEntries, pBuffer)
           
              If lResult = 0 Or lResult = ERROR_MORE_DATA Then
                  If lNumEntries > 0 Then
                      ReDim pndg(lNumEntries - 1)
                      '/* Copy information to VB friendly structure
                      CopyMem pndg(0), ByVal pBuffer, Len(pndg(0)) * lNumEntries
                      
                      For i = 0 To lNumEntries - 1
                          List1.AddItem PointerToString(pndg(i).grpi3_name)
                      Next
                      
                      '/* Get index for next iteration
                      lIndex = pndg(i - 1).grpi3_next_index
                  End If
              Else
                  MsgBox "Error: " & lResult
              End If
              
              If pBuffer Then
                  '/* Release NetAPI buffer.
                  NetApiBufferFree (pBuffer)
              End If
              
              lTotalEntries = lNumEntries + lTotalEntries
          Wend
      Else
          MsgBox "Invalid level!"
      End If

      txtTotal.Text = lTotalEntries
  End Sub

  Private Function PointerToString(lpszString As Long) As String
      Dim Temp1 As String, res As Long, Temp2 As String
      Temp1 = String(1000, "*")
      res = CopyString(Temp1, lpszString)
      Temp2 = (StrConv(Temp1, vbFromUnicode))
      PointerToString = Left(Temp2, InStr(Temp2, Chr$(0)) - 1)
  End Function

REFERENCES
==========

For additional information, click the article numbers below to view the articles
in the Microsoft Knowledge Base:

  Q159498 HOWTO: Call LanMan Services from 32-bit Visual Basic Apps

  Q159423 HOWTO: Call LAN Manager Functions from 16-bit Visual Basic 4.0

  Q151774 HOWTO: Call NetUserGetInfo from Visual Basic

  Q106553 HOWTO: Write C DLLs and Call Them from Visual Basic

  Q118643 How to Pass a String or String Arrays Between VB and a C DLL

Additional query words:

======================================================================
Keywords          : kbAPI kbSDKPlatform kbNetAPI kbDSupport kbGrpDSNet 
Technology        : kbVBSearch kbAudDeveloper kbVB400Search
Version           : :4.0
Issue type        : kbhowto kbinfo

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.