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,515 @@
#include "stdafx.h"// Slider.cpp : Implementation of cSlider
#include <stdio.h>
#include "DecalControls.h"
#include "Slider.h"
/////////////////////////////////////////////////////////////////////////////
// cSlider
cSlider::cSlider() : m_nTextColor(RGB(0, 0, 0)),
m_bMouseIn(VARIANT_FALSE),
m_bGrappled(VARIANT_FALSE),
m_nMinimum(0),
m_nMaximum(100),
m_nMinSliderColor( RGB(200,0,0) ),
m_nMaxSliderColor( RGB(0,200,0) ),
m_nSliderPos(0),
m_strTextLeft(NULL),
m_strTextRight(NULL),
m_bVertical(VARIANT_FALSE) {
}
cSlider::~cSlider() {
if (m_strTextLeft)
free(m_strTextLeft);
if (m_strTextRight)
free(m_strTextRight);
}
STDMETHODIMP cSlider::get_Font(IFontCacheDisp **pVal) {
_ASSERTE(pVal != NULL);
if (m_pFont.p == NULL)
*pVal = NULL;
else
m_pFont->QueryInterface(pVal);
return S_OK;
}
STDMETHODIMP cSlider::putref_Font(IFontCacheDisp *newVal) {
_ASSERTE(newVal != NULL);
if (m_pFont.p)
m_pFont.Release();
HRESULT hRes = newVal->QueryInterface(&m_pFont);
_ASSERTE(SUCCEEDED(hRes));
m_pSite->Reformat();
return S_OK;
}
STDMETHODIMP cSlider::get_TextColor(long *pVal) {
_ASSERTE(pVal != NULL);
*pVal = m_nTextColor;
return S_OK;
}
STDMETHODIMP cSlider::put_TextColor(long newVal) {
_ASSERTE((newVal & 0xFF000000L) == 0);
m_nTextColor = newVal;
m_pSite->Invalidate();
Reformat();
return S_OK;
}
STDMETHODIMP cSlider::get_SliderPosition(long *pVal) {
_ASSERTE(pVal != NULL);
*pVal = m_nSliderPos;
return S_OK;
}
STDMETHODIMP cSlider::put_SliderPosition(long newVal) {
if (m_nSliderPos == newVal)
return S_OK;
if (newVal < m_nMinimum || newVal > m_nMaximum)
return S_FALSE;
m_nSliderPos = newVal;
Reformat();
m_pSite->Invalidate();
return S_OK;
}
STDMETHODIMP cSlider::get_Minimum(long *pVal) {
_ASSERTE(pVal != NULL);
*pVal = m_nMinimum;
return S_OK;
}
STDMETHODIMP cSlider::put_Minimum(long newVal) {
if (m_nMinimum == newVal)
return S_OK;
m_nMinimum = newVal;
Reformat();
m_pSite->Invalidate();
return S_OK;
}
STDMETHODIMP cSlider::get_Maximum(long *pVal) {
_ASSERTE(pVal != NULL);
*pVal = m_nMaximum;
return S_OK;
}
STDMETHODIMP cSlider::put_Maximum(long newVal) {
if (m_nMaximum == newVal)
return S_OK;
m_nMaximum = newVal;
Reformat();
m_pSite->Invalidate();
return S_OK;
}
STDMETHODIMP cSlider::SchemaLoad(IView *pView, IUnknown *pSchema)
{
// First attempt to load the font
CComPtr< IPluginSite > pPlugin;
m_pSite->get_PluginSite( &pPlugin );
pPlugin->CreateFontSchema(14, 0, pSchema, &m_pFont);
MSXML::IXMLDOMElementPtr pElement = pSchema;
_variant_t vTextColor = pElement->getAttribute(_T("textcolor")),
vMinSliderColor = pElement->getAttribute(_T("mincolor")),
vMaxSliderColor = pElement->getAttribute(_T("maxcolor")),
vVertical = pElement->getAttribute(_T("vertical")),
vDefault = pElement->getAttribute(_T("default")),
vMaximum = pElement->getAttribute(_T("maximum")),
vMinimum = pElement->getAttribute(_T("minimum")),
vName = pElement->getAttribute(_T("name"));
// Maximum must exist
_ASSERTE(vMaximum.vt == VT_INT);
if (vTextColor.vt != VT_NULL) {
try {
m_nTextColor = static_cast<long>(vTextColor);
} catch(...) {
// Type conversion error
_ASSERTE(FALSE);
}
}
if (vMinSliderColor.vt != VT_NULL) {
try {
_bstr_t szWhat = vMinSliderColor.bstrVal;
m_nMinSliderColor = wcstoul( szWhat, 0, 16 );
} catch( ... ) {
// Type conversion error
_ASSERTE(FALSE);
}
}
if (vMaxSliderColor.vt != VT_NULL) {
try {
_bstr_t szWhat = vMaxSliderColor.bstrVal;
m_nMaxSliderColor = wcstoul( szWhat, 0, 16 );
} catch( ... ) {
// Type conversion error
_ASSERTE(FALSE);
}
}
if (vVertical.vt != VT_NULL) {
try {
m_bVertical = (static_cast<bool>(vVertical)) ? VARIANT_TRUE : VARIANT_FALSE;
} catch( ... ) {
// Type conversion error
_ASSERTE(FALSE);
}
}
if (vMaximum.vt != VT_NULL) {
try {
m_nMaximum = static_cast<long>(vMaximum);
} catch( ... ) {
// Type conversion error
_ASSERTE(FALSE);
}
}
if (vMinimum.vt != VT_NULL) {
try {
m_nMinimum = static_cast<long>(vMinimum);
} catch( ... ) {
// Type conversion error
_ASSERTE(FALSE);
}
}
if (vDefault.vt != VT_NULL) {
try {
m_nSliderPos = static_cast<long>(vDefault);
} catch( ... ) {
m_nSliderPos = m_nMinimum;
}
}
/* fprintf( f, "name - %s\n", OLE2A(vName.bstrVal) );
fprintf( f, "textcolor - %08X\n", m_nTextColor );
fprintf( f, "mincolor - %08X\n", m_nMinSliderColor );
fprintf( f, "maxcolor - %08X\n", m_nMaxSliderColor );
fprintf( f, "vertical - %X\n", m_bVertical );
fprintf( f, "maximum - %08X\n", m_nMaximum );
fprintf( f, "minimum - %08X\n\n", m_nMinimum ); */
/* // it's a pain in the ass that we need set the min and max for them to work, aye? let's fix it
RECT rc;
m_pSite->get_Position(&rc);
long siteHHalf = (rc.bottom - rc.top) / 2;
// The background bar
m_rcBackground.left = 0;
m_rcBackground.top = siteHHalf - 4;
m_rcBackground.bottom = siteHHalf + 6;
m_rcBackground.right = rc.right - rc.left;
// The middle bar
m_rcBar.top = siteHHalf;
m_rcBar.left = 0;
m_rcBar.bottom = siteHHalf + 3;
m_rcBar.right = rc.right - rc.left;
// Ensure sane slider position
if (m_nSliderPos < m_nMinimum)
m_nSliderPos = m_nMinimum;
if (m_nSliderPos > m_nMaximum)
m_nSliderPos = m_nMaximum;
long siteDiff = abs(m_rcBar.right - m_rcBar.left);
long extentDiff = abs(m_nMaximum - m_nMinimum);
long valDiff = m_nSliderPos - m_nMinimum;
if (valDiff == 0) {
m_ptSlider.x = m_rcBar.left;
} else {
long diff = (long)(((float)valDiff / (float)extentDiff) * (float)siteDiff);
m_ptSlider.x = m_rcBar.left + diff;
if (m_ptSlider.x >= m_rcBar.right - 6)
m_ptSlider.x = m_rcBar.right - 6;
}
m_ptSlider.y = siteHHalf - 5;
*/
// fclose( f );
return S_OK;
}
STDMETHODIMP cSlider::Reformat() {
USES_CONVERSION;
char strTemp[16];
if (m_strTextLeft)
free(m_strTextLeft);
if (m_strTextRight)
free(m_strTextRight);
_snprintf(strTemp, 15, "%i", m_nMinimum);
m_strTextLeft = strdup(strTemp);
_snprintf(strTemp, 15, "%i", m_nMaximum);
m_strTextRight = strdup(strTemp);
if (m_pFont.p == NULL) {
// No font was specified, create the default font
CComPtr<IPluginSite> pPlugin;
m_pSite->get_PluginSite(&pPlugin);
BSTR bstrFontName;
pPlugin->get_FontName(&bstrFontName);
pPlugin->CreateFont(bstrFontName /*_bstr_t(_T("Times New Roman"))*/, 14, 0, &m_pFont);
}
RECT rc;
m_pSite->get_Position(&rc);
SIZE textRight;
m_pFont->MeasureText(_bstr_t(m_strTextRight), &textRight);
long siteHHalf = (rc.bottom - rc.top) / 2;
// The background bar
m_rcBackground.left = 0;
m_rcBackground.top = siteHHalf - 4;
m_rcBackground.bottom = siteHHalf + 6;
m_rcBackground.right = rc.right - rc.left;
// The middle bar
m_rcBar.top = siteHHalf;
m_rcBar.left = 0;
m_rcBar.bottom = siteHHalf + 3;
m_rcBar.right = rc.right - rc.left;
m_ptLeftText.x = m_rcBackground.left + 1;
m_ptLeftText.y = m_rcBackground.bottom + 1;
m_ptRightText.x = m_rcBackground.right - (textRight.cx + 1);
m_ptRightText.y = m_rcBackground.bottom + 1;
// Ensure sane slider position
if (m_nSliderPos < m_nMinimum)
m_nSliderPos = m_nMinimum;
if (m_nSliderPos > m_nMaximum)
m_nSliderPos = m_nMaximum;
long siteDiff = abs(m_rcBar.right - m_rcBar.left);
long extentDiff = abs(m_nMaximum - m_nMinimum);
long valDiff = m_nSliderPos - m_nMinimum;
if (valDiff == 0) {
m_ptSlider.x = m_rcBar.left;
} else {
long diff = (long)(((float)valDiff / (float)extentDiff) * (float)siteDiff);
m_ptSlider.x = m_rcBar.left + diff;
if (m_ptSlider.x >= m_rcBar.right - 6)
m_ptSlider.x = m_rcBar.right - 6;
}
m_ptSlider.y = siteHHalf - 5;
return S_OK;
}
STDMETHODIMP cSlider::Render(ICanvas *pCanvas)
{
// intensity to lose or gain for 3d effect
#define COLOR_BAND 20
USES_CONVERSION;
CComPtr<IPluginSite> pPlugin;
m_pSite->get_PluginSite(&pPlugin);
CComPtr<IIconCache> pIcon;
SIZE szIcon = {7, 12};
pPlugin->GetIconCache(&szIcon, &pIcon);
// we're averaging color differences w/bias...
float fractional = m_nSliderPos / m_nMaximum;
float lFraction = (1 - fractional) * 2;
float rFraction = fractional * 2;
long lMinSliderRed = lFraction * (BYTE) m_nMinSliderColor;
long lMinSliderGreen = lFraction * (BYTE) (m_nMinSliderColor >> 8);
long lMinSliderBlue = lFraction * (BYTE) (m_nMinSliderColor >> 16);
long lMaxSliderRed = rFraction * (BYTE) m_nMaxSliderColor;
long lMaxSliderGreen = rFraction * (BYTE) (m_nMaxSliderColor >> 8);
long lMaxSliderBlue = rFraction * (BYTE) (m_nMaxSliderColor >> 16);
long lFillColorTop, lFillColorMiddle, lFillColorBottom;
long lFillColorRed = (lMinSliderRed + lMaxSliderRed) / 2,
lFillColorGreen = (lMinSliderGreen + lMaxSliderGreen) / 2,
lFillColorBlue = (lMinSliderBlue + lMaxSliderBlue) / 2;
if( m_nMinSliderColor && m_nMaxSliderColor ) // not black .. who would choose all black for both bars anyway? grr.
{
// find the most intense color channel to maul for our evil purposes (we're using std::max here)
long lMax = max( max( lFillColorRed, lFillColorGreen ), lFillColorBlue );
// if we're dark, don't overflow
long lOffset = lMax > (COLOR_BAND - 1) ? COLOR_BAND : 0;
long lOffset2 = lMax > (COLOR_BAND - 1) ? 0 : COLOR_BAND;
// red
if( lMax == lFillColorRed )
{
lFillColorTop = RGB( lFillColorRed - lOffset, lFillColorGreen, lFillColorBlue );
lFillColorMiddle = RGB( lFillColorRed + lOffset2, lFillColorGreen, lFillColorBlue );
lFillColorBottom = RGB( lFillColorRed - lOffset, lFillColorGreen, lFillColorBlue );
}
// green
else if( lMax == lFillColorGreen )
{
lFillColorTop = RGB( lFillColorRed, lFillColorGreen - lOffset, lFillColorBlue );
lFillColorMiddle = RGB( lFillColorRed, lFillColorGreen + lOffset2, lFillColorBlue );
lFillColorBottom = RGB( lFillColorRed, lFillColorGreen - lOffset, lFillColorBlue );
}
// has to be blue
else
{
lFillColorTop = RGB( lFillColorRed, lFillColorGreen, lFillColorBlue - lOffset );
lFillColorMiddle = RGB( lFillColorRed, lFillColorGreen, lFillColorBlue + lOffset2 );
lFillColorBottom = RGB( lFillColorRed, lFillColorGreen, lFillColorBlue - lOffset );
}
}
// someone's a GOTH
else
{
lFillColorTop = 0;
lFillColorMiddle = 0x00161616;
lFillColorBottom = 0;
}
pCanvas->Fill( &m_rcBar, lFillColorMiddle );
RECT topBar = {m_rcBar.left, m_rcBar.top, m_rcBar.right, m_rcBar.top + 1};
pCanvas->Fill( &topBar, lFillColorTop );
RECT bottomBar = {m_rcBar.left, m_rcBar.bottom - 1, m_rcBar.right, m_rcBar.bottom};
pCanvas->Fill( &bottomBar, lFillColorBottom );
pIcon->DrawIcon(&m_ptSlider, 0x06001286, 0, pCanvas);
m_pFont->DrawText(&m_ptLeftText, _bstr_t(m_strTextLeft), RGB(0, 0, 0), pCanvas);
m_pFont->DrawText(&m_ptRightText, _bstr_t(m_strTextRight), RGB(0, 0, 0), pCanvas);
return S_OK;
}
STDMETHODIMP cSlider::MouseDown(struct MouseState *mouseState) {
_ASSERTE(m_pSite != NULL);
POINT pt = mouseState->client;
if (pt.x >= (m_ptSlider.x) && (pt.x <= m_ptSlider.x + 6) &&
pt.y >= (m_ptSlider.y) && (pt.y <= m_ptSlider.y + 12)) {
// They hit the grapple point!
m_ptLastMouse = mouseState->client;
m_bGrappled = VARIANT_TRUE;
} else {
// The hit the bar - see if that's within the bar rect
if (pt.x > m_rcBar.left && pt.x < m_rcBar.right &&
pt.y > (m_rcBar.top - 3) && pt.y < (m_rcBar.bottom + 3)) {
// Calcuate the new slider position
float pixelValue = (float)((float)(m_nMaximum - m_nMinimum) / (float)(m_rcBar.right - m_rcBar.left));
m_nSliderPos = (pt.x - m_rcBar.left) * pixelValue;
Reformat();
m_pSite->Invalidate();
long nID;
m_pSite->get_ID(&nID);
_ASSERTE(m_pSite.p != NULL);
Fire_Change(nID, m_nSliderPos);
}
}
return S_OK;
}
STDMETHODIMP cSlider::MouseUp(struct MouseState *mouseState) {
m_bGrappled = VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP cSlider::MouseMove(struct MouseState *mouseState) {
if (m_bGrappled) {
long dx;
POINT pt = mouseState->client;
dx = m_ptLastMouse.x - pt.x;
m_ptLastMouse = pt;
float pixelValue = (float)((float)(m_nMaximum - m_nMinimum) / (float)(m_rcBar.right - m_rcBar.left));
m_nSliderPos -= ((float)dx * pixelValue);
// I personally like being able to drag the slider
// PAST THE EDGE OF THE SLIDE BAR without needing pixel accuracy...
if( pt.x >= m_rcBar.right )
m_nSliderPos = m_nMaximum;
Reformat();
m_pSite->Invalidate();
long nID;
m_pSite->get_ID(&nID);
_ASSERTE(m_pSite.p != NULL);
Fire_Change(nID, m_nSliderPos);
}
return S_OK;
}