Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Get the User Names and Group Name from NT

Posted on 1999-07-26
Medium Priority
Last Modified: 2008-02-01
I wish to fill my User table with the User Name and Group Names from the NT security. I tried to use the 'NetGroupGetUsers' API call but for some reason I was unable to make it work. Can anyone give me a example or another way to work around it.
Question by:umeshkhoje
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions

Accepted Solution

JohnLucas earned 200 total points
ID: 1527595
This will get you the user name under NT/98 or 95

Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
   (ByVal lpBuffer As String, nSize As Long) As long

    Dim lpBuff As String * 25
    Dim ret As Long, UserName As String

    ret = GetUserName(lpBuff, 25)
    GetUser = Left(lpBuff, InStr(lpBuff, Chr(0)) - 1)

LVL 10

Expert Comment

ID: 1527596
This is not needed...

Left(lpBuff, InStr(lpBuff, Chr(0)) - 1)

Expert Comment

ID: 1527597
It is needed if you dont want a null character after the name followed by lots of blank spaces.

Nice answer JohnLucas. Only one suggestion, why not extend the length of lpBuff to 255 characters since you are going to trim it anyways? Just allows for future expansion of name lengths (beyond 25 chars) without recoding :)

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Author Comment

ID: 1527598
I wish to fill all the users. Not the user who is logged in.

Expert Comment

ID: 1527599
Function EnumerateUsers(ByVal SName As String, ByVal GName As String) As Long
    Dim Result As Long, BufPtr As Long, EntriesRead As Long
    Dim TotalEntries As Long, ResumeHandle As Long, BufLen As Long
    Dim SNArray() As Byte, GNArray() As Byte, UNArray(99) As Byte
    Dim UName As String, I As Integer, UNPtr As Long, TempPtr As MungeLong
    Dim TempStr As MungeInt, Found As Boolean
    Dim RS As ADODB.Recordset

    On Error Resume Next
    Set RS = frmMain.Adodc1.Recordset.Clone
    SNArray = SName & vbNullChar       ' Move to byte array
    GNArray = GName & vbNullChar       ' Move to Byte array
    BufLen = 255                       ' Buffer size
    ResumeHandle = 0                   ' Start with the first entry
        If Len(GName) = 0 Then
            Result = NetUserEnum0(SNArray(0), 0, FILTER_NORMAL_ACCOUNT, BufPtr, BufLen, EntriesRead, TotalEntries, ResumeHandle)
            Result = NetGroupEnumUsers0(SNArray(0), GNArray(0), 0, BufPtr, BufLen, EntriesRead, TotalEntries, ResumeHandle)
        End If
        EnumerateUsers = Result
        If Result <> 0 And Result <> 234 Then    ' 234 means multiple reads
                                                ' required
            If Result = 2220 Then GoTo exitFun
        End If
        For I = 1 To EntriesRead
            ' Get pointer to string from beginning of buffer
            ' Copy 4-byte block of memory in 2 steps
            Result = PtrToInt(TempStr.XLo, BufPtr + (I - 1) * 4, 2)
            Result = PtrToInt(TempStr.XHi, BufPtr + (I - 1) * 4 + 2, 2)
            LSet TempPtr = TempStr ' munge 2 integers into a Long
            ' Copy string to array
            Result = PtrToStr(UNArray(0), TempPtr.X)
            UName = Left(UNArray, StrLen(TempPtr.X))
            RS.Find "username='" & UName & "'"
            If RS.EOF Then
                frmUser.CbUserName.AddItem UName
            End If
        Next I
    Loop Until EntriesRead = TotalEntries
    ' The above condition is only valid for reading accounts on Windows NT,
    ' but is not OK for OS/2 or LanMan

    Result = NetAPIBufferFree(BufPtr)         ' Don't leak memory
End Function
Public Function GetPrimaryDCName(ByVal MName As String, ByVal DName As String) As String
    Dim Result As Long, DCNPtr As Long
    Dim DNArray() As Byte, MNArray() As Byte, DCNArray(100) As Byte
    GetPrimaryDCName = ""
    MNArray = MName & vbNullChar
    DNArray = DName & vbNullChar
    Result = NetGetDCName(MNArray(0), DNArray(0), DCNPtr)
    If Result <> 0 Then Exit Function
    Result = PtrToStr(DCNArray(0), DCNPtr)
    Result = NetAPIBufferFree(DCNPtr)
    GetPrimaryDCName = DCNArray()
End Function

EnumerateUsers GetPrimaryDCName("", ""), ""

LVL 10

Expert Comment

ID: 1527600
No, it is not needed...

Expert Comment

ID: 1527601

    Dim lpBuff As String * 25

Creates as string called lpBuff which has a fixed length of 25 characters.

    ret = GetUserName(lpBuff, 25)

Gets the username and puts it into lpBuff, which is fixed at 25 character length. IT also returns a null character to signify the end of the returned string.

IE :

lpBuff="Viktornet§                "
Noting that I have used § to represent a null character.

That is why you must have the line:
GetUser = Left(lpBuff, InStr(lpBuff, Chr(0)) - 1)

which will give the value:


Which is in a much more usable format.

If you put a break point in JohnLucas' code on the last line <GetUser = Left(lpBuff, InStr(lpBuff, Chr(0)) - 1)> and type ?"*" & lpbuff & "*" into the debug window, you will see what I mean.

Try it, and if you still think you're right, justify your comment with an explanation as to why you are right. Don't just repeat your previous answer.

As I said before JohnLucas is right, the line is needed.


LVL 10

Expert Comment

ID: 1527602
oh come on... stop arguing.... as i'm telling you that ISNT needed..

try this..

    Dim str As String * 100
    str = "Viktor" & Chr(0) & "net"
    Text1.Text = str

Now Text1.Text = "Viktor" not "Viktor#0"... VB knows what to do with the NULL char and doesn't include it in the string... it just let's it know where the string is ending...


Expert Comment

ID: 1527603

Your code works perfectly. You are right that the textbox control knows how to handle a null char.

However, if you return the value from a function (or use it in the same function), and do not place it into a control, you do need the line in your code to trim out the crap, as my code (in my last comment) demonstrates.

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction In a recent article ( for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Suggested Courses

660 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question