Files
ZuneShell.dll/ZuneDBApi/MicrosoftZuneInterop/QueryPropertyBag.cs
T
2026-07-12 23:03:52 -05:00

122 lines
4.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
namespace MicrosoftZuneInterop;
// Native COM interface IMultiSortAttributes — vtable layout (x64, IUnknown = slots 02):
// [3] unknown
// [4] GetSortAttributes() -> int* (parallel array of SchemaMap indices)
// [5] GetSortOrders() -> int* (parallel array of EQuerySortType values)
//
// Native struct IDList (16 bytes):
// int Count
// (4 bytes padding)
// int* Ids (heap-allocated array of Count media IDs; freed by the native caller)
public class QueryPropertyBag : IDisposable
{
private IQueryPropertyBag? _bag;
public QueryPropertyBag()
{
// TODO: P/Invoke ZuneLibraryExports.CreatePropertyBag to get an IQueryPropertyBag* pointer,
// then wrap it:
// IntPtr ptr = ...; // from CreatePropertyBag
// _bag = (IQueryPropertyBag)StrategyBasedComWrappers.Instance
// .GetOrCreateObjectForComInstance(ptr, CreateObjectFlags.None);
}
public void SetValue(string propertyName, object? value)
{
EQueryPropertyBagProp prop = MapNameToProp(propertyName);
if (prop == (EQueryPropertyBagProp)(-1) || value is null)
return;
int hr = value switch
{
int i => _bag!.SetInt(prop, i),
bool b => _bag!.SetInt(prop, b ? 1 : 0),
string s => _bag!.SetString(prop, s),
_ => throw new ApplicationException($"Unsupported property value type: {value.GetType()}")
};
if (hr < 0)
throw new ApplicationException($"SetValue failed: HRESULT 0x{hr:X8}");
}
public bool IsSet(string propertyName)
{
EQueryPropertyBagProp prop = MapNameToProp(propertyName);
if (prop == (EQueryPropertyBagProp)(-1))
return false;
_bag!.IsSet(prop, out int result);
return result == 1;
}
public EQueryPropertyBagProp MapNameToProp(string propertyName)
{
// TODO: recover the 37-entry kPropIdMap table from the native binary
// (case-insensitive wchar_t* → EQueryPropertyBagProp, stored as PropIdMapEntry[37]
// at MicrosoftZuneInterop.?A0x52c37a46.kPropIdMap; each entry is 16 bytes:
// [0..7] wchar_t* name, [8..11] EQueryPropertyBagProp id, [12..15] padding)
throw new NotImplementedException();
}
// Returns the underlying COM pointer for callers that pass it to native query APIs.
public IntPtr GetIQueryPropertyBag()
{
if (_bag is null) return IntPtr.Zero;
return StrategyBasedComWrappers.Instance.GetOrCreateComInterfaceForObject(_bag, CreateComInterfaceFlags.None);
}
// Packs multiIds into a native IDList: { int Count; (4 pad); int* Ids }.
// The returned IntPtr points to native heap memory; the native caller is responsible for freeing it.
public unsafe IntPtr PackIDList(IList multiIds)
{
int count = multiIds.Count;
// Allocate the 16-byte IDList struct and zero the Ids pointer slot before filling it,
// so the struct is never in a half-initialized state if AllocHGlobal below throws.
IntPtr listPtr = Marshal.AllocHGlobal(16);
*(int*)listPtr = count;
*(long*)(listPtr + 8) = 0L;
IntPtr idsPtr = Marshal.AllocHGlobal(count * sizeof(int));
*(IntPtr*)(listPtr + 8) = idsPtr;
for (int i = 0; i < count; i++)
*(int*)(idsPtr + i * sizeof(int)) = (int)multiIds[i]!;
return listPtr;
}
// Packs parallel sort-direction/attribute arrays into a native IMultiSortAttributes COM object.
// Requires CSchemaMap.GetIndex to map attribute name strings to schema indices,
// and a native ZuneLibraryExports.CreateMultiSortAttributes factory.
public IntPtr PackMultiSortAttributes(string[] sortStrings, bool[] sortAscendings)
{
throw new NotImplementedException();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
(_bag as IDisposable)?.Dispose();
_bag = null;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~QueryPropertyBag()
{
Dispose(false);
}
}