Vanara/PInvoke/Shell32/ShObjIdl.ShellUtil.cs

104 lines
3.8 KiB
C#

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
using System.Text;
namespace Vanara.PInvoke
{
public static partial class Shell32
{
/// <remarks>Methods in this class will only work on Vista and above.</remarks>
public static class ShellUtil
{
/// <summary>Gets the KNOWNFOLDERID enum from a KNOWNFOLDERID Guid.</summary>
/// <param name="knownFolder">The KNOWNFOLDERID Guid.</param>
/// <returns>The KNOWNFOLDERID enum.</returns>
public static KNOWNFOLDERID GetKnownFolderFromGuid(Guid knownFolder) =>
Enum.GetValues(typeof(KNOWNFOLDERID)).Cast<KNOWNFOLDERID>().Single(k => k.Guid() == knownFolder);
/// <summary>Gets the KNOWNFOLDERID enum from a path.</summary>
/// <param name="path">The folder path.</param>
/// <returns>The KNOWNFOLDERID enum.</returns>
public static KNOWNFOLDERID GetKnownFolderFromPath(string path)
{
if (Environment.OSVersion.Version.Major < 6)
return Enum.GetValues(typeof(KNOWNFOLDERID)).Cast<KNOWNFOLDERID>().Single(k => string.Equals(k.FullPath(), path, StringComparison.InvariantCultureIgnoreCase));
var ikfm = new IKnownFolderManager();
return GetKnownFolderFromGuid(ikfm.FindFolderFromPath(path, FFFP_MODE.FFFP_EXACTMATCH).GetId());
}
/// <summary>Gets the path for a KNOWNFOLDERID Guid.</summary>
/// <param name="knownFolder">The KNOWNFOLDERID Guid.</param>
/// <returns>The file system path.</returns>
[SecurityCritical]
public static string GetPathForKnownFolder(Guid knownFolder)
{
if (knownFolder == default)
return null;
var pathBuilder = new StringBuilder(260);
if (SHGetFolderPathEx(knownFolder, 0, HTOKEN.NULL, pathBuilder, (uint)pathBuilder.Capacity).Failed)
return null;
return pathBuilder.ToString();
}
/// <summary>Gets the path from shell item.</summary>
/// <param name="item">The shell item.</param>
/// <returns>The file system path.</returns>
[SecurityCritical]
public static string GetPathFromShellItem(IShellItem item) => item.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEEDITING);
/// <summary>Gets the shell item for a file system path.</summary>
/// <returns>The file system path.</returns>
/// <returns>The corresponding IShellItem.</returns>
[SecurityCritical]
public static IShellItem GetShellItemForPath(string path)
{
if (string.IsNullOrEmpty(path))
return null;
var hr = SHCreateItemFromParsingName(path, null, typeof(IShellItem).GUID, out var unk);
if (hr == 0x80070002)
{
Ole32.CreateBindCtx(0, out var ibc).ThrowIfFailed();
using (var _ibc = new InteropServices.ComReleaser<IBindCtx>(ibc))
{
var bd = new IntFileSysBindData();
ibc.RegisterObjectParam(STR_FILE_SYS_BIND_DATA, bd);
hr = SHCreateItemFromParsingName(path, ibc, typeof(IShellItem).GUID, out unk);
}
}
hr.ThrowIfFailed();
return (IShellItem)unk;
}
[ComVisible(true)]
private class IntFileSysBindData : IFileSystemBindData2
{
private static readonly Guid CLSID_UnknownJunction = new Guid("{fc0a77e6-9d70-4258-9783-6dab1d0fe31e}");
private Guid clsidJunction;
private WIN32_FIND_DATA fd;
private long fileId;
public IntFileSysBindData()
{
}
public long GetFileID() => fileId;
public void GetFindData(out WIN32_FIND_DATA pfd) => pfd = fd;
[return: MarshalAs(UnmanagedType.LPStruct)]
public Guid GetJunctionCLSID() => clsidJunction != CLSID_UnknownJunction ? clsidJunction : throw new COMException("Unable to handle junctions", unchecked((int)HRESULT.E_FAIL));
public void SetFileID(long liFileID) => fileId = liFileID;
public void SetFindData(in WIN32_FIND_DATA pfd) => fd = pfd;
public void SetJunctionCLSID(in Guid clsid) => clsidJunction = clsid;
}
}
}
}