#region Copyright (C) 2007-2013 Team MediaPortal
/*
Copyright (C) 2007-2013 Team MediaPortal
http://www.team-mediaportal.com
This file is part of MediaPortal 2
MediaPortal 2 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
MediaPortal 2 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with MediaPortal 2. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
namespace MediaPortal.Utilities.Network
{
[StructLayout(LayoutKind.Sequential)]
public class NetResource
{
public ResourceScope dwScope = 0;
public ResourceType dwType = 0;
public ResourceDisplayType dwDisplayType = 0;
public ResourceUsage dwUsage = 0;
public string lpLocalName = null;
public string lpRemoteName = null;
public string lpComment = null;
public string lpProvider = null;
};
public enum ResourceScope
{
Connected = 1,
GlobalNet,
Remembered,
Recent,
Context
};
public enum ResourceType
{
Any,
Disk,
Print,
Reserved
};
[Flags]
public enum ResourceUsage
{
Connectable = 0x00000001,
Container = 0x00000002,
NoLocalDevice = 0x00000004,
Sibling = 0x00000008,
Attached = 0x00000010,
All = (Connectable | Container | Attached),
};
public enum ResourceDisplayType
{
Generic,
Domain,
Server,
Share,
File,
Group,
Network,
Root,
ShareAdmin,
Directory,
Tree,
Ndscontainer
};
///
/// Enumerator for several types of network resources, see parameters of .
///
public static class NetworkResourcesEnumerator
{
private enum ErrorCodes
{
NoError = 0,
ErrorNoMoreItems = 259
};
static int _recursionLevel = 0;
static string _path = @"c:\NetworkResourceEnumeratorLog3.txt";
#region Windows API functions
[DllImport("Mpr.dll", EntryPoint = "WNetOpenEnumA", CallingConvention = CallingConvention.Winapi)]
private static extern ErrorCodes WNetOpenEnum(ResourceScope dwScope, ResourceType dwType, ResourceUsage dwUsage, NetResource p, out IntPtr lphEnum);
[DllImport("Mpr.dll", EntryPoint = "WNetCloseEnum", CallingConvention = CallingConvention.Winapi)]
private static extern ErrorCodes WNetCloseEnum(IntPtr hEnum);
[DllImport("Mpr.dll", EntryPoint = "WNetEnumResourceA", CallingConvention = CallingConvention.Winapi)]
private static extern ErrorCodes WNetEnumResource(IntPtr hEnum, ref uint lpcCount, IntPtr buffer, ref uint lpBufferSize);
#endregion
public static ICollection EnumerateResources(ResourceScope scope, ResourceType type, ResourceUsage usage, ResourceDisplayType displayType)
{
NetResource pRsrc = new NetResource();
return EnumerateResources(pRsrc, scope, type, usage, displayType);
}
private static ICollection EnumerateResources(NetResource pRsrc, ResourceScope scope, ResourceType type,
ResourceUsage usage, ResourceDisplayType displayType)
{
_recursionLevel++;
Log("EnumerateResources called with pRsrc:");
LogNetResource(pRsrc);
List result = new List();
uint bufferSize = 16384;
IntPtr buffer = Marshal.AllocHGlobal((int) bufferSize);
try
{
IntPtr handle;
uint cEntries = 1;
ErrorCodes res = WNetOpenEnum(scope, type, usage, pRsrc, out handle);
Log("WNetOpenEnum called");
Log(" Parameters:");
Log(String.Format(" scope: '{0}", scope.ToString()));
Log(String.Format(" type: '{0}", type.ToString()));
Log(String.Format(" usage: '{0}", usage.ToString()));
Log(String.Format(" Returned Error Code: '{0}'", res.ToString()));
Log("");
if (res == ErrorCodes.NoError)
try
{
do
{
res = WNetEnumResource(handle, ref cEntries, buffer, ref bufferSize);
Log("WNetEnumResource called");
Log(" Returned Ref-Values:");
Log(String.Format(" cEntries (before: '1'): '{0}", cEntries));
Log(String.Format(" bufferSize (before: '16384'): '{0}", bufferSize));
Log(String.Format(" Returned Error Code: '{0}'", res.ToString()));
Log("");
if (res == ErrorCodes.NoError)
{
Marshal.PtrToStructure(buffer, pRsrc);
Log("New pRsrc from Buffer:");
LogNetResource(pRsrc);
if (pRsrc.dwDisplayType == displayType)
{
Log(String.Format("DisplayTypeMatch (Requested:'{0}')", displayType));
Log(String.Format(" Adding lpRemoteName '{0}' to result", pRsrc.lpRemoteName));
Log("");
result.Add(pRsrc.lpRemoteName);
}
if (String.IsNullOrEmpty(pRsrc.lpRemoteName))
Log("lpRemoteName is Null or empty. Even if it's a container DO NOT CALL RECURSIVELY!");
if ((pRsrc.dwUsage & ResourceUsage.Container) == ResourceUsage.Container &&
!String.IsNullOrEmpty(pRsrc.lpRemoteName))
{
Log("ResourceUsage==Container: Calling EnumerateResources recursively");
Log("");
result.AddRange(EnumerateResources(pRsrc, scope, type, usage, displayType));
}
}
else if (res != ErrorCodes.ErrorNoMoreItems)
{
Log("WNetEnumResource returned unknown error ==> break!");
Log("");
break;
}
} while (res != ErrorCodes.ErrorNoMoreItems);
}
catch (Exception ex)
{
Log(String.Format("Exception in inner try block: '{0}'", ex.ToString()));
}
finally
{
Log("Calling WNetCloseEnum");
Log("");
WNetCloseEnum(handle);
}
}
catch (Exception ex)
{
Log(String.Format("Exception in outer try block: '{0}'", ex.ToString()));
}
finally
{
Log("Calling FreeHGlobal");
Log("");
Marshal.FreeHGlobal(buffer);
_recursionLevel--;
}
return result;
}
private static void LogNetResource(NetResource rsc)
{
Log(" NetResource:");
if(rsc == null)
{
Log(" NULL");
return;
}
Log(String.Format(" lpLocalName : '{0}'", rsc.lpLocalName));
Log(String.Format(" lpRemoteName: '{0}'", rsc.lpRemoteName));
Log(String.Format(" lpComment: '{0}'", rsc.lpComment));
Log(String.Format(" lpProvider: '{0}'", rsc.lpProvider));
Log(String.Format(" dwScope: '{0}'", rsc.dwScope.ToString()));
Log(String.Format(" dwType: '{0}'", rsc.dwType.ToString()));
Log(String.Format(" dwDisplayType: '{0}'", rsc.dwDisplayType.ToString()));
Log(String.Format(" dwUsage: '{0}'", rsc.dwUsage.ToString()));
Log("");
}
private static void Log(String text)
{
if (text == "")
File.AppendAllText(_path, Environment.NewLine);
else
File.AppendAllText(_path, String.Format("Recursion {0}: {1}" + Environment.NewLine, _recursionLevel, text));
}
}
}