This commit is contained in:
erik 2025-06-09 02:03:11 +02:00
parent 01151e679b
commit 57b2f0400e
265 changed files with 22828 additions and 6 deletions

View file

@ -0,0 +1,26 @@
using System;
namespace Decal.Adapter;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class BaseEventAttribute : Attribute
{
private string eventName;
private string baseFilter;
public string EventName => eventName;
public string FilterName => baseFilter;
public BaseEventAttribute(string eventName)
: this(eventName, string.Empty)
{
}
public BaseEventAttribute(string eventName, string baseFilter)
{
this.eventName = eventName;
this.baseFilter = baseFilter;
}
}

View file

@ -0,0 +1,11 @@
using System.Runtime.InteropServices;
namespace Decal.Adapter;
internal class COMHResultException : COMException
{
internal COMHResultException(HResults hResult)
{
base.HResult = (int)hResult;
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Adapter;
public class ChatClickInterceptEventArgs : EatableEventArgs
{
private string myText;
private int myId;
public string Text => myText;
public int Id => myId;
internal ChatClickInterceptEventArgs(string text, int id, bool eat)
: base(eat)
{
myText = text;
myId = id;
}
}

View file

@ -0,0 +1,14 @@
namespace Decal.Adapter;
public class ChatParserInterceptEventArgs : EatableEventArgs
{
private string myText;
public string Text => myText;
internal ChatParserInterceptEventArgs(string text, bool eat)
: base(eat)
{
myText = text;
}
}

View file

@ -0,0 +1,24 @@
namespace Decal.Adapter;
public class ChatTextInterceptEventArgs : EatableEventArgs
{
private string myText;
private int myColor;
private int myTarget;
public string Text => myText;
public int Color => myColor;
public int Target => myTarget;
internal ChatTextInterceptEventArgs(string text, int color, int target, bool eat)
: base(eat)
{
myText = text;
myColor = color;
myTarget = target;
}
}

View file

@ -0,0 +1,14 @@
namespace Decal.Adapter;
public class CheckBoxChangeEventArgs : ControlEventArgs
{
private bool check;
public bool Checked => check;
internal CheckBoxChangeEventArgs(int ID, bool Check)
: base(ID)
{
check = Check;
}
}

View file

@ -0,0 +1,15 @@
using System;
namespace Decal.Adapter;
public class ContainerOpenedEventArgs : EventArgs
{
private int myItemGUID;
public int ItemGuid => myItemGUID;
internal ContainerOpenedEventArgs(int itemGUID)
{
myItemGUID = itemGUID;
}
}

View file

@ -0,0 +1,15 @@
using System;
namespace Decal.Adapter;
public class ControlEventArgs : EventArgs
{
private int id;
public int Id => id;
internal ControlEventArgs(int ID)
{
id = ID;
}
}

View file

@ -0,0 +1,35 @@
using System;
namespace Decal.Adapter;
/// <summary>
/// ControlEvent AutoWireup
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class ControlEventAttribute : ViewBaseAttribute
{
private string myControl;
private string myEventName;
/// <summary>
/// Control Name
/// </summary>
public string Control => myControl;
/// <summary>
/// Event to Wire
/// </summary>
public string EventName => myEventName;
/// <summary>
/// Constructs the ControlEvent
/// </summary>
/// <param name="control">Control Name</param>
/// <param name="controlEvent">Event to Wire</param>
public ControlEventAttribute(string control, string eventName)
{
myControl = control;
myEventName = eventName;
}
}

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.ObjectModel;
namespace Decal.Adapter;
/// <summary>
/// ControlReferenceArray AutoWireup
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public sealed class ControlReferenceArrayAttribute : ViewBaseAttribute
{
private Collection<string> myControls;
/// <summary>
/// Control collection
/// </summary>
public Collection<string> Controls => myControls;
/// <summary>
/// Constructs a new ControlReference array
/// </summary>
/// <param name="controls">Names of the controls to put in the array</param>
public ControlReferenceArrayAttribute(params string[] controls)
{
myControls = new Collection<string>(controls);
}
}

View file

@ -0,0 +1,26 @@
using System;
namespace Decal.Adapter;
/// <summary>
/// ControlReference AutoWireup
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public sealed class ControlReferenceAttribute : ViewBaseAttribute
{
private string myControl;
/// <summary>
/// The Control Name
/// </summary>
public string Control => myControl;
/// <summary>
/// Construct a new ControlReference
/// </summary>
/// <param name="control">Control to reference</param>
public ControlReferenceAttribute(string control)
{
myControl = control;
}
}

View file

@ -0,0 +1,987 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using Decal.Adapter.IDQueue;
using Decal.Adapter.Messages;
using Decal.Adapter.Support;
using Decal.Adapter.Wrappers;
using Decal.Interop.Core;
using Decal.Interop.D3DService;
using Decal.Interop.DHS;
using Decal.Interop.Filters;
using Decal.Interop.Inject;
using Decal.Interop.Render;
using Microsoft.Win32;
namespace Decal.Adapter;
/// <summary>
/// Lifetime Service required for the .NET Surrogate to function.
/// </summary>
[CLSCompliant(true)]
public sealed class CoreManager : MarshalByRefObject
{
private struct sAssemblyPreloadData
{
public string AssemblyName;
public string Path;
}
private static bool myServiceRunning;
private static CoreManager myService;
private DecalCoreClass myDecal;
private ACHooksClass myHooks;
private PluginSite mySitev1;
private DecalWrapper myWrappedDecal;
private HooksWrapper myWrappedHooks;
private global::Decal.Adapter.Wrappers.HotkeySystem myDHS;
private CharacterFilter myCharacterFilter;
private WorldFilter myWorldFilter;
private global::Decal.Adapter.Wrappers.EchoFilter2 myEchoFilter;
private D3DService myD3DService;
private RenderServiceWrapper myRenderService;
private FairIDQueue myIDQueue;
private Collection<string> myPaths = new Collection<string>();
private Dictionary<AppDomain, Dictionary<string, Assembly>> myAssemblies = new Dictionary<AppDomain, Dictionary<string, Assembly>>();
private int myAssemblyPreloadCounter = 1;
private bool myAssemblyPreloadStarted;
private Dictionary<Type, FilterBase> myFilters = new Dictionary<Type, FilterBase>();
private Dictionary<string, FilterBase> myNamedFilters = new Dictionary<string, FilterBase>();
private Dictionary<Type, ServiceBase> myServices = new Dictionary<Type, ServiceBase>();
private Dictionary<string, ServiceBase> myNamedServices = new Dictionary<string, ServiceBase>();
private Dictionary<string, PluginBase> myPlugins = new Dictionary<string, PluginBase>();
private EventHandler<ItemSelectedEventArgs> myItemSelected;
private EventHandler<ItemDestroyedEventArgs> myItemDestroyed;
private EventHandler<ChatParserInterceptEventArgs> myChatParserIntercept;
private EventHandler<RegionChange3DEventArgs> myRegionChange3D;
private EventHandler<ChatTextInterceptEventArgs> myChatTextIntercept;
private EventHandler<StatusTextInterceptEventArgs> myStatusTextIntercept;
private EventHandler<MessageProcessedEventArgs> myMessageProcessed;
private EventHandler<ContainerOpenedEventArgs> myContainerOpened;
private EventHandler<ChatClickInterceptEventArgs> myChatClickIntercept;
private EventHandler<WindowMessageEventArgs> myWindowMessage;
private EventHandler<EventArgs> myFilterInitComplete;
private EventHandler<EventArgs> myServiceInitComplete;
private EventHandler<EventArgs> myPluginInitComplete;
private EventHandler<EventArgs> myFilterTermComplete;
private EventHandler<EventArgs> myServiceTermComplete;
private EventHandler<EventArgs> myPluginTermComplete;
private EventHandler<EventArgs> myRender_PreUI;
private EventHandler<AdapterMessageEventArgs> myExtensionMessage;
private AppDomain myPluginDomain;
private AppDomain myDomain;
/// <summary>
/// Returns if the service was initialized by Decal.
/// </summary>
public static bool ServiceRunning => myServiceRunning;
/// <summary>
/// Returns the Singleton instance of the Service
/// (Initializes if necessary)
/// </summary>
public static CoreManager Current
{
get
{
if (myService == null)
{
myService = new CoreManager();
}
return myService;
}
}
/// <summary>
/// Tracing level for Decal.Adapter, and all loaded plugins.
/// </summary>
public static int TracingLevel => Util.TraceLevel;
/// <summary>
/// FileService (Decal.FileService)
/// </summary>
public FilterBase FileService => Filter("Decal.FileService");
/// <summary>
/// Decal Hotkey System
/// </summary>
public global::Decal.Adapter.Wrappers.HotkeySystem HotkeySystem => myDHS;
/// <summary>
/// Character Filter
/// </summary>
[CLSCompliant(false)]
public CharacterFilter CharacterFilter => myCharacterFilter;
[CLSCompliant(false)]
public WorldFilter WorldFilter => myWorldFilter;
/// <summary>
/// Direct3D Service
/// </summary>
[CLSCompliant(false)]
public global::Decal.Adapter.Wrappers.EchoFilter2 EchoFilter => myEchoFilter;
[CLSCompliant(false)]
public D3DService D3DService => myD3DService;
[CLSCompliant(false)]
public HooksWrapper Actions => myWrappedHooks;
[CLSCompliant(false)]
public DecalWrapper Decal => myWrappedDecal;
public RenderServiceWrapper RenderService => myRenderService;
public FairIDQueue IDQueue => myIDQueue;
internal AppDomain PluginDomain => myDomain;
[CLSCompliant(false)]
public event EventHandler<ItemSelectedEventArgs> ItemSelected
{
add
{
myItemSelected = (EventHandler<ItemSelectedEventArgs>)Delegate.Combine(myItemSelected, value);
}
remove
{
myItemSelected = (EventHandler<ItemSelectedEventArgs>)Delegate.Remove(myItemSelected, value);
}
}
[CLSCompliant(false)]
public event EventHandler<ItemDestroyedEventArgs> ItemDestroyed
{
add
{
myItemDestroyed = (EventHandler<ItemDestroyedEventArgs>)Delegate.Combine(myItemDestroyed, value);
}
remove
{
myItemDestroyed = (EventHandler<ItemDestroyedEventArgs>)Delegate.Remove(myItemDestroyed, value);
}
}
[CLSCompliant(false)]
public event EventHandler<ChatParserInterceptEventArgs> CommandLineText
{
add
{
myChatParserIntercept = (EventHandler<ChatParserInterceptEventArgs>)Delegate.Combine(myChatParserIntercept, value);
}
remove
{
myChatParserIntercept = (EventHandler<ChatParserInterceptEventArgs>)Delegate.Remove(myChatParserIntercept, value);
}
}
[CLSCompliant(false)]
public event EventHandler<StatusTextInterceptEventArgs> StatusBoxMessage
{
add
{
myStatusTextIntercept = (EventHandler<StatusTextInterceptEventArgs>)Delegate.Combine(myStatusTextIntercept, value);
}
remove
{
myStatusTextIntercept = (EventHandler<StatusTextInterceptEventArgs>)Delegate.Remove(myStatusTextIntercept, value);
}
}
[CLSCompliant(false)]
public event EventHandler<RegionChange3DEventArgs> RegionChange3D
{
add
{
myRegionChange3D = (EventHandler<RegionChange3DEventArgs>)Delegate.Combine(myRegionChange3D, value);
}
remove
{
myRegionChange3D = (EventHandler<RegionChange3DEventArgs>)Delegate.Remove(myRegionChange3D, value);
}
}
[CLSCompliant(false)]
public event EventHandler<ChatTextInterceptEventArgs> ChatBoxMessage
{
add
{
myChatTextIntercept = (EventHandler<ChatTextInterceptEventArgs>)Delegate.Combine(myChatTextIntercept, value);
}
remove
{
myChatTextIntercept = (EventHandler<ChatTextInterceptEventArgs>)Delegate.Remove(myChatTextIntercept, value);
}
}
[CLSCompliant(false)]
public event EventHandler<MessageProcessedEventArgs> MessageProcessed
{
add
{
myMessageProcessed = (EventHandler<MessageProcessedEventArgs>)Delegate.Combine(myMessageProcessed, value);
}
remove
{
myMessageProcessed = (EventHandler<MessageProcessedEventArgs>)Delegate.Remove(myMessageProcessed, value);
}
}
[CLSCompliant(false)]
public event EventHandler<ContainerOpenedEventArgs> ContainerOpened
{
add
{
myContainerOpened = (EventHandler<ContainerOpenedEventArgs>)Delegate.Combine(myContainerOpened, value);
}
remove
{
myContainerOpened = (EventHandler<ContainerOpenedEventArgs>)Delegate.Remove(myContainerOpened, value);
}
}
[CLSCompliant(false)]
public event EventHandler<ChatClickInterceptEventArgs> ChatNameClicked
{
add
{
myChatClickIntercept = (EventHandler<ChatClickInterceptEventArgs>)Delegate.Combine(myChatClickIntercept, value);
}
remove
{
myChatClickIntercept = (EventHandler<ChatClickInterceptEventArgs>)Delegate.Remove(myChatClickIntercept, value);
}
}
public event EventHandler<EventArgs> FilterInitComplete
{
add
{
myFilterInitComplete = (EventHandler<EventArgs>)Delegate.Combine(myFilterInitComplete, value);
}
remove
{
myFilterInitComplete = (EventHandler<EventArgs>)Delegate.Remove(myFilterInitComplete, value);
}
}
public event EventHandler<EventArgs> ServiceInitComplete
{
add
{
myServiceInitComplete = (EventHandler<EventArgs>)Delegate.Combine(myServiceInitComplete, value);
}
remove
{
myServiceInitComplete = (EventHandler<EventArgs>)Delegate.Remove(myServiceInitComplete, value);
}
}
public event EventHandler<EventArgs> PluginInitComplete
{
add
{
myPluginInitComplete = (EventHandler<EventArgs>)Delegate.Combine(myPluginInitComplete, value);
}
remove
{
myPluginInitComplete = (EventHandler<EventArgs>)Delegate.Remove(myPluginInitComplete, value);
}
}
public event EventHandler<EventArgs> FilterTermComplete
{
add
{
myFilterTermComplete = (EventHandler<EventArgs>)Delegate.Combine(myFilterTermComplete, value);
}
remove
{
myFilterTermComplete = (EventHandler<EventArgs>)Delegate.Remove(myFilterTermComplete, value);
}
}
public event EventHandler<EventArgs> ServiceTermComplete
{
add
{
myServiceTermComplete = (EventHandler<EventArgs>)Delegate.Combine(myServiceTermComplete, value);
}
remove
{
myServiceTermComplete = (EventHandler<EventArgs>)Delegate.Remove(myServiceTermComplete, value);
}
}
public event EventHandler<EventArgs> PluginTermComplete
{
add
{
myPluginTermComplete = (EventHandler<EventArgs>)Delegate.Combine(myPluginTermComplete, value);
}
remove
{
myPluginTermComplete = (EventHandler<EventArgs>)Delegate.Remove(myPluginTermComplete, value);
}
}
public event EventHandler<EventArgs> RenderFrame
{
add
{
myRender_PreUI = (EventHandler<EventArgs>)Delegate.Combine(myRender_PreUI, value);
}
remove
{
myRender_PreUI = (EventHandler<EventArgs>)Delegate.Remove(myRender_PreUI, value);
}
}
[CLSCompliant(false)]
public event EventHandler<WindowMessageEventArgs> WindowMessage
{
add
{
myWindowMessage = (EventHandler<WindowMessageEventArgs>)Delegate.Combine(myWindowMessage, value);
}
remove
{
myWindowMessage = (EventHandler<WindowMessageEventArgs>)Delegate.Remove(myWindowMessage, value);
}
}
internal event EventHandler<AdapterMessageEventArgs> ExtensionMessage
{
add
{
myExtensionMessage = (EventHandler<AdapterMessageEventArgs>)Delegate.Combine(myExtensionMessage, value);
}
remove
{
myExtensionMessage = (EventHandler<AdapterMessageEventArgs>)Delegate.Remove(myExtensionMessage, value);
}
}
private CoreManager()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
string location = System.Reflection.Assembly.GetExecutingAssembly().Location;
AddAssemblyPath(Path.GetDirectoryName(location));
myDomain = AppDomain.CurrentDomain;
Util.InitializeTracing("HKEY_LOCAL_MACHINE\\Software\\Decal\\Decal.Adapter", "Tracing", 0);
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
AppDomain appDomain = (AppDomain)sender;
Assembly[] assemblies = appDomain.GetAssemblies();
string text = appDomain.ApplyPolicy(args.Name);
if (string.IsNullOrEmpty(text))
{
text = args.Name;
}
Assembly[] array = assemblies;
foreach (Assembly assembly in array)
{
if (assembly.FullName == text)
{
return assembly;
}
}
if (!appDomain.IsDefaultAppDomain())
{
assemblies = myDomain.GetAssemblies();
array = assemblies;
foreach (Assembly assembly2 in array)
{
if (assembly2.FullName == text)
{
AssemblyName name = assembly2.GetName(copiedName: false);
return appDomain.Load(name);
}
}
}
string text2 = ((text.IndexOf(",") <= 0) ? text : text.Substring(0, text.IndexOf(",")));
if (!string.IsNullOrEmpty(text2))
{
text2 = text2.ToLowerInvariant();
if (string.IsNullOrEmpty(Path.GetExtension(text2)))
{
text2 += ".dll";
}
foreach (string myPath in myPaths)
{
if (File.Exists(Path.Combine(myPath, text2)))
{
AssemblyName assemblyName = new AssemblyName();
assemblyName.CodeBase = Path.Combine(myPath, text2);
return appDomain.Load(assemblyName);
}
}
}
Util.WriteLine("Assembly resolve failed for assembly:" + args.Name);
return null;
}
private void AddAssemblyPath(string path)
{
string item = path.ToLowerInvariant();
if (!myPaths.Contains(item))
{
myPaths.Add(item);
}
}
private void myDecal_InitializeComplete(eDecalComponentType myComponent)
{
Util.WriteLine("InitializeComplete for: " + myComponent);
switch (myComponent)
{
case eDecalComponentType.eService:
Message.Initialize(Path.Combine((string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Decal\\Agent", "AgentPath", ""), "messages.xml"));
if (myWrappedDecal != null)
{
try
{
if (myWrappedDecal.GetObject("services\\D3DService.Service") is CService obj)
{
myD3DService = new D3DService(obj);
}
if (myWrappedDecal.GetObject("services\\DecalRender.RenderService") is RenderService render)
{
myRenderService = new RenderServiceWrapper(render);
}
object obj2 = myWrappedDecal.GetObject("services\\DecalPlugins.InjectService\\site", DecalWrapper.IID_IUNKNOWN);
mySitev1 = obj2 as PluginSite;
}
catch (Exception ex)
{
Util.WriteLine("Unable to get service reference: " + ex.Message);
}
}
else
{
Util.WriteLine("Not getting services, we don't have a Decal object to call GetObject on.");
}
try
{
myIDQueue = new FairIDQueue();
}
catch (Exception ex2)
{
Util.WriteLine("Service initialization exception: " + ex2.Message);
}
Util.SafeFireEvent(this, myServiceInitComplete, new EventArgs());
break;
case eDecalComponentType.eNetworkFilter:
if (myWrappedDecal != null)
{
try
{
if (myWrappedDecal.GetObject("services\\DecalNet.NetService\\DecalFilters.World") is World obj3)
{
myWorldFilter = new WorldFilter(obj3);
}
if (myWrappedDecal.GetObject("services\\DecalNet.NetService\\DecalFilters.CharacterStats") is CharacterStats obj4)
{
myCharacterFilter = new CharacterFilter(obj4);
}
if (myWrappedDecal.GetObject("services\\DecalNet.NetService\\DecalFilters.EchoFilter2") is global::Decal.Interop.Filters.EchoFilter2 obj5)
{
myEchoFilter = new global::Decal.Adapter.Wrappers.EchoFilter2(obj5);
}
}
catch (Exception ex3)
{
Util.WriteLine("Unable to get filter reference: " + ex3.Message);
}
}
else
{
Util.WriteLine("Not getting filters, we don't have a Decal object to call GetObject on.");
}
Util.SafeFireEvent(this, myFilterInitComplete, new EventArgs());
DecrementAssemblyPreloadLockCounter();
break;
case eDecalComponentType.ePlugin:
if (myWrappedDecal.GetObject("plugins\\DHS.HotkeySystem") is global::Decal.Interop.DHS.HotkeySystem hks)
{
myDHS = new global::Decal.Adapter.Wrappers.HotkeySystem(hks);
}
myIDQueue.Start();
Util.SafeFireEvent(this, myPluginInitComplete, new EventArgs());
break;
}
}
private void myDecal_TerminateComplete(eDecalComponentType myComponent)
{
Util.WriteLine("TerminateComplete for: " + myComponent);
switch (myComponent)
{
case eDecalComponentType.eService:
if (myD3DService != null)
{
myD3DService.Dispose();
myD3DService = null;
}
if (myRenderService != null)
{
myRenderService.Dispose();
myRenderService = null;
}
if (mySitev1 != null)
{
Marshal.ReleaseComObject(mySitev1);
}
myServices.Clear();
myNamedServices.Clear();
Util.SafeFireEvent(this, myServiceTermComplete, new EventArgs());
break;
case eDecalComponentType.eNetworkFilter:
if (myWorldFilter != null)
{
myWorldFilter.Dispose();
myWorldFilter = null;
}
if (myCharacterFilter != null)
{
myCharacterFilter.Dispose();
myCharacterFilter = null;
}
if (myEchoFilter != null)
{
myEchoFilter.Dispose();
myEchoFilter = null;
}
myFilters.Clear();
myNamedFilters.Clear();
Util.SafeFireEvent(this, myFilterTermComplete, new EventArgs());
break;
case eDecalComponentType.ePlugin:
myIDQueue.Stop();
if (myDHS != null)
{
myDHS.Dispose();
myDHS = null;
}
myPlugins.Clear();
if (myPluginDomain != null)
{
lock (myAssemblies)
{
if (myAssemblies.ContainsKey(myPluginDomain))
{
myAssemblies[myPluginDomain].Clear();
myAssemblies.Remove(myPluginDomain);
}
AppDomain.Unload(myPluginDomain);
myPluginDomain = null;
}
}
Util.SafeFireEvent(this, myPluginTermComplete, new EventArgs());
break;
}
}
private void myHooks_ObjectSelected(int lGUID)
{
Util.SafeFireEvent(this, myItemSelected, new ItemSelectedEventArgs(lGUID));
}
private void myHooks_ObjectDestroyed(int lGUID)
{
Util.SafeFireEvent(this, myItemDestroyed, new ItemDestroyedEventArgs(lGUID));
}
private void myHooks_AC3DRegionChanged(int left, int top, int right, int bottom)
{
Util.SafeFireEvent(this, myRegionChange3D, new RegionChange3DEventArgs(left, top, right, bottom));
}
private void myHooks_ChatParserIntercept(string bstrText, ref bool bEat)
{
Util.SafeFireEvent(this, myChatParserIntercept, new ChatParserInterceptEventArgs(bstrText, bEat), ref bEat);
}
private void myHooks_StatusTextIntercept(string bstrText, ref bool bEat)
{
Util.SafeFireEvent(this, myStatusTextIntercept, new StatusTextInterceptEventArgs(bstrText, bEat), ref bEat);
}
private void myHooks_ChatTextIntercept(string bstrText, int lColor, int target, ref bool bEat)
{
Util.SafeFireEvent(this, myChatTextIntercept, new ChatTextInterceptEventArgs(bstrText, lColor, target, bEat), ref bEat);
}
private void myHooks_MessageProcessed(int pbData, int dwSize)
{
if (myMessageProcessed != null)
{
MessageProcessedEventArgs args = new MessageProcessedEventArgs(pbData, dwSize);
Util.SafeFireEvent(this, myMessageProcessed, args);
}
}
private void myHooks_ContainerOpened(int lGUID)
{
Util.SafeFireEvent(this, myContainerOpened, new ContainerOpenedEventArgs(lGUID));
}
private void myHooks_ChatClickIntercept(string bstrText, int id, ref bool bEat)
{
Util.SafeFireEvent(this, myChatClickIntercept, new ChatClickInterceptEventArgs(bstrText, id, bEat), ref bEat);
}
private void myHooks_RenderPreUI()
{
Util.SafeFireEvent(this, myRender_PreUI, new EventArgs());
}
internal bool FireWindowMessage(int HWND, short uMsg, int wParam, int lParam)
{
bool eaten = false;
WindowMessageEventArgs args = new WindowMessageEventArgs(HWND, uMsg, wParam, lParam);
Util.SafeFireEvent(this, myWindowMessage, args, ref eaten);
return eaten;
}
internal void FireExtensionMessage(object sender, AdapterMessageEventArgs args)
{
args.CanAddHandlers = true;
Util.SafeFireEvent(this, myExtensionMessage, args);
args.CanAddHandlers = false;
}
public FilterBase Filter(string filterName)
{
try
{
if (myNamedFilters.ContainsKey(filterName))
{
return myNamedFilters[filterName];
}
Type type = Type.GetType(filterName);
if (null != type && myFilters.ContainsKey(type))
{
return myFilters[type];
}
}
catch (Exception)
{
}
return null;
}
public T Filter<T>() where T : FilterBase
{
try
{
if (myFilters.ContainsKey(typeof(T)))
{
return (T)myFilters[typeof(T)];
}
}
catch (Exception)
{
}
return null;
}
public ServiceBase Service(string serviceName)
{
try
{
if (myNamedServices.ContainsKey(serviceName))
{
return myNamedServices[serviceName];
}
Type type = Type.GetType(serviceName);
if (null != type && myServices.ContainsKey(type))
{
return myServices[type];
}
}
catch (Exception)
{
}
return null;
}
public T Service<T>() where T : ServiceBase
{
try
{
if (myServices.ContainsKey(typeof(T)))
{
return (T)myServices[typeof(T)];
}
}
catch (Exception)
{
}
return null;
}
/// <summary>
/// Get Mapped Keyboard Key
/// </summary>
/// <param name="name">Name to retrive mapping for. </param>
/// <returns>Mapped Key</returns>
public int QueryKeyBoardMap(string name)
{
int result = 0;
if (mySitev1 != null)
{
result = mySitev1.QueryKeyboardMap(name);
}
return result;
}
internal void AddFilter(FilterBase newFilter)
{
AddFilter(newFilter.ReferenceName, newFilter);
}
internal void AddFilter(string filterName, FilterBase newFilter)
{
myFilters.Add(newFilter.GetType(), newFilter);
myNamedFilters.Add(filterName, newFilter);
}
internal void AddService(ServiceBase newService)
{
AddService(newService.ReferenceName, newService);
}
internal void AddService(string serviceName, ServiceBase newService)
{
myServices.Add(newService.GetType(), newService);
myNamedServices.Add(serviceName, newService);
}
internal void AddPlugin(PluginBase newPlugin)
{
AddPlugin(newPlugin.ReferenceName, newPlugin);
}
internal void AddPlugin(string pluginName, PluginBase newPlugin)
{
myPlugins.Add(pluginName, newPlugin);
}
/// <summary>
/// Load the Assembly requested, first checking our internal cache
/// </summary>
/// <param name="name">Assembly name to load</param>
/// <param name="path">Path to the assembly</param>
/// <returns>Loaded Assembly, from cache if already loaded</returns>
internal Assembly Assembly(string name, string path)
{
return Assembly(name, path, AppDomain.CurrentDomain);
}
internal Assembly Assembly(string name, string path, AppDomain useDomain)
{
lock (myAssemblies)
{
string text = name.ToLowerInvariant();
useDomain = myDomain;
Dictionary<string, Assembly> dictionary;
if (myAssemblies.ContainsKey(useDomain))
{
dictionary = myAssemblies[useDomain];
}
else
{
myAssemblies.Add(useDomain, new Dictionary<string, Assembly>());
dictionary = myAssemblies[useDomain];
}
if (dictionary.ContainsKey(text))
{
return dictionary[text];
}
AddAssemblyPath(path);
Assembly assembly = System.Reflection.Assembly.LoadFrom(Path.Combine(path, text));
dictionary.Add(text, assembly);
return assembly;
}
}
internal void Initialize(DecalCore pDecal)
{
Util.WriteLine("Decal.Adapter Lifetime-service Initialize Begun");
myServiceRunning = true;
Util.Write("Get Decal.. ");
myDecal = (DecalCoreClass)pDecal;
myWrappedDecal = new DecalWrapper(myDecal);
Util.WriteLine("Sink Decal Events.. ");
myDecal.InitializeComplete += myDecal_InitializeComplete;
myDecal.TerminateComplete += myDecal_TerminateComplete;
Util.Write("Get Hooks.. ");
myHooks = (ACHooksClass)myDecal.Hooks;
myWrappedHooks = new HooksWrapper(myHooks);
Util.WriteLine("Sink Hooks Events.. ");
myHooks.ChatTextIntercept += myHooks_ChatTextIntercept;
myHooks.StatusTextIntercept += myHooks_StatusTextIntercept;
myHooks.ChatParserIntercept += myHooks_ChatParserIntercept;
myHooks.AC3DRegionChanged += myHooks_AC3DRegionChanged;
myHooks.ObjectSelected += myHooks_ObjectSelected;
myHooks.ObjectDestroyed += myHooks_ObjectDestroyed;
myHooks.MessageProcessed += myHooks_MessageProcessed;
myHooks.ContainerOpened += myHooks_ContainerOpened;
myHooks.ChatClickIntercept += myHooks_ChatClickIntercept;
myHooks.RenderPreUI += myHooks_RenderPreUI;
Util.WriteLine("Decal.Adapter Lifetime-service Initiliazed");
}
internal void Terminate()
{
myDecal.InitializeComplete -= myDecal_InitializeComplete;
myDecal.TerminateComplete -= myDecal_TerminateComplete;
myHooks.ChatTextIntercept -= myHooks_ChatTextIntercept;
myHooks.StatusTextIntercept -= myHooks_StatusTextIntercept;
myHooks.ChatParserIntercept -= myHooks_ChatParserIntercept;
myHooks.AC3DRegionChanged -= myHooks_AC3DRegionChanged;
myHooks.ObjectSelected -= myHooks_ObjectSelected;
myHooks.ObjectDestroyed -= myHooks_ObjectDestroyed;
myHooks.MessageProcessed -= myHooks_MessageProcessed;
myHooks.ContainerOpened -= myHooks_ContainerOpened;
myHooks.ChatClickIntercept -= myHooks_ChatClickIntercept;
myHooks.RenderPreUI -= myHooks_RenderPreUI;
myWrappedDecal.Dispose();
myWrappedDecal = null;
Marshal.ReleaseComObject(myDecal);
myDecal = null;
myHooks = null;
myWrappedHooks.Dispose();
myWrappedHooks = null;
myService = null;
myServiceRunning = false;
}
public void IncrementAssemblyPreloadLockCounter()
{
myAssemblyPreloadCounter++;
}
public void DecrementAssemblyPreloadLockCounter()
{
myAssemblyPreloadCounter--;
if (myAssemblyPreloadCounter < 0)
{
myAssemblyPreloadCounter = 0;
}
if (myAssemblyPreloadCounter != 0 || myAssemblyPreloadStarted)
{
return;
}
myAssemblyPreloadStarted = true;
List<sAssemblyPreloadData> list = new List<sAssemblyPreloadData>();
Guid clsidAdvance = Guid.Empty;
Guid guid = new Guid("{71A69713-6593-47EC-0002-0000000DECA1}");
DecalEnum decalEnum = ((IDecalCore)Decal.Underlying).get_Configuration("Plugins", ref clsidAdvance);
try
{
while (true)
{
decalEnum.Next();
if (!decalEnum.Enabled || decalEnum.SurrogateClass != guid)
{
continue;
}
try
{
if (decalEnum.Restricted)
{
continue;
}
}
catch
{
continue;
}
list.Add(new sAssemblyPreloadData
{
AssemblyName = (string)((IDecalEnum)decalEnum).get_Property("Assembly"),
Path = (string)((IDecalEnum)decalEnum).get_Property("Path")
});
}
}
catch
{
}
finally
{
Marshal.ReleaseComObject(decalEnum);
}
ThreadPool.QueueUserWorkItem(AssemblyPreloadThreadProc, list);
}
internal void AssemblyPreloadThreadProc(object data)
{
if (!(data is List<sAssemblyPreloadData> list))
{
return;
}
foreach (sAssemblyPreloadData item in list)
{
try
{
Util.WriteLine("Preloading plugin assembly {0}, {1}", item.AssemblyName, item.Path);
Assembly(item.AssemblyName, item.Path, AppDomain.CurrentDomain);
}
catch
{
}
}
}
}

View file

@ -0,0 +1,17 @@
using System;
namespace Decal.Adapter;
/// <summary>
///
/// </summary>
[CLSCompliant(true)]
public enum DecalExtensionType
{
Surrogate,
Service,
InputAction,
FileFilter,
NetworkFilter,
Plugin
}

View file

@ -0,0 +1,12 @@
using System;
using Decal.Interop.Core;
namespace Decal.Adapter;
public sealed class DirectoryProxy : MarshalByRefObject, IDecalDirectory
{
public object Lookup(string strName)
{
throw new NotImplementedException("The method or operation is not implemented.");
}
}

View file

@ -0,0 +1,29 @@
using System;
namespace Decal.Adapter;
public class DirectoryResolveEventArgs : EventArgs
{
private string myPath;
private object myResult;
public string Path => myPath;
public object Result
{
get
{
return myResult;
}
set
{
myResult = value;
}
}
internal DirectoryResolveEventArgs(string path)
{
myPath = path;
}
}

View file

@ -0,0 +1,60 @@
using System;
namespace Decal.Adapter;
public class DisposableByRefObject : MarshalByRefObject, IDisposable
{
private bool isDisposed;
private EventHandler myDisposing;
public event EventHandler Disposing
{
add
{
myDisposing = (EventHandler)Delegate.Combine(myDisposing, value);
}
remove
{
myDisposing = (EventHandler)Delegate.Remove(myDisposing, value);
}
}
internal DisposableByRefObject()
{
}
~DisposableByRefObject()
{
Dispose(userCalled: false);
}
public void Dispose()
{
Dispose(userCalled: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool userCalled)
{
if (!isDisposed && userCalled && myDisposing != null)
{
try
{
myDisposing(this, new EventArgs());
}
catch
{
}
}
isDisposed = true;
}
protected void EnforceDisposedOnce()
{
if (isDisposed)
{
throw new ObjectDisposedException(GetType().ToString());
}
}
}

View file

@ -0,0 +1,123 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Decal.Adapter.Support;
namespace Decal.Adapter;
public class DisposableObjectDictionary<K, T> : DisposableByRefObject, IDictionary<K, T>, ICollection<KeyValuePair<K, T>>, IEnumerable<KeyValuePair<K, T>>, IEnumerable where T : DisposableByRefObject
{
private Dictionary<K, T> items = new Dictionary<K, T>();
private PropertyInfo keyProperty;
public ICollection<K> Keys => items.Keys;
public ICollection<T> Values => items.Values;
public T this[K key]
{
get
{
return items[key];
}
set
{
items[key] = value;
}
}
public int Count => ((ICollection<KeyValuePair<K, T>>)items).Count;
public bool IsReadOnly => ((ICollection<KeyValuePair<K, T>>)items).IsReadOnly;
public DisposableObjectDictionary(string keyPropertyName)
{
keyProperty = typeof(T).GetProperty(keyPropertyName, BindingFlags.Instance | BindingFlags.Public);
}
protected override void Dispose(bool userCalled)
{
if (userCalled)
{
Clear();
}
base.Dispose(userCalled);
}
private void value_Disposing(object sender, EventArgs e)
{
K key = (K)keyProperty.GetValue(sender, null);
((T)sender).Disposing -= value_Disposing;
items.Remove(key);
}
public void Add(K key, T value)
{
items.Add(key, value);
value.Disposing += value_Disposing;
}
public bool ContainsKey(K key)
{
return items.ContainsKey(key);
}
public bool Remove(K key)
{
return items.Remove(key);
}
public bool TryGetValue(K key, out T value)
{
return items.TryGetValue(key, out value);
}
public void Add(KeyValuePair<K, T> item)
{
items.Add(item.Key, item.Value);
}
public void Clear()
{
foreach (T value in items.Values)
{
try
{
value.Disposing -= value_Disposing;
value.Dispose();
}
catch (Exception ex)
{
Util.WriteLine("GDW_Clear: Exception: {0}", ex.Message);
}
}
items.Clear();
}
public bool Contains(KeyValuePair<K, T> item)
{
return ((ICollection<KeyValuePair<K, T>>)items).Contains(item);
}
public void CopyTo(KeyValuePair<K, T>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<K, T>>)items).CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<K, T> item)
{
return ((ICollection<KeyValuePair<K, T>>)items).Remove(item);
}
public IEnumerator<KeyValuePair<K, T>> GetEnumerator()
{
return ((IEnumerable<KeyValuePair<K, T>>)items).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)items).GetEnumerator();
}
}

View file

@ -0,0 +1,25 @@
using System;
namespace Decal.Adapter;
public class EatableEventArgs : EventArgs
{
private bool myEat;
public bool Eat
{
get
{
return myEat;
}
set
{
myEat = value;
}
}
internal EatableEventArgs(bool eat)
{
myEat = eat;
}
}

View file

@ -0,0 +1,249 @@
using System;
using Decal.Adapter.Messages;
namespace Decal.Adapter;
/// <summary>
///
/// </summary>
[CLSCompliant(true)]
public abstract class Extension : MarshalByRefObject
{
private DecalExtensionType myExtensionType;
private CoreManager myLifetime;
private string myPath;
private EventHandler<DirectoryResolveEventArgs> directoryResolve;
public DecalExtensionType ExtensionType => myExtensionType;
public string Path
{
get
{
return myPath;
}
internal set
{
myPath = value;
}
}
protected CoreManager Core
{
get
{
if (myLifetime == null)
{
myLifetime = CoreManager.Current;
}
return myLifetime;
}
}
public virtual object ComOM => null;
public virtual string ReferenceName => GetType().FullName;
[CLSCompliant(false)]
protected event EventHandler<DirectoryResolveEventArgs> DirectoryResolve
{
add
{
directoryResolve = (EventHandler<DirectoryResolveEventArgs>)Delegate.Combine(directoryResolve, value);
}
remove
{
directoryResolve = (EventHandler<DirectoryResolveEventArgs>)Delegate.Remove(directoryResolve, value);
}
}
[CLSCompliant(false)]
protected event EventHandler<WindowMessageEventArgs> WindowMessage
{
add
{
Core.WindowMessage += value;
}
remove
{
Core.WindowMessage -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<ChatClickInterceptEventArgs> ChatNameClicked
{
add
{
Core.ChatNameClicked += value;
}
remove
{
Core.ChatNameClicked -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<MessageProcessedEventArgs> MessageProcessed
{
add
{
Core.MessageProcessed += value;
}
remove
{
Core.MessageProcessed -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<RegionChange3DEventArgs> RegionChange3D
{
add
{
Core.RegionChange3D += value;
}
remove
{
Core.RegionChange3D -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<ChatTextInterceptEventArgs> ChatBoxMessage
{
add
{
Core.ChatBoxMessage += value;
}
remove
{
Core.ChatBoxMessage -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<ItemSelectedEventArgs> ItemSelected
{
add
{
Core.ItemSelected += value;
}
remove
{
Core.ItemSelected -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<ItemDestroyedEventArgs> ItemDestroyed
{
add
{
Core.ItemDestroyed += value;
}
remove
{
Core.ItemDestroyed -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<ChatParserInterceptEventArgs> CommandLineText
{
add
{
Core.CommandLineText += value;
}
remove
{
Core.CommandLineText -= value;
}
}
[CLSCompliant(false)]
protected event EventHandler<ContainerOpenedEventArgs> ContainerOpened
{
add
{
Core.ContainerOpened += value;
}
remove
{
Core.ContainerOpened -= value;
}
}
protected event EventHandler<AdapterMessageEventArgs> AdapterMessage
{
add
{
Core.ExtensionMessage += value;
}
remove
{
Core.ExtensionMessage -= value;
}
}
internal Extension(DecalExtensionType type)
{
myExtensionType = type;
}
internal void standardEvent(ExtensionEvents evtToFire)
{
switch (evtToFire)
{
case ExtensionEvents.Startup:
Startup();
break;
case ExtensionEvents.Shutdown:
Shutdown();
break;
case ExtensionEvents.InternalWireup:
Wireup();
break;
case ExtensionEvents.InternalUnwire:
UnWire();
break;
}
}
internal object ResolvePath(string path)
{
DirectoryResolveEventArgs e = new DirectoryResolveEventArgs(path);
if (directoryResolve != null)
{
try
{
directoryResolve(this, e);
return e.Result;
}
catch
{
}
}
return null;
}
internal virtual void Wireup()
{
}
internal virtual void UnWire()
{
}
protected abstract void Startup();
protected abstract void Shutdown();
protected void SendAdapterMessage(AdapterMessageEventArgs args)
{
Core.FireExtensionMessage(this, args);
}
}

View file

@ -0,0 +1,12 @@
namespace Decal.Adapter;
/// <summary>
/// Sorts of events to be fired by the PluginProxy
/// </summary>
internal enum ExtensionEvents
{
InternalWireup,
InternalUnwire,
Startup,
Shutdown
}

View file

@ -0,0 +1,46 @@
using System;
using Decal.Adapter.Wrappers;
namespace Decal.Adapter;
[CLSCompliant(true)]
public abstract class FilterBase : Extension
{
private NetServiceHost myHost;
[CLSCompliant(false)]
protected NetServiceHost Host => myHost;
[CLSCompliant(false)]
protected event EventHandler<NetworkMessageEventArgs> ServerDispatch;
[CLSCompliant(false)]
protected event EventHandler<NetworkMessageEventArgs> ClientDispatch;
protected FilterBase()
: base(DecalExtensionType.NetworkFilter)
{
}
/// <summary>
/// Used for internal wiring up of base-class variables.
/// Called by FilterProxy
/// </summary>
/// <param name="newHost">Host (pluginsite) object</param>
internal void SetHost(NetServiceHost newHost)
{
myHost = newHost;
}
internal void fireNetwork(Message newMsg, bool Server)
{
if (Server && this.ServerDispatch != null)
{
this.ServerDispatch(this, new NetworkMessageEventArgs(newMsg));
}
else if (!Server && this.ClientDispatch != null)
{
this.ClientDispatch(this, new NetworkMessageEventArgs(newMsg));
}
}
}

View file

@ -0,0 +1,51 @@
using Decal.Adapter.NetParser;
using Decal.Adapter.Wrappers;
using Decal.Interop.Core;
using Decal.Interop.Net;
namespace Decal.Adapter;
public sealed class FilterProxy : INetworkFilter2, IDecalDirectory
{
private NetServiceHost myService;
private FilterBase myFilter;
internal FilterProxy(FilterBase toWrap)
{
myFilter = toWrap;
}
void INetworkFilter2.DispatchClient(IMessage2 msg)
{
Message message = null;
message = ((!(msg is MessageWrapper messageWrapper)) ? new Message(msg, MessageDirection.Inbound) : messageWrapper.Wrapped);
myFilter.fireNetwork(message, Server: false);
}
void INetworkFilter2.DispatchServer(IMessage2 msg)
{
Message message = null;
message = ((!(msg is MessageWrapper messageWrapper)) ? new Message(msg, MessageDirection.Inbound) : messageWrapper.Wrapped);
myFilter.fireNetwork(message, Server: true);
}
void INetworkFilter2.Initialize(NetService pService)
{
myService = new NetServiceHost(pService);
myFilter.SetHost(myService);
myFilter.standardEvent(ExtensionEvents.InternalWireup);
myFilter.standardEvent(ExtensionEvents.Startup);
}
void INetworkFilter2.Terminate()
{
myFilter.standardEvent(ExtensionEvents.Shutdown);
myService.Dispose();
}
object IDecalDirectory.Lookup(string strName)
{
return myFilter.ResolvePath(strName);
}
}

View file

@ -0,0 +1,16 @@
using System;
namespace Decal.Adapter;
[AttributeUsage(AttributeTargets.Class)]
public sealed class FriendlyNameAttribute : Attribute
{
private string myName;
public string Name => myName;
public FriendlyNameAttribute(string name)
{
myName = name;
}
}

View file

@ -0,0 +1,32 @@
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Decal.Adapter;
public class GenericDisposableWrapper<T> : DisposableByRefObject where T : class
{
private T myObj;
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public T Underlying => myObj;
[CLSCompliant(false)]
protected T Wrapped => myObj;
internal GenericDisposableWrapper(T obj)
{
myObj = obj;
}
protected override void Dispose(bool userCalled)
{
EnforceDisposedOnce();
base.Dispose(userCalled);
if (myObj != null)
{
Marshal.ReleaseComObject(myObj);
}
}
}

View file

@ -0,0 +1,9 @@
namespace Decal.Adapter;
internal enum HResults
{
E_FAIL = -2147483640,
E_NOINTERFACE = -2147483644,
S_FAIL = -1,
S_OK = 0
}

View file

@ -0,0 +1,41 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Decal.Interop.Core;
namespace Decal.Adapter;
[ComImport]
[InterfaceType(1)]
[Guid("DA98635C-A312-463B-A746-2CF62AF7413A")]
internal interface IAdapterSurrogate
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
IntPtr CreateInstance([MarshalAs(UnmanagedType.Interface)] DecalEnum pInitData, ref Guid riid);
[DispId(1610678273)]
string Version
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[return: MarshalAs(UnmanagedType.BStr)]
get;
}
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetEnum([MarshalAs(UnmanagedType.Interface)] DecalEnum pInitData);
[DispId(1610678275)]
bool FileExists
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
get;
}
[DispId(1610678276)]
string FilePath
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[return: MarshalAs(UnmanagedType.BStr)]
get;
}
}

View file

@ -0,0 +1,14 @@
namespace Decal.Adapter;
public class IndexChangeEventArgs : ControlEventArgs
{
private int index;
public int Index => index;
internal IndexChangeEventArgs(int ID, int Index)
: base(ID)
{
index = Index;
}
}

View file

@ -0,0 +1,15 @@
using System;
namespace Decal.Adapter;
public class ItemDestroyedEventArgs : EventArgs
{
private int myItemGUID;
public int ItemGuid => myItemGUID;
internal ItemDestroyedEventArgs(int itemGUID)
{
myItemGUID = itemGUID;
}
}

View file

@ -0,0 +1,15 @@
using System;
namespace Decal.Adapter;
public class ItemSelectedEventArgs : EventArgs
{
private int myItemGUID;
public int ItemGuid => myItemGUID;
internal ItemSelectedEventArgs(int itemGUID)
{
myItemGUID = itemGUID;
}
}

View file

@ -0,0 +1,72 @@
using System;
using System.Runtime.InteropServices;
using Decal.Adapter.Support;
using Decal.Interop.Core;
using Microsoft.Win32;
namespace Decal.Adapter;
[ComVisible(true)]
[ComDefaultInterface(typeof(IDecalService))]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("DecalAdapter.Lifetime")]
[Guid("71A69713-6593-47EC-0001-0000000DECA1")]
public sealed class LifetimeProxy : MarshalByRefObject, IDecalService, IDecalDirectory, IDecalWindowsMessageSink
{
private CoreManager myLifetime;
public LifetimeProxy()
{
Util.WriteLine("Lifetime Proxy retrieving Lifetime manager");
myLifetime = CoreManager.Current;
Util.WriteLine("Lifetime Proxy ctor complete");
}
[ComRegisterFunction]
internal static void SelfRegister(Type t)
{
RegistryKey registryKey = Registry.LocalMachine.CreateSubKey("Software\\Decal\\Services").CreateSubKey("{71A69713-6593-47EC-0001-0000000DECA1}");
registryKey.SetValue("", "Decal .NET Lifetime Service", RegistryValueKind.String);
registryKey.SetValue("Enabled", true, RegistryValueKind.DWord);
RegistryKey registryKey2 = Registry.LocalMachine.CreateSubKey("Software\\Decal\\Surrogates").CreateSubKey("{71A69713-6593-47EC-0002-0000000DECA1}");
registryKey2.SetValue("", "Decal.Adapter Surrogate", RegistryValueKind.String);
registryKey2.SetValue("Enabled", true, RegistryValueKind.DWord);
}
[ComUnregisterFunction]
internal static void UnRegister(Type t)
{
}
void IDecalService.AfterPlugins()
{
}
void IDecalService.BeforePlugins()
{
}
void IDecalService.Initialize(DecalCore pDecal)
{
if (!RuntimePolicyHelper.LegacyV2RuntimeEnabledSuccessfully)
{
Util.WriteLine("Can't load v2 mixed-mode");
}
myLifetime.Initialize(pDecal);
}
void IDecalService.Terminate()
{
myLifetime.Terminate();
}
object IDecalDirectory.Lookup(string strName)
{
return null;
}
bool IDecalWindowsMessageSink.WindowMessage(int HWND, short uMsg, int wParam, int lParam)
{
return myLifetime.FireWindowMessage(HWND, uMsg, wParam, lParam);
}
}

View file

@ -0,0 +1,19 @@
namespace Decal.Adapter;
public class ListSelectEventArgs : ControlEventArgs
{
private int row;
private int col;
public int Row => row;
public int Column => col;
internal ListSelectEventArgs(int ID, int Row, int Column)
: base(ID)
{
row = Row;
col = Column;
}
}

View file

@ -0,0 +1,509 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using Decal.Adapter.NetParser;
using Decal.Interop.Net;
namespace Decal.Adapter;
/// <summary>
/// Protocol Message Data
/// </summary>
public class Message : MessageStruct
{
private static Dictionary<int, MemberParser> mRecv;
private static Dictionary<int, MemberParser> mSend;
private static Dictionary<string, MemberParser> mTypes;
private int mType;
internal MessageStruct mStruct;
/// <summary>
/// Message Type
/// </summary>
public int Type => mType;
/// <summary>
/// Returns the number of fields (or vector length)
/// </summary>
public override int Count => mStruct.Count;
/// <summary>
/// Returns the specified field data
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Field value</returns>
public override object this[int index] => mStruct[index];
/// <summary>
/// Returns the specified field data
/// </summary>
/// <param name="name">Field name</param>
/// <returns>Field value</returns>
public override object this[string name] => mStruct[name];
/// <summary>
/// Returns the raw bytes for this field
/// </summary>
public override byte[] RawData => mStruct.RawData;
/// <summary>
/// Returns the next object in the (parent) vector
/// </summary>
public override object Next => mStruct.Next;
/// <summary>
/// Returns the parent field
/// </summary>
public override MessageStruct Parent => mStruct.Parent;
internal Message()
{
}
internal Message(IMessage2 msg, MessageDirection dir)
{
mType = BitConverter.ToInt32(msg.RawData, 0);
mStruct = new MessageStruct(msg.RawData, 4, GetParser(mType, dir));
}
internal Message(byte[] Data, MemberParser Parser)
{
mType = BitConverter.ToInt32(Data, 0);
mStruct = new MessageStruct(Data, 4, Parser);
}
internal Message(Message Source)
{
mType = Source.mType;
mStruct = Source.mStruct;
}
internal static MemberParser GetParser(int type, MessageDirection dir)
{
MemberParser result = null;
switch (dir)
{
case MessageDirection.Inbound:
if (mRecv.ContainsKey(type))
{
result = mRecv[type];
}
break;
case MessageDirection.Outbound:
if (mSend.ContainsKey(type))
{
result = mSend[type];
}
break;
}
return result;
}
/// <summary>
/// Return the field name for the specified index
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Name of the field</returns>
public override string Name(int index)
{
return mStruct.Name(index);
}
/// <summary>
/// Returns the passed in value?
/// </summary>
/// <param name="memberName"></param>
/// <returns></returns>
public override string Name(string memberName)
{
return mStruct.Name(memberName);
}
/// <summary>
/// Returns the specified child structure
/// </summary>
/// <param name="index">Field index</param>
/// <returns>MessageStruct for the specified field</returns>
public override MessageStruct Struct(int index)
{
return mStruct.Struct(index);
}
/// <summary>
/// Returns the specified child structure
/// </summary>
/// <param name="name">Field name</param>
/// <returns>MessageStruct for the specified field</returns>
public override MessageStruct Struct(string name)
{
return mStruct.Struct(name);
}
/// <summary>
/// Returns the specified field value
/// </summary>
/// <typeparam name="FieldType">Type of the field</typeparam>
/// <param name="index">Field index</param>
/// <returns>Field value cast to the specified FieldType</returns>
public override FieldType Value<FieldType>(int index)
{
return mStruct.Value<FieldType>(index);
}
/// <summary>
/// Returns the specified field value
/// </summary>
/// <typeparam name="FieldType">Type of the field</typeparam>
/// <param name="name">Field name</param>
/// <returns>Field value cast to the specified FieldType</returns>
public override FieldType Value<FieldType>(string name)
{
return mStruct.Value<FieldType>(name);
}
/// <summary>
/// Returns the raw bytes of the specified field
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Raw field value</returns>
public override byte[] RawValue(int index)
{
return mStruct.RawValue(index);
}
/// <summary>
/// Returns the raw bytes of the specified field
/// </summary>
/// <param name="name">Field name</param>
/// <returns>Raw field value</returns>
public override byte[] RawValue(string name)
{
return mStruct.RawValue(name);
}
internal static void Initialize(string xmlFile)
{
mRecv = new Dictionary<int, MemberParser>();
mSend = new Dictionary<int, MemberParser>();
mTypes = new Dictionary<string, MemberParser>();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(xmlFile);
foreach (XmlNode item in xmlDocument.SelectNodes("/schema/datatypes/type"))
{
ParseType(item, xmlDocument);
}
foreach (XmlNode item2 in xmlDocument.SelectNodes("/schema/messages/message"))
{
ParseMessage(item2, xmlDocument);
}
}
private static void ParseType(XmlNode node, XmlDocument doc)
{
XmlAttribute xmlAttribute = node.Attributes["name"];
if (xmlAttribute == null)
{
return;
}
string value = xmlAttribute.Value;
if (mTypes.ContainsKey(value))
{
return;
}
MemberParser memberParser = new MemberParser();
mTypes.Add(value, memberParser);
xmlAttribute = node.Attributes["primitive"];
if (xmlAttribute != null && string.Compare(xmlAttribute.Value, "true", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
if (string.Compare(value, "BYTE", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.BYTE;
}
else if (string.Compare(value, "WORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.WORD;
}
else if (string.Compare(value, "PackedWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.PackedWORD;
}
else if (string.Compare(value, "DWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.DWORD;
}
else if (string.Compare(value, "PackedDWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.PackedDWORD;
}
else if (string.Compare(value, "QWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.QWORD;
}
else if (string.Compare(value, "float", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.@float;
}
else if (string.Compare(value, "double", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.@double;
}
else if (string.Compare(value, "String", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.String;
}
else if (string.Compare(value, "WString", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.WString;
}
}
else
{
memberParser.MemberType = MemberParserType.Struct;
memberParser.Child = ParseStruct(node.ChildNodes, doc);
}
}
private static void ParseMessage(XmlNode node, XmlDocument doc)
{
XmlAttribute xmlAttribute = node.Attributes["type"];
if (xmlAttribute == null)
{
return;
}
string text = xmlAttribute.Value;
if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
{
text = text.Substring(2);
}
int key = int.Parse(text, NumberStyles.HexNumber);
bool flag = true;
bool flag2 = false;
xmlAttribute = node.Attributes["direction"];
if (xmlAttribute != null)
{
if (string.Compare(xmlAttribute.Value, "outbound", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
flag = false;
flag2 = true;
}
else if (string.Compare(xmlAttribute.Value, "both", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
flag2 = true;
}
}
if ((flag && !mRecv.ContainsKey(key)) || (flag2 && !mSend.ContainsKey(key)))
{
MemberParser value = ParseStruct(node.ChildNodes, doc);
if (flag && !mRecv.ContainsKey(key))
{
mRecv.Add(key, value);
}
if (flag2 && !mSend.ContainsKey(key))
{
mSend.Add(key, value);
}
}
}
private static MemberParser ParseStruct(XmlNodeList nodes, XmlDocument doc)
{
MemberParser memberParser = new MemberParser();
MemberParser memberParser2 = memberParser;
int count = nodes.Count;
for (int i = 0; i < count; i++)
{
XmlNode xmlNode = nodes[i];
if (xmlNode.NodeType != XmlNodeType.Element)
{
continue;
}
string name = xmlNode.Name;
if (string.Compare(name, "field", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
XmlAttribute xmlAttribute = xmlNode.Attributes["type"];
if (xmlAttribute != null)
{
string value = xmlAttribute.Value;
if (!mTypes.ContainsKey(value))
{
ParseType(doc.SelectSingleNode("/schema/datatypes/type[@name='" + value + "']"), doc);
}
memberParser2.Next = new MemberParser(mTypes[value]);
memberParser2 = memberParser2.Next;
memberParser2.MemberName = xmlNode.Attributes["name"].Value;
}
}
else if (string.Compare(name, "maskmap", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
XmlAttribute xmlAttribute = xmlNode.Attributes["xor"];
long conditionXor = 0L;
string value;
if (xmlAttribute != null)
{
value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
conditionXor = long.Parse(value, NumberStyles.HexNumber);
}
value = xmlNode.Attributes["name"].Value;
memberParser2.Next = ParseMaskMap(xmlNode.ChildNodes, doc);
while (memberParser2.Next != null)
{
memberParser2 = memberParser2.Next;
memberParser2.Condition = MemberParserCondition.NE;
memberParser2.ConditionResult = 0L;
memberParser2.ConditionField = value;
memberParser2.ConditionXor = conditionXor;
}
}
else if (string.Compare(name, "switch", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
string value = xmlNode.Attributes["name"].Value;
XmlAttribute xmlAttribute = xmlNode.Attributes["mask"];
long conditionXor = -1L;
if (xmlAttribute != null)
{
value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
conditionXor = long.Parse(value, NumberStyles.HexNumber);
}
memberParser2.Next = ParseSwitch(xmlNode.ChildNodes, doc);
while (memberParser2.Next != null)
{
memberParser2 = memberParser2.Next;
memberParser2.Condition = MemberParserCondition.EQ;
memberParser2.ConditionField = value;
memberParser2.ConditionAnd = conditionXor;
}
}
else if (string.Compare(name, "vector", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.Next = new MemberParser();
memberParser2 = memberParser2.Next;
memberParser2.MemberType = MemberParserType.Vector;
memberParser2.MemberName = xmlNode.Attributes["name"].Value;
memberParser2.LengthField = xmlNode.Attributes["length"].Value;
XmlAttribute xmlAttribute = xmlNode.Attributes["mask"];
long conditionXor = -1L;
if (xmlAttribute != null)
{
string value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
conditionXor = long.Parse(value, NumberStyles.HexNumber);
}
memberParser2.LengthMask = conditionXor;
xmlAttribute = xmlNode.Attributes["skip"];
int num = 0;
if (xmlAttribute != null)
{
string value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
num = int.Parse(value, NumberStyles.HexNumber);
}
memberParser2.LengthDelta = -num;
memberParser2.Child = ParseStruct(xmlNode.ChildNodes, doc);
}
else if (string.Compare(name, "align", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
string value = xmlNode.Attributes["type"].Value;
if (string.Compare(value, "WORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.PostAlignment = 2;
}
else if (string.Compare(value, "DWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.PostAlignment = 4;
}
else if (string.Compare(value, "QWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.PostAlignment = 8;
}
}
}
if (memberParser.PostAlignment != 0 && memberParser.Next != null)
{
memberParser.Next.PreAlignment = memberParser.PostAlignment;
}
return memberParser.Next;
}
private static MemberParser ParseMaskMap(XmlNodeList nodes, XmlDocument doc)
{
MemberParser memberParser = new MemberParser();
MemberParser memberParser2 = memberParser;
int count = nodes.Count;
for (int i = 0; i < count; i++)
{
XmlNode xmlNode = nodes[i];
if (xmlNode.NodeType != XmlNodeType.Element || string.Compare(xmlNode.Name, "mask", ignoreCase: true, CultureInfo.InvariantCulture) != 0)
{
continue;
}
long conditionAnd = 0L;
XmlAttribute xmlAttribute = xmlNode.Attributes["value"];
if (xmlAttribute != null)
{
string text = xmlAttribute.Value;
if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
{
text = text.Substring(2);
}
conditionAnd = long.Parse(text, NumberStyles.HexNumber);
}
memberParser2.Next = new MemberParser();
memberParser2 = memberParser2.Next;
memberParser2.MemberType = MemberParserType.Case;
memberParser2.ConditionAnd = conditionAnd;
memberParser2.Child = ParseStruct(xmlNode.ChildNodes, doc);
}
return memberParser.Next;
}
private static MemberParser ParseSwitch(XmlNodeList nodes, XmlDocument doc)
{
MemberParser memberParser = new MemberParser();
MemberParser memberParser2 = memberParser;
int count = nodes.Count;
for (int i = 0; i < count; i++)
{
XmlNode xmlNode = nodes[i];
if (xmlNode.NodeType != XmlNodeType.Element || string.Compare(xmlNode.Name, "case", ignoreCase: true, CultureInfo.InvariantCulture) != 0)
{
continue;
}
long conditionResult = 0L;
XmlAttribute xmlAttribute = xmlNode.Attributes["value"];
if (xmlAttribute != null)
{
string text = xmlAttribute.Value;
if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
{
text = text.Substring(2);
}
conditionResult = long.Parse(text, NumberStyles.HexNumber);
}
memberParser2.Next = new MemberParser();
memberParser2 = memberParser2.Next;
memberParser2.MemberType = MemberParserType.Case;
memberParser2.ConditionResult = conditionResult;
memberParser2.Child = ParseStruct(xmlNode.ChildNodes, doc);
}
return memberParser.Next;
}
}

View file

@ -0,0 +1,16 @@
namespace Decal.Adapter;
/// <summary>
/// Message Direction
/// </summary>
public enum MessageDirection
{
/// <summary>
/// Server to Client message
/// </summary>
Inbound,
/// <summary>
/// Client to Server message
/// </summary>
Outbound
}

View file

@ -0,0 +1,31 @@
using System;
using System.Runtime.InteropServices;
namespace Decal.Adapter;
public class MessageProcessedEventArgs : EventArgs
{
private Message myMessage;
private int myData;
private int mySize;
public Message Message => myMessage;
public int Data => myData;
public int Size => mySize;
internal MessageProcessedEventArgs(int pbData, int dwSize)
{
if (pbData != 0 && dwSize != 0)
{
byte[] array = (byte[])Array.CreateInstance(typeof(byte), dwSize);
Marshal.Copy(new IntPtr(pbData), array, 0, dwSize);
myMessage = new Message(array, Message.GetParser(BitConverter.ToInt32(array, 0), MessageDirection.Inbound));
}
myData = pbData;
mySize = dwSize;
}
}

View file

@ -0,0 +1,676 @@
using System;
using System.Globalization;
using System.Text;
using Decal.Adapter.NetParser;
using Decal.Adapter.Support;
namespace Decal.Adapter;
/// <summary>
/// Represents Message data
/// </summary>
public class MessageStruct : MarshalByRefObject
{
internal struct MessageField
{
internal string Name;
internal MemberParserType Type;
internal object Value;
internal int Offset;
internal int Length;
}
internal byte[] mData;
internal int mOffset;
internal int mLength;
internal MemberParser mParser;
internal MessageStruct mParent;
internal int mIndex;
internal bool mParsed;
internal int mCount;
internal MessageField[] mFields;
/// <summary>
/// Returns the number of fields (or vector length)
/// </summary>
public virtual int Count
{
get
{
if (!mParsed)
{
Parse();
}
return mCount;
}
}
/// <summary>
/// Returns the specified field data
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Field value</returns>
public virtual object this[int index]
{
get
{
if (!mParsed)
{
Parse();
}
if (index >= 0 && index < mCount)
{
return mFields[index].Value;
}
return null;
}
}
/// <summary>
/// Returns the specified field data
/// </summary>
/// <param name="name">Field name</param>
/// <returns>Field value</returns>
public virtual object this[string name]
{
get
{
if (!mParsed)
{
Parse();
}
int num = IndexFromName(name);
if (num >= 0 && num < mCount)
{
return mFields[num].Value;
}
return null;
}
}
/// <summary>
/// Returns the raw bytes for this field
/// </summary>
public virtual byte[] RawData
{
get
{
if (mParent != null)
{
return mParent.RawValue(mIndex);
}
byte[] array = (byte[])Array.CreateInstance(typeof(byte), mData.Length);
Buffer.BlockCopy(mData, 0, array, 0, mData.Length);
return array;
}
}
/// <summary>
/// Returns the next object in the (parent) vector
/// </summary>
public virtual object Next
{
get
{
if (mParent == null)
{
return null;
}
return mParent[mIndex + 1];
}
}
/// <summary>
/// Returns the parent field
/// </summary>
public virtual MessageStruct Parent => mParent;
internal MessageStruct()
{
}
internal MessageStruct(byte[] Data, int Offset, MemberParser Parser)
{
mData = (byte[])Array.CreateInstance(typeof(byte), Data.Length);
Buffer.BlockCopy(Data, 0, mData, 0, mData.Length);
mOffset = Offset;
mParser = Parser;
mCount = -1;
}
internal MessageStruct(byte[] Data, int Offset, MemberParser Parser, MessageStruct Parent, int Index)
{
mData = Data;
mOffset = Offset;
mParser = Parser;
mParent = Parent;
mIndex = Index;
mCount = -1;
}
internal MessageStruct(byte[] Data, int Offset, MemberParser Parser, int Length, MessageStruct Parent, int Index)
{
mData = Data;
mOffset = Offset;
mParser = Parser;
mParent = Parent;
mIndex = Index;
mCount = Length;
}
internal int ObjectToIndex(object vIndex)
{
string text = vIndex as string;
int num = -1;
num = (string.IsNullOrEmpty(text) ? Util.UnboxTo<int>(vIndex) : IndexFromName(text));
if (num >= 0 && num < mCount)
{
return num;
}
return -1;
}
/// <summary>
/// Return the field name for the specified index
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Name of the field</returns>
public virtual string Name(int index)
{
if (!mParsed)
{
Parse();
}
if (index >= 0 && index < mCount)
{
return mFields[index].Name;
}
return null;
}
/// <summary>
/// Returns the passed in value?
/// </summary>
/// <param name="memberName"></param>
/// <returns></returns>
public virtual string Name(string memberName)
{
if (!mParsed)
{
Parse();
}
int num = IndexFromName(memberName);
if (num >= 0 && num < mCount)
{
return mFields[num].Name;
}
return null;
}
/// <summary>
/// Returns the specified child structure
/// </summary>
/// <param name="index">Field index</param>
/// <returns>MessageStruct for the specified field</returns>
public virtual MessageStruct Struct(int index)
{
if (!mParsed)
{
Parse();
}
if (index >= 0 && index < mCount)
{
MemberParserType type = mFields[index].Type;
if (type == MemberParserType.Struct || type == MemberParserType.Vector)
{
return mFields[index].Value as MessageStruct;
}
}
return null;
}
/// <summary>
/// Returns the specified child structure
/// </summary>
/// <param name="name">Field name</param>
/// <returns>MessageStruct for the specified field</returns>
public virtual MessageStruct Struct(string name)
{
if (!mParsed)
{
Parse();
}
int num = IndexFromName(name);
if (num >= 0 && num < mCount)
{
MemberParserType type = mFields[num].Type;
if (type == MemberParserType.Struct || type == MemberParserType.Vector)
{
return mFields[num].Value as MessageStruct;
}
}
return null;
}
/// <summary>
/// Returns the specified field value
/// </summary>
/// <typeparam name="FieldType">Type of the field</typeparam>
/// <param name="index">Field index</param>
/// <returns>Field value cast to the specified FieldType</returns>
public virtual FieldType Value<FieldType>(int index)
{
if (!mParsed)
{
Parse();
}
if (index >= 0 && index < mCount)
{
return Util.UnboxTo<FieldType>(mFields[index].Value);
}
return default(FieldType);
}
/// <summary>
/// Returns the specified field value
/// </summary>
/// <typeparam name="FieldType">Type of the field</typeparam>
/// <param name="name">Field name</param>
/// <returns>Field value cast to the specified FieldType</returns>
public virtual FieldType Value<FieldType>(string name)
{
if (!mParsed)
{
Parse();
}
int num = IndexFromName(name);
if (num >= 0 && num < mCount)
{
return Util.UnboxTo<FieldType>(mFields[num].Value);
}
return default(FieldType);
}
/// <summary>
/// Returns the raw bytes of the specified field
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Raw field value</returns>
public virtual byte[] RawValue(int index)
{
if (!mParsed)
{
Parse();
}
if (index >= 0 && index < mCount)
{
int length = mFields[index].Length;
byte[] array = (byte[])Array.CreateInstance(typeof(byte), length);
Buffer.BlockCopy(mData, mFields[index].Offset, array, 0, length);
return array;
}
return null;
}
/// <summary>
/// Returns the raw bytes of the specified field
/// </summary>
/// <param name="name">Field name</param>
/// <returns>Raw field value</returns>
public virtual byte[] RawValue(string name)
{
if (!mParsed)
{
Parse();
}
int num = IndexFromName(name);
if (num >= 0 && num < mCount)
{
int length = mFields[num].Length;
byte[] array = (byte[])Array.CreateInstance(typeof(byte), length);
Buffer.BlockCopy(mData, mFields[num].Offset, array, 0, length);
return array;
}
return null;
}
internal int IndexFromName(string Name)
{
int num = mCount;
for (int i = 0; i < num; i++)
{
if (string.Compare(Name, mFields[i].Name, ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
return i;
}
}
return -1;
}
internal void Parse()
{
if (mCount == -1)
{
ParseStruct();
}
else
{
ParseVector();
}
}
internal void ParseStruct()
{
int length = ParseCounter(mParser);
mFields = (MessageField[])Array.CreateInstance(typeof(MessageField), length);
mParsed = true;
int ByteIndex = mOffset;
mCount = 0;
ParseHelper(mParser, ref mCount, ref ByteIndex);
mLength = ByteIndex - mOffset;
MessageField[] sourceArray = mFields;
mFields = (MessageField[])Array.CreateInstance(typeof(MessageField), mCount);
Array.Copy(sourceArray, mFields, mCount);
}
internal void ParseVector()
{
int num = mCount;
mFields = (MessageField[])Array.CreateInstance(typeof(MessageField), num);
mParsed = true;
int num2 = mOffset;
for (int i = 0; i < num; i++)
{
mFields[i].Name = i.ToString();
mFields[i].Offset = num2;
mFields[i].Type = MemberParserType.Struct;
MessageStruct messageStruct = new MessageStruct(mData, num2, mParser, this, i);
messageStruct.ParseStruct();
mFields[i].Value = messageStruct;
mFields[i].Length = messageStruct.mLength;
num2 += messageStruct.mLength;
}
mLength = num2 - mOffset;
}
internal int ParseCounter(MemberParser Parser)
{
int num = 0;
while (Parser != null)
{
num = ((Parser.MemberType != MemberParserType.Case) ? (num + 1) : (num + ParseCounter(Parser.Child)));
Parser = Parser.Next;
}
return num;
}
internal void ParseHelper(MemberParser Parser, ref int FieldIndex, ref int ByteIndex)
{
Encoding encoding = Encoding.GetEncoding(1252);
while (Parser != null)
{
if (Parser.PreAlignment != 0)
{
int num = ByteIndex % Parser.PreAlignment;
if (num != 0)
{
ByteIndex += Parser.PreAlignment - num;
}
}
bool flag = Parser.Condition == MemberParserCondition.None;
if (!flag)
{
MessageStruct messageStruct = this;
object obj;
do
{
obj = messageStruct[Parser.ConditionField];
if (obj != null)
{
break;
}
messageStruct = messageStruct.mParent;
}
while (messageStruct != null);
if (obj != null)
{
long num2 = 0L;
Type type = obj.GetType();
if (type.Equals(typeof(int)))
{
num2 = Convert.ToInt64(obj);
num2 &= 0xFFFFFFFFu;
}
else if (type.Equals(typeof(short)))
{
num2 = Convert.ToInt64(obj);
num2 &= 0xFFFF;
}
else if (type.Equals(typeof(byte)))
{
num2 = Convert.ToInt64(obj);
num2 &= 0xFF;
}
else if (type.Equals(typeof(long)))
{
num2 = Convert.ToInt64(obj);
}
num2 ^= Parser.ConditionXor;
num2 &= Parser.ConditionAnd;
switch (Parser.Condition)
{
case MemberParserCondition.EQ:
flag = num2 == Parser.ConditionResult;
break;
case MemberParserCondition.NE:
flag = num2 != Parser.ConditionResult;
break;
case MemberParserCondition.GE:
flag = num2 >= Parser.ConditionResult;
break;
case MemberParserCondition.GT:
flag = num2 > Parser.ConditionResult;
break;
case MemberParserCondition.LE:
flag = num2 <= Parser.ConditionResult;
break;
case MemberParserCondition.LT:
flag = num2 < Parser.ConditionResult;
break;
}
}
}
if (flag)
{
mFields[FieldIndex].Name = Parser.MemberName;
mFields[FieldIndex].Offset = ByteIndex;
mFields[FieldIndex].Type = Parser.MemberType;
switch (Parser.MemberType)
{
case MemberParserType.BYTE:
mFields[FieldIndex].Value = mData[ByteIndex++];
break;
case MemberParserType.WORD:
mFields[FieldIndex].Value = BitConverter.ToInt16(mData, ByteIndex);
ByteIndex += 2;
break;
case MemberParserType.PackedWORD:
{
int num6 = mData[ByteIndex++];
if ((num6 & 0x80) != 0)
{
num6 = ((num6 & 0x7F) << 8) | mData[ByteIndex++];
}
mFields[FieldIndex].Value = num6;
break;
}
case MemberParserType.DWORD:
mFields[FieldIndex].Value = BitConverter.ToInt32(mData, ByteIndex);
ByteIndex += 4;
break;
case MemberParserType.PackedDWORD:
{
int num6 = BitConverter.ToInt16(mData, ByteIndex);
ByteIndex += 2;
if ((num6 & 0x8000) != 0)
{
num6 = ((num6 & 0x7FFF) << 16) | (BitConverter.ToInt16(mData, ByteIndex) & 0xFFFF);
ByteIndex += 2;
}
mFields[FieldIndex].Value = num6;
break;
}
case MemberParserType.QWORD:
mFields[FieldIndex].Value = BitConverter.ToInt64(mData, ByteIndex);
ByteIndex += 8;
break;
case MemberParserType.@float:
mFields[FieldIndex].Value = BitConverter.ToSingle(mData, ByteIndex);
ByteIndex += 4;
break;
case MemberParserType.@double:
mFields[FieldIndex].Value = BitConverter.ToDouble(mData, ByteIndex);
ByteIndex += 8;
break;
case MemberParserType.String:
{
int num6 = BitConverter.ToInt16(mData, ByteIndex);
ByteIndex += 2;
if (num6 == -1)
{
num6 = BitConverter.ToInt32(mData, ByteIndex);
ByteIndex += 4;
}
StringBuilder stringBuilder = new StringBuilder(num6);
for (int j = 0; j < num6; j++)
{
stringBuilder.Append(encoding.GetChars(mData, ByteIndex++, 1));
}
mFields[FieldIndex].Value = stringBuilder.ToString();
ByteIndex = (ByteIndex + 3) & -4;
break;
}
case MemberParserType.WString:
{
int num6 = mData[ByteIndex++];
if ((num6 & 0x80) != 0)
{
num6 = ((num6 & 0x7F) << 8) | mData[ByteIndex++];
}
StringBuilder stringBuilder = new StringBuilder(num6);
for (int i = 0; i < num6; i++)
{
stringBuilder.Append(BitConverter.ToChar(mData, ByteIndex));
ByteIndex += 2;
}
mFields[FieldIndex].Value = stringBuilder.ToString();
break;
}
case MemberParserType.Struct:
{
MessageStruct messageStruct = new MessageStruct(mData, ByteIndex, Parser.Child, this, FieldIndex);
messageStruct.ParseStruct();
ByteIndex += messageStruct.mLength;
mFields[FieldIndex].Value = messageStruct;
break;
}
case MemberParserType.Vector:
{
MessageStruct messageStruct = this;
object obj;
do
{
obj = messageStruct[Parser.LengthField];
if (obj != null)
{
break;
}
messageStruct = messageStruct.mParent;
}
while (messageStruct != null);
long num4 = 0L;
if (obj != null)
{
Type type2 = obj.GetType();
if (type2.Equals(typeof(int)))
{
num4 = Convert.ToInt64(obj);
num4 &= 0xFFFFFFFFu;
}
else if (type2.Equals(typeof(short)))
{
num4 = Convert.ToInt64(obj);
num4 &= 0xFFFF;
}
else if (type2.Equals(typeof(byte)))
{
num4 = Convert.ToInt64(obj);
num4 &= 0xFF;
}
else if (type2.Equals(typeof(long)))
{
num4 = Convert.ToInt64(obj);
}
}
long num5 = Parser.LengthMask;
num4 &= num5;
if (num5 != 0L)
{
while ((num5 & 1) == 0L)
{
num4 >>= 1;
num5 >>= 1;
}
}
messageStruct = new MessageStruct(mData, ByteIndex, Parser.Child, (int)num4 + Parser.LengthDelta, this, FieldIndex);
messageStruct.ParseVector();
ByteIndex += messageStruct.mLength;
mFields[FieldIndex].Value = messageStruct;
break;
}
case MemberParserType.Case:
{
int num3 = FieldIndex;
ParseHelper(Parser.Child, ref FieldIndex, ref ByteIndex);
if (FieldIndex > num3)
{
FieldIndex--;
}
break;
}
}
mFields[FieldIndex].Length = ByteIndex - mFields[FieldIndex].Offset;
}
if (Parser.PostAlignment != 0)
{
int num7 = ByteIndex % Parser.PostAlignment;
if (num7 != 0)
{
num7 = Parser.PostAlignment - num7;
ByteIndex += num7;
if (flag)
{
mFields[FieldIndex].Length += num7;
}
}
}
if (flag)
{
FieldIndex++;
}
Parser = Parser.Next;
}
}
}

View file

@ -0,0 +1,15 @@
using System;
namespace Decal.Adapter;
public class NetworkMessageEventArgs : EventArgs
{
private Message myMsg;
public Message Message => myMsg;
internal NetworkMessageEventArgs(Message msg)
{
myMsg = msg;
}
}

View file

@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Decal.Adapter.Wrappers;
namespace Decal.Adapter;
/// <summary>
/// Base class used to create Decal Plugins
/// </summary>
[CLSCompliant(true)]
public abstract class PluginBase : Extension, IViewHandler
{
private PluginHost myHost;
private EventHandler myGraphicsReset;
private BindingFlags myBindingFlags;
private Dictionary<string, ViewWrapper> myViews;
/// <summary>
/// Wrapper Object to the Host.
/// Similar to IPluginSite
/// </summary>
protected PluginHost Host => myHost;
/// <summary>
/// The Default view
/// </summary>
public ViewWrapper DefaultView => myViews["Default"];
/// <summary>
/// BindingFlags for internal scanning
/// </summary>
public BindingFlags BindingFlags => myBindingFlags;
[CLSCompliant(false)]
protected event EventHandler<NetworkMessageEventArgs> ServerDispatch
{
add
{
if (base.Core.EchoFilter != null)
{
base.Core.EchoFilter.ServerDispatch += value;
}
}
remove
{
if (base.Core.EchoFilter != null)
{
base.Core.EchoFilter.ServerDispatch -= value;
}
}
}
[CLSCompliant(false)]
protected event EventHandler<NetworkMessageEventArgs> ClientDispatch
{
add
{
if (base.Core.EchoFilter != null)
{
base.Core.EchoFilter.ClientDispatch += value;
}
}
remove
{
if (base.Core.EchoFilter != null)
{
base.Core.EchoFilter.ClientDispatch -= value;
}
}
}
protected event EventHandler GraphicsReset
{
add
{
myGraphicsReset = (EventHandler)Delegate.Combine(myGraphicsReset, value);
if (myHost != null)
{
myHost.Render.DeviceLost += value;
}
}
remove
{
myGraphicsReset = (EventHandler)Delegate.Remove(myGraphicsReset, value);
if (myHost != null)
{
myHost.Render.DeviceLost -= value;
}
}
}
/// <summary>
/// Default Constructor for the Base class. Should be called by all decendants.
/// </summary>
protected PluginBase()
: base(DecalExtensionType.Plugin)
{
myBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
}
/// <summary>
/// Called by the base class to Wire Up events.
/// </summary>
internal override void Wireup()
{
if (myGraphicsReset != null)
{
Host.Render.DeviceLost += myGraphicsReset;
}
scanBaseEvents(connect: true);
myViews = new Dictionary<string, ViewWrapper>();
PluginHost.LoadViewHandler(this);
}
/// <summary>
/// Called by the base class to Unwire events
/// </summary>
internal override void UnWire()
{
if (myGraphicsReset != null)
{
Host.Render.DeviceLost -= myGraphicsReset;
}
scanBaseEvents(connect: false);
foreach (ViewWrapper value in myViews.Values)
{
value.Dispose();
}
myViews.Clear();
}
/// <summary>
/// Used for internal wiring up of base-class variables.
/// Called by PluginProxy
/// </summary>
/// <param name="newHost">Host (pluginsite) object</param>
internal void SetHost(PluginHost newHost)
{
myHost = newHost;
}
private void scanBaseEvents(bool connect)
{
Type type = GetType();
Type type2 = base.Core.GetType();
if (!Attribute.IsDefined(type, typeof(WireUpBaseEventsAttribute)))
{
return;
}
MethodInfo[] methods = type.GetMethods(BindingFlags);
foreach (MethodInfo methodInfo in methods)
{
if (!Attribute.IsDefined(methodInfo, typeof(BaseEventAttribute)))
{
continue;
}
Attribute[] customAttributes = Attribute.GetCustomAttributes(methodInfo, typeof(BaseEventAttribute));
for (int j = 0; j < customAttributes.Length; j++)
{
BaseEventAttribute baseEventAttribute = (BaseEventAttribute)customAttributes[j];
object obj;
Type type3;
if (baseEventAttribute.FilterName == string.Empty)
{
obj = this;
type3 = type;
}
else
{
PropertyInfo property = type2.GetProperty(baseEventAttribute.FilterName, BindingFlags.Instance | BindingFlags.Public);
if (property == null)
{
continue;
}
obj = property.GetValue(base.Core, null);
type3 = obj.GetType();
}
EventInfo eventInfo = null;
while ((eventInfo = type3.GetEvent(baseEventAttribute.EventName, BindingFlags)) == null && type3 == type)
{
type3 = type2;
obj = base.Core;
}
if (!(eventInfo == null))
{
if (connect)
{
eventInfo.GetAddMethod(nonPublic: true).Invoke(obj, new object[1] { Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo.Name) });
}
else
{
eventInfo.GetRemoveMethod(nonPublic: true).Invoke(obj, new object[1] { Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo.Name) });
}
}
}
}
}
/// <summary>
/// Loads a new view into the internal list (should only be called internally)
/// </summary>
/// <param name="name">view name</param>
/// <param name="resource">resource path</param>
public void LoadView(string name, string resource)
{
myViews.Add(name, Host.LoadViewResource(resource, GetType().Assembly));
}
/// <summary>
/// Retrieves a view from the internal list
/// </summary>
/// <param name="name">view name</param>
/// <returns>the specified view or null</returns>
public ViewWrapper GetView(string name)
{
if (myViews.TryGetValue(name, out var value))
{
return value;
}
return null;
}
}

View file

@ -0,0 +1,71 @@
using System;
using Decal.Adapter.Support;
using Decal.Adapter.Wrappers;
using Decal.Interop.Core;
namespace Decal.Adapter;
/// <summary>
///
/// </summary>
public sealed class PluginProxy : IPlugin2, IDecalDirectory
{
private PluginHost mySite;
private PluginBase myWrapped;
internal PluginProxy(PluginBase toWrap)
{
myWrapped = toWrap;
}
void IPlugin2.Initialize(PluginSite2 Site)
{
mySite = new PluginHost(Site);
myWrapped.SetHost(mySite);
try
{
myWrapped.standardEvent(ExtensionEvents.InternalWireup);
}
catch (Exception ex)
{
Util.WriteLine("InternalWireup Exception: " + ex.Message);
}
try
{
myWrapped.standardEvent(ExtensionEvents.Startup);
}
catch (Exception ex2)
{
Util.WriteLine("Startup Exception: " + ex2.Message);
}
}
void IPlugin2.Terminate()
{
try
{
myWrapped.standardEvent(ExtensionEvents.Shutdown);
}
catch (Exception ex)
{
Util.WriteLine("Shutdown Exception: " + ex.Message);
}
try
{
myWrapped.standardEvent(ExtensionEvents.InternalUnwire);
}
catch (Exception ex2)
{
Util.WriteLine("InternalUnwire Exception: " + ex2.Message);
}
mySite.Dispose();
mySite = null;
myWrapped = null;
}
object IDecalDirectory.Lookup(string strName)
{
return myWrapped.ResolvePath(strName);
}
}

View file

@ -0,0 +1,33 @@
using System;
using System.Drawing;
namespace Decal.Adapter;
public class RegionChange3DEventArgs : EventArgs
{
private int myLeft;
private int myRight;
private int myTop;
private int myBottom;
public int Left => myLeft;
public int Right => myRight;
public int Top => myTop;
public int Bottom => myBottom;
public Rectangle Rect => new Rectangle(myLeft, myTop, myRight - myLeft, myBottom - myTop);
internal RegionChange3DEventArgs(int left, int top, int right, int bottom)
{
myLeft = left;
myTop = top;
myRight = right;
myBottom = bottom;
}
}

View file

@ -0,0 +1,11 @@
using System;
namespace Decal.Adapter;
internal class RenderViolationException : Exception
{
internal RenderViolationException(string message)
: base(message)
{
}
}

View file

@ -0,0 +1,53 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Decal.Adapter;
internal static class RuntimePolicyHelper
{
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("BD39D1D2-BA2F-486A-89B0-B4B0CB466891")]
private interface ICLRRuntimeInfo
{
void xGetVersionString();
void xGetRuntimeDirectory();
void xIsLoaded();
void xIsLoadable();
void xLoadErrorString();
void xLoadLibrary();
void xGetProcAddress();
void xGetInterface();
void xSetDefaultStartupFlags();
void xGetDefaultStartupFlags();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void BindAsLegacyV2Runtime();
}
public static bool LegacyV2RuntimeEnabledSuccessfully { get; private set; }
static RuntimePolicyHelper()
{
ICLRRuntimeInfo iCLRRuntimeInfo = (ICLRRuntimeInfo)RuntimeEnvironment.GetRuntimeInterfaceAsObject(Guid.Empty, typeof(ICLRRuntimeInfo).GUID);
try
{
iCLRRuntimeInfo.BindAsLegacyV2Runtime();
LegacyV2RuntimeEnabledSuccessfully = true;
}
catch (COMException)
{
LegacyV2RuntimeEnabledSuccessfully = false;
}
}
}

View file

@ -0,0 +1,36 @@
namespace Decal.Adapter;
public abstract class ServiceBase : Extension
{
internal enum ServiceEventType
{
BeforePlugins,
AfterPluigins
}
public ServiceBase()
: base(DecalExtensionType.Service)
{
}
internal void ServiceEvent(ServiceEventType evt)
{
switch (evt)
{
case ServiceEventType.BeforePlugins:
OnBeforePlugins();
break;
case ServiceEventType.AfterPluigins:
OnAfterPlugins();
break;
}
}
protected virtual void OnBeforePlugins()
{
}
protected virtual void OnAfterPlugins()
{
}
}

View file

@ -0,0 +1,38 @@
using Decal.Interop.Core;
namespace Decal.Adapter;
public sealed class ServiceProxy : IDecalService, IDecalDirectory
{
private ServiceBase wrapped;
internal ServiceProxy(ServiceBase toWrap)
{
wrapped = toWrap;
}
void IDecalService.AfterPlugins()
{
wrapped.ServiceEvent(ServiceBase.ServiceEventType.AfterPluigins);
}
void IDecalService.BeforePlugins()
{
wrapped.ServiceEvent(ServiceBase.ServiceEventType.BeforePlugins);
}
void IDecalService.Initialize(DecalCore pDecal)
{
wrapped.standardEvent(ExtensionEvents.Startup);
}
void IDecalService.Terminate()
{
wrapped.standardEvent(ExtensionEvents.Shutdown);
}
object IDecalDirectory.Lookup(string strName)
{
return wrapped.ResolvePath(strName);
}
}

View file

@ -0,0 +1,12 @@
namespace Decal.Adapter;
public class StatusTextInterceptEventArgs : EatableEventArgs
{
public string Text { get; protected set; }
internal StatusTextInterceptEventArgs(string text, bool eat)
: base(eat)
{
Text = text;
}
}

View file

@ -0,0 +1,266 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Decal.Adapter.Support;
using Decal.Interop.Core;
using Decal.Interop.Net;
using Microsoft.Win32;
namespace Decal.Adapter;
/// <summary>
///
/// </summary>
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IAdapterSurrogate))]
[ProgId("DecalAdapter.Surrogate")]
[Guid("71A69713-6593-47EC-0002-0000000DECA1")]
public sealed class Surrogate : MarshalByRefObject, IAdapterSurrogate, IDecalFileSurrogate
{
private string myAssemblyName;
private string myPath;
private string myTypeName;
string IAdapterSurrogate.Version
{
get
{
CoreManager current = CoreManager.Current;
if (current == null)
{
current = CoreManager.Current;
}
if (File.Exists(Path.Combine(myPath, myAssemblyName)))
{
return FileVersionInfo.GetVersionInfo(Path.Combine(myPath, myAssemblyName)).FileVersion;
}
return "";
}
}
bool IAdapterSurrogate.FileExists => File.Exists(Path.Combine(myPath, myAssemblyName));
string IAdapterSurrogate.FilePath => Path.Combine(myPath, myAssemblyName);
string IDecalFileSurrogate.Description => "Decal.Adapter Extension";
string IDecalFileSurrogate.Extension => "dll";
IntPtr IAdapterSurrogate.CreateInstance(DecalEnum pInitData, ref Guid riid)
{
if (CoreManager.ServiceRunning)
{
CoreManager current = CoreManager.Current;
try
{
myTypeName = (string)((IDecalEnum)pInitData).get_Property("Object");
myAssemblyName = (string)((IDecalEnum)pInitData).get_Property("Assembly");
myPath = (string)((IDecalEnum)pInitData).get_Property("Path");
Assembly assembly = ((!(pInitData.Group == "Plugins")) ? current.Assembly(myAssemblyName, myPath) : current.Assembly(myAssemblyName, myPath, current.PluginDomain));
Type type = assembly.GetType(myTypeName);
if (null == type)
{
throw new COMHResultException(HResults.E_FAIL);
}
IntPtr ppv;
if (type.IsSubclassOf(typeof(Extension)))
{
Extension extension = ((!type.IsSubclassOf(typeof(PluginBase))) ? ((Extension)Activator.CreateInstance(type, null)) : ((Extension)current.PluginDomain.CreateInstanceFromAndUnwrap(Path.Combine(myPath, myAssemblyName), myTypeName)));
extension.Path = myPath;
object obj = null;
switch (extension.ExtensionType)
{
case DecalExtensionType.Service:
if (extension is ServiceBase serviceBase)
{
current.AddService(serviceBase);
obj = new ServiceProxy(serviceBase);
}
break;
case DecalExtensionType.NetworkFilter:
if (extension is FilterBase filterBase)
{
current.AddFilter(filterBase);
obj = new FilterProxy(filterBase);
}
break;
case DecalExtensionType.Plugin:
if (extension is PluginBase pluginBase)
{
current.AddPlugin(pluginBase);
obj = new PluginProxy(pluginBase);
}
break;
}
IntPtr pUnk = ((obj == null) ? Marshal.GetIUnknownForObject(extension) : Marshal.GetIUnknownForObject(obj));
int num = Marshal.QueryInterface(pUnk, ref riid, out ppv);
Marshal.Release(pUnk);
if (num < 0)
{
throw new Exception();
}
return ppv;
}
object o = Activator.CreateInstance(type, null);
if (!type.IsSubclassOf(typeof(INetworkFilter)))
{
type.IsSubclassOf(typeof(INetworkFilter2));
}
IntPtr iUnknownForObject = Marshal.GetIUnknownForObject(o);
Marshal.QueryInterface(iUnknownForObject, ref riid, out ppv);
Marshal.Release(iUnknownForObject);
return ppv;
}
catch
{
throw new COMHResultException(HResults.E_FAIL);
}
finally
{
Marshal.ReleaseComObject(pInitData);
}
}
Marshal.ReleaseComObject(pInitData);
throw new COMHResultException(HResults.E_FAIL);
}
void IAdapterSurrogate.SetEnum(DecalEnum pInitData)
{
try
{
myTypeName = (string)((IDecalEnum)pInitData).get_Property("Object");
myAssemblyName = (string)((IDecalEnum)pInitData).get_Property("Assembly");
myPath = (string)((IDecalEnum)pInitData).get_Property("Path");
Marshal.ReleaseComObject(pInitData);
}
catch (COMException)
{
}
}
void IDecalFileSurrogate.Register(string Filename)
{
bool flag = false;
int num = 0;
int num2 = 0;
try
{
if (File.Exists(Filename))
{
Assembly assembly = Assembly.LoadFile(Filename);
string text = "";
if (Attribute.IsDefined(assembly, typeof(GuidAttribute)))
{
text = ((GuidAttribute)Attribute.GetCustomAttribute(assembly, typeof(GuidAttribute))).Value.ToUpper(CultureInfo.InvariantCulture);
}
Type[] types;
try
{
types = assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
types = ex.Types;
}
Type[] array = types;
foreach (Type type in array)
{
if (null == type || !type.IsPublic)
{
continue;
}
int num3 = 0;
if (!type.IsSubclassOf(typeof(Extension)))
{
continue;
}
string directoryName = Path.GetDirectoryName(Filename);
string fileName = Path.GetFileName(Filename);
string value = "";
string value2 = "{71A69713-6593-47EC-0002-0000000DECA1}";
string text2 = "";
if (type.IsSubclassOf(typeof(PluginBase)))
{
text2 = "Plugins";
num++;
num3 = num;
}
else
{
if (!type.IsSubclassOf(typeof(FilterBase)))
{
continue;
}
text2 = "NetworkFilters";
num2++;
num3 = num2;
}
if (Attribute.IsDefined(type, typeof(FriendlyNameAttribute)))
{
value = ((FriendlyNameAttribute)Attribute.GetCustomAttribute(type, typeof(FriendlyNameAttribute))).Name;
}
string text3 = type.Namespace.ToString() + "." + type.Name.ToString();
string text4 = "";
if (Attribute.IsDefined(type, typeof(GuidAttribute)))
{
text4 = ((GuidAttribute)Attribute.GetCustomAttribute(type, typeof(GuidAttribute))).Value.ToString();
}
else if (!string.IsNullOrEmpty(text) && num3 == 1)
{
text4 = text;
}
else if (!string.IsNullOrEmpty(text))
{
byte[] array2 = new Guid(text).ToByteArray();
array2[15] = (byte)(array2[15] ^ num3);
text4 = new Guid(array2).ToString();
}
else
{
text4 = Guid.NewGuid().ToString();
}
text4 = text4.ToUpper(CultureInfo.InvariantCulture);
string subkey = string.Format("SOFTWARE\\Decal\\{0}\\{1}", text2, "{" + text4 + "}");
Util.WriteLine("Registering Decal.Adapter extension (Type:" + type.ToString() + ")");
Util.WriteLine("Assembly Directory: " + directoryName);
Util.WriteLine("Assembly File: " + fileName);
Util.WriteLine("Assembly Object: " + text3);
Util.WriteLine("Extension Registry CLSID: " + text4);
RegistryKey registryKey = Registry.LocalMachine.CreateSubKey(subkey);
if (registryKey != null)
{
registryKey.SetValue("Enabled", 0, RegistryValueKind.DWord);
registryKey.SetValue("Assembly", fileName, RegistryValueKind.String);
registryKey.SetValue("Path", directoryName, RegistryValueKind.String);
registryKey.SetValue("Object", text3, RegistryValueKind.String);
registryKey.SetValue("Surrogate", value2, RegistryValueKind.String);
if (!string.IsNullOrEmpty(value))
{
registryKey.SetValue("", value, RegistryValueKind.String);
}
else
{
registryKey.SetValue("", text3, RegistryValueKind.String);
}
flag = true;
}
}
}
}
catch (Exception ex2)
{
Util.WriteLine("Exception registering plugin: " + ex2.ToString());
throw new COMHResultException(HResults.E_FAIL);
}
if (!flag)
{
throw new COMHResultException(HResults.E_FAIL);
}
}
}

View file

@ -0,0 +1,14 @@
namespace Decal.Adapter;
public class TextBoxChangeEventArgs : ControlEventArgs
{
private string text;
public string Text => text;
internal TextBoxChangeEventArgs(int ID, string text)
: base(ID)
{
this.text = text;
}
}

View file

@ -0,0 +1,14 @@
namespace Decal.Adapter;
public class TextBoxEndEventArgs : ControlEventArgs
{
private bool success;
public bool Success => success;
internal TextBoxEndEventArgs(int ID, bool success)
: base(ID)
{
this.success = success;
}
}

View file

@ -0,0 +1,26 @@
using System;
namespace Decal.Adapter;
/// <summary>
/// Defines a plugin view
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class ViewAttribute : ViewBaseAttribute
{
private string myResource;
/// <summary>
/// The resource to load
/// </summary>
public string Resource => myResource;
/// <summary>
/// Constructs a new view from the specified resource
/// </summary>
/// <param name="Resource">Embedded resource path</param>
public ViewAttribute(string resource)
{
myResource = resource;
}
}

View file

@ -0,0 +1,28 @@
using System;
namespace Decal.Adapter;
public abstract class ViewBaseAttribute : Attribute
{
private string myName;
/// <summary>
/// Name named attribute
/// </summary>
public string ViewName
{
get
{
return myName;
}
set
{
myName = value;
}
}
protected ViewBaseAttribute()
{
myName = "Default";
}
}

View file

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Decal.Adapter.Wrappers;
namespace Decal.Adapter;
[CLSCompliant(true)]
public class ViewHandler : IViewHandler, IDisposable
{
private Dictionary<string, ViewWrapper> myViews;
private BindingFlags myBindingFlags;
private PluginHost myHost;
private bool isDisposed;
protected bool IsDisposed => isDisposed;
protected PluginHost Host => myHost;
public ViewWrapper DefaultView => myViews["Default"];
public BindingFlags BindingFlags => myBindingFlags;
public ViewHandler(PluginHost host)
{
myBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
myViews = new Dictionary<string, ViewWrapper>();
myHost = host;
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing && myViews != null)
{
foreach (ViewWrapper value in myViews.Values)
{
value.Dispose();
}
myViews.Clear();
myViews = null;
}
isDisposed = true;
}
internal void LoadComplete()
{
OnLoad();
}
protected virtual void OnLoad()
{
}
public void LoadView(string name, string resource)
{
myViews.Add(name, Host.LoadViewResource(resource, GetType().Assembly));
}
public ViewWrapper GetView(string name)
{
if (myViews.TryGetValue(name, out var value))
{
return value;
}
return null;
}
}

View file

@ -0,0 +1,29 @@
namespace Decal.Adapter;
public class WindowMessageEventArgs : EatableEventArgs
{
private int myHwnd;
private short myMsg;
private int mywParam;
private int mylParam;
public int Hwnd => myHwnd;
public short Msg => myMsg;
public int WParam => mywParam;
public int LParam => mylParam;
internal WindowMessageEventArgs(int hwnd, short uMsg, int wParam, int lParam)
: base(eat: false)
{
myHwnd = hwnd;
myMsg = uMsg;
mywParam = wParam;
mylParam = lParam;
}
}

View file

@ -0,0 +1,8 @@
using System;
namespace Decal.Adapter;
[AttributeUsage(AttributeTargets.Class)]
public sealed class WireUpBaseEventsAttribute : Attribute
{
}

View file

@ -0,0 +1,8 @@
using System;
namespace Decal.Adapter;
[AttributeUsage(AttributeTargets.Class)]
public sealed class WireUpControlEventsAttribute : Attribute
{
}