mirror of https://github.com/dahall/Vanara.git
Compare commits
2 Commits
94fdd98d31
...
831d40e2e5
Author | SHA1 | Date |
---|---|---|
David Hall | 831d40e2e5 | |
David Hall | 7d03749a4c |
|
@ -2,6 +2,7 @@
|
|||
using System.Linq;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Security;
|
||||
using System.Windows;
|
||||
using static Vanara.PInvoke.Ole32;
|
||||
|
||||
namespace Vanara.PInvoke;
|
||||
|
@ -2330,7 +2331,11 @@ public static partial class Shell32
|
|||
/// </remarks>
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellfolder-getdisplaynameof HRESULT
|
||||
// GetDisplayNameOf( PCUITEMID_CHILD pidl, SHGDNF uFlags, STRRET *pName );
|
||||
public static string? GetDisplayNameOf(this IShellFolder sf, SHGDNF uFlags, PIDL pidl) { sf.GetDisplayNameOf(pidl ?? PIDL.Null, uFlags, out var p); return p; }
|
||||
public static string? GetDisplayNameOf(this IShellFolder sf, SHGDNF uFlags, PIDL pidl)
|
||||
{
|
||||
sf.GetDisplayNameOf(pidl ?? PIDL.Null, uFlags, out var p);
|
||||
return ShlwApi.StrRetToBSTR(new PinnedObject(p), default, out var str).Succeeded ? str : null;
|
||||
}
|
||||
|
||||
/// <summary>Extension method to simplify using the <see cref="IShellFolder.GetUIObjectOf"/> method.</summary>
|
||||
/// <typeparam name="T">Type of the interface to get.</typeparam>
|
||||
|
|
|
@ -126,34 +126,69 @@ public static partial class Shell32
|
|||
}
|
||||
|
||||
/// <summary>Contains strings returned from the IShellFolder interface methods.</summary>
|
||||
[StructLayout(LayoutKind.Explicit, Size = 264)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[PInvokeData("Shtypes.h", MSDNShortId = "bb759820")]
|
||||
public struct STRRET
|
||||
{
|
||||
const int strlenbuf = 260;
|
||||
|
||||
/// <summary>A value that specifies the desired format of the string.</summary>
|
||||
[FieldOffset(0)]
|
||||
public STRRET_TYPE uType;
|
||||
|
||||
private DUMMYUNIONNAME union;
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the string. This memory must be allocated with CoTaskMemAlloc. It is the calling application's responsibility to
|
||||
/// free this memory with CoTaskMemFree when it is no longer needed.
|
||||
/// </summary>
|
||||
[FieldOffset(4)]
|
||||
public StrPtrUni pOleStr; // must be freed by caller of GetDisplayNameOf
|
||||
public StrPtrUni pOleStr => union.pOleStr; // must be freed by caller of GetDisplayNameOf
|
||||
|
||||
/// <summary>The offset into the item identifier list.</summary>
|
||||
[FieldOffset(4)]
|
||||
public uint uOffset; // Offset into SHITEMID
|
||||
public uint uOffset => union.uOffset; // Offset into SHITEMID
|
||||
|
||||
/// <summary>The buffer to receive the display name. CHAR[MAX_PATH]</summary>
|
||||
[FieldOffset(4)]
|
||||
public StrPtrAnsi cStr;
|
||||
public string? cStr => uType == STRRET_TYPE.STRRET_CSTR ? union.cStr : null;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="STRRET"/> struct.</summary>
|
||||
/// <param name="lpstr">The initial string.</param>
|
||||
public STRRET(string? lpstr)
|
||||
{
|
||||
uType = STRRET_TYPE.STRRET_WSTR;
|
||||
union.pOleStr = Marshal.StringToCoTaskMemUni(lpstr);
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="STRRET" /> struct.</summary>
|
||||
/// <param name="offset">The offset into the item identifier list.</param>
|
||||
public STRRET(uint offset)
|
||||
{
|
||||
uType = STRRET_TYPE.STRRET_OFFSET;
|
||||
union.uOffset = offset;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = strlenbuf)]
|
||||
private struct DUMMYUNIONNAME
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public StrPtrUni pOleStr;
|
||||
[FieldOffset(0)]
|
||||
public uint uOffset;
|
||||
[FieldOffset(0)]
|
||||
public StrPtrAnsi cStr;
|
||||
}
|
||||
|
||||
/// <summary>Performs an implicit conversion from <see cref="STRRET"/> to <see cref="System.String"/>.</summary>
|
||||
/// <param name="s">The <see cref="STRRET"/> instance.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator string?(in STRRET s) =>
|
||||
ShlwApi.StrRetToBSTR(new PinnedObject(s), default, out var ret).Succeeded ? ret : null;
|
||||
public static implicit operator string?(in STRRET s) => s.uType switch
|
||||
{
|
||||
STRRET_TYPE.STRRET_OFFSET => ShlwApi.StrRetToBSTR(new PinnedObject(s), default, out var ret).Succeeded ? ret : null,
|
||||
STRRET_TYPE.STRRET_WSTR => s.pOleStr.ToString(),
|
||||
STRRET_TYPE.STRRET_CSTR => s.cStr,
|
||||
_ => throw new ArgumentException("Invalid STRRET type", nameof(s)),
|
||||
};
|
||||
|
||||
/// <summary>Frees any memory associated with this instance.</summary>
|
||||
public void Free() { if (uType == STRRET_TYPE.STRRET_WSTR) { Marshal.FreeCoTaskMem((IntPtr)union.pOleStr); union.pOleStr = IntPtr.Zero; } }
|
||||
|
||||
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
|
||||
/// <returns>A <see cref="string"/> that represents this instance.</returns>
|
||||
|
@ -180,8 +215,7 @@ public static partial class Shell32
|
|||
public IntPtr MarshalManagedToNative(object ManagedObj)
|
||||
{
|
||||
if (ManagedObj is not string s) throw new InvalidCastException();
|
||||
var sr = new STRRET { uType = STRRET_TYPE.STRRET_WSTR };
|
||||
sr.pOleStr.Assign(s);
|
||||
var sr = new STRRET(s);
|
||||
return sr.MarshalToPtr(Marshal.AllocCoTaskMem, out var _);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using NUnit.Framework;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using static Vanara.PInvoke.Shell32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests;
|
||||
|
||||
|
@ -32,4 +33,21 @@ public class BlitTests
|
|||
}
|
||||
Assert.That(allGood);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StrRetTest()
|
||||
{
|
||||
var s1 = new string('c', 300);
|
||||
var sr = new STRRET(s1);
|
||||
Assert.That(sr.uType, Is.EqualTo(STRRET_TYPE.STRRET_WSTR));
|
||||
Assert.That(sr.ToString(), Is.EqualTo(s1));
|
||||
Assert.That((string?)sr.pOleStr, Is.EqualTo(s1));
|
||||
Assert.That(() => sr.Free(), Throws.Nothing);
|
||||
Assert.That((IntPtr)sr.pOleStr, Is.EqualTo(IntPtr.Zero));
|
||||
|
||||
sr = new STRRET(s1);
|
||||
ShlwApi.StrRetToBSTR(new PinnedObject(sr), default, out var ret).ThrowIfFailed();
|
||||
Assert.That(ret, Is.EqualTo(s1));
|
||||
//Assert.That((IntPtr)sr.pOleStr, Is.EqualTo(IntPtr.Zero));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue