NetLocalGroupEnum

C# Signature:

[DllImport("Netapi32.dll")]
internal extern static int NetLocalGroupEnum([MarshalAs(UnmanagedType.LPWStr)] 
       string servername, 
       int level, 
       out IntPtr bufptr, 
       int prefmaxlen, 
       out int entriesread, 
       out int totalentries, 
       ref int resume_handle);

VB Signature:

Declare Function NetLocalGroupEnum Lib "netapi32.dll" (TODO) As TODO

User-Defined Types:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
    internal struct LOCALGROUP_USERS_INFO_0
    {
        [MarshalAs(UnmanagedType.LPWStr)]internal string name;
    }

User-Defined Types:

[StructLayout(LayoutKind.Sequential)]
    internal struct LOCALGROUP_USERS_INFO_1
    {
        [MarshalAs(UnmanagedType.LPWStr)] public string name;
        [MarshalAs(UnmanagedType.LPWStr)] public string comment;
    }

Sample Code:

private string [] GetAllLocalGroups(string ServerName) {
            int size=1024;    //Start with 1k
            IntPtr bufptr=new IntPtr(size);
            int level=0;
            int prefmaxlen=1023;
            int entriesread=0;
            int totalentries=0;
            int resume_handle=0;
            int err=0;
            do
            {
                err= NativeMethods.NetLocalGroupEnum(
                    ServerName,
                    level,
                    out bufptr,
                    prefmaxlen,
                    out entriesread,
                    out totalentries,
                    ref resume_handle
                );
                switch(err)
                {
                    //If there is more data, double the size of the buffer...
                    case 2123:        //NERR_BufTooSmall
                    case 234:        //ERROR_MORE_DATA
                        size*=2;
                        bufptr=new IntPtr(size);
                        prefmaxlen=size-1;    //Increase the size you want read as well
                        resume_handle=0;    //And reset the resume_handle or you'll just pick up where you left off.

                        break;
                    case 2351:    //NERR_InvalidComputer
                    case 0:        //NERR_Success
                    default:
                        break;
                }
            }
            while(err==234);    // and start over

            LOCALGROUP_USERS_INFO_0 group=new LOCALGROUP_USERS_INFO_0(); //See user type above
            string [] ret = new string[totalentries];
            IntPtr iter = bufptr;

            for(int i=0; i < totalentries; i++)
            {
                group = (LOCALGROUP_USERS_INFO_0)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_USERS_INFO_0));
                ret[i] = group.name;
                iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LOCALGROUP_USERS_INFO_0)));
            }

            return ret;
        }

Sample Code:

[DllImport("Netapi32.dll")]
        internal extern static int NetLocalGroupEnum(
            [MarshalAs(UnmanagedType.LPWStr)] string servername,
               int level,
               out IntPtr bufptr,
               int prefmaxlen,
               out int entriesread,
               out int totalentries,
               ref int resume_handle);

        [DllImport("Netapi32.dll")]
        internal extern static int NetApiBufferFree(IntPtr buffer);

        private static readonly int NERR_Success = 0;

        private static readonly int ERROR_ACCESS_DENIED = 5;
        private static readonly int ERROR_MORE_DATA = 234;
        private static readonly int NERR_Base = 2100;
        private static readonly int NERR_InvalidComputer = NERR_Base + 251;
        private static readonly int NERR_BufTooSmall = NERR_Base + 23;

Sample Code:

public static LOCALGROUP_USERS_INFO_1[] GetAllLocalGroups()
        {
            return GetAllLocalGroups(null);
        }

        public static LOCALGROUP_USERS_INFO_1[] GetAllLocalGroups(string serverName)
        {
            int res = 0;
            int level = 1;
            IntPtr buffer = IntPtr.Zero;
            int MAX_PREFERRED_LENGTH = -1;
            int read, total;
            int handle = 0;

            var groups = new List<LOCALGROUP_USERS_INFO_1>();
            try
            {
                res = NetLocalGroupEnum(serverName, level, out buffer, MAX_PREFERRED_LENGTH,
                    out read, out total, ref handle);

                if (res != NERR_Success)
                {
                    DumpError(res);
                    return groups.ToArray();
                }

                IntPtr ptr = buffer;
                for (int i = 0; i < read; i++)
                {
                    var group = (LOCALGROUP_USERS_INFO_1)Marshal.PtrToStructure(ptr, typeof(LOCALGROUP_USERS_INFO_1));
                    groups.Add(group);
                    ptr = (IntPtr)((int)ptr + Marshal.SizeOf(typeof(LOCALGROUP_USERS_INFO_1)));
                }
            }
            finally
            {
                NetApiBufferFree(buffer);
            }

            return groups.ToArray();
        }

        private static void DumpError(int res)
        {
            if(res == ERROR_ACCESS_DENIED)
                Trace.WriteLine("ERROR_ACCESS_DENIED");
            else if(res == ERROR_MORE_DATA)
                    Trace.WriteLine("ERROR_MORE_DATA");
            else if(res == NERR_InvalidComputer)
                    Trace.WriteLine("NERR_InvalidComputer");
            else if(res == NERR_BufTooSmall)
                    Trace.WriteLine("NERR_BufTooSmall");
            else
                Trace.WriteLine("Error 0x" + res.ToString("x"));
        }

Última actualización