Сканирование открытых шар на SMB ресурсах локальной сети
От: Trex_0  
Дата: 01.08.07 08:16
Оценка:
Всем привет! Уже задавал такой вопрос здесь, но так ни кто и не ответил... Как можно средствами .NET просканировать окрытые шары на SMB ресурсах в локальной сети(причем как и обычные так и системные — которые заканчиваюся на $)? Пишу на С#.
Re: Сканирование открытых шар на SMB ресурсах локальной сети
От: Владек Россия Github
Дата: 03.08.07 16:04
Оценка:
Здравствуйте, Trex_0, Вы писали:

T_>Всем привет! Уже задавал такой вопрос здесь, но так ни кто и не ответил... Как можно средствами .NET просканировать окрытые шары на SMB ресурсах в локальной сети(причем как и обычные так и системные — которые заканчиваюся на $)? Пишу на С#.


Вот этот API поможет тебе в твоей задаче, как пользоваться вызовами можно узнать в MSDN.

NativeMethods.cs
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;

namespace Scanner
{
    [HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
    internal static class NativeMethods
    {
        #region Constants

        internal static readonly HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);

        internal const uint ERROR_SUCCESS                  = 0;
        internal const uint ERROR_ACCESS_DENIED            = 5;
        internal const uint ERROR_NOT_ENOUGH_MEMORY        = 8;
        internal const uint ERROR_REM_NOT_LIST             = 51;
        internal const uint ERROR_BAD_NETPATH              = 53;
        internal const uint ERROR_NETNAME_DELETED          = 64;
        internal const uint ERROR_INVALID_PARAMETER        = 87;
        internal const uint ERROR_MORE_DATA                = 234;
        internal const uint ERROR_INVALID_COMPUTER_NAME    = 2351;
        internal const uint ERROR_NO_BROWSER_SERVERS_FOUND = 6118;

        internal const uint MAX_PREFERRED_LENGTH = UInt32.MaxValue;

        [Flags]
        internal enum FORMAT_MESSAGE: uint
        {
            NONE            = 0x00000000,
            ALLOCATE_BUFFER = 0x00000100,
            IGNORE_INSERTS  = 0x00000200,
            FROM_STRING     = 0x00000400,
            FROM_HMODULE    = 0x00000800,
            FROM_SYSTEM     = 0x00001000,
            ARGUMENT_ARRAY  = 0x00002000,
            MAX_WIDTH_MASK  = 0x000000FF
        }

        [Flags]
        internal enum SV_TYPE: uint
        {
            NONE              = 0x00000000,
            WORKSTATION       = 0x00000001,
            SERVER            = 0x00000002,
            SQLSERVER         = 0x00000004,
            DOMAIN_CTRL       = 0x00000008,
            DOMAIN_BAKCTRL    = 0x00000010,
            TIME_SOURCE       = 0x00000020,
            AFP               = 0x00000040,
            NOVELL            = 0x00000080,
            DOMAIN_MEMBER     = 0x00000100,
            PRINTQ_SERVER     = 0x00000200,
            DIALIN_SERVER     = 0x00000400,
            XENIX_SERVER      = 0x00000800,
            SERVER_UNIX       = 0x00000800,
            NT                = 0x00001000,
            WFW               = 0x00002000,
            SERVER_MFPN       = 0x00004000,
            SERVER_NT         = 0x00008000,
            POTENTIAL_BROWSER = 0x00010000,
            BACKUP_BROWSER    = 0x00020000,
            MASTER_BROWSER    = 0x00040000,
            DOMAIN_MASTER     = 0x00080000,
            SERVER_OSF        = 0x00100000,
            SERVER_VMS        = 0x00200000,
            WINDOWS           = 0x00400000,
            DFS               = 0x00800000,
            CLUSTER_NT        = 0x01000000,
            TERMINALSERVER    = 0x02000000,
            CLUSTER_VS_NT     = 0x04000000,
            DCE               = 0x10000000,
            ALTERNATE_XPORT   = 0x20000000,
            LOCAL_LIST_ONLY   = 0x40000000,
            DOMAIN_ENUM       = 0x80000000,
            ALL               = 0xFFFFFFFF
        }

        internal enum PLATFORM_ID
        {
            DOS = 300,
            OS2 = 400,
            NT = 500,
            OSF = 600,
            VMS = 700
        }

        internal enum SERVER_INFO_LEVEL
        {
            _100 = 100,
            _101 = 101
        }

        internal enum STYPE: uint
        {
            DISKTREE = 0,
            PRINTQ = 1,
            DEVICE = 2,
            IPC = 3,
            TEMPORARY = 0x40000000,
            SPECIAL = 0x80000000
        }

        internal enum SHARE_INFO_LEVEL
        {
            _0   = 0,
            _1   = 1,
            _2   = 2,
            _50  = 50,
            _502 = 502
        }

        [Flags]
        internal enum SUPPORTS: uint
        {
            NONE                  = 0x00000000,
            REMOTE_ADMIN_PROTOCOL = 0x00000002,
            RPC                   = 0x00000004,
            SAM_PROTOCOL          = 0x00000008,
            UNICODE               = 0x00000010,
            LOCAL                 = 0x00000020,
            ANY                   = 0xFFFFFFFF
        }

        #endregion

        #region Data Structures

        [StructLayout(LayoutKind.Sequential)]
        internal struct SERVER_INFO_100
        {
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            internal PLATFORM_ID sv100_platform_id;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            internal string sv100_name;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct SERVER_INFO_101
        {
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            internal PLATFORM_ID sv101_platform_id;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            internal string sv101_name;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            internal uint sv101_version_major;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            internal uint sv101_version_minor;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            internal uint sv101_type;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            internal string sv101_comment;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct SHARE_INFO_0
        {
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            internal string shi0_netname;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct SHARE_INFO_1
        {
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            internal string shi1_netname;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
            internal STYPE shi1_type;
            [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
            internal string shi1_remark;
        }

        #endregion

        #region API Entries

        [DllImport("netapi32.dll", EntryPoint="NetApiBufferFree")]
        internal static extern int NetApiBufferFree(IntPtr buffer);

        [DllImport("netapi32.dll", CharSet=CharSet.Unicode, EntryPoint="NetServerEnum")]
        internal static extern uint NetServerEnum(
            [MarshalAs(UnmanagedType.LPWStr)]
            string serverName,
            SERVER_INFO_LEVEL level,
            out IntPtr bufPtr,
            uint prefMaxLen,
            ref uint entriesRead,
            ref uint totalEntries,
            SV_TYPE serverType,
            [MarshalAs(UnmanagedType.LPWStr)]
            string domain,
            IntPtr resumeHandle);

        [DllImport("netapi32.dll", CharSet=CharSet.Unicode, EntryPoint="NetShareEnum")]
        internal static extern uint NetShareEnum(
            [MarshalAs(UnmanagedType.LPWStr)]     
            string serverName,
            SHARE_INFO_LEVEL level,
            out IntPtr bufPtr,
            uint prefMaxLen,
            ref uint entriesRead,
            ref uint totalEntries,
            IntPtr resumeHandle);

#if false
        [DllImport("netapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "NetRemoteComputerSupports")]
        internal static extern uint NetRemoteComputerSupports(
            [MarshalAs(UnmanagedType.LPWStr)]
            string uncServerName,
            SUPPORTS optionsWanted,
            out SUPPORTS optionsSupported);
#endif

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true)]
        internal static extern int FormatMessage(
            FORMAT_MESSAGE flags, 
            HandleRef source, 
            uint messageId, 
            uint languageId,
            StringBuilder buffer, 
            int bufferSize, 
            IntPtr arguments);
        
        #endregion
    }
}


DomainComputerCollection.cs (пример использования NetServerEnum, работа с другими вызовами NetApi32 похожая):
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace Scanner
{
    public class DomainComputerCollection: ResourceWrapper, IEnumerable<string>
    {
        public DomainComputerCollection(string domain)
        {
            this.domain = domain;

            serverInfoPtr = new IntPtr();

            uint status = NativeMethods.NetServerEnum(null,
                NativeMethods.SERVER_INFO_LEVEL._100, out serverInfoPtr,
                NativeMethods.MAX_PREFERRED_LENGTH, ref entriesReadNo,
                ref entriesTotalNo, NativeMethods.SV_TYPE.ALL, domain, IntPtr.Zero);

            if (status != NativeMethods.ERROR_SUCCESS)
                throw new NetApiException("NetServerEnum", status);
        }

        public uint TotalCount
        {
            get { return entriesTotalNo; }
        }

        public uint ReadCount
        {
            get { return entriesReadNo; }
        }

        public string Domain
        {
            get { return domain; }
        }

        #region IEnumerable<string> Members

        public IEnumerator<string> GetEnumerator()
        {
            int ptr = serverInfoPtr.ToInt32();

            for (uint entry = 0; entry != entriesReadNo; ++entry) {
                NativeMethods.SERVER_INFO_100 serverInfo =
                    (NativeMethods.SERVER_INFO_100)Marshal.PtrToStructure(new IntPtr(ptr), 
                        typeof(NativeMethods.SERVER_INFO_100));
                ptr += Marshal.SizeOf(serverInfo);
                yield return serverInfo.sv100_name;
            }
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion

        protected override void DisposeUnmanagedResources()
        {
            NativeMethods.NetApiBufferFree(serverInfoPtr);
        }

        private string domain;
        private IntPtr serverInfoPtr;
        private uint entriesReadNo;
        private uint entriesTotalNo;
    }
}


Вспомогательные полезные классы:

NetApiException.cs:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Scanner.Properties;
using System.Runtime.Serialization;
using System.Security.Permissions;

namespace Scanner
{
    [Serializable]
    public class NetApiException: Exception
    {
        public NetApiException()
            : base(Resources.NetApiNoDetails)
        {
        }

        public NetApiException(string message)
            : base(message)
        {
        }

        public NetApiException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        protected NetApiException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            if (info != null) {
                api = info.GetString("Api");
                errorCode = info.GetUInt32("ErrorCode");
            }
        }

        public NetApiException(string api, uint win32ErrorCode)
            : base(GetErrorMessage(win32ErrorCode))
        {
            this.api = api;
            this.errorCode = win32ErrorCode;
            HResult = HResultFromWin32(win32ErrorCode);
        }

        public string Api
        {
            get { return api; }
        }

        public uint ErrorCode
        {
            get { return errorCode; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                return;
            base.GetObjectData(info, context);
            info.AddValue("Api", api);
            info.AddValue("ErrorCode", errorCode);
        }

        private static string GetErrorMessage(uint errorCode)
        {
            StringBuilder message = new StringBuilder(256);
            int length = NativeMethods.FormatMessage(NativeMethods.FORMAT_MESSAGE.IGNORE_INSERTS | NativeMethods.FORMAT_MESSAGE.FROM_SYSTEM, NativeMethods.NullHandleRef, errorCode, 0, message, message.Capacity + 1, IntPtr.Zero);
            if (length > 0)
                return message.ToString(0, length);
            return String.Format(Resources.Culture, Resources.NetApiUnknownError, Convert.ToString(errorCode, 0x10));
        }

        private static int HResultFromWin32(uint x)
        {
            return ((int)(x) <= 0 ? ((int)(x)) : ((int)(((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)));
        }

        private string api;
        private uint errorCode;

        private const int FACILITY_WIN32 = 7;
    }
}


ResourceWrapper.cs:
using System;

namespace Scanner
{
    public abstract class ResourceWrapper: IDisposable
    {
        ~ResourceWrapper()
        {
            // Call our helper method.
            // Specifying "false" signifies that
            // the GC triggered the clean up.
            Dispose(false);
        }

        public void Dispose()
        {
            // Call our helper method.
            // Specifying "true" signifies that
            // the object user triggered the clean up.
            Dispose(true);
            // Now suppress finalization.
            GC.SuppressFinalize(this);
        }

        protected virtual void DisposeManagedResources()
        {
        }

        protected abstract void DisposeUnmanagedResources();

        private void Dispose(bool disposing)
        {
            // Be sure we have not already been disposed!
            if (!disposed) {
                // If disposing equals true, dispose all
                // managed resources.
                if (disposing) {
                    // Dispose managed resources.
                    DisposeManagedResources();
                }
                // Clean up unmanaged resources here.
                DisposeUnmanagedResources();
            }
            disposed = true;
        }

        // Used to determine if Dispose()
        // has already been called.
        private bool disposed;
    }
}
Сегодня я проснулся рано — вчера утром.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.