Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Function/BNTypeArchiveNewSnapshotTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ internal static extern IntPtr BNTypeArchiveNewSnapshotTransaction(
IntPtr context ,

// const char** parents
string[] parents ,
IntPtr parents,

// uint64_t parentCount
ulong parentCount

);
}
}
}
2 changes: 1 addition & 1 deletion Handle/BNTypeArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace BinaryNinja
/// that can be shared across multiple binary views and kept in sync via snapshots.
/// Each archive is backed by a file on disk and exposes a versioned snapshot graph.
/// </summary>
public sealed class TypeArchive : AbstractSafeHandle<TypeArchive>
public sealed partial class TypeArchive : AbstractSafeHandle<TypeArchive>
{
// Live notification registrations, keyed by the user's TypeArchiveNotification instance. Each
// entry roots its native callback delegates and struct for the registration lifetime.
Expand Down
113 changes: 113 additions & 0 deletions Handle/BNTypeArchiveTransactions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;

namespace BinaryNinja
{
/// <summary>
/// Performs archive mutations in a new snapshot transaction.
/// </summary>
/// <param name="snapshotId">Identifier reserved for the new snapshot.</param>
public delegate void TypeArchiveSnapshotTransaction(string snapshotId);

public sealed partial class TypeArchive
{
[UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeSnapshotTransaction(
IntPtr context,
[MarshalAs(UnmanagedType.LPUTF8Str)] string snapshotId);

private sealed class SnapshotTransactionContext
{
private readonly TypeArchiveSnapshotTransaction transaction;
private ExceptionDispatchInfo? exception;

internal SnapshotTransactionContext(TypeArchiveSnapshotTransaction transaction)
{
this.transaction = transaction;
}

internal bool Invoke(IntPtr context, string snapshotId)
{
try
{
this.transaction(snapshotId);
return true;
}
catch (Exception caught)
{
this.exception = ExceptionDispatchInfo.Capture(caught);
return false;
}
}

internal void ThrowIfFailed()
{
if (null != this.exception)
{
this.exception.Throw();
}
}
}

/// <summary>
/// Runs archive mutations atomically and creates a new snapshot when they succeed.
/// </summary>
/// <param name="transaction">Mutations to perform using the reserved snapshot identifier.</param>
/// <param name="parents">Parent snapshot identifiers for the new snapshot.</param>
/// <returns>The committed snapshot identifier.</returns>
public string NewSnapshotTransaction(
TypeArchiveSnapshotTransaction transaction,
string[] parents)
{
if (null == transaction)
{
throw new ArgumentNullException(nameof(transaction));
}

if (null == parents)
{
throw new ArgumentNullException(nameof(parents));
}

for (int i = 0; i < parents.Length; i++)
{
if (null == parents[i])
{
throw new ArgumentException("Snapshot parents cannot contain null entries.", nameof(parents));
}
}

SnapshotTransactionContext transactionContext =
new SnapshotTransactionContext(transaction);
NativeSnapshotTransaction nativeTransaction = transactionContext.Invoke;
IntPtr result;

using (ScopedAllocator allocator = new ScopedAllocator())
{
try
{
result = NativeMethods.BNTypeArchiveNewSnapshotTransaction(
this.handle,
Marshal.GetFunctionPointerForDelegate<NativeSnapshotTransaction>(nativeTransaction),
IntPtr.Zero,
allocator.AllocUtf8StringArray(parents),
(ulong)parents.Length);
}
finally
{
GC.KeepAlive(nativeTransaction);
}
}

transactionContext.ThrowIfFailed();
if (IntPtr.Zero == result)
{
throw new InvalidOperationException("BNTypeArchiveNewSnapshotTransaction failed.");
}

return UnsafeUtils.TakeUtf8String(result);
}
}
}
6 changes: 1 addition & 5 deletions Misc/CoreUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1449,14 +1449,10 @@ public static unsafe string[] ParseTypeParserOptionsText(string optionsText)
// TODO: BNPerformCustomRequest / BNPerformDownloadRequest — on DownloadInstance,
// requires callback context parameters for progress/completion notifications.

// TODO: BNTypeArchiveMergeSnapshots / BNTypeArchiveNewSnapshotTransaction —
// callback-based transaction functions requiring managed delegate infrastructure.
// TODO: BNTypeArchiveMergeSnapshots requires conflict-map and progress callback marshalling.

// NOTE: BNReadSnapshotDataWithProgress — implemented on Snapshot class as ReadDataWithProgress().

// TODO: BNResolveStructureMemberOrBaseMember — on Structure, requires callback
// context (void* callbackContext, void** resolveFunc) for member resolution.

// TODO: BNComponentsNotEqual — skip, handled by AbstractSafeHandle operators (== and !=).

// TODO: BNRepositoryFreePluginDirectoryList — internal free function, not a wrapper target.
Expand Down
Loading