Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Download Visual Studio Add-In

NetQueryDisplayInformation (netapi32)
 
.
Summary
The NetQueryDisplayInformation function returns user account, computer, or group account information. Call this function to quickly enumerate account information for display in user interfaces.

C# Signature:

    [DllImport("Netapi32.dll")]
       extern static uint NetQueryDisplayInformation([MarshalAs(UnmanagedType.LPWStr)]
       string serverName,
       uint Level,
       uint ResumeHandle,
       uint EntriesRequested,
       uint prefMaxLength,
       out uint entriesRead,
       out IntPtr Buffer);

VB Signature:

    Declare Function NetQueryDisplayInformation Lib "Netapi32.dll"
    (serverName As Byte, _
    ByVal level As Long, _
    ByVal ResumeHandle As Long, _
    ByVal EntriesRequested As Long, _
    ByVal prefMaxLen As Long, _
    entriesRead As Long, _
    Buffer As Long) As Long

VB.Net Signature:

    Declare Function NetQueryDisplayInformation Lib "Netapi32.dll" _
    (serverName As IntPtr, _
    ByVal level As Integer, _
    ByVal ResumeHandle As Integer, _
    ByVal EntriesRequested As Integer, _
    ByVal prefMaxLen As Integer, _
    ByRef entriesRead As Integer, _
    ByRef Buffer As Long) As Integer

User-Defined Types:

Notes:

None.

Tips & Tricks:

I hugely increased the speed of this API by doing the following:

Add 'private const uint MAX_PREFERRED_LENGTH = 4294967294;' to the defines and request 100 records at a time thus:

lret = NetQueryDisplayInformation(strDomain, 3, lindex, 100, MAX_PREFERRED_LENGTH, out lread , out x);

The following C# function returns user information just as fast as the C++ equivalent.

Sample Code:

    public struct UserInfo
    {
        public string Username;
        public string FullName;
    }

    public List<UserInfo> GetUserList(string DomainController)
    {
        System.IntPtr UsrBuf = System.IntPtr.Zero;
        System.IntPtr item = System.IntPtr.Zero;
        uint lindex = 0;
        uint lread = 0;
        uint lret = ERROR_MORE_DATA;
        uint reqRecs = 100; // Number of records to get (Win2K+ only allows 100 at a time)
        List<UserInfo> UserData = new List<UserInfo>();
        NET_DISPLAY_USER usr = new NET_DISPLAY_USER();

        int StructSize = Marshal.SizeOf(typeof(NET_DISPLAY_USER));

        // Get user information
        lret = ERROR_MORE_DATA;
        while ((lret == ERROR_MORE_DATA))
        {
        // Get batches of 100 users
        lret = NetQueryDisplayInformation(DomainController, 1, lindex, reqRecs, MAX_PREFERRED_LENGTH, out lread, out UsrBuf);
        if (lread > 0)
        {
            // Get users from buffer
            item = UsrBuf;

            // lread contains the number of records returned.
            for( ; lread > 0; lread--)
            {

            if (item != System.IntPtr.Zero)
            {
                UserInfo nUser = new UserInfo();

                // Convert strings and load UserInfo structure
                usr = (NET_DISPLAY_USER)Marshal.PtrToStructure(item, typeof(NET_DISPLAY_USER));
                nUser.Username = Marshal.PtrToStringUni(usr.usri1_name);
                nUser.FullName = Marshal.PtrToStringUni(usr.usri1_full_name);
                UserData.Add(nUser);
            }

            // Update index (used in GetInfo call to set offset for next batch)
            lindex = usr.usri1_next_index;

            // Increment UserInfo pointer
            item = (IntPtr)(item.ToInt64() + StructSize);
            }

            // Free buffer (allocated by system)
            if (UsrBuf != System.IntPtr.Zero)
            {
            NetApiBufferFree(UsrBuf);
            }

        }

        }

        return UserData;
    }

Sample Code:

    [ StructLayout( LayoutKind.Sequential)]
    public struct NET_DISPLAY_USER
    {
        public System.IntPtr usri1_name;  
        public System.IntPtr usri1_comment;  
        public uint usri1_flags;  
        public System.IntPtr usri1_full_name;  
        public uint usri1_user_id;  
        public uint usri1_next_index;
    }

    [StructLayout( LayoutKind.Sequential )]
    public    struct NET_DISPLAY_GROUP
    {
        public System.IntPtr grp_name;
        public System.IntPtr grp_comment;
        public int grp_group_id;
        public int grp_attributes;
        public int grp_next_index;
    }

    [StructLayout( LayoutKind.Sequential )]
    public struct NET_DISPLAY_MACHINE
    {
        public System.IntPtr usri2_name;
        public System.IntPtr usri2_comment;
        public int  usri2_flags;
        public int  usri2_user_id;
        public int  usri2_next_index;
    }

    #region constants
    private const int READ_CONTROL = 0x20000;
    private const int TOKEN_QUERY = 0x8;
    private const int ERROR_MORE_DATA = 234;
    private const int NERR_TRUE = 1;
    private const int RPC_S_SERVER_UNAVAILABLE = 1722;
    private const int ERROR_ACCESS_DENIED = 5;
    private const int ERROR_INVALID_LEVEL = 124;
    private const int NERR_Success = 0;
    #endregion

    #region external dll declares

    [DllImport( "advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]

    [DllImport("Netapi32.dll")]    static extern int NetQueryDisplayInformation([MarshalAs(UnmanagedType.LPWStr)] string serverName,
    int Level,     int ResumeHandle,     int EntriesRequested,    int prefMaxLength,    out int entriesRead,     out System.IntPtr Buffer);

    [DllImport("netapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] private static extern int NetApiBufferFree (System.IntPtr pBuffer);

    #endregion    

public static test(string strDomain)

{

    System.IntPtr x = System.IntPtr.Zero;
    uint lindex = 0;
    uint lread = 0;
    uint lret = ERROR_MORE_DATA;
    ArrayList a = new ArrayList();
    NET_DISPLAY_GROUP grp = new NET_DISPLAY_GROUP ();
    NET_DISPLAY_USER usr = new NET_DISPLAY_USER();
    while ((lret == ERROR_MORE_DATA))
    {
        //get each group
        lret = NetQueryDisplayInformation(strDomain, 3, lindex, 1, 1024, out lread , out x);
        if (lread > 0)
        {
            //get group
            if (x != System.IntPtr.Zero)
            {
                grp = (NET_DISPLAY_GROUP)Marshal.PtrToStructure (x, typeof(NET_DISPLAY_GROUP));
                a.Add(Marshal.PtrToStringUni(grp.grp_name));
            }

            //get next index
            lindex = grp.grp_next_index;

            //free buffer
            if (x != System.IntPtr.Zero)
            {
                NetApiBufferFree(x);
            }
        }
    }

    lret = ERROR_MORE_DATA;
    //now get users
    while ((lret == ERROR_MORE_DATA))
    {
        //get each user
        lret = NetQueryDisplayInformation(strDomain, 1, lindex, 1, 1024, out lread , out x);
        if (lread > 0)
        {
            //get group
            if (x != System.IntPtr.Zero)
            {
                usr = (NET_DISPLAY_USER)Marshal.PtrToStructure(x, typeof(NET_DISPLAY_USER));
                a.Add(Marshal.PtrToStringUni(usr.usri1_name));
            }

            //get next index
            lindex = usr.usri1_next_index;
            //free buffer
            if (x != System.IntPtr.Zero)
            {
                NetApiBufferFree (x);
            }
        }
    }

    lret = ERROR_MORE_DATA;
    NET_DISPLAY_MACHINE mac = new NET_DISPLAY_MACHINE ();

    //now get users
    while ((lret == ERROR_MORE_DATA))
    {
        //get each group
        lret = NetQueryDisplayInformation(strDomain, 2, lindex, 1, 1024, out lread , out x);

        if (lread > 0)
        {
            //get group
            if (x != System.IntPtr.Zero)
            {
                mac = (NET_DISPLAY_MACHINE) Marshal.PtrToStructure(x,typeof(NET_DISPLAY_MACHINE));
                a.Add(Marshal.PtrToStringUni(mac.usri2_name));
            }

            //get next index
            lindex = mac.usri2_next_index;

            //free buffer
            if (x != System.IntPtr.Zero)
            {
                NetApiBufferFree (x);
            }
        }
    }

}

Alternative Managed API:

Do you know one? Please contribute it!

Documentation

Please edit this page!

Do you have...

  • helpful tips or sample code to share for using this API in managed code?
  • corrections to the existing content?
  • variations of the signature you want to share?
  • additional languages you want to include?

Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).

 
Access PInvoke.net directly from VS:
Terms of Use
Edit This Page
Find References
Show Printable Version
Revisions