diff --git a/Scylla/PickApiGui.cpp b/Scylla/PickApiGui.cpp index d08da45..c066ed3 100644 --- a/Scylla/PickApiGui.cpp +++ b/Scylla/PickApiGui.cpp @@ -1,168 +1,178 @@ #include "PickApiGui.h" #include // string conversion #include "WindowDeferrer.h" PickApiGui::PickApiGui(const std::vector &moduleList) : moduleList(moduleList) { selectedApi = 0; hIcon.LoadIcon(IDI_ICON_SCYLLA); } BOOL PickApiGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { DoDataExchange(); // attach controls fillDllComboBox(ComboDllSelect); CenterWindow(); SetIcon(hIcon, TRUE); SetIcon(hIcon, FALSE); GetWindowRect(&minDlgSize); return TRUE; } void PickApiGui::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { lpMMI->ptMinTrackSize = CPoint(minDlgSize.Size()); } void PickApiGui::OnSizing(UINT fwSide, RECT* pRect) { // Get size difference CRect rectOld; GetWindowRect(&rectOld); CRect rectNew = *pRect; sizeOffset = rectNew.Size() - rectOld.Size(); } void PickApiGui::OnSize(UINT nType, CSize size) { const WindowDeferrer::Deferrable controls[] = { {IDC_GROUP_DLL, false, false, true, false}, {IDC_CBO_DLLSELECT, false, false, true, false}, {IDC_GROUP_APIS, false, false, true, true}, {IDC_LIST_APISELECT, false, false, true, true}, {IDC_STATIC_APIFILTER, false, true, false, false}, {IDC_EDIT_APIFILTER, false, true, true, false}, {IDC_BTN_PICKAPI_OK, true, true, false, false}, {IDC_BTN_PICKAPI_CANCEL, true, true, false, false} }; if(nType == SIZE_RESTORED) { WindowDeferrer deferrer(m_hWnd, controls, _countof(controls)); deferrer.defer(sizeOffset.cx, sizeOffset.cy); sizeOffset.SetSize(0, 0); } } void PickApiGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { - int indexDll = ComboDllSelect.GetCurSel(); - int indexApi = ListApiSelect.GetCurSel(); - if (indexDll != CB_ERR && indexApi != CB_ERR) - { - selectedApi = apiListTemp[indexApi]; - EndDialog(1); - } + actionApiSelected(); } void PickApiGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void PickApiGui::OnDllListSelected(UINT uNotifyCode, int nID, CWindow wndCtl) { int indexDll = ComboDllSelect.GetCurSel(); if (indexDll != CB_ERR) { apiListTemp = moduleList[indexDll].apiList; fillApiListBox(ListApiSelect, apiListTemp); EditApiFilter.SetWindowText(L""); } } +void PickApiGui::OnApiListDoubleClick(UINT uNotifyCode, int nID, CWindow wndCtl) +{ + actionApiSelected(); +} + void PickApiGui::OnApiFilterUpdated(UINT uNotifyCode, int nID, CWindow wndCtl) { // remove from apiListTemp that don't fit int indexDll = ComboDllSelect.GetCurSel(); if (indexDll != CB_ERR) { WCHAR filter[MAX_PATH]; int lenFilter = EditApiFilter.GetWindowText(filter, _countof(filter)); if(lenFilter > 0) { apiListTemp.clear(); const std::vector &apis = moduleList[indexDll].apiList; for (size_t i = 0; i < apis.size(); i++) { ApiInfo* api = apis[i]; if(api->name[0] != '\0') { CA2WEX wStr(api->name); if(!_wcsnicmp(wStr, filter, lenFilter)) { apiListTemp.push_back(api); } } else { WCHAR buf[6]; swprintf_s(buf, _countof(buf), L"#%04X", api->ordinal); if(!_wcsnicmp(buf, filter, lenFilter)) { apiListTemp.push_back(api); } } } } else { apiListTemp = moduleList[indexDll].apiList; } fillApiListBox(ListApiSelect, apiListTemp); } } +void PickApiGui::actionApiSelected() +{ + int indexDll = ComboDllSelect.GetCurSel(); + int indexApi = ListApiSelect.GetCurSel(); + if (indexDll != CB_ERR && indexApi != CB_ERR) + { + selectedApi = apiListTemp[indexApi]; + EndDialog(1); + } +} + void PickApiGui::fillDllComboBox(CComboBox& combo) { combo.ResetContent(); for (size_t i = 0; i < moduleList.size(); i++) { combo.AddString(moduleList[i].fullPath); } } void PickApiGui::fillApiListBox(CListBox& list, const std::vector &apis) { list.ResetContent(); for (size_t i = 0; i < apis.size(); i++) { const ApiInfo* api = apis[i]; if(api->name[0] != '\0') { CA2WEX wStr(api->name); list.AddString(wStr); } else { WCHAR buf[6]; swprintf_s(buf, _countof(buf), L"#%04X", api->ordinal); list.AddString(buf); } } } diff --git a/Scylla/PickApiGui.h b/Scylla/PickApiGui.h index 8b152dc..ed295e3 100644 --- a/Scylla/PickApiGui.h +++ b/Scylla/PickApiGui.h @@ -1,85 +1,91 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL utility classes like CString #include // WTL enhanced msg map macros #include // WTL controls #include // WTL dialog data exchange #include #include "ProcessAccessHelp.h" class PickApiGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_PICKAPI }; BEGIN_DDX_MAP(PickApiGui) DDX_CONTROL_HANDLE(IDC_CBO_DLLSELECT, ComboDllSelect) DDX_CONTROL_HANDLE(IDC_LIST_APISELECT, ListApiSelect) DDX_CONTROL_HANDLE(IDC_EDIT_APIFILTER, EditApiFilter) END_DDX_MAP() BEGIN_MSG_MAP(PickDllGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) MSG_WM_SIZING(OnSizing) MSG_WM_SIZE(OnSize) COMMAND_HANDLER_EX(IDC_CBO_DLLSELECT, CBN_SELENDOK, OnDllListSelected) + COMMAND_HANDLER_EX(IDC_LIST_APISELECT, LBN_DBLCLK, OnApiListDoubleClick) COMMAND_HANDLER_EX(IDC_EDIT_APIFILTER, EN_UPDATE, OnApiFilterUpdated) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKAPI_OK, OnOK) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKAPI_CANCEL, OnCancel) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) END_MSG_MAP() PickApiGui(const std::vector &moduleList); ApiInfo* getSelectedApi() const { return selectedApi; } protected: // Variables const std::vector &moduleList; std::vector apiListTemp; ApiInfo* selectedApi; // Controls CComboBox ComboDllSelect; CListBox ListApiSelect; CEdit EditApiFilter; CRect minDlgSize; CSize sizeOffset; // Handles CIcon hIcon; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnGetMinMaxInfo(MINMAXINFO* lpMMI); void OnSizing(UINT fwSide, RECT* pRect); void OnSize(UINT nType, CSize size); void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); void OnDllListSelected(UINT uNotifyCode, int nID, CWindow wndCtl); + void OnApiListDoubleClick(UINT uNotifyCode, int nID, CWindow wndCtl); void OnApiFilterUpdated(UINT uNotifyCode, int nID, CWindow wndCtl); + // Actions + + void actionApiSelected(); + // GUI functions void fillDllComboBox(CComboBox& combo); void fillApiListBox(CListBox& list, const std::vector &apis); }; diff --git a/Scylla/PickDllGui.cpp b/Scylla/PickDllGui.cpp index 1808c18..f2f20a4 100644 --- a/Scylla/PickDllGui.cpp +++ b/Scylla/PickDllGui.cpp @@ -1,171 +1,185 @@ #include "PickDllGui.h" #include "WindowDeferrer.h" PickDllGui::PickDllGui(std::vector &moduleList) : moduleList(moduleList) { prevColumn = -1; ascending = true; selectedModule = 0; hIcon.LoadIcon(IDI_ICON_SCYLLA); } BOOL PickDllGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) { DoDataExchange(); // attach controls addColumnsToModuleList(ListDLLSelect); displayModuleList(ListDLLSelect); CenterWindow(); SetIcon(hIcon, TRUE); SetIcon(hIcon, FALSE); GetWindowRect(&minDlgSize); return TRUE; } void PickDllGui::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { lpMMI->ptMinTrackSize = CPoint(minDlgSize.Size()); } void PickDllGui::OnSizing(UINT fwSide, RECT* pRect) { // Get size difference CRect rectOld; GetWindowRect(&rectOld); CRect rectNew = *pRect; sizeOffset = rectNew.Size() - rectOld.Size(); } void PickDllGui::OnSize(UINT nType, CSize size) { const WindowDeferrer::Deferrable controls[] = { {IDC_LIST_DLLSELECT, false, false, true, true}, {IDC_BTN_PICKDLL_OK, true, true, false, false}, {IDC_BTN_PICKDLL_CANCEL, true, true, false, false}, }; if(nType == SIZE_RESTORED) { WindowDeferrer deferrer(m_hWnd, controls, _countof(controls)); deferrer.defer(sizeOffset.cx, sizeOffset.cy); sizeOffset.SetSize(0, 0); } } LRESULT PickDllGui::OnListDllColumnClicked(NMHDR* pnmh) { NMLISTVIEW* list = (NMLISTVIEW*)pnmh; int column = list->iSubItem; if(column == prevColumn) { ascending = !ascending; } else { prevColumn = column; ascending = true; } // lo-byte: column, hi-byte: sort-order ListDLLSelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending)); return 0; } +LRESULT PickDllGui::OnListDllDoubleClick(NMHDR* pnmh) +{ + NMITEMACTIVATE* ia = (NMITEMACTIVATE*)pnmh; + LVHITTESTINFO hti; + hti.pt = ia->ptAction; + int clicked = ListDLLSelect.HitTest(&hti); + if(clicked != -1) + { + selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(clicked); + EndDialog(1); + } + return 0; +} + void PickDllGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl) { int index = ListDLLSelect.GetSelectionMark(); if (index != -1) { selectedModule = (ModuleInfo *)ListDLLSelect.GetItemData(index); EndDialog(1); } } void PickDllGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl) { EndDialog(0); } void PickDllGui::addColumnsToModuleList(CListViewCtrl& list) { list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); list.InsertColumn(COL_NAME, L"Name", LVCFMT_LEFT); list.InsertColumn(COL_IMAGEBASE, L"ImageBase", LVCFMT_CENTER); list.InsertColumn(COL_IMAGESIZE, L"ImageSize", LVCFMT_CENTER); list.InsertColumn(COL_PATH, L"Path", LVCFMT_LEFT); } void PickDllGui::displayModuleList(CListViewCtrl& list) { WCHAR temp[20]; list.DeleteAllItems(); std::vector::const_iterator iter; int count = 0; for( iter = moduleList.begin(); iter != moduleList.end(); iter++ , count++) { list.InsertItem(count, iter->getFilename()); #ifdef _WIN64 swprintf_s(temp, _countof(temp), L"%016I64X", iter->modBaseAddr); #else swprintf_s(temp, _countof(temp), L"%08X", iter->modBaseAddr); #endif list.SetItemText(count, COL_IMAGEBASE, temp); swprintf_s(temp, _countof(temp),L"%08X",iter->modBaseSize); list.SetItemText(count, COL_IMAGESIZE, temp); list.SetItemText(count, COL_PATH, iter->fullPath); list.SetItemData(count, (DWORD_PTR)&(*iter)); } list.SetColumnWidth(COL_NAME, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_IMAGEBASE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_IMAGESIZE, LVSCW_AUTOSIZE_USEHEADER); list.SetColumnWidth(COL_PATH, LVSCW_AUTOSIZE_USEHEADER); } // lParamSort - lo-byte: column, hi-byte: sort-order int PickDllGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { const ModuleInfo * module1 = (ModuleInfo *)lParam1; const ModuleInfo * module2 = (ModuleInfo *)lParam2; int column = LOBYTE(lParamSort); bool ascending = HIBYTE(lParamSort) == true; int diff = 0; switch(column) { case COL_NAME: diff = _wcsicmp(module1->getFilename(), module2->getFilename()); break; case COL_IMAGEBASE: diff = module1->modBaseAddr < module2->modBaseAddr ? -1 : 1; break; case COL_IMAGESIZE: diff = module1->modBaseSize < module2->modBaseSize ? -1 : 1; break; case COL_PATH: diff = _wcsicmp(module1->fullPath, module2->fullPath); break; } return ascending ? diff : -diff; } diff --git a/Scylla/PickDllGui.h b/Scylla/PickDllGui.h index c494c78..bef5740 100644 --- a/Scylla/PickDllGui.h +++ b/Scylla/PickDllGui.h @@ -1,90 +1,92 @@ #pragma once #include #include "resource.h" // WTL #include // base ATL classes #include // base WTL classes #include // ATL GUI classes #include // WTL utility classes like CString #include // WTL enhanced msg map macros #include // WTL controls #include // WTL dialog data exchange #include #include "ProcessAccessHelp.h" class PickDllGui : public CDialogImpl, public CWinDataExchange { public: enum { IDD = IDD_DLG_PICKDLL }; BEGIN_DDX_MAP(PickDllGui) DDX_CONTROL_HANDLE(IDC_LIST_DLLSELECT, ListDLLSelect) END_DDX_MAP() BEGIN_MSG_MAP(PickDllGui) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) MSG_WM_SIZING(OnSizing) MSG_WM_SIZE(OnSize) NOTIFY_HANDLER_EX(IDC_LIST_DLLSELECT, LVN_COLUMNCLICK, OnListDllColumnClicked) + NOTIFY_HANDLER_EX(IDC_LIST_DLLSELECT, NM_DBLCLK, OnListDllDoubleClick) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_OK, OnOK) COMMAND_ID_HANDLER_EX(IDC_BTN_PICKDLL_CANCEL, OnCancel) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) END_MSG_MAP() PickDllGui(std::vector &moduleList); ModuleInfo* getSelectedModule() const { return selectedModule; } protected: // Variables std::vector &moduleList; ModuleInfo* selectedModule; // Controls CListViewCtrl ListDLLSelect; enum ListColumns { COL_NAME = 0, COL_IMAGEBASE, COL_IMAGESIZE, COL_PATH }; int prevColumn; bool ascending; CRect minDlgSize; CSize sizeOffset; // Handles CIcon hIcon; protected: // Message handlers BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); void OnGetMinMaxInfo(MINMAXINFO* lpMMI); void OnSizing(UINT fwSide, RECT* pRect); void OnSize(UINT nType, CSize size); LRESULT OnListDllColumnClicked(NMHDR* pnmh); + LRESULT OnListDllDoubleClick(NMHDR* pnmh); void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); // GUI functions void addColumnsToModuleList(CListViewCtrl& list); void displayModuleList(CListViewCtrl& list); static int CALLBACK listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); };