2021-03-31 16:42:58 -05:00
|
|
|
// Decompiled with JetBrains decompiler
|
|
|
|
|
// Type: Microsoft.Iris.CodeModel.Cpp.DllProxyObject
|
|
|
|
|
// Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
|
|
|
|
|
// MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11
|
|
|
|
|
// Assembly location: C:\Program Files\Zune\UIX.dll
|
|
|
|
|
|
|
|
|
|
using Microsoft.Iris.Library;
|
|
|
|
|
using Microsoft.Iris.Markup;
|
|
|
|
|
using Microsoft.Iris.OS;
|
|
|
|
|
using Microsoft.Iris.RenderAPI;
|
|
|
|
|
using Microsoft.Iris.Session;
|
|
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.Iris.CodeModel.Cpp
|
|
|
|
|
{
|
|
|
|
|
internal class DllProxyObject : NotifyObjectBase, ISchemaInfo, IDisposableObject
|
|
|
|
|
{
|
|
|
|
|
private IntPtr _nativeObject;
|
|
|
|
|
private ulong _handle;
|
|
|
|
|
private DllTypeSchemaBase _type;
|
|
|
|
|
private static object s_finalizeLock = new object();
|
|
|
|
|
private static bool s_pendingAppThreadRelease = false;
|
|
|
|
|
private static Vector<DllProxyObject.AppThreadReleaseEntry> s_pendingReleases;
|
2021-03-31 17:20:20 -05:00
|
|
|
private static SimpleCallback s_releaseOnAppThread = new SimpleCallback(ReleaseFinalizedObjects);
|
2021-03-31 16:42:58 -05:00
|
|
|
private static DllProxyObjectHandleTable s_handleTable;
|
|
|
|
|
|
2021-03-31 17:20:20 -05:00
|
|
|
public static void CreateHandleTable() => s_handleTable = new DllProxyObjectHandleTable();
|
2021-03-31 16:42:58 -05:00
|
|
|
|
|
|
|
|
public static void ReleaseOutstandingProxies()
|
|
|
|
|
{
|
2021-03-31 17:20:20 -05:00
|
|
|
s_pendingAppThreadRelease = true;
|
2021-03-31 16:42:58 -05:00
|
|
|
GC.Collect();
|
|
|
|
|
GC.WaitForPendingFinalizers();
|
2021-03-31 17:15:06 -05:00
|
|
|
foreach (IDisposableObject disposableObject in s_handleTable)
|
|
|
|
|
disposableObject.Dispose(disposableObject);
|
2021-03-31 17:20:20 -05:00
|
|
|
ReleaseFinalizedObjects();
|
2021-03-31 16:42:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static DllProxyObject Wrap(IntPtr nativeObject)
|
|
|
|
|
{
|
2021-03-31 17:15:06 -05:00
|
|
|
DllProxyObject dllProxyObject = null;
|
2021-03-31 16:42:58 -05:00
|
|
|
uint typeID;
|
|
|
|
|
if (!NativeApi.SUCCEEDED(NativeApi.SpGetTypeID(nativeObject, out typeID)))
|
2021-03-31 17:15:06 -05:00
|
|
|
return null;
|
2021-03-31 16:42:58 -05:00
|
|
|
TypeSchema type = DllLoadResult.MapType(typeID);
|
|
|
|
|
if (type != null)
|
|
|
|
|
{
|
2021-03-31 17:20:20 -05:00
|
|
|
dllProxyObject = GetExistingProxy(nativeObject) ?? WrapNewObject(nativeObject, type);
|
2021-03-31 16:42:58 -05:00
|
|
|
NativeApi.SpReleaseExternalObject(nativeObject);
|
|
|
|
|
}
|
|
|
|
|
return dllProxyObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static DllProxyObject GetExistingProxy(IntPtr nativeObject)
|
|
|
|
|
{
|
2021-03-31 17:15:06 -05:00
|
|
|
DllProxyObject dllProxyObject = null;
|
2021-03-31 16:42:58 -05:00
|
|
|
ulong state;
|
|
|
|
|
NativeApi.SpGetStateCache(nativeObject, out state);
|
2021-03-31 17:20:20 -05:00
|
|
|
if (state != 0UL && !s_handleTable.LookupByHandle(state, out dllProxyObject))
|
2021-03-31 16:42:58 -05:00
|
|
|
ErrorManager.ReportError("IUIXObject::GetStateCache retrieved unexpected value");
|
|
|
|
|
return dllProxyObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static DllProxyObject WrapNewObject(IntPtr nativeObject, TypeSchema type)
|
|
|
|
|
{
|
2021-03-31 17:15:06 -05:00
|
|
|
DllProxyObject dllProxyObject = null;
|
2021-03-31 16:42:58 -05:00
|
|
|
uint marshalAs;
|
|
|
|
|
IntPtr nativeImpl;
|
2021-03-31 17:20:20 -05:00
|
|
|
if (DetermineProxyInterfaceForObject(nativeObject, type, out marshalAs, out nativeImpl))
|
2021-03-31 16:42:58 -05:00
|
|
|
{
|
|
|
|
|
switch (marshalAs)
|
|
|
|
|
{
|
|
|
|
|
case 4294967281:
|
|
|
|
|
case 4294967286:
|
|
|
|
|
case 4294967287:
|
|
|
|
|
case 4294967288:
|
|
|
|
|
case 4294967289:
|
|
|
|
|
case 4294967290:
|
|
|
|
|
case 4294967291:
|
|
|
|
|
dllProxyObject = new DllProxyObject();
|
|
|
|
|
break;
|
|
|
|
|
case 4294967285:
|
2021-03-31 17:15:06 -05:00
|
|
|
dllProxyObject = new DllProxyList();
|
2021-03-31 16:42:58 -05:00
|
|
|
break;
|
|
|
|
|
case uint.MaxValue:
|
|
|
|
|
dllProxyObject = new DllProxyObject();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
dllProxyObject = new DllProxyObject();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
dllProxyObject.Load(nativeObject, nativeImpl, (DllTypeSchemaBase)type);
|
|
|
|
|
}
|
|
|
|
|
return dllProxyObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool DetermineProxyInterfaceForObject(
|
|
|
|
|
IntPtr nativeObject,
|
|
|
|
|
TypeSchema type,
|
|
|
|
|
out uint marshalAs,
|
|
|
|
|
out IntPtr nativeImpl)
|
|
|
|
|
{
|
|
|
|
|
bool flag = false;
|
|
|
|
|
DllTypeSchemaBase dllTypeSchemaBase = (DllTypeSchemaBase)type;
|
|
|
|
|
marshalAs = dllTypeSchemaBase.MarshalAs;
|
|
|
|
|
if (marshalAs == uint.MaxValue)
|
|
|
|
|
{
|
|
|
|
|
flag = true;
|
|
|
|
|
nativeImpl = IntPtr.Zero;
|
|
|
|
|
}
|
2021-03-31 17:20:20 -05:00
|
|
|
else if (CheckNativeReturn(NativeApi.SpQueryForMarshalAsInterface(nativeObject, marshalAs, out nativeImpl)) && nativeImpl != IntPtr.Zero)
|
2021-03-31 16:42:58 -05:00
|
|
|
flag = true;
|
|
|
|
|
else
|
2021-03-31 17:15:06 -05:00
|
|
|
ErrorManager.ReportError("Object didn't implement expected interface '{0}'", marshalAs);
|
2021-03-31 16:42:58 -05:00
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected DllProxyObject() => this._handle = 0UL;
|
|
|
|
|
|
2021-03-31 17:20:20 -05:00
|
|
|
~DllProxyObject() => RegisterAppThreadRelease(new DllProxyObject.AppThreadReleaseEntry(this._nativeObject, this._handle, this.OwningLoadResult));
|
2021-03-31 16:42:58 -05:00
|
|
|
|
|
|
|
|
protected static void RegisterAppThreadRelease(DllProxyObject.AppThreadReleaseEntry entry)
|
|
|
|
|
{
|
2021-03-31 17:20:20 -05:00
|
|
|
lock (s_finalizeLock)
|
2021-03-31 16:42:58 -05:00
|
|
|
{
|
2021-03-31 17:20:20 -05:00
|
|
|
if (s_pendingReleases == null)
|
|
|
|
|
s_pendingReleases = new Vector<DllProxyObject.AppThreadReleaseEntry>();
|
|
|
|
|
s_pendingReleases.Add(entry);
|
|
|
|
|
if (s_pendingAppThreadRelease)
|
2021-03-31 16:42:58 -05:00
|
|
|
return;
|
2021-03-31 17:20:20 -05:00
|
|
|
s_pendingAppThreadRelease = true;
|
|
|
|
|
DeferredCall.Post(DispatchPriority.Idle, s_releaseOnAppThread);
|
2021-03-31 16:42:58 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Load(IntPtr nativeObject, IntPtr marshalAs, DllTypeSchemaBase type)
|
|
|
|
|
{
|
|
|
|
|
this._type = type;
|
|
|
|
|
this._nativeObject = nativeObject;
|
|
|
|
|
this.OwningLoadResult.RegisterProxyUsage();
|
2021-03-31 17:20:20 -05:00
|
|
|
this._handle = s_handleTable.RegisterProxy(this);
|
2021-03-31 16:42:58 -05:00
|
|
|
NativeApi.SpSetStateCache(this._nativeObject, this._handle);
|
|
|
|
|
NativeApi.SpAddRefExternalObject(this._nativeObject);
|
|
|
|
|
this.LoadWorker(nativeObject, marshalAs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void LoadWorker(IntPtr nativeObject, IntPtr nativeMarshalAs)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static HRESULT OnChangeNotification(IntPtr nativeObject, uint id)
|
|
|
|
|
{
|
|
|
|
|
HRESULT hresult = new HRESULT(0);
|
2021-03-31 17:20:20 -05:00
|
|
|
DllProxyObject existingProxy = GetExistingProxy(nativeObject);
|
2021-03-31 16:42:58 -05:00
|
|
|
if (existingProxy != null)
|
|
|
|
|
{
|
2021-03-31 17:15:06 -05:00
|
|
|
string id1 = null;
|
2021-03-31 16:42:58 -05:00
|
|
|
if (existingProxy._type is DllTypeSchema type)
|
|
|
|
|
id1 = type.MapChangeID(id);
|
|
|
|
|
if (id1 != null)
|
|
|
|
|
{
|
|
|
|
|
existingProxy.FireNotification(id1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-03-31 17:15:06 -05:00
|
|
|
ErrorManager.ReportError("Invalid UIXID '0x{0:X8}' passed to NotifyChange", id);
|
2021-03-31 16:42:58 -05:00
|
|
|
hresult = new HRESULT(-2147024809);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return hresult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ulong Handle => this._handle;
|
|
|
|
|
|
|
|
|
|
public IntPtr NativeObject => this._nativeObject;
|
|
|
|
|
|
2021-03-31 17:15:06 -05:00
|
|
|
public TypeSchema TypeSchema => _type;
|
2021-03-31 16:42:58 -05:00
|
|
|
|
|
|
|
|
protected DllLoadResult OwningLoadResult => this._type.Owner as DllLoadResult;
|
|
|
|
|
|
|
|
|
|
private static bool CheckNativeReturn(uint hr) => DllLoadResult.CheckNativeReturn(hr, "IUIXObject");
|
|
|
|
|
|
|
|
|
|
bool IDisposableObject.IsDisposed => this._nativeObject == IntPtr.Zero;
|
|
|
|
|
|
|
|
|
|
void IDisposableObject.DeclareOwner(object owner)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IDisposableObject.TransferOwnership(object owner)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IDisposableObject.Dispose(object owner)
|
|
|
|
|
{
|
|
|
|
|
this.OnDispose();
|
|
|
|
|
new DllProxyObject.AppThreadReleaseEntry(this._nativeObject, this._handle, this.OwningLoadResult).Release();
|
2021-03-31 17:15:06 -05:00
|
|
|
GC.SuppressFinalize(this);
|
2021-03-31 16:42:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void OnDispose()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ReleaseFinalizedObjects()
|
|
|
|
|
{
|
|
|
|
|
Vector<DllProxyObject.AppThreadReleaseEntry> pendingReleases;
|
2021-03-31 17:20:20 -05:00
|
|
|
lock (s_finalizeLock)
|
2021-03-31 16:42:58 -05:00
|
|
|
{
|
2021-03-31 17:20:20 -05:00
|
|
|
pendingReleases = s_pendingReleases;
|
|
|
|
|
s_pendingReleases = null;
|
|
|
|
|
s_pendingAppThreadRelease = false;
|
2021-03-31 16:42:58 -05:00
|
|
|
}
|
|
|
|
|
if (pendingReleases == null || pendingReleases.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
foreach (DllProxyObject.AppThreadReleaseEntry threadReleaseEntry in pendingReleases)
|
|
|
|
|
threadReleaseEntry.Release();
|
2021-03-31 17:20:20 -05:00
|
|
|
lock (s_finalizeLock)
|
2021-03-31 16:42:58 -05:00
|
|
|
{
|
2021-03-31 17:20:20 -05:00
|
|
|
if (s_pendingAppThreadRelease)
|
2021-03-31 16:42:58 -05:00
|
|
|
return;
|
|
|
|
|
pendingReleases.Clear();
|
2021-03-31 17:20:20 -05:00
|
|
|
s_pendingReleases = pendingReleases;
|
2021-03-31 16:42:58 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string DEBUG_FormatIntPtr(IntPtr ptr) => (string)null;
|
|
|
|
|
|
|
|
|
|
public string DEBUG_Description() => string.Empty;
|
|
|
|
|
|
|
|
|
|
public override string ToString() => this._type is DllTypeSchema type ? type.InvokeToString(this) : this.GetType().Name;
|
|
|
|
|
|
|
|
|
|
internal struct AppThreadReleaseEntry
|
|
|
|
|
{
|
|
|
|
|
private bool _releaseHandle;
|
|
|
|
|
public IntPtr _nativeObject;
|
|
|
|
|
public ulong _handle;
|
|
|
|
|
public DllLoadResult _loadResult;
|
|
|
|
|
|
|
|
|
|
public AppThreadReleaseEntry(IntPtr nativeObject, ulong handle, DllLoadResult loadResult)
|
|
|
|
|
{
|
|
|
|
|
this._nativeObject = nativeObject;
|
|
|
|
|
this._handle = handle;
|
|
|
|
|
this._loadResult = loadResult;
|
|
|
|
|
this._releaseHandle = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public AppThreadReleaseEntry(IntPtr nativeObject)
|
|
|
|
|
{
|
|
|
|
|
this._nativeObject = nativeObject;
|
|
|
|
|
this._releaseHandle = false;
|
|
|
|
|
this._handle = 0UL;
|
2021-03-31 17:15:06 -05:00
|
|
|
this._loadResult = null;
|
2021-03-31 16:42:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Release()
|
|
|
|
|
{
|
|
|
|
|
if (this._releaseHandle)
|
|
|
|
|
{
|
2021-03-31 17:20:20 -05:00
|
|
|
s_handleTable.ReleaseProxy(this._handle);
|
2021-03-31 16:42:58 -05:00
|
|
|
ulong state;
|
|
|
|
|
NativeApi.SpGetStateCache(this._nativeObject, out state);
|
|
|
|
|
if ((long)this._handle == (long)state)
|
|
|
|
|
NativeApi.SpSetStateCache(this._nativeObject, 0UL);
|
|
|
|
|
}
|
|
|
|
|
NativeApi.SpReleaseExternalObject(this._nativeObject);
|
|
|
|
|
if (!this._releaseHandle)
|
|
|
|
|
return;
|
|
|
|
|
this._loadResult.UnregisterProxyUsage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|