🐧 Cross-platform build support

This commit is contained in:
bitcookies
2026-04-05 22:09:59 +08:00
parent 47fe667eda
commit 8c3814fe8e
12 changed files with 908 additions and 19 deletions
+129
View File
@@ -0,0 +1,129 @@
name: Build All Platforms
on:
workflow_dispatch:
jobs:
# --- Windows builds (MSBuild + vcpkg) ---
windows:
strategy:
matrix:
include:
- platform: x64
artifact: winrar-keygen-x64
- platform: Win32
artifact: winrar-keygen-x86
- platform: ARM64
artifact: winrar-keygen-arm64
name: Windows ${{ matrix.platform }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v6.0.2
- name: Setup vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: 'a34c873a9717a888f58dc05268dea15592c2f0ff'
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
- name: Build
run: |
msbuild winrar-keygen.sln /p:Configuration=Release /p:Platform=${{ matrix.platform }} /p:VcpkgEnableManifest=true
- name: Prepare artifact
shell: pwsh
run: |
$src = "bin/${{ matrix.platform }}-Release/winrar-keygen.exe"
Copy-Item $src "${{ matrix.artifact }}.exe"
- name: Upload artifact
uses: actions/upload-artifact@v6.0.0
with:
name: ${{ matrix.artifact }}
path: ${{ matrix.artifact }}.exe
# --- Linux x64 build (CMake) ---
linux-x64:
name: Linux x64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgmp-dev
- name: Build
run: |
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
- name: Prepare artifact
run: |
cp build/winrar-keygen winrar-keygen-linux-x64
chmod +x winrar-keygen-linux-x64
- name: Upload artifact
uses: actions/upload-artifact@v6.0.0
with:
name: winrar-keygen-linux-x64
path: winrar-keygen-linux-x64
# --- Linux ARM64 build (native runner) ---
linux-arm64:
name: Linux ARM64
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v6.0.2
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgmp-dev
- name: Build
run: |
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
- name: Prepare artifact
run: |
cp build/winrar-keygen winrar-keygen-linux-arm64
chmod +x winrar-keygen-linux-arm64
- name: Upload artifact
uses: actions/upload-artifact@v6.0.0
with:
name: winrar-keygen-linux-arm64
path: winrar-keygen-linux-arm64
# --- macOS ARM64 build (CMake) ---
macos:
name: macOS ARM64
runs-on: macos-latest
steps:
- uses: actions/checkout@v6.0.2
- name: Install dependencies
run: brew install gmp
- name: Build
run: |
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
- name: Prepare artifact
run: |
cp build/winrar-keygen winrar-keygen-macos-arm64
chmod +x winrar-keygen-macos-arm64
- name: Upload artifact
uses: actions/upload-artifact@v6.0.0
with:
name: winrar-keygen-macos-arm64
path: winrar-keygen-macos-arm64
+19 -2
View File
@@ -1,7 +1,24 @@
#pragma once #pragma once
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4146 4244 4267)
#endif
#include <gmp.h> #include <gmp.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
// MPIR (used by vcpkg x86/x64) provides mpz_*_sx/mpz_*_ux for intmax_t.
// Standard GMP (used by ARM64 and Linux/macOS) does not; fall back to long variants.
#ifndef __MPIR_VERSION
#define mpz_init_set_sx(z, v) mpz_init_set_si((z), static_cast<long>(v))
#define mpz_init_set_ux(z, v) mpz_init_set_ui((z), static_cast<unsigned long>(v))
#define mpz_set_sx(z, v) mpz_set_si((z), static_cast<long>(v))
#define mpz_set_ux(z, v) mpz_set_ui((z), static_cast<unsigned long>(v))
#endif
#include <vector> #include <vector>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
@@ -300,11 +317,11 @@ public:
} }
bool TestBit(size_t i) const noexcept { bool TestBit(size_t i) const noexcept {
return mpz_tstbit(_Value, i) != 0; return mpz_tstbit(_Value, static_cast<mp_bitcnt_t>(i)) != 0;
} }
void SetBit(size_t i) noexcept { void SetBit(size_t i) noexcept {
mpz_setbit(_Value, i); mpz_setbit(_Value, static_cast<mp_bitcnt_t>(i));
} }
std::string ToString(size_t Base, bool LowerCase) const { std::string ToString(size_t Base, bool LowerCase) const {
+50
View File
@@ -0,0 +1,50 @@
cmake_minimum_required(VERSION 3.16)
project(winrar-keygen LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Version
set(APP_VERSION "4.1.0.0")
add_executable(winrar-keygen
_tmain.cpp
BigInteger.hpp
EllipticCurveGF2m.hpp
GaloisField.hpp
Hasher.hpp
HasherCrc32Traits.hpp
HasherSha1Traits.hpp
WinRarConfig.hpp
WinRarKeygen.hpp
)
target_compile_definitions(winrar-keygen PRIVATE
APP_VERSION="${APP_VERSION}"
)
# Find GMP
find_path(GMP_INCLUDE_DIR gmp.h REQUIRED)
target_include_directories(winrar-keygen PRIVATE ${GMP_INCLUDE_DIR})
# macOS Universal Binary support
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
message(STATUS "Building macOS Universal Binary: ${CMAKE_OSX_ARCHITECTURES}")
endif()
# Static linking on Linux for portable binaries
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_library(GMP_STATIC_LIBRARY libgmp.a)
if(GMP_STATIC_LIBRARY)
target_link_libraries(winrar-keygen PRIVATE ${GMP_STATIC_LIBRARY})
target_link_options(winrar-keygen PRIVATE -static-libgcc -static-libstdc++)
message(STATUS "Using static GMP: ${GMP_STATIC_LIBRARY}")
else()
find_library(GMP_LIBRARY gmp REQUIRED)
target_link_libraries(winrar-keygen PRIVATE ${GMP_LIBRARY})
message(STATUS "Using dynamic GMP: ${GMP_LIBRARY}")
endif()
else()
find_library(GMP_LIBRARY gmp REQUIRED)
target_link_libraries(winrar-keygen PRIVATE ${GMP_LIBRARY})
endif()
+135 -1
View File
@@ -149,5 +149,139 @@ public:
} }
} }
}; };
#endif #else
#include <cstring>
#include <stdexcept>
struct HasherSha1Traits {
public:
static constexpr size_t BlockSize = 512 / 8;
static constexpr size_t DigestSize = 160 / 8;
struct DigestType {
uint8_t Bytes[DigestSize];
};
struct ContextType {
uint32_t State[5];
uint64_t Count;
uint8_t Buffer[64];
ContextType() noexcept : State{}, Count(0), Buffer{} {}
ContextType(const ContextType&) noexcept = default;
ContextType& operator=(const ContextType&) noexcept = default;
ContextType(ContextType&& Other) noexcept = default;
ContextType& operator=(ContextType&& Other) noexcept = default;
};
private:
static inline uint32_t RotateLeft(uint32_t x, int n) noexcept {
return (x << n) | (x >> (32 - n));
}
static void ProcessBlock(uint32_t state[5], const uint8_t block[64]) noexcept {
uint32_t w[80];
for (int i = 0; i < 16; ++i) {
w[i] = (static_cast<uint32_t>(block[i * 4]) << 24) |
(static_cast<uint32_t>(block[i * 4 + 1]) << 16) |
(static_cast<uint32_t>(block[i * 4 + 2]) << 8) |
(static_cast<uint32_t>(block[i * 4 + 3]));
}
for (int i = 16; i < 80; ++i) {
w[i] = RotateLeft(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
}
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4];
for (int i = 0; i < 80; ++i) {
uint32_t f, k;
if (i < 20) { f = (b & c) | (~b & d); k = 0x5A827999; }
else if (i < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1; }
else if (i < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; }
else { f = b ^ c ^ d; k = 0xCA62C1D6; }
uint32_t temp = RotateLeft(a, 5) + f + e + k + w[i];
e = d; d = c; c = RotateLeft(b, 30); b = a; a = temp;
}
state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e;
}
public:
static inline ContextType ContextCreate() {
ContextType Ctx;
Ctx.State[0] = 0x67452301;
Ctx.State[1] = 0xEFCDAB89;
Ctx.State[2] = 0x98BADCFE;
Ctx.State[3] = 0x10325476;
Ctx.State[4] = 0xC3D2E1F0;
Ctx.Count = 0;
return Ctx;
}
static inline ContextType ContextCreate(const void* lpBuffer, size_t cbBuffer) {
ContextType Ctx = ContextCreate();
ContextUpdate(Ctx, lpBuffer, cbBuffer);
return Ctx;
}
static inline ContextType ContextCopy(const ContextType& Ctx) {
return Ctx;
}
static inline void ContextUpdate(ContextType& Ctx, const void* lpBuffer, size_t cbBuffer) {
auto data = reinterpret_cast<const uint8_t*>(lpBuffer);
size_t bufferOffset = static_cast<size_t>(Ctx.Count % 64);
Ctx.Count += cbBuffer;
if (bufferOffset > 0) {
size_t toCopy = 64 - bufferOffset;
if (toCopy > cbBuffer) toCopy = cbBuffer;
std::memcpy(Ctx.Buffer + bufferOffset, data, toCopy);
data += toCopy;
cbBuffer -= toCopy;
bufferOffset += toCopy;
if (bufferOffset == 64) {
ProcessBlock(Ctx.State, Ctx.Buffer);
bufferOffset = 0;
}
}
while (cbBuffer >= 64) {
ProcessBlock(Ctx.State, data);
data += 64;
cbBuffer -= 64;
}
if (cbBuffer > 0) {
std::memcpy(Ctx.Buffer, data, cbBuffer);
}
}
static inline void ContextEvaluate(const ContextType& Ctx, DigestType& Digest) {
ContextType tmp = Ctx;
uint64_t totalBits = tmp.Count * 8;
uint8_t pad = 0x80;
ContextUpdate(tmp, &pad, 1);
uint8_t zero = 0;
while (tmp.Count % 64 != 56) {
ContextUpdate(tmp, &zero, 1);
}
uint8_t lenBytes[8];
for (int i = 7; i >= 0; --i) {
lenBytes[i] = static_cast<uint8_t>(totalBits);
totalBits >>= 8;
}
ContextUpdate(tmp, lenBytes, 8);
for (int i = 0; i < 5; ++i) {
Digest.Bytes[i * 4] = static_cast<uint8_t>(tmp.State[i] >> 24);
Digest.Bytes[i * 4 + 1] = static_cast<uint8_t>(tmp.State[i] >> 16);
Digest.Bytes[i * 4 + 2] = static_cast<uint8_t>(tmp.State[i] >> 8);
Digest.Bytes[i * 4 + 3] = static_cast<uint8_t>(tmp.State[i]);
}
}
static inline void ContextDestroy(ContextType& Ctx) noexcept {
std::memset(&Ctx, 0, sizeof(Ctx));
}
};
#endif
+9 -3
View File
@@ -9,6 +9,12 @@
#include <string> #include <string>
#include <utility> #include <utility>
#ifdef _MSC_VER
#define BSWAP32(x) _byteswap_ulong(x)
#else
#define BSWAP32(x) __builtin_bswap32(x)
#endif
template<typename __ConfigType> template<typename __ConfigType>
class WinRarKeygen { class WinRarKeygen {
public: public:
@@ -40,7 +46,7 @@ private:
Sha1Digest = Sha1.Evaluate(); Sha1Digest = Sha1.Evaluate();
for (unsigned i = 0; i < 5; ++i) { for (unsigned i = 0; i < 5; ++i) {
Generator[i + 1] = _byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]); Generator[i + 1] = BSWAP32(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]);
} }
} else { } else {
Generator[1] = 0xeb3eb781; Generator[1] = 0xeb3eb781;
@@ -59,7 +65,7 @@ private:
Sha1Digest = Sha1.Evaluate(); Sha1Digest = Sha1.Evaluate();
RawPrivateKey[i] = static_cast<uint16_t>( RawPrivateKey[i] = static_cast<uint16_t>(
_byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[0]) BSWAP32(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[0])
); );
} }
@@ -112,7 +118,7 @@ private:
HasherSha1Traits::DigestType Sha1Digest = Sha1.Evaluate(); HasherSha1Traits::DigestType Sha1Digest = Sha1.Evaluate();
for (size_t i = 0; i < 5; ++i) { for (size_t i = 0; i < 5; ++i) {
RawHash[i] = _byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]); RawHash[i] = BSWAP32(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]);
} }
// SHA1("") with all-zeroed initial value // SHA1("") with all-zeroed initial value
+470 -7
View File
@@ -1,17 +1,35 @@
#ifdef _WIN32
#include <windows.h> #include <windows.h>
#include <winhttp.h>
#include <fcntl.h> #include <fcntl.h>
#include <io.h> #include <io.h>
#else
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/stat.h>
#include <unistd.h>
#include <strings.h>
#endif
#include <locale.h> #include <locale.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <codecvt>
#include "WinRarConfig.hpp" #include "WinRarConfig.hpp"
#include "WinRarKeygen.hpp" #include "WinRarKeygen.hpp"
#include <system_error> #include <stdexcept>
#ifdef _WIN32
#pragma comment(lib, "Version.lib") #pragma comment(lib, "Version.lib")
#pragma comment(lib, "winhttp.lib")
#endif
#ifndef APP_VERSION
#define APP_VERSION "4.1.0.0"
#endif
#ifdef _WIN32
std::string WideToUtf8(const std::wstring& wstr) { std::string WideToUtf8(const std::wstring& wstr) {
if (wstr.empty()) return {}; if (wstr.empty()) return {};
int size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr); int size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
@@ -43,20 +61,30 @@ std::string WideToAnsi(const std::wstring& wstr) {
&result[0], size, nullptr, nullptr); &result[0], size, nullptr, nullptr);
return result; return result;
} }
#endif
enum class Encoding { ASCII, ANSI, UTF8 }; enum class Encoding { ASCII, ANSI, UTF8 };
struct Options { struct Options {
#ifdef _WIN32
std::wstring username; std::wstring username;
std::wstring license; std::wstring license;
Encoding encoding = Encoding::UTF8; Encoding encoding = Encoding::UTF8;
std::wstring outputFile = L"rarreg.key"; std::wstring outputFile = L"rarreg.key";
#else
std::string username;
std::string license;
Encoding encoding = Encoding::UTF8;
std::string outputFile = "rarreg.key";
#endif
bool textOnly = false; bool textOnly = false;
bool activate = false; bool activate = false;
bool showVersion = false; bool showVersion = false;
bool showHelp = false; bool showHelp = false;
bool checkUpdate = false;
}; };
#ifdef _WIN32
bool ParseArguments(int argc, wchar_t* argv[], Options& opts) { bool ParseArguments(int argc, wchar_t* argv[], Options& opts) {
std::vector<std::wstring> positional; std::vector<std::wstring> positional;
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
@@ -73,6 +101,9 @@ bool ParseArguments(int argc, wchar_t* argv[], Options& opts) {
if (arg == L"-a" || arg == L"--activate") { if (arg == L"-a" || arg == L"--activate") {
opts.activate = true; continue; opts.activate = true; continue;
} }
if (arg == L"-u" || arg == L"--update") {
opts.checkUpdate = true; return true;
}
if (arg == L"-e" || arg == L"--encoding") { if (arg == L"-e" || arg == L"--encoding") {
if (++i >= argc) { if (++i >= argc) {
std::wcerr << L"Error: Missing value for " << arg << L"\n"; std::wcerr << L"Error: Missing value for " << arg << L"\n";
@@ -114,7 +145,70 @@ bool ParseArguments(int argc, wchar_t* argv[], Options& opts) {
<< positional.size() << L"\n"; << positional.size() << L"\n";
return false; return false;
} }
#else
bool ParseArguments(int argc, char* argv[], Options& opts) {
std::vector<std::string> positional;
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "-v" || arg == "--version" || strcasecmp(arg.c_str(), "ver") == 0) {
opts.showVersion = true; return true;
}
if (arg == "-h" || arg == "--help" || strcasecmp(arg.c_str(), "help") == 0) {
opts.showHelp = true; return true;
}
if (arg == "-t" || arg == "--text") {
opts.textOnly = true; continue;
}
if (arg == "-a" || arg == "--activate") {
opts.activate = true; continue;
}
if (arg == "-u" || arg == "--update") {
opts.checkUpdate = true; return true;
}
if (arg == "-e" || arg == "--encoding") {
if (++i >= argc) {
std::cerr << "Error: Missing value for " << arg << "\n";
return false;
}
std::string val = argv[i];
if (strcasecmp(val.c_str(), "ascii") == 0) opts.encoding = Encoding::ASCII;
else if (strcasecmp(val.c_str(), "ansi") == 0) opts.encoding = Encoding::ANSI;
else if (strcasecmp(val.c_str(), "utf8") == 0 || strcasecmp(val.c_str(), "utf-8") == 0)
opts.encoding = Encoding::UTF8;
else {
std::cerr << "Error: Unknown encoding '" << val << "'. Use: ascii, ansi, utf8\n";
return false;
}
continue;
}
if (arg == "-o" || arg == "--output") {
if (++i >= argc) {
std::cerr << "Error: Missing value for " << arg << "\n";
return false;
}
opts.outputFile = argv[i]; continue;
}
if (!arg.empty() && arg[0] == '-') {
std::cerr << "Error: Unknown option '" << arg << "'\n";
return false;
}
positional.push_back(arg);
}
if (positional.size() == 2) {
opts.username = positional[0];
opts.license = positional[1];
return true;
}
if (positional.empty()) {
opts.showHelp = true; return true;
}
std::cerr << "Error: Expected 2 arguments (Username, LicenseName), got "
<< positional.size() << "\n";
return false;
}
#endif
#ifdef _WIN32
void ShowHelp(const std::wstring& version) { void ShowHelp(const std::wstring& version) {
std::wcout << L"WinRAR Keygen v" << version << L"\n\n"; std::wcout << L"WinRAR Keygen v" << version << L"\n\n";
std::wcout << L"Usage:\n"; std::wcout << L"Usage:\n";
@@ -126,17 +220,43 @@ void ShowHelp(const std::wstring& version) {
std::wcout << L" -o, --output <file> Output file (default: rarreg.key)\n"; std::wcout << L" -o, --output <file> Output file (default: rarreg.key)\n";
std::wcout << L" -a, --activate Write to %APPDATA%\\WinRAR\\rarreg.key\n"; std::wcout << L" -a, --activate Write to %APPDATA%\\WinRAR\\rarreg.key\n";
std::wcout << L" -t, --text Print to console only, don't write file\n"; std::wcout << L" -t, --text Print to console only, don't write file\n";
std::wcout << L" -u, --update Check for updates on GitHub\n";
std::wcout << L" -v, --version Show version\n"; std::wcout << L" -v, --version Show version\n";
std::wcout << L" -h, --help Show this help\n\n"; std::wcout << L" -h, --help Show this help\n\n";
std::wcout << L"Examples:\n"; std::wcout << L"Examples:\n";
std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\"\n"; std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\"\n";
std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\" -e ansi\n"; std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\" -e ascii\n";
std::wcout << L" winrar-keygen.exe \"YourName\" \"Single PC usage license\" -e utf8\n"; std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\" -a\n";
std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\" -o \"D:\\keys\\rarreg.key\"\n";
std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\" --activate\n";
std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\" -t\n"; std::wcout << L" winrar-keygen.exe \"Github\" \"Single PC usage license\" -t\n";
} }
#else
void ShowHelp(const std::string& version) {
std::cout << "WinRAR Keygen v" << version << "\n\n";
std::cout << "Usage:\n";
std::cout << " winrar-keygen <Username> <LicenseName> [options]\n";
std::cout << " winrar-keygen -v | --version\n";
std::cout << " winrar-keygen -h | --help\n\n";
std::cout << "Options:\n";
std::cout << " -e, --encoding <enc> utf8 (default), ascii\n";
std::cout << " -o, --output <file> Output file (default: rarreg.key)\n";
#ifdef __APPLE__
std::cout << " -a, --activate Write to ~/Library/Application Support/com.rarlab.WinRAR/rarreg.key\n";
#else
std::cout << " -a, --activate Write to ~/.rarkey\n";
#endif
std::cout << " -t, --text Print to console only, don't write file\n";
std::cout << " -u, --update Check for updates on GitHub\n";
std::cout << " -v, --version Show version\n";
std::cout << " -h, --help Show this help\n\n";
std::cout << "Examples:\n";
std::cout << " winrar-keygen \"Github\" \"Single PC usage license\"\n";
std::cout << " winrar-keygen \"Github\" \"Single PC usage license\" -e ascii\n";
std::cout << " winrar-keygen \"Github\" \"Single PC usage license\" -a\n";
std::cout << " winrar-keygen \"Github\" \"Single PC usage license\" -t\n";
}
#endif
#ifdef _WIN32
std::wstring GetExecutableVersion() { std::wstring GetExecutableVersion() {
wchar_t exePath[MAX_PATH] = {}; wchar_t exePath[MAX_PATH] = {};
DWORD pathLen = GetModuleFileNameW(nullptr, exePath, MAX_PATH); DWORD pathLen = GetModuleFileNameW(nullptr, exePath, MAX_PATH);
@@ -169,7 +289,13 @@ std::wstring GetExecutableVersion() {
std::to_wstring(HIWORD(fixedInfo->dwFileVersionLS)) + L"." + std::to_wstring(HIWORD(fixedInfo->dwFileVersionLS)) + L"." +
std::to_wstring(LOWORD(fixedInfo->dwFileVersionLS)); std::to_wstring(LOWORD(fixedInfo->dwFileVersionLS));
} }
#else
std::string GetAppVersion() {
return APP_VERSION;
}
#endif
#ifdef _WIN32
void PrintRegisterInfo(const WinRarKeygen<WinRarConfig>::RegisterInfo& Info, void PrintRegisterInfo(const WinRarKeygen<WinRarConfig>::RegisterInfo& Info,
const std::wstring& wUser, const std::wstring& wLicense) { const std::wstring& wUser, const std::wstring& wLicense) {
std::wstring uid = Utf8ToWide(Info.UID); std::wstring uid = Utf8ToWide(Info.UID);
@@ -184,6 +310,19 @@ void PrintRegisterInfo(const WinRarKeygen<WinRarConfig>::RegisterInfo& Info,
std::wcout << data.substr(i, 54) << L"\n"; std::wcout << data.substr(i, 54) << L"\n";
} }
} }
#else
void PrintRegisterInfo(const WinRarKeygen<WinRarConfig>::RegisterInfo& Info,
const std::string& user, const std::string& license) {
std::cout << "RAR registration data\n";
std::cout << user << "\n";
std::cout << license << "\n";
std::cout << "UID=" << Info.UID << "\n";
for (size_t i = 0; i < Info.HexData.length(); i += 54) {
std::cout << Info.HexData.substr(i, 54) << "\n";
}
}
#endif
std::string BuildRegFileContent(const WinRarKeygen<WinRarConfig>::RegisterInfo& Info) { std::string BuildRegFileContent(const WinRarKeygen<WinRarConfig>::RegisterInfo& Info) {
std::string s; std::string s;
@@ -197,6 +336,7 @@ std::string BuildRegFileContent(const WinRarKeygen<WinRarConfig>::RegisterInfo&
return s; return s;
} }
#ifdef _WIN32
bool WriteRegFile(const std::wstring& filePath, const std::string& content) { bool WriteRegFile(const std::wstring& filePath, const std::string& content) {
FILE* fp = nullptr; FILE* fp = nullptr;
if (_wfopen_s(&fp, filePath.c_str(), L"wb") != 0 || !fp) if (_wfopen_s(&fp, filePath.c_str(), L"wb") != 0 || !fp)
@@ -205,7 +345,17 @@ bool WriteRegFile(const std::wstring& filePath, const std::string& content) {
fclose(fp); fclose(fp);
return written == content.size(); return written == content.size();
} }
#else
bool WriteRegFile(const std::string& filePath, const std::string& content) {
FILE* fp = fopen(filePath.c_str(), "wb");
if (!fp) return false;
size_t written = fwrite(content.data(), 1, content.size(), fp);
fclose(fp);
return written == content.size();
}
#endif
#ifdef _WIN32
bool IsConsoleHandle(HANDLE handle) { bool IsConsoleHandle(HANDLE handle) {
if (handle == nullptr || handle == INVALID_HANDLE_VALUE) { if (handle == nullptr || handle == INVALID_HANDLE_VALUE) {
return false; return false;
@@ -238,7 +388,187 @@ void ConfigureConsoleOutput() {
std::wcerr << L"Failed to set stderr _O_U8TEXT\n"; std::wcerr << L"Failed to set stderr _O_U8TEXT\n";
} }
} }
#endif
struct Version {
int major = 0, minor = 0, patch = 0;
bool valid = false;
};
Version ParseVersion(const std::string& verStr) {
Version v;
std::string s = verStr;
if (!s.empty() && (s[0] == 'v' || s[0] == 'V')) s = s.substr(1);
#ifdef _MSC_VER
int count = sscanf_s(s.c_str(), "%d.%d.%d", &v.major, &v.minor, &v.patch);
#else
int count = sscanf(s.c_str(), "%d.%d.%d", &v.major, &v.minor, &v.patch);
#endif
v.valid = (count >= 2);
return v;
}
bool IsNewer(const Version& remote, const Version& local) {
if (remote.major != local.major) return remote.major > local.major;
if (remote.minor != local.minor) return remote.minor > local.minor;
return remote.patch > local.patch;
}
std::string ExtractTagFromJson(const std::string& responseBody) {
std::string tagKey = "\"tag_name\"";
size_t pos = responseBody.find(tagKey);
if (pos == std::string::npos) return "";
pos = responseBody.find('\"', pos + tagKey.length());
if (pos == std::string::npos) return "";
size_t end = responseBody.find('\"', pos + 1);
if (end == std::string::npos) return "";
return responseBody.substr(pos + 1, end - pos - 1);
}
int CompareAndPrintUpdate(const std::string& currentVersion, const std::string& remoteTag) {
Version local = ParseVersion(currentVersion);
Version remote = ParseVersion(remoteTag);
if (!remote.valid) {
#ifdef _WIN32
std::wcerr << L"Error: Could not parse remote version '" << Utf8ToWide(remoteTag) << L"'.\n";
#else
std::cerr << "Error: Could not parse remote version '" << remoteTag << "'.\n";
#endif
return -1;
}
if (IsNewer(remote, local)) {
#ifdef _WIN32
std::wcout << L"\n New version available: " << Utf8ToWide(remoteTag)
<< L" (current: v" << Utf8ToWide(currentVersion) << L")\n";
std::wcout << L" Download: https://github.com/bitcookies/winrar-keygen/releases/latest\n\n";
#else
std::cout << "\n New version available: " << remoteTag
<< " (current: v" << currentVersion << ")\n";
std::cout << " Download: https://github.com/bitcookies/winrar-keygen/releases/latest\n\n";
#endif
} else {
#ifdef _WIN32
std::wcout << L"Already up to date. (v" << Utf8ToWide(currentVersion) << L")\n";
#else
std::cout << "Already up to date. (v" << currentVersion << ")\n";
#endif
}
return 0;
}
#ifdef _WIN32
int CheckForUpdate(const std::string& currentVersion) {
std::wcout << L"Checking for updates...\n";
HINTERNET hSession = WinHttpOpen(L"winrar-keygen-updater",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (!hSession) {
std::wcerr << L"Error: Failed to initialize WinHTTP.\n";
return -1;
}
HINTERNET hConnect = WinHttpConnect(hSession, L"api.github.com",
INTERNET_DEFAULT_HTTPS_PORT, 0);
if (!hConnect) {
std::wcerr << L"Error: Failed to connect to api.github.com.\n";
WinHttpCloseHandle(hSession);
return -1;
}
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET",
L"/repos/bitcookies/winrar-keygen/releases/latest",
nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
if (!hRequest) {
std::wcerr << L"Error: Failed to create HTTP request.\n";
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return -1;
}
BOOL bResult = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
if (!bResult) {
std::wcerr << L"Error: Failed to send HTTP request. Check your network connection.\n";
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return -1;
}
bResult = WinHttpReceiveResponse(hRequest, nullptr);
if (!bResult) {
std::wcerr << L"Error: No response from GitHub API.\n";
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return -1;
}
std::string responseBody;
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
do {
dwSize = 0;
WinHttpQueryDataAvailable(hRequest, &dwSize);
if (dwSize == 0) break;
std::vector<char> buffer(dwSize);
WinHttpReadData(hRequest, buffer.data(), dwSize, &dwDownloaded);
responseBody.append(buffer.data(), dwDownloaded);
} while (dwSize > 0);
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
if (responseBody.empty()) {
std::wcerr << L"Error: Empty response from GitHub API.\n";
return -1;
}
std::string remoteTag = ExtractTagFromJson(responseBody);
if (remoteTag.empty()) {
std::wcerr << L"Error: Could not find version info in GitHub response.\n";
return -1;
}
return CompareAndPrintUpdate(currentVersion, remoteTag);
}
#else
int CheckForUpdate(const std::string& currentVersion) {
std::cout << "Checking for updates...\n";
FILE* pipe = popen("curl -s https://api.github.com/repos/bitcookies/winrar-keygen/releases/latest 2>/dev/null", "r");
if (!pipe) {
std::cerr << "Error: Failed to run curl. Make sure curl is installed.\n";
return -1;
}
std::string responseBody;
char buf[4096];
while (fgets(buf, sizeof(buf), pipe)) {
responseBody += buf;
}
int status = pclose(pipe);
if (status != 0 || responseBody.empty()) {
std::cerr << "Error: Failed to fetch update info. Check your network connection.\n";
return -1;
}
std::string remoteTag = ExtractTagFromJson(responseBody);
if (remoteTag.empty()) {
std::cerr << "Error: Could not find version info in GitHub response.\n";
return -1;
}
return CompareAndPrintUpdate(currentVersion, remoteTag);
}
#endif
#ifdef _WIN32
int wmain(int argc, wchar_t* argv[]) { int wmain(int argc, wchar_t* argv[]) {
ConfigureConsoleOutput(); ConfigureConsoleOutput();
@@ -248,6 +578,7 @@ int wmain(int argc, wchar_t* argv[]) {
} }
std::wstring version = GetExecutableVersion(); std::wstring version = GetExecutableVersion();
std::string versionUtf8 = WideToUtf8(version);
if (opts.showVersion) { if (opts.showVersion) {
std::wcout << L"winrar-keygen v" << version << L"\n"; std::wcout << L"winrar-keygen v" << version << L"\n";
@@ -257,6 +588,9 @@ int wmain(int argc, wchar_t* argv[]) {
ShowHelp(version); ShowHelp(version);
return 0; return 0;
} }
if (opts.checkUpdate) {
return CheckForUpdate(versionUtf8);
}
if (opts.activate && opts.outputFile != L"rarreg.key") { if (opts.activate && opts.outputFile != L"rarreg.key") {
std::wcerr << L"Error: --activate and -o cannot be used together.\n"; std::wcerr << L"Error: --activate and -o cannot be used together.\n";
@@ -271,7 +605,7 @@ int wmain(int argc, wchar_t* argv[]) {
wchar_t appdata[MAX_PATH] = {}; wchar_t appdata[MAX_PATH] = {};
DWORD len = ExpandEnvironmentStringsW(L"%APPDATA%\\WinRAR", appdata, MAX_PATH); DWORD len = ExpandEnvironmentStringsW(L"%APPDATA%\\WinRAR", appdata, MAX_PATH);
if (len == 0 || len > MAX_PATH) { if (len == 0 || len > MAX_PATH) {
std::wcerr << L"Error: Failed to resolve %%APPDATA%% path.\n"; std::wcerr << L"Error: Failed to resolve %APPDATA% path.\n";
return -1; return -1;
} }
CreateDirectoryW(appdata, nullptr); CreateDirectoryW(appdata, nullptr);
@@ -355,3 +689,132 @@ int wmain(int argc, wchar_t* argv[]) {
return 0; return 0;
} }
#else
int main(int argc, char* argv[]) {
Options opts;
if (!ParseArguments(argc, argv, opts)) {
return -1;
}
std::string version = GetAppVersion();
if (opts.showVersion) {
std::cout << "winrar-keygen v" << version << "\n";
return 0;
}
if (opts.showHelp) {
ShowHelp(version);
return 0;
}
if (opts.checkUpdate) {
return CheckForUpdate(version);
}
if (opts.activate && opts.outputFile != "rarreg.key") {
std::cerr << "Error: --activate and -o cannot be used together.\n";
return -1;
}
if (opts.activate && opts.textOnly) {
std::cerr << "Error: --activate and -t cannot be used together.\n";
return -1;
}
if (opts.activate) {
#ifdef __APPLE__
const char* home = getenv("HOME");
if (!home) {
std::cerr << "Error: Failed to resolve $HOME path.\n";
return -1;
}
std::string activateDir = std::string(home) + "/Library/Application Support/com.rarlab.WinRAR";
mkdir(activateDir.c_str(), 0755);
opts.outputFile = activateDir + "/rarreg.key";
#else
const char* home = getenv("HOME");
if (!home) {
std::cerr << "Error: Failed to resolve $HOME path.\n";
return -1;
}
opts.outputFile = std::string(home) + "/.rarkey";
#endif
}
try {
if (opts.username.empty() || opts.license.empty()) {
std::cerr << "Error: Username and License Name must not be empty.\n";
return -1;
}
if (opts.username.length() > 200 || opts.license.length() > 200) {
std::cerr << "Error: Username and License Name must not exceed 200 characters.\n";
return -1;
}
std::string displayUser = opts.username;
std::string displayLicense = opts.license;
std::string user, license;
switch (opts.encoding) {
case Encoding::UTF8: {
auto hasNonAscii = [](const std::string& s) {
for (unsigned char c : s)
if (c > 127) return true;
return false;
};
if (hasNonAscii(displayUser) &&
(displayUser.length() < 5 || displayUser.substr(0, 5) != "utf8:"))
displayUser = "utf8:" + displayUser;
if (hasNonAscii(displayLicense) &&
(displayLicense.length() < 5 || displayLicense.substr(0, 5) != "utf8:"))
displayLicense = "utf8:" + displayLicense;
user = displayUser;
license = displayLicense;
break;
}
case Encoding::ANSI:
std::cerr << "Warning: ANSI encoding is not supported on this platform. Using UTF-8.\n";
user = displayUser;
license = displayLicense;
break;
case Encoding::ASCII:
default:
user = displayUser;
license = displayLicense;
for (unsigned char c : user)
if (c > 127)
throw std::runtime_error(
"Username contains non-ASCII characters. Use '-e utf8'.");
for (unsigned char c : license)
if (c > 127)
throw std::runtime_error(
"License name contains non-ASCII characters. Use '-e utf8'.");
break;
}
auto Info = WinRarKeygen<WinRarConfig>::GenerateRegisterInfo(user.c_str(), license.c_str());
if (opts.textOnly) {
PrintRegisterInfo(Info, displayUser, displayLicense);
} else {
std::string content = BuildRegFileContent(Info);
if (!WriteRegFile(opts.outputFile, content)) {
std::cerr << "Error: Failed to write file: " << opts.outputFile << "\n";
return -1;
}
const char* encName = (opts.encoding == Encoding::UTF8) ? "UTF-8" :
(opts.encoding == Encoding::ANSI) ? "ANSI" : "ASCII";
std::cout << "\n";
PrintRegisterInfo(Info, displayUser, displayLicense);
std::cout << "\nDone! " << opts.outputFile << " has been generated. ("
<< encName << ")\n";
}
}
catch (std::exception& e) {
std::cerr << "Error: " << e.what() << "\n";
return -1;
}
return 0;
}
#endif
Binary file not shown.
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
{
"name": "winrar-keygen",
"version": "4.1.0.0",
"dependencies": [
"gmp"
]
}
+4 -4
View File
@@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,0,1,0 FILEVERSION 4,1,0,0
PRODUCTVERSION 4,0,1,0 PRODUCTVERSION 4,1,0,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@@ -69,12 +69,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "WinRAR Keygen" VALUE "CompanyName", "WinRAR Keygen"
VALUE "FileDescription", "WinRAR Key Generation Tool" VALUE "FileDescription", "WinRAR Key Generation Tool"
VALUE "FileVersion", "4.0.1.0" VALUE "FileVersion", "4.1.0.0"
VALUE "InternalName", "winrar-keygen.exe" VALUE "InternalName", "winrar-keygen.exe"
VALUE "LegalCopyright", "Copyright (C) 2021 Bitcookies" VALUE "LegalCopyright", "Copyright (C) 2021 Bitcookies"
VALUE "OriginalFilename", "winrar-keygen.exe" VALUE "OriginalFilename", "winrar-keygen.exe"
VALUE "ProductName", "WinRAR Keygen" VALUE "ProductName", "WinRAR Keygen"
VALUE "ProductVersion", "4.0.1.0" VALUE "ProductVersion", "4.1.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
+8 -2
View File
@@ -1,14 +1,16 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 17
VisualStudioVersion = 16.0.29009.5 VisualStudioVersion = 17.14.37111.16
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrar-keygen", "winrar-keygen.vcxproj", "{2443AA55-9534-4451-9BCC-48AC0982A0CC}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrar-keygen", "winrar-keygen.vcxproj", "{2443AA55-9534-4451-9BCC-48AC0982A0CC}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
@@ -21,6 +23,10 @@ Global
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x64.Build.0 = Release|x64 {2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x64.Build.0 = Release|x64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x86.ActiveCfg = Release|Win32 {2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x86.ActiveCfg = Release|Win32
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x86.Build.0 = Release|Win32 {2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|x86.Build.0 = Release|Win32
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Debug|ARM64.ActiveCfg = Debug|ARM64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Debug|ARM64.Build.0 = Debug|ARM64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|ARM64.ActiveCfg = Release|ARM64
{2443AA55-9534-4451-9BCC-48AC0982A0CC}.Release|ARM64.Build.0 = Release|ARM64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+77
View File
@@ -17,6 +17,14 @@
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>x64</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion> <VCProjectVersion>16.0</VCProjectVersion>
@@ -26,6 +34,7 @@
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet> <VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet> <VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='ARM64'">arm64-windows-static</VcpkgTriplet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -58,6 +67,21 @@
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation> <SpectreMitigation>false</SpectreMitigation>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
@@ -75,6 +99,12 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <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" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<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|ARM64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
@@ -96,6 +126,16 @@
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir> <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir> <IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
@@ -157,6 +197,43 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>