Skip to content

Commit

Permalink
Avoid double file loading in the OnOpenDocument.
Browse files Browse the repository at this point in the history
Removed unused old stuff from CFileLoader. Initialize m_stFileInfo.fHasIAT.
g_mapLibpeErrors from std::wstring to std::wstring_view.
  • Loading branch information
jovibor committed May 24, 2023
1 parent d34bec5 commit ae2151d
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 80 deletions.
1 change: 1 addition & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Checks: '*,
-llvm-namespace-comment,
-llvm-qualified-auto,
-misc-non-private-member-variables-in-classes,
-misc-no-recursion,
-misc-use-after-move,
-modernize-use-trailing-return-type,
-modernize-avoid-c-arrays,
Expand Down
98 changes: 52 additions & 46 deletions Pepper/CFileLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,20 @@
* Pepper is a PE32 (x86) and PE32+ (x64) binares viewer/editor. *
****************************************************************************************************/
#include "stdafx.h"
#include "res/resource.h"
#include "CFileLoader.h"
#include "CPepperDoc.h"
#include "res/resource.h"
#include <algorithm>

import Utility;

void CFileLoader::CreateHexCtrlWnd()
auto CFileLoader::GetData()const->std::span<std::byte>
{
m_pHex->Create(m_hcs);

const auto hWndHex = m_pHex->GetWindowHandle(EHexWnd::WND_MAIN);
const auto iWidthActual = m_pHex->GetActualWidth() + GetSystemMetrics(SM_CXVSCROLL);
CRect rcHex(0, 0, iWidthActual, iWidthActual); //Square window.
AdjustWindowRectEx(rcHex, m_dwStyle, FALSE, m_dwExStyle);
const auto iWidth = rcHex.Width();
const auto iHeight = rcHex.Height() - rcHex.Height() / 3;
const auto iPosX = GetSystemMetrics(SM_CXSCREEN) / 2 - iWidth / 2;
const auto iPosY = GetSystemMetrics(SM_CYSCREEN) / 2 - iHeight / 2;
::SetWindowPos(hWndHex, nullptr, iPosX, iPosY, iWidth, iHeight, SWP_SHOWWINDOW);

const auto hIconSmall = static_cast<HICON>(LoadImageW(AfxGetInstanceHandle(), MAKEINTRESOURCEW(IDI_HEXCTRL_LOGO), IMAGE_ICON, 0, 0, 0));
const auto hIconBig = static_cast<HICON>(LoadImageW(AfxGetInstanceHandle(), MAKEINTRESOURCEW(IDI_HEXCTRL_LOGO), IMAGE_ICON, 96, 96, 0));
if (hIconSmall != nullptr) {
::SendMessageW(m_pHex->GetWindowHandle(EHexWnd::WND_MAIN), WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hIconSmall));
::SendMessageW(m_pHex->GetWindowHandle(EHexWnd::WND_MAIN), WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hIconBig));
if (!IsLoaded()) {
return { };
}
}

bool CFileLoader::Flush()
{
if (!IsLoaded())
return false;

if (IsModified())
FlushViewOfFile(m_lpBase, 0);

return false;
return { static_cast<std::byte*>(m_lpBase), static_cast<std::size_t>(m_stFileSize.QuadPart) };
}

HRESULT CFileLoader::LoadFile(LPCWSTR lpszFileName, CPepperDoc* pDoc)
Expand Down Expand Up @@ -72,8 +48,8 @@ HRESULT CFileLoader::LoadFile(LPCWSTR lpszFileName, CPepperDoc* pDoc)
MessageBoxW(L"CreateFileMappingW call in FileLoader::LoadFile failed.", L"Error", MB_ICONERROR);
return E_ABORT;
}
m_fLoaded = true;

m_fLoaded = true;
m_lpBase = MapViewOfFile(m_hMapObject, fWritable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0);

if (!CWnd::CreateEx(0, AfxRegisterWndClass(0), nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr))
Expand All @@ -92,8 +68,9 @@ HRESULT CFileLoader::LoadFile(LPCWSTR lpszFileName, CPepperDoc* pDoc)
HRESULT CFileLoader::ShowOffsetInWholeFile(ULONGLONG ullOffset, ULONGLONG ullSelSize, IHexCtrl* pHexCtrl)
{
if (!pHexCtrl) {
if (!m_pHex->IsCreated())
if (!m_pHex->IsCreated()) {
CreateHexCtrlWnd();
}
pHexCtrl = m_pHex.get();
}

Expand All @@ -102,7 +79,7 @@ HRESULT CFileLoader::ShowOffsetInWholeFile(ULONGLONG ullOffset, ULONGLONG ullSel
if (const auto iter = std::find_if(m_vecCheck.begin(), m_vecCheck.end(), [pHexCtrl](const HEXTODATACHECK& ref) {
return ref.pHexCtrl == pHexCtrl; }); iter == m_vecCheck.end() || !iter->fWhole) {
m_hds.fMutable = m_pMainDoc->IsEditMode();
m_hds.spnData = { static_cast<std::byte*>(m_lpBase), static_cast<std::size_t>(m_stFileSize.QuadPart) };
m_hds.spnData = GetData();
pHexCtrl->SetData(m_hds);

if (iter == m_vecCheck.end()) {
Expand All @@ -114,16 +91,16 @@ HRESULT CFileLoader::ShowOffsetInWholeFile(ULONGLONG ullOffset, ULONGLONG ullSel
}

if (ullSelSize > 0) {
std::vector<HEXSPAN> vecSel { { ullOffset, ullSelSize } };
pHexCtrl->SetSelection(vecSel);
pHexCtrl->SetSelection({ { ullOffset, ullSelSize } });
if (!pHexCtrl->IsOffsetVisible(ullOffset)) {
pHexCtrl->GoToOffset(ullOffset);
}
}

//If floating HexCtrl is in use we bring it to the front.
if (pHexCtrl == m_pHex.get())
if (pHexCtrl == m_pHex.get()) {
::SetForegroundWindow(pHexCtrl->GetWindowHandle(EHexWnd::WND_MAIN));
}

return S_OK;
}
Expand All @@ -134,17 +111,20 @@ HRESULT CFileLoader::ShowFilePiece(ULONGLONG ullOffset, ULONGLONG ullSize, IHexC
return E_ABORT;

if (!pHexCtrl) {
if (!m_pHex->IsCreated())
if (!m_pHex->IsCreated()) {
CreateHexCtrlWnd();
}
pHexCtrl = m_pHex.get();
}

if (ullOffset >= static_cast<ULONGLONG>(m_stFileSize.QuadPart)) { //Overflow check.
pHexCtrl->ClearData();
return E_ABORT;
}
if (ullOffset + ullSize > static_cast<ULONGLONG>(m_stFileSize.QuadPart)) //Overflow check.

if (ullOffset + ullSize > static_cast<ULONGLONG>(m_stFileSize.QuadPart)) { //Overflow check.
ullSize = static_cast<ULONGLONG>(m_stFileSize.QuadPart) - ullOffset;
}

if (const auto iter = std::find_if(m_vecCheck.begin(), m_vecCheck.end(), [pHexCtrl](const HEXTODATACHECK& ref) {
return ref.pHexCtrl == pHexCtrl; }); iter == m_vecCheck.end()) {
Expand All @@ -155,23 +135,30 @@ HRESULT CFileLoader::ShowFilePiece(ULONGLONG ullOffset, ULONGLONG ullSize, IHexC
}

m_hds.fMutable = m_pMainDoc->IsEditMode();
m_hds.spnData = { reinterpret_cast<std::byte*>(reinterpret_cast<DWORD_PTR>(m_lpBase) + ullOffset), static_cast<std::size_t>(ullSize) };
m_hds.spnData = { reinterpret_cast<std::byte*>(reinterpret_cast<DWORD_PTR>(m_lpBase) + ullOffset),
static_cast<std::size_t>(ullSize) };
pHexCtrl->SetData(m_hds);

return S_OK;
}

HRESULT CFileLoader::UnloadFile()
{
if (!m_fLoaded)
if (!IsLoaded())
return E_ABORT;

if (m_lpBase)
if (m_lpBase) {
FlushViewOfFile(m_lpBase, 0);
UnmapViewOfFile(m_lpBase);
if (m_hMapObject)
}

if (m_hMapObject) {
CloseHandle(m_hMapObject);
if (m_hFile)
}

if (m_hFile) {
CloseHandle(m_hFile);
}

m_lpBase = nullptr;
m_hMapObject = nullptr;
Expand All @@ -181,12 +168,31 @@ HRESULT CFileLoader::UnloadFile()
return S_OK;
}

bool CFileLoader::IsLoaded()const
//Private methods.

void CFileLoader::CreateHexCtrlWnd()
{
return m_fLoaded;
m_pHex->Create(m_hcs);

const auto hWndHex = m_pHex->GetWindowHandle(EHexWnd::WND_MAIN);
const auto iWidthActual = m_pHex->GetActualWidth() + GetSystemMetrics(SM_CXVSCROLL);
CRect rcHex(0, 0, iWidthActual, iWidthActual); //Square window.
AdjustWindowRectEx(rcHex, m_dwStyle, FALSE, m_dwExStyle);
const auto iWidth = rcHex.Width();
const auto iHeight = rcHex.Height() - rcHex.Height() / 3;
const auto iPosX = GetSystemMetrics(SM_CXSCREEN) / 2 - iWidth / 2;
const auto iPosY = GetSystemMetrics(SM_CYSCREEN) / 2 - iHeight / 2;
::SetWindowPos(hWndHex, nullptr, iPosX, iPosY, iWidth, iHeight, SWP_SHOWWINDOW);

const auto hIconSmall = static_cast<HICON>(LoadImageW(AfxGetInstanceHandle(), MAKEINTRESOURCEW(IDI_HEXCTRL_LOGO), IMAGE_ICON, 0, 0, 0));
const auto hIconBig = static_cast<HICON>(LoadImageW(AfxGetInstanceHandle(), MAKEINTRESOURCEW(IDI_HEXCTRL_LOGO), IMAGE_ICON, 96, 96, 0));
if (hIconSmall != nullptr) {
::SendMessageW(m_pHex->GetWindowHandle(EHexWnd::WND_MAIN), WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hIconSmall));
::SendMessageW(m_pHex->GetWindowHandle(EHexWnd::WND_MAIN), WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hIconBig));
}
}

BOOL CFileLoader::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
bool CFileLoader::IsLoaded()const
{
return CWnd::OnNotify(wParam, lParam, pResult);
return m_fLoaded;
}
24 changes: 10 additions & 14 deletions Pepper/CFileLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,35 @@ class CPepperDoc;
class CFileLoader : public CWnd
{
public:
[[nodiscard]] auto GetData()const->std::span<std::byte>;
HRESULT LoadFile(LPCWSTR lpszFileName, CPepperDoc* pDoc); //First function to call.
[[nodiscard]] bool IsWritable()const { return m_fWritable; }

//Shows arbitrary offset in already loaded file (LoadFile). If pHexCtrl == nullptr the inner IHexCtrl object is used.
HRESULT ShowOffsetInWholeFile(ULONGLONG ullOffset, ULONGLONG ullSelSize, IHexCtrl* pHexCtrl = nullptr);

//Shows only a piece of the whole loaded file. If pHexCtrl == nullptr the inner CHexCtrl object is used.
//Shows only a piece of the whole loaded file. If pHexCtrl == nullptr the inner IHexCtrl object is used.
HRESULT ShowFilePiece(ULONGLONG ullOffset, ULONGLONG ullSize, IHexCtrl* pHexCtrl = nullptr);
[[nodiscard]] bool IsModified()const { return m_fModified; } //Has file been modified in memory or not.
bool Flush(); //Writes memory mapped file on disk.
HRESULT UnloadFile(); //Unloads loaded file and all pieces, if present.
private:
[[nodiscard]] bool IsLoaded()const;
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
void CreateHexCtrlWnd();
[[nodiscard]] bool IsLoaded()const;
private:
//Does given IHexCtrl set with a whole file data or only with a file piece.
struct HEXTODATACHECK {
static constexpr DWORD m_dwStyle { WS_POPUP | WS_OVERLAPPEDWINDOW };
static constexpr DWORD m_dwExStyle { WS_EX_APPWINDOW }; //To force to the taskbar.
struct HEXTODATACHECK { //Was given IHexCtrl set with a whole file data or only with a file piece.
IHexCtrl* pHexCtrl { };
bool fWhole { };
};
static constexpr DWORD m_dwStyle { WS_POPUP | WS_OVERLAPPEDWINDOW };
static constexpr DWORD m_dwExStyle { WS_EX_APPWINDOW }; //To force to the taskbar.
CPepperDoc* m_pMainDoc { };
IHexCtrlPtr m_pHex { HEXCTRL::CreateHexCtrl() };
HEXCREATE m_hcs;
HEXDATA m_hds;
LARGE_INTEGER m_stFileSize { }; //Size of the loaded PE file.
HANDLE m_hFile { };
HANDLE m_hMapObject { }; //Returned by CreateFileMappingW.
LPVOID m_lpBase { };
LARGE_INTEGER m_stFileSize { }; //Size of the loaded PE file.
HANDLE m_hFile { }; //Returned by CreateFileW.
HANDLE m_hMapObject { }; //Returned by CreateFileMappingW.
LPVOID m_lpBase { }; //Returned by MapViewOfFile.
std::vector<HEXTODATACHECK> m_vecCheck;
bool m_fLoaded { false };
bool m_fModified { false };
bool m_fWritable { false };
};
21 changes: 11 additions & 10 deletions Pepper/CPepperDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,19 @@ BOOL CPepperDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
m_wstrDocName = lpszPathName;
m_wstrDocName = m_wstrDocName.substr(m_wstrDocName.find_last_of(L'\\') + 1); //Doc name with .extension.
libpe::Clibpe libPE;
const std::wstring wstrErrCaption = L"File load failed: " + m_wstrDocName;

if (m_stFileLoader.LoadFile(lpszPathName, this) != S_OK) {
MessageBoxW(nullptr, L"File load failed.", wstrErrCaption.data(), MB_ICONERROR);
return FALSE;
}

if (const auto err = libPE.OpenFile(lpszPathName); err != libpe::PEOK) {
m_wstrDocName += L" File Load Failed.";
libpe::Clibpe libPE;
if (const auto err = libPE.OpenFile(m_stFileLoader.GetData()); err != libpe::PEOK) {
const auto it = g_mapLibpeErrors.find(err);
MessageBoxW(nullptr, std::vformat(L"File load failed with libpe error code: 0x{:04X}\n{}",
MessageBoxW(nullptr, std::vformat(L"File load failed with the libpe error code: 0x{:04X}\n{}",
std::make_wformat_args(err, it != g_mapLibpeErrors.end() ? it->second : L"N/A")).data(),
m_wstrDocName.data(), MB_ICONERROR);

wstrErrCaption.data(), MB_ICONERROR);
return FALSE;
}

Expand All @@ -56,7 +60,7 @@ BOOL CPepperDoc::OnOpenDocument(LPCTSTR lpszPathName)
m_optExport = libPE.GetExport();
m_stFileInfo.fHasExport = m_optExport.has_value();
m_optImport = libPE.GetImport();
m_stFileInfo.fHasImport = m_optImport.has_value();
m_stFileInfo.fHasImport = m_stFileInfo.fHasIAT = m_optImport.has_value();
m_optResRoot = libPE.GetResources();
m_stFileInfo.fHasResource = m_optResRoot.has_value();
m_optExcept = libPE.GetExceptions();
Expand Down Expand Up @@ -104,16 +108,13 @@ BOOL CPepperDoc::OnOpenDocument(LPCTSTR lpszPathName)
}
}

libPE.CloseFile();
m_stFileLoader.LoadFile(lpszPathName, this);
UpdateAllViews(nullptr);

return TRUE;
}

void CPepperDoc::OnCloseDocument()
{
m_stFileLoader.Flush();
m_stFileLoader.UnloadFile();

CDocument::OnCloseDocument();
Expand Down
2 changes: 1 addition & 1 deletion Pepper/CPepperDoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class CPepperDoc : public CDocument
std::optional<PEBOUNDIMPORT_VEC> m_optBoundImp;
std::optional<PEDELAYIMPORT_VEC> m_optDelayImp;
std::optional<PECOMDESCRIPTOR> m_optComDescr;
Util::PEFILEINFO m_stFileInfo;
Util::PEFILEINFO m_stFileInfo { };
bool m_fEditMode { false };
bool m_fHasCur { false };
bool m_fHasIco { false };
Expand Down
18 changes: 9 additions & 9 deletions Pepper/Utility.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,13 @@ export namespace Util
}
}

//Errors, that might come from libpe.
inline const std::unordered_map<DWORD, std::wstring> g_mapLibpeErrors {
//Errors, that might come from the libpe.
inline const std::unordered_map<DWORD, std::wstring_view> g_mapLibpeErrors {
TO_WSTR_MAP(libpe::PEOK),
TO_WSTR_MAP(libpe::ERR_FILE_OPEN),
TO_WSTR_MAP(libpe::ERR_FILE_MAPPING),
TO_WSTR_MAP(libpe::ERR_FILE_SIZESMALL),
TO_WSTR_MAP(libpe::ERR_FILE_NODOSHDR)
TO_WSTR_MAP(libpe::ERR_FILE_OPEN),
TO_WSTR_MAP(libpe::ERR_FILE_MAPPING),
TO_WSTR_MAP(libpe::ERR_FILE_SIZESMALL),
TO_WSTR_MAP(libpe::ERR_FILE_NODOSHDR)
};

struct PEFILEINFO {
Expand Down Expand Up @@ -580,8 +580,8 @@ export namespace Util
//All HexCtrl dialogs' IDs for hiding/showing in Views, when tab is deactivated/activated.
inline const std::vector<HEXCTRL::EHexWnd> g_vecHexDlgs {
HEXCTRL::EHexWnd::DLG_BKMMANAGER, HEXCTRL::EHexWnd::DLG_DATAINTERP, HEXCTRL::EHexWnd::DLG_MODIFY,
HEXCTRL::EHexWnd::DLG_SEARCH, HEXCTRL::EHexWnd::DLG_ENCODING,
HEXCTRL::EHexWnd::DLG_GOTO, HEXCTRL::EHexWnd::DLG_TEMPLMGR };
HEXCTRL::EHexWnd::DLG_SEARCH, HEXCTRL::EHexWnd::DLG_ENCODING,
HEXCTRL::EHexWnd::DLG_GOTO, HEXCTRL::EHexWnd::DLG_TEMPLMGR };


/*****************************************************************
Expand Down Expand Up @@ -656,5 +656,5 @@ export namespace Util
********************************************************/

//Color of the list's "Offset" column
constexpr COLORREF g_clrOffset = RGB(150, 150, 150);
constexpr auto g_clrOffset = RGB(150, 150, 150);
};

0 comments on commit ae2151d

Please sign in to comment.