using System;

// namespace System.Antimalware
namespace Win32
{
	extension Win32
	{
		// --- Typedefs ---
		
		public typealias HAMSICONTEXT = int;
		public typealias HAMSISESSION = int;
		
		// --- Enums ---
		
		public enum AMSI_RESULT : int32
		{
			CLEAN = 0,
			NOT_DETECTED = 1,
			BLOCKED_BY_ADMIN_START = 16384,
			BLOCKED_BY_ADMIN_END = 20479,
			DETECTED = 32768,
		}
		public enum AMSI_ATTRIBUTE : int32
		{
			APP_NAME = 0,
			CONTENT_NAME = 1,
			CONTENT_SIZE = 2,
			CONTENT_ADDRESS = 3,
			SESSION = 4,
			REDIRECT_CHAIN_SIZE = 5,
			REDIRECT_CHAIN_ADDRESS = 6,
			ALL_SIZE = 7,
			ALL_ADDRESS = 8,
			QUIET = 9,
		}
		public enum AMSI_UAC_REQUEST_TYPE : int32
		{
			EXE = 0,
			COM = 1,
			MSI = 2,
			AX = 3,
			PACKAGED_APP = 4,
			MAX = 5,
		}
		public enum AMSI_UAC_TRUST_STATE : int32
		{
			TRUSTED = 0,
			UNTRUSTED = 1,
			BLOCKED = 2,
			MAX = 3,
		}
		public enum AMSI_UAC_MSI_ACTION : int32
		{
			INSTALL = 0,
			UNINSTALL = 1,
			UPDATE = 2,
			MAINTENANCE = 3,
			MAX = 4,
		}
		
		// --- Structs ---
		
		[CRepr]
		public struct AMSI_UAC_REQUEST_EXE_INFO
		{
			public uint32 ulLength;
			public PWSTR lpwszApplicationName;
			public PWSTR lpwszCommandLine;
			public PWSTR lpwszDLLParameter;
		}
		[CRepr]
		public struct AMSI_UAC_REQUEST_COM_INFO
		{
			public uint32 ulLength;
			public PWSTR lpwszServerBinary;
			public PWSTR lpwszRequestor;
			public Guid Clsid;
		}
		[CRepr]
		public struct AMSI_UAC_REQUEST_MSI_INFO
		{
			public uint32 ulLength;
			public AMSI_UAC_MSI_ACTION MsiAction;
			public PWSTR lpwszProductName;
			public PWSTR lpwszVersion;
			public PWSTR lpwszLanguage;
			public PWSTR lpwszManufacturer;
			public PWSTR lpwszPackagePath;
			public PWSTR lpwszPackageSource;
			public uint32 ulUpdates;
			public PWSTR* ppwszUpdates;
			public PWSTR* ppwszUpdateSources;
		}
		[CRepr]
		public struct AMSI_UAC_REQUEST_AX_INFO
		{
			public uint32 ulLength;
			public PWSTR lpwszLocalInstallPath;
			public PWSTR lpwszSourceURL;
		}
		[CRepr]
		public struct AMSI_UAC_REQUEST_PACKAGED_APP_INFO
		{
			public uint32 ulLength;
			public PWSTR lpwszApplicationName;
			public PWSTR lpwszCommandLine;
			public PWSTR lpPackageFamilyName;
			public PWSTR lpApplicationId;
		}
		[CRepr]
		public struct AMSI_UAC_REQUEST_CONTEXT
		{
			public uint32 ulLength;
			public uint32 ulRequestorProcessId;
			public AMSI_UAC_TRUST_STATE UACTrustState;
			public AMSI_UAC_REQUEST_TYPE Type;
			public _RequestType_e__Union RequestType;
			public BOOL bAutoElevateRequest;
			
			[CRepr, Union]
			public struct _RequestType_e__Union
			{
				public AMSI_UAC_REQUEST_EXE_INFO ExeInfo;
				public AMSI_UAC_REQUEST_COM_INFO ComInfo;
				public AMSI_UAC_REQUEST_MSI_INFO MsiInfo;
				public AMSI_UAC_REQUEST_AX_INFO ActiveXInfo;
				public AMSI_UAC_REQUEST_PACKAGED_APP_INFO PackagedAppInfo;
			}
		}
		
		// --- COM Class IDs ---
		
		public const Guid CLSID_CAntimalware = .(0xfdb00e52, 0xa214, 0x4aa1, 0x8f, 0xba, 0x43, 0x57, 0xbb, 0x00, 0x72, 0xec);
		
		// --- COM Interfaces ---
		
		[CRepr]
		public struct IAmsiStream : IUnknown
		{
			public const new Guid IID = .(0x3e47f2e5, 0x81d4, 0x4d3b, 0x89, 0x7f, 0x54, 0x50, 0x96, 0x77, 0x03, 0x73);
			
			public new VTable* VT { get => (.)vt; }
			
			public HRESULT GetAttribute(AMSI_ATTRIBUTE attribute, uint32 dataSize, uint8* data, out uint32 retData) mut => VT.GetAttribute(ref this, attribute, dataSize, data, out retData);
			public HRESULT Read(uint64 position, uint32 size, uint8* buffer, out uint32 readSize) mut => VT.Read(ref this, position, size, buffer, out readSize);

			[CRepr]
			public struct VTable : IUnknown.VTable
			{
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAmsiStream self, AMSI_ATTRIBUTE attribute, uint32 dataSize, uint8* data, out uint32 retData) GetAttribute;
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAmsiStream self, uint64 position, uint32 size, uint8* buffer, out uint32 readSize) Read;
			}
		}
		[CRepr]
		public struct IAntimalwareProvider : IUnknown
		{
			public const new Guid IID = .(0xb2cabfe3, 0xfe04, 0x42b1, 0xa5, 0xdf, 0x08, 0xd4, 0x83, 0xd4, 0xd1, 0x25);
			
			public new VTable* VT { get => (.)vt; }
			
			public HRESULT Scan(ref IAmsiStream stream, out AMSI_RESULT result) mut => VT.Scan(ref this, ref stream, out result);
			public void CloseSession(uint64 session) mut => VT.CloseSession(ref this, session);
			public HRESULT DisplayName(out PWSTR displayName) mut => VT.DisplayName(ref this, out displayName);

			[CRepr]
			public struct VTable : IUnknown.VTable
			{
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAntimalwareProvider self, ref IAmsiStream stream, out AMSI_RESULT result) Scan;
				public new function [CallingConvention(.Stdcall)] void(ref IAntimalwareProvider self, uint64 session) CloseSession;
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAntimalwareProvider self, out PWSTR displayName) DisplayName;
			}
		}
		[CRepr]
		public struct IAntimalwareUacProvider : IUnknown
		{
			public const new Guid IID = .(0xb2cabfe4, 0xfe04, 0x42b1, 0xa5, 0xdf, 0x08, 0xd4, 0x83, 0xd4, 0xd1, 0x25);
			
			public new VTable* VT { get => (.)vt; }
			
			public HRESULT UacScan(ref AMSI_UAC_REQUEST_CONTEXT context, out AMSI_RESULT result) mut => VT.UacScan(ref this, ref context, out result);
			public HRESULT DisplayName(out PWSTR displayName) mut => VT.DisplayName(ref this, out displayName);

			[CRepr]
			public struct VTable : IUnknown.VTable
			{
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAntimalwareUacProvider self, ref AMSI_UAC_REQUEST_CONTEXT context, out AMSI_RESULT result) UacScan;
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAntimalwareUacProvider self, out PWSTR displayName) DisplayName;
			}
		}
		[CRepr]
		public struct IAntimalwareProvider2 : IAntimalwareProvider
		{
			public const new Guid IID = .(0x7c1e6570, 0x3f73, 0x4e0f, 0x8a, 0xd4, 0x98, 0xb9, 0x4c, 0xd3, 0x29, 0x0f);
			
			public new VTable* VT { get => (.)vt; }
			
			public HRESULT Notify(void* buffer, uint32 length, PWSTR contentName, PWSTR appName, out AMSI_RESULT pResult) mut => VT.Notify(ref this, buffer, length, contentName, appName, out pResult);

			[CRepr]
			public struct VTable : IAntimalwareProvider.VTable
			{
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAntimalwareProvider2 self, void* buffer, uint32 length, PWSTR contentName, PWSTR appName, out AMSI_RESULT pResult) Notify;
			}
		}
		[CRepr]
		public struct IAntimalware : IUnknown
		{
			public const new Guid IID = .(0x82d29c2e, 0xf062, 0x44e6, 0xb5, 0xc9, 0x3d, 0x9a, 0x2f, 0x24, 0xa2, 0xdf);
			
			public new VTable* VT { get => (.)vt; }
			
			public HRESULT Scan(ref IAmsiStream stream, out AMSI_RESULT result, out IAntimalwareProvider* provider) mut => VT.Scan(ref this, ref stream, out result, out provider);
			public void CloseSession(uint64 session) mut => VT.CloseSession(ref this, session);

			[CRepr]
			public struct VTable : IUnknown.VTable
			{
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAntimalware self, ref IAmsiStream stream, out AMSI_RESULT result, out IAntimalwareProvider* provider) Scan;
				public new function [CallingConvention(.Stdcall)] void(ref IAntimalware self, uint64 session) CloseSession;
			}
		}
		[CRepr]
		public struct IAntimalware2 : IAntimalware
		{
			public const new Guid IID = .(0x301035b5, 0x2d42, 0x4f56, 0x8c, 0x65, 0x2d, 0xca, 0xa7, 0xfb, 0x3c, 0xdc);
			
			public new VTable* VT { get => (.)vt; }
			
			public HRESULT Notify(void* buffer, uint32 length, PWSTR contentName, PWSTR appName, out AMSI_RESULT pResult) mut => VT.Notify(ref this, buffer, length, contentName, appName, out pResult);

			[CRepr]
			public struct VTable : IAntimalware.VTable
			{
				public new function [CallingConvention(.Stdcall)] HRESULT(ref IAntimalware2 self, void* buffer, uint32 length, PWSTR contentName, PWSTR appName, out AMSI_RESULT pResult) Notify;
			}
		}
		
		// --- Functions ---
		
		[Import("amsi.dll"), CLink, CallingConvention(.Stdcall)]
		public static extern HRESULT AmsiInitialize(PWSTR appName, out HAMSICONTEXT amsiContext);
		[Import("amsi.dll"), CLink, CallingConvention(.Stdcall)]
		public static extern void AmsiUninitialize(HAMSICONTEXT amsiContext);
		[Import("amsi.dll"), CLink, CallingConvention(.Stdcall)]
		public static extern HRESULT AmsiOpenSession(HAMSICONTEXT amsiContext, out HAMSISESSION amsiSession);
		[Import("amsi.dll"), CLink, CallingConvention(.Stdcall)]
		public static extern void AmsiCloseSession(HAMSICONTEXT amsiContext, HAMSISESSION amsiSession);
		[Import("amsi.dll"), CLink, CallingConvention(.Stdcall)]
		public static extern HRESULT AmsiScanBuffer(HAMSICONTEXT amsiContext, void* buffer, uint32 length, PWSTR contentName, HAMSISESSION amsiSession, out AMSI_RESULT result);
		[Import("amsi.dll"), CLink, CallingConvention(.Stdcall)]
		public static extern HRESULT AmsiNotifyOperation(HAMSICONTEXT amsiContext, void* buffer, uint32 length, PWSTR contentName, out AMSI_RESULT result);
		[Import("amsi.dll"), CLink, CallingConvention(.Stdcall)]
		public static extern HRESULT AmsiScanString(HAMSICONTEXT amsiContext, PWSTR string, PWSTR contentName, HAMSISESSION amsiSession, out AMSI_RESULT result);
		[Import("kernel32.lib"), CLink, CallingConvention(.Stdcall)]
		public static extern BOOL InstallELAMCertificateInfo(HANDLE ELAMFile);
	}
}
