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);
}
}
}
}
}