File "xdmgr.bas"

Path: /xdmgr/xdmgr.bas
File size: 16.98 KB
MIME-type:
Charset: utf-8

#COMPILE EXE
#DIM ALL

$EXE = "xdmgr - ExeData Manager"
$VER = "v0.1"

'------------------------------------------------------------------------------
'   ** Includes **
'------------------------------------------------------------------------------
#RESOURCE "res\xdmgr.pbr"
#INCLUDE ONCE "WIN32API.INC"
#INCLUDE ONCE "inc\GdiPlus.inc"
#INCLUDE ONCE "inc\xdata.inc"
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** Constants **
'------------------------------------------------------------------------------
%IDC_LBL_DUM  = 1001
%IDC_LBL_NFO  = 1002
%IDC_LBL_EXE  = 1003
%IDC_BTN_EXE  = 1004
%IDC_LVW_LST  = 1005
%IDC_BTN_ADD  = 1006
%IDC_BTN_RM1  = 1007
%IDC_BTN_RMA  = 1008
%IDC_BTN_PVW  = 1009
%IDC_BTN_XT1  = 1010
%IDC_BTN_XTA  = 1011
'------------------------------------------------------------------------------
GLOBAL myExe AS STRING
GLOBAL myNfo AS STRING
GLOBAL xd()  AS ExeData
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** Main Application Entry Point **
'------------------------------------------------------------------------------
FUNCTION PBMAIN()
    ' Initialize GDI+ library
    GdipInitialize()
    ' Clean previous session
    KILL EXE.PATH$ + "temp.img"
    ' Treat arguments
    IF INSTR(LCASE$(COMMAND$), ".exe") > 0 THEN myExe = TRIM$(COMMAND$, $DQ)
    ' Show main dialog
    MainShow %HWND_DESKTOP
END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
SUB LogMe(s AS STRING)
END SUB
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
MACRO RefreshControls
    LISTVIEW RESET CB.HNDL, %IDC_LVW_LST
    REDIM xd(-1)
    CONTROL SET TEXT  CB.HNDL, %IDC_LBL_EXE, myExe
    IF myExe <> "" THEN
        CONTROL ENABLE CB.HNDL, %IDC_BTN_ADD
        CONTROL SET COLOR CB.HNDL, %IDC_LBL_EXE, -1, %WHITE
    END IF
    ParseExeData myExe, xd()
    FOR i = UBOUND(xd) TO LBOUND(xd) STEP -1
        LISTVIEW INSERT ITEM CB.HNDL, %IDC_LVW_LST, 1, %NULL, FORMAT$(i)
        LISTVIEW SET TEXT CB.HNDL, %IDC_LVW_LST, 1, 2, xd(i).desc
        LISTVIEW SET TEXT CB.HNDL, %IDC_LVW_LST, 1, 3, IIF$(INSTR(GetExeData(myExe,xd(i)),CHR$(0)),"Binary","Text")
        LISTVIEW SET TEXT CB.HNDL, %IDC_LVW_LST, 1, 4, FORMAT$(xd(i).length,"#,") & " B"
        LISTVIEW SET TEXT CB.HNDL, %IDC_LVW_LST, 1, 5, "@ " & FORMAT$(xd(i).address,"#,")
    NEXT
    IF UBOUND(xd) >= 1 THEN
        LISTVIEW SELECT CB.HNDL, %IDC_LVW_LST, 1
        CONTROL ENABLE CB.HNDL, %IDC_BTN_PVW
        CONTROL ENABLE CB.HNDL, %IDC_BTN_XT1
        CONTROL ENABLE CB.HNDL, %IDC_BTN_XTA
        CONTROL ENABLE CB.HNDL, %IDC_BTN_RM1
        CONTROL ENABLE CB.HNDL, %IDC_BTN_RMA
    ELSE
        CONTROL DISABLE CB.HNDL, %IDC_BTN_PVW
        CONTROL DISABLE CB.HNDL, %IDC_BTN_XT1
        CONTROL DISABLE CB.HNDL, %IDC_BTN_XTA
        CONTROL DISABLE CB.HNDL, %IDC_BTN_RM1
        CONTROL DISABLE CB.HNDL, %IDC_BTN_RMA
    END IF
    i = MAX(0,UBOUND(xd))
    CONTROL SET TEXT CB.HNDL, %IDC_LBL_NFO, FORMAT$(i) & " chunk" & IIF$(i>1,"s","") & " of data detected:"
    DIALOG REDRAW CB.HNDL
END MACRO
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
SUB ExtractOne_xd (BYVAL hDlg AS LONG, BYVAL xdId AS LONG)
    LOCAL dat   AS STRING
    LOCAL typ   AS STRING
    LOCAL tgt   AS STRING

    typ = LCASE$(xd(xdID).desc)

    DISPLAY SAVEFILE hDlg, -100, 0, "Save As", _
        $NUL, CHR$("All files (*.*)", 0, "*.*", 0), LEFT$(myExe,-3)+"xdata."+typ, _
        "", %OFN_PATHMUSTEXIST OR %OFN_OVERWRITEPROMPT TO tgt
    IF tgt = "" THEN EXIT SUB

    dat   = GetExeData(myExe, xd(xdID))
    SetFile dat, tgt
    MessageBox hDlg, "ExeData successfully saved as:"+$CR+tgt, EXE.NAME$, %MB_ICONINFORMATION
END SUB
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
SUB ExtractAll_xd (BYVAL hDlg AS LONG)
    LOCAL dat   AS STRING
    LOCAL typ   AS STRING
    LOCAL tgt   AS STRING
    LOCAL i     AS LONG
    LOCAL res   AS STRING

    FOR i = UBOUND(xd) TO LBOUND(xd) STEP -1
        typ = LCASE$(xd(i).desc)
        tgt = LEFT$(myExe,-3)+"xdata."+typ
        dat   = GetExeData(myExe, xd(i))
        SetFile dat, tgt
        res += "- " + MID$(tgt,INSTR(-1,tgt,"\")+1) + $CR
    NEXT

    MessageBox hDlg, "ExeData successfully saved as:"+$CR+res _
        +"in folder "+$DQ+LEFT$(myExe,INSTR(-1,tgt,"\")-1)+$DQ, _
        EXE.NAME$, %MB_ICONINFORMATION
END SUB
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
SUB Preview_xd (BYVAL hParent AS LONG, BYVAL xdID AS LONG)
    LOCAL hD    AS LONG
    LOCAL dat   AS STRING
    LOCAL isBin AS LONG
    LOCAL hDib  AS DWORD
    LOCAL hFont  AS DWORD
    LOCAL w, h  AS LONG

    dat   = GetExeData(myExe, xd(xdID))
    isBin = INSTR(dat, CHR$(0))

    DIALOG NEW PIXELS, hParent, "xdmgr - viewer", -120, -70, _
        640, 320, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR _
        %WS_CAPTION OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
        %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
        %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
        %WS_EX_LTRREADING, TO hD
    DIALOG SET ICON hD, "ICO1"

    IF ISTRUE isBin THEN    ' Picture.. or other?
        SetFile dat, EXE.PATH$ + "temp.img"
        GdipLoadImageFromFile UCODE$(EXE.PATH$ + "temp.img"), hDib
        IF ISTRUE hDib THEN
            CONTROL ADD GRAPHIC, hD, 1001, "", 2, 2, 636, 316, _
                %WS_VISIBLE OR %WS_CHILD OR %SS_SUNKEN
            GRAPHIC ATTACH hD, 1001
            GRAPHIC CLEAR %RGB_LIGHTGRAY
            GdipGetImageWidth  hDib, w
            GdipGetImageHeight hDib, h
            GdipDrawImageRect  hGdip(), hDib, 0, 0, w, h
            DIALOG SHOW MODAL hD
            GdipDisposeImage hDib
            KILL EXE.PATH$ + "temp.img"
            EXIT SUB
        END IF
        KILL EXE.PATH$ + "temp.img"
    END IF

    ' Text
    CONTROL ADD TEXTBOX, hD, 1001, "", 2, 2, 636, 316, _
        %ES_MULTILINE OR %WS_BORDER OR %ES_READONLY OR _
        %ES_WANTRETURN OR %WS_VSCROLL OR %ES_AUTOVSCROLL, _
        %WS_EX_CLIENTEDGE OR %WS_EX_LEFT
    CONTROL SET COLOR hD, 1001, %BLACK, %WHITE
    CONTROL POST hD, 1001, %EM_SETSEL, -1, 0
    FONT NEW "Courier New", 10 TO hFont
    CONTROL SET FONT hD, 1001, hFont
    IF ISFALSE isBin THEN
        CONTROL SET TEXT hD, 1001, dat
    ELSE
        dat = LEFT$(dat,2048)
        LOCAL s AS STRING
        FOR w = 1 TO LEN(dat)
            s += HEX$(ASC(dat,w),2)+$SPC
        NEXT
        s += $CRLF+"[...] (Truncated)"
        CONTROL SET TEXT hD, 1001, s
    END IF

    DIALOG SHOW MODAL hD
    FONT END hFont
END SUB
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
FUNCTION AskDescriptor (BYVAL hParent AS DWORD) AS STRING
' Return descriptor of data chunk on 3 bytes, different from any existing one
    LOCAL hD AS DWORD

    DIALOG NEW PIXELS, hParent, "xdmgr - add exedata", , _
        , 200, 80, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR _
        %WS_CAPTION OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
        %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
        %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
        %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hD
    DIALOG SET ICON      hD, "ICO1"

    CONTROL ADD LABEL,   hD, %IDC_LBL_DUM, _
        "Alphanumeric 3-character description:", 8, 6, 200-16, 16
    CONTROL ADD TEXTBOX, hD, %IDC_LBL_NFO, "", 70, 24, 60, 22, _
        %ES_UPPERCASE OR %WS_BORDER OR %WS_TABSTOP OR %ES_AUTOHSCROLL, _
        %WS_EX_CLIENTEDGE OR %WS_EX_LEFT
    CONTROL ADD BUTTON,  hD, %IDCANCEL, "Cancel", 8, 50, 60, 24
    CONTROL ADD BUTTON,  hD, %IDOK, "OK", 200-8-60, 50, 60, 24

    myNfo = ""
    DIALOG SHOW MODAL hD CALL AskDeskProc
    FUNCTION = myNfo

END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** CallBacks **
'------------------------------------------------------------------------------
CALLBACK FUNCTION AskDeskProc()
    LOCAL e AS STRING
    LOCAL i, found AS LONG
    IF CB.MSG = %WM_COMMAND THEN
        IF CB.CTL = %IDCANCEL THEN
            DIALOG END CB.HNDL
        ELSEIF CB.CTL = %IDOK THEN
            CONTROL GET TEXT CB.HNDL, %IDC_LBL_NFO TO e
            e = UCASE$(TRIM$(e))
            IF LEN(e) <> 3 THEN
                MessageBox CB.HNDL, "Invalid descriptor!"+$CR _
                    +"Please type only 3 characters among A-Z and 0-9.", "xdmgr - error", %MB_ICONERROR
                CONTROL SET TEXT CB.HNDL, %IDC_LBL_NFO, ""
                CONTROL SET FOCUS CB.HNDL, %IDC_LBL_NFO
                EXIT FUNCTION
            END IF
            FOR i = LBOUND(xd) TO UBOUND(xd)
                IF xd(i).desc = e THEN found = i : EXIT FOR
            NEXT
            IF ISTRUE found THEN
                MessageBox CB.HNDL, "This descriptor is already in use!"+$CR _
                    +"Please choose another one...", "xdmgr - error", %MB_ICONERROR
                CONTROL SET TEXT CB.HNDL, %IDC_LBL_NFO, ""
                CONTROL SET FOCUS CB.HNDL, %IDC_LBL_NFO
                EXIT FUNCTION
            END IF
            ' We're good to go!
            myNfo = e
            DIALOG END CB.HNDL
        END IF
    END IF
END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
CALLBACK FUNCTION MainProc()
    LOCAL i, j      AS LONG
    LOCAL res, desc AS STRING

    SELECT CASE AS LONG CB.MSG
        CASE %WM_INITDIALOG
            ' Initialization handler
            RefreshControls

        CASE %WM_COMMAND
            ' Process control notifications
            SELECT CASE AS LONG CB.CTL

                CASE %IDC_BTN_EXE       ' Open EXE ...
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        DISPLAY OPENFILE CB.HNDL, -50, -100, "Select Program", $NUL, _
                            CHR$("Windows Executable", 0, "*.exe", 0), $NUL, "*.EXE", _
                            %OFN_FILEMUSTEXIST TO myExe
                        IF myExe <> "" THEN
                            RefreshControls
                        END IF
                    END IF

                CASE %IDC_BTN_ADD       ' Add ExeData
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        DISPLAY OPENFILE CB.HNDL, -50, -100, "Select resource", $NUL, _
                            CHR$("All files (*.*)", 0, "*.*", 0), $NUL, $NUL, _
                            %OFN_FILEMUSTEXIST TO res
                        IF res <> "" THEN
                            desc = AskDescriptor(CB.HNDL)
                            IF desc <> "" THEN
                                res = AddExeData(myExe, desc, GetFile(res))
                                SetFile res, myExe
                                RefreshControls
                            END IF
                        END IF
                    END IF

                CASE %IDC_BTN_RM1       ' Remove One
                    IF MessageBox(CB.HNDL, "Are you sure?", "xdmgr - remove one", _
                        %MB_ICONQUESTION OR %MB_YESNO) = %IDYES THEN
                        LISTVIEW GET SELECT CB.HNDL, %IDC_LVW_LST TO i
                        res = GetFile(myExe)
                        IF i = UBOUND(xd) THEN j = LEN(res)+1 ELSE j = xd(i+1).address
                        res = LEFT$(res, xd(i).address - 1) + MID$(res, j)
                        SetFile res, myExe
                        RefreshControls
                    END IF

                CASE %IDC_BTN_RMA       ' Remove All
                    IF MessageBox(CB.HNDL, "Are you sure?", "xdmgr - remove all", _
                        %MB_ICONQUESTION OR %MB_YESNO) = %IDYES THEN
                        SetFile ClearExeData(myExe), myExe
                        RefreshControls
                    END IF

                CASE %IDC_BTN_PVW       ' Preview
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        LISTVIEW GET SELECT CB.HNDL, %IDC_LVW_LST TO i
                        Preview_xd CB.HNDL, i
                    END IF

                CASE %IDC_BTN_XT1       ' Extract One
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        LISTVIEW GET SELECT CB.HNDL, %IDC_LVW_LST TO i
                        ExtractOne_xd CB.HNDL, i
                    END IF

                CASE %IDC_BTN_XTA       ' Extract All
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        ExtractAll_xd CB.HNDL
                    END IF

            END SELECT
    END SELECT
END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** Dialogs **
'------------------------------------------------------------------------------
FUNCTION MainShow(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt,lStyle AS LONG
    LOCAL hDlg  AS DWORD

    DIALOG NEW PIXELS, hParent, $EXE+$SPC+$VER, , _
        , 400, 246, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR _
        %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_CLIPSIBLINGS OR _
        %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
        %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
        %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
    DIALOG SET ICON         hDlg, "ICO1"

    CONTROL ADD LABEL,      hDlg, %IDC_LBL_DUM, "Exe:", 8, 9, 40, 16
    CONTROL ADD LABEL,      hDlg, %IDC_LBL_EXE, "<none>", 48, 8, 312, 16, _
        %WS_CHILD OR %WS_VISIBLE OR %SS_LEFT OR %SS_SUNKEN OR %SS_PATHELLIPSIS, _
        %WS_EX_STATICEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_EXE, "...", 360, 7, 32, 18
    CONTROL ADD LABEL,      hDlg, %IDC_LBL_NFO, "0 chunk of data detected:", 8, 30, 272, 16

    CONTROL ADD LISTVIEW,   hDlg, %IDC_LVW_LST, "", 8, 48, 384, 132
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 1, "#", 24, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 2, "ID", 70, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 3, "Type", 60, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 4, "Size", 90, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 5, "Offset", 100, %SS_LEFT
    LISTVIEW GET STYLEXX    hDlg, %IDC_LVW_LST TO lStyle
    LISTVIEW SET STYLEXX    hDlg, %IDC_LVW_LST, lStyle OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES

    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_ADD, "Add ExeData", 129, 186, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING
    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_RM1, "Remove One", 220, 186, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING
    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_RMA, "Remove All", 312, 186, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING

    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_PVW, "Preview", 129, 216, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING
    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_XT1, "Extract One", 220, 216, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING
    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_XTA, "Extract All", 312, 216, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING

    DIALOG SHOW MODAL hDlg, CALL MainProc TO lRslt

    FUNCTION = lRslt
END FUNCTION
'------------------------------------------------------------------------------