// Copyright (c) 2015-2026 Vector 35 Inc // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. #include #include "binaryninjaapi.h" #include "binaryninjacore.h" using namespace BinaryNinja; using namespace Json; using namespace std; char* NavigationHandler::GetCurrentViewCallback(void* ctxt) { NavigationHandler* handler = (NavigationHandler*)ctxt; string result = handler->GetCurrentView(); return BNAllocString(result.c_str()); } uint64_t NavigationHandler::GetCurrentOffsetCallback(void* ctxt) { NavigationHandler* handler = (NavigationHandler*)ctxt; return handler->GetCurrentOffset(); } bool NavigationHandler::NavigateCallback(void* ctxt, const char* view, uint64_t offset) { NavigationHandler* handler = (NavigationHandler*)ctxt; return handler->Navigate(view, offset); } NavigationHandler::NavigationHandler() { m_callbacks.context = this; m_callbacks.getCurrentView = GetCurrentViewCallback; m_callbacks.getCurrentOffset = GetCurrentOffsetCallback; m_callbacks.navigate = NavigateCallback; } FileMetadata::FileMetadata() { m_object = BNCreateFileMetadata(); } FileMetadata::FileMetadata(const string& filename) { m_object = BNCreateFileMetadata(); BNSetFilename(m_object, filename.c_str()); } FileMetadata::FileMetadata(Ref projectFile) { m_object = BNCreateFileMetadata(); BNSetProjectFile(m_object, projectFile->m_object); BNSetFilename(m_object, projectFile->GetPathOnDisk().c_str()); } FileMetadata::FileMetadata(BNFileMetadata* file) { m_object = file; } void FileMetadata::Close() { BNCloseFile(m_object); } void FileMetadata::SetNavigationHandler(NavigationHandler* handler) { if (handler) BNSetFileMetadataNavigationHandler(m_object, handler->GetCallbacks()); else BNSetFileMetadataNavigationHandler(m_object, nullptr); } string FileMetadata::GetOriginalFilename() const { char* str = BNGetOriginalFilename(m_object); string result = str; BNFreeString(str); return result; } void FileMetadata::SetOriginalFilename(const string& name) { BNSetOriginalFilename(m_object, name.c_str()); } string FileMetadata::GetFilename() const { char* str = BNGetFilename(m_object); string result = str; BNFreeString(str); return result; } void FileMetadata::SetFilename(const string& name) { BNSetFilename(m_object, name.c_str()); } string FileMetadata::GetVirtualPath() const { char* str = BNGetVirtualPath(m_object); string result = str; BNFreeString(str); return result; } void FileMetadata::SetVirtualPath(const string& path) { BNSetVirtualPath(m_object, path.c_str()); } string FileMetadata::GetDisplayName() const { char* str = BNGetDisplayName(m_object); string result = str; BNFreeString(str); return result; } void FileMetadata::SetDisplayName(const string& name) { BNSetDisplayName(m_object, name.c_str()); } bool FileMetadata::IsModified() const { return BNIsFileModified(m_object); } bool FileMetadata::IsAnalysisChanged() const { return BNIsAnalysisChanged(m_object); } void FileMetadata::MarkFileModified() { BNMarkFileModified(m_object); } void FileMetadata::MarkFileSaved() { BNMarkFileSaved(m_object); } bool FileMetadata::IsBackedByDatabase(const string& binaryViewType) const { return BNIsBackedByDatabase(m_object, binaryViewType.c_str()); } bool FileMetadata::CreateDatabase(const string& name, BinaryView* data, Ref settings) { return BNCreateDatabase(data->GetObject(), name.c_str(), settings ? settings->GetObject() : nullptr); } bool FileMetadata::CreateDatabase(const string& name, BinaryView* data, const ProgressFunction& progressCallback, Ref settings) { ProgressContext cb; cb.callback = progressCallback; return BNCreateDatabaseWithProgress( data->GetObject(), name.c_str(), &cb, ProgressCallback, settings ? settings->GetObject() : nullptr); } Ref FileMetadata::OpenExistingDatabase(const string& path) { BNBinaryView* data = BNOpenExistingDatabase(m_object, path.c_str()); if (!data) return nullptr; return new BinaryView(data); } Ref FileMetadata::OpenExistingDatabase( const string& path, const ProgressFunction& progressCallback) { ProgressContext cb; cb.callback = progressCallback; BNBinaryView* data = BNOpenExistingDatabaseWithProgress(m_object, path.c_str(), &cb, ProgressCallback); if (!data) return nullptr; return new BinaryView(data); } Ref FileMetadata::OpenDatabaseForConfiguration(const string& path) { BNBinaryView* data = BNOpenDatabaseForConfiguration(m_object, path.c_str()); if (!data) return nullptr; return new BinaryView(data); } bool FileMetadata::SaveAutoSnapshot(BinaryView* data, Ref settings) { return BNSaveAutoSnapshot(data->GetObject(), settings ? settings->GetObject() : nullptr); } bool FileMetadata::SaveAutoSnapshot( BinaryView* data, const ProgressFunction& progressCallback, Ref settings) { ProgressContext cb; cb.callback = progressCallback; return BNSaveAutoSnapshotWithProgress( data->GetObject(), &cb, ProgressCallback, settings ? settings->GetObject() : nullptr); } void FileMetadata::GetSnapshotData( Ref data, Ref cache, const ProgressFunction& progress) { ProgressContext cb; cb.callback = progress; BNGetSnapshotData(GetObject(), data->GetObject(), cache->GetObject(), &cb, ProgressCallback); } void FileMetadata::ApplySnapshotData(BinaryView* file, Ref data, Ref cache, const ProgressFunction& progress, bool openForConfiguration, bool restoreRawView) { ProgressContext cb; cb.callback = progress; BNApplySnapshotData(GetObject(), file->GetObject(), data->GetObject(), cache->GetObject(), &cb, ProgressCallback, openForConfiguration, restoreRawView); } Ref FileMetadata::GetDatabase() { BNDatabase* db = BNGetFileMetadataDatabase(m_object); if (db == nullptr) return nullptr; return new Database(db); } bool FileMetadata::Rebase(BinaryView* data, uint64_t address) { return BNRebase(data->GetObject(), address); } bool FileMetadata::Rebase( BinaryView* data, uint64_t address, const ProgressFunction& progressCallback) { ProgressContext cb; cb.callback = progressCallback; return BNRebaseWithProgress(data->GetObject(), address, &cb, ProgressCallback); } bool FileMetadata::CreateSnapshotedView(BinaryView *data, const std::string &viewName) { return BNCreateSnapshotedView(data->GetObject(), viewName.c_str()); } bool FileMetadata::CreateSnapshotedView(BinaryView* data, const std::string& viewName, const ProgressFunction& progressCallback) { ProgressContext cb; cb.callback = progressCallback; return BNCreateSnapshotedViewWithProgress(data->GetObject(), viewName.c_str(), &cb, ProgressCallback); } bool FileMetadata::RunUndoableTransaction(std::function func) { auto undo = BeginUndoActions(false); try { bool result = func(); if (result) { CommitUndoActions(undo); } else { RevertUndoActions(undo); } return result; } catch (...) { RevertUndoActions(undo); throw; } } std::string FileMetadata::BeginUndoActions(bool anonymousAllowed) { char* id = BNBeginUndoActions(m_object, anonymousAllowed); std::string result = id; BNFreeString(id); return result; } void FileMetadata::CommitUndoActions(const std::string& id) { BNCommitUndoActions(m_object, id.c_str()); } void FileMetadata::RevertUndoActions(const std::string& id) { BNRevertUndoActions(m_object, id.c_str()); } void FileMetadata::ForgetUndoActions(const std::string &id) { BNForgetUndoActions(m_object, id.c_str()); } bool FileMetadata::CanUndo() { return BNCanUndo(m_object); } bool FileMetadata::Undo() { return BNUndo(m_object); } bool FileMetadata::CanRedo() { return BNCanRedo(m_object); } bool FileMetadata::Redo() { return BNRedo(m_object); } vector> FileMetadata::GetUsers() { size_t count; BNUser** users = BNGetUsers(m_object, &count); vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new User(BNNewUserReference(users[i]))); BNFreeUserList(users, count); return result; } vector> FileMetadata::GetUndoEntries() { size_t count; BNUndoEntry** entries = BNGetUndoEntries(m_object, &count); vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(new UndoEntry(BNNewUndoEntryReference(entries[i]))); } BNFreeUndoEntryList(entries, count); return result; } vector> FileMetadata::GetRedoEntries() { size_t count; BNUndoEntry** entries = BNGetRedoEntries(m_object, &count); vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) { result.push_back(new UndoEntry(BNNewUndoEntryReference(entries[i]))); } BNFreeUndoEntryList(entries, count); return result; } Ref FileMetadata::GetLastUndoEntry() { BNUndoEntry* bnEntry = BNGetLastUndoEntry(m_object); if (bnEntry == nullptr) return nullptr; return new UndoEntry(bnEntry); } Ref FileMetadata::GetLastRedoEntry() { BNUndoEntry* bnEntry = BNGetLastRedoEntry(m_object); if (bnEntry == nullptr) return nullptr; return new UndoEntry(bnEntry); } std::optional FileMetadata::GetLastUndoEntryTitle() { char* title = BNGetLastUndoEntryTitle(m_object); if (!title) { return std::nullopt; } std::string titleStr = title; BNFreeString(title); return titleStr; } std::optional FileMetadata::GetLastRedoEntryTitle() { char* title = BNGetLastRedoEntryTitle(m_object); if (!title) { return std::nullopt; } std::string titleStr = title; BNFreeString(title); return titleStr; } void FileMetadata::ClearUndoEntries() { BNClearUndoEntries(m_object); } string FileMetadata::GetCurrentView() { char* view = BNGetCurrentView(m_object); string result = view; BNFreeString(view); return result; } uint64_t FileMetadata::GetCurrentOffset() { return BNGetCurrentOffset(m_object); } bool FileMetadata::Navigate(const string& view, uint64_t offset) { return BNNavigate(m_object, view.c_str(), offset); } Ref FileMetadata::GetViewOfType(const string& name) { BNBinaryView* view = BNGetFileViewOfType(m_object, name.c_str()); if (!view) return nullptr; return new BinaryView(view); } std::vector FileMetadata::GetExistingViews() const { size_t count; char** views = BNGetExistingViews(m_object, &count); vector result; result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(string(views[i])); BNFreeStringList(views, count); return result; } size_t FileMetadata::GetSessionId() const { return BNFileMetadataGetSessionId(m_object); } bool FileMetadata::IsSnapshotDataAppliedWithoutError() const { return BNIsSnapshotDataAppliedWithoutError(m_object); } void FileMetadata::UnregisterViewOfType(const std::string& type, BinaryNinja::Ref data) { BNUnregisterViewOfType(m_object, type.c_str(), data->GetObject()); } void FileMetadata::SetProjectFile(Ref projectFile) { BNSetProjectFile(m_object, projectFile ? projectFile->m_object : nullptr); } Ref FileMetadata::GetProjectFile() const { BNProjectFile* bin = BNGetProjectFile(m_object); if (!bin) return nullptr; return new ProjectFile(bin); } SaveSettings::SaveSettings() { m_object = BNCreateSaveSettings(); } SaveSettings::SaveSettings(BNSaveSettings* settings) { m_object = settings; } bool SaveSettings::IsOptionSet(BNSaveOption option) const { return BNIsSaveSettingsOptionSet(m_object, option); } void SaveSettings::SetOption(BNSaveOption option, bool state) { BNSetSaveSettingsOption(m_object, option, state); } std::string SaveSettings::GetName() const { char* name = BNGetSaveSettingsName(m_object); std::string result = name; BNFreeString(name); return result; } void SaveSettings::SetName(const std::string& name) { BNSetSaveSettingsName(m_object, name.c_str()); }