Finish process wrapper
This commit is contained in:
parent
c0be5d7cad
commit
908d480e59
@ -19,8 +19,8 @@ Reverse engineering and analysis of Call of Duty: Black Ops 3. Very experimental
|
||||
- [x] Disable Integrity Checks
|
||||
- [x] Demonware Emulation
|
||||
- [ ] Disable Anti-Debugging Mechanisms (probably never gonna happen cause who needs that if you have printf debugging)
|
||||
- [x] Process wrapper
|
||||
- [x] P2P multiplayer
|
||||
- [ ] Process hollowing loader
|
||||
- [ ] Dedicated Servers
|
||||
|
||||
## Disclaimer
|
||||
|
16
premake5.lua
16
premake5.lua
@ -285,10 +285,10 @@ project "common"
|
||||
dependencies.imports()
|
||||
|
||||
project "client"
|
||||
kind "SharedLib"
|
||||
kind "WindowedApp"
|
||||
language "C++"
|
||||
|
||||
targetname "d3d11"
|
||||
targetname "boiii"
|
||||
|
||||
pchheader "std_include.hpp"
|
||||
pchsource "src/client/std_include.cpp"
|
||||
@ -311,6 +311,18 @@ project "client"
|
||||
|
||||
dependencies.imports()
|
||||
|
||||
project "tlsdll"
|
||||
kind "SharedLib"
|
||||
language "C++"
|
||||
|
||||
files {"./src/tlsdll/**.rc", "./src/tlsdll/**.hpp", "./src/tlsdll/**.cpp", "./src/tlsdll/resources/**.*"}
|
||||
|
||||
includedirs {"./src/tlsdll", "%{prj.location}/src"}
|
||||
|
||||
links {"common"}
|
||||
|
||||
resincludedirs {"$(ProjectDir)src"}
|
||||
|
||||
|
||||
project "runner"
|
||||
kind "WindowedApp"
|
||||
|
@ -384,7 +384,7 @@ namespace arxan
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
memcpy(buffers[i], func, sizeof(buffer));
|
||||
@ -698,14 +698,11 @@ namespace arxan
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
component()
|
||||
void pre_start() override
|
||||
{
|
||||
auto* dll_characteristics = &utils::nt::library().get_optional_header()->DllCharacteristics;
|
||||
utils::hook::set<WORD>(dll_characteristics, *dll_characteristics | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
|
||||
}
|
||||
|
||||
void pre_start() override
|
||||
{
|
||||
disable_tls_callbacks();
|
||||
restore_debug_functions();
|
||||
|
||||
|
@ -18,13 +18,13 @@ namespace game
|
||||
|
||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x1420EC8B0};
|
||||
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{
|
||||
0x1420ED530_g
|
||||
0x1420ED530
|
||||
};
|
||||
WEAK symbol<void(char* text, int maxSize)> Con_GetTextCopy{0x14133A7D0};
|
||||
|
||||
// DB
|
||||
WEAK symbol<void(XZoneInfo* zoneInfo, uint32_t zoneCount, bool sync, bool suppressSync)> DB_LoadXAssets{
|
||||
0x1414236A0_g
|
||||
0x1414236A0
|
||||
};
|
||||
|
||||
// Live
|
||||
@ -50,12 +50,12 @@ namespace game
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetDebugName{0x1422BDCB0};
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetString{0x1422BFFF0};
|
||||
WEAK symbol<void(const char* dvarName, const char* string, bool createIfMissing)> Dvar_SetFromStringByName{
|
||||
0x1422C7F60_g
|
||||
0x1422C7F60
|
||||
};
|
||||
|
||||
// Rendering
|
||||
WEAK symbol<void(const char*, int, void*, float, float, float, float, float, float*, int)> R_AddCmdDrawText{
|
||||
0x141CD98D0_g
|
||||
0x141CD98D0
|
||||
};
|
||||
|
||||
// Variables
|
||||
|
@ -138,8 +138,16 @@ std::vector<std::unique_ptr<component_interface>>& component_loader::get_compone
|
||||
|
||||
size_t get_base()
|
||||
{
|
||||
static auto base = size_t(utils::nt::library{}.get_ptr());
|
||||
assert(base && "Failed to resolve base");
|
||||
static auto base = []
|
||||
{
|
||||
const utils::nt::library host{};
|
||||
if(!host || host == utils::nt::library::get_by_address(get_base))
|
||||
{
|
||||
throw std::runtime_error("Invalid host application");
|
||||
}
|
||||
|
||||
return size_t(host.get_ptr());
|
||||
}();
|
||||
return base;
|
||||
}
|
||||
|
||||
|
118
src/client/loader/loader.cpp
Normal file
118
src/client/loader/loader.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader.hpp"
|
||||
#include "tls.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
namespace loader
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void load_imports(const utils::nt::library& target)
|
||||
{
|
||||
const auto* const import_directory = &target.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
auto* descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress);
|
||||
|
||||
while (descriptor->Name)
|
||||
{
|
||||
std::string name = LPSTR(target.get_ptr() + descriptor->Name);
|
||||
|
||||
auto* name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->
|
||||
OriginalFirstThunk);
|
||||
auto* address_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
|
||||
if (!descriptor->OriginalFirstThunk)
|
||||
{
|
||||
name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
}
|
||||
|
||||
while (*name_table_entry)
|
||||
{
|
||||
FARPROC function = nullptr;
|
||||
std::string function_name;
|
||||
const char* function_procname;
|
||||
|
||||
if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry))
|
||||
{
|
||||
function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry));
|
||||
function_procname = MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
|
||||
function_name = import->Name;
|
||||
function_procname = function_name.data();
|
||||
}
|
||||
|
||||
auto library = utils::nt::library::load(name);
|
||||
if (library)
|
||||
{
|
||||
function = GetProcAddress(library, function_procname);
|
||||
}
|
||||
|
||||
if (!function)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load import '%s' from library '%s'",
|
||||
function_name.data(), name.data()));
|
||||
}
|
||||
|
||||
utils::hook::set(address_table_entry, reinterpret_cast<uintptr_t>(function));
|
||||
|
||||
name_table_entry++;
|
||||
address_table_entry++;
|
||||
}
|
||||
|
||||
descriptor++;
|
||||
}
|
||||
}
|
||||
|
||||
void load_tls(const utils::nt::library& target)
|
||||
{
|
||||
if (target.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
|
||||
{
|
||||
auto* target_tls = tls::allocate_tls_index();
|
||||
const auto* const source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(target.get_ptr() + target.
|
||||
get_optional_header()
|
||||
->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
|
||||
const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData;
|
||||
const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex);
|
||||
utils::hook::set<DWORD>(source_tls->AddressOfIndex, tls_index);
|
||||
|
||||
if (target_tls->AddressOfCallBacks)
|
||||
{
|
||||
utils::hook::set<void*>(target_tls->AddressOfCallBacks, nullptr);
|
||||
}
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(PVOID(target_tls->StartAddressOfRawData),
|
||||
source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE,
|
||||
&old_protect);
|
||||
|
||||
auto* const tls_base = *reinterpret_cast<LPVOID*>(__readgsqword(0x58) + 8ull * tls_index);
|
||||
std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData),
|
||||
tls_size);
|
||||
|
||||
VirtualProtect(target_tls, sizeof(*target_tls), PAGE_READWRITE, &old_protect);
|
||||
*target_tls = *source_tls;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils::nt::library load_binary(const std::string& filename)
|
||||
{
|
||||
const auto target = utils::nt::library::load(filename);
|
||||
if (!target)
|
||||
{
|
||||
throw std::runtime_error{"Failed to map binary!"};
|
||||
}
|
||||
|
||||
load_imports(target);
|
||||
load_tls(target);
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
7
src/client/loader/loader.hpp
Normal file
7
src/client/loader/loader.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <utils/nt.hpp>
|
||||
|
||||
namespace loader
|
||||
{
|
||||
utils::nt::library load_binary(const std::string& filename);
|
||||
}
|
42
src/client/loader/tls.cpp
Normal file
42
src/client/loader/tls.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include <std_include.hpp>
|
||||
#include "tls.hpp"
|
||||
|
||||
#include <utils/nt.hpp>
|
||||
#include <utils/binary_resource.hpp>
|
||||
|
||||
#include "resource.hpp"
|
||||
|
||||
namespace tls
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::binary_resource tls_dll_file(TLS_DLL, "boiii-tlsdll.dll");
|
||||
}
|
||||
|
||||
PIMAGE_TLS_DIRECTORY allocate_tls_index()
|
||||
{
|
||||
static auto already_allocated = false;
|
||||
if (already_allocated)
|
||||
{
|
||||
throw std::runtime_error("Currently only a single allocation is supported!");
|
||||
}
|
||||
|
||||
already_allocated = true;
|
||||
|
||||
const auto dll_path = tls_dll_file.get_extracted_file();
|
||||
const auto tls_dll = utils::nt::library::load(dll_path);
|
||||
if (!tls_dll)
|
||||
{
|
||||
throw std::runtime_error("Failed to load TLS DLL");
|
||||
}
|
||||
|
||||
const auto tls_dir_entry = tls_dll.get_optional_header()
|
||||
->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;
|
||||
if (!tls_dir_entry)
|
||||
{
|
||||
throw std::runtime_error("TLS DLL is invalid");
|
||||
}
|
||||
|
||||
return reinterpret_cast<PIMAGE_TLS_DIRECTORY>(tls_dll.get_ptr() + tls_dir_entry);
|
||||
}
|
||||
}
|
6
src/client/loader/tls.hpp
Normal file
6
src/client/loader/tls.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace tls
|
||||
{
|
||||
PIMAGE_TLS_DIRECTORY allocate_tls_index();
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "loader/loader.hpp"
|
||||
|
||||
#include <utils/finally.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
@ -11,6 +12,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
volatile bool g_call_tls_callbacks = false;
|
||||
std::pair<void**, void*> g_original_import{};
|
||||
|
||||
DECLSPEC_NORETURN void WINAPI exit_hook(const uint32_t code)
|
||||
@ -84,8 +86,61 @@ namespace
|
||||
utils::io::remove_file(game_path.generic_string());
|
||||
}
|
||||
|
||||
bool run()
|
||||
PIMAGE_TLS_CALLBACK* get_tls_callbacks()
|
||||
{
|
||||
const utils::nt::library game{};
|
||||
const auto& entry = game.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
|
||||
if (!entry.VirtualAddress || !entry.Size)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto* tls_dir = reinterpret_cast<IMAGE_TLS_DIRECTORY*>(game.get_ptr() + entry.VirtualAddress);
|
||||
return reinterpret_cast<PIMAGE_TLS_CALLBACK*>(tls_dir->AddressOfCallBacks);
|
||||
}
|
||||
|
||||
void run_tls_callbacks(const DWORD reason)
|
||||
{
|
||||
if (!g_call_tls_callbacks)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* callback = get_tls_callbacks();
|
||||
while (callback && *callback)
|
||||
{
|
||||
(*callback)(GetModuleHandleA(nullptr), reason, nullptr);
|
||||
++callback;
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] thread_local struct tls_runner
|
||||
{
|
||||
tls_runner()
|
||||
{
|
||||
run_tls_callbacks(DLL_THREAD_ATTACH);
|
||||
}
|
||||
|
||||
~tls_runner()
|
||||
{
|
||||
run_tls_callbacks(DLL_THREAD_DETACH);
|
||||
}
|
||||
} tls_runner;
|
||||
|
||||
FARPROC load_process(const std::string& procname)
|
||||
{
|
||||
const auto proc = loader::load_binary(procname);
|
||||
|
||||
auto* const peb = reinterpret_cast<PPEB>(__readgsqword(0x60));
|
||||
peb->Reserved3[1] = proc.get_ptr();
|
||||
static_assert(offsetof(PEB, Reserved3[1]) == 0x10);
|
||||
|
||||
return FARPROC(proc.get_ptr() + proc.get_relative_entry_point());
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FARPROC entry_point{};
|
||||
srand(uint32_t(time(nullptr)) ^ ~(GetTickCount() * GetCurrentProcessId()));
|
||||
|
||||
{
|
||||
@ -100,12 +155,19 @@ namespace
|
||||
|
||||
try
|
||||
{
|
||||
patch_imports();
|
||||
remove_crash_file();
|
||||
|
||||
entry_point = load_process("BlackOps3.exe");
|
||||
if (!entry_point)
|
||||
{
|
||||
throw std::runtime_error("Unable to load binary into memory");
|
||||
}
|
||||
|
||||
patch_imports();
|
||||
|
||||
if (!component_loader::pre_start())
|
||||
{
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
premature_shutdown = false;
|
||||
@ -113,141 +175,17 @@ namespace
|
||||
catch (std::exception& e)
|
||||
{
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class patch
|
||||
{
|
||||
public:
|
||||
patch() = default;
|
||||
|
||||
patch(void* source, void* target)
|
||||
: source_(source)
|
||||
{
|
||||
memcpy(this->data_, source, sizeof(this->data_));
|
||||
utils::hook::jump(this->source_, target, true, true);
|
||||
}
|
||||
|
||||
~patch()
|
||||
{
|
||||
if (source_)
|
||||
{
|
||||
utils::hook::copy(this->source_, this->data_, sizeof(this->data_));
|
||||
}
|
||||
}
|
||||
|
||||
patch(patch&& obj) noexcept
|
||||
: patch()
|
||||
{
|
||||
this->operator=(std::move(obj));
|
||||
}
|
||||
|
||||
patch& operator=(patch&& obj) noexcept
|
||||
{
|
||||
if (this != &obj)
|
||||
{
|
||||
this->~patch();
|
||||
|
||||
this->source_ = obj.source_;
|
||||
memcpy(this->data_, obj.data_, sizeof(this->data_));
|
||||
|
||||
obj.source_ = nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void* source_{nullptr};
|
||||
uint8_t data_[15]{};
|
||||
};
|
||||
|
||||
std::vector<patch> initialization_hooks{};
|
||||
|
||||
uint8_t* get_entry_point()
|
||||
{
|
||||
const utils::nt::library game{};
|
||||
return game.get_ptr() + game.get_optional_header()->AddressOfEntryPoint;
|
||||
}
|
||||
|
||||
std::vector<uint8_t*> get_tls_callbacks()
|
||||
{
|
||||
const utils::nt::library game{};
|
||||
const auto& entry = game.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
|
||||
if (!entry.VirtualAddress || !entry.Size)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto* tls_dir = reinterpret_cast<IMAGE_TLS_DIRECTORY*>(game.get_ptr() + entry.VirtualAddress);
|
||||
auto* callback = reinterpret_cast<uint8_t**>(tls_dir->AddressOfCallBacks);
|
||||
|
||||
std::vector<uint8_t*> addresses{};
|
||||
while (callback && *callback)
|
||||
{
|
||||
addresses.emplace_back(*callback);
|
||||
++callback;
|
||||
}
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
int patch_main()
|
||||
{
|
||||
if (!run())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
initialization_hooks.clear();
|
||||
return reinterpret_cast<int(*)()>(get_entry_point())();
|
||||
}
|
||||
|
||||
void nullsub()
|
||||
{
|
||||
}
|
||||
|
||||
void patch_entry_point()
|
||||
{
|
||||
initialization_hooks.emplace_back(get_entry_point(), patch_main);
|
||||
|
||||
for (auto* tls_callback : get_tls_callbacks())
|
||||
{
|
||||
initialization_hooks.emplace_back(tls_callback, nullsub);
|
||||
}
|
||||
g_call_tls_callbacks = true;
|
||||
return static_cast<int>(entry_point());
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE, const DWORD reason, LPVOID)
|
||||
|
||||
int __stdcall WinMain(HINSTANCE, HINSTANCE, PSTR, int)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
patch_entry_point();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport)
|
||||
HRESULT D3D11CreateDevice(void* adapter, const uint64_t driver_type,
|
||||
const HMODULE software, const UINT flags,
|
||||
const void* p_feature_levels, const UINT feature_levels,
|
||||
const UINT sdk_version, void** device, void* feature_level,
|
||||
void** immediate_context)
|
||||
{
|
||||
static auto func = []
|
||||
{
|
||||
char dir[MAX_PATH]{0};
|
||||
GetSystemDirectoryA(dir, sizeof(dir));
|
||||
|
||||
const auto d3d11 = utils::nt::library::load(dir + "/d3d11.dll"s);
|
||||
return d3d11.get_proc<decltype(&D3D11CreateDevice)>("D3D11CreateDevice");
|
||||
}();
|
||||
|
||||
return func(adapter, driver_type, software, flags, p_feature_levels, feature_levels, sdk_version, device,
|
||||
feature_level, immediate_context);
|
||||
return main();
|
||||
}
|
||||
|
@ -13,3 +13,4 @@
|
||||
#define DW_QOSCONFIG 307
|
||||
|
||||
#define RUNNER 308
|
||||
#define TLS_DLL 309
|
||||
|
@ -108,6 +108,12 @@ RUNNER RCDATA "../../build/bin/x64/Debug/runner.exe"
|
||||
RUNNER RCDATA "../../build/bin/x64/Release/runner.exe"
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
TLS_DLL RCDATA "../../build/bin/x64/Debug/tlsdll.dll"
|
||||
#else
|
||||
TLS_DLL RCDATA "../../build/bin/x64/Release/tlsdll.dll"
|
||||
#endif
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
7
src/tlsdll/dllmain.cpp
Normal file
7
src/tlsdll/dllmain.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#define TLS_PAYLOAD_SIZE 0x2000
|
||||
thread_local char tls_data[TLS_PAYLOAD_SIZE];
|
||||
|
||||
__declspec(dllexport) void* get_tls_data()
|
||||
{
|
||||
return &tls_data[0];
|
||||
}
|
100
src/tlsdll/resource.rc
Normal file
100
src/tlsdll/resource.rc
Normal file
@ -0,0 +1,100 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#pragma code_page(65001)
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "windows.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""windows.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "X Labs"
|
||||
VALUE "FileDescription", "TLS index allocation dll"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "InternalName", "TLS DLL"
|
||||
VALUE "LegalCopyright", "All rights reserved."
|
||||
VALUE "OriginalFilename", "tlsdll.dll"
|
||||
VALUE "ProductName", "tlsdll"
|
||||
VALUE "ProductVersion", "1.0.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Binary Data
|
||||
//
|
||||
|
||||
// Nothing here
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
Loading…
Reference in New Issue
Block a user