using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke { /// Items from the mpr.dll public static partial class Mpr { /// The WNetEnumResources function enumerates network resources. /// /// /// Pointer to a NETRESOURCE structure that specifies the container to enumerate. If the dwScope parameter is not /// RESOURCE_GLOBALNET, this parameter must be NULL. /// /// /// If this parameter is NULL, the root of the network is assumed. (The system organizes a network as a hierarchy; the root is /// the topmost container in the network.) /// /// /// If this parameter is not NULL, it must point to a NETRESOURCE structure. This structure can be filled in by the /// application or it can be returned by a call to the WNetEnumResource function. The NETRESOURCE structure must /// specify a container resource; that is, the RESOURCEUSAGE_CONTAINER value must be specified in the dwUsage parameter. /// /// /// To enumerate all network resources, an application can begin the enumeration by calling WNetOpenEnum with the /// lpNetResource parameter set to NULL, and then use the returned handle to call WNetEnumResource to enumerate /// resources. If one of the resources in the NETRESOURCE array returned by the WNetEnumResource function is a /// container resource, you can call WNetOpenEnum to open the resource for further enumeration. /// /// /// /// Scope of the enumeration. This parameter can be one of the following values. /// /// /// /// Value /// Meaning /// /// /// RESOURCE_CONNECTED /// /// Enumerate all currently connected resources. The function ignores the dwUsage parameter. For more information, see the following /// Remarks section. /// /// /// /// RESOURCE_CONTEXT /// /// Enumerate only resources in the network context of the caller. Specify this value for a Network Neighborhood view. The function /// ignores the dwUsage parameter. /// /// /// /// RESOURCE_GLOBALNET /// Enumerate all resources on the network. /// /// /// RESOURCE_REMEMBERED /// Enumerate all remembered (persistent) connections. The function ignores the dwUsage parameter. /// /// /// /// /// /// Resource types to be enumerated. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// RESOURCETYPE_ANY /// All resources. This value cannot be combined with RESOURCETYPE_DISK or RESOURCETYPE_PRINT. /// /// /// RESOURCETYPE_DISK /// All disk resources. /// /// /// RESOURCETYPE_PRINT /// All print resources. /// /// /// /// If a network provider cannot distinguish between print and disk resources, it can enumerate all resources. /// /// /// Resource usage type to be enumerated. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// 0 /// All resources. /// /// /// RESOURCEUSAGE_CONNECTABLE /// All connectable resources. /// /// /// RESOURCEUSAGE_CONTAINER /// All container resources. /// /// /// RESOURCEUSAGE_ATTACHED /// /// Setting this value forces WNetOpenEnum to fail if the user is not authenticated. The function fails even if the network allows /// enumeration without authentication. /// /// /// /// RESOURCEUSAGE_ALL /// Setting this value is equivalent to setting RESOURCEUSAGE_CONNECTABLE, RESOURCEUSAGE_CONTAINER, and RESOURCEUSAGE_ATTACHED. /// /// /// /// /// This parameter is ignored unless the dwScope parameter is equal to RESOURCE_GLOBALNET. For more information, see the following /// Remarks section. /// /// /// if set to [recurse containers]. /// The enumeration results. The results are returned as a list of NETRESOURCE structures. public static IEnumerable WNetEnumResources([Optional] NETRESOURCE root, NETRESOURCEScope dwScope = NETRESOURCEScope.RESOURCE_GLOBALNET, NETRESOURCEType dwType = NETRESOURCEType.RESOURCETYPE_ANY, NETRESOURCEUsage dwUsage = 0, bool recurseContainers = false) { var err = WNetOpenEnum(dwScope, dwType, dwUsage, root, out var h); if (err == Win32Error.ERROR_NOT_CONTAINER || err == Win32Error.ERROR_NO_NETWORK) yield break; else if (err.Failed) throw err.GetException(); using (h) { var count = -1; var sz = 16 * 1024U; using (var mem = new SafeHGlobalHandle((int)sz)) { do { mem.Zero(); err = WNetEnumResource(h, ref count, (IntPtr)mem, ref sz); if (err.Succeeded) { foreach (var e in mem.ToEnumerable(count)) { yield return e; if (recurseContainers && e.dwUsage.IsFlagSet(NETRESOURCEUsage.RESOURCEUSAGE_CONTAINER)) foreach (var ce in WNetEnumResources(e, dwScope, dwType, dwUsage, recurseContainers)) yield return ce; } } else if (err != Win32Error.ERROR_NO_MORE_ITEMS) throw err.GetException("Last resource = " + (root is null ? "" : $"Type:{root.dwDisplayType}=Prov:{root.lpProvider}; Rem:{root.lpRemoteName}")); } while (err != Win32Error.ERROR_NO_MORE_ITEMS); } } } } }