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,426 @@
// Choice.cpp : Implementation of cChoice
#include "stdafx.h"
#include "DecalControls.h"
#include "Choice.h"
#include "ChoicePopup.h"
#include "ChoiceDropDown.h"
/////////////////////////////////////////////////////////////////////////////
// cChoice
cChoice::cChoice()
: m_nSelected( -1 ),
m_nHotSelect( -1 ),
m_nDropLines( 8 ),
m_bPopup( false ),
m_bMouseDown( false ),
m_bMouseOver( false )
{
}
void cChoice::setPopup( bool bPopup )
{
// Always reset hot select
m_bPopup = bPopup;
m_nHotSelect = -1;
if( bPopup )
{
long nID;
m_pSite->get_ID( &nID );
Fire_DropDown( nID );
m_pPopup->put_Popup( VARIANT_TRUE );
}
// Redraw everything
m_pSite->Reformat();
m_pSite->Invalidate();
}
void cChoice::onCreate()
{
CComPtr< IPluginSite > pPluginSite;
m_pSite->get_PluginSite( &pPluginSite );
// Create the image info
pPluginSite->LoadBitmapPortal( 0x06001276, &m_pInactive );
BSTR bstrFontName;
pPluginSite->get_FontName(&bstrFontName);
pPluginSite->CreateFont( bstrFontName /*_bstr_t( _T( "Times New Roman" ) )*/, 14, 0, &m_pFont );
// Create the dropdown
CComObject< cChoiceDropDown > *pDropDown;
CComObject< cChoiceDropDown >::CreateInstance( &pDropDown );
pDropDown->m_pChoice = this;
LayerParams lp = { 0, { -1, -1, 0, 0 }, 0 };
m_pSite->CreateChild( &lp, pDropDown );
m_pPopup = pDropDown->m_pSite;
// Create the scroller
CComPtr< ILayer > pScrollerLayer;
HRESULT hRes = ::CoCreateInstance( CLSID_Scroller, NULL, CLSCTX_INPROC_SERVER, IID_ILayer, reinterpret_cast< void ** >( &pScrollerLayer ) );
_ASSERTE( SUCCEEDED( hRes ) );
pScrollerLayer->QueryInterface( &m_pScroller );
// Create the scroller object
LayerParams lpScroller = { 0, { 0, 0, 0, 0 }, eRenderClipped };
m_pPopup->CreateChild( &lpScroller, pScrollerLayer );
// Configure the scroller
SIZE szLine = { 18, 1 };
m_pScroller->put_Increments( &szLine );
// Create the popup window
CComObject< cChoicePopup > *pPopup;
CComObject< cChoicePopup >::CreateInstance( &pPopup );
pPopup->m_pChoice = this;
m_pScroller->CreateClient( pPopup );
m_pPopup->put_Transparent( VARIANT_FALSE );
m_pSite->put_Transparent( VARIANT_FALSE );
}
void cChoice::onDestroy()
{
m_pPopup.Release();
m_pFont.Release();
m_pInactive.Release();
}
STDMETHODIMP cChoice::MouseUp(MouseState *)
{
m_bMouseDown = false;
if( m_bMouseOver )
{
setPopup( !m_bPopup );
if( !m_bPopup )
m_pPopup->put_Popup( VARIANT_FALSE );
}
return S_OK;
}
#define RENDER_LEFTSTRETCH 10
#define RENDER_RIGHTSTRETCH 7
#define ROW_HEIGHT 18
#define ICON_WIDTH 20
#define ICON_HEIGHT 19
STDMETHODIMP cChoice::Render(ICanvas *pCanvas)
{
// First draw the background
RECT rcPos;
m_pSite->get_Position( &rcPos );
SIZE szImage;
m_pInactive->get_Size( &szImage );
static POINT ptBack = { 0, 0 };
m_pInactive->StretchBlt( pCanvas, &ptBack, rcPos.right - rcPos.left, RENDER_LEFTSTRETCH, szImage.cx - RENDER_RIGHTSTRETCH );
if( m_nSelected != -1 )
{
// Draw the selected text
static POINT ptText = { 12, 2 };
m_pFont->DrawTextEx( &ptText, m_options[ m_nSelected ].m_strText, 0, 0, eAA, pCanvas );
}
// Draw the up/down icon
CComPtr< IPluginSite > pPluginSite;
m_pSite->get_PluginSite( &pPluginSite );
SIZE szIcon = { ICON_WIDTH, ICON_HEIGHT };
CComPtr< IIconCache > pIconCache;
pPluginSite->GetIconCache( &szIcon, &pIconCache );
POINT ptIcon = { rcPos.right - rcPos.left - ICON_WIDTH, 0 };
pIconCache->DrawIcon( &ptIcon, ( ( m_bMouseDown && m_bMouseOver ) ? !m_bPopup : m_bPopup ) ? 0x06001275 : 0x06001274, 0, pCanvas );
return S_OK;
}
STDMETHODIMP cChoice::Reformat()
{
if( !m_bPopup || m_options.size() == 0 )
{
// If it's hidden great, hide it well
static RECT rcHidden = { -1, -1, 0, 0 };
m_pPopup->put_Position( &rcHidden );
return S_OK;
}
// Calculate the correct position
RECT rc;
m_pSite->get_ScreenPosition( &rc );
// Two modes, with scroll bar and without
if( m_options.size() > m_nDropLines )
{
// With a scroller
RECT rcPopup = { rc.left, rc.bottom, rc.right - ICON_WIDTH + 16, rc.bottom +
ROW_HEIGHT * m_nDropLines };
m_pPopup->put_Position( &rcPopup );
m_pScroller->put_VerticalEnabled( VARIANT_TRUE );
SIZE szArea = { rc.right - ICON_WIDTH, ROW_HEIGHT * m_options.size() };
m_pScroller->put_Area( &szArea );
}
else
{
RECT rcPopup = { rc.left, rc.bottom, rc.right - ICON_WIDTH, rc.bottom +
ROW_HEIGHT * m_options.size() };
m_pPopup->put_Position( &rcPopup );
POINT ptOffset = { 0, 0 };
m_pScroller->put_Offset( &ptOffset );
m_pScroller->put_VerticalEnabled( VARIANT_FALSE );
SIZE szArea = { rc.right - ICON_WIDTH, ROW_HEIGHT * m_options.size() };
m_pScroller->put_Area( &szArea );
}
return S_OK;
}
STDMETHODIMP cChoice::SchemaLoad(IView *pView, IUnknown *pSchema)
{
// Load the data from the schema
MSXML::IXMLDOMElementPtr pElement = pSchema;
MSXML::IXMLDOMElementPtr pRow;
for( MSXML::IXMLDOMNodeListPtr pRows = pElement->selectNodes( _T( "option" ) );
( pRow = pRows->nextNode() ).GetInterfacePtr() != NULL; )
{
_variant_t vRow = pRow->getAttribute( _T( "text" ) ),
vData = pRow->getAttribute( _T( "data" ) );
_ASSERTE( vRow.vt == VT_BSTR );
cOption o;
o.m_strText = vRow;
o.m_value = vData;
m_options.push_back( o );
}
_variant_t vDropRows = pElement->getAttribute( "droplines" ),
vSelected = pElement->getAttribute( "selected" );
if( vDropRows.vt != VT_NULL )
{
try
{
m_nDropLines = static_cast< long >( vDropRows );
_ASSERTE( m_nDropLines > 0 );
}
catch( ... )
{
// Type conversion error
_ASSERTE( FALSE );
}
}
if( vSelected.vt != VT_NULL )
{
try
{
m_nSelected = static_cast< long >( vSelected );
_ASSERTE( m_nSelected >= 0 );
}
catch( ... )
{
// Type conversion error
_ASSERTE( FALSE );
}
}
return S_OK;
}
STDMETHODIMP cChoice::AddChoice(BSTR strDisplay, VARIANT vData)
{
cOption o;
o.m_strText = strDisplay;
o.m_value = vData;
m_options.push_back( o );
m_pSite->Reformat();
return S_OK;
}
STDMETHODIMP cChoice::get_ChoiceCount(long *pVal)
{
_ASSERTE( pVal != NULL );
*pVal = m_options.size();
return S_OK;
}
STDMETHODIMP cChoice::get_Data(long nIndex, VARIANT *pVal)
{
if( pVal == NULL )
return E_POINTER;
if( nIndex < 0 || nIndex > m_options.size() )
{
pVal->lVal = -1;
pVal->vt = VT_I4;
}
else
::VariantCopy( pVal, &m_options[ nIndex ].m_value );
return S_OK;
}
STDMETHODIMP cChoice::put_Data(long nIndex, VARIANT newVal)
{
_ASSERTE( nIndex >= 0 );
_ASSERTE( nIndex < m_options.size() );
::VariantCopy( &m_options[ nIndex ].m_value, &newVal );
return S_OK;
}
STDMETHODIMP cChoice::get_Text(long nIndex, BSTR *pVal)
{
USES_CONVERSION;
_ASSERTE( nIndex >= 0 );
_ASSERTE( nIndex < m_options.size() );
_ASSERTE( pVal != NULL );
*pVal = OLE2BSTR( m_options[ nIndex ].m_strText );
return S_OK;
}
STDMETHODIMP cChoice::put_Text(long nIndex, BSTR newVal)
{
_ASSERTE( nIndex >= 0 );
_ASSERTE( nIndex < m_options.size() );
_ASSERTE( newVal != NULL );
m_options[ nIndex ].m_strText = newVal;
m_pPopup->Invalidate();
return S_OK;
}
STDMETHODIMP cChoice::RemoveChoice(long nIndex)
{
_ASSERTE( nIndex >= 0 );
_ASSERTE( nIndex < m_options.size() );
m_options.erase( m_options.begin() + nIndex );
if( m_nSelected >= m_options.size() )
m_nSelected = m_options.size() - 1;
long nID;
m_pSite->get_ID( &nID );
Fire_Change( nID, m_nSelected );
// Redraw the concerned
m_pSite->Reformat();
m_pPopup->Invalidate();
return S_OK;
}
STDMETHODIMP cChoice::get_Dropped(VARIANT_BOOL *pVal)
{
_ASSERTE( pVal != NULL );
*pVal = ( m_bPopup ) ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP cChoice::put_Dropped(VARIANT_BOOL newVal)
{
if( !!newVal != m_bPopup )
setPopup( !!newVal );
return S_OK;
}
STDMETHODIMP cChoice::get_Selected(long *pVal)
{
_ASSERTE( pVal != NULL );
*pVal = m_nSelected;
return S_OK;
}
STDMETHODIMP cChoice::put_Selected(long newVal)
{
_ASSERTE( newVal >= -1 );
//_ASSERTE( newVal < m_options.size() );
//back out if out of bounds, don't error to prevent breaking vb plugs
//this should fix the crash on display bug
if (newVal >= m_options.size())
return S_OK;
if( newVal == m_nSelected )
return S_OK;
m_nSelected = newVal;
long nID;
m_pSite->get_ID( &nID );
Fire_Change( nID, m_nSelected );
// Redraw the concerned
m_pSite->Invalidate();
m_pPopup->Invalidate();
return S_OK;
}
STDMETHODIMP cChoice::get_DropLines(long *pVal)
{
_ASSERTE( pVal != NULL );
*pVal = m_nDropLines;
return S_OK;
}
STDMETHODIMP cChoice::put_DropLines(long newVal)
{
_ASSERTE( newVal > 0 );
m_nDropLines = newVal;
m_pSite->Reformat();
return S_OK;
}
STDMETHODIMP cChoice::Clear()
{
m_options.clear();
m_nSelected = -1;
long nID;
m_pSite->get_ID( &nID );
Fire_Change( nID, m_nSelected );
m_pSite->Reformat();
return S_OK;
}