It works for me on Windows 10 22H2 with INamespaceWalk
Test with a phone (WPD), depth = 4 =>
public enum HRESULT : int
{
S_OK = 0,
S_FALSE = 1,
E_NOINTERFACE = unchecked((int)0x80004002),
E_NOTIMPL = unchecked((int)0x80004001),
E_FAIL = unchecked((int)0x80004005),
E_UNEXPECTED = unchecked((int)0x8000FFFF),
E_OUTOFMEMORY = unchecked((int)0x8007000E)
}
[ComImportAttribute()]
[GuidAttribute("d92995f8-cf5e-4a76-bf59-ead39ea2b97e")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface INamespaceWalkCB
{
void FoundItem([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl);
void EnterFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl);
void LeaveFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl);
void InitializeProgressDialog(StringBuilder ppszTitle, StringBuilder ppszCancel);
}
[ComImportAttribute()]
[GuidAttribute("7ac7492b-c38e-438a-87db-68737844ff70")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface INamespaceWalkCB2 : INamespaceWalkCB
{
#region INamespaceWalkCB
new void FoundItem([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl);
new void EnterFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl);
new void LeaveFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl);
new void InitializeProgressDialog(StringBuilder ppszTitle, StringBuilder ppszCancel);
#endregion
void WalkComplete(HRESULT hr);
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214E6-0000-0000-C000-000000000046")]
public interface IShellFolder
{
HRESULT ParseDisplayName(IntPtr hwnd,
// IBindCtx pbc,
IntPtr pbc,
[MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
HRESULT BindToObject(IntPtr pidl,
//IBindCtx pbc,
IntPtr pbc,
[In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
//HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
// [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, ref IntPtr apidl, [In] ref Guid riid, [In, Out] ref uint rgfReserved, out IntPtr ppv);
HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
}
[Flags]
public enum SHCONTF : ushort
{
SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
SHCONTF_FOLDERS = 0x0020,
SHCONTF_NONFOLDERS = 0x0040,
SHCONTF_INCLUDEHIDDEN = 0x0080,
SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
SHCONTF_NETPRINTERSRCH = 0x0200,
SHCONTF_SHAREABLE = 0x0400,
SHCONTF_STORAGE = 0x0800,
SHCONTF_NAVIGATION_ENUM = 0x1000,
SHCONTF_FASTITEMS = 0x2000,
SHCONTF_FLATLIST = 0x4000,
SHCONTF_ENABLE_ASYNC = 0x8000
}
[Flags]
public enum SFGAO : uint
{
CANCOPY = 0x00000001,
CANMOVE = 0x00000002,
CANLINK = 0x00000004,
STORAGE = 0x00000008,
CANRENAME = 0x00000010,
CANDELETE = 0x00000020,
HASPROPSHEET = 0x00000040,
DROPTARGET = 0x00000100,
CAPABILITYMASK = 0x00000177,
ENCRYPTED = 0x00002000,
ISSLOW = 0x00004000,
GHOSTED = 0x00008000,
LINK = 0x00010000,
SHARE = 0x00020000,
READONLY = 0x00040000,
HIDDEN = 0x00080000,
DISPLAYATTRMASK = 0x000FC000,
STREAM = 0x00400000,
STORAGEANCESTOR = 0x00800000,
VALIDATE = 0x01000000,
REMOVABLE = 0x02000000,
COMPRESSED = 0x04000000,
BROWSABLE = 0x08000000,
FILESYSANCESTOR = 0x10000000,
FOLDER = 0x20000000,
FILESYSTEM = 0x40000000,
HASSUBFOLDER = 0x80000000,
CONTENTSMASK = 0x80000000,
STORAGECAPMASK = 0x70C50008,
PKEYSFGAOMASK = 0x81044000
}
public enum SHGDNF
{
SHGDN_NORMAL = 0,
SHGDN_INFOLDER = 0x1,
SHGDN_FOREDITING = 0x1000,
SHGDN_FORADDRESSBAR = 0x4000,
SHGDN_FORPARSING = 0x8000
}
[StructLayout(LayoutKind.Explicit, Size = 264)]
public struct STRRET
{
[FieldOffset(0)]
//One of the STRRET_* values
public uint uType;
[FieldOffset(4)]
//must be freed by caller of GetDisplayNameOf
public IntPtr pOleStr;
// <FieldOffset(4)> Public pStr As IntPtr 'NOT USED
[FieldOffset(4)]
//Offset into SHITEMID
public uint uOffset;
[FieldOffset(4)]
//Buffer to fill in (ANSI)
public IntPtr cString;
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F2-0000-0000-C000-000000000046")]
public interface IEnumIDList
{
[PreserveSig()]
HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched);
[PreserveSig()]
HRESULT Skip(uint celt);
void Reset();
[return: MarshalAs(UnmanagedType.Interface)]
IEnumIDList Clone();
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("57ced8a7-3f4a-432c-9350-30f24483f74f")]
public interface INamespaceWalk
{
HRESULT Walk(IntPtr punkToWalk, int dwFlags, int cDepth, [MarshalAs(UnmanagedType.Interface)] INamespaceWalkCB pnswcb);
HRESULT GetIDArrayResult(out uint pcItems, out IntPtr prgpidl);
}
public enum NAMESPACEWALKFLAG
{
NSWF_DEFAULT = 0,
NSWF_NONE_IMPLIES_ALL = 0x1,
NSWF_ONE_IMPLIES_ALL = 0x2,
NSWF_DONT_TRAVERSE_LINKS = 0x4,
NSWF_DONT_ACCUMULATE_RESULT = 0x8,
NSWF_TRAVERSE_STREAM_JUNCTIONS = 0x10,
NSWF_FILESYSTEM_ONLY = 0x20,
NSWF_SHOW_PROGRESS = 0x40,
NSWF_FLAG_VIEWORDER = 0x80,
NSWF_IGNORE_AUTOPLAY_HIDA = 0x100,
NSWF_ASYNC = 0x200,
NSWF_DONT_RESOLVE_LINKS = 0x400,
NSWF_ACCUMULATE_FOLDERS = 0x800,
NSWF_DONT_SORT = 0x1000,
NSWF_USE_TRANSFER_MEDIUM = 0x2000,
NSWF_DONT_TRAVERSE_STREAM_JUNCTIONS = 0x4000,
NSWF_ANY_IMPLIES_ALL = 0x8000
};
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
public interface IShellItem
{
[PreserveSig()]
HRESULT BindToHandler(IntPtr pbc, ref Guid bhid, ref Guid riid, ref IntPtr ppv);
HRESULT GetParent(ref IShellItem ppsi);
HRESULT GetDisplayName(SIGDN sigdnName, ref System.Text.StringBuilder ppszName);
HRESULT GetAttributes(uint sfgaoMask, ref uint psfgaoAttribs);
HRESULT Compare(IShellItem psi, uint hint, ref int piOrder);
}
public enum SIGDN : int
{
SIGDN_NORMALDISPLAY = 0x0,
SIGDN_PARENTRELATIVEPARSING = unchecked((int)0x80018001),
SIGDN_DESKTOPABSOLUTEPARSING = unchecked((int)0x80028000),
SIGDN_PARENTRELATIVEEDITING = unchecked((int)0x80031001),
SIGDN_DESKTOPABSOLUTEEDITING = unchecked((int)0x8004C000),
SIGDN_FILESYSPATH = unchecked((int)0x80058000),
SIGDN_URL = unchecked((int)0x80068000),
SIGDN_PARENTRELATIVEFORADDRESSBAR = unchecked((int)0x8007C001),
SIGDN_PARENTRELATIVE = unchecked((int)0x80080001)
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
// WPD
NamespaceWalk nw = new NamespaceWalk("shell:::{35786D3C-B075-49b9-88DD-029876E11C01}", 4);
}
}
public class NamespaceWalk : INamespaceWalkCB2
{
[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern HRESULT SHCreateItemFromParsingName(string pszPath, IntPtr pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv);
[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern HRESULT StrRetToBuf(ref STRRET pstr, IntPtr pidl, StringBuilder pszBuf, [MarshalAs(UnmanagedType.U4)] uint cchBuf);
private static Guid CLSID_NamespaceWalker = new Guid("72eb61e0-8672-4303-9175-f2e4c68b2e7c");
public NamespaceWalk(string sPath, int nDepth = 5)
{
Type NamespaceWalkerType = Type.GetTypeFromCLSID(CLSID_NamespaceWalker, true);
object oNamespaceWalk = Activator.CreateInstance(NamespaceWalkerType);
INamespaceWalk pNamespaceWalk = (INamespaceWalk)oNamespaceWalk;
if (pNamespaceWalk != null)
{
IShellItem pShellItem = null;
HRESULT hr = SHCreateItemFromParsingName(sPath, IntPtr.Zero, typeof(IShellItem).GUID, out pShellItem);
if (hr == HRESULT.S_OK)
{
IntPtr pUnk = Marshal.GetIUnknownForObject(pShellItem);
hr = pNamespaceWalk.Walk(pUnk, (int)(NAMESPACEWALKFLAG.NSWF_DONT_TRAVERSE_LINKS | NAMESPACEWALKFLAG.NSWF_DONT_ACCUMULATE_RESULT), nDepth, this);
}
}
}
string sIndent = "";
void INamespaceWalkCB.EnterFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl)
{
STRRET strretFolderName;
HRESULT hr = psf.GetDisplayNameOf(pidl, SHGDNF.SHGDN_NORMAL, out strretFolderName);
string sDisplayName = null;
StringBuilder sbDisplayName = default(StringBuilder);
sbDisplayName = new StringBuilder(256);
StrRetToBuf(ref strretFolderName, pidl, sbDisplayName, (uint)sbDisplayName.Capacity);
sDisplayName = sbDisplayName.ToString();
Console.WriteLine("{0}Folder : {1}", sIndent, sDisplayName);
sIndent += "-";
}
void INamespaceWalkCB2.EnterFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl)
{
}
void INamespaceWalkCB.FoundItem([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl)
{
STRRET strretFolderName;
HRESULT hr = psf.GetDisplayNameOf(pidl, SHGDNF.SHGDN_FOREDITING , out strretFolderName);
string sDisplayName = null;
StringBuilder sbDisplayName = default(StringBuilder);
sbDisplayName = new StringBuilder(256);
StrRetToBuf(ref strretFolderName, pidl, sbDisplayName, (uint)sbDisplayName.Capacity);
sDisplayName = sbDisplayName.ToString();
Console.WriteLine("{0}Item : {1}", sIndent, sDisplayName);
}
void INamespaceWalkCB2.FoundItem([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl)
{
}
void INamespaceWalkCB.InitializeProgressDialog(StringBuilder ppszTitle, StringBuilder ppszCancel)
{
}
void INamespaceWalkCB2.InitializeProgressDialog(StringBuilder ppszTitle, StringBuilder ppszCancel)
{
}
void INamespaceWalkCB.LeaveFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl)
{
STRRET strretFolderName;
HRESULT hr = psf.GetDisplayNameOf(pidl, SHGDNF.SHGDN_FOREDITING, out strretFolderName);
string sDisplayName = null;
StringBuilder sbDisplayName = default(StringBuilder);
sbDisplayName = new StringBuilder(256);
StrRetToBuf(ref strretFolderName, pidl, sbDisplayName, (uint)sbDisplayName.Capacity);
sIndent = sIndent.Substring(0, sIndent.Length - 1);
sDisplayName = sbDisplayName.ToString();
}
void INamespaceWalkCB2.LeaveFolder([MarshalAs(UnmanagedType.Interface)] IShellFolder psf, IntPtr pidl)
{
}
void INamespaceWalkCB2.WalkComplete(HRESULT hr)
{
}
}