Displaying long file names using C#

I need to list all the files in a shared folder. My file search program is throwing me a message saying that "The file name length must be less than 248 characters long".

But some paths in my UNC shares have more than 2000 characters.

How should I get the long file names using C#?

Do I have any Win32 API function to achieve this?
sputrevuAsked:
Who is Participating?
 
sputrevuConnect With a Mentor Author Commented:
I figured it myself.
The code is pasted below.
Compile this program and it generates an executable.

The usage is ACL <machinename> <Sharename>

Example:
ACL VINAYKPM.MYSERVER.COM  MYSHAREFOLDER
ACL VINAYKPM  MYSHAREFOLDER

You need to be a member of Administrators to get permissions of a shared folder in local system, and member of Domain Administrators to check against a network folder.

The only limitation of this program is that the share users added in the shared folder's permission list, need to visit the particular shared folder at-least once, or else the application will show their SID (Security Identifier) instead of the user name.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
 
namespace ACL
{
    class LookUpSidName
    {  
        const int NO_ERROR = 0;
        const int ERROR_INSUFFICIENT_BUFFER = 122;
 
        enum SID_NAME_USE
        {
            SidTypeUser = 1,
            SidTypeGroup,
            SidTypeDomain,
            SidTypeAlias,
            SidTypeWellKnownGroup,
            SidTypeDeletedAccount,
            SidTypeInvalid,
            SidTypeUnknown,
            SidTypeComputer
        }
 
       
 
        [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool ConvertSidToStringSid(
            [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
            out IntPtr ptrSid);
 
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool LookupAccountSid(
          string lpSystemName,
          [MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
          System.Text.StringBuilder lpName,
          ref uint cchName,
          System.Text.StringBuilder ReferencedDomainName,
          ref uint cchReferencedDomainName,
          out SID_NAME_USE peUse);
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool LookupAccountSid(
            [In, MarshalAs(UnmanagedType.LPTStr)] string systemName,
            IntPtr sid,
            [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder name,
            ref int cbName,
            StringBuilder referencedDomainName,
            ref int cbReferencedDomainName,
            out int use);
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool ConvertStringSidToSid(
            [In, MarshalAs(UnmanagedType.LPTStr)] string pStringSid,
            ref IntPtr sid);
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool ConvertSidToStringSid(
            IntPtr sid,
            [In, Out, MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);
 
        public void GetAccountNamefromSid(byte[] Sid)
        {
            StringBuilder name = new StringBuilder();
            uint cchName = (uint)name.Capacity;
            StringBuilder referencedDomainName = new StringBuilder();
            uint cchReferencedDomainName = (uint)referencedDomainName.Capacity;
            SID_NAME_USE sidUse;
            // Sid for BUILTIN\Administrators
            //byte[] Sid = new byte[] { 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2 };
 
            int err = NO_ERROR;
            if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
            {
                err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                if (err == ERROR_INSUFFICIENT_BUFFER)
                {
                    name.EnsureCapacity((int)cchName);
                    referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
                    err = NO_ERROR;
                    if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
                        err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                }
            }
            if (err == 0)
                Console.WriteLine(@"{0}\{1}", referencedDomainName.ToString(), name.ToString());
            else
            {
                string asid = GetSidString(Sid);
                try
                {
                    Console.WriteLine(GetName(asid));
                }
                catch
                {
                    //Console.WriteLine(@"Error : {0}", err);
                    Console.WriteLine(asid);
                }
                
            }
        }
 
        public static string GetSidString(byte[] sid)
        {
            IntPtr ptrSid;
            string sidString;
            if (!ConvertSidToStringSid(sid, out ptrSid))
                throw new System.ComponentModel.Win32Exception();
            try
            {
                sidString = Marshal.PtrToStringAuto(ptrSid);
            }
            finally
            {
                //LocalFree(ptrSid);
            }
            return sidString;
        }
 
        public static string GetName(string sid)
        {
            IntPtr _sid = IntPtr.Zero;    //pointer to binary form of SID string.
            int _nameLength = 0;        //size of object name buffer
            int _domainLength = 0;        //size of domain name buffer
            int _use;                    //type of object
            StringBuilder _domain = new StringBuilder();    //domain name variable
            int _error = 0;
            StringBuilder _name = new StringBuilder();        //object name variable
            //converts SID string into the binary form
            bool _rc0 = ConvertStringSidToSid(sid, ref _sid);
            if (_rc0 == false)
            {
                _error = Marshal.GetLastWin32Error();
                Marshal.FreeHGlobal(_sid);
                throw (new Exception(new Win32Exception(_error).Message));
            }
 
            //first call of method returns the size of domain name 
            //and object name buffers
            bool _rc = LookupAccountSid(null, _sid, _name, ref _nameLength, _domain,
                             ref _domainLength, out _use);
            _domain = new StringBuilder(_domainLength);    //allocates memory for domain name
            _name = new StringBuilder(_nameLength);        //allocates memory for object name
            _rc = LookupAccountSid(null, _sid, _name, ref _nameLength, _domain,
                             ref _domainLength, out _use);
            if (_rc == false)
            {
                _error = Marshal.GetLastWin32Error();
                Marshal.FreeHGlobal(_sid);
                throw (new Exception(new Win32Exception(_error).Message));
            }
            else
            {
                Marshal.FreeHGlobal(_sid);
                return _domain.ToString() + "\\" + _name.ToString();
            }
        }
 
    }
 
    class Program
    {
        [DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int NetShareGetInfo(
            [MarshalAs(UnmanagedType.LPWStr)] string serverName,
            [MarshalAs(UnmanagedType.LPWStr)] string netName,
            Int32 level,
            out IntPtr bufPtr);
 
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetSecurityDescriptorDacl(
            IntPtr pSecurityDescriptor,
            [MarshalAs(UnmanagedType.Bool)] out bool bDaclPresent,
            ref IntPtr pDacl,
            [MarshalAs(UnmanagedType.Bool)] out bool bDaclDefaulted
            );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetAclInformation(
            IntPtr pAcl,
            ref ACL_SIZE_INFORMATION pAclInformation,
            uint nAclInformationLength,
            ACL_INFORMATION_CLASS dwAclInformationClass
         );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int GetAce(
            IntPtr aclPtr,
            int aceIndex,
            out IntPtr acePtr
         );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int GetLengthSid(
            IntPtr pSID
         );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool ConvertSidToStringSid(
            [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
            out IntPtr ptrSid
         );
 
        [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int NetApiBufferFree(
            IntPtr buffer
         );
 
 
 
        [StructLayout(LayoutKind.Sequential)]
        struct SHARE_INFO_502
        {
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi502_netname;
            public uint shi502_type;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi502_remark;
            public Int32 shi502_permissions;
            public Int32 shi502_max_uses;
            public Int32 shi502_current_uses;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi502_path;
            public IntPtr shi502_passwd;
            public Int32 shi502_reserved;
            public IntPtr shi502_security_descriptor;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        struct ACL_SIZE_INFORMATION
        {
            public uint AceCount;
            public uint AclBytesInUse;
            public uint AclBytesFree;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        public struct ACE_HEADER
        {
            public byte AceType;
            public byte AceFlags;
            public short AceSize;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        struct ACCESS_ALLOWED_ACE
        {
            public ACE_HEADER Header;
            public int Mask;
            public int SidStart;
        }
 
        enum ACL_INFORMATION_CLASS
        {
            AclRevisionInformation = 1,
            AclSizeInformation
        }
 
        static void Main(string[] args)
        {
            IntPtr bufptr = IntPtr.Zero;
            int err = NetShareGetInfo(args[0], args[1], 502, out bufptr);
            if (0 == err)
            {
                SHARE_INFO_502 shareInfo = (SHARE_INFO_502)Marshal.PtrToStructure(bufptr, typeof(SHARE_INFO_502));
 
                bool bDaclPresent;
                bool bDaclDefaulted;
                IntPtr pAcl = IntPtr.Zero;
                GetSecurityDescriptorDacl(shareInfo.shi502_security_descriptor, out bDaclPresent, ref pAcl, out bDaclDefaulted);
                if (bDaclPresent)
                {
                    ACL_SIZE_INFORMATION AclSize = new ACL_SIZE_INFORMATION();
                    GetAclInformation(pAcl, ref AclSize, (uint)Marshal.SizeOf(typeof(ACL_SIZE_INFORMATION)), ACL_INFORMATION_CLASS.AclSizeInformation);
 
                    LookUpSidName ln = new LookUpSidName();
 
                    for (int i = 0; i < AclSize.AceCount; i++)
                    {
                        IntPtr pAce;
                        err = GetAce(pAcl, i, out pAce);
                        ACCESS_ALLOWED_ACE ace = (ACCESS_ALLOWED_ACE)Marshal.PtrToStructure(pAce, typeof(ACCESS_ALLOWED_ACE));
 
                        IntPtr iter = (IntPtr)((int)pAce + (int)Marshal.OffsetOf(typeof(ACCESS_ALLOWED_ACE), "SidStart"));
                        byte[] bSID = null;
                        int size = (int)GetLengthSid(iter);
                        bSID = new byte[size];
                        Marshal.Copy(iter, bSID, 0, size);
                        IntPtr ptrSid;
                        ConvertSidToStringSid(bSID, out ptrSid);
                        string strSID = Marshal.PtrToStringAuto(ptrSid);
 
                        //Console.WriteLine("{0} : {1}/{2}/{3}", strSID, ace.Header.AceType.ToString(), ace.Mask.ToString(), ace.Header.AceFlags.ToString());
                        ln.GetAccountNamefromSid(bSID);
                    }
                }
                err = NetApiBufferFree(bufptr);
            }
        }
    }
}

Open in new window

0
 
Haris VCommented:
0
 
openshacCommented:
You could run a bat file from C# and then just process the results:

There's an example on how to do this sort of thing here:

http://blogs.msdn.com/csharpfaq/archive/2004/06/01/146375.aspx
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.