| 421 | #if defined(RESHADE_API_LIBRARY_EXPORT) |
| 422 | |
| 423 | bool ReShadeRegisterAddon(void *module, uint32_t api_version) |
| 424 | { |
| 425 | // Can only register an add-on module once |
| 426 | if (module == nullptr || module == g_module_handle || reshade::find_addon(module)) |
| 427 | { |
| 428 | reshade::log::message(reshade::log::level::error, "Failed to register add-on, because it provided an invalid module handle!"); |
| 429 | return false; |
| 430 | } |
| 431 | |
| 432 | // Check that the requested API version is supported |
| 433 | if (api_version == 0 || api_version > RESHADE_API_VERSION || (api_version / 10000) != (RESHADE_API_VERSION / 10000)) |
| 434 | { |
| 435 | reshade::log::message(reshade::log::level::error, "Failed to register add-on, because the requested API version (%u) is not supported (%u)!", api_version, static_cast<uint32_t>(RESHADE_API_VERSION)); |
| 436 | return false; |
| 437 | } |
| 438 | |
| 439 | const std::filesystem::path path = get_module_path(static_cast<HMODULE>(module)); |
| 440 | |
| 441 | reshade::addon_info info; |
| 442 | info.name = path.stem().u8string(); |
| 443 | info.file = path.filename().u8string(); |
| 444 | info.handle = module; |
| 445 | |
| 446 | DWORD version_dummy, version_size = GetFileVersionInfoSizeW(path.c_str(), &version_dummy); |
| 447 | std::vector<uint8_t> version_data(version_size); |
| 448 | if (GetFileVersionInfoW(path.c_str(), version_dummy, version_size, version_data.data())) |
| 449 | { |
| 450 | WORD language = 0x0400; |
| 451 | WORD codepage = 0x04b0; |
| 452 | |
| 453 | if (WORD *translation = nullptr; |
| 454 | VerQueryValueA(version_data.data(), "\\VarFileInfo\\Translation", reinterpret_cast<LPVOID *>(&translation), nullptr)) |
| 455 | // Simply use the first translation available |
| 456 | language = translation[0], codepage = translation[1]; |
| 457 | |
| 458 | const auto query_file_version_info = [&version_data, language, codepage](std::string &target, const char *name) { |
| 459 | char subblock[64]; |
| 460 | std::snprintf(subblock, std::size(subblock), "\\StringFileInfo\\%04x%04x\\%s", language, codepage, name); |
| 461 | if (char *value = nullptr; |
| 462 | VerQueryValueA(version_data.data(), subblock, reinterpret_cast<LPVOID *>(&value), nullptr)) |
| 463 | target = value; |
| 464 | }; |
| 465 | |
| 466 | query_file_version_info(info.name, "ProductName"); |
| 467 | query_file_version_info(info.author, "CompanyName"); |
| 468 | query_file_version_info(info.description, "FileDescription"); |
| 469 | |
| 470 | if (VS_FIXEDFILEINFO *fixed_file_version_info = nullptr; |
| 471 | VerQueryValueW(version_data.data(), L"\\", reinterpret_cast<LPVOID *>(&fixed_file_version_info), nullptr)) |
| 472 | { |
| 473 | info.version = { |
| 474 | HIWORD(fixed_file_version_info->dwFileVersionMS), |
| 475 | LOWORD(fixed_file_version_info->dwFileVersionMS), |
| 476 | HIWORD(fixed_file_version_info->dwFileVersionLS), |
| 477 | LOWORD(fixed_file_version_info->dwFileVersionLS) |
| 478 | }; |
| 479 | } |
| 480 | } |
no test coverage detected