1 Востаннє редагувалося Дмитро-Чебурашка (04.02.2015 18:06:47)

Тема: Допоможіть запустити бумеранг!

Доброго дня усім !! Хай щастить!
  Я другий день мучу бумеранг- декомпілятор такий. Загалом тепер лається так мов "Точка входа в процедуру ?x@QPoint@@QBEHXZ не найдена в библиотеке DLL QtCore4.dll. ".

До речі, він в мене по черзі, просив купу різних длл, мовляв знайти не можу і усе таке.
Я йому три години їх підвантажував. Тепер нарешті ось.

Дуже хочу з ним погратися !!!

2

Re: Допоможіть запустити бумеранг!

бумеранг вже давно як не розвивається, IDA pro використовуйте, версія 6.1 чи 6.5. А там жне далі Otions -> Demangles names - * Names, що б не читати такі страшні x@QPoint@@QBEHXZ.
чого саме бумеранг ?

Re: Допоможіть запустити бумеранг!

Тобто може хтось підкаже як налагодити. Або ж виложить сюди робочу вєрсію Бумеранга, бо я вже затрахавсь, прямо кажучі!  Заздалегідь дуже дякую!

Re: Допоможіть запустити бумеранг!

чого саме бумеранг ?   Та не знаю!Просто хотів спробувати, порівняти, я ж не знаю як він працює, перевірити його. цікаво просто!

Re: Допоможіть запустити бумеранг!

Дякую!! IDA в мене є.  Але опції я знаю дуже погано!

Re: Допоможіть запустити бумеранг!

Доброго часу доби! Друзі, хтось грав з декомпеляторами? Ось, бумеранг.
Я звичайно дико вибачаюся.. як йому на вхід правильно подати файл? Щось не те.

Re: Допоможіть запустити бумеранг!

Все вже
Тобто я його запустив.І використовую, щоправда він падає

Re: Допоможіть запустити бумеранг!

Так, падає. При цьому викликається відладчик Олька. Програма намагається узяти щось з нульової адреси. Я використовую Boomerang - GUI, тобто консольну версію.

Загалом ось

0049D467   8B13             MOV EDX,DWORD PTR DS:[EBX]   виникає виключення


0049D3E0   51               PUSH ECX
0049D3E1   53               PUSH EBX
0049D3E2   55               PUSH EBP
0049D3E3   56               PUSH ESI
0049D3E4   57               PUSH EDI
0049D3E5   8B7C24 18        MOV EDI,DWORD PTR SS:[ESP+18]     
0049D3E9   8BF1             MOV ESI,ECX                       
0049D3EB   8D4424 18        LEA EAX,DWORD PTR SS:[ESP+18]     
0049D3EF   50               PUSH EAX                          
0049D3F0   8D4C24 14        LEA ECX,DWORD PTR SS:[ESP+14]     
0049D3F4   8D6E 60          LEA EBP,DWORD PTR DS:[ESI+60]     
0049D3F7   51               PUSH ECX                          
0049D3F8   8BCD             MOV ECX,EBP                       
0049D3FA   897C24 20        MOV DWORD PTR SS:[ESP+20],EDI     
0049D3FE   E8 9DACFEFF      CALL boomeran.004880A0            
0049D403   8B00             MOV EAX,DWORD PTR DS:[EAX]        
0049D405   3B46 64          CMP EAX,DWORD PTR DS:[ESI+64]     
0049D408   75 04            JNZ SHORT boomeran.0049D40E       
0049D40A   33DB             XOR EBX,EBX                       
0049D40C   EB 18            JMP SHORT boomeran.0049D426
0049D40E   8B58 10          MOV EBX,DWORD PTR DS:[EAX+10]     
0049D411   85DB             TEST EBX,EBX                      
0049D413   74 11            JE SHORT boomeran.0049D426
0049D415   8B13             MOV EDX,DWORD PTR DS:[EBX]        
0049D417   8BCB             MOV ECX,EBX
0049D419   FF52 08          CALL DWORD PTR DS:[EDX+8]         
0049D41C   84C0             TEST AL,AL
0049D41E   75 24            JNZ SHORT boomeran.0049D444
0049D420   837B 48 01       CMP DWORD PTR DS:[EBX+48],1      
0049D424   7D 1E            JGE SHORT boomeran.0049D444      
0049D426   8B46 14          MOV EAX,DWORD PTR DS:[ESI+14]    
0049D429   3B78 18          CMP EDI,DWORD PTR DS:[EAX+18]    
0049D42C   72 7E            JB SHORT boomeran.0049D4AC
0049D42E   3B78 1C          CMP EDI,DWORD PTR DS:[EAX+1C]    
0049D431   73 79            JNB SHORT boomeran.0049D4AC
0049D433   8B4E 18          MOV ECX,DWORD PTR DS:[ESI+18]    
0049D436   57               PUSH EDI
0049D437   56               PUSH ESI                         
0049D438   E8 E333FAFF      CALL boomeran.00440820           
0049D43D   8BCE             MOV ECX,ESI
0049D43F   E8 6CE0FFFF      CALL boomeran.0049B4B0           
0049D444   85DB             TEST EBX,EBX                     
0049D446   75 1F            JNZ SHORT boomeran.0049D467      
0049D448   8D4424 18        LEA EAX,DWORD PTR SS:[ESP+18]
0049D44C   50               PUSH EAX
0049D44D   8D4C24 14        LEA ECX,DWORD PTR SS:[ESP+14]
0049D451   51               PUSH ECX
0049D452   8BCD             MOV ECX,EBP
0049D454   897C24 20        MOV DWORD PTR SS:[ESP+20],EDI
0049D458   E8 43ACFEFF      CALL boomeran.004880A0        
0049D45D   8B00             MOV EAX,DWORD PTR DS:[EAX]    
0049D45F   3B46 64          CMP EAX,DWORD PTR DS:[ESI+64] 
0049D462   74 03            JE SHORT boomeran.0049D467
0049D464   8B58 10          MOV EBX,DWORD PTR DS:[EAX+10]                                 
0049D467   8B13             MOV EDX,DWORD PTR DS:[EBX]    ; TUTA 00000000
0049D469   8BCB             MOV ECX,EBX
0049D46B   FF52 08          CALL DWORD PTR DS:[EDX+8]                           
0049D46E   84C0             TEST AL,AL                                          
0049D470   0F85 98000000    JNZ boomeran.0049D50E                               
0049D476   8B7E 08          MOV EDI,DWORD PTR DS:[ESI+8]                        
0049D479   8B4F 04          MOV ECX,DWORD PTR DS:[EDI+4]                        
0049D47C   83C6 04          ADD ESI,4
0049D47F   8D4424 18        LEA EAX,DWORD PTR SS:[ESP+18]
0049D483   50               PUSH EAX
0049D484   51               PUSH ECX
0049D485   57               PUSH EDI
0049D486   8BCE             MOV ECX,ESI
0049D488   895C24 24        MOV DWORD PTR SS:[ESP+24],EBX
0049D48C   E8 6F66F7FF      CALL boomeran.00413B00         
0049D491   6A 01            PUSH 1
0049D493   8BCE             MOV ECX,ESI
0049D495   8BD8             MOV EBX,EAX
0049D497   E8 849AFEFF      CALL boomeran.00486F20         
0049D49C   895F 04          MOV DWORD PTR DS:[EDI+4],EBX   
0049D49F   8B53 04          MOV EDX,DWORD PTR DS:[EBX+4]   
0049D4A2   5F               POP EDI
0049D4A3   5E               POP ESI
0049D4A4   5D               POP EBP
0049D4A5   891A             MOV DWORD PTR DS:[EDX],EBX
0049D4A7   5B               POP EBX
0049D4A8   59               POP ECX
0049D4A9   C2 0400          RETN 4                         ;                    
0049D4AC   A1 54814E00      MOV EAX,DWORD PTR DS:[<&MSVCP71.?cerr@st>
0049D4B1   8B35 58814E00    MOV ESI,DWORD PTR DS:[<&MSVCP71.??$?6U?$>; MSVCP71.??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
0049D4B7   68 04904E00      PUSH boomeran.004E9004
0049D4BC   57               PUSH EDI
0049D4BD   68 E0724F00      PUSH boomeran.004F72E0                   ; ASCII "attempt to decode entrypoint at address outside text area, addr="
0049D4C2   50               PUSH EAX
0049D4C3   FFD6             CALL ESI
0049D4C5   83C4 08          ADD ESP,8
0049D4C8   8BC8             MOV ECX,EAX
0049D4CA   FF15 48814E00    CALL DWORD PTR DS:[<&MSVCP71.??6?$basic_>; MSVCP71.??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@K@Z
0049D4D0   50               PUSH EAX
0049D4D1   FFD6             CALL ESI
0049D4D3   83C4 08          ADD ESP,8
0049D4D6   E8 954AF6FF      CALL boomeran.00401F70
0049D4DB   8A48 4C          MOV CL,BYTE PTR DS:[EAX+4C]
0049D4DE   84C9             TEST CL,CL
0049D4E0   74 2C            JE SHORT boomeran.0049D50E
0049D4E2   E8 894AF6FF      CALL boomeran.00401F70
0049D4E7   8BC8             MOV ECX,EAX
0049D4E9   E8 92FFF7FF      CALL boomeran.0041D480
0049D4EE   8B10             MOV EDX,DWORD PTR DS:[EAX]
0049D4F0   68 E0724F00      PUSH boomeran.004F72E0                   ; ASCII "attempt to decode entrypoint at address outside text area, addr="
0049D4F5   8BC8             MOV ECX,EAX
0049D4F7   FF52 30          CALL DWORD PTR DS:[EDX+30]
0049D4FA   8B10             MOV EDX,DWORD PTR DS:[EAX]
0049D4FC   57               PUSH EDI
0049D4FD   8BC8             MOV ECX,EAX
0049D4FF   FF52 04          CALL DWORD PTR DS:[EDX+4]
0049D502   8B10             MOV EDX,DWORD PTR DS:[EAX]
0049D504   68 04904E00      PUSH boomeran.004E9004
0049D509   8BC8             MOV ECX,EAX
0049D50B   FF52 30          CALL DWORD PTR DS:[EDX+30]
0049D50E   5F               POP EDI
0049D50F   5E               POP ESI
0049D510   5D               POP EBP
0049D511   5B               POP EBX
0049D512   59               POP ECX
0049D513   C2 0400          RETN 4
0049D516   CC               INT3

9 Востаннє редагувалося Дмитро-Чебурашка (23.02.2015 14:34:30)

Re: Допоможіть запустити бумеранг!

Бумеранг з відкритим икодом. Шукав яндексом такий же текст. Що те знайшлося, тільки я нормальної відповідності не бачу, тобто тє що я бачу в OlliDbg як би не є тєщо в цих кодах, як я не вдивляюся.

     return NULL;
01231 #endif
01232 }
01233 
01234 void Prog::decodeEntryPoint(ADDRESS a) { 
01235     Proc* p = (UserProc*)findProc(a);
01236     if (p == NULL || (!p->isLib() && !((UserProc*)p)->isDecoded())) {
01237         if (a < pBF->getLimitTextLow() || a >= pBF->getLimitTextHigh()) {
01238             std::cerr << "attempt to decode entrypoint at address outside text area, addr=" << a << "\n";
01239             if (VERBOSE)
01240                 LOG << "attempt to decode entrypoint at address outside text area, addr=" << a << "\n";
01241             return;
01242         }
01243         pFE->decode(this, a);
01244         finishDecode();
01245     }
01246     if (p == NULL)
01247         p = findProc(a);
01248     assert(p);
01249     if (!p->isLib())                // -sf procs marked as __nodecode are treated as library procs (?)
01250         entryProcs.push_back((UserProc*)p);

посилання на  цей код бумеранга
  http://boomerang.sourceforge.net/doxy/p … ource.html

Re: Допоможіть запустити бумеранг!

Не зміркую з чого почати. Взагалі багато різних файлів!! Я б може спробував сам зібрати собі консольну версію,

не зміркую, які первинники узяти.

11

Re: Допоможіть запустити бумеранг!

Починайте з власного 'Hello, World!'

Re: Допоможіть запустити бумеранг!

Ну так при розборі 'Hello, World і падає!

Re: Допоможіть запустити бумеранг!

Я б може скомпілював сам собі консольну версію, то може був би цікавий досвід.

Re: Допоможіть запустити бумеранг!

Боровся з декомпилятором як міг. Пробував його відкрити сам з себе.


Падає. Склав такого роду батник.


Падає. Ледве блимає і вистрибує відладчик. Може його треба доповнити ключами або іншими витребеньками.



rem start system\game.exe startgame table_bin

start /d"D:\Double\boomerang-win32-alpha-0.3.1" boomerang.exe boomerang-gui.exe

Пробував відкрити його з іншого декомпилятора.
Інший лається


Боровся з декомпилятором як міг. Пробував його відкрити сам з себе.


Падає. Склав такого роду батник.


Падає. Ледве блимає і вистрибує відладчик. Може його треба доповнити ключами або іншими витребеньками.

Пробував відкрити його з іншого декомпилятора.
Інший лається
Довжина початкового масиву недостатня. Перевірте значення srcIndex і довжини, а також нижні межі масиву.

Інший - WindowsDecompiler.exe.

Довжина початкового масиву недостатня. Перевірте значення srcIndex і довжини, а також нижні межі масиву.

Інший - WindowsDecompiler.exe.

15 Востаннє редагувалося Дмитро-Чебурашка (04.03.2015 18:32:23)

Re: Допоможіть запустити бумеранг!

Я скачав якісь файли, гадаю що ті що потрібно, і будую поект сам. Прикиньте! Microsoft Visual Studio 10.0 лається мені так российською мовою: Ошибка    9    error C2365: log: переопределение; предыдущим определением было "функция"    d:\skladannja3\libid\boomerang\windows.cpp    268    1    boomerang


Офигеть!! Там майже вагон файлів, величезниший обїєм, але однак "функция" росийською мовою ніде в кодах бути не може  однозначна!!

Що ж це таке? Хиба такє бува?!! Щож за помилка така?

Re: Допоможіть запустити бумеранг!

// windows.cpp : Defines the entry point for the application.
//

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <sstream>
#include "resource.h"
#undef NO_ADDRESS
#include "prog.h"
#include "proc.h"
#include "signature.h"
#include "statement.h"
#include "boomerang.h"
#include "log.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
HWND hTopWnd, hStatusBar, hTreeView, hLogView;
HBRUSH yellowBrush, buttonBrush;
HFONT hTabBarFont, hMemoryDumpFont;
static Prog *prog = NULL;
std::map<Proc*,HTREEITEM> procItems;
HTREEITEM treeDragging = NULL;
HMENU clusterMenu = NULL, procMenu = NULL, callersMenu = NULL, callsMenu = NULL;
bool someUnknown = false;

enum { V_CODE, V_RTL, V_MIXED } view_as = V_RTL;

struct my_tab
{
    const char *name;
    HWND edit;
    Cluster *cluster;
};
std::map<std::string, my_tab> tabWithName;
char *selectedTab = NULL;
RECT tabBarRect;
int iCluster, iProc, iDProc, iLProc, iULProc;


class MyLParam
{
public:
    Proc *p;
    Cluster *c;
    int isCluster;
    MyLParam(Cluster *c) : c(c)
    {
        isCluster = 1;
    }
    MyLParam(Proc *p) : p(p)
    {
        isCluster = 0;
    }
};

HANDLE hDecompilerThread = NULL;

void updateDecompilerMenu()
{
    if (hDecompilerThread == NULL)
        {
            EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_SUSPEND, MF_GRAYED);
            EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_RESUME, MF_GRAYED);
            EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_TERMINATE, MF_GRAYED);
            EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_START, MF_ENABLED);
            SendMessage(hStatusBar, SB_SETICON, 2, NULL);
        }
    else
        {
            EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_SUSPEND, MF_ENABLED);
            EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_TERMINATE, MF_ENABLED);
            EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_START, MF_GRAYED);
            SendMessage(hStatusBar, SB_SETICON, 2, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)));
        }
}

void updateAllTabs()
{
    for (std::map<std::string, my_tab>::iterator it = tabWithName.begin(); it != tabWithName.end(); )
        if ((*it).first != (*it).second.cluster->getName())
            {
                struct my_tab t = (*it).second;
                if ((*it).first == selectedTab)
                    selectedTab = strdup(t.cluster->getName());
                tabWithName.erase(it);
                t.name = strdup(t.cluster->getName());
                tabWithName[t.cluster->getName()] = t;
                it = tabWithName.begin();
            }
        else
            it++;
    InvalidateRect(hTopWnd, &tabBarRect, TRUE);
}

void updateTreeView()
{
    HTREEITEM h = TreeView_GetRoot(hTreeView);
    while (h)
        {
            TVITEM i;
            i.hItem = h;
            i.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
            char buf[1024];
            i.pszText = buf;
            i.cchTextMax = sizeof(buf);
            TreeView_GetItem(hTreeView, &i);
            if (strcmp(i.pszText, ((MyLParam*)i.lParam)->c->getName()))
                {
                    i.mask = TVIF_TEXT;
                    strcpy(buf, ((MyLParam*)i.lParam)->c->getName());
                    TreeView_SetItem(hTreeView, &i);
                }
            h = TreeView_GetNextSibling(hTreeView, h);
        }
    for (std::map<Proc*,HTREEITEM>::iterator it = procItems.begin(); it != procItems.end(); it++)
        {
            TVITEM i;
            i.hItem = (*it).second;
            i.mask = TVIF_TEXT;
            i.pszText = strdup((*it).first->getName());
            TreeView_SetItem(hTreeView, &i);
        }
}

void suspendDecompiler()
{
    EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_SUSPEND, MF_GRAYED);
    EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_RESUME, MF_ENABLED);
    SendMessage(hStatusBar, SB_SETICON, 2, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_SUSPEND)));
    SuspendThread(hDecompilerThread);
}

void resumeDecompiler()
{
    EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_SUSPEND, MF_ENABLED);
    EnableMenuItem(GetMenu(hTopWnd), ID_DECOMPILER_RESUME, MF_GRAYED);
    SendMessage(hStatusBar, SB_SETICON, 2, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)));
    ResumeThread(hDecompilerThread);
}

void generateCodeForCluster(Cluster *c);
void generateCodeForUserProc(UserProc *p);

void updateCodeView()
{
    HTREEITEM h = TreeView_GetSelection(hTreeView);
    if (h == NULL)
        return;
    TVITEM i;
    i.hItem = h;
    i.mask = TVIF_PARAM;
    TreeView_GetItem(hTreeView, &i);
    MyLParam *lp = (MyLParam*)i.lParam;
    if (lp->isCluster)
        {
            generateCodeForCluster(lp->c);
            if (lp->c->getNumChildren() == 0)
                {
                    PROGMAP::const_iterator it;
                    bool found = false;
                    for (Proc *proc = prog->getFirstProc(it); proc; proc = prog->getNextProc(it))
                        if (proc->getCluster() == lp->c)
                            {
                                found = true;
                                break;
                            }
                    if (!found)
                        {
                            EnableMenuItem(GetMenu(hTopWnd), ID_VIEW_DELETECLUSTER, MF_ENABLED);
                            if (clusterMenu)
                                EnableMenuItem(clusterMenu, ID_VIEW_DELETECLUSTER, MF_ENABLED);
                        }
                }
        }
    else
        {
            UserProc *u = dynamic_cast<UserProc*>(lp->p);
            if (u)
                generateCodeForUserProc(u);
        }
}

void saveUndoPoint()
{
    return;  // Possibly Mike broke it
    if (prog)
        {
            prog->takeMemo();
            if (prog->canRestore())
                EnableMenuItem(GetMenu(hTopWnd), ID_EDIT_UNDO, MF_ENABLED);
            else
                EnableMenuItem(GetMenu(hTopWnd), ID_EDIT_UNDO, MF_GRAYED);
            EnableMenuItem(GetMenu(hTopWnd), ID_EDIT_REDO, MF_GRAYED);
        }
}

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    StatusBar(HWND, UINT, WPARAM, LPARAM);
WNDPROC oldStatusBarProc = NULL;
LRESULT CALLBACK    TreeView(HWND, UINT, WPARAM, LPARAM);
WNDPROC oldTreeViewProc = NULL;
LRESULT CALLBACK    TabEdit(HWND, UINT, WPARAM, LPARAM);
WNDPROC oldTabEditProc = NULL;
LRESULT CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    NewProject(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    DebugOptions(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    DecodeOptions(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    DecompileOptions(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    Decoding(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    ProcProperties(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    SymbolTable(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    MemoryDump(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR       lpCmdLine,
                     int       nCmdShow)
{
    // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    char filename[MAX_PATH];
    GetCurrentDirectory(sizeof(filename), filename);
    strcat(filename, "\\");
    Boomerang::get()->setProgPath(filename);
    strcat(filename, "output");
    Boomerang::get()->setOutputPath(filename);

    InitCommonControls();

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_BOOMERANG, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }

    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_BOOMERANG);

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
        }

    return (int) msg.wParam;
}

#define LOG_SIZE 1024*92
char log[LOG_SIZE], *plog = log;

class WindowLogger : public Log
{
public:
    WindowLogger() : Log() { }
    virtual Log &operator<<(const char *pstr)
    {
        if (pstr == NULL)
            return *this;
        char *str = new char[strlen(pstr) + 1024], *p2 = str;
        for (const char *p1 = pstr; *p1; p1++)
            if (*p1 != '\n')
                *p2++ = *p1;
            else
                {
                    *p2++ = '\r';
                    *p2++ = '\n';
                }
        *p2 = 0;

        if (strlen(str) + plog - log < LOG_SIZE)
            {
                strcpy(plog, str);
                plog += strlen(str);
            }
        else
            {
                memmove(log, log + 1024, LOG_SIZE - 1024);
                plog -= 1024;
                if (strlen(str) + plog - log < LOG_SIZE)
                    {
                        strcpy(plog, str);
                        plog += strlen(str);
                    }
            }
        SetWindowText(hLogView, log);
        SendMessage(hLogView, WM_VSCROLL, SB_BOTTOM, 0);
        return *this;
    }
    virtual ~WindowLogger() {};
};

void OpenProject();
void SaveProject();
void CloseProject();

//
//    FUNCTION: MyRegisterClass()
//
//    PURPOSE: Registers the window class.
//
//    COMMENTS:
//
//      This function and its usage are only necessary if you want this code
//      to be compatible with Win32 systems prior to the 'RegisterClassEx'
//      function that was added to Windows 95. It is important to call this function
//      so that the application will get 'well formed' small icons associated
//      with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, (LPCTSTR)IDI_BOOMERANG);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = (LPCTSTR)IDC_BOOMERANG;
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_BOOMERANG);

    return RegisterClassEx(&wcex);
}

void addNewTab(Cluster *cluster);

HFONT MyCreateFont( void )
{
    CHOOSEFONT cf;
    LOGFONT lf;
    HFONT hfont;

    // Initialize members of the CHOOSEFONT structure.

    cf.lStructSize = sizeof(CHOOSEFONT);
    cf.hwndOwner = (HWND)NULL;
    cf.hDC = (HDC)NULL;
    cf.lpLogFont = &lf;
    cf.iPointSize = 0;
    cf.Flags = CF_SCREENFONTS;
    cf.rgbColors = RGB(0,0,0);
    cf.lCustData = 0L;
    cf.lpfnHook = (LPCFHOOKPROC)NULL;
    cf.lpTemplateName = (LPSTR)NULL;
    cf.hInstance = (HINSTANCE) NULL;
    cf.lpszStyle = (LPSTR)NULL;
    cf.nFontType = SCREEN_FONTTYPE;
    cf.nSizeMin = 0;
    cf.nSizeMax = 0;

    // Display the CHOOSEFONT common-dialog box.

    ChooseFont(&cf);

    // Create a logical font based on the user's
    // selection and return a handle identifying
    // that font.

    OpenClipboard(hTopWnd);
    EmptyClipboard();
    HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, 8192);
    char *buf = (char*)GlobalLock(hglbCopy);
    buf[0] = 0;
    for (unsigned i = 0; i < sizeof(lf); i++)
        sprintf(buf + strlen(buf), "0x%02X, ", ((unsigned char*)&lf)[i]);
    GlobalUnlock(hglbCopy);
    SetClipboardData(CF_TEXT, hglbCopy);
    CloseClipboard();
    hfont = CreateFontIndirect(cf.lpLogFont);

    return (hfont);
}

void setupDecompiler();

//
//     FUNCTION: InitInstance(HANDLE, 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)
{
    HWND hWnd;

    hInst = hInstance; // Store instance handle in our global variable

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

    if (!hWnd)
        {
            return FALSE;
        }

    hTopWnd = hWnd;

    hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hWnd, NULL, hInstance, NULL);

    oldStatusBarProc = (WNDPROC)SetWindowLongPtr (hStatusBar, GWLP_WNDPROC, (LONG_PTR)StatusBar);
    SetTimer(hStatusBar, 1, 1000, NULL);

    RECT r, rsb;
    GetClientRect(hWnd, &r);
    GetClientRect(hStatusBar, &rsb);

    int parts[] = { rsb.right / 2, rsb.right / 2 + 200, rsb.right / 2 + 232, -1 };
    SendMessage(hStatusBar, SB_SETPARTS, 4, (LPARAM) parts);

    hTreeView = CreateWindowEx(0, WC_TREEVIEW, NULL, WS_CHILD | WS_DLGFRAME | WS_VISIBLE | TVS_EDITLABELS | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS, r.right - 200, 0, 200, r.bottom - rsb.bottom, hWnd, NULL, hInstance, NULL);

    oldTreeViewProc = (WNDPROC)SetWindowLongPtr (hTreeView, GWLP_WNDPROC, (LONG_PTR)TreeView);
    HIMAGELIST himglist = ImageList_Create(16, 16, ILC_COLOR4, 5, 1);
    iCluster = ImageList_AddIcon(himglist, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CLUSTER)));
    iProc = ImageList_AddIcon(himglist, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROC)));
    iDProc = ImageList_AddIcon(himglist, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DPROC)));
    iLProc = ImageList_AddIcon(himglist, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LPROC)));
    iULProc = ImageList_AddIcon(himglist, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ULPROC)));
    TreeView_SetImageList(hTreeView, himglist, TVSIL_NORMAL);

    yellowBrush = CreateSolidBrush(RGB(255, 255, 200));
    buttonBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));

    unsigned char lf_bits[] = { 0xF3, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x22, 0x41, 0x72, 0x69, 0x61, 0x6C, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, };
    hTabBarFont = CreateFontIndirect((LOGFONT*)lf_bits);
    LOGFONT mmfont;
    memcpy(&mmfont, lf_bits, sizeof(mmfont));
    strcpy(mmfont.lfFaceName, "OEM fixed font");
    mmfont.lfPitchAndFamily &= ~3;
    mmfont.lfPitchAndFamily |= FIXED_PITCH;
    hMemoryDumpFont = CreateFontIndirect(&mmfont);

    hLogView = CreateWindowEx(0, WC_EDIT, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL    | WS_DLGFRAME
                              | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
                              0, r.bottom - rsb.bottom - 200, r.right - 200, 200, hTopWnd, NULL, hInst, NULL);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    setupDecompiler();
    return TRUE;
}

void selectTab(const char *name)
{
    if (selectedTab)
        {
            if (!strcmp(selectedTab, name))
                return;
            ShowWindowAsync(tabWithName[selectedTab].edit, SW_HIDE);
        }
    selectedTab = strdup(name);
    ShowWindowAsync(tabWithName[selectedTab].edit, SW_SHOW);
    InvalidateRect(hTopWnd, &tabBarRect, TRUE);
}

void updateTab(const char *name)
{
    Cluster *c = tabWithName[name].cluster;
    const char *path = c->getOutPath((view_as == V_CODE || view_as == V_MIXED) ? "c" : "rtl");
    std::ifstream in(path, std::ios_base::binary);
    if (in.is_open())
        {
            in.seekg(0, std::ios_base::end);
            int n = in.tellg();
            in.seekg(0, std::ios_base::beg);
            char *buf = new char[n];
            in.read(buf, n);
            in.close();
            SendMessage(tabWithName[c->getName()].edit, WM_SETTEXT, 0, (LPARAM)buf);
        }
}

void generateCodeForClusterThread(Cluster *c)
{
    char buf[1024];
    sprintf(buf, "Generating code for cluster %s", c->getName());
    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)buf);
    if (view_as == V_CODE)
        prog->generateCode(c);
    else if (view_as == V_RTL)
        prog->generateRTL(c);
    else if (view_as == V_MIXED)
        prog->generateCode(c, NULL, true);
    selectTab(c->getName());
    updateTab(c->getName());
    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"Done");
    ExitThread(0);
}

void generateCodeForCluster(Cluster *c)
{
    addNewTab(c);
    DWORD id;
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)generateCodeForClusterThread, (LPVOID)c, 0, &id);
}

void generateCodeForAllThread(void *n)
{
    char buf[1024];
    sprintf(buf, "Generating code...");
    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)buf);
    prog->generateCode();
    if (selectedTab)
        updateTab(selectedTab);
    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"Done");
    ExitThread(0);
}

void generateCodeForAll()
{
    DWORD id;
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)generateCodeForAllThread, 0, 0, &id);
}

void generateCodeForUserProcThread(UserProc *proc)
{
    if (prog == NULL)
        return;
    char buf[1024];
    sprintf(buf, "Generating code for proc %s", proc->getName());
    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)buf);
    if (view_as == V_CODE)
        prog->generateCode(proc->getCluster(), proc);
    else if (view_as == V_RTL)
        prog->generateRTL(proc->getCluster(), proc);
    else if (view_as == V_MIXED)
        prog->generateCode(proc->getCluster(), proc, true);
    selectTab(proc->getCluster()->getName());
    updateTab(proc->getCluster()->getName());
    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"Done");
    ExitThread(0);
}

void generateCodeForUserProc(UserProc *proc)
{
    addNewTab(proc->getCluster());
    DWORD id;
    HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)generateCodeForUserProcThread, (LPVOID)proc, 0, &id);
}

void closeTab(const char *name)
{
    for (std::map<std::string, struct my_tab>::iterator it = tabWithName.begin(); it != tabWithName.end(); it++)
        if ((*it).first == name)
            {
                DestroyWindow((*it).second.edit);
                if (!strcmp(selectedTab, name))
                    selectedTab = NULL;
                tabWithName.erase(it);
                break;
            }
    InvalidateRect(hTopWnd, &tabBarRect, TRUE);
}

void closeAllTabs()
{
    for (std::map<std::string, struct my_tab>::iterator it = tabWithName.begin(); it != tabWithName.end(); it++)
        {
            DestroyWindow((*it).second.edit);
        }
    tabWithName.clear();
    selectedTab = NULL;
    InvalidateRect(hTopWnd, &tabBarRect, TRUE);
}

void addNewTab(Cluster *cluster)
{
    const char *name = cluster->getName();
    if (tabWithName.find(name) != tabWithName.end())
        return;

    struct my_tab tab;
    tab.name = strdup(name);
    tab.cluster = cluster;
    RECT r, rsb;
    GetClientRect(hTopWnd, &r);
    GetClientRect(hStatusBar, &rsb);

    tab.edit = CreateWindowEx(0, WC_EDIT, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL    | WS_DLGFRAME
                              | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
                              0, tabBarRect.bottom, r.right - 200, r.bottom - rsb.bottom - tabBarRect.bottom - 200, hTopWnd, NULL, hInst, NULL);
    oldTabEditProc = (WNDPROC)SetWindowLongPtr (tab.edit, GWLP_WNDPROC, (LONG_PTR)TabEdit);
    tabWithName[name] = tab;
    if (selectedTab == NULL)
        selectTab(name);
    InvalidateRect(hTopWnd, &tabBarRect, TRUE);
}

void drawTabBar(HDC hdc)
{
    RECT r = tabBarRect;
    FillRect(hdc, &r, yellowBrush);
    r.left += 4;
    for (std::map<std::string, struct my_tab>::iterator it = tabWithName.begin(); it != tabWithName.end(); it++)
        {
            const char *name = (*it).second.name;
            DrawText(hdc, name, -1, &r, DT_CALCRECT | DT_LEFT | DT_TOP);
            r.bottom++;
            r.right += 4;
            if (selectedTab && !strcmp(name, selectedTab))
                {
                    r.left -= 4;
                    r.top++;
                    FillRect(hdc, &r, buttonBrush);
                    r.left += 4;
                    r.top--;
                    SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
                    DrawText(hdc, name, -1, &r, DT_LEFT | DT_TOP);
                    MoveToEx(hdc, r.right, r.top + 1, NULL);
                    LineTo(hdc, r.right, r.bottom - 1);
                }
            else
                {
                    SetBkColor(hdc, RGB(255, 255, 200));
                    DrawText(hdc, name, -1, &r, DT_LEFT | DT_TOP);
                    MoveToEx(hdc, r.right, r.top + 2, NULL);
                    LineTo(hdc, r.right, r.bottom - 3);
                }
            r.left += r.right - r.left + 4;
            r.right = r.left + 10;
        }
}

void handleTabBarPress(int xPos)
{
    HDC hdc = GetDC(hTopWnd);
    RECT r = tabBarRect;
    r.left += 4;

    for (std::map<std::string, struct my_tab>::iterator it = tabWithName.begin(); it != tabWithName.end(); it++)
        {
            const char *name = (*it).second.name;
            DrawText(hdc, name, -1, &r, DT_CALCRECT | DT_LEFT | DT_TOP);
            r.bottom++;
            r.right += 4;
            if (xPos >= r.left && xPos < r.right)
                {
                    selectTab(name);
                    break;
                }
            r.left += r.right - r.left + 4;
            r.right = r.left + 10;
        }
    ReleaseDC(hTopWnd, hdc);
}

Proc *selectedProc()
{
    HTREEITEM h = TreeView_GetSelection(hTreeView);
    TVITEM it;
    it.hItem = h;
    it.mask = TVIF_HANDLE;
    if (!TreeView_GetItem(hTreeView, &it))
        return NULL;
    MyLParam *lp = (MyLParam*)it.lParam;
    if (lp->isCluster)
        return NULL;
    return lp->p;
}

LRESULT CALLBACK StatusBar(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
        {
        case WM_COMMAND:
            break;
        case WM_LBUTTONUP:
        {
            int parts[5];
            SendMessage(hWnd, SB_GETPARTS, 5, (LPARAM)parts);
            if (LOWORD(lParam) > parts[1] && LOWORD(lParam) < parts[2])
                {
                    if ((HICON)SendMessage(hWnd, SB_GETICON, 2, 0) == LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)) ||
                            (HICON)SendMessage(hWnd, SB_GETICON, 2, 0) == LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME1)))
                        {
                            SendMessage(hWnd, SB_SETICON, 2, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_SUSPEND)));
                            suspendDecompiler();
                        }
                    else
                        {
                            SendMessage(hWnd, SB_SETICON, 2, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)));
                            resumeDecompiler();
                        }
                }
        }
        break;
        case WM_TIMER:
            if ((HICON)SendMessage(hWnd, SB_GETICON, 2, 0) == LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)))
                {
                    SendMessage(hWnd, SB_SETICON, 2, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME1)));
                }
            else if ((HICON)SendMessage(hWnd, SB_GETICON, 2, 0) == LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME1)))
                {
                    SendMessage(hWnd, SB_SETICON, 2, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)));
                }
            break;
        case WM_RBUTTONDOWN:
            break;
        case WM_MOUSEMOVE:
            break;
        }
    return CallWindowProc(oldStatusBarProc, hWnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK TreeView(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    RECT r;
    TVHITTESTINFO tvhti;
    TVITEM tvi;
    MyLParam *lp;

    switch (uMsg)
        {
        case WM_LBUTTONUP:
            if (treeDragging)
                {
                    TreeView_SetInsertMark(hTreeView, NULL, TRUE);
                    TVHITTESTINFO tvh;
                    tvh.pt.x = LOWORD(lParam);
                    tvh.pt.y = HIWORD(lParam);
                    TreeView_HitTest(hTreeView, &tvh);
                    if (tvh.hItem && tvh.hItem != treeDragging)
                        {
                            TVINSERTSTRUCT tvi;
                            tvi.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
                            tvi.item.hItem = treeDragging;
                            char buf[1024];
                            tvi.item.pszText = buf;
                            tvi.item.cchTextMax = sizeof(buf);
                            TreeView_GetItem(hTreeView, &tvi.item);
                            TVITEM tv;
                            tv.mask = TVIF_PARAM;
                            tv.hItem = tvh.hItem;
                            TreeView_GetItem(hTreeView, &tv);
                            MyLParam *tp = (MyLParam*)tv.lParam;
                            if (tp->isCluster)
                                {
                                    tvi.hParent = tvh.hItem;
                                    tvi.hInsertAfter = TVI_FIRST;
                                }
                            else
                                {
                                    tvi.hParent = TreeView_GetParent(hTreeView, tvh.hItem);
                                    tvi.hInsertAfter = tvh.hItem;
                                }
                            MyLParam *p = (MyLParam*)tvi.item.lParam;
                            if (!p->isCluster || tp->isCluster)
                                {
                                    HTREEITEM h = TreeView_InsertItem(hTreeView, &tvi);
                                    TreeView_DeleteItem(hTreeView, treeDragging);
                                    if (p->isCluster)
                                        {
                                            p->c->getParent()->removeChild(p->c);
                                            tp->c->addChild(p->c);
                                        }
                                    else
                                        {
                                            procItems[p->p] = h;
                                            if (tp->isCluster)
                                                {
                                                    p->p->setCluster(tp->c);
                                                }
                                            else
                                                {
                                                    p->p->setCluster(tp->p->getCluster());
                                                }
                                        }
                                }
                        }
                    treeDragging = NULL;
                }
            break;
        case WM_RBUTTONDOWN:
            tvhti.pt.x = LOWORD(lParam);
            tvhti.pt.y = HIWORD(lParam);
            TreeView_HitTest(hTreeView, &tvhti);
            tvi.hItem = tvhti.hItem;
            tvi.mask = TVIF_PARAM;
            TreeView_GetItem(hTreeView, &tvi);
            GetWindowRect(hWnd, &r);
            lp = (MyLParam*)tvi.lParam;
            if (lp->isCluster)
                {
                    if (clusterMenu == NULL)
                        {
                            clusterMenu = CreatePopupMenu();
                            AppendMenu(clusterMenu, MF_STRING, ID_VIEW_RENAME, "&Rename");
                            AppendMenu(clusterMenu, MF_STRING, ID_VIEW_NEWCLUSTER, "&New Cluster");
                            AppendMenu(clusterMenu, MF_STRING | MF_GRAYED, ID_VIEW_DELETECLUSTER, "&Delete Cluster");
                        }
                    TreeView_SelectItem(hTreeView, tvhti.hItem);
                    TrackPopupMenu(clusterMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, r.left + LOWORD(lParam), r.top + HIWORD(lParam), 0, hTopWnd, NULL);
                }
            else
                {
                    UserProc *u = dynamic_cast<UserProc*>(lp->p);
                    if (procMenu != NULL)
                        {
                            DestroyMenu(procMenu);
                        }
                    callersMenu = CreatePopupMenu();
                    callsMenu = CreatePopupMenu();
                    procMenu = CreatePopupMenu();
                    AppendMenu(procMenu, MF_STRING, ID_VIEW_RENAME, "&Rename");
                    AppendMenu(procMenu, MF_SEPARATOR, 0, 0);
                    AppendMenu(procMenu, MF_STRING | MF_POPUP, (UINT_PTR)callersMenu, "&Callers");
                    AppendMenu(procMenu, MF_STRING | MF_POPUP, (UINT_PTR)callsMenu, "C&alls");
                    AppendMenu(procMenu, MF_STRING, ID_VIEW_PROPERTIES, "&Properties");
                    while (DeleteMenu(callersMenu, 0, MF_BYPOSITION))
                        ;
                    std::set<CallStatement*> &callers = lp->p->getCallers();
                    int n = 33001;
                    for (std::set<CallStatement*>::iterator it = callers.begin(); it != callers.end(); it++, n++)
                        AppendMenu(callersMenu, MF_STRING, n, (*it)->getProc()->getName());
                    while (DeleteMenu(callsMenu, 0, MF_BYPOSITION))
                        ;
                    if (u)
                        {
                            std::list<Proc*> &calls = u->getCallees();
                            n = 34001;
                            for (std::list<Proc*>::iterator it = calls.begin(); it != calls.end(); it++, n++)
                                AppendMenu(callsMenu, MF_STRING, n, (*it)->getName());
                        }
                    TreeView_Select(hTreeView, tvhti.hItem, TVGN_CARET);
                    TrackPopupMenu(procMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, r.left + LOWORD(lParam), r.top + HIWORD(lParam), 0, hTopWnd, NULL);
                }
            break;
        case WM_MOUSEMOVE:
            if (treeDragging)
                {
                    TVHITTESTINFO tvh;
                    tvh.pt.x = LOWORD(lParam);
                    tvh.pt.y = HIWORD(lParam);
                    TreeView_HitTest(hTreeView, &tvh);
                    if (tvh.hItem)
                        TreeView_SetInsertMark(hTreeView, tvh.hItem, TRUE);
                    else
                        TreeView_SetInsertMark(hTreeView, NULL, TRUE);
                }
            break;
        default:
            return CallWindowProc(oldTreeViewProc, hWnd, uMsg, wParam, lParam);
        }
    return 0;
}

LRESULT CALLBACK TabEdit(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static Statement *stmt;
    static Exp *exp;

    //std::map<std::string, my_tab>::iterator it;
    //for (it = tabWithName.begin(); it != tabWithName.end(); it++)
    //    if ((*it).second.edit == hWnd)
    //        break;

    switch (uMsg)
        {
        case WM_COMMAND:
            switch(LOWORD(wParam))
                {
                case ID_STMT_PROPAGATE_TO:
                    stmt->propagateTo(-1);
                    stmt->getProc()->updateBlockVars();
                    updateCodeView();
                    break;
                }
            break;
        case WM_LBUTTONUP:
            break;
        case WM_RBUTTONDOWN:
        {
            DWORD d = SendMessage(hWnd, EM_CHARFROMPOS, 0, lParam);
            int ch = LOWORD(d);
            int line = HIWORD(d);
            Proc *p = selectedProc();
            if (p == NULL)
                break;  // don't currently support right click in cluster view
            UserProc *u = dynamic_cast<UserProc*>(p);
            if (u == NULL)
                break;
            stmt = u->getStmtAtLex(ch, -1);
            if (stmt == NULL)
                break;
            exp = stmt->getExpAtLex(ch, -1);
            HMENU editMenu = CreatePopupMenu();
            AppendMenu(editMenu, MF_STRING, ID_STMT_PROPAGATE_TO, "&Propagate to this statement");
            RECT r;
            GetWindowRect(hWnd, &r);
            TrackPopupMenu(editMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, r.left + LOWORD(lParam), r.top + HIWORD(lParam), 0, hWnd, NULL);
            DestroyMenu(editMenu);
        }
        break;
        case WM_MOUSEMOVE:
            break;
        }
    return CallWindowProc(oldTabEditProc, hWnd, uMsg, wParam, lParam);
}

//
//    FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//    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)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    TEXTMETRIC tm;
    LPNMTREEVIEW pnmtv;
    LPNMTVDISPINFO ptvdi;

    switch (message)
        {
        case WM_SIZE:
        {
            RECT r;
            RECT rsb;
            GetClientRect(hTopWnd, &r);
            GetClientRect(hStatusBar, &rsb);
            SetWindowPos(hTreeView, 0, r.right - 200, 0, 200, r.bottom - rsb.bottom, SWP_NOZORDER);
            SetWindowPos(hStatusBar, 0, 0, r.bottom - rsb.bottom, r.right, rsb.bottom, SWP_NOZORDER);
            SetWindowPos(hLogView, 0, 0, r.bottom - rsb.bottom - 200, r.right - 200, 200, SWP_NOZORDER);
            for (std::map<std::string, my_tab>::iterator it = tabWithName.begin(); it != tabWithName.end(); it++)
                {
                    SetWindowPos((*it).second.edit, 0, 0, tabBarRect.bottom, r.right - 200, r.bottom - rsb.bottom - tabBarRect.bottom - 200, SWP_NOZORDER);
                }
        }
        break;
        case WM_COMMAND:
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            if (selectedTab && wmEvent == EN_CHANGE && (HWND)lParam == tabWithName[selectedTab].edit)
                {
                    updateTab(selectedTab);
                }
            if (wmId > 33000)
                {
                    char buf[1024];
                    MENUITEMINFO mi;
                    mi.cbSize = sizeof(mi);
                    mi.fMask = MIIM_STRING;
                    mi.cch = sizeof(buf);
                    mi.dwTypeData = buf;
                    if (GetMenuItemInfo(procMenu, wmId, FALSE, &mi))
                        {
                            Proc *p = prog->findProc(buf);
                            if (p && procItems.find(p) != procItems.end())
                                TreeView_SelectItem(hTreeView, procItems[p]);
                        }
                }
            // Parse the menu selections:
            switch (wmId)
                {
                case IDM_ABOUT:
                    DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                case ID_NEW_PROJECT:
                    if (DialogBox(hInst, (LPCTSTR)IDD_NEWPROJECT, hWnd, (DLGPROC)NewProject) == IDOK)
                        if (DialogBox(hInst, (LPCTSTR)IDD_DECODING, hWnd, (DLGPROC)Decoding) == IDOK)
                            ;
                    break;
                case ID_DECODER_SHOWCOVERAGE:
                    DialogBox(hInst, (LPCTSTR)IDD_DECODING, hWnd, (DLGPROC)Decoding);
                    break;
                case ID_OPEN_PROJECT:
                    OpenProject();
                    break;
                case ID_FILE_SAVE:
                    SaveProject();
                    break;
                case ID_FILE_CLOSE:
                    CloseProject();
                    break;
                case ID_HELP_BOOMERANGWEBSITE:
                    ShellExecute(NULL, "open", "[url]http://boomerang.sourceforge.net/[/url]", NULL, NULL, SW_SHOW);
                    break;
                case ID_HELP_BOOMERANGFAQ:
                    ShellExecute(NULL, "open", "[url]http://boomerang.sourceforge.net/FAQ.html[/url]", NULL, NULL, SW_SHOW);
                    break;
                case ID_LOADER_SYMBOLTABLE:
                    DialogBox(hInst, (LPCTSTR)IDD_SYMBOLTABLE, hWnd, (DLGPROC)SymbolTable);
                    break;
                case ID_LOADER_MEMORYDUMP:
                    DialogBox(hInst, (LPCTSTR)IDD_MEMORYDUMP, hWnd, (DLGPROC)MemoryDump);
                    break;
                case ID_DECOMPILER_START:
                    if (hDecompilerThread == NULL)
                        {
                            saveUndoPoint();
                            prog->decompile();
                        }
                    break;
                case ID_DECOMPILER_SUSPEND:
                    if (hDecompilerThread)
                        {
                            suspendDecompiler();
                        }
                    break;
                case ID_DECOMPILER_RESUME:
                    if (hDecompilerThread)
                        {
                            resumeDecompiler();
                        }
                    break;
                case ID_DECOMPILER_TERMINATE:
                    if (hDecompilerThread)
                        {
                            TerminateThread(hDecompilerThread, 0);
                            hDecompilerThread = NULL;
                            updateDecompilerMenu();
                        }
                    break;
                case ID_SETOUTPUTPATH:
                {
                    OPENFILENAME ofn;
                    memset(&ofn, 0, sizeof(ofn));
                    ofn.lStructSize = sizeof(ofn);
                    char buf[MAX_PATH];
                    buf[0] = 0;
                    ofn.lpstrFile = buf;
                    ofn.nMaxFile = MAX_PATH;
                    if (GetOpenFileName(&ofn))
                        {
                            Boomerang::get()->setOutputDirectory(buf);
                        }
                }
                break;
                case ID_VIEW_CODE:
                    if (view_as != V_CODE)
                        {
                            view_as = V_CODE;
                            updateCodeView();
                        }
                    break;
                case ID_VIEW_RTL:
                    if (view_as != V_RTL)
                        {
                            view_as = V_RTL;
                            updateCodeView();
                        }
                    break;
                case ID_VIEW_MIXED:
                    if (view_as != V_MIXED)
                        {
                            view_as = V_MIXED;
                            updateCodeView();
                        }
                    break;
                case ID_VIEW_RENAME:
                    TreeView_EditLabel(hTreeView, TreeView_GetSelection(hTreeView));
                    break;
                case ID_TO_SSA:
                {
                    UserProc *u = dynamic_cast<UserProc*>(selectedProc());
                    if (u == NULL)
                        break;
                    Boomerang::get()->noDecompile = true;
                    u->decompile(new CycleList);
                    Boomerang::get()->noDecompile = false;
                    updateCodeView();
                }
                break;
                case ID_FROM_SSA:
                {
                    UserProc *u = dynamic_cast<UserProc*>(selectedProc());
                    if (u == NULL)
                        break;
                    u->fromSSAform();
                    updateCodeView();
                }
                break;
                case ID_PROP_REGS:
                {
                    UserProc *u = dynamic_cast<UserProc*>(selectedProc());
                    if (u == NULL)
                        break;
                    u->propagateAtDepth(0);
                    updateCodeView();
                }
                break;
                case ID_VIEW_NEWCLUSTER:
                {
                    TVINSERTSTRUCT tvi;
                    tvi.hParent = TreeView_GetRoot(hTreeView);
                    tvi.hInsertAfter = TVI_LAST;
                    tvi.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
                    tvi.item.state = tvi.item.stateMask = TVIS_EXPANDED;
                    tvi.item.pszText = "New Cluster";
                    tvi.item.iImage = tvi.item.iSelectedImage = iCluster;
                    MyLParam *p = new MyLParam(new Cluster());
                    tvi.item.lParam = (LPARAM)p;
                    prog->getRootCluster()->addChild(p->c);
                    HTREEITEM h = TreeView_InsertItem(hTreeView, &tvi);
                    TreeView_EditLabel(hTreeView, h);
                }
                break;
                case ID_VIEW_DELETECLUSTER:
                {
                    TVITEM tvi;
                    tvi.hItem = TreeView_GetSelection(hTreeView);
                    tvi.mask = TVIF_PARAM;
                    TreeView_GetItem(hTreeView, &tvi);
                    MyLParam *p = (MyLParam*)tvi.lParam;
                    if (p->isCluster && p->c != prog->getRootCluster())
                        {
                            p->c->getParent()->removeChild(p->c);
                            TreeView_DeleteItem(hTreeView, tvi.hItem);
                            closeTab(p->c->getName());
                        }
                }
                break;
                case ID_VIEW_PROPERTIES:
                {
                    Proc *p = selectedProc();
                    if (p)
                        if (p->isLib())
                            DialogBox(hInst, (LPCTSTR)IDD_LPROCPROPERTIES, hWnd, (DLGPROC)ProcProperties);
                        else
                            DialogBox(hInst, (LPCTSTR)IDD_PROCPROPERTIES, hWnd, (DLGPROC)ProcProperties);
                }
                break;
                case ID_DECODER_OPTIONS:
                    DialogBox(hInst, (LPCTSTR)IDD_DECODEOPTIONS, hWnd, (DLGPROC)DecodeOptions);
                    break;
                case ID_DECOMPILER_OPTIONS:
                    DialogBox(hInst, (LPCTSTR)IDD_DECOMPILEOPTIONS, hWnd, (DLGPROC)DecompileOptions);
                    break;
                case ID_CODEGENERATOR_REGENERATEALL:
                    generateCodeForAll();
                    break;
                case ID_EDIT_UNDO:
                    prog->restoreMemo();
                    if (!prog->canRestore())
                        EnableMenuItem(GetMenu(hTopWnd), ID_EDIT_UNDO, MF_GRAYED);
                    EnableMenuItem(GetMenu(hTopWnd), ID_EDIT_REDO, MF_ENABLED);
                    updateAllTabs();
                    updateTreeView();
                    updateCodeView();
                    break;
                case ID_EDIT_REDO:
                    prog->restoreMemo(true);
                    if (!prog->canRestore(true))
                        EnableMenuItem(GetMenu(hTopWnd), ID_EDIT_REDO, MF_GRAYED);
                    EnableMenuItem(GetMenu(hTopWnd), ID_EDIT_UNDO, MF_ENABLED);
                    updateAllTabs();
                    updateTreeView();
                    updateCodeView();
                    break;
                case ID_EDIT_COPY:
                    if (selectedTab)
                        SendMessage(tabWithName[selectedTab].edit, WM_COPY, 0, 0);
                    break;
                case ID_EDIT_PASTE:
                    if (selectedTab)
                        SendMessage(tabWithName[selectedTab].edit, WM_PASTE, 0, 0);
                    break;
                case ID_EDIT_SELECTALL:
                    if (selectedTab)
                        SendMessage(tabWithName[selectedTab].edit, EM_SETSEL, 0, -1);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
                }
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            SelectObject(hdc, hTabBarFont);
            GetTextMetrics(hdc, &tm);
            GetClientRect(hWnd, &tabBarRect);
            tabBarRect.right -= 200;
            tabBarRect.bottom = tm.tmHeight;
            drawTabBar(hdc);
            // TODO: Add any drawing code here...
            EndPaint(hWnd, &ps);
            break;
        case WM_LBUTTONDOWN:
            if (GET_Y_LPARAM(lParam) <= tabBarRect.bottom)
                handleTabBarPress(GET_X_LPARAM(lParam));  

17

Re: Допоможіть запустити бумеранг!

Якщо ту змінну log перейменувати, щось зміниться?

Re: Допоможіть запустити бумеранг!

Так, ця помилка пішла. Я перейменував log в llog. Тепер взагалі лається так!! Навіть не уявляю що це таке.
Ошибка    1    error LNK2019: ссылка на неразрешенный внешний символ "class SymbolMatcher * __cdecl SymbolMatcherFactory_getInstanceFor(class Prog *,char const *,char const *)" (?SymbolMatcherFactory_getInstanceFor@@YAPAVSymbolMatcher@@PAVProg@@PBD1@Z) в функции "public: void __thiscall Prog::MatchSignatures(char const *,char const *)" (?MatchSignatures@Prog@@QAEXPBD0@Z)    D:\Skladannja3\libid\boomerang\win32make\console\prog.obj    console

Re: Допоможіть запустити бумеранг!

У величезному-величезнішому файлі (prog.cpp) є ось таке:

void Prog::MatchSignatures(const char * sig_file, const char * hint)
/**
    Search for library signatures from sig_file and match them
    'hint' is used to force usage of specified signature matching
    module
*/
{
    SymbolMatcher *sym_matcher;

    sym_matcher = SymbolMatcherFactory_getInstanceFor(this, sig_file, hint);

    if(sym_matcher)
        sym_matcher->MatchAll();
    else
        std::cerr << "No default symbol matcher module for " << sig_file << std::endl;

}

Ось, таке в нім є, але я все одно зовсім не зрозумію що не так.

Re: Допоможіть запустити бумеранг!

А також є  libidloader.h

SymbolMatcher * SymbolMatcherFactory_getInstanceFor(Prog *prog, const char *sSymbolContainer, const char *hint);