Add DMM version.dll proxy hook for CGSS
Signed-off-by: Sean Du <do4suki@gmail.com>
This commit is contained in:
+121
@@ -0,0 +1,121 @@
|
||||
#include "stdinclude.hpp"
|
||||
|
||||
namespace {
|
||||
using GetSchemeTypeFn = int (*)();
|
||||
constexpr int kHttpSchemeType = 0;
|
||||
constexpr DWORD kHookPollIntervalMs = 500;
|
||||
constexpr DWORD kGameAssemblySettleDelayMs = 5000;
|
||||
constexpr int kHookPollMaxAttempts = 600;
|
||||
|
||||
volatile LONG g_hook_installed = 0;
|
||||
GetSchemeTypeFn g_orig_get_scheme_type = nullptr;
|
||||
volatile LONG g_logged_gameassembly = 0;
|
||||
volatile LONG g_exports_state = 0;
|
||||
ULONGLONG g_gameassembly_seen_tick = 0;
|
||||
volatile LONG g_scheme_hook_called = 0;
|
||||
|
||||
int get_scheme_type_hook() {
|
||||
if (InterlockedCompareExchange(&g_scheme_hook_called, 1, 0) == 0) {
|
||||
hook_log("[cgss-http-hook] GetSchemeType hook invoked");
|
||||
}
|
||||
return kHttpSchemeType;
|
||||
}
|
||||
|
||||
void patch_custom_preference_scheme() {
|
||||
auto custom_preference = il2cpp_symbols::get_class(
|
||||
"Assembly-CSharp.dll", "Cute", "CustomPreference"
|
||||
);
|
||||
if (!custom_preference) {
|
||||
hook_log("[cgss-http-hook] failed to resolve Cute.CustomPreference");
|
||||
return;
|
||||
}
|
||||
|
||||
if (il2cpp_symbols::set_static_int_field(custom_preference, "_schemeType", kHttpSchemeType)) {
|
||||
hook_log("[cgss-http-hook] patched Cute.CustomPreference._schemeType=0");
|
||||
} else {
|
||||
hook_log("[cgss-http-hook] failed to patch Cute.CustomPreference._schemeType");
|
||||
}
|
||||
}
|
||||
|
||||
void try_install_hook() {
|
||||
if (InterlockedCompareExchange(&g_hook_installed, 1, 1) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto game_assembly = GetModuleHandleW(L"GameAssembly.dll");
|
||||
if (!game_assembly) {
|
||||
return;
|
||||
}
|
||||
if (InterlockedCompareExchange(&g_logged_gameassembly, 1, 0) == 0) {
|
||||
hook_log("[cgss-http-hook] GameAssembly.dll loaded");
|
||||
g_gameassembly_seen_tick = GetTickCount64();
|
||||
}
|
||||
if (g_gameassembly_seen_tick != 0 &&
|
||||
GetTickCount64() - g_gameassembly_seen_tick < kGameAssemblySettleDelayMs) {
|
||||
return;
|
||||
}
|
||||
|
||||
il2cpp_symbols::init(game_assembly);
|
||||
if (!il2cpp_symbols::ready()) {
|
||||
if (InterlockedCompareExchange(&g_exports_state, 1, 0) == 0) {
|
||||
hook_log("[cgss-http-hook] il2cpp exports not ready");
|
||||
}
|
||||
return;
|
||||
}
|
||||
LONG prev_exports_state = InterlockedExchange(&g_exports_state, 2);
|
||||
if (prev_exports_state != 2) {
|
||||
hook_log("[cgss-http-hook] il2cpp exports ready");
|
||||
}
|
||||
|
||||
patch_custom_preference_scheme();
|
||||
|
||||
auto addr = il2cpp_symbols::get_method_pointer(
|
||||
"Assembly-CSharp.dll", "Stage", "NetworkUtil", "GetSchemeType", 0
|
||||
);
|
||||
if (!addr) {
|
||||
hook_log("[cgss-http-hook] failed to resolve Stage.NetworkUtil.GetSchemeType");
|
||||
return;
|
||||
}
|
||||
|
||||
auto mh_status = MH_Initialize();
|
||||
if (mh_status != MH_OK && mh_status != MH_ERROR_ALREADY_INITIALIZED) {
|
||||
hook_log("[cgss-http-hook] MH_Initialize failed");
|
||||
return;
|
||||
}
|
||||
|
||||
auto create_status = MH_CreateHook(
|
||||
reinterpret_cast<void*>(addr),
|
||||
reinterpret_cast<void*>(&get_scheme_type_hook),
|
||||
reinterpret_cast<void**>(&g_orig_get_scheme_type)
|
||||
);
|
||||
if (create_status != MH_OK && create_status != MH_ERROR_ALREADY_CREATED) {
|
||||
hook_log("[cgss-http-hook] MH_CreateHook failed");
|
||||
return;
|
||||
}
|
||||
|
||||
auto enable_status = MH_EnableHook(reinterpret_cast<void*>(addr));
|
||||
if (enable_status != MH_OK && enable_status != MH_ERROR_ENABLED) {
|
||||
hook_log("[cgss-http-hook] MH_EnableHook failed");
|
||||
return;
|
||||
}
|
||||
|
||||
InterlockedExchange(&g_hook_installed, 1);
|
||||
hook_log("[cgss-http-hook] hooked Stage.NetworkUtil.GetSchemeType");
|
||||
}
|
||||
|
||||
DWORD WINAPI init_thread(void*) {
|
||||
for (int i = 0; i < kHookPollMaxAttempts; ++i) {
|
||||
try_install_hook();
|
||||
if (InterlockedCompareExchange(&g_hook_installed, 1, 1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
Sleep(kHookPollIntervalMs);
|
||||
}
|
||||
hook_log("[cgss-http-hook] timed out waiting for hook target");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void start_hook_thread() {
|
||||
CreateThread(nullptr, 0, init_thread, nullptr, 0, nullptr);
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
#include "stdinclude.hpp"
|
||||
|
||||
il2cpp_domain_get_t il2cpp_symbols::il2cpp_domain_get = nullptr;
|
||||
il2cpp_domain_assembly_open_t il2cpp_symbols::il2cpp_domain_assembly_open = nullptr;
|
||||
il2cpp_assembly_get_image_t il2cpp_symbols::il2cpp_assembly_get_image = nullptr;
|
||||
il2cpp_class_from_name_t il2cpp_symbols::il2cpp_class_from_name = nullptr;
|
||||
il2cpp_class_get_method_from_name_t il2cpp_symbols::il2cpp_class_get_method_from_name = nullptr;
|
||||
il2cpp_class_get_methods_t il2cpp_symbols::il2cpp_class_get_methods = nullptr;
|
||||
il2cpp_class_get_field_from_name_t il2cpp_symbols::il2cpp_class_get_field_from_name = nullptr;
|
||||
il2cpp_method_get_name_t il2cpp_symbols::il2cpp_method_get_name = nullptr;
|
||||
il2cpp_thread_attach_t il2cpp_symbols::il2cpp_thread_attach = nullptr;
|
||||
il2cpp_thread_current_t il2cpp_symbols::il2cpp_thread_current = nullptr;
|
||||
il2cpp_runtime_class_init_t il2cpp_symbols::il2cpp_runtime_class_init = nullptr;
|
||||
il2cpp_field_get_flags_t il2cpp_symbols::il2cpp_field_get_flags = nullptr;
|
||||
il2cpp_field_static_set_value_t il2cpp_symbols::il2cpp_field_static_set_value = nullptr;
|
||||
void* il2cpp_symbols::il2cpp_domain = nullptr;
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
void resolve(HMODULE module, const char* name, T& out) {
|
||||
out = reinterpret_cast<T>(GetProcAddress(module, name));
|
||||
}
|
||||
}
|
||||
|
||||
void il2cpp_symbols::init(HMODULE game_module) {
|
||||
resolve(game_module, "il2cpp_domain_get", il2cpp_domain_get);
|
||||
resolve(game_module, "il2cpp_domain_assembly_open", il2cpp_domain_assembly_open);
|
||||
resolve(game_module, "il2cpp_assembly_get_image", il2cpp_assembly_get_image);
|
||||
resolve(game_module, "il2cpp_class_from_name", il2cpp_class_from_name);
|
||||
resolve(game_module, "il2cpp_class_get_method_from_name", il2cpp_class_get_method_from_name);
|
||||
resolve(game_module, "il2cpp_class_get_methods", il2cpp_class_get_methods);
|
||||
resolve(game_module, "il2cpp_class_get_field_from_name", il2cpp_class_get_field_from_name);
|
||||
resolve(game_module, "il2cpp_method_get_name", il2cpp_method_get_name);
|
||||
resolve(game_module, "il2cpp_thread_attach", il2cpp_thread_attach);
|
||||
resolve(game_module, "il2cpp_thread_current", il2cpp_thread_current);
|
||||
resolve(game_module, "il2cpp_runtime_class_init", il2cpp_runtime_class_init);
|
||||
resolve(game_module, "il2cpp_field_get_flags", il2cpp_field_get_flags);
|
||||
resolve(game_module, "il2cpp_field_static_set_value", il2cpp_field_static_set_value);
|
||||
}
|
||||
|
||||
bool il2cpp_symbols::ready() {
|
||||
return il2cpp_domain_get && il2cpp_domain_assembly_open && il2cpp_assembly_get_image &&
|
||||
il2cpp_class_from_name && il2cpp_class_get_method_from_name &&
|
||||
il2cpp_class_get_field_from_name && il2cpp_thread_attach &&
|
||||
il2cpp_runtime_class_init && il2cpp_field_get_flags && il2cpp_field_static_set_value;
|
||||
}
|
||||
|
||||
bool il2cpp_symbols::domain_ready() {
|
||||
if (!il2cpp_domain_get) {
|
||||
return false;
|
||||
}
|
||||
if (!il2cpp_domain) {
|
||||
il2cpp_domain = il2cpp_domain_get();
|
||||
}
|
||||
return il2cpp_domain != nullptr;
|
||||
}
|
||||
|
||||
bool il2cpp_symbols::attach_thread() {
|
||||
if (!ready()) {
|
||||
return false;
|
||||
}
|
||||
if (!domain_ready()) {
|
||||
return false;
|
||||
}
|
||||
if (il2cpp_thread_current && il2cpp_thread_current()) {
|
||||
return true;
|
||||
}
|
||||
il2cpp_thread_attach(il2cpp_domain);
|
||||
return true;
|
||||
}
|
||||
|
||||
void* il2cpp_symbols::get_class(const char* assembly_name, const char* namespaze, const char* klass_name) {
|
||||
if (!attach_thread()) {
|
||||
hook_log("[cgss-http-hook] il2cpp domain not ready");
|
||||
return nullptr;
|
||||
}
|
||||
if (!ready() || !il2cpp_domain) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto assembly = il2cpp_domain_assembly_open(il2cpp_domain, assembly_name);
|
||||
if (!assembly) {
|
||||
hook_log("[cgss-http-hook] assembly not found");
|
||||
return nullptr;
|
||||
}
|
||||
auto image = il2cpp_assembly_get_image(assembly);
|
||||
if (!image) {
|
||||
hook_log("[cgss-http-hook] image not found");
|
||||
return nullptr;
|
||||
}
|
||||
auto klass = il2cpp_class_from_name(image, namespaze, klass_name);
|
||||
if (!klass) {
|
||||
hook_log("[cgss-http-hook] class not found");
|
||||
return nullptr;
|
||||
}
|
||||
return klass;
|
||||
}
|
||||
|
||||
bool il2cpp_symbols::set_static_int_field(void* klass, const char* field_name, int value) {
|
||||
if (!klass || !field_name || !attach_thread()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
il2cpp_runtime_class_init(klass);
|
||||
auto field = il2cpp_class_get_field_from_name(klass, field_name);
|
||||
if (!field) {
|
||||
hook_log("[cgss-http-hook] field not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto flags = il2cpp_field_get_flags(field);
|
||||
if ((flags & 0x10U) == 0) {
|
||||
hook_log("[cgss-http-hook] field is not static");
|
||||
return false;
|
||||
}
|
||||
|
||||
il2cpp_field_static_set_value(field, &value);
|
||||
return true;
|
||||
}
|
||||
|
||||
uintptr_t il2cpp_symbols::get_method_pointer(const char* assembly_name, const char* namespaze,
|
||||
const char* klass_name, const char* method_name, int args_count) {
|
||||
auto klass = get_class(assembly_name, namespaze, klass_name);
|
||||
if (!klass) {
|
||||
return 0;
|
||||
}
|
||||
auto method = il2cpp_class_get_method_from_name(klass, method_name, args_count);
|
||||
if (!method) {
|
||||
hook_log("[cgss-http-hook] method not found");
|
||||
return 0;
|
||||
}
|
||||
return method->methodPointer;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct MethodInfo;
|
||||
struct FieldInfo;
|
||||
|
||||
typedef void* (*il2cpp_domain_get_t)();
|
||||
typedef void* (*il2cpp_domain_assembly_open_t)(void* domain, const char* name);
|
||||
typedef void* (*il2cpp_assembly_get_image_t)(void* assembly);
|
||||
typedef void* (*il2cpp_class_from_name_t)(void* image, const char* namespaze, const char* name);
|
||||
typedef MethodInfo* (*il2cpp_class_get_method_from_name_t)(void* klass, const char* name, int argsCount);
|
||||
typedef MethodInfo* (*il2cpp_class_get_methods_t)(void* klass, void** iter);
|
||||
typedef FieldInfo* (*il2cpp_class_get_field_from_name_t)(void* klass, const char* name);
|
||||
typedef const char* (*il2cpp_method_get_name_t)(MethodInfo* method);
|
||||
typedef void (*il2cpp_thread_attach_t)(void* domain);
|
||||
typedef void* (*il2cpp_thread_current_t)();
|
||||
typedef void (*il2cpp_runtime_class_init_t)(void* klass);
|
||||
typedef uint32_t (*il2cpp_field_get_flags_t)(FieldInfo* field);
|
||||
typedef void (*il2cpp_field_static_set_value_t)(FieldInfo* field, void* value);
|
||||
|
||||
struct MethodInfo
|
||||
{
|
||||
uintptr_t methodPointer;
|
||||
uintptr_t invoker_method;
|
||||
const char* name;
|
||||
uintptr_t klass;
|
||||
const void* return_type;
|
||||
const void* parameters;
|
||||
uintptr_t methodDefinition;
|
||||
uintptr_t genericContainer;
|
||||
uint32_t token;
|
||||
uint16_t flags;
|
||||
uint16_t iflags;
|
||||
uint16_t slot;
|
||||
uint8_t parameters_count;
|
||||
uint8_t is_generic : 1;
|
||||
uint8_t is_inflated : 1;
|
||||
uint8_t wrapper_type : 1;
|
||||
uint8_t is_marshaled_from_native : 1;
|
||||
};
|
||||
|
||||
namespace il2cpp_symbols {
|
||||
extern il2cpp_domain_get_t il2cpp_domain_get;
|
||||
extern il2cpp_domain_assembly_open_t il2cpp_domain_assembly_open;
|
||||
extern il2cpp_assembly_get_image_t il2cpp_assembly_get_image;
|
||||
extern il2cpp_class_from_name_t il2cpp_class_from_name;
|
||||
extern il2cpp_class_get_method_from_name_t il2cpp_class_get_method_from_name;
|
||||
extern il2cpp_class_get_methods_t il2cpp_class_get_methods;
|
||||
extern il2cpp_class_get_field_from_name_t il2cpp_class_get_field_from_name;
|
||||
extern il2cpp_method_get_name_t il2cpp_method_get_name;
|
||||
extern il2cpp_thread_attach_t il2cpp_thread_attach;
|
||||
extern il2cpp_thread_current_t il2cpp_thread_current;
|
||||
extern il2cpp_runtime_class_init_t il2cpp_runtime_class_init;
|
||||
extern il2cpp_field_get_flags_t il2cpp_field_get_flags;
|
||||
extern il2cpp_field_static_set_value_t il2cpp_field_static_set_value;
|
||||
extern void* il2cpp_domain;
|
||||
|
||||
void init(HMODULE game_module);
|
||||
bool ready();
|
||||
bool domain_ready();
|
||||
bool attach_thread();
|
||||
void* get_class(const char* assembly_name, const char* namespaze, const char* klass_name);
|
||||
bool set_static_int_field(void* klass, const char* field_name, int value);
|
||||
uintptr_t get_method_pointer(const char* assembly_name, const char* namespaze,
|
||||
const char* klass_name, const char* method_name, int args_count);
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
#include "stdinclude.hpp"
|
||||
|
||||
namespace {
|
||||
HANDLE g_log_file = INVALID_HANDLE_VALUE;
|
||||
|
||||
HANDLE get_log_file() {
|
||||
if (g_log_file != INVALID_HANDLE_VALUE) {
|
||||
return g_log_file;
|
||||
}
|
||||
|
||||
char path[MAX_PATH] = {};
|
||||
DWORD len = GetModuleFileNameA(nullptr, path, MAX_PATH);
|
||||
if (len == 0 || len >= MAX_PATH) {
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
char* last_sep = path;
|
||||
for (char* p = path; *p != '\0'; ++p) {
|
||||
if (*p == '\\' || *p == '/') {
|
||||
last_sep = p;
|
||||
}
|
||||
}
|
||||
*last_sep = '\0';
|
||||
lstrcatA(path, "\\cgss-http-hook.log");
|
||||
|
||||
g_log_file = CreateFileA(
|
||||
path,
|
||||
FILE_APPEND_DATA,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr
|
||||
);
|
||||
return g_log_file;
|
||||
}
|
||||
}
|
||||
|
||||
void hook_log(const char* message) {
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
|
||||
OutputDebugStringA(message);
|
||||
OutputDebugStringA("\r\n");
|
||||
|
||||
HANDLE log_file = get_log_file();
|
||||
if (log_file == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD ignored = 0;
|
||||
WriteFile(log_file, message, lstrlenA(message), &ignored, nullptr);
|
||||
WriteFile(log_file, "\r\n", 2, &ignored, nullptr);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "stdinclude.hpp"
|
||||
|
||||
extern "C" {
|
||||
void* GetFileVersionInfoA_Original = nullptr;
|
||||
void* GetFileVersionInfoSizeA_Original = nullptr;
|
||||
void* VerQueryValueA_Original = nullptr;
|
||||
|
||||
BOOL WINAPI GetFileVersionInfoA_EXPORT(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) {
|
||||
using Fn = BOOL(WINAPI*)(LPCSTR, DWORD, DWORD, LPVOID);
|
||||
if (!GetFileVersionInfoA_Original) {
|
||||
SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
return FALSE;
|
||||
}
|
||||
return reinterpret_cast<Fn>(GetFileVersionInfoA_Original)(lptstrFilename, dwHandle, dwLen, lpData);
|
||||
}
|
||||
|
||||
DWORD WINAPI GetFileVersionInfoSizeA_EXPORT(LPCSTR lptstrFilename, LPDWORD lpdwHandle) {
|
||||
using Fn = DWORD(WINAPI*)(LPCSTR, LPDWORD);
|
||||
if (!GetFileVersionInfoSizeA_Original) {
|
||||
SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<Fn>(GetFileVersionInfoSizeA_Original)(lptstrFilename, lpdwHandle);
|
||||
}
|
||||
|
||||
BOOL WINAPI VerQueryValueA_EXPORT(LPCVOID pBlock, LPCSTR lpSubBlock, LPVOID* lplpBuffer, PUINT puLen) {
|
||||
using Fn = BOOL(WINAPI*)(LPCVOID, LPCSTR, LPVOID*, PUINT);
|
||||
if (!VerQueryValueA_Original) {
|
||||
SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
return FALSE;
|
||||
}
|
||||
return reinterpret_cast<Fn>(VerQueryValueA_Original)(pBlock, lpSubBlock, lplpBuffer, puLen);
|
||||
}
|
||||
}
|
||||
|
||||
void start_hook_thread();
|
||||
|
||||
namespace {
|
||||
constexpr DWORD kProxyInitDelayMs = 1000;
|
||||
HMODULE g_original = nullptr;
|
||||
|
||||
void load_original_version_dll() {
|
||||
if (g_original) {
|
||||
return;
|
||||
}
|
||||
|
||||
char system_dir[MAX_PATH] = {};
|
||||
GetSystemDirectoryA(system_dir, MAX_PATH);
|
||||
char path[MAX_PATH] = {};
|
||||
lstrcpynA(path, system_dir, MAX_PATH);
|
||||
lstrcatA(path, "\\version.dll");
|
||||
|
||||
g_original = LoadLibraryA(path);
|
||||
if (!g_original) {
|
||||
hook_log("[cgss-http-hook] failed to load original version.dll");
|
||||
return;
|
||||
}
|
||||
|
||||
GetFileVersionInfoA_Original = reinterpret_cast<void*>(GetProcAddress(g_original, "GetFileVersionInfoA"));
|
||||
GetFileVersionInfoSizeA_Original = reinterpret_cast<void*>(GetProcAddress(g_original, "GetFileVersionInfoSizeA"));
|
||||
VerQueryValueA_Original = reinterpret_cast<void*>(GetProcAddress(g_original, "VerQueryValueA"));
|
||||
|
||||
if (!GetFileVersionInfoA_Original || !GetFileVersionInfoSizeA_Original || !VerQueryValueA_Original) {
|
||||
hook_log("[cgss-http-hook] failed to resolve version exports");
|
||||
return;
|
||||
}
|
||||
|
||||
hook_log("[cgss-http-hook] version.dll initialized");
|
||||
}
|
||||
|
||||
DWORD WINAPI init_thread(void*) {
|
||||
Sleep(kProxyInitDelayMs);
|
||||
load_original_version_dll();
|
||||
start_hook_thread();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE module, DWORD reason, LPVOID) {
|
||||
if (reason == DLL_PROCESS_ATTACH) {
|
||||
DisableThreadLibraryCalls(module);
|
||||
CreateThread(nullptr, 0, init_thread, nullptr, 0, nullptr);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <MinHook.h>
|
||||
|
||||
#include "il2cpp_symbols.hpp"
|
||||
|
||||
void hook_log(const char* message);
|
||||
@@ -0,0 +1,4 @@
|
||||
EXPORTS
|
||||
GetFileVersionInfoA=GetFileVersionInfoA_EXPORT
|
||||
GetFileVersionInfoSizeA=GetFileVersionInfoSizeA_EXPORT
|
||||
VerQueryValueA=VerQueryValueA_EXPORT
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <winver.h>
|
||||
|
||||
#define VER_FILEVERSION 1,0,0,0
|
||||
#define VER_FILEVERSION_STR "1.0.0.0\0"
|
||||
#define VER_PRODUCTVERSION 1,0,0,0
|
||||
#define VER_PRODUCTVERSION_STR "1.0.0.0\0"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "YumeMichi\0"
|
||||
VALUE "FileDescription", "cgss-http-hook version.dll proxy\0"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "cgss-http-hook\0"
|
||||
VALUE "OriginalFilename", "version.dll\0"
|
||||
VALUE "ProductName", "cgss-http-hook\0"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
END
|
||||
END
|
||||
Reference in New Issue
Block a user