main.asm
nqxcode_010-Editor-k3yg3n/main.asm
;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                    This is a keygen for 010 Editor                    |
;   |                                                                       |
;   |             http://www.sweetscape.com/download/010editor/             |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                               *WARNING*                               |
;   |                                                                       |
;   |                     FOR EDUCATIONAL PURPOSES ONLY                     |
;   |                                                                       |
;   |                           I did it for fun !                          |
;   |                     IF YOU LIKE IT PLEASE BUY IT                      |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

;   Boxes using ASCII Characters look beautiful :-)

;   This Program is only 6260 bytes !
;   I wrote the keygen first in C, using Visual Studio 2017
;   The Binary Produced by Visual Studio is 68,608 Bytes
;   So, I wrote it using Flat Assembler (FASM)

;   Usage Instructions

;   +-----------------------------------------------------------------------+
;   |                                 USAGE                                 |
;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |       1. Download Flat Assembler (FASM)                               |
;   |          URL : https://flatassembler.net/download.php                 |
;   |                                                                       |
;   |       2. Assemble the Source Code                                     |
;   |           -> fasm [filename].asm                                      |
;   |                                                                       |
;   |       3. Execute the Executable File                                  |
;   |                                                                       |
;   +-----------------------------------------------------------------------+


;   Format of the License Key generated by this program

;   +-----------------------------------------------------------------------+
;   |                            LICENSE FORMAT                             |
;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |               The License Key is Formatted as follows                 |
;   |                      AABB-CCDD-EEFF-GGHH-IIJJ                         |
;   |           1.  AA, BB, ..., JJ are Hexadecimal Values                  |
;   |           2.  DD is 0xAC                                              |
;   |           3.  Any License can be valid for atmost 983 years           |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

;   +-----------------------------------------------------------------------+
;   |                             LICENSE TYPES                             |
;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |               1.  Single User License                                 |
;   |               2.  N User License, where 1 < N < 1000                  |
;   |               3.  1000 User License (Site License)                    |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

;   We Need to Execute in Windows SubSystem
;

    format PE GUI 6.0
    entry initialize
    include '\fasm\include\win32ax.inc'

macro init_dll dll_id, dll_name, [func_name]
{
    common
        label dll_id
        .size = 0
        .dll db dll_name, 0
        label .functions
    forward
        .size = .size + 1
    forward
        dd func_name, fn#func_name
    forward
        label func_name dword
        .str db `func_name, 0
    forward
        label fn#func_name dword
        dd  0
}

macro push [reg] { forward push reg }
macro pop [reg] { reverse pop reg }

macro load_dll [dll_id]
{
    forward
    push ebx
    push esi
    push edx
    local ..next, ..load_loop
..next:
    mov eax, esp
    invoke fnLoadLibraryEx, dll_id#.dll, 0, 0
    mov esi, eax
    xor ebx, ebx
..load_loop:
    invoke fnGetProcAddress, esi, dword [dll_id#.functions+ebx*8]
    mov edx, [dll_id#.functions+ebx*8+4]
    mov [edx], eax
    inc ebx
    cmp ebx, dll_id#.size
    jl ..load_loop
    pop edx
    pop esi
    pop ebx
}

;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                          Control Identifiers                          |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

    IDD_MAIN_DIALOG     =       1729
    IDC_TEXT_NAME       =       0x01
    IDC_TEXT_USERS      =       0x02
    IDC_SPIN_USERS      =       0x03
    IDC_BTN_COPY        =       0x04
    IDC_BTN_CLRREG      =       0x05
    IDC_BTN_INFO        =       0x06
    IDC_LABEL_SERIAL    =       0x07
    IDC_DATE_DAYS       =       0x0A


    UDM_SETRANGE32      =       0x46f
    GDTR_MIN            =       0x001
    GDTR_MAX            =       0x002

    LANGUAGE_ID         =       LANG_ENGLISH or SUBLANG_ENGLISH_US

    FORMAT_FLAGS        =       FORMAT_MESSAGE_ALLOCATE_BUFFER \
                                    or FORMAT_MESSAGE_FROM_STRING \
                                    or FORMAT_MESSAGE_ARGUMENT_ARRAY

    DELETE_FLAGS        =       0x00010000 or KEY_QUERY_VALUE \
                                    or KEY_ENUMERATE_SUB_KEYS



;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                              Global Data                              |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

section '.data' data readable writeable

    fnGetProcAddress    dd  0
    fnLoadLibraryEx     dd  0

    szMsgBoxTitle       db      'Info', 0              ;   Our Message Box Title
    szHex               db      '0123456789ABCDEF'     ;   Hexadecimal translation table
    szLicense           rb      25                     ;   Stores the formatted license key
    szBytes             rb      10                     ;   Stores the raw bytes of license key
    hHeap               dd      ?                      ;   Handle to the heap of this process
    hTextName           dd      ?                      ;   Handle to text box labeled 'Name'
    hTextUsers          dd      ?                      ;   Handle to text box labeled 'Users'
    hSpinUsers          dd      ?                      ;   Handle to up-down control for 'Users'
    hBtnCopy            dd      ?                      ;   Handle to 'Copy' button
    hBtnInfo            dd      ?                      ;   Handle to 'Info' button
    hBtnClr             dd      ?                      ;   Handle to 'Clear Registry' button
    hStaticSerial       dd      ?                      ;   Handle to the label inside the 'License Info' frame
    hDatePicker         dd      ?                      ;   Handle to the date picker for license validity

    sysCurrDate     SYSTEMTIME  ?
    sysStartDate    SYSTEMTIME  ?
    sysEndDate      SYSTEMTIME  3000, 12, 3, 31, 23, 59, 59, 0
    sysFileTime         dq      ?

    ;
    ; Declaring imports in a dll
    ; init_dll [dll_id], [dll_name], [function_1], [function_2], ...
    ;
    ; For Example
    ; init_dll user32, 'user32.dll', MessageBoxTimeoutA
    ; init_dll kernel32, 'kernel32.dll', ExitProcess
    ;
    init_dll kernel32, 'kernel32.dll',\
        FormatMessageA, ExitProcess, GlobalAlloc, GlobalLock,\
        HeapAlloc, HeapFree, LocalFree, GetLocalTime,\
        SystemTimeToFileTime, FileTimeToSystemTime,\
        GlobalUnlock, FileTimeToLocalFileTime

    init_dll advapi32, 'advapi32.dll',\
        RegOpenKeyExA, RegDeleteTreeA, RegCloseKey, RegQueryValueExA

    init_dll ntdll, 'ntdll.dll', NtQuerySystemTime

    init_dll user32, 'user32.dll',\
        SendMessageA, OpenClipboard, EmptyClipboard, GetDlgItem,\
        SetClipboardData, CloseClipboard, DialogBoxIndirectParamA,\
        PostQuitMessage, GetDlgItemInt, MessageBoxA

        ;   Path to Registry Key for querying the existence of a registered user
    ;   Also used for deleting the 'CLASSES' SubKey

    szPath              db      'SOFTWARE\SweetScape\010 Editor', 0

    ;   Format String for displaying the registered user information
    ;   when 'Info' button is clicked

    szRegMsg            db      "Registered to '%1!s!'%nLicense Key: %2!s!", 0

    szNameKey           db      'Name', 0
    szPassword          db      'Password', 0

    ;   Message to display when 010 Editor is Unregistered

    szUnregistered      db      '010 Editor is currently UNREGISTERED !'
                        db      10
                        db      'Please Register it !', 0

    ;   Message to display when 010 Editor is not installed

    szNotInstalled      db      "You haven't yet installed 010 Editor !"
                        db      10, 10
                        db      'Download 010 Editor : http://www.sweetscape.com/download/010editor/', 0

    szMessages          dd      szNotInstalled, szUnregistered

    ;   Used for Calculating bytes at offset 4, 5, 6, 7 in the license key

    rawBytes            dd      969622712, 594890599, 1593930257, 1052452058, 890701766, 1677293387, 394424968
                        dd      266815521, 1532978959, 1211194088, 2019260265, 729421127, 953225874, 1117854514
                        dd      892543556, 2000911200, 514538256, 1400963072, 486675118, 1862498216, 1136668818
                        dd      758909582, 1653935295, 821063674, 888606944, 687085563, 890056597, 1513495898
                        dd      365692427, 184357836, 677395407, 863045227, 818746596, 391985767, 1842768403
                        dd      758385145, 1478392706, 1985112985, 1552765320, 746944881, 368385984, 1758203153
                        dd      1240817244, 660489060, 756944316, 1290697955, 844453952, 288239112, 1769473626
                        dd      1922176006, 826636519, 391520695, 1081548223, 1069693142, 1244729994, 766313326
                        dd      1101031894, 624951698, 14501479, 1794907983, 1460682958, 1660839647, 1104890686
                        dd      897721119, 1442187162, 480708164, 454443986, 1064446153, 1595150448, 1041527979
                        dd      1145775470, 1399869657, 255985995, 802693350, 2005610078, 1897360642, 2146073193
                        dd      1538606632, 431647857, 964049561, 395138253, 19164808, 856904574, 730737943
                        dd      708645054, 1506870658, 933323739, 819349658, 1780571206, 236747382, 533160167
                        dd      2042104933, 670325172, 2040165158, 1354372994, 705785180, 1669754395, 1066536508
                        dd      1426207888, 1437950089, 741941201, 796931522, 1694313338, 1290302874, 1367672048
                        dd      2039808424, 1062939821, 954597728, 1668694488, 859122242, 1369582617, 140269649
                        dd      53024683, 729221831, 816609203, 736893191, 55706320, 262747091, 1629838835, 581764799
                        dd      1488480625, 1607077349, 1879925846, 1453945819, 1521965565, 856558562, 1530662365
                        dd      1230847072, 1404918182, 1281256849, 1238970765, 272453753, 1640907491, 2127893021
                        dd      350314733, 556617458, 654390256, 1648581270, 531062411, 1862873022, 1241517385
                        dd      1471028336, 5121143, 1444839026, 1183580211, 1573659650, 2018540230, 1487873223
                        dd      234237236, 898254600, 1023090193, 728843548, 2007454357, 1451820833, 267351539
                        dd      302982385, 26807015, 865879122, 664886158, 195503981, 1625037691, 1330347906
                        dd      1742434311, 1330272217, 1645368040, 542321916, 1782121222, 411042851, 435386250
                        dd      1176704752, 1454246199, 1136813916, 1707755005, 224415730, 201138891, 989750331
                        dd      1006010278, 1147286905, 406860280, 840388503, 1282017578, 1605698145, 23396724
                        dd      862145265, 1898780916, 1855549801, 1571519230, 2083204840, 1859876276, 1602449334
                        dd      1009413590, 690816450, 86131931, 345661263, 1565025600, 857544170, 1329948960
                        dd      1211787679, 994381573, 991984748, 1956475134, 1098146294, 1655714289, 659576699
                        dd      689116467, 1485584392, 451884118, 255590636, 2108114754, 1266252396, 1589326471
                        dd      2019907768, 15552498, 1651075358, 614606175, 1656823678, 797605325, 1681594366
                        dd      2005080248, 624648446, 884695971, 1526931791, 1595240948, 439447199, 2060396292
                        dd      680093752, 409028215, 469068267, 195583689, 1791650630, 507724330, 1364025102
                        dd      1094582668, 813049577, 32316922, 1240756058, 1176200235, 2104494066, 325396055
                        dd      1796606917, 1709197385, 525495836, 1510101430, 735526761, 767523533, 1374043776
                        dd      1559389967, 567085571, 1560216161, 867042846, 1001796703, 1568754293, 628841972
                        dd      173812827, 379868455, 384973125

    ;   Template for dialog box

    tmpDialog           dd      DS_SETFONT or DS_FIXEDSYS or WS_CAPTION or WS_SYSMENU
                        dd      0
                        dw      13
                        dw      100, 100, 260, 114

                        align 2
                        dw      0
                        dw      0
                        du      '010 Editor KeyGen', 0
                        dw      8
                        du      'MS Shell Dlg 2', 0

                        align 4
                        dd      ES_LEFT+ES_AUTOHSCROLL+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_TABSTOP
                        dd      0
                        dw      34,12,69,12
                        dw      IDC_TEXT_NAME
                        dw      -1, 0x81
                        dw      0, 0

                        align 4
                        dd      WS_VISIBLE+WS_TABSTOP
                        dd      0
                        dw      153,23,90,14
                        dw      IDC_DATE_DAYS
                        du      'SysDateTimePick32', 0
                        dw      0, 0

                        align 4
                        dd      ES_LEFT+ES_AUTOHSCROLL+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_NUMBER
                        dd      0
                        dw      34,32,60,14
                        dw      IDC_TEXT_USERS
                        dw      -1, 0x81
                        dw      0, 0

                        align 4
                        dd      WS_CHILD or WS_VISIBLE or WS_TABSTOP or BS_PUSHBUTTON
                        dd      0
                        dw      72,93,50,14
                        dw      IDC_BTN_COPY
                        du      -1, 0x80
                        du      'Copy', 0
                        dw      0

                        align 4
                        dd      WS_CHILD or WS_VISIBLE or WS_TABSTOP or BS_PUSHBUTTON
                        dd      0
                        dw      203,93,50,14
                        dw      IDC_BTN_INFO
                        du      -1, 0x80
                        du      'Info', 0
                        dw      0

                        align 4
                        dd      WS_CHILD or WS_VISIBLE or WS_TABSTOP or BS_PUSHBUTTON
                        dd      0
                        dw      7,93,59,14
                        dw      IDC_BTN_CLRREG
                        du      -1, 0x80
                        du      'Clear Registry', 0
                        dw      0

                        align 4
                        dd      SS_LEFT+WS_CHILD+WS_VISIBLE+WS_GROUP
                        dd      0
                        dw      7,15,19,8
                        dw      -1
                        du      -1, 0x82
                        du      'Name', 0
                        dw      0

                        align 4
                        dd      SS_LEFT+WS_CHILD+WS_VISIBLE+WS_GROUP
                        dd      0
                        dw      7,35,19,8
                        dw      -1
                        du      -1, 0x82
                        du      'Users', 0
                        dw      0

                        align 4
                        dd      UDS_SETBUDDYINT+UDS_ARROWKEYS+WS_CHILD+WS_VISIBLE
                        dd      0
                        dw      93,32,12,14
                        dw      IDC_SPIN_USERS
                        du      'msctls_updown32', 0
                        dw      0, 0

                        align 4
                        dd      BS_GROUPBOX+WS_CHILD+WS_VISIBLE
                        dd      0
                        dw      7,50,245,36
                        dw      -1
                        du      -1, 0x80
                        du      'License Info', 0
                        dw      0

                        align 4
                        dd      SS_CENTER+WS_CHILD+WS_VISIBLE+WS_GROUP
                        dd      0
                        dw      70,64,120,12
                        dw      IDC_LABEL_SERIAL
                        du      -1, 0x82
                        dw      0, 0

                        align 4
                        dd      BS_GROUPBOX+WS_CHILD+WS_VISIBLE
                        dd      0
                        dw      109,11,143,34
                        dw      -1
                        du      -1, 0x80
                        du      'Validity', 0
                        dw      0

                        align 4
                        dd      SS_LEFT+WS_CHILD+WS_VISIBLE+WS_GROUP
                        dd      0
                        dw      117,26,29,8
                        dw      -1
                        du      -1, 0x82
                        du      'End Date', 0
                        dw      0

;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                             Text Section                              |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

section '.text' code executable

    GET_PROC_ADDRESS    =   0x8f900864
    LOAD_LIBRARY        =   0x00635164
    KERNEL32_HASH       =   0x29A1244C


jenkins_hash:
    push ebx
    xor eax, eax
@@:
    movzx ebx, byte [esi]
    or bl, bl
    jz @f
    add eax, ebx
    mov ebx, eax
    shl ebx, 10
    add eax, ebx
    mov ebx, eax
    shr ebx, 6
    xor eax, ebx
    inc esi
    jmp @b
@@:
    mov ebx, eax
    shl ebx, 3
    add eax, ebx
    mov ebx, eax
    shr ebx, 11
    xor eax, ebx
    mov ebx, eax
    shl ebx, 15
    add eax, ebx
    pop ebx
    ret

hash:
    push ebx
    xor eax, eax
    sub esi, 2
@@:
    inc esi
    inc esi
    movzx ebx, word [esi]
    or ebx, ebx
    jz .ret
    ror eax, 9
    xor eax, ebx
    cmp ebx, 0x61
    jl @b
    cmp ebx, 0x7b
    jge @b
    xor eax, ebx
    sub ebx, 0x20
    xor eax, ebx
    jmp @b
.ret:
    pop ebx
    ret

initialize:
    mov eax, [fs:0x30]
    mov eax, [eax+12]
    mov ebx, [eax+0x1c]

.find:
    mov esi, [ebx+0x20]
    call hash
    cmp eax, KERNEL32_HASH
    jz .found
    mov ebx, [ebx]
    jmp .find

.found:
    mov ebx, [ebx+8]
    mov eax, [ebx+0x3c]
    mov eax, [eax+ebx+24+96]
    add eax, ebx
    push eax
    mov ecx, [eax+24]
    mov ebp, [eax+32]   ; name table
    mov edx, [eax+36]   ; ordinal table
    add edx, ebx
    add ebp, ebx
    xor edi, edi

.search_loop:
    mov esi, [ebp]
    add esi, ebx
    call jenkins_hash
    cmp eax, LOAD_LIBRARY
    jnz .is_proc_addr
    inc edi
    movzx eax, word [edx]
    mov [fnLoadLibraryEx], eax
    jmp .next_func

.is_proc_addr:
    cmp eax, GET_PROC_ADDRESS
    jnz .next_func
    inc edi
    movzx eax, word [edx]
    mov [fnGetProcAddress], eax

.next_func:
    add edx, 2
    add ebp, 4
    cmp edi, 2
    jz @f
    dec ecx
    jnz .search_loop

@@:
    pop edi
    mov edx, [edi+28]
    add edx, ebx
    mov eax, [fnLoadLibraryEx]
    mov ecx, [edx+eax*4]
    add ecx, ebx
    mov [fnLoadLibraryEx], ecx
    mov eax, [fnGetProcAddress]
    mov ecx, [edx+eax*4]
    add ecx, ebx
    mov [fnGetProcAddress], ecx
    jmp main


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |           Function    :   get_last_block                              |
;   |           Arguments   :   %edi, %esi, %edx                            |
;   |               %edi -> Pointer to a String                             |
;   |               %esi -> # days left for license to become invalid       |
;   |               %edx -> # Users                                         |
;   |           Returns     :   %eax                                        |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |            Computes EE, FF, GG, HH and returns 0xHHGGFFEE             |
;   |                       See @LICENSE FORMAT above                       |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
get_last_block:
    push ebx
    push ecx
    xor ebx, ebx
    mov ecx, esi
    shl ecx, 4
    lea esi, [esi+ecx]
    mov ecx, edx
    shl edx, 4
    neg ecx
    lea edx, [edx+ecx]
    mov ecx, ebx
    mov eax, ebx
@@:
    movzx ebx, byte [edi]
    or bl, bl
    jz @f
    sub ebx, 0x61
    cmp ebx, 0x1a
    lea ebx, [ebx+0x41]
    cmovnb ebx, [edi]
    movzx ebx, bl
    add eax, [rawBytes+ebx*4]
    xor eax, [rawBytes+ebx*4+52]
    imul eax, [rawBytes+ebx*4+188]
    mov ebx, esi
    movzx ebx, bl
    add eax, [rawBytes+ebx*4]
    mov ebx, edx
    movzx ebx, bl
    add eax, [rawBytes+ebx*4]
    mov ebx, ecx
    movzx ebx, bl
    add eax, [rawBytes+ebx*4]
    lea ecx, [ecx+19]
    lea esi, [esi+9]
    lea edx, [edx+13]
    inc edi
    jmp @b
 @@:
    pop ecx
    pop ebx
    ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |           Function    :   get_days                                    |
;   |           Arguments   :   %edi                                        |
;   |               %edi -> # days left for license to become invalid       |
;   |           Returns     :   %eax                                        |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |   Computes the following                                              |
;   |                                                                       |
;   |           M = 0x1845c8a0ce512957                                      |
;   |           T = _time64(0)                                              |
;   |           M *= _mktime64(_localtime64(&T))                            |
;   |           M >>= 77                                                    |
;   |           return M                                                    |
;   |                                                                       |
;   |   i.e.,                                                               |
;   |           return mktime64(_localtime64(&T)) / 86400                   |
;   |       which is the number of days since January 1, 1970 at 00:00      |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
get_days:
    push ebx
    push eax
    push eax
    lea ebx, [esp]
    push eax
    push eax
    invoke fnNtQuerySystemTime, ebx
    invoke fnFileTimeToLocalFileTime, ebx, esp
    pop eax
    pop edx
    pop ebx
    pop ebx
    shrd eax, edx, 14
    shr edx, 14
    mov ebx, 0x324a9a7
    div ebx
    xor edx, edx
    lea eax, [eax+edi-134774]
    pop ebx
    ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |               Function    :   generate_license_key                    |
;   |               Arguments   :   %edi, %esi, %edx                        |
;   |                   %edi -> Pointer to String (User Name)               |
;   |                   %esi -> Number of Users                             |
;   |                   %edx -> Number of Years of Validity                 |
;   |               Return      :   none                                    |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |           Computes the License Key bytes in 'szBytes' array           |
;   |           and the formatted license key in 'szLicense' array          |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
generate_license_key:
    push edi
    push esi
    push edx
    push ebx
    push ecx
    mov edi, edx
    call get_days
    mov ecx, eax
    mov ebx, 17
    imul ebx
    xor eax, 0xE53167
    add eax, 0x2C175
    xor eax, 0x794c5f
    mov ebx, esi
    imul ebx, 11
    xor ebx, 0x3421
    sub ebx, 0x4D30
    xor ebx, 0x7892
    mov edi, [esp+16]
    mov esi, ecx
    mov edx, [esp+12]
    push eax
    call get_last_block
    mov ecx, ebx
    pop edx
    push ebx
    mov [szBytes+3], 0xAC
    mov [szBytes+4], al
    mov ebx, edx
    xor bh, al
    mov [szBytes+8], bh
    mov [szBytes+5], ah
    bswap edx
    xor dh, ah
    mov [szBytes+9], dh
    pop ebx
    xor cl, ah
    mov [szBytes+2], cl
    bswap eax
    mov [szBytes+6], ah
    mov ecx, edx
    bswap ecx
    xor cl, ah
    mov [szBytes], cl
    mov [szBytes+7], al
    xor bh, al
    mov [szBytes+1], bh
    mov eax, '----'
    mov edi, szLicense
    rept 6 {
        stosd
    }
    xor ebx, ebx
    sub edi, 24
@@:
    xor edx, edx
    movzx edx, [szBytes+ebx]
    mov ecx, edx
    shr dl, 4
    mov ah, [szHex+edx]
    and cl, 0xf
    mov al, [szHex+ecx]
    inc ebx
    shl eax, 16
    movzx edx, [szBytes+ebx]
    mov ecx, edx
    shr dl, 4
    mov ah, [szHex+edx]
    and cl, 0xf
    mov al, [szHex+ecx]
    bswap eax
    stosd
    inc edi
    inc ebx
    cmp ebx, 10
    jl @b
    pop ecx
    pop ebx
    pop edx
    pop esi
    pop edi
    ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |               Called when the 'Copy' button is clicked                |
;   |                                                                       |
;   |             Copies the displayed license key to clipboard             |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
copy_license:
    invoke fnSendMessageA, [hStaticSerial], WM_GETTEXTLENGTH, 0, 0
    and eax, eax
    jz .ret
    push ebx
    push esi
    inc eax
    mov ebx, eax
    invoke fnOpenClipboard, ebp
    invoke fnEmptyClipboard
    invoke fnGlobalAlloc, GHND, ebx
    mov esi, eax
    invoke fnGlobalLock, eax
    push eax
    invoke fnSendMessageA, [hStaticSerial], WM_GETTEXT, ebx, eax
    call [fnGlobalUnlock]
    invoke fnSetClipboardData, CF_TEXT, esi
    invoke fnCloseClipboard
    pop esi
    pop ebx

.ret:
    mov eax, 1
    ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                        WM_CLOSE Event Handler                         |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
on_close:
    invoke fnPostQuitMessage, 0
    jmp copy_license.ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                      WM_INITDIALOG Event Handler                      |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
on_init_dialog:
    mov eax, [fs:0x30]
    mov eax, [eax+0x18]
    mov [hHeap], eax

    invoke fnGetLocalTime, sysCurrDate
    mov edi, sysFileTime
    invoke fnSystemTimeToFileTime, sysCurrDate, edi
    add dword [edi], 0x2a69c000
    adc dword [edi+4], 0xc9
    invoke fnFileTimeToSystemTime, edi, sysStartDate

    ;   Store the Handles of the required controls

    invoke fnGetDlgItem, ebp, IDC_TEXT_NAME
    mov [hTextName], eax
    invoke fnGetDlgItem, ebp, IDC_TEXT_USERS
    mov [hTextUsers], eax
    invoke fnGetDlgItem, ebp, IDC_SPIN_USERS
    mov [hSpinUsers], eax
    invoke fnGetDlgItem, ebp, IDC_LABEL_SERIAL
    mov [hStaticSerial], eax
    invoke fnGetDlgItem, ebp, IDC_BTN_COPY
    mov [hBtnCopy], eax
    invoke fnGetDlgItem, ebp, IDC_BTN_INFO
    mov [hBtnInfo], eax
    invoke fnGetDlgItem, ebp, IDC_BTN_CLRREG
    mov [hBtnClr], eax
    invoke fnGetDlgItem, ebp, IDC_DATE_DAYS
    mov [hDatePicker], eax

    invoke fnSendMessageA, [hSpinUsers], UDM_SETBUDDY, [hTextUsers], 0
    invoke fnSendMessageA, [hSpinUsers], UDM_SETRANGE32, 1, 0x3e8
    invoke fnSendMessageA, [hSpinUsers], UDM_SETPOS, 0, 1
    invoke fnSendMessageA, [hTextUsers], EM_SETLIMITTEXT, 4, 0
    invoke fnSendMessageA, [hDatePicker], DTM_SETRANGE, 3, sysStartDate

    call $+22
    db 'ddd, MMM d, yyyy', 0
    invoke fnSendMessageA, [hDatePicker], DTM_SETFORMAT, 0

    ;   Prefer short jumps :-)

    jmp clear_license_display.ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |   Clear the contents of the label that displays the license key       |
;   |   EFLAGS.CF indicates whether memory is allocated from heap           |
;   |   If so, we need to free it                                           |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
clear_license_display:
    jnc @f
    invoke fnHeapFree, [hHeap], 0, edi
@@:
    lea eax, [szLicense+24]
    invoke fnSendMessageA, [hStaticSerial], WM_SETTEXT, 0, eax

.ret:
    mov eax, 1
    ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                        EN_CHANGE Event Handler                        |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
update_license_key:
    invoke fnSendMessageA, [hTextName], WM_GETTEXTLENGTH, 0, 0
    or eax, eax
    clc

    ;   ---------------------------------------------
    ;   Is the Number of Characters in UserName = 0 ?
    ;   ---------------------------------------------

    jz clear_license_display
    inc eax
    mov esi, eax

    ;   -----------------------------------------
    ;   Allocate Len(username)+1 bytes from heap
    ;   -----------------------------------------

    invoke fnHeapAlloc, [hHeap], HEAP_ZERO_MEMORY, eax
    or eax, eax
    stc

    ;   --------------------
    ;   Allocation Failed ?
    ;   --------------------

    jz clear_license_display
    mov edi, eax

    invoke fnSendMessageA, [hTextName], WM_GETTEXT, esi, eax
    invoke fnGetDlgItemInt, ebp, IDC_TEXT_USERS, NULL, FALSE
    mov ebx, eax
    invoke fnSendMessageA, [hDatePicker], DTM_GETSYSTEMTIME, 0, sysStartDate
    test eax, eax
    stc
    js clear_license_display

    ;   -------------------------------------------
    ;   Check Whether 1 <= Number of Users <= 1000
    ;   -------------------------------------------

    cmp ebx, 1
    jl clear_license_display
    cmp ebx, 1000
    jg clear_license_display

    ;   Get The Number of Days from the Selected Date

    push edi
    invoke fnSystemTimeToFileTime, sysStartDate, sysFileTime
    mov esi, dword [sysFileTime]
    mov edi, dword [sysFileTime+4]
    invoke fnSystemTimeToFileTime, sysCurrDate, sysFileTime
    sub esi, dword [sysFileTime]
    sbb edi, dword [sysFileTime+4]
    add esi, 0x2a69c000
    adc edi, 0xc9
    shrd esi, edi, 14
    shr edi, 14
    mov eax, esi
    mov edx, edi
    mov edi, 0x324a9a7
    div edi
    pop edi

    mov esi, ebx
    mov edx, eax

    ;   -------------------------------------------------
    ;   All parameters are valid, generate license key
    ;                   and display it
    ;   -------------------------------------------------

    call generate_license_key
    invoke fnSendMessageA, [hStaticSerial], WM_SETTEXT, 0, szLicense

    ;   -----------------------------------------------
    ;   Free the memory allocated for storing username
    ;   -----------------------------------------------

    invoke fnHeapFree, [hHeap], 0, edi
    jmp on_notify.ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                       WM_NOTIFY Event Handler                         |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

on_notify:
    mov eax, [esp+12]
    cmp eax, IDC_DATE_DAYS

    ;   Is WM_NOTIFY sent by the Date Picker Control ?

    jnz on_notify.ret
    mov eax, [esp+16]
    mov eax, [eax+8]
    cmp eax, DTN_DATETIMECHANGE

    ;   Selected Date changed ?

    jz update_license_key

.ret:
    mov eax, 1
    ret

;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |           Called when 'Clear Registry' button is clicked              |
;   |                                                                       |
;   |                   Deletes 'CLASSES' subkey in                         |
;   |         HKEY_CURRENT_USER\SOFTWARE\SweetScape\010 Editor              |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
clear_registry:
    xor eax, eax
    call $+13
    db 'CLASSES', 0
    push eax

    invoke fnRegOpenKeyExA, HKEY_CURRENT_USER, szPath, 0, DELETE_FLAGS, esp
    mov ebx, [esp]

    ;   Delete the tree pointed by the 'CLASSES' subkey

    call [fnRegDeleteTreeA]
    invoke fnRegCloseKey, ebx

    jmp on_notify.ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                 Called when 'Info' button is clicked                  |
;   |                                                                       |
;   |                Displays Registered License Information                |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
get_info:
    xor eax, eax
    push eax
    invoke fnRegOpenKeyExA, HKEY_CURRENT_USER, szPath, 0, KEY_QUERY_VALUE, esp
    or eax, eax
    clc
    jnz @f

    invoke fnHeapAlloc, [hHeap], HEAP_ZERO_MEMORY, 1024
    mov ebx, eax
    invoke fnHeapAlloc, [hHeap], HEAP_ZERO_MEMORY, 32
    mov esi, eax
    pop edi

    ;   ----------------------------------------------
    ;   Set EFLAGS.CF to indicate Memory is allocated
    ;   It must be freed if RegQueryValueEx fails
    ;   ----------------------------------------------

    push 1024
    invoke fnRegQueryValueExA, edi, szNameKey, 0, 0, ebx, esp
    cmp eax, 2
    stc

    ;   -----------------------------
    ;   "Name" Value doesn't exist ?
    ;   -----------------------------

    jz @f
    mov dword [esp], 32
    invoke fnRegQueryValueExA, edi, szPassword, 0, 0, esi, esp
    cmp eax, 2
    stc

    ;   ---------------------------------
    ;   "Password" Value doesn't exist ?
    ;   ---------------------------------

    jz @f
    mov [esp], edi
    call [fnRegCloseKey]

    ;   -------------------------------------------
    ;   Format and Display the License Information
    ;   -------------------------------------------

    xor eax, eax
    push eax
    push esi
    push ebx
    lea edi, [esp+8]

    invoke fnFormatMessageA, FORMAT_FLAGS, szRegMsg, 0, 0, edi, 1, esp
    invoke fnMessageBoxA, ebp, dword [edi], szMsgBoxTitle, MB_ICONINFORMATION

    ;   -------------------------
    ;   Free the memory allocated
    ;   -------------------------

    invoke fnHeapFree, [hHeap], 0, ebx
    invoke fnHeapFree, [hHeap], 0, esi
    add esp, 8
    call [fnLocalFree]

.ret:
    mov eax, 1
    ret

;   -----------------------------
;   Is 010 Editor Unregistered ?
;   -----------------------------
@@:
    pop eax
    pushf
    jnc @f
    invoke fnHeapFree, [hHeap], 0, ebx
    invoke fnHeapFree, [hHeap], 0, esi
    invoke fnRegCloseKey, edi
@@:
    popf
    sbb eax, eax
    neg eax
    invoke fnMessageBoxA, ebp, [szMessages+eax*4], szMsgBoxTitle, MB_ICONWARNING
    jmp get_info.ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                  Callback routine for the dialog box                  |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
dialog_callback:
    mov ebp, [esp+4]
    mov ecx, [esp+8]
    sub ecx, 0x10
    jz on_close
    sub ecx, 0x3e
    jz on_notify
    sub ecx, 0xc2
    jz on_init_dialog
    dec ecx
    jnz on_command.ret


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                       WM_COMMAND Event Handler                        |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
on_command:
    mov eax, [esp+12]
    movzx edx, ax
    shr eax, 16
    cmp eax, EN_CHANGE
    jz update_license_key
    cmp edx, IDC_BTN_COPY
    jz copy_license
    cmp edx, IDC_BTN_CLRREG
    jz clear_registry
    cmp edx, IDC_BTN_INFO
    jz get_info

.ret:
    xor eax, eax
    ret



;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                              Entry Point                              |
;   |                                                                       |
;   +-----------------------------------------------------------------------+
main:
    load_dll ntdll, kernel32, advapi32, user32
    mov eax, [fs:0x30]
    mov eax, [eax+8]
    invoke fnDialogBoxIndirectParamA, eax, tmpDialog, NULL, dialog_callback, NULL
    invoke fnExitProcess, 0


;   +-----------------------------------------------------------------------+
;   |                                                                       |
;   |                       Define the Resources                            |
;   |                                                                       |
;   +-----------------------------------------------------------------------+

section '.res' data readable resource

    directory RT_MANIFEST, manifest_info

    resource manifest_info, 1, LANGUAGE_ID, m_info
    ;   -----------------------------------
    ;   Manifest for enabling Visual Styles
    ;   -----------------------------------

    resdata m_info
        db "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
        db "<assembly xmlns='urn:schemas-microsoft-com:asm.v1' "
        db "manifestVersion='1.0'>"
        db '<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">'
        db '<security><requestedPrivileges>'
        db "<requestedExecutionLevel "
        db "level='asInvoker' uiAccess='false' />"
        db '</requestedPrivileges></security></trustInfo>'
        db '<dependency>'
        db '<dependentAssembly>'
        db "<assemblyIdentity type='win32' "
        db "name='Microsoft.Windows.Common-Controls' "
        db "version='6.0.0.0' processorArchitecture='*' "
        db "publicKeyToken='6595b64144ccf1df' language='*' />"
        db '</dependentAssembly>'
        db '</dependency>'
        db '</assembly>'
    endres
