C# Programming

Image

PDC, BDC, SQL サーバなどのサーバをリストする

 

1.目次

2.目的

ネットに接続しているサーバをリストします。
このぐらい、Platform SDK じゃなくって、System.Net あたりに用意しておけよ!って感じ。

3.参考書

(1) MSDN NetApi32
(2) MSDN WNet
(2) C# プログラミング: InterOp

4.サーバをリストする方法

Platform SDK: NetApi32と、Windows Networking (WNet)が考えられます。
方法 メリット デメリット
Platform SDK
NetApi32
PDC, BDC, SQL サーバなどのサーバの種類を指定してリストできる。 NetBIOS のない環境ではサポートされません。
Windows NT/2000:Windows NT 3.1 以降のみ
Windows 95/98:対応していません
Platform SDK
WNet
Windows NT/2000:Windows NT 3.1 以降
Windows 95/98:Windows 95 以降
PDC, BDC, SQL サーバなどのサーバの種類を指定できない。

5.Platform SDK/NetApi32 を使用する方法

Kernel32.dll の SetEnvironmentVariable(), GetEnvironmentVariable() のプラットフォームSDK 呼び出しを行います。
呼び出しは次の2つのステップになります。
(1) NetServerEnum
        [DllImport("netapi32")]
        public static extern int NetServerEnum (
            [In] string servername,      // 予約済み
            [In] uint level,             // 情報レベル
            [Out] out IntPtr bufptr,      // 情報が格納されるバッファ
            [In] uint prefmaxlen,         // バッファの最大サイズ
            [Out] out uint entriesread,    // 格納されたエントリの数
            [Out] out uint totalentries,   // 利用可能なエントリの総数
            [In] uint servertype,         // サーバーのタイプ
            [In] string domain,          // 列挙対象のドメイン 
            [In, Out] ref uint resume_handle   // レジュームハンドル
            );
(2) NetApiBufferFree
        [DllImport("netapi32")]
        public static extern int NetApiBufferFree(
            [In] IntPtr lpBuffer);

実行例
ServerName:UCHUKAMEN
Platform:PLATFORM_ID_NT
MajorVersion:5
MinorVersion:1
Type:201219
Comment:コメントです

6.Platform SDK/WNet を使用する方法

Kernel32.dll の SetEnvironmentVariable(), GetEnvironmentVariable() のプラットフォームSDK 呼び出しを行います。
呼び出しは次の3つのステップになります。
(1) WNetOpenEnum
        [DllImport("Mpr.dll")]
        public static extern uint WNetOpenEnum(
            [In] WNet.Scope dwScope, 
            [In] WNet.Type dwType, 
            [In] WNet.Usage dwUsage, 
            [In] IntPtr lpNetResource, 
            [Out] out IntPtr lphEnum);
(2) WNetEnumResource
        [DllImport("Mpr.dll")]
        public static extern uint WNetEnumResource(
            [In] IntPtr hEnum, 
            [In, Out] ref uint lpcCount, 
            [Out] IntPtr lpBuffer, 
            [In, Out] ref uint lpBufferSize);
(3) WNetCloseEnum
        [DllImport("Mpr.dll")]
        public static extern uint WNetCloseEnum(
            [In] IntPtr hEnum);

実行例
lpProvider:Microsoft Windows Network
lpRemoteName:\\UCHUKAMEN
lpComment:コメントです
lpProvider:Microsoft Windows Network

7.改訂履歴

2003/6/8   初版作成。

8.NetApi32 用テストソースコード

NetApi32 用ライブラリ
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Uchukamen
{
        /// <summary>
        /// NetApi32 の概要の説明です。
        /// </summary>
        public class NetApi32
        {
                public NetApi32()
                {
                }

        #region 高レベル・メソッド


        public string [] GetServerName()
        {
            return GetServerName(null);
        }
        
        public string [] GetServerName(string domain)
        {
            return GetServerName(domain, NetApi32.ServerType.SV_TYPE_SQLSERVER);
        }

        public string [] GetSQLServerName()
        {
            return GetServerName(null, NetApi32.ServerType.SV_TYPE_SQLSERVER);
        }

        public string [] GetSQLServerName(string domain)
        {
            return GetServerName(domain, NetApi32.ServerType.SV_TYPE_SQLSERVER);
        }
        
        public string [] GetServerName(NetApi32.ServerType servtype)
        {
            return GetServerName(null, servtype);
        }

        /// <summary>
        /// GetServerName(string domain)
        /// </summary>
        /// <param name="domain"></param>
        /// <returns>ServerInfo []</returns>
        public string [] GetServerName(string domain, NetApi32.ServerType stype)
        {
            string servername = null;   // 予約されています。NULL を指定します。 
            uint level = 100;
            IntPtr bufptr;
            uint prefmaxlen = NetApi32.MAX_PREFERRED_LENGTH;
            uint entriesread;
            uint totalentries;
            uint servertype = (uint)(stype);
            uint resume_handle = 0;
            int result;

            result = NetApi32.NetServerEnum (servername, level,
                out bufptr, prefmaxlen, out entriesread,
                out totalentries, servertype,
                domain, ref resume_handle);

            Type t = typeof(NetApi32.SERVER_INFO_100);
            int offset = Marshal.SizeOf( t );
            
            string [] server = new string[totalentries];
            for (int index = 0; index < (int)totalentries; index++)
            {
                IntPtr ptr = new IntPtr(bufptr.ToInt32() + index * offset);     
                NetApi32.SERVER_INFO_100 info = (NetApi32.SERVER_INFO_100)(Marshal.PtrToStructure(ptr, t));
                server[index] = Marshal.PtrToStringUni(info.sv100_name);
                Debug.WriteLine("sv100_name:" + Marshal.PtrToStringUni(info.sv100_name));
            }
            NetApi32.NetApiBufferFree(bufptr);

            return server;
        }

        /// <summary>
        /// サーバの情報を取得する。
        /// </summary>
        
        public struct ServerInfo 
        {
            public PlatformID Platform;
            public string ServerName;
            public uint MajorVersion;
            public uint MinorVersion;
            public uint Type;
            public string Comment;
        }
        
        public ServerInfo [] GetServerInfo()
        {
            return GetServerInfo(null, NetApi32.ServerType.SV_TYPE_ALL);
        }

        public ServerInfo [] GetSQLServerInfo()
        {
            return GetServerInfo(null, NetApi32.ServerType.SV_TYPE_SQLSERVER);
        }

        public ServerInfo [] GetServerInfo(string domain)
        {
            return GetServerInfo(domain, NetApi32.ServerType.SV_TYPE_ALL);
        }

        public ServerInfo [] GetSQLServerInfo(string domain)
        {
            return GetServerInfo(domain, NetApi32.ServerType.SV_TYPE_SQLSERVER);
        }
        
        public ServerInfo [] GetServerInfo(NetApi32.ServerType servtype)
        {
            return GetServerInfo(null, servtype);
        }

        public ServerInfo[] GetServerInfo(string domain, NetApi32.ServerType stype)
        {
            string servername = null;   // 予約されています。NULL を指定します。 
            uint level = 101;
            IntPtr bufptr;
            uint prefmaxlen = NetApi32.MAX_PREFERRED_LENGTH;
            uint entriesread;
            uint totalentries;
            uint servertype = (uint)(stype);
            uint resume_handle = 0;
            int result;

            result = NetApi32.NetServerEnum (servername, level,
                out bufptr, prefmaxlen, out entriesread,
                out totalentries, servertype,
                domain, ref resume_handle);

            Type t = typeof(NetApi32.SERVER_INFO_101);
            int offset = Marshal.SizeOf(t);

            ServerInfo[] sinfo = new ServerInfo[totalentries];
            
            for (int index = 0; index < (int)totalentries; index++)
            {
                IntPtr ptr = new IntPtr(bufptr.ToInt32() + index * offset);     
                NetApi32.SERVER_INFO_101 info = (NetApi32.SERVER_INFO_101)(Marshal.PtrToStructure(ptr, t));
                sinfo[index].ServerName = Marshal.PtrToStringUni(info.sv101_name);
                sinfo[index].Platform = (PlatformID)info.sv101_platform_id;
                sinfo[index].MajorVersion = info.sv101_version_major;
                sinfo[index].MinorVersion = info.sv101_version_minor;
                sinfo[index].Type = info.sv101_type;
                sinfo[index].Comment = Marshal.PtrToStringUni(info.sv101_comment);

                Debug.WriteLine("ServerName:" + sinfo[index].ServerName);
                Debug.WriteLine("Platform:" + sinfo[index].Platform);
                Debug.WriteLine("MajorVersion:" + sinfo[index].MajorVersion);
                Debug.WriteLine("MinorVersion:" + sinfo[index].MinorVersion);
                Debug.WriteLine("Type:" + sinfo[index].Type);
                Debug.WriteLine("Comment:" + sinfo[index].Comment);
            }
            NetApi32.NetApiBufferFree(bufptr);
            return sinfo;
        }
        #endregion

        #region 低レベルメソッド用 定数
        public const uint MAX_PREFERRED_LENGTH = unchecked((uint)-1);

        public enum ServerType : uint
        {
            SV_TYPE_WORKSTATION     = 0x00000001,   // すべてのワークステーション
            SV_TYPE_SERVER          = 0x00000002,   // すべてのサーバー
            SV_TYPE_SQLSERVER       = 0x00000004,   // すべてのMS SQL Server 
            SV_TYPE_DOMAIN_CTRL     = 0x00000008,   // プライマリドメインコントローラ
            SV_TYPE_DOMAIN_BAKCTRL  = 0x00000010,   // バックアップドメインコントローラ
            SV_TYPE_TIME_SOURCE     = 0x00000020,   // Timesource サービスを実行しているサーバー
            SV_TYPE_AFP             = 0x00000040,   // Apple File Protocol(AFP)サーバー
            SV_TYPE_NOVELL          = 0x00000080,   // Novell サーバー
            SV_TYPE_DOMAIN_MEMBER   = 0x00000100,   // LAN Manager 2.x のドメインメンバ
            SV_TYPE_PRINTQ_SERVER   = 0x00000200,   // プリントキューを共有するサーバー
            SV_TYPE_DIALIN_SERVER   = 0x00000400,   // ダイヤルインサービスを実行しているサーバー
            SV_TYPE_XENIX_SERVER    = 0x00000800,   // Xenix サーバー
            SV_TYPE_SERVER_UNIX     = SV_TYPE_XENIX_SERVER,   // 
            SV_TYPE_NT              = 0x00001000,   // Windows NT/2000 のワークステーションまたはサーバー
            SV_TYPE_WFW             = 0x00002000,   // Windows for Workgroups を実行しているサーバー
            SV_TYPE_SERVER_MFPN     = 0x00004000,   // 
            SV_TYPE_SERVER_NT       = 0x00008000,   // ドメインコントローラではない、Windows NT/2000 のサーバー
            SV_TYPE_POTENTIAL_BROWSER = 0x00010000,   // ブラウザサービスを実行できるサーバー
            SV_TYPE_BACKUP_BROWSER  = 0x00020000,   // バックアップとしてブラウザサービスを実行しているサーバー
            SV_TYPE_MASTER_BROWSER  = 0x00040000,   // マスタブラウザサービスを実行しているサーバー
            SV_TYPE_DOMAIN_MASTER   = 0x00080000,   // ドメインマスタブラウザを実行しているサーバー
            SV_TYPE_SERVER_OSF      = 0x00100000,   // 
            SV_TYPE_SERVER_VMS      = 0x00200000,   // 
            SV_TYPE_WINDOWS         = 0x00400000,   // Windows 95 以降
            SV_TYPE_DFS             = 0x00800000,   // 
            SV_TYPE_CLUSTER_NT      = 0x01000000,   // ドメイン内で利用できるサーバークラスタ
            SV_TYPE_TERMINALSERVER  = 0x02000000,   // Terminal Server
            SV_TYPE_CLUSTER_VS_NT   = 0x04000000,   // NT Cluster Virtual Server Name 
            SV_TYPE_DCE             = 0x10000000,   // IBM DSS or equivalent 
            SV_TYPE_ALTERNATE_XPORT = 0x20000000,   // return list for alternate transport 
            SV_TYPE_LOCAL_LIST_ONLY = 0x40000000,   // Return local list only 
            SV_TYPE_DOMAIN_ENUM     = 0x80000000,
            SV_TYPE_ALL             = 0xFFFFFFFF    // すべてのサーバー
        }
        
        public enum PlatformID : uint
        {
            PLATFORM_ID_DOS = 300,
            PLATFORM_ID_OS2 = 400,
            PLATFORM_ID_NT = 500,
            PLATFORM_ID_OSF = 600,
            PLATFORM_ID_VMS = 700
        }

        /*
        typedef struct _SERVER_INFO_100 
                {
                    DWORD     sv100_platform_id;
                    LPWSTR    sv100_name;
                } SERVER_INFO_100, *PSERVER_INFO_100, *LPSERVER_INFO_100;
                */
        [StructLayout(LayoutKind.Sequential)]
            public struct SERVER_INFO_100 
        {
            public uint sv100_platform_id;
            public IntPtr sv100_name;
        }

        /*
        typedef struct _SERVER_INFO_101 
                {
                    DWORD     sv101_platform_id;
                    LPWSTR    sv101_name;
                    DWORD     sv101_version_major;
                    DWORD     sv101_version_minor;
                    DWORD     sv101_type;
                    LPWSTR    sv101_comment;
                } SERVER_INFO_101, *PSERVER_INFO_101, *LPSERVER_INFO_101;
                */
        [StructLayout(LayoutKind.Sequential)]
            public struct SERVER_INFO_101 
        {
            public uint sv101_platform_id;
            public IntPtr sv101_name;
            public uint sv101_version_major;
            public uint sv101_version_minor;
            public uint sv101_type;
            public IntPtr sv101_comment;
        }
        #endregion

        #region 低レベルメソッド
        /*
        NET_API_STATUS NetServerEnum(
            LPCWSTR servername,    // 予約済み
            DWORD level,           // 情報レベル
            LPBYTE *bufptr,        // 情報が格納されるバッファ
            DWORD prefmaxlen,      // バッファの最大サイズ
            LPDWORD entriesread,   // 格納されたエントリの数
            LPDWORD totalentries,  // 利用可能なエントリの総数
            DWORD servertype,      // サーバーのタイプ
            LPCWSTR domain,        // 列挙対象のドメイン
            LPDWORD resume_handle  // レジュームハンドル
            );
            */
        [DllImport("netapi32")]
        public static extern int NetServerEnum (
            [In] string servername,      // 予約済み
            [In] uint level,             // 情報レベル
            [Out] out IntPtr bufptr,      // 情報が格納されるバッファ
            [In] uint prefmaxlen,         // バッファの最大サイズ
            [Out] out uint entriesread,    // 格納されたエントリの数
            [Out] out uint totalentries,   // 利用可能なエントリの総数
            [In] uint servertype,         // サーバーのタイプ
            [In] string domain,          // 列挙対象のドメイン 
            [In, Out] ref uint resume_handle   // レジュームハンドル
            );

        // bufptr は、NetApiBufferFree(bufptr)で開放する必要がある。
        /*
        NET_API_STATUS NetApiBufferFree(
            LPVOID Buffer  // バッファ
            );
        */        
        [DllImport("netapi32")]
        public static extern int NetApiBufferFree(
            [In] IntPtr lpBuffer);
        #endregion
        }
}

9.WNet 用テストソースコード

WNet 用ライブラリ
using System;
using System.Text; 
using System.Runtime.InteropServices;
using System.Diagnostics; 

namespace Uchukamen
{
    /// <summary>
    /// WNet の概要の説明です。
    /// </summary>
    public class WNet
    {
        public WNet()
        {
            // 
            // TODO: コンストラクタ ロジックをここに追加してください。
            //
        }
        
        #region 定数、構造体
        public struct HostInfo 
        {
            public string lpLocalName;
            public string lpRemoteName;
            public string lpComment;
            public string lpProvider;
        }

        public enum Scope : uint
        {
            RESOURCE_CONNECTED = 0x00000001,    // 現在接続されているすべてのリソース
            RESOURCE_CONTEXT = 0x00000005,      // 呼び出し側のネットワークコンテキスト内のリソース
            RESOURCE_GLOBALNET = 0x00000002,    // ネットワーク上のすべてのリソース
            RESOURCE_REMEMBERED = 0x00000003  // 記憶されている( 永続的な)すべての接続
        }
        public enum Type : uint
        {
            RESOURCETYPE_ANY = 0x00000000,      // すべてのリソース
            RESOURCETYPE_DISK = 0x00000001,     // すべてのディスクリソース
            RESOURCETYPE_PRINT = 0x00000002     // すべての印刷リソース
        }
        public enum Usage : uint
        {
            RESOURCEUSAGE_CONNECTABLE = 0x00000001,     // 接続可能なすべてのリソース
            RESOURCEUSAGE_CONTAINER = 0x00000002,       // すべてのコンテナリソース
            RESOURCEUSAGE_ATTACHED = 0x00000010,        // ユーザーが認証されていない場合、失敗
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED)
        }
        
        public enum DisplayType : uint
        {
            RESOURCEDISPLAYTYPE_GENERIC = 0x00000000, 
            RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001, 
            RESOURCEDISPLAYTYPE_SERVER = 0x00000002,
            RESOURCEDISPLAYTYPE_SHARE = 0x00000003,
            RESOURCEDISPLAYTYPE_FILE = 0x00000004,
            RESOURCEDISPLAYTYPE_GROUP = 0x00000005,
            RESOURCEDISPLAYTYPE_NETWORK = 0x00000006,
            RESOURCEDISPLAYTYPE_ROOT = 0x00000007,
            RESOURCEDISPLAYTYPE_SHAREADMIN = 0x00000008,
            RESOURCEDISPLAYTYPE_DIRECTORY = 0x00000009,
            RESOURCEDISPLAYTYPE_TREE = 0x0000000A,
            RESOURCEDISPLAYTYPE_NDSCONTAINER = 0x0000000B 
        }

        // エラー
        private const uint NO_ERROR = 0;
        private const uint ERROR_NOT_CONTAINER = 1207;
        private const uint ERROR_INVALID_PARAMETER = 87;
        private const uint ERROR_NO_NETWORK = 1222;
        private const uint ERROR_EXTENDED_ERROR = 1208;
        private const uint ERROR_NO_MORE_ITEMS = 259;

        // 構造体
        [StructLayout(LayoutKind.Sequential)]
            public struct NETRESOURCE 
        {
            public uint dwScope;
            public uint dwType;
            public uint dwDisplayType;
            public uint dwUsage;
            public string lpLocalName;
            public string lpRemoteName;
            public string lpComment;
            public string lpProvider;
        }
        #endregion
        
        #region プロトタイプ宣言
        //DWORD WNetConnectionDialog(
        //    HWND hwnd,     // ダイアログボックスを所有するウィンドウのハンドル
        //    DWORD dwType   // 資源の種類
        //    );
        [DllImport("Mpr.dll")]
        public static extern uint WNetConnectionDialog(IntPtr hwnd, uint dwType);


        // DWORD WNetGetLastError(
        //     LPDWORD lpError,     // [out] エラーコード
        //     LPTSTR lpErrorBuf,   // [out] エラー記述バッファ
        //     DWORD nErrorBufSize, // [in]  記述バッファのサイズ
        //     LPTSTR lpNameBuf,    // [out] プロバイダ名を保持するバッファ
        //     DWORD nNameBufSize   // [in]  プロバイダ名バッファのサイズ
        //     );
        [DllImport("Mpr.dll")]
        public static extern uint WNetGetLastError(
            out uint lpError,
            StringBuilder lpErrorBuf,
            uint nErrorBufSize,
            StringBuilder lpNameBuf,
            uint nNameBufSize);

        //DWORD WNetOpenEnum(
        //    DWORD dwScope,                // [in]  列挙のスコープ
        //    DWORD dwType,                 // [in]  列挙したいリソースのタイプ
        //    DWORD dwUsage,                // [in]  列挙したいリソースの用途
        //    LPNETRESOURCE lpNetResource,  // [in]  リソースの構造体
        //    LPHANDLE lphEnum              // [out] 列挙ハンドルのバッファ
        //    );
        [DllImport("Mpr.dll")]
        public static extern uint WNetOpenEnum(
            [In] WNet.Scope dwScope, 
            [In] WNet.Type dwType, 
            [In] WNet.Usage dwUsage, 
            [In] IntPtr lpNetResource, 
            [Out] out IntPtr lphEnum);
        
        //DWORD WNetEnumResource(
        //    HANDLE hEnum,          // [in]      列挙のハンドル
        //    LPDWORD lpcCount,      // [In, Out] 列挙したいエントリ
        //    LPVOID lpBuffer,       // [out]     バッファ
        //    LPDWORD lpBufferSize   // [In, Out] バッファサイズ
        //    );
        [DllImport("Mpr.dll")]
        public static extern uint WNetEnumResource(
            [In] IntPtr hEnum, 
            [In, Out] ref uint lpcCount, 
            [Out] NETRESOURCE[] lpBuffer, 
            [In, Out] ref uint lpBufferSize);

        //DWORD WNetEnumResource(
        //    HANDLE hEnum,          // [in]      列挙のハンドル
        //    LPDWORD lpcCount,      // [In, Out] 列挙したいエントリ
        //    LPVOID lpBuffer,       // [out]     バッファ
        //    LPDWORD lpBufferSize   // [In, Out] バッファサイズ
        //    );
        [DllImport("Mpr.dll")]
        public static extern uint WNetEnumResource(
            [In] IntPtr hEnum, 
            [In, Out] ref uint lpcCount, 
            [Out] IntPtr lpBuffer, 
            [In, Out] ref uint lpBufferSize);

        // DWORD WNetCloseEnum(
        //    HANDLE hEnum   // 列挙のハンドル
        //    );
        [DllImport("Mpr.dll")]
        public static extern uint WNetCloseEnum(
            [In] IntPtr hEnum);
        #endregion

        public HostInfo [] EnumServer()
        {
            Scope dwScope = Scope.RESOURCE_GLOBALNET;
            Type dwType  = Type.RESOURCETYPE_ANY;
            Usage dwUsage = Usage.RESOURCEUSAGE_ALL;

            NETRESOURCE nr = new NETRESOURCE();
            nr.dwScope = (uint)Scope.RESOURCE_GLOBALNET;
            nr.dwType = (uint)Type.RESOURCETYPE_ANY;
           // nr.dwDisplayType = DisplayType.RESOURCEDISPLAYTYPE_DOMAIN;
            nr.lpLocalName = null;
            nr.dwUsage = (uint)Usage.RESOURCEUSAGE_ALL;
            nr.lpRemoteName = "Mshome";
            nr.lpProvider = "Microsoft Windows Network";

            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NETRESOURCE)));
            Marshal.StructureToPtr(nr, ptr, true);
            IntPtr hEnum = new IntPtr();
            uint ret = WNetOpenEnum(dwScope, dwType, dwUsage, ptr, out hEnum);
            Marshal.FreeHGlobal(ptr);

            switch (ret)
            {
                case NO_ERROR:
                    break;
                case ERROR_NOT_CONTAINER:
                    // lpNetResource パラメータがコンテナリソースを指していません。
                    throw(new Exception("lpNetResource パラメータがコンテナリソースを指していません。"));
                case ERROR_INVALID_PARAMETER:
                    // dwScope パラメータまたは dwType パラメータの値が無効です。
                    // あるいは、パラメータの値の組み合わせが無効です。
                    throw(new Exception("dwScope パラメータまたは dwType パラメータの値が無効です。"));
                case ERROR_NO_NETWORK:
                    // ネットワークが利用できません。
                    throw(new Exception("ネットワークが利用できません。"));
                case ERROR_EXTENDED_ERROR:
                {
                    // ネットワーク固有のエラーが発生しました。
                    uint lpError = 0;
                    StringBuilder lpErrorBuf = new StringBuilder(100);
                    StringBuilder lpNameBuf = new StringBuilder(100);
                    uint err = WNetGetLastError(
                        out lpError,
                        lpErrorBuf,
                        (uint)lpErrorBuf.Capacity,
                        lpNameBuf,
                        (uint)lpNameBuf.Capacity);
                    Debug.WriteLine(lpErrorBuf.ToString());
                    Debug.WriteLine(lpNameBuf.ToString());
                    throw(new Exception("ネットワーク固有のエラーが発生しました。"));
                }
                default:
                    break;
            }
            // -1 は、できるだけ多くの数を返す。
            uint lpcCount = unchecked((uint)(-1));            
            IntPtr p = Marshal.AllocHGlobal(16*1024);
            uint BufSize = 16 * 1024;
            uint result = WNetEnumResource(hEnum, ref lpcCount, p, ref BufSize);
            HostInfo [] info = null;
            switch (result)
            {
                case NO_ERROR:
                {
                    info = new HostInfo[lpcCount];
                    for(int i = 0; i < (int)lpcCount; i++)
                    {
                        uint pt = (uint)p + (uint)(i * Marshal.SizeOf(new NETRESOURCE()));
                        NETRESOURCE ppBuf = (NETRESOURCE)Marshal.PtrToStructure((IntPtr)pt, typeof(NETRESOURCE));
                        info[i].lpRemoteName = ppBuf.lpRemoteName;
                        info[i].lpComment = ppBuf.lpComment;
                        info[i].lpLocalName = ppBuf.lpLocalName;
                        info[i].lpProvider = ppBuf.lpProvider;

                        Debug.WriteLine("lpRemoteName:" + ppBuf.lpRemoteName);
                        Debug.WriteLine("lpComment:" + ppBuf.lpComment);
                        Debug.WriteLine("lpLocalName:" + ppBuf.lpLocalName);
                        Debug.WriteLine("lpProvider:" + ppBuf.lpProvider);
                    }
                }
                    break;
                case ERROR_NO_MORE_ITEMS:
                    break;
            }
            Marshal.FreeHGlobal(p);
            WNetCloseEnum(hEnum);
            return info;
        }
    }
}