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