mirror of
https://github.com/LANCommander/LANCommander.Interposer.git
synced 2026-08-01 03:08:17 -04:00
Sample Interposer plugin
This commit is contained in:
parent
a35d553481
commit
39c9a2f4cd
3 changed files with 319 additions and 0 deletions
|
|
@ -0,0 +1,165 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>18.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{a1b2c3d4-e5f6-7890-abcd-ef1234567890}</ProjectGuid>
|
||||
<RootNamespace>LANCommanderInterposerPluginExample</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="Shared" />
|
||||
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)Release\Example\x86\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)Release\Example\x64\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WIN32_LEAN_AND_MEAN;NOMINMAX;UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;WIN32_LEAN_AND_MEAN;NOMINMAX;UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN32_LEAN_AND_MEAN;NOMINMAX;UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;WIN32_LEAN_AND_MEAN;NOMINMAX;UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<PreBuildEvent>
|
||||
<Command>powershell -NoProfile -ExecutionPolicy Bypass -File "$(SolutionDir)generate_version.ps1" -Output "$(SolutionDir)version_info.h"</Command>
|
||||
</PreBuildEvent>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="src\resource.rc" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\dllmain.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
124
LANCommander.Interposer.Plugin.Example/src/dllmain.cpp
Normal file
124
LANCommander.Interposer.Plugin.Example/src/dllmain.cpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
//
|
||||
// LANCommander.Interposer.Plugin.Example
|
||||
//
|
||||
// Minimal example plugin for LANCommander Interposer. Use this as a starting
|
||||
// point for writing your own plugins.
|
||||
//
|
||||
// Build this project as a DLL and drop it (or a subfolder containing it) into
|
||||
// .interposer\Plugins\ next to the Interposer DLL. The Interposer loads all
|
||||
// .dll and .asi files from that directory tree automatically.
|
||||
//
|
||||
// Plugin lifecycle:
|
||||
// 1. Interposer calls LoadLibrary on your DLL -> DllMain(DLL_PROCESS_ATTACH)
|
||||
// 2. Interposer looks for an "InterposerPluginInit" export via GetProcAddress.
|
||||
// If found, it calls InterposerPluginInit(hInterposer) with its own HMODULE.
|
||||
// 3. Use the provided HMODULE to resolve any Interposer exports you need.
|
||||
// 4. On shutdown the Interposer calls FreeLibrary -> DllMain(DLL_PROCESS_DETACH)
|
||||
//
|
||||
// Available Interposer exports (resolve with GetProcAddress):
|
||||
//
|
||||
// Configuration / Logging (wchar_t*):
|
||||
// InterposerGetUsername(wchar_t* buf, DWORD bufSize) -> BOOL
|
||||
// InterposerLog(const wchar_t* verb, const wchar_t* message) -> void
|
||||
// InterposerGetConfigString(const wchar_t* dotPath,
|
||||
// wchar_t* buf, DWORD bufSize) -> BOOL
|
||||
// InterposerRegisterPluginConfig(const wchar_t* pluginName,
|
||||
// const wchar_t* yamlDefaults) -> BOOL
|
||||
//
|
||||
// Virtual Registry (wchar_t*):
|
||||
// InterposerSetRegistryValue(const wchar_t* keyPath,
|
||||
// const wchar_t* valueName,
|
||||
// const wchar_t* value) -> void
|
||||
// InterposerSetRegistryValueBySuffix(const wchar_t* keySuffix,
|
||||
// const wchar_t* valueName,
|
||||
// const wchar_t* value) -> DWORD
|
||||
//
|
||||
// Rich Presence (char* — UTF-8):
|
||||
// InterposerSetPresenceDetails(const char* details) -> void
|
||||
// InterposerSetPresenceState(const char* state) -> void
|
||||
// InterposerSetPresenceTimestamps(int64_t start, int64_t end) -> void
|
||||
// InterposerSetPresenceLargeImage(const char* key, text) -> void
|
||||
// InterposerSetPresenceSmallImage(const char* key, text) -> void
|
||||
// InterposerSetPresenceParty(const char* id, int size, max) -> void
|
||||
// InterposerSetPresenceButton(int index, const char* text, url) -> void
|
||||
// InterposerSetPresenceType(int type) -> void
|
||||
// InterposerSetPresenceName(const char* name) -> void
|
||||
// InterposerUpdatePresence() -> void
|
||||
// InterposerClearPresence() -> void
|
||||
//
|
||||
// Config.yml example for this plugin:
|
||||
//
|
||||
// Plugins:
|
||||
// Example:
|
||||
// Greeting: "Hello from the example plugin!"
|
||||
//
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
|
||||
// ---- Interposer API typedefs ------------------------------------------------
|
||||
// Declare function pointer types for each export you intend to use.
|
||||
// These have no link-time dependency on the Interposer.
|
||||
|
||||
using FnInterposerLog = void (WINAPI*)(const wchar_t* verb, const wchar_t* message);
|
||||
using FnInterposerGetConfigString = BOOL (WINAPI*)(const wchar_t* dotPath, wchar_t* buf, DWORD bufSize);
|
||||
using FnInterposerGetUsername = BOOL (WINAPI*)(wchar_t* buf, DWORD bufSize);
|
||||
using FnInterposerRegisterPluginConfig = BOOL (WINAPI*)(const wchar_t* pluginName, const wchar_t* yamlDefaults);
|
||||
|
||||
static FnInterposerLog pfnLog = nullptr;
|
||||
static FnInterposerGetConfigString pfnGetConfig = nullptr;
|
||||
static FnInterposerGetUsername pfnGetUser = nullptr;
|
||||
|
||||
// ---- Plugin entry point -----------------------------------------------------
|
||||
// The Interposer calls this immediately after LoadLibrary, passing its own
|
||||
// HMODULE. Use it for all GetProcAddress calls — this works regardless of
|
||||
// whether the Interposer was deployed as LANCommander.Interposer.dll,
|
||||
// version.dll, dinput8.dll, or an .asi file.
|
||||
|
||||
extern "C" __declspec(dllexport) void WINAPI InterposerPluginInit(HMODULE hInterposer)
|
||||
{
|
||||
// Resolve the exports we need.
|
||||
pfnLog = reinterpret_cast<FnInterposerLog>(GetProcAddress(hInterposer, "InterposerLog"));
|
||||
pfnGetConfig = reinterpret_cast<FnInterposerGetConfigString>(GetProcAddress(hInterposer, "InterposerGetConfigString"));
|
||||
pfnGetUser = reinterpret_cast<FnInterposerGetUsername>(GetProcAddress(hInterposer, "InterposerGetUsername"));
|
||||
|
||||
if (!pfnLog)
|
||||
return; // Can't even log — bail out.
|
||||
|
||||
// Register default config. On first run this writes the Plugins.Example
|
||||
// section into Config.yml; on subsequent runs it's a no-op.
|
||||
auto pfnRegConfig = reinterpret_cast<FnInterposerRegisterPluginConfig>(
|
||||
GetProcAddress(hInterposer, "InterposerRegisterPluginConfig"));
|
||||
if (pfnRegConfig)
|
||||
pfnRegConfig(L"Example", L"Greeting: 'Hello from the example plugin!'");
|
||||
|
||||
// Read a plugin-specific setting from Config.yml.
|
||||
wchar_t greeting[256] = {};
|
||||
if (pfnGetConfig && pfnGetConfig(L"Plugins.Example.Greeting", greeting, ARRAYSIZE(greeting)))
|
||||
{
|
||||
pfnLog(L"EXAMPLE", greeting);
|
||||
}
|
||||
else
|
||||
{
|
||||
pfnLog(L"EXAMPLE", L"Plugin loaded (no Plugins.Example.Greeting configured)");
|
||||
}
|
||||
|
||||
// Demonstrate reading the current username.
|
||||
wchar_t username[256] = {};
|
||||
if (pfnGetUser && pfnGetUser(username, ARRAYSIZE(username)))
|
||||
{
|
||||
std::wstring msg = L"Current player: ";
|
||||
msg += username;
|
||||
pfnLog(L"EXAMPLE", msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// ---- DllMain ----------------------------------------------------------------
|
||||
// Keep DllMain minimal. Heavy work belongs in InterposerPluginInit where you
|
||||
// have guaranteed access to the Interposer API.
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD /*fdwReason*/, LPVOID /*lpReserved*/)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
30
LANCommander.Interposer.Plugin.Example/src/resource.rc
Normal file
30
LANCommander.Interposer.Plugin.Example/src/resource.rc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include "version_info.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0x0L
|
||||
FILEOS 0x00040004L
|
||||
FILETYPE 0x00000002L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", VER_COMPANY_STR
|
||||
VALUE "FileDescription", "LANCommander Interposer Example Plugin\0"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "LANCommander.Interposer.Plugin.Example\0"
|
||||
VALUE "LegalCopyright", VER_COPYRIGHT_STR
|
||||
VALUE "OriginalFilename", "LANCommander.Interposer.Plugin.Example.dll\0"
|
||||
VALUE "ProductName", VER_PRODUCT_STR
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
Loading…
Add table
Add a link
Reference in a new issue