parent
405b97e4d3
commit
2ccf8e777c
@ -24,9 +24,11 @@ namespace hex::prv {
|
||||
bool isAvailable() override;
|
||||
bool isReadable() override;
|
||||
bool isWritable() override;
|
||||
bool isResizable() override;
|
||||
|
||||
void read(u64 offset, void *buffer, size_t size, bool overlays) override;
|
||||
void write(u64 offset, const void *buffer, size_t size) override;
|
||||
void resize(ssize_t newSize) override;
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
@ -41,6 +43,7 @@ namespace hex::prv {
|
||||
#else
|
||||
int m_file;
|
||||
#endif
|
||||
|
||||
std::string m_path;
|
||||
void *m_mappedFile;
|
||||
size_t m_fileSize;
|
||||
@ -49,6 +52,9 @@ namespace hex::prv {
|
||||
struct stat m_fileStats = { 0 };
|
||||
|
||||
bool m_readable, m_writable;
|
||||
|
||||
void open();
|
||||
void close();
|
||||
};
|
||||
|
||||
}
|
@ -46,6 +46,7 @@ namespace hex {
|
||||
s64 m_gotoAddress = 0;
|
||||
|
||||
char m_baseAddressBuffer[0x20] = { 0 };
|
||||
u64 m_resizeSize = 0;
|
||||
|
||||
std::vector<u8> m_dataToSave;
|
||||
|
||||
@ -59,9 +60,10 @@ namespace hex {
|
||||
void drawGotoPopup();
|
||||
void drawEditPopup();
|
||||
|
||||
void openFile(std::string path);
|
||||
bool saveToFile(std::string path, const std::vector<u8>& data);
|
||||
bool loadFromFile(std::string path, std::vector<u8>& data);
|
||||
bool createFile(std::string_view path);
|
||||
void openFile(std::string_view path);
|
||||
bool saveToFile(std::string_view path, const std::vector<u8>& data);
|
||||
bool loadFromFile(std::string_view path, std::vector<u8>& data);
|
||||
|
||||
enum class Language { C, Cpp, CSharp, Rust, Python, Java, JavaScript };
|
||||
void copyBytes();
|
||||
|
@ -16,6 +16,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
{ "hex.welcome.header.main", "Wilkommen zu ImHex" },
|
||||
{ "hex.welcome.header.start", "Start" },
|
||||
{ "hex.welcome.start.create_file", "Neue Datei Erstellen" },
|
||||
{ "hex.welcome.start.open_file", "Datei Öffnen" },
|
||||
{ "hex.welcome.start.open_project", "Projekt Öffnen" },
|
||||
{ "hex.welcome.start.recent", "Kürzlich geöffnet" },
|
||||
@ -139,7 +140,8 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.help.calc_cheat_sheet", "Rechner Cheat Sheet" },
|
||||
|
||||
{ "hex.view.hexeditor.name", "Hex editor" },
|
||||
{ "hex.view.hexeditor.open_file", "Datei öffnen" },
|
||||
{ "hex.view.hexeditor.create_file", "Neu" },
|
||||
{ "hex.view.hexeditor.open_file", "Öffnen" },
|
||||
{ "hex.view.hexeditor.open_project", "Projekt öffnen" },
|
||||
{ "hex.view.hexeditor.save_project", "Projekt speichern" },
|
||||
{ "hex.view.hexeditor.save_data", "Daten speichern" },
|
||||
@ -189,6 +191,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.hexeditor.goto.offset.end", "Ende" },
|
||||
{ "hex.view.hexeditor.error.read_only", "Schreibzugriff konnte nicht erlangt werden. Datei wurde im Lesemodus geöffnet." },
|
||||
{ "hex.view.hexeditor.error.open", "Öffnen der Datei fehlgeschlagen!" },
|
||||
{ "hex.view.hexeditor.error.create", "Erstellen der neuen Datei fehlgeschlagen!" },
|
||||
{ "hex.view.hexeditor.menu.edit.undo", "Rückgängig" },
|
||||
{ "hex.view.hexeditor.menu.edit.redo", "Wiederholen" },
|
||||
{ "hex.view.hexeditor.menu.edit.copy", "Kopieren" },
|
||||
@ -206,6 +209,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.hexeditor.menu.edit.paste", "Einfügen" },
|
||||
{ "hex.view.hexeditor.menu.edit.bookmark", "Lesezeichen erstellen" },
|
||||
{ "hex.view.hexeditor.menu.edit.set_base", "Basisadresse setzen" },
|
||||
{ "hex.view.hexeditor.menu.edit.resize", "Grösse ändern" },
|
||||
|
||||
{ "hex.view.information.name", "Dateninformationen" },
|
||||
{ "hex.view.information.control", "Einstellungen" },
|
||||
@ -276,6 +280,8 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.yara.whole_data", "Gesammte Daten Übereinstimmung!" },
|
||||
{ "hex.view.yara.no_rules", "Keine Yara Regeln gefunden. Platziere sie in ImHex' 'yara' Ordner" },
|
||||
|
||||
{ "hex.view.constants.name", "Konstanten" },
|
||||
|
||||
/* Builtin plugin features */
|
||||
|
||||
{ "hex.builtin.command.calc.desc", "Rechner" },
|
||||
|
@ -16,6 +16,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
{ "hex.welcome.header.main", "Welcome to ImHex" },
|
||||
{ "hex.welcome.header.start", "Start" },
|
||||
{ "hex.welcome.start.create_file", "Create New File" },
|
||||
{ "hex.welcome.start.open_file", "Open File" },
|
||||
{ "hex.welcome.start.open_project", "Open Project" },
|
||||
{ "hex.welcome.start.recent", "Recent Files" },
|
||||
@ -139,7 +140,8 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.help.calc_cheat_sheet", "Calculator Cheat Sheet" },
|
||||
|
||||
{ "hex.view.hexeditor.name", "Hex editor" },
|
||||
{ "hex.view.hexeditor.open_file", "Open File" },
|
||||
{ "hex.view.hexeditor.create_file", "New" },
|
||||
{ "hex.view.hexeditor.open_file", "Open" },
|
||||
{ "hex.view.hexeditor.open_project", "Open Project" },
|
||||
{ "hex.view.hexeditor.save_project", "Save Project" },
|
||||
{ "hex.view.hexeditor.save_data", "Save Data" },
|
||||
@ -189,6 +191,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.hexeditor.goto.offset.end", "End" },
|
||||
{ "hex.view.hexeditor.error.read_only", "Couldn't get write access. File opened in read-only mode." },
|
||||
{ "hex.view.hexeditor.error.open", "Failed to open file!" },
|
||||
{ "hex.view.hexeditor.error.create", "Failed to create new file!" },
|
||||
{ "hex.view.hexeditor.menu.edit.undo", "Undo" },
|
||||
{ "hex.view.hexeditor.menu.edit.redo", "Redo" },
|
||||
{ "hex.view.hexeditor.menu.edit.copy", "Copy" },
|
||||
@ -206,6 +209,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.hexeditor.menu.edit.paste", "Paste" },
|
||||
{ "hex.view.hexeditor.menu.edit.bookmark", "Create bookmark" },
|
||||
{ "hex.view.hexeditor.menu.edit.set_base", "Set base address" },
|
||||
{ "hex.view.hexeditor.menu.edit.resize", "Resize" },
|
||||
|
||||
{ "hex.view.information.name", "Data Information" },
|
||||
{ "hex.view.information.control", "Control" },
|
||||
@ -276,6 +280,8 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.yara.whole_data", "Whole file matches!" },
|
||||
{ "hex.view.yara.no_rules", "No YARA rules found. Put them in ImHex' 'yara' folder" },
|
||||
|
||||
{ "hex.view.constants.name", "Constants" },
|
||||
|
||||
/* Builtin plugin features */
|
||||
|
||||
{ "hex.builtin.command.calc.desc", "Calculator" },
|
||||
|
@ -16,6 +16,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
{ "hex.welcome.header.main", "Benvenuto in ImHex" },
|
||||
{ "hex.welcome.header.start", "Inizia" },
|
||||
// { "hex.welcome.start.create_file", "Create New File" },
|
||||
{ "hex.welcome.start.open_file", "Apri un File" },
|
||||
{ "hex.welcome.start.open_project", "Apri un Progetto" },
|
||||
{ "hex.welcome.start.recent", "File recenti" },
|
||||
@ -139,7 +140,8 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.help.calc_cheat_sheet", "Calcolatrice Cheat Sheet" },
|
||||
|
||||
{ "hex.view.hexeditor.name", "Hex editor" },
|
||||
{ "hex.view.hexeditor.open_file", "Apri File" },
|
||||
// { "hex.view.hexeditor.create_file", "New" },
|
||||
{ "hex.view.hexeditor.open_file", "Apri" },
|
||||
{ "hex.view.hexeditor.menu.file.open_recent", "File recenti" },
|
||||
{ "hex.view.hexeditor.open_project", "Apri i Progetti" },
|
||||
{ "hex.view.hexeditor.save_project", "Salva i Progetti" },
|
||||
@ -189,6 +191,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.hexeditor.goto.offset.end", "Fine" },
|
||||
{ "hex.view.hexeditor.error.read_only", "Impossibile scrivere sul File. File aperto solo in modalità lettura" },
|
||||
{ "hex.view.hexeditor.error.open", "Impossibile aprire il File!" },
|
||||
// { "hex.view.hexeditor.error.create", "Failed to create new file!" },
|
||||
{ "hex.view.hexeditor.menu.edit.undo", "Annulla" },
|
||||
{ "hex.view.hexeditor.menu.edit.redo", "Ripeti" },
|
||||
{ "hex.view.hexeditor.menu.edit.copy", "Copia" },
|
||||
@ -206,6 +209,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.hexeditor.menu.edit.paste", "Incolla" },
|
||||
{ "hex.view.hexeditor.menu.edit.bookmark", "Crea segnalibro" },
|
||||
{ "hex.view.hexeditor.menu.edit.set_base", "Imposta indirizzo di base" },
|
||||
// { "hex.view.hexeditor.menu.edit.resize", "Resize" },
|
||||
|
||||
{ "hex.view.information.name", "Informazione sui Dati" },
|
||||
{ "hex.view.information.control", "Controllo" },
|
||||
@ -276,6 +280,8 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.view.yara.whole_data", "Tutti i file combaciano!" },
|
||||
{ "hex.view.yara.no_rules", "Nessuna regola di YARA. Aggiungile in nella cartella 'yara' di 'ImHex'" },
|
||||
|
||||
// { "hex.view.constants.name", "Constants" },
|
||||
|
||||
/* Builtin plugin features */
|
||||
|
||||
{ "hex.builtin.command.calc.desc", "Calcolatrice" },
|
||||
|
@ -22,12 +22,15 @@ namespace hex::prv {
|
||||
virtual bool isAvailable() = 0;
|
||||
virtual bool isReadable() = 0;
|
||||
virtual bool isWritable() = 0;
|
||||
virtual bool isResizable() = 0;
|
||||
|
||||
virtual void read(u64 offset, void *buffer, size_t size, bool overlays = true);
|
||||
virtual void readRelative(u64 offset, void *buffer, size_t size, bool overlays = true);
|
||||
virtual void write(u64 offset, const void *buffer, size_t size);
|
||||
virtual void writeRelative(u64 offset, const void *buffer, size_t size);
|
||||
|
||||
virtual void resize(ssize_t newSize);
|
||||
|
||||
virtual void readRaw(u64 offset, void *buffer, size_t size) = 0;
|
||||
virtual void writeRaw(u64 offset, const void *buffer, size_t size) = 0;
|
||||
virtual size_t getActualSize() = 0;
|
||||
|
@ -34,6 +34,8 @@ namespace hex::prv {
|
||||
this->write(offset + this->getBaseAddress(), buffer, size);
|
||||
}
|
||||
|
||||
void Provider::resize(ssize_t newSize) { }
|
||||
|
||||
void Provider::applyOverlays(u64 offset, void *buffer, size_t size) {
|
||||
for (auto &overlay : this->m_overlays) {
|
||||
auto overlayOffset = overlay->getAddress();
|
||||
|
@ -13,7 +13,128 @@
|
||||
namespace hex::prv {
|
||||
|
||||
FileProvider::FileProvider(std::string_view path) : Provider(), m_path(path) {
|
||||
this->m_fileStatsValid = stat(path.data(), &this->m_fileStats) == 0;
|
||||
this->open();
|
||||
}
|
||||
|
||||
FileProvider::~FileProvider() {
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
||||
bool FileProvider::isAvailable() {
|
||||
#if defined(OS_WINDOWS)
|
||||
return this->m_file != nullptr && this->m_mapping != nullptr && this->m_mappedFile != nullptr;
|
||||
#else
|
||||
return this->m_file != -1 && this->m_mappedFile != nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FileProvider::isReadable() {
|
||||
return isAvailable() && this->m_readable;
|
||||
}
|
||||
|
||||
bool FileProvider::isWritable() {
|
||||
return isAvailable() && this->m_writable;
|
||||
}
|
||||
|
||||
bool FileProvider::isResizable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FileProvider::read(u64 offset, void *buffer, size_t size, bool overlays) {
|
||||
|
||||
if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset - this->getBaseAddress(), size);
|
||||
|
||||
for (u64 i = 0; i < size; i++)
|
||||
if (getPatches().contains(offset + i))
|
||||
reinterpret_cast<u8*>(buffer)[i] = getPatches()[offset + PageSize * this->m_currPage + i];
|
||||
|
||||
if (overlays)
|
||||
this->applyOverlays(offset, buffer, size);
|
||||
}
|
||||
|
||||
void FileProvider::write(u64 offset, const void *buffer, size_t size) {
|
||||
if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
addPatch(offset, buffer, size);
|
||||
}
|
||||
|
||||
void FileProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
if ((offset + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset, size);
|
||||
}
|
||||
|
||||
void FileProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
if ((offset + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset, buffer, size);
|
||||
}
|
||||
|
||||
void FileProvider::resize(ssize_t newSize) {
|
||||
close();
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
std::wstring widePath;
|
||||
{
|
||||
auto length = static_cast<int>(this->m_path.length() + 1);
|
||||
auto wideLength = MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, nullptr, 0);
|
||||
auto buffer = new wchar_t[wideLength];
|
||||
MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, buffer, wideLength);
|
||||
widePath = buffer;
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
auto handle = ::CreateFileW(widePath.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
::SetFilePointerEx(handle, LARGE_INTEGER { .QuadPart = newSize }, nullptr, FILE_BEGIN);
|
||||
::SetEndOfFile(handle);
|
||||
::CloseHandle(handle);
|
||||
}
|
||||
#else
|
||||
auto handle = ::open(path.data(), O_RDWR | O_CREAT);
|
||||
|
||||
truncate(handle, newSize - 1);
|
||||
|
||||
close(handle);
|
||||
#endif
|
||||
|
||||
open();
|
||||
}
|
||||
|
||||
size_t FileProvider::getActualSize() {
|
||||
return this->m_fileSize;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> FileProvider::getDataInformation() {
|
||||
std::vector<std::pair<std::string, std::string>> result;
|
||||
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, this->m_path);
|
||||
result.emplace_back("hex.builtin.provider.file.size"_lang, hex::toByteString(this->getActualSize()));
|
||||
|
||||
if (this->m_fileStatsValid) {
|
||||
result.emplace_back("hex.builtin.provider.file.creation"_lang, ctime(&this->m_fileStats.st_ctime));
|
||||
result.emplace_back("hex.builtin.provider.file.access"_lang, ctime(&this->m_fileStats.st_atime));
|
||||
result.emplace_back("hex.builtin.provider.file.modification"_lang, ctime(&this->m_fileStats.st_mtime));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileProvider::open() {
|
||||
this->m_fileStatsValid = stat(this->m_path.data(), &this->m_fileStats) == 0;
|
||||
|
||||
this->m_readable = true;
|
||||
this->m_writable = true;
|
||||
@ -21,10 +142,10 @@ namespace hex::prv {
|
||||
#if defined(OS_WINDOWS)
|
||||
std::wstring widePath;
|
||||
{
|
||||
auto length = path.length() + 1;
|
||||
auto wideLength = MultiByteToWideChar(CP_UTF8, 0, path.data(), length, 0, 0);
|
||||
auto length = this->m_path.length() + 1;
|
||||
auto wideLength = MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, 0, 0);
|
||||
wchar_t* buffer = new wchar_t[wideLength];
|
||||
MultiByteToWideChar(CP_UTF8, 0, path.data(), length, buffer, wideLength);
|
||||
MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, buffer, wideLength);
|
||||
widePath = buffer;
|
||||
delete[] buffer;
|
||||
}
|
||||
@ -72,12 +193,12 @@ namespace hex::prv {
|
||||
fileCleanup.release();
|
||||
mappingCleanup.release();
|
||||
|
||||
ProjectFile::setFilePath(path);
|
||||
ProjectFile::setFilePath(this->m_path);
|
||||
|
||||
#else
|
||||
this->m_file = open(path.data(), O_RDWR);
|
||||
this->m_file = ::open(path.data(), O_RDWR);
|
||||
if (this->m_file == -1) {
|
||||
this->m_file = open(path.data(), O_RDONLY);
|
||||
this->m_file = ::open(path.data(), O_RDONLY);
|
||||
this->m_writable = false;
|
||||
}
|
||||
|
||||
@ -90,97 +211,21 @@ namespace hex::prv {
|
||||
|
||||
this->m_mappedFile = mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
FileProvider::~FileProvider() {
|
||||
#if defined(OS_WINDOWS)
|
||||
void FileProvider::close() {
|
||||
#if defined(OS_WINDOWS)
|
||||
if (this->m_mappedFile != nullptr)
|
||||
UnmapViewOfFile(this->m_mappedFile);
|
||||
::UnmapViewOfFile(this->m_mappedFile);
|
||||
if (this->m_mapping != nullptr)
|
||||
CloseHandle(this->m_mapping);
|
||||
::CloseHandle(this->m_mapping);
|
||||
if (this->m_file != nullptr)
|
||||
CloseHandle(this->m_file);
|
||||
#else
|
||||
munmap(this->m_mappedFile, this->m_fileSize);
|
||||
close(this->m_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool FileProvider::isAvailable() {
|
||||
#if defined(OS_WINDOWS)
|
||||
return this->m_file != nullptr && this->m_mapping != nullptr && this->m_mappedFile != nullptr;
|
||||
#else
|
||||
return this->m_file != -1 && this->m_mappedFile != nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FileProvider::isReadable() {
|
||||
return isAvailable() && this->m_readable;
|
||||
}
|
||||
|
||||
bool FileProvider::isWritable() {
|
||||
return isAvailable() && this->m_writable;
|
||||
}
|
||||
|
||||
|
||||
void FileProvider::read(u64 offset, void *buffer, size_t size, bool overlays) {
|
||||
|
||||
if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset - this->getBaseAddress(), size);
|
||||
|
||||
for (u64 i = 0; i < size; i++)
|
||||
if (getPatches().contains(offset + i))
|
||||
reinterpret_cast<u8*>(buffer)[i] = getPatches()[offset + PageSize * this->m_currPage + i];
|
||||
|
||||
if (overlays)
|
||||
this->applyOverlays(offset, buffer, size);
|
||||
}
|
||||
|
||||
void FileProvider::write(u64 offset, const void *buffer, size_t size) {
|
||||
if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
addPatch(offset, buffer, size);
|
||||
}
|
||||
|
||||
void FileProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
if ((offset + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset, size);
|
||||
}
|
||||
|
||||
void FileProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
if ((offset + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset, buffer, size);
|
||||
}
|
||||
size_t FileProvider::getActualSize() {
|
||||
return this->m_fileSize;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> FileProvider::getDataInformation() {
|
||||
std::vector<std::pair<std::string, std::string>> result;
|
||||
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, this->m_path);
|
||||
result.emplace_back("hex.builtin.provider.file.size"_lang, hex::toByteString(this->getActualSize()));
|
||||
|
||||
if (this->m_fileStatsValid) {
|
||||
result.emplace_back("hex.builtin.provider.file.creation"_lang, ctime(&this->m_fileStats.st_ctime));
|
||||
result.emplace_back("hex.builtin.provider.file.access"_lang, ctime(&this->m_fileStats.st_atime));
|
||||
result.emplace_back("hex.builtin.provider.file.modification"_lang, ctime(&this->m_fileStats.st_mtime));
|
||||
}
|
||||
|
||||
return result;
|
||||
::CloseHandle(this->m_file);
|
||||
#else
|
||||
::munmap(this->m_mappedFile, this->m_fileSize);
|
||||
::close(this->m_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
@ -16,6 +16,13 @@
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
ViewHexEditor::ViewHexEditor() : View("hex.view.hexeditor.name"_lang) {
|
||||
@ -168,7 +175,16 @@ namespace hex {
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestOpenWindow>(this, [this](std::string name) {
|
||||
if (name == "Open File") {
|
||||
if (name == "Create File") {
|
||||
View::openFileBrowser("hex.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||
if (!this->createFile(path)) {
|
||||
View::showErrorPopup("hex.view.hexeditor.error.create"_lang);
|
||||
return;
|
||||
}
|
||||
this->openFile(path);
|
||||
this->getWindowOpenState() = true;
|
||||
});
|
||||
} else if (name == "Open File") {
|
||||
View::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
this->openFile(path);
|
||||
this->getWindowOpenState() = true;
|
||||
@ -361,6 +377,24 @@ namespace hex {
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("hex.view.hexeditor.menu.edit.resize"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::InputScalar("hex.common.size"_lang, ImGuiDataType_U64, &this->m_resizeSize, nullptr, nullptr, "0x%016llx", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::NewLine();
|
||||
|
||||
confirmButtons("hex.common.set"_lang, "hex.common.cancel"_lang,
|
||||
[this, &provider]{
|
||||
provider->resize(this->m_resizeSize);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}, []{
|
||||
ImGui::CloseCurrentPopup();
|
||||
});
|
||||
|
||||
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewHexEditor::drawMenu() {
|
||||
@ -583,17 +617,47 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewHexEditor::createFile(std::string_view path) {
|
||||
#if defined(OS_WINDOWS)
|
||||
std::wstring widePath;
|
||||
{
|
||||
auto length = path.length() + 1;
|
||||
auto wideLength = MultiByteToWideChar(CP_UTF8, 0, path.data(), length, 0, 0);
|
||||
auto buffer = new wchar_t[wideLength];
|
||||
MultiByteToWideChar(CP_UTF8, 0, path.data(), length, buffer, wideLength);
|
||||
widePath = buffer;
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void ViewHexEditor::openFile(std::string path) {
|
||||
auto handle = ::CreateFileW(widePath.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
::SetFilePointer(handle, 1, nullptr, FILE_BEGIN);
|
||||
::SetEndOfFile(handle);
|
||||
::CloseHandle(handle);
|
||||
#else
|
||||
auto handle = ::open(path.data(), O_RDWR | O_CREAT);
|
||||
if (handle == -1)
|
||||
return false;
|
||||
|
||||
lseek(handle, 0, SEEK_SET);
|
||||
write(handle, "", 1);
|
||||
|
||||
close(handle);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewHexEditor::openFile(std::string_view path) {
|
||||
auto& provider = SharedData::currentProvider;
|
||||
|
||||
if (provider != nullptr)
|
||||
delete provider;
|
||||
delete provider;
|
||||
|
||||
provider = new prv::FileProvider(path);
|
||||
if (!provider->isWritable()) {
|
||||
@ -615,13 +679,13 @@ namespace hex {
|
||||
|
||||
this->getWindowOpenState() = true;
|
||||
|
||||
EventManager::post<EventFileLoaded>(path);
|
||||
EventManager::post<EventFileLoaded>(std::string(path));
|
||||
EventManager::post<EventDataChanged>();
|
||||
EventManager::post<EventPatternChanged>();
|
||||
}
|
||||
|
||||
bool ViewHexEditor::saveToFile(std::string path, const std::vector<u8>& data) {
|
||||
FILE *file = fopen(path.c_str(), "wb");
|
||||
bool ViewHexEditor::saveToFile(std::string_view path, const std::vector<u8>& data) {
|
||||
FILE *file = fopen(path.data(), "wb");
|
||||
|
||||
if (file == nullptr)
|
||||
return false;
|
||||
@ -632,8 +696,8 @@ namespace hex {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewHexEditor::loadFromFile(std::string path, std::vector<u8>& data) {
|
||||
FILE *file = fopen(path.c_str(), "rb");
|
||||
bool ViewHexEditor::loadFromFile(std::string_view path, std::vector<u8>& data) {
|
||||
FILE *file = fopen(path.data(), "rb");
|
||||
|
||||
if (file == nullptr)
|
||||
return false;
|
||||
@ -1228,6 +1292,13 @@ R"(
|
||||
std::memset(this->m_baseAddressBuffer, 0x00, sizeof(this->m_baseAddressBuffer));
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.view.hexeditor.menu.edit.set_base"_lang); });
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.resize"_lang, nullptr, false, provider != nullptr && provider->isResizable())) {
|
||||
View::doLater([this, &provider]{
|
||||
this->m_resizeSize = provider->getActualSize();
|
||||
ImGui::OpenPopup("hex.view.hexeditor.menu.edit.resize"_lang);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -424,6 +424,8 @@ namespace hex {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.welcome.header.start"_lang);
|
||||
{
|
||||
if (ImGui::BulletHyperlink("hex.welcome.start.create_file"_lang))
|
||||
EventManager::post<RequestOpenWindow>("Create File");
|
||||
if (ImGui::BulletHyperlink("hex.welcome.start.open_file"_lang))
|
||||
EventManager::post<RequestOpenWindow>("Open File");
|
||||
if (ImGui::BulletHyperlink("hex.welcome.start.open_project"_lang))
|
||||
|
Loading…
Reference in New Issue
Block a user