Refactor plugin third-party layout to UE standard
Plugin was non-autonomous: Build.cs referenced ../../../../Dependencies (SDK installed externally) and copied dpwin64.dll into the project's Binaries at build time, requiring manual DLL placement. Migrate to the canonical UE third-party pattern so the plugin self-contains everything and UBT handles staging. - Embed minimal SDK files inside the plugin: dris.h, dpwin64.lib in Source/ThirdParty/DinkeyPro/, dpwin64.dll in Binaries/ThirdParty/DinkeyPro/Win64/. - Switch from runtime GetProcAddress to import-lib delay-load (better protection: calls go through PE import table instead of named lookup). - Load DLL via IPluginManager::FindPlugin()->GetBaseDir() — no more ProjectDir-based path, no more manual File.Copy in Build.cs. - Drop Win32 dead code; plugin is Win64-only per the .uplugin whitelist. - Update .gitignore to keep Binaries/ThirdParty/ tracked while ignoring build artifacts under Binaries/Win64/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,8 +1,11 @@
|
||||
# Unreal generated / per-machine
|
||||
Unreal/PS_Dinkey/.vs/
|
||||
Unreal/PS_Dinkey/Binaries/Win64/PS_DinkeyEditor.target
|
||||
Unreal/PS_Dinkey/Binaries/
|
||||
Unreal/PS_Dinkey/DerivedDataCache/
|
||||
Unreal/PS_Dinkey/Intermediate/
|
||||
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Binaries/Win64/UE4Editor.modules
|
||||
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Binaries/
|
||||
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Intermediate/
|
||||
Unreal/PS_Dinkey/Saved/
|
||||
|
||||
# Plugin generated — but keep Binaries/ThirdParty (DLLs shipped with the plugin)
|
||||
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Binaries/*
|
||||
!Unreal/PS_Dinkey/Plugins/PS_Dinkey/Binaries/ThirdParty/
|
||||
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Intermediate/
|
||||
|
||||
@@ -8,26 +8,21 @@
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogDinkeyPlugin, Log, All);
|
||||
|
||||
typedef struct DRIS;
|
||||
|
||||
UCLASS()
|
||||
class UDinkey : public UObject
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
#if DINKEY_DYNAMIC_LINKAGE
|
||||
static void *dpWinDllHandle;
|
||||
typedef int(*_DDProtCheck)(DRIS *dris, BYTE *data);
|
||||
static _DDProtCheck DDProtCheck;
|
||||
|
||||
static void Initialize();
|
||||
static void Finalize();
|
||||
#endif
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Dinkey")
|
||||
static int ProtCheck(); // a standard protection check
|
||||
|
||||
private:
|
||||
static void* DpWinDllHandle;
|
||||
|
||||
static void random_set(void *buffer, int length);
|
||||
static void DisplayError(int ret_code, int extended_error);
|
||||
};
|
||||
|
||||
@@ -1,107 +1,37 @@
|
||||
// Copyright 2017 Polymorph. All Rights Reserved.
|
||||
#define DYNAMIC_LINKAGE
|
||||
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DinkeyPlugin : ModuleRules
|
||||
{
|
||||
private string ModulePath { get { return ModuleDirectory; } }
|
||||
private string ThirdPartyPath { get { return Path.GetFullPath(Path.Combine(ModulePath, "../../../../Dependencies")); } }
|
||||
|
||||
public DinkeyPlugin(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
PublicDependencyModuleNames.AddRange(new string[]
|
||||
{
|
||||
"Core",
|
||||
"Projects",
|
||||
});
|
||||
|
||||
#if DYNAMIC_LINKAGE
|
||||
PublicDefinitions.Add("DINKEY_DYNAMIC_LINKAGE=1");
|
||||
#endif
|
||||
// Dinkey dependencies
|
||||
string dinkeyPlatformString = (Target.Platform == UnrealTargetPlatform.Win64 ? "64" : "32");
|
||||
//string dinkeySDKPath = Path.Combine(ThirdPartyPath, "DinkeyPro/Dinkey Pro 7.2.0/Samples/C");
|
||||
string dinkeySDKPath = Path.Combine(ThirdPartyPath, "DinkeyPro/Dinkey Pro 7.6.1/Samples/C");
|
||||
PrivateDependencyModuleNames.AddRange(new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
});
|
||||
|
||||
// Compile/Link dependencies
|
||||
PublicIncludePaths.Add(dinkeySDKPath);
|
||||
#if DYNAMIC_LINKAGE
|
||||
string dpwinDLLName = string.Format("dpwin{0}.dll", dinkeyPlatformString);
|
||||
//string dinkeyDLLsPath = Path.Combine(ThirdPartyPath, string.Format("DinkeyPro/Dinkey Pro 7.2.0/Modules/{0}bit", dinkeyPlatformString));
|
||||
//string dinkeyDLLsPath = Path.Combine(ThirdPartyPath, string.Format("DinkeyPro/Dinkey Pro 7.6.1/Modules/{0}bit", dinkeyPlatformString));
|
||||
//string dpwinDLLPath = Path.Combine(dinkeyDLLsPath, dpwinDLLName);
|
||||
// Runtime dependencies (DLLs)
|
||||
PublicDelayLoadDLLs.Add(dpwinDLLName);
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
string ThirdPartyDir = Path.Combine(PluginDirectory, "Source", "ThirdParty", "DinkeyPro");
|
||||
|
||||
// RuntimeDependencies.Add(string.Format("$(EngineDir)/Binaries/ThirdParty/DinkeyPro/Win{0}/{1}", dinkeyPlatformString, dpwinDLLName));
|
||||
PublicSystemIncludePaths.Add(Path.Combine(ThirdPartyDir, "Include"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(ThirdPartyDir, "Lib", "Win64", "dpwin64.lib"));
|
||||
|
||||
if (Target.Type == TargetRules.TargetType.Editor) {
|
||||
string srcPath = Path.Combine(ModulePath, "../../ThirdParty/Win64/dpwin64.dll");
|
||||
string destPath = Path.Combine(ModulePath, "../../../../Binaries/Win64/dpwin64.dll");
|
||||
|
||||
// Only copy if destination is missing or source is newer
|
||||
bool needCopy = !File.Exists(destPath);
|
||||
if (!needCopy)
|
||||
{
|
||||
var srcInfo = new FileInfo(srcPath);
|
||||
var destInfo = new FileInfo(destPath);
|
||||
needCopy = srcInfo.LastWriteTimeUtc > destInfo.LastWriteTimeUtc
|
||||
|| srcInfo.Length != destInfo.Length;
|
||||
}
|
||||
|
||||
if (needCopy)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Copy(srcPath, destPath, true);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// DLL is locked by a running process (e.g. editor during Live Coding) — skip copy.
|
||||
// The existing DLL is already in place and will be used as-is.
|
||||
System.Console.WriteLine("DinkeyPlugin: Could not copy dpwin64.dll (file locked). Using existing copy.");
|
||||
}
|
||||
}
|
||||
PublicDelayLoadDLLs.Add("dpwin64.dll");
|
||||
RuntimeDependencies.Add(
|
||||
Path.Combine(PluginDirectory, "Binaries", "ThirdParty", "DinkeyPro", "Win64", "dpwin64.dll"),
|
||||
StagedFileType.NonUFS);
|
||||
}
|
||||
|
||||
RuntimeDependencies.Add(string.Format("$(ProjectDir)/Binaries/Win{0}/{1}", dinkeyPlatformString, dpwinDLLName));
|
||||
|
||||
|
||||
/* if (Target.Type == TargetRules.TargetType.Editor) {
|
||||
// Copy DLLs into Project Binaries Engine folders
|
||||
string dinkeyUnrealEngineThirdPartyPath = Path.Combine(Target.RelativeEnginePath, string.Format("Binaries/ThirdParty/DinkeyPro/Win{0}", dinkeyPlatformString));
|
||||
Directory.CreateDirectory(dinkeyUnrealEngineThirdPartyPath);
|
||||
File.Copy(string.Format("$(ProjectDir)/Binaries/Win{0}/{1}", dinkeyPlatformString, dpwinDLLName), Path.Combine(dinkeyUnrealEngineThirdPartyPath, dpwinDLLName), true);
|
||||
}*/
|
||||
#else
|
||||
// PublicAdditionalLibraries.Add(Path.Combine(dinkeySDKPath, string.Format("import_libs/dpwin{0}{1}.lib", dinkeyPlatformString, dinkeyConfigurationString)));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(dinkeySDKPath, string.Format("object_modules/dpwin{0}.obj", dinkeyPlatformString)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,52 @@
|
||||
// Copyright 2017 Polymorph. All Rights Reserved.
|
||||
|
||||
#include "Dinkey.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "Misc/Paths.h"
|
||||
|
||||
#include "dris.h" // for DRIS definition + DDProtCheck declaration
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogDinkeyPlugin);
|
||||
|
||||
#include "dris.h" // for DRIS definition
|
||||
|
||||
#define DISABLE_PROTECTION 0
|
||||
|
||||
#define ASTERION_PS 13290
|
||||
#define MY_PRODCODE "PROSERVE" // Dongle Product Code
|
||||
|
||||
#ifdef DINKEY_DYNAMIC_LINKAGE
|
||||
void *UDinkey::dpWinDllHandle = NULL;
|
||||
UDinkey::_DDProtCheck UDinkey::DDProtCheck = NULL;
|
||||
void* UDinkey::DpWinDllHandle = nullptr;
|
||||
|
||||
void UDinkey::Initialize() {
|
||||
UE_LOG(LogDinkeyPlugin, Log, TEXT("UDinkey::Initialize()"));
|
||||
|
||||
// Load the Dinkey dynamic library
|
||||
#if PLATFORM_64BITS
|
||||
FString Platform = TEXT("64");
|
||||
#else
|
||||
FString Platform = TEXT("32");
|
||||
#endif
|
||||
//FString dpwinDLLFilename = FPaths::EngineDir() / FString::Printf(TEXT("Binaries/ThirdParty/DinkeyPro/Win%s/dpwin%s.dll"), *Platform, *Platform);
|
||||
FString dpwinDLLFilename = FPaths::ProjectDir() / FString::Printf(TEXT("Binaries/Win%s/dpwin%s.dll"), *Platform, *Platform);
|
||||
|
||||
if (FPaths::FileExists(dpwinDLLFilename)) {
|
||||
dpWinDllHandle = FPlatformProcess::GetDllHandle(*dpwinDLLFilename);
|
||||
const TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(TEXT("DinkeyPlugin"));
|
||||
if (!Plugin.IsValid()) {
|
||||
UE_LOG(LogDinkeyPlugin, Fatal, TEXT("DinkeyPlugin not found by IPluginManager"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (dpWinDllHandle != NULL) {
|
||||
DDProtCheck = NULL;
|
||||
DDProtCheck = (_DDProtCheck)FPlatformProcess::GetDllExport(dpWinDllHandle, TEXT("DDProtCheck"));
|
||||
const FString DllPath = FPaths::Combine(
|
||||
Plugin->GetBaseDir(),
|
||||
TEXT("Binaries/ThirdParty/DinkeyPro/Win64/dpwin64.dll"));
|
||||
|
||||
if (!FPaths::FileExists(DllPath)) {
|
||||
UE_LOG(LogDinkeyPlugin, Fatal, TEXT("Dinkey DLL not found at: %s"), *DllPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dpWinDllHandle == NULL || DDProtCheck == NULL) {
|
||||
UE_LOG(LogDinkeyPlugin, Fatal, TEXT("Unable to load Dinkey Library : "));
|
||||
DpWinDllHandle = FPlatformProcess::GetDllHandle(*DllPath);
|
||||
if (DpWinDllHandle == nullptr) {
|
||||
UE_LOG(LogDinkeyPlugin, Fatal, TEXT("Failed to load Dinkey DLL: %s"), *DllPath);
|
||||
}
|
||||
}
|
||||
|
||||
void UDinkey::Finalize() {
|
||||
UE_LOG(LogDinkeyPlugin, Log, TEXT("UDinkey::Finalize()"));
|
||||
|
||||
// Unload the Dinkey dynamic library
|
||||
if (dpWinDllHandle != NULL) {
|
||||
DDProtCheck = NULL;
|
||||
FPlatformProcess::FreeDllHandle(dpWinDllHandle);
|
||||
dpWinDllHandle = NULL;
|
||||
if (DpWinDllHandle != nullptr) {
|
||||
FPlatformProcess::FreeDllHandle(DpWinDllHandle);
|
||||
DpWinDllHandle = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UDinkey::UDinkey(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer) {
|
||||
@@ -69,16 +64,15 @@ int UDinkey::ProtCheck() {
|
||||
dris.function = PROTECTION_CHECK; // standard protection check
|
||||
dris.flags = 0; // no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
|
||||
#ifdef DINKEY_DYNAMIC_LINKAGE
|
||||
if (DDProtCheck == NULL) {
|
||||
UE_LOG(LogDinkeyPlugin, Error, TEXT("Dinkey library not correctly loaded !"));
|
||||
if (DpWinDllHandle == nullptr) {
|
||||
UE_LOG(LogDinkeyPlugin, Error, TEXT("Dinkey library not loaded!"));
|
||||
#if DISABLE_PROTECTION || WITH_EDITOR
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
ret_code = DDProtCheck(&dris, NULL);
|
||||
|
||||
if (ret_code != 0) {
|
||||
|
||||
101
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Source/ThirdParty/DinkeyPro/Include/dris.h
vendored
Normal file
101
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Source/ThirdParty/DinkeyPro/Include/dris.h
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// dris.h
|
||||
// Dinkey Runtime Information Structure (DRIS)
|
||||
// !! this file should not be modified
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct DRIS {
|
||||
// the first 4 fields are never encrypted
|
||||
char header[4]; // should be set to DRIS
|
||||
// inputs
|
||||
int size; // size of this structure
|
||||
int seed1; // seed for data/dris encryption
|
||||
int seed2; // as above
|
||||
// (maybe encrypted from now on)
|
||||
int function; // specify only one function
|
||||
int flags; // options for the function selected. To use more than one OR them together: OPTION1 | OPTION2...
|
||||
unsigned int execs_decrement; // amount by which to dec execs if we use flag: DEC_MANY_EXECS
|
||||
int data_crypt_key_num; // number of the key (1-3) that the dongle uses to encrypt or decrypt user data
|
||||
int rw_offset; // offset in the dongle data area to read or write data
|
||||
int rw_length; // length of data are to read/write/encrypt/decrypt
|
||||
char *rw_data_ptr; // pointer to data to write / be read
|
||||
char alt_licence_name[256]; // protection check for different licence instead of the default one, must be null-terminated
|
||||
int var_a; // variable values for user algorithm
|
||||
int var_b;
|
||||
int var_c;
|
||||
int var_d;
|
||||
int var_e;
|
||||
int var_f;
|
||||
int var_g;
|
||||
int var_h;
|
||||
int alg_number; // the number of the user algorithm that you want to execute
|
||||
|
||||
// outputs
|
||||
int ret_code; // return code from the protection check
|
||||
int ext_err; // extended error
|
||||
int type; // type of dongle detected. 1 = Pro, 2 = FD
|
||||
int model; // model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
|
||||
int sdsn; // Software Developer's Serial Number
|
||||
char prodcode[12]; // Product Code (null-terminated)
|
||||
unsigned int dongle_number;
|
||||
int update_number;
|
||||
unsigned int data_area_size; // size of the data area used in the dongle detected
|
||||
int max_alg_num; // the maximum algorithm number in the dongle detected
|
||||
int execs; // executions left: -1 indicates 'no limit'
|
||||
int exp_day; // expiry day: -1 indicates 'no limit'
|
||||
int exp_month; // expiry month: -1 indicates 'no limit'
|
||||
int exp_year; // expiry year: -1 indicates 'no limit'
|
||||
unsigned int features; // features value
|
||||
int net_users; // maximum number of network users for the dongle detected: -1 indicates 'no limit'
|
||||
int alg_answer; // answer to the user algorithm executed with the given variable values
|
||||
unsigned int fd_capacity; // capacity of the data area in FD dongle.
|
||||
char fd_drive[128]; // drive letter of FD dongle detected e.g. 'f:\' (or mount name under Linux)
|
||||
int swkey_type; // 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
|
||||
int swkey_exp_day; // software key expiry date (if software key detected)
|
||||
int swkey_exp_month;
|
||||
int swkey_exp_year;
|
||||
} DRIS;
|
||||
|
||||
typedef struct NU_INFO {
|
||||
char licenceName[256];
|
||||
char userName[50];
|
||||
char computerName[256];
|
||||
char ipAddress[16];
|
||||
} NU_INFO;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
// functions - must specify only one
|
||||
#define PROTECTION_CHECK 1 // checks for dongle, check program params...
|
||||
#define EXECUTE_ALGORITHM 2 // protection check + calculate answer for specified algorithm with specified inputs
|
||||
#define WRITE_DATA_AREA 3 // protection check + writes dongle data area
|
||||
#define READ_DATA_AREA 4 // protection check + reads dongle data area
|
||||
#define ENCRYPT_USER_DATA 5 // protection check + the dongle will encrypt user data
|
||||
#define DECRYPT_USER_DATA 6 // protection check + the dongle will decrypt user data
|
||||
#define FAST_PRESENCE_CHECK 7 // checks for the presence of the correct dongle only with minimal security, no flags allowed.
|
||||
#define STOP_NET_USER 8 // stops a network user (a protection check is NOT performed)
|
||||
|
||||
// flags - can specify as many as you like
|
||||
#define DEC_ONE_EXEC 1 // decrement execs by 1
|
||||
#define DEC_MANY_EXECS 2 // decrement execs by number specified in execs_decrement
|
||||
#define START_NET_USER 4 // starts a network user
|
||||
#define USE_FUNCTION_ARGUMENT 16 // use the extra argument in the function for pointers
|
||||
#define CHECK_LOCAL_FIRST 32 // always look in local ports before looking in network ports
|
||||
#define CHECK_NETWORK_FIRST 64 // always look on the network before looking in local ports
|
||||
#define USE_ALT_LICENCE_NAME 128 // use name specified in alt_licence_name instead of the default one
|
||||
#define DONT_SET_MAXDAYS_EXPIRY 256 // if the max days expiry date has not been calculated then do not do it this time
|
||||
#define MATCH_DONGLE_NUMBER 512 // restrict the search to match the dongle number specified in the DRIS
|
||||
#define DONT_RETURN_FD_DRIVE 1024 // if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
|
||||
|
||||
|
||||
// Runtime module API declarations
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int WINAPI DDProtCheck(DRIS *dris, unsigned char *data);
|
||||
int WINAPI DDGetNetUserList(char *licence_name, int *num_net_users, NU_INFO *nu_info, int num_info_structs, int *extended_error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
BIN
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Source/ThirdParty/DinkeyPro/Lib/Win64/dpwin64.lib
vendored
Normal file
BIN
Unreal/PS_Dinkey/Plugins/PS_Dinkey/Source/ThirdParty/DinkeyPro/Lib/Win64/dpwin64.lib
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user