Initial commit: Complete open-source Decal rebuild

All 5 phases of the open-source Decal rebuild:

Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil)
Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs
  - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters
  - Decal.Core, DecalControls, DecalRender, D3DService
Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL
Phase 4: DenAgent WinForms tray application
Phase 5: WiX installer and build script

25 C# projects building with 0 errors.
Native C++ projects require VS 2022 + Windows SDK (x86).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erik 2026-02-08 18:27:56 +01:00
commit d1442e3747
1382 changed files with 170725 additions and 0 deletions

View file

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Decal.DHS</AssemblyName>
<RootNamespace>Decal.DHS</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Decal.Interop.Core\Decal.Interop.Core.csproj" />
<ProjectReference Include="..\Decal.Interop.DHS\Decal.Interop.DHS.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,19 @@
using System.Runtime.InteropServices;
using Decal.Interop.DHS;
namespace Decal.DHS
{
[ComVisible(true)]
[Guid("F5AA853D-CCF3-4562-A654-3A68AB583BCC")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("DHS.Hotkey")]
public class HotkeyImpl : IHotkey
{
public string EventTitle { get; set; }
public string EventDescription { get; set; }
public bool AltState { get; set; }
public bool ControlState { get; set; }
public bool ShiftState { get; set; }
public int VirtualKey { get; set; }
}
}

View file

@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Decal.Interop.Core;
using Decal.Interop.DHS;
namespace Decal.DHS
{
internal class RegisteredHotkey
{
public string PluginCookie;
public HotkeyImpl Hotkey;
}
[ComVisible(true)]
[Guid("6B6B9FA8-37DE-4FA3-8C60-52BD6A2F9855")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(_IHotkeySystemEvents))]
[ProgId("DHS.HotkeySystem")]
public class HotkeySystemImpl : IHotkeySystem, IDecalService
{
private readonly List<RegisteredHotkey> _hotkeys = new List<RegisteredHotkey>();
private readonly Dictionary<object, IDHSHotkeyEvents> _connectedPlugins = new Dictionary<object, IDHSHotkeyEvents>();
// COM event — raised when a hotkey fires
public event _IHotkeySystemEvents_HotkeyEventEventHandler HotkeyEvent;
public void AddHotkey(string szPlugin, Hotkey pHotkey)
{
var impl = pHotkey as HotkeyImpl;
if (impl == null)
{
// Wrap foreign IHotkey implementation
impl = new HotkeyImpl
{
EventTitle = ((IHotkey)pHotkey).EventTitle,
EventDescription = ((IHotkey)pHotkey).EventDescription,
AltState = ((IHotkey)pHotkey).AltState,
ControlState = ((IHotkey)pHotkey).ControlState,
ShiftState = ((IHotkey)pHotkey).ShiftState,
VirtualKey = ((IHotkey)pHotkey).VirtualKey
};
}
_hotkeys.Add(new RegisteredHotkey
{
PluginCookie = szPlugin,
Hotkey = impl
});
}
public bool QueryHotkey(string bstrTitle)
{
foreach (var rh in _hotkeys)
{
if (string.Equals(rh.Hotkey.EventTitle, bstrTitle, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
public Hotkey QueryHotkeyEx(string szPluginCookie, string szTitle)
{
foreach (var rh in _hotkeys)
{
if (string.Equals(rh.PluginCookie, szPluginCookie, StringComparison.OrdinalIgnoreCase) &&
string.Equals(rh.Hotkey.EventTitle, szTitle, StringComparison.OrdinalIgnoreCase))
{
return (Hotkey)(object)rh.Hotkey;
}
}
return null;
}
public void Connect(object pPlugin)
{
// Plugin implements IDHSHotkeyEvents for receiving hotkey notifications
var events = pPlugin as IDHSHotkeyEvents;
if (events != null)
{
_connectedPlugins[pPlugin] = events;
}
}
public void DeleteHotkey(string szPluginCookie, string szHotkeyName)
{
_hotkeys.RemoveAll(rh =>
string.Equals(rh.PluginCookie, szPluginCookie, StringComparison.OrdinalIgnoreCase) &&
string.Equals(rh.Hotkey.EventTitle, szHotkeyName, StringComparison.OrdinalIgnoreCase));
}
/// <summary>
/// Called by the input system when a key combination matches a registered hotkey.
/// Fires the HotkeyEvent and notifies connected plugins.
/// </summary>
internal bool FireHotkey(string eventTitle)
{
bool eat = false;
// Fire COM connection point event
HotkeyEvent?.Invoke(eventTitle, ref eat);
if (eat) return true;
// Notify connected plugins via IDHSHotkeyEvents
foreach (var plugin in _connectedPlugins.Values)
{
try
{
if (plugin.OnHotkey(eventTitle))
return true;
}
catch
{
// Plugin error — don't propagate
}
}
return false;
}
/// <summary>
/// Check if a key press matches any registered hotkey and fire it.
/// </summary>
internal bool ProcessKey(int virtualKey, bool alt, bool ctrl, bool shift)
{
foreach (var rh in _hotkeys)
{
var hk = rh.Hotkey;
if (hk.VirtualKey == virtualKey &&
hk.AltState == alt &&
hk.ControlState == ctrl &&
hk.ShiftState == shift)
{
if (FireHotkey(hk.EventTitle))
return true;
}
}
return false;
}
// IDecalService implementation
public void Initialize(DecalCore pDecal)
{
// DHS doesn't need DecalCore reference directly
}
public void BeforePlugins()
{
}
public void AfterPlugins()
{
}
public void Terminate()
{
_hotkeys.Clear();
_connectedPlugins.Clear();
}
}
}