mirror of https://github.com/dahall/Vanara.git
Added nullability to AMSI
parent
708e778a35
commit
4f00c9c357
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Vanara.Extensions;
|
||||
using Vanara.InteropServices;
|
||||
|
||||
namespace Vanara.PInvoke;
|
||||
|
||||
|
@ -548,14 +544,14 @@ public static partial class AMSI
|
|||
/// <summary>Initializes a new instance of the <see cref="AmsiStream"/> class and inserts the contents of a buffer.</summary>
|
||||
/// <param name="buffer">The buffer to copy.</param>
|
||||
/// <param name="writable">if set to <see langword="true"/>, the stream is read-write; if <see langword="false"/>, it is read-only.</param>
|
||||
public AmsiStream(byte[] buffer, bool writable) : base(new SafeCoTaskMemHandle(buffer), access: writable ? FileAccess.ReadWrite : FileAccess.Read)
|
||||
public AmsiStream(byte[]? buffer, bool writable) : base(buffer is null ? SafeCoTaskMemHandle.Null : new SafeCoTaskMemHandle(buffer), access: writable ? FileAccess.ReadWrite : FileAccess.Read)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AmsiStream"/> class with file information.</summary>
|
||||
/// <param name="file">The file information.</param>
|
||||
/// <param name="writable">if set to <see langword="true"/>, the stream is read-write; if <see langword="false"/>, it is read-only.</param>
|
||||
public AmsiStream(FileInfo file, bool writable) : this(file is null ? null : File.ReadAllBytes(file.FullName), writable) => ContentName = file.FullName;
|
||||
public AmsiStream(FileInfo? file, bool writable) : this(file is null ? null : File.ReadAllBytes(file.FullName), writable) => ContentName = file?.FullName;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AmsiStream"/> class.</summary>
|
||||
/// <param name="mem">The memory allocator used to create and extend the native memory.</param>
|
||||
|
@ -565,10 +561,10 @@ public static partial class AMSI
|
|||
}
|
||||
|
||||
/// <summary>Gets or sets the name, version, or GUID string of the calling application.</summary>
|
||||
public string AppName { get; set; }
|
||||
public string? AppName { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the filename, URL, unique script ID, or similar of the content.</summary>
|
||||
public string ContentName { get; set; }
|
||||
public string? ContentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session is used to associate different scan calls, such as if the contents to be scanned belong to the
|
||||
|
@ -578,10 +574,10 @@ public static partial class AMSI
|
|||
|
||||
HRESULT IAmsiStream.GetAttribute(AMSI_ATTRIBUTE attribute, uint dataSize, IntPtr data, out uint retData)
|
||||
{
|
||||
byte[] bytes = attribute switch
|
||||
byte[]? bytes = attribute switch
|
||||
{
|
||||
AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_APP_NAME => StringHelper.GetBytes(AppName, true, CharSet.Unicode),
|
||||
AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_CONTENT_NAME => StringHelper.GetBytes(ContentName, true, CharSet.Unicode),
|
||||
AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_APP_NAME => AppName is null ? null : StringHelper.GetBytes(AppName, true, CharSet.Unicode),
|
||||
AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_CONTENT_NAME => ContentName is null ? null : StringHelper.GetBytes(ContentName, true, CharSet.Unicode),
|
||||
AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_CONTENT_SIZE => BitConverter.GetBytes((ulong)Length),
|
||||
AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_CONTENT_ADDRESS => IntPtr.Size == 8 ? BitConverter.GetBytes(Pointer.ToInt64()) : BitConverter.GetBytes(Pointer.ToInt32()),
|
||||
AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_SESSION => IntPtr.Size == 8 ? BitConverter.GetBytes(Session.ToInt64()) : BitConverter.GetBytes(Session.ToInt32()),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Vanara.PInvoke;
|
||||
|
||||
|
@ -265,7 +264,7 @@ public static partial class AMSI
|
|||
public static bool operator ==(HAMSICONTEXT h1, HAMSICONTEXT h2) => h1.handle == h2.handle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj) => (obj is IHandle h && handle == h.DangerousGetHandle()) || (obj is IntPtr p && handle == p);
|
||||
public override bool Equals(object? obj) => obj is IHandle h && handle == h.DangerousGetHandle() || obj is IntPtr p && handle == p;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => handle.GetHashCode();
|
||||
|
@ -313,7 +312,7 @@ public static partial class AMSI
|
|||
public static bool operator ==(HAMSISESSION h1, HAMSISESSION h2) => h1.handle == h2.handle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj) => (obj is IHandle h && handle == h.DangerousGetHandle()) || (obj is IntPtr p && handle == p);
|
||||
public override bool Equals(object? obj) => obj is IHandle h && handle == h.DangerousGetHandle() || obj is IntPtr p && handle == p;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => handle.GetHashCode();
|
||||
|
@ -340,6 +339,9 @@ public static partial class AMSI
|
|||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator HAMSICONTEXT(SafeHAMSICONTEXT h) => h.handle;
|
||||
|
||||
/// <summary>Represents a NULL handle.</summary>
|
||||
public static readonly SafeHAMSICONTEXT Null = new(IntPtr.Zero, false);
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool InternalReleaseHandle() { AmsiUninitialize(handle); return true; }
|
||||
}
|
||||
|
@ -354,11 +356,11 @@ public static partial class AMSI
|
|||
/// <param name="ownsHandle">
|
||||
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||
/// </param>
|
||||
public SafeHAMSISESSION(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||
public SafeHAMSISESSION(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) => ctx = SafeHAMSICONTEXT.Null;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="SafeHAMSISESSION"/> class.</summary>
|
||||
/// <param name="context">The context.</param>
|
||||
public SafeHAMSISESSION(HAMSICONTEXT context) : base() => Open(Context = context);
|
||||
public SafeHAMSISESSION(HAMSICONTEXT context) : base() => Open(ctx = new(context.DangerousGetHandle(), false));
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="SafeHAMSISESSION"/> class.</summary>
|
||||
/// <param name="appName">The name, version, or GUID string of the app calling the AMSI API.</param>
|
||||
|
@ -369,7 +371,7 @@ public static partial class AMSI
|
|||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="SafeHAMSISESSION"/> class.</summary>
|
||||
private SafeHAMSISESSION() : base() { }
|
||||
private SafeHAMSISESSION() : base() => ctx = SafeHAMSICONTEXT.Null;
|
||||
|
||||
/// <summary>Gets or sets the handle of type HAMSICONTEXT that was initially received from AmsiInitialize.</summary>
|
||||
/// <value>The context handle.</value>
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Vanara.InteropServices;
|
||||
using static Vanara.PInvoke.AMSI;
|
||||
|
||||
namespace Vanara.PInvoke.Tests;
|
||||
|
@ -68,10 +65,10 @@ public class AMSITests
|
|||
{
|
||||
var fn = TestCaseSources.BmpFile;
|
||||
var app = "MyTestApp";
|
||||
AmsiStream str = null;
|
||||
AmsiStream? str = null;
|
||||
Assert.That(() => str = new(new FileInfo(fn), false) { AppName = app }, Throws.Nothing);
|
||||
|
||||
var istr = str as IAmsiStream;
|
||||
var istr = (IAmsiStream)str!;
|
||||
using var mem = new SafeCoTaskMemHandle(2048);
|
||||
|
||||
Assert.That(istr.GetAttribute(AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_APP_NAME, mem.Size, mem, out var sz), ResultIs.Successful);
|
||||
|
@ -82,7 +79,7 @@ public class AMSITests
|
|||
|
||||
Assert.That(istr.GetAttribute(AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_CONTENT_SIZE, mem.Size, mem, out sz), ResultIs.Successful);
|
||||
Assert.That(sz, Is.EqualTo(sizeof(ulong)));
|
||||
Assert.That(mem.ToStructure<ulong>(), Is.EqualTo((ulong)str.Length));
|
||||
Assert.That(mem.ToStructure<ulong>(), Is.EqualTo((ulong)str!.Length));
|
||||
|
||||
Assert.That(istr.GetAttribute(AMSI_ATTRIBUTE.AMSI_ATTRIBUTE_CONTENT_ADDRESS, mem.Size, mem, out sz), ResultIs.Successful);
|
||||
Assert.That(sz, Is.EqualTo(IntPtr.Size));
|
||||
|
@ -98,11 +95,11 @@ public class AMSITests
|
|||
{
|
||||
var fn = TestCaseSources.BmpFile;
|
||||
var app = "MyTestApp";
|
||||
AmsiStream str = null;
|
||||
AmsiStream? str = null;
|
||||
Assert.That(() => str = new(new FileInfo(fn), false) { AppName = app }, Throws.Nothing);
|
||||
|
||||
IAntimalware2 iam = new();
|
||||
Assert.That(iam.Scan(str, out var res, out var prov), ResultIs.Successful);
|
||||
Assert.That(iam.Scan(str!, out var res, out var prov), ResultIs.Successful);
|
||||
TestContext.WriteLine(res);
|
||||
Assert.That(prov.DisplayName(out var pname), ResultIs.Successful);
|
||||
TestContext.WriteLine(pname);
|
||||
|
|
Loading…
Reference in New Issue