using System; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke { public static partial class Shell32 { /// Describes how a property should be treated. [PInvokeData("Shtypes.h")] [Flags] public enum SHCOLSTATE { /// The value is displayed according to default settings for the column. SHCOLSTATE_DEFAULT = 0x00000000, /// The value is displayed as a string. SHCOLSTATE_TYPE_STR = 0x00000001, /// The value is displayed as an integer. SHCOLSTATE_TYPE_INT = 0x00000002, /// The value is displayed as a date/time. SHCOLSTATE_TYPE_DATE = 0x00000003, /// A mask for display type values SHCOLSTATE_TYPE_STR, SHCOLSTATE_TYPE_STR, and SHCOLSTATE_TYPE_DATE. SHCOLSTATE_TYPEMASK = 0x0000000f, /// The column should be on by default in Details view. SHCOLSTATE_ONBYDEFAULT = 0x00000010, /// Will be slow to compute. Perform on a background thread. SHCOLSTATE_SLOW = 0x00000020, /// Provided by a handler, not the folder. SHCOLSTATE_EXTENDED = 0x00000040, /// Not displayed in the context menu, but is listed in the More... dialog. SHCOLSTATE_SECONDARYUI = 0x00000080, /// Not displayed in the UI. SHCOLSTATE_HIDDEN = 0x00000100, /// VarCmp produces same result as IShellFolder::CompareIDs. SHCOLSTATE_PREFER_VARCMP = 0x00000200, /// PSFormatForDisplay produces same result as IShellFolder::CompareIDs. SHCOLSTATE_PREFER_FMTCMP = 0x00000400, /// Do not sort folders separately. SHCOLSTATE_NOSORTBYFOLDERNESS = 0x00000800, /// Only displayed in the UI. SHCOLSTATE_VIEWONLY = 0x00010000, /// Marks columns with values that should be read in a batch. SHCOLSTATE_BATCHREAD = 0x00020000, /// Grouping is disabled for this column. SHCOLSTATE_NO_GROUPBY = 0x00040000, /// Can't resize the column. SHCOLSTATE_FIXED_WIDTH = 0x00001000, /// The width is the same in all dpi. SHCOLSTATE_NODPISCALE = 0x00002000, /// Fixed width and height ratio. SHCOLSTATE_FIXED_RATIO = 0x00004000, /// Filters out new display flags. SHCOLSTATE_DISPLAYMASK = 0x0000F000, } /// A value that specifies the desired format of the string. [PInvokeData("Shtypes.h", MSDNShortId = "bb759820")] public enum STRRET_TYPE : uint { /// The string is at the address specified by pOleStr member. STRRET_WSTR = 0x0000, /// /// The uOffset member value indicates the number of bytes from the beginning of the item identifier list where the string is located. /// STRRET_OFFSET = 0x0001, /// The string is returned in the cStr member. STRRET_CSTR = 0x0002, } /// Contains a list of item identifiers. [StructLayout(LayoutKind.Sequential)] [PInvokeData("Shtypes.h", MSDNShortId = "bb773321")] public struct ITEMIDLIST { /// A list of item identifiers. public SHITEMID mkid; } /// Reports detailed information on an item in a Shell folder. [StructLayout(LayoutKind.Sequential)] [PInvokeData("Shtypes.h", MSDNShortId = "bb759781")] public struct SHELLDETAILS { /// The alignment of the column heading and the subitem text in the column. public ComCtl32.ListViewColumnFormat fmt; /// he number of average-sized characters in the header. public int cxChar; /// /// An STRRET structure that includes a string with the requested information. To convert this structure to a string, use /// StrRetToBuf or StrRetToStr. /// public STRRET str; } /// Defines an item identifier. [StructLayout(LayoutKind.Sequential)] [PInvokeData("Shtypes.h", MSDNShortId = "bb759800")] public struct SHITEMID { /// The size of identifier, in bytes, including itself. public ushort cb; /// A variable-length item identifier. public byte[] abID; } /// Contains strings returned from the IShellFolder interface methods. [StructLayout(LayoutKind.Explicit, Size = 264)] [PInvokeData("Shtypes.h", MSDNShortId = "bb759820")] public struct STRRET { /// A value that specifies the desired format of the string. [FieldOffset(0)] public STRRET_TYPE uType; /// /// 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. /// [FieldOffset(4), MarshalAs(UnmanagedType.BStr)] public StrPtrUni pOleStr; // must be freed by caller of GetDisplayNameOf /// The offset into the item identifier list. [FieldOffset(4)] public uint uOffset; // Offset into SHITEMID /// The buffer to receive the display name. CHAR[MAX_PATH] [FieldOffset(4), MarshalAs(UnmanagedType.LPStr, SizeConst = Kernel32.MAX_PATH)] public string cStr; // Buffer to fill in (ANSI) /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => uType == STRRET_TYPE.STRRET_CSTR ? cStr : (uType == STRRET_TYPE.STRRET_WSTR ? pOleStr.ToString() : string.Empty); } internal class STRRETMarshaler : ICustomMarshaler { public static ICustomMarshaler GetInstance(string cookie) => new STRRETMarshaler(); public void CleanUpManagedData(object ManagedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return; pNativeData.ToStructure().pOleStr.Free(); Marshal.FreeCoTaskMem(pNativeData); } public int GetNativeDataSize() => Marshal.SizeOf(typeof(STRRET)); public IntPtr MarshalManagedToNative(object ManagedObj) { if (!(ManagedObj is string s)) throw new InvalidCastException(); var sr = new STRRET { uType = STRRET_TYPE.STRRET_WSTR }; sr.pOleStr.Assign(s); return sr.StructureToPtr(Marshal.AllocCoTaskMem, out var _); } public object MarshalNativeToManaged(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return null; var sr = pNativeData.ToStructure(); var s = sr.ToString().Clone() as string; if (sr.uType == STRRET_TYPE.STRRET_WSTR) sr.pOleStr.Free(); return s; } } } }