using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Vanara.Extensions;
using Vanara.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG;

namespace Vanara.PInvoke
{
	public static partial class Ole32
	{
		/// <summary>
		/// The <c>ILockBytes</c> interface is implemented on a byte array object that is backed by some physical storage, such as a disk
		/// file, global memory, or a database. It is used by a COM compound file storage object to give its root storage access to the
		/// physical device, while isolating the root storage from the details of accessing the physical storage.
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nn-objidl-ilockbytes
		[PInvokeData("objidl.h", MSDNShortId = "bb2c5d0d-8dc8-4844-9a20-ef8e4def5731")]
		[ComImport, Guid("0000000a-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface ILockBytes
		{
			/// <summary>
			/// The <c>ReadAt</c> method reads a specified number of bytes starting at a specified offset from the beginning of the byte
			/// array object.
			/// </summary>
			/// <param name="ulOffset">Specifies the starting point from the beginning of the byte array for reading data.</param>
			/// <param name="pv">Pointer to the buffer into which the byte array is read. The size of this buffer is contained in cb.</param>
			/// <param name="cb">Specifies the number of bytes of data to attempt to read from the byte array.</param>
			/// <param name="pcbRead">
			/// Pointer to a <c>ULONG</c> where this method writes the actual number of bytes read from the byte array. You can set this
			/// pointer to <c>NULL</c> to indicate that you are not interested in this value. In this case, this method does not provide the
			/// actual number of bytes that were read.
			/// </param>
			/// <remarks>
			/// <para>
			/// <c>ILockBytes::ReadAt</c> reads bytes from the byte array object. It reports the number of bytes that were actually read.
			/// This value may be less than the number of bytes requested if an error occurs or if the end of the byte array is reached
			/// during the read.
			/// </para>
			/// <para>
			/// It is not an error to read less than the specified number of bytes if the operation encounters the end of the byte array.
			/// Note that this is the same end-of-file behavior as found in MS-DOS file allocation table (FAT) file system files.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ilockbytes-readat HRESULT ReadAt( ULARGE_INTEGER
			// ulOffset, void *pv, ULONG cb, ULONG *pcbRead );
			[PInvokeData("objidl.h", MSDNShortId = "0478d6f0-65c4-445b-946a-692f2373e8f1")]
			void ReadAt(ulong ulOffset, [Out] IntPtr pv, uint cb, out uint pcbRead);

			/// <summary>
			/// The <c>WriteAt</c> method writes the specified number of bytes starting at a specified offset from the beginning of the byte array.
			/// </summary>
			/// <param name="ulOffset">Specifies the starting point from the beginning of the byte array for the data to be written.</param>
			/// <param name="pv">Pointer to the buffer containing the data to be written.</param>
			/// <param name="cb">Specifies the number of bytes of data to attempt to write into the byte array.</param>
			/// <param name="pcbWritten">
			/// Pointer to a location where this method specifies the actual number of bytes written to the byte array. You can set this
			/// pointer to <c>NULL</c> to indicate that you are not interested in this value. In this case, this method does not provide the
			/// actual number of bytes written.
			/// </param>
			/// <remarks>
			/// <para>
			/// <c>ILockBytes::WriteAt</c> writes the specified data at the specified location in the byte array. The number of bytes
			/// actually written must always be returned in pcbWritten, even if an error is returned. If the byte count is zero bytes, the
			/// write operation has no effect.
			/// </para>
			/// <para>
			/// If ulOffset is past the end of the byte array and cb is greater than zero, <c>ILockBytes::WriteAt</c> increases the size of
			/// the byte array. The fill bytes written to the byte array are not initialized to any particular value.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ilockbytes-writeat HRESULT WriteAt( ULARGE_INTEGER
			// ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten );
			[PInvokeData("objidl.h", MSDNShortId = "a27af4e1-293d-438a-8068-87275a51fd48")]
			void WriteAt(ulong ulOffset, [In] IntPtr pv, uint cb, out uint pcbWritten);

			/// <summary>
			/// The <c>Flush</c> method ensures that any internal buffers maintained by the ILockBytes implementation are written out to the
			/// underlying physical storage.
			/// </summary>
			/// <remarks>
			/// <para><c>ILockBytes::Flush</c> flushes internal buffers to the underlying storage device.</para>
			/// <para>
			/// The COM-provided implementation of compound files calls this method during a transacted commit operation to provide a
			/// two-phase commit process that protects against loss of data.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ilockbytes-flush HRESULT Flush( );
			[PInvokeData("objidl.h", MSDNShortId = "9396c44f-ad76-49f4-9796-d29570466a27")]
			void Flush();

			/// <summary>The <c>SetSize</c> method changes the size of the byte array.</summary>
			/// <param name="cb">Specifies the new size of the byte array as a number of bytes.</param>
			/// <remarks>
			/// <para>
			/// <c>ILockBytes::SetSize</c> changes the size of the byte array. If the cb parameter is larger than the current byte array, the
			/// byte array is extended to the indicated size by filling the intervening space with bytes of undefined value, as does
			/// ILockBytes::WriteAt, if the seek pointer is past the current end-of-stream.
			/// </para>
			/// <para>If the cb parameter is smaller than the current byte array, the byte array is truncated to the indicated size.</para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// Callers cannot rely on STG_E_MEDIUMFULL being returned at the appropriate time because of cache buffering in the operating
			/// system or network. However, callers must be able to deal with this return code because some ILockBytes implementations might
			/// support it.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ilockbytes-setsize HRESULT SetSize( ULARGE_INTEGER cb );
			[PInvokeData("objidl.h", MSDNShortId = "13b3237b-d113-4505-b397-b06916368fef")]
			void SetSize(ulong cb);

			/// <summary>The <c>LockRegion</c> method restricts access to a specified range of bytes in the byte array.</summary>
			/// <param name="libOffset">Specifies the byte offset for the beginning of the range.</param>
			/// <param name="cb">Specifies, in bytes, the length of the range to be restricted.</param>
			/// <param name="dwLockType">
			/// Specifies the type of restrictions being requested on accessing the range. This parameter uses one of the values from the
			/// LOCKTYPE enumeration.
			/// </param>
			/// <remarks>
			/// <para>
			/// <c>ILockBytes::LockRegion</c> restricts access to the specified range of bytes. Once a region is locked, attempts by others
			/// to gain access to the restricted range must fail with the STG_E_ACCESSDENIED error.
			/// </para>
			/// <para>
			/// The byte range can extend past the current end of the byte array. Locking beyond the end of an array is useful as a method of
			/// communication between different instances of the byte array object without changing data that is actually part of the byte
			/// array. For example, an implementation of ILockBytes for compound files could rely on locking past the current end of the
			/// array as a means of access control, using specific locked regions to indicate permissions currently granted.
			/// </para>
			/// <para>
			/// The dwLockType parameter specifies one of three types of locking, using values from the LOCKTYPE enumeration. The types are
			/// as follows: locking to exclude other writers, locking to exclude other readers or writers, and locking that allows only one
			/// requester to obtain a lock on the given range. This third type of locking is usually an alias for one of the other two lock
			/// types, and permits an Implementer to add other behavior as well. A given byte array might support either of the first two
			/// types, or both.
			/// </para>
			/// <para>
			/// To determine the lock types supported by a particular ILockBytes implementation, you can examine the <c>grfLocksSupported</c>
			/// member of the STATSTG structure returned by a call to ILockBytes::Stat.
			/// </para>
			/// <para>
			/// Any region locked with <c>ILockBytes::LockRegion</c> must later be explicitly unlocked by calling ILockBytes::UnlockRegion
			/// with exactly the same values for the libOffset, cb, and dwLockType parameters. The region must be unlocked before the stream
			/// is released. Two adjacent regions cannot be locked separately and then unlocked with a single unlock call.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// Since the type of locking supported is optional and can vary in different implementations of ILockBytes, you must provide
			/// code to deal with the STG_E_INVALIDFUNCTION error.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// Support for this method depends on how the storage object built on top of the ILockBytes implementation is used. If you know
			/// that only one storage object at any given time can be opened on the storage device that underlies the byte array, then your
			/// <c>ILockBytes</c> implementation does not need to support locking. However, if multiple simultaneous openings of a storage
			/// object are possible, then region locking is needed to coordinate them.
			/// </para>
			/// <para>
			/// A <c>LockRegion</c> implementation can choose to support all, some, or none of the lock types. For unsupported lock types,
			/// the implementation should return STG_E_INVALIDFUNCTION.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ilockbytes-lockregion HRESULT LockRegion( ULARGE_INTEGER
			// libOffset, ULARGE_INTEGER cb, DWORD dwLockType );
			[PInvokeData("objidl.h", MSDNShortId = "cea59e2a-99d8-472d-8e4f-2e2474789c20")]
			void LockRegion(ulong libOffset, ulong cb, LOCKTYPE dwLockType);

			/// <summary>The <c>UnlockRegion</c> method removes the access restriction on a previously locked range of bytes.</summary>
			/// <param name="libOffset">Specifies the byte offset for the beginning of the range.</param>
			/// <param name="cb">Specifies, in bytes, the length of the range that is restricted.</param>
			/// <param name="dwLockType">
			/// Specifies the type of access restrictions previously placed on the range. This parameter uses a value from the LOCKTYPE enumeration.
			/// </param>
			/// <remarks>
			/// <c>ILockBytes::UnlockRegion</c> unlocks a region previously locked with a call to ILockBytes::LockRegion. Each region locked
			/// must be explicitly unlocked, using the same values for the libOffset, cb, and dwLockType parameters as in the matching calls
			/// to <c>ILockBytes::LockRegion</c>. Two adjacent regions cannot be locked separately and then unlocked with a single unlock call.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ilockbytes-unlockregion HRESULT UnlockRegion(
			// ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType );
			[PInvokeData("objidl.h", MSDNShortId = "036ba242-8630-4013-860d-dd37919253be")]
			void UnlockRegion(ulong libOffset, ulong cb, LOCKTYPE dwLockType);

			/// <summary>The <c>Stat</c> method retrieves a STATSTG structure containing information for this byte array object.</summary>
			/// <param name="pstatstg">
			/// Pointer to a STATSTG structure in which this method places information about this byte array object. The pointer is
			/// <c>NULL</c> if an error occurs.
			/// </param>
			/// <param name="grfStatFlag">
			/// Specifies whether this method should supply the <c>pwcsName</c> member of the STATSTG structure through values taken from the
			/// STATFLAG enumeration. If the STATFLAG_NONAME is specified, the <c>pwcsName</c> member of <c>STATSTG</c> is not supplied, thus
			/// saving a memory-allocation operation. The other possible value, STATFLAG_DEFAULT, indicates that all members of the
			/// <c>STATSTG</c> structure be supplied.
			/// </param>
			/// <remarks><c>ILockBytes::Stat</c> should supply information about the byte array object in a STATSTG structure.</remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ilockbytes-stat HRESULT Stat( STATSTG *pstatstg, DWORD
			// grfStatFlag );
			[PInvokeData("objidl.h", MSDNShortId = "e7953f21-ac34-44e3-9b6f-b93ac89e2e32")]
			void Stat(out STATSTG pstatstg, STATFLAG grfStatFlag);
		}

		/// <summary>
		/// Enables application developers to monitor (spy on) memory allocation, detect memory leaks, and simulate memory failure in calls
		/// to IMalloc methods.
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-imallocspy
		[PInvokeData("objidl.h", MSDNShortId = "8ba500f7-c070-4788-b7fe-58b6a4e6a94c")]
		[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000001d-0000-0000-C000-000000000046")]
		public interface IMallocSpy
		{
			/// <summary>Performs operations required before calling IMalloc::Alloc.</summary>
			/// <param name="cbRequest">The number of bytes specified in the allocation request the caller is passing to Alloc.</param>
			/// <returns>The number of bytes specified in the call to Alloc, which can be greater than or equal to the value of cbRequest.</returns>
			/// <remarks>
			/// <para>
			/// The <c>PreAlloc</c> implementation may extend and/or modify the allocation to store debug-specific information with the allocation.
			/// </para>
			/// <para>
			/// <c>PreAlloc</c> can force memory allocation failure by returning 0, allowing testing to ensure that the application handles
			/// allocation failure gracefully in all cases. In this case, IMallocSpy::PostAlloc is not called and Alloc returns <c>NULL</c>.
			/// Forcing allocation failure is effective only if cbRequest is not equal to 0. If <c>PreAlloc</c> is forcing failure by
			/// returning <c>NULL</c>, <c>PostAlloc</c> is not called. However, <c>Alloc</c> encounters a real memory failure and returns
			/// <c>NULL</c>, <c>PostAlloc</c> is called.
			/// </para>
			/// <para>The call to <c>PreAlloc</c> through the return from PostAlloc is guaranteed to be thread-safe.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-prealloc SIZE_T PreAlloc( SIZE_T cbRequest );
			[PreserveSig]
			SizeT PreAlloc(SizeT cbRequest);

			/// <summary>Performs operations required after calling IMalloc::Alloc.</summary>
			/// <param name="pActual">The pointer returned from Alloc.</param>
			/// <returns>
			/// This method returns a pointer to the beginning of the block of memory actually allocated. This pointer is also returned to
			/// the caller of Alloc. If debug information is written at the front of the caller's allocation, this should be a forward offset
			/// from pActual. The value is the same as pActual if debug information is appended or if no debug information is attached.
			/// </returns>
			/// <remarks>
			/// When a spy object implementing IMallocSpy is registered using the CoRegisterMallocSpy function, COM calls <c>PostAlloc</c>
			/// after any call to Alloc. It takes as input a pointer to the allocation done by the call to <c>Alloc</c>, and returns a
			/// pointer to the beginning of the total allocation, which could include a forward offset from the other value if
			/// IMallocSpy::PreAlloc was implemented to attach debug information to the allocation in this way. If not, the same pointer is
			/// returned and also becomes the return value to the caller of <c>Alloc</c>.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-postalloc void * PostAlloc( void *pActual );
			[PreserveSig]
			IntPtr PostAlloc(IntPtr pActual);

			/// <summary>
			/// Performs operations required before calling IMalloc::Free. This method ensures that the pointer passed to <c>Free</c> points
			/// to the beginning of the actual allocation.
			/// </summary>
			/// <param name="pRequest">A pointer to the block of memory that the caller is passing to Free.</param>
			/// <param name="fSpyed">Indicates whether the block of memory to be freed was allocated while the current spy was active.</param>
			/// <returns>The value to be passed to IMalloc::Free.</returns>
			/// <remarks>
			/// If IMallocSpy::PreAlloc modified the original allocation request passed to IMalloc::Alloc (or IMalloc::Realloc),
			/// <c>PreFree</c> must supply a pointer to the actual allocation, which COM will pass to IMalloc::Free. For example, if the
			/// <c>PreAlloc</c>/PostAlloc pair attached a header used to store debug information to the beginning of the caller's allocation,
			/// <c>PreFree</c> must return a pointer to the beginning of this header so that all of the block that was allocated can be freed.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-prefree void * PreFree( void *pRequest, BOOL
			// fSpyed );
			IntPtr PreFree(IntPtr pRequest, [MarshalAs(UnmanagedType.Bool)] bool fSpyed);

			/// <summary>Performs operations required after calling IMalloc::Free.</summary>
			/// <param name="fSpyed">Indicates whether the block of memory to be freed was allocated while the current spy was active.</param>
			/// <returns>This method does not return a value.</returns>
			/// <remarks>
			/// When a spy object implementing IMallocSpy is registered using CoRegisterMallocSpy function, COM calls this method immediately
			/// after any call to IMalloc::Free. This method is included for completeness and consistencyâ€”it is not anticipated that
			/// developers will implement significant functionality in this method.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-postfree void PostFree( BOOL fSpyed );
			[PreserveSig]
			void PostFree([MarshalAs(UnmanagedType.Bool)] bool fSpyed);

			/// <summary>Performs operations required before calling IMalloc::Realloc.</summary>
			/// <param name="pRequest">The pointer to the block of memory specified in the call to IMalloc::Realloc.</param>
			/// <param name="cbRequest">The byte count of the block of memory as specified in the original call to IMalloc::Realloc.</param>
			/// <param name="ppNewRequest">
			/// Address of pointer variable that receives a pointer to the memory block to be reallocated. This may be different from the
			/// pointer in pRequest if the implementation of <c>PreRealloc</c> extends or modifies the reallocation. This is pointer should
			/// always be stored by <c>PreRealloc</c>.
			/// </param>
			/// <param name="fSpyed">Indicates whether the block of memory was allocated while this spy was active.</param>
			/// <returns>The byte count to be passed to IMalloc::Realloc.</returns>
			/// <remarks>
			/// <para>
			/// The <c>PreRealloc</c> implementation may extend and/or modify the allocation to store debug-specific information with the
			/// allocation. Thus, the ppNewRequest parameter may differ from pRequest, a pointer to the request specified in the original
			/// call to Realloc.
			/// </para>
			/// <para>
			/// <c>PreRealloc</c> can force memory allocation failure by returning 0, allowing testing to ensure that the application handles
			/// allocation failure gracefully in all cases. In this case, PostRealloc is not called and Realloc returns <c>NULL</c>. However,
			/// if <c>Realloc</c> encounters a real memory failure and returns <c>NULL</c>, <c>PostRealloc</c> is called. Forcing allocation
			/// failure is effective only if cbRequest is not equal to 0.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-prerealloc SIZE_T PreRealloc( void *pRequest,
			// SIZE_T cbRequest, void **ppNewRequest, BOOL fSpyed );
			[PreserveSig]
			SizeT PreRealloc(IntPtr pRequest, SizeT cbRequest, out IntPtr ppNewRequest, [MarshalAs(UnmanagedType.Bool)] bool fSpyed);

			/// <summary>Performs operations required after calling IMalloc::Realloc.</summary>
			/// <param name="pActual">The pointer specified in the call to Realloc.</param>
			/// <param name="fSpyed">Indicates whether the block of memory was allocated while the current spy was active.</param>
			/// <returns>
			/// The method returns a pointer to the beginning of the block actually allocated. This pointer is also returned to the caller of
			/// IMalloc::Realloc. If debug information is written at the front of the caller's allocation, it should be a forward offset from
			/// pActual. The value should be the same as pActual if debug information is appended or if no debug information is attached.
			/// </returns>
			/// <remarks>
			/// If memory is successfully reallocated while the spy is active, fSpyed will be <c>TRUE</c> in subsequent calls to IMallocSpy
			/// methods that track the reallocated memory, even if fSpyed was previously <c>FALSE</c>.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-postrealloc void * PostRealloc( void *pActual,
			// BOOL fSpyed );
			[PreserveSig]
			IntPtr PostRealloc(IntPtr pActual, [MarshalAs(UnmanagedType.Bool)] bool fSpyed);

			/// <summary>Performs operations required before calling IMalloc::GetSize.</summary>
			/// <param name="pRequest">The pointer that the caller is passing to GetSize.</param>
			/// <param name="fSpyed">Indicates whether the block of memory was allocated while the current spy was active.</param>
			/// <returns>A pointer to the actual allocation for which the size is to be determined.</returns>
			/// <remarks>
			/// <para>
			/// The <c>PreGetSize</c> method receives as its pRequest parameter the pointer the caller is passing to IMalloc::GetSize. It
			/// must then return a pointer to the actual allocation, which may have altered pRequest in the implementation of either the
			/// PreAlloc or the PreRealloc method of IMallocSpy. The pointer to the true allocation is then passed to <c>GetSize</c> as its
			/// pv parameter.
			/// </para>
			/// <para>IMalloc::GetSize then returns the size determined, and COM passes this value to IMallocSpy::PostGetSize in cbActual.</para>
			/// <para>
			/// The size determined by GetSize is the value returned by the HeapSize function. This is the size originally requested. For
			/// example, a memory allocation request of 27 bytes returns an allocation of 32 bytes and <c>GetSize</c> returns 27.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-pregetsize void * PreGetSize( void *pRequest,
			// BOOL fSpyed );
			IntPtr PreGetSize(IntPtr pRequest, [MarshalAs(UnmanagedType.Bool)] bool fSpyed);

			/// <summary>Performs operations required after calling IMalloc::GetSize.</summary>
			/// <param name="cbActual">The number of bytes in the allocation, as returned by GetSize.</param>
			/// <param name="fSpyed">Indicates whether the block of memory was allocated while the current spy was active.</param>
			/// <returns>The value returned by IMalloc::GetSize, which is the size of the allocated block of memory, in bytes.</returns>
			/// <remarks>
			/// The size determined by GetSize is the value returned by the HeapSize function. This is the size originally requested. For
			/// example, a memory allocation request of 27 bytes returns an allocation of 32 bytes and <c>GetSize</c> returns 27.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-postgetsize SIZE_T PostGetSize( SIZE_T
			// cbActual, BOOL fSpyed );
			[PreserveSig]
			SizeT PostGetSize(SizeT cbActual, [MarshalAs(UnmanagedType.Bool)] bool fSpyed);

			/// <summary>Performs operations required before calling IMalloc::DidAlloc.</summary>
			/// <param name="pRequest">The pointer specified in the call to DidAlloc.</param>
			/// <param name="fSpyed">Indicates whether the allocation was done while this spy was active.</param>
			/// <returns>The value passed to DidAlloc as the fActual parameter.</returns>
			/// <remarks>
			/// When a spy object implementing IMallocSpy is registered with the CoRegisterMallocSpy function, COM calls this method
			/// immediately before any call to IMalloc::DidAlloc. This method is included for completeness and consistencyâ€”it is not
			/// anticipated that developers will implement significant functionality in this method.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-predidalloc void * PreDidAlloc( void *pRequest,
			// BOOL fSpyed );
			[PreserveSig]
			IntPtr PreDidAlloc(IntPtr pRequest, [MarshalAs(UnmanagedType.Bool)] bool fSpyed);

			/// <summary>Performs operations required after calling IMalloc::DidAlloc.</summary>
			/// <param name="pRequest">The pointer specified in the call to DidAlloc.</param>
			/// <param name="fSpyed">Indicates whether the allocation was done while this spy was active.</param>
			/// <param name="fActual">The value returned by DidAlloc.</param>
			/// <returns>The value returned to the caller of DidAlloc.</returns>
			/// <remarks>
			/// <para>
			/// When a spy object implementing IMallocSpy is registered using the CoRegisterMallocSpy function, COM calls this method
			/// immediately after any call to DidAlloc. This method is included for completeness and consistencyâ€”it is not anticipated that
			/// developers will implement significant functionality in this method.
			/// </para>
			/// <para>
			/// For convenience, pRequest, the original pointer passed in the call to DidAlloc, is passed to <c>PostDidAlloc</c>. In
			/// addition, the parameter fActual is a Boolean value that indicates whether this value was actually passed to <c>DidAlloc</c>.
			/// If not, it would indicate that IMallocSpy::PreDidAlloc was implemented to alter this pointer for some debugging purpose.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-postdidalloc int PostDidAlloc( void *pRequest,
			// BOOL fSpyed, int fActual );
			[PreserveSig]
			int PostDidAlloc(IntPtr pRequest, [MarshalAs(UnmanagedType.Bool)] bool fSpyed, int fActual);

			/// <summary>Performs operations required before calling IMalloc::HeapMinimize.</summary>
			/// <returns>This method does not return a value.</returns>
			/// <remarks>
			/// This method is included for completeness; it is not anticipated that developers will implement significant functionality in
			/// this method.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-preheapminimize void PreHeapMinimize( );
			[PreserveSig]
			void PreHeapMinimize();

			/// <summary>Performs operations required after calling IMalloc::HeapMinimize.</summary>
			/// <returns>This method does not return a value.</returns>
			/// <remarks>
			/// When a spy object implementing IMallocSpy is registered using the CoRegisterMallocSpy function, COM calls this method
			/// immediately after any call to IMalloc::Free. This method is included for completeness and consistencyâ€”it is not anticipated
			/// that developers will implement significant functionality in this method.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imallocspy-postheapminimize void PostHeapMinimize( );
			[PreserveSig]
			void PostHeapMinimize();
		}

		/// <summary>
		/// <para>This interface allows an application to capture a message before it is dispatched to a control or form.</para>
		/// <para>
		/// A class that implements the IMessageFilter interface can be added to the application's message pump to filter out a message or
		/// perform other operations before the message is dispatched to a form or control. To add the message filter to an application's
		/// message pump, use the AddMessageFilter method in the Application class.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.imessagefilter?view=netframework-4.8
		[PInvokeData("", MSDNShortId = "System.Windows.Forms.IMessageFilter")]
		[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000016-0000-0000-C000-000000000046")]
		public interface IMessageFilter
		{
			/// <summary>
			/// <para>Provides a single entry point for incoming calls.</para>
			/// <para>
			/// This method is called prior to each method invocation originating outside the current process and provides the ability to
			/// filter or reject incoming calls (or callbacks) to an object or a process.
			/// </para>
			/// </summary>
			/// <param name="dwCallType">The type of incoming call that has been received. Possible values are from the enumeration CALLTYPE.</param>
			/// <param name="htaskCaller">The thread id of the caller.</param>
			/// <param name="dwTickCount">
			/// The elapsed tick count since the outgoing call was made, if dwCallType is not CALLTYPE_TOPLEVEL. If dwCallType is
			/// CALLTYPE_TOPLEVEL, dwTickCount should be ignored.
			/// </param>
			/// <param name="lpInterfaceInfo">
			/// A pointer to an INTERFACEINFO structure that identifies the object, interface, and method being called. In the case of DDE
			/// calls, lpInterfaceInfo can be <c>NULL</c> because the DDE layer does not return interface information.
			/// </param>
			/// <returns>
			/// <para>This method can return the following values.</para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>SERVERCALL_ISHANDLED</term>
			/// <term>The application might be able to process the call.</term>
			/// </item>
			/// <item>
			/// <term>SERVERCALL_REJECTED</term>
			/// <term>
			/// The application cannot handle the call due to an unforeseen problem, such as network unavailability, or if it is in the
			/// process of terminating.
			/// </term>
			/// </item>
			/// <item>
			/// <term>SERVERCALL_RETRYLATER</term>
			/// <term>
			/// The application cannot handle the call at this time. An application might return this value when it is in a user-controlled
			/// modal state.
			/// </term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>If implemented, <c>HandleInComingCall</c> is called by COM when an incoming COM message is received.</para>
			/// <para>
			/// Depending on an application's current state, a call is either accepted and processed or rejected (permanently or
			/// temporarily). If SERVERCALL_ISHANDLED is returned, the application may be able to process the call, although success depends
			/// on the interface for which the call is destined. If the call cannot be processed, COM returns RPC_E_CALL_REJECTED.
			/// </para>
			/// <para>Input-synchronized and asynchronous calls are dispatched even if the application returns SERVERCALL_REJECTED or SERVERCALL_RETRYLATER.</para>
			/// <para>
			/// <c>HandleInComingCall</c> should not be used to hold off updates to objects during operations such as band printing. For that
			/// purpose, use IViewObject::Freeze.
			/// </para>
			/// <para>
			/// You can also use <c>HandleInComingCall</c> to set up the application's state so that the call can be processed in the future.
			/// </para>
			/// <para>
			/// <c>Note</c> Although the htaskCaller parameter is typed as an HTASK, it contains the thread id of the calling thread. When
			/// you implement the IMessageFilter interface, you can call the OpenThread function to get the thread handle from the
			/// htaskCaller parameter, and you can call the GetProcessIdOfThread function to get the process id.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imessagefilter-handleincomingcall DWORD
			// HandleInComingCall( DWORD dwCallType, HTASK htaskCaller, DWORD dwTickCount, LPINTERFACEINFO lpInterfaceInfo );
			[PreserveSig]
			SERVERCALL HandleInComingCall(CALLTYPE dwCallType, HTASK htaskCaller, uint dwTickCount, [Optional] INTERFACEINFO lpInterfaceInfo);

			/// <summary>
			/// Provides applications with an opportunity to display a dialog box offering retry, cancel, or task-switching options.
			/// </summary>
			/// <param name="htaskCallee">The thread id of the called application.</param>
			/// <param name="dwTickCount">The number of elapsed ticks since the call was made.</param>
			/// <param name="dwRejectType">Specifies either SERVERCALL_REJECTED or SERVERCALL_RETRYLATER, as returned by the object application.</param>
			/// <returns>
			/// <para>This method can return the following values.</para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return value</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>-1</term>
			/// <term>The call should be canceled. COM then returns RPC_E_CALL_REJECTED from the original method call.</term>
			/// </item>
			/// <item>
			/// <term>0 ≤ value &lt; 100</term>
			/// <term>The call is to be retried immediately.</term>
			/// </item>
			/// <item>
			/// <term>100 ≤ value</term>
			/// <term>COM will wait for this many milliseconds and then retry the call.</term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// COM calls <c>RetryRejectedCall</c> on the caller's IMessageFilter interface immediately after receiving SERVERCALL_RETRYLATER
			/// or SERVERCALL_REJECTED from the IMessageFilter::HandleInComingCall method on the callee's <c>IMessageFilter</c> interface.
			/// </para>
			/// <para>
			/// If a called task rejects a call, the application is probably in a state where it cannot handle such calls, possibly only
			/// temporarily. When this occurs, COM returns to the caller and issues <c>RetryRejectedCall</c> to determine whether it should
			/// retry the rejected call.
			/// </para>
			/// <para>
			/// Applications should silently retry calls that have returned with SERVERCALL_RETRYLATER. If, after a reasonable amount of time
			/// has passed, say about 30 seconds, the application should display the busy dialog box; a standard implementation of this
			/// dialog box is available in the OLEDLG library. The callee may momentarily be in a state where calls can be handled. The
			/// option to wait and retry is provided for special kinds of calling applications, such as background tasks executing macros or
			/// scripts, so that they can retry the calls in a nonintrusive way.
			/// </para>
			/// <para>
			/// If, after a dialog box is displayed, the user chooses to cancel, <c>RetryRejectedCall</c> returns -1 and the call will appear
			/// to fail with RPC_E_CALL_REJECTED.
			/// </para>
			/// <para>
			/// If a client implements IMessageFilter and calls a server method on a remote machine, <c>RetryRejectedCall</c> will not be called.
			/// </para>
			/// <para>
			/// <c>Note</c> Although the htaskCallee parameter is typed as an HTASK, it contains the thread id of the called thread. When you
			/// implement the IMessageFilter interface, you can call the OpenThread function to get the thread handle from the htaskCallee
			/// parameter, and you can call the GetProcessIdOfThread function to get the process id.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imessagefilter-retryrejectedcall DWORD RetryRejectedCall(
			// HTASK htaskCallee, DWORD dwTickCount, DWORD dwRejectType );
			[PreserveSig]
			uint RetryRejectedCall(HTASK htaskCallee, uint dwTickCount, SERVERCALL dwRejectType);

			/// <summary>
			/// <para>Indicates that a message has arrived while COM is waiting to respond to a remote call.</para>
			/// <para>
			/// Handling input while waiting for an outgoing call to finish can introduce complications. The application should determine
			/// whether to process the message without interrupting the call, to continue waiting, or to cancel the operation.
			/// </para>
			/// </summary>
			/// <param name="htaskCallee">The thread id of the called application.</param>
			/// <param name="dwTickCount">The number of ticks since the call was made. It is calculated from the GetTickCount function.</param>
			/// <param name="dwPendingType">
			/// The type of call made during which a message or event was received. Possible values are from the enumeration PENDINGTYPE,
			/// where PENDINGTYPE_TOPLEVEL means the outgoing call was not nested within a call from another application and
			/// PENDINTGYPE_NESTED means the outgoing call was nested within a call from another application.
			/// </param>
			/// <returns>
			/// <para>This method can return the following values.</para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>PENDINGMSG_CANCELCALL</term>
			/// <term>
			/// Cancel the outgoing call. This should be returned only under extreme conditions. Canceling a call that has not replied or
			/// been rejected can create orphan transactions and lose resources. COM fails the original call and returns RPC_E_CALL_CANCELLED.
			/// </term>
			/// </item>
			/// <item>
			/// <term>PENDINGMSG_WAITNOPROCESS</term>
			/// <term>Unused.</term>
			/// </item>
			/// <item>
			/// <term>PENDINGMSG_WAITDEFPROCESS</term>
			/// <term>
			/// Keyboard and mouse messages are no longer dispatched. However there are some cases where mouse and keyboard messages could
			/// cause the system to deadlock, and in these cases, mouse and keyboard messages are discarded. WM_PAINT messages are
			/// dispatched. Task-switching and activation messages are handled as before.
			/// </term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// COM calls <c>MessagePending</c> after an application has made a COM method call and a Windows message occurs before the call
			/// has returned. A Windows message is sent, for example, when the user selects a menu command or double-clicks an object. Before
			/// COM makes the <c>MessagePending</c> call, it calculates the elapsed time since the original COM method call was made. COM
			/// delivers the elapsed time in the dwTickCount parameter. In the meantime, COM does not remove the message from the queue.
			/// </para>
			/// <para>
			/// Windows messages that appear in the caller's queue should remain in the queue until sufficient time has passed to ensure that
			/// the messages are probably not the result of typing ahead, but are instead an attempt to get attention. Set the delay with the
			/// dwTickCount parameter —a two-second or three-second delay is recommended. If that amount of time passes and the call has not
			/// been completed, the caller should flush the messages from the queue and the OLE UI busy dialog box should be displayed
			/// offering the user the choice of retrying the call (continue waiting) or switching to the specified task. This ensures the
			/// following behaviors:
			/// </para>
			/// <list type="bullet">
			/// <item>
			/// <term>If calls are completed in a reasonable amount of time, type ahead will be treated correctly.</term>
			/// </item>
			/// <item>
			/// <term>
			/// If the callee does not respond, type ahead is not misinterpreted and the user is able to act to solve the problem. For
			/// example, OLE 1 servers can queue up requests without responding when they are in modal dialog boxes.
			/// </term>
			/// </item>
			/// </list>
			/// <para>
			/// Handling input while waiting for an outgoing call to finish can introduce complications. The application should determine
			/// whether to process the message without interrupting the call, to continue waiting, or to cancel the operation.
			/// </para>
			/// <para>
			/// When there is no response to the original COM call, the application can cancel the call and restore the COM object to a
			/// consistent state by calling IStorage::Revert on its storage. The object can be released when the container can shut down.
			/// However, canceling a call can create orphaned operations and resource leaks. Canceling should be used only as a last resort.
			/// It is strongly recommended that applications not allow such calls to be canceled.
			/// </para>
			/// <para>
			/// <c>Note</c> Although the htaskCallee parameter is typed as an HTASK, it contains the thread id of the called thread. When you
			/// implement the IMessageFilter interface, you can call the OpenThread function to get the thread handle from the htaskCallee
			/// parameter, and you can call the GetProcessIdOfThread function to get the process id.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-imessagefilter-messagepending DWORD MessagePending( HTASK
			// htaskCallee, DWORD dwTickCount, DWORD dwPendingType );
			[PreserveSig]
			PENDINGMSG MessagePending(HTASK htaskCallee, uint dwTickCount, PENDINGTYPE dwPendingType);
		}

		/// <summary>
		/// <para>
		/// Provides the CLSID of an object that can be stored persistently in the system. Allows the object to specify which object handler
		/// to use in the client process, as it is used in the default implementation of marshaling.
		/// </para>
		/// <para>
		/// <c>IPersist</c> is the base interface for three other interfaces: IPersistStorage, IPersistStream, and IPersistFile. Each of
		/// these interfaces, therefore, includes the GetClassID method, and the appropriate one of these three interfaces is implemented on
		/// objects that can be serialized to a storage, a stream, or a file. The methods of these interfaces allow the state of these
		/// objects to be saved for later instantiations, and load the object using the saved state. Typically, the persistence interfaces
		/// are implemented by an embedded or linked object, and are called by the container application or the default object handler.
		/// </para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nn-objidl-ipersist
		[PInvokeData("objidl.h", MSDNShortId = "932eb0e2-35a6-482e-9138-00cff30508a9")]
		[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000010c-0000-0000-C000-000000000046")]
		public interface IPersist
		{
			/// <summary>Retrieves the class identifier (CLSID) of the object.</summary>
			/// <returns>
			/// <para>
			/// A pointer to the location that receives the CLSID on return. The CLSID is a globally unique identifier (GUID) that uniquely
			/// represents an object class that defines the code that can manipulate the object's data.
			/// </para>
			/// <para>If the method succeeds, the return value is S_OK. Otherwise, it is E_FAIL.</para>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The <c>GetClassID</c> method retrieves the class identifier (CLSID) for an object, used in later operations to load
			/// object-specific code into the caller's context.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// A container application might call this method to retrieve the original CLSID of an object that it is treating as a
			/// different class. Such a call would be necessary if a user performed an editing operation that required the object to be
			/// saved. If the container were to save it using the treat-as CLSID, the original application would no longer be able to edit
			/// the object. Typically, in this case, the container calls the OleSave helper function, which performs all the necessary
			/// steps. For this reason, most container applications have no need to call this method directly.
			/// </para>
			/// <para>
			/// The exception would be a container that provides an object handler for certain objects. In particular, a container
			/// application should not get an object's CLSID and then use it to retrieve class specific information from the registry.
			/// Instead, the container should use IOleObject and IDataObject interfaces to retrieve such class-specific information directly
			/// from the object.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// Typically, implementations of this method simply supply a constant CLSID for an object. If, however, the object's
			/// <c>TreatAs</c> registry key has been set by an application that supports emulation (and so is treating the object as one of
			/// a different class), a call to <c>GetClassID</c> must supply the CLSID specified in the <c>TreatAs</c> key. For more
			/// information on emulation, see CoTreatAsClass.
			/// </para>
			/// <para>
			/// When an object is in the running state, the default handler calls an implementation of <c>GetClassID</c> that delegates the
			/// call to the implementation in the object. When the object is not running, the default handler instead calls the ReadClassStg
			/// function to read the CLSID that is saved in the object's storage.
			/// </para>
			/// <para>
			/// If you are writing a custom object handler for your object, you might want to simply delegate this method to the default
			/// handler implementation (see OleCreateDefaultHandler).
			/// </para>
			/// <para>URL Moniker Notes</para>
			/// <para>This method returns CLSID_StdURLMoniker.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ipersist-getclassid HRESULT GetClassID( CLSID *pClassID );
			Guid GetClassID();
		}

		/// <summary>
		/// Enables a container application to pass a storage object to one of its contained objects and to load and save the storage object.
		/// This interface supports the structured storage model, in which each contained object has its own storage that is nested within
		/// the container's storage.
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-ipersiststorage
		[PInvokeData("objidl.h", MSDNShortId = "1c1a20fc-c101-4cbc-a7a6-30613aa387d7")]
		[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000010a-0000-0000-C000-000000000046")]
		public interface IPersistStorage : IPersist
		{
			/// <summary>Retrieves the class identifier (CLSID) of the object.</summary>
			/// <returns>
			/// <para>
			/// A pointer to the location that receives the CLSID on return. The CLSID is a globally unique identifier (GUID) that uniquely
			/// represents an object class that defines the code that can manipulate the object's data.
			/// </para>
			/// <para>If the method succeeds, the return value is S_OK. Otherwise, it is E_FAIL.</para>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The <c>GetClassID</c> method retrieves the class identifier (CLSID) for an object, used in later operations to load
			/// object-specific code into the caller's context.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// A container application might call this method to retrieve the original CLSID of an object that it is treating as a different
			/// class. Such a call would be necessary if a user performed an editing operation that required the object to be saved. If the
			/// container were to save it using the treat-as CLSID, the original application would no longer be able to edit the object.
			/// Typically, in this case, the container calls the OleSave helper function, which performs all the necessary steps. For this
			/// reason, most container applications have no need to call this method directly.
			/// </para>
			/// <para>
			/// The exception would be a container that provides an object handler for certain objects. In particular, a container
			/// application should not get an object's CLSID and then use it to retrieve class specific information from the registry.
			/// Instead, the container should use IOleObject and IDataObject interfaces to retrieve such class-specific information directly
			/// from the object.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// Typically, implementations of this method simply supply a constant CLSID for an object. If, however, the object's
			/// <c>TreatAs</c> registry key has been set by an application that supports emulation (and so is treating the object as one of a
			/// different class), a call to <c>GetClassID</c> must supply the CLSID specified in the <c>TreatAs</c> key. For more information
			/// on emulation, see CoTreatAsClass.
			/// </para>
			/// <para>
			/// When an object is in the running state, the default handler calls an implementation of <c>GetClassID</c> that delegates the
			/// call to the implementation in the object. When the object is not running, the default handler instead calls the ReadClassStg
			/// function to read the CLSID that is saved in the object's storage.
			/// </para>
			/// <para>
			/// If you are writing a custom object handler for your object, you might want to simply delegate this method to the default
			/// handler implementation (see OleCreateDefaultHandler).
			/// </para>
			/// <para>URL Moniker Notes</para>
			/// <para>This method returns CLSID_StdURLMoniker.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ipersist-getclassid HRESULT GetClassID( CLSID *pClassID );
			new Guid GetClassID();

			/// <summary>Determines whether an object has changed since it was last saved to its current storage.</summary>
			/// <returns>This method returns S_OK to indicate that the object has changed. Otherwise, it returns S_FALSE.</returns>
			/// <remarks>
			/// <para>
			/// Use this method to determine whether an object should be saved before closing it. The dirty flag for an object is
			/// conditionally cleared in the IPersistStorage::Save method.
			/// </para>
			/// <para>
			/// For example, you could optimize a <c>File Save</c> operation by calling the <c>IPersistStorage::IsDirty</c> method for each
			/// object and then calling the IPersistStorage::Save method only for those objects that are dirty.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// You should treat any error return codes as an indication that the object has changed. Unless this method explicitly returns
			/// S_FALSE, assume that the object must be saved.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>An object with no contained objects simply checks its dirty flag to return the appropriate result.</para>
			/// <para>
			/// A container with one or more contained objects must maintain an internal dirty flag that is set when any of its contained
			/// objects has changed since it was last saved.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststorage-isdirty HRESULT IsDirty( );
			[PreserveSig]
			HRESULT IsDirty();

			/// <summary>Initializes a new storage object.</summary>
			/// <param name="pStg">
			/// An IStorage pointer to the new storage object to be initialized. The container creates a nested storage object in its storage
			/// object (see IStorage::CreateStorage). Then, the container calls the WriteClassStg function to initialize the new storage
			/// object with the object class identifier (CLSID).
			/// </param>
			/// <remarks>
			/// <para>
			/// A container application can call this method when it needs to initialize a new object, for example, with an InsertObject command.
			/// </para>
			/// <para>
			/// An object that supports the IPersistStorage interface must have access to a valid storage object at all times while it is
			/// running. This includes the time just after the object has been created but before it has been made persistent. The object's
			/// container must provide the object with a valid IStorage pointer to the storage during this time through the call to
			/// <c>IPersistStorage::InitNew</c>. Depending on the container's state, a temporary file might have to be created for this purpose.
			/// </para>
			/// <para>If the object wants to retain the IStorage instance, it must call AddRef to increment its reference count.</para>
			/// <para>
			/// After the call to <c>IPersistStorage::InitNew</c>, the object is in either the loaded or running state. For example, if the
			/// object class has an in-process server, the object will be in the running state. However, if the object uses the default
			/// handler, the container's call to <c>InitNew</c> only invokes the handler's implementation which does not run the object.
			/// Later if the container runs the object, the handler calls the <c>InitNew</c> method for the object.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// Rather than calling <c>IPersistStorage::InitNew</c> directly, you typically call the OleCreate helper function which does the following:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Calls the CoCreateInstance function to create an instance of the object class.</term>
			/// </item>
			/// <item>
			/// <term>Queries the new instance for the IPersistStorage interface.</term>
			/// </item>
			/// <item>
			/// <term>Calls the <c>InitNew</c> method to initialize the object.</term>
			/// </item>
			/// </list>
			/// <para>
			/// The container application should cache the IPersistStorage pointer to the object for use in later operations on the object.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// An implementation of <c>IPersistStorage::InitNew</c> should initialize the object to its default state, taking the following steps:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Pre-open and cache the pointers to any streams or storages that the object will need to save itself to this storage.</term>
			/// </item>
			/// <item>
			/// <term>Call AddRef and cache the storage pointer that is passed in.</term>
			/// </item>
			/// <item>
			/// <term>
			/// Call the WriteFmtUserTypeStg function to write the native clipboard format and user type string for the object to the storage object.
			/// </term>
			/// </item>
			/// <item>
			/// <term>Set the dirty flag for the object.</term>
			/// </item>
			/// </list>
			/// <para>
			/// The first two steps are particularly important for ensuring that the object can save itself in low memory situations.
			/// Pre-opening and holding onto pointers to the stream and storage interfaces guarantee that a save operation to this storage
			/// will not fail due to insufficient memory.
			/// </para>
			/// <para>
			/// Your implementation of this method should return the CO_E_ALREADYINITIALIZED error code if it receives a call to either the
			/// <c>IPersistStorage::InitNew</c> method or the IPersistStorage::Load method after it is already initialized.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststorage-initnew HRESULT InitNew( IStorage *pStg );
			void InitNew([In] IStorage pStg);

			/// <summary>Loads an object from its existing storage.</summary>
			/// <param name="pStg">An IStorage pointer to the existing storage from which the object is to be loaded.</param>
			/// <remarks>
			/// <para>
			/// This method initializes an object from an existing storage. The object is placed in the loaded state if this method is called
			/// by the container application. If called by the default handler, this method places the object in the running state.
			/// </para>
			/// <para>Either the default handler or the object itself can hold onto the IStorage pointer while the object is loaded or running.</para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// Rather than calling <c>IPersistStorage::Load</c> directly, you typically call the OleLoad helper function which does the following:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Create an uninitialized instance of the object class.</term>
			/// </item>
			/// <item>
			/// <term>Query the new instance for the IPersistStorage interface.</term>
			/// </item>
			/// <item>
			/// <term>Call <c>Load</c> to initialize the object from the existing storage.</term>
			/// </item>
			/// </list>
			/// <para>
			/// You also call this method indirectly when you call the OleCreateFromData function or the OleCreateFromFile function to insert
			/// an object into a compound file (as in a drag-and-drop or clipboard paste operation).
			/// </para>
			/// <para>The container should cache the IPersistStorage pointer for use in later operations on the object.</para>
			/// <para>Notes to Implementers</para>
			/// <para>Your implementation should perform the following steps to load an object:</para>
			/// <list type="number">
			/// <item>
			/// <term>Open the object's streams in the storage object, and read the necessary data into the object's internal data structures.</term>
			/// </item>
			/// <item>
			/// <term>Clear the object's dirty flag.</term>
			/// </item>
			/// <item>
			/// <term>Call the AddRef method and cache the passed in storage pointer.</term>
			/// </item>
			/// <item>
			/// <term>Keep open and cache the pointers to any streams or storages that the object will need to save itself to this storage.</term>
			/// </item>
			/// <item>
			/// <term>Perform any other default initialization required for the object.</term>
			/// </item>
			/// </list>
			/// <para>
			/// Steps 3 and 4 are particularly important for ensuring that the object can save itself in low memory situations. Holding onto
			/// pointers to the storage and stream interfaces guarantees that a save operation to this storage will not fail due to
			/// insufficient memory.
			/// </para>
			/// <para>
			/// Your implementation of this method should return the CO_E_ALREADYINITIALIZED error code if it receives a call to either the
			/// IPersistStorage::InitNew method or the <c>IPersistStorage::Load</c> method after it is already initialized.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststorage-load HRESULT Load( IStorage *pStg );
			void Load([In] IStorage pStg);

			/// <summary>
			/// Saves an object, and any nested objects that it contains, into the specified storage object. The object enters NoScribble mode.
			/// </summary>
			/// <param name="pStgSave">An IStorage pointer to the storage into which the object is to be saved.</param>
			/// <param name="fSameAsLoad">
			/// <para>
			/// Indicates whether the specified storage is the current one, which was passed to the object by one of the following calls:
			/// IPersistStorage::InitNew, IPersistStorage::Load, or IPersistStorage::SaveCompleted.
			/// </para>
			/// <para>
			/// This parameter is set to <c>FALSE</c> when performing a <c>Save As</c> or <c>Save A Copy To</c> operation or when performing
			/// a full save. In the latter case, this method saves to a temporary file, deletes the original file, and renames the temporary file.
			/// </para>
			/// <para>
			/// This parameter is set to <c>TRUE</c> to perform a full save in a low-memory situation or to perform a fast incremental save
			/// in which only the dirty components are saved.
			/// </para>
			/// </param>
			/// <remarks>
			/// <para>
			/// This method saves an object, and any nested objects it contains, into the specified storage. It also places the object into
			/// NoScribble mode. Thus, the object cannot write to its storage until a subsequent call to the IPersistStorage::SaveCompleted
			/// method returns the object to Normal mode.
			/// </para>
			/// <para>
			/// If the storage object is the same as the one it was loaded or created from, the save operation may be able to write
			/// incremental changes to the storage object. Otherwise, a full save must be done.
			/// </para>
			/// <para>
			/// This method recursively calls the <c>IPersistStorage::Save</c> method, the OleSave function, or the IStorage::CopyTo method
			/// to save its nested objects.
			/// </para>
			/// <para>
			/// This method does not call the IStorage::Commit method. Nor does it write the CLSID to the storage object. Both of these tasks
			/// are the responsibilities of the caller.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// Rather than calling <c>IPersistStorage::Save</c> directly, you typically call the OleSave helper function which performs the
			/// following steps:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Call the WriteClassStg function to write the class identifier for the object to the storage.</term>
			/// </item>
			/// <item>
			/// <term>Call the <c>IPersistStorage::Save</c> method.</term>
			/// </item>
			/// <item>
			/// <term>If needed, call the IStorage::Commit method on the storage object.</term>
			/// </item>
			/// </list>
			/// <para>
			/// Then, a container application performs any other operations necessary to complete the save and calls the SaveCompleted method
			/// for each object.
			/// </para>
			/// <para>
			/// If an embedded object passes the <c>IPersistStorage::Save</c> method to its nested objects, it must receive a call to its
			/// IPersistStorage::SaveCompleted method before calling this method for its nested objects.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststorage-save HRESULT Save( IStorage *pStgSave,
			// BOOL fSameAsLoad );
			void Save([In] IStorage pStgSave, [MarshalAs(UnmanagedType.Bool)] bool fSameAsLoad);

			/// <summary>
			/// Notifies the object that it can write to its storage object. It does this by notifying the object that it can revert from
			/// NoScribble mode (in which it must not write to its storage object), to Normal mode (in which it can). The object enters
			/// NoScribble mode when it receives an IPersistStorage::Save call.
			/// </summary>
			/// <param name="pStgNew">
			/// An IStorage pointer to the new storage object, if different from the storage object prior to saving. This pointer can be
			/// <c>NULL</c> if the current storage object does not change during the save operation. If the object is in HandsOff mode, this
			/// parameter must be non- <c>NULL</c>.
			/// </param>
			/// <remarks>
			/// <para>
			/// This method notifies an object that it can revert to Normal mode and can once again write to its storage object. The object
			/// exits NoScribble mode or HandsOff mode.
			/// </para>
			/// <para>
			/// If the object is reverting from HandsOff mode, the pStgNew parameter must be non- <c>NULL</c>. In HandsOffFromNormal mode,
			/// this parameter is the new storage object that replaces the one that was revoked by the IPersistStorage::HandsOffStorage
			/// method. The data in the storage object is a copy of the data from the revoked storage object. In HandsOffAfterSave mode, the
			/// data is the same as the data that was most recently saved. It is not the same as the data in the revoked storage object.
			/// </para>
			/// <para>
			/// If the object is reverting from NoScribble mode, the pStgNew parameter can be <c>NULL</c> or non- <c>NULL</c>. If
			/// <c>NULL</c>, the object once again has access to its storage object. If it is not <c>NULL</c>, the component object should
			/// simulate receiving a call to its HandsOffStorage method. If the component object cannot simulate this call, its container
			/// must be prepared to actually call the <c>HandsOffStorage</c> method.
			/// </para>
			/// <para>This method must recursively call any nested objects that are loaded or running.</para>
			/// <para>
			/// If this method returns an error code, the object is not returned to Normal mode. Thus, the container object can attempt
			/// different save strategies.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststorage-savecompleted HRESULT SaveCompleted(
			// IStorage *pStgNew );
			void SaveCompleted([In] IStorage pStgNew);

			/// <summary>
			/// Instructs the object to release all storage objects that have been passed to it by its container and to enter HandsOff mode.
			/// </summary>
			/// <remarks>
			/// <para>
			/// This method causes an object to release any storage objects that it is holding and to enter the HandsOff mode until a
			/// subsequent IPersistStorage::SaveCompleted call. In HandsOff mode, the object cannot do anything and the only operation that
			/// works is a close operation.
			/// </para>
			/// <para>
			/// A container application typically calls this method during a full save or low-memory full save operation to force the object
			/// to release all pointers to its current storage. In these scenarios, the <c>HandsOffStorage</c> call comes after a call to
			/// either OleSave or IPersistStorage::Save, putting the object in HandsOffAfterSave mode. Calling this method is necessary so
			/// the container application can delete the current file as part of a full save, or so it can call the
			/// IRootStorage::SwitchToFile method as part of a low-memory save.
			/// </para>
			/// <para>
			/// A container application also calls this method when an object is in Normal mode to put the object in HandsOffFromNormal mode.
			/// </para>
			/// <para>
			/// While the component object is in either HandsOffAfterSave or HandsOffFromNormal mode, most operations on the object will
			/// fail. Thus, the container should restore the object to Normal mode as soon as possible. The container application does this
			/// by calling the IPersistStorage::SaveCompleted method, which passes a storage pointer back to the component object for the new
			/// storage object.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// This method must release all pointers to the current storage object, including pointers to any nested streams and storages.
			/// If the object contains nested objects, the container application must recursively call this method for any nested objects
			/// that are loaded or running.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststorage-handsoffstorage HRESULT HandsOffStorage( );
			void HandsOffStorage();
		}

		/// <summary>Enables the saving and loading of objects that use a simple serial stream for their storage needs.</summary>
		/// <remarks>
		/// <para>
		/// One way in which this interface is used is to support OLE moniker implementations. Each of the OLE-provided moniker interfaces
		/// provides an <c>IPersistStream</c> implementation through which the moniker saves or loads itself. An instance of the OLE generic
		/// composite moniker class calls the <c>IPersistStream</c> methods of its component monikers to load or save the components in the
		/// proper sequence in a single stream.
		/// </para>
		/// <para>IPersistStream URL Moniker Implementation</para>
		/// <para>
		/// The URL moniker implementation of <c>IPersistStream</c> is found on an URL moniker object, which supports IUnknown,
		/// <c>IAsyncMoniker</c>, and IMoniker. The <c>IMoniker</c> interface inherits its definition from <c>IPersistStream</c> and thus,
		/// the URL moniker also provides an implementation of <c>IPersistStream</c> as part of its implementation of <c>IMoniker</c>.
		/// </para>
		/// <para>
		/// The IAsyncMoniker interface on an URL moniker is simply IUnknown (there are no additional methods); it is used to allow clients
		/// to determine if a moniker supports asynchronous binding. To get a pointer to the IMoniker interface on this object, call the
		/// <c>CreateURLMonikerEx</c> function. Then, to get a pointer to <c>IPersistStream</c>, call the QueryInterface method.
		/// </para>
		/// <para>
		/// <c>IPersistStream</c>, in addition to inheriting its definition from IUnknown, also inherits the single method of IPersist, GetClassID.
		/// </para>
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nn-objidl-ipersiststream
		[PInvokeData("objidl.h", MSDNShortId = "97ea64ee-d950-4872-add6-1f532a6eb33f")]
		[ComImport, Guid("00000109-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IPersistStream : IPersist
		{
			/// <summary>Retrieves the class identifier (CLSID) of the object.</summary>
			/// <returns>
			/// <para>
			/// A pointer to the location that receives the CLSID on return. The CLSID is a globally unique identifier (GUID) that uniquely
			/// represents an object class that defines the code that can manipulate the object's data.
			/// </para>
			/// <para>If the method succeeds, the return value is S_OK. Otherwise, it is E_FAIL.</para>
			/// </returns>
			/// <remarks>
			/// <para>
			/// The <c>GetClassID</c> method retrieves the class identifier (CLSID) for an object, used in later operations to load
			/// object-specific code into the caller's context.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// A container application might call this method to retrieve the original CLSID of an object that it is treating as a
			/// different class. Such a call would be necessary if a user performed an editing operation that required the object to be
			/// saved. If the container were to save it using the treat-as CLSID, the original application would no longer be able to edit
			/// the object. Typically, in this case, the container calls the OleSave helper function, which performs all the necessary
			/// steps. For this reason, most container applications have no need to call this method directly.
			/// </para>
			/// <para>
			/// The exception would be a container that provides an object handler for certain objects. In particular, a container
			/// application should not get an object's CLSID and then use it to retrieve class specific information from the registry.
			/// Instead, the container should use IOleObject and IDataObject interfaces to retrieve such class-specific information directly
			/// from the object.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// Typically, implementations of this method simply supply a constant CLSID for an object. If, however, the object's
			/// <c>TreatAs</c> registry key has been set by an application that supports emulation (and so is treating the object as one of
			/// a different class), a call to <c>GetClassID</c> must supply the CLSID specified in the <c>TreatAs</c> key. For more
			/// information on emulation, see CoTreatAsClass.
			/// </para>
			/// <para>
			/// When an object is in the running state, the default handler calls an implementation of <c>GetClassID</c> that delegates the
			/// call to the implementation in the object. When the object is not running, the default handler instead calls the ReadClassStg
			/// function to read the CLSID that is saved in the object's storage.
			/// </para>
			/// <para>
			/// If you are writing a custom object handler for your object, you might want to simply delegate this method to the default
			/// handler implementation (see OleCreateDefaultHandler).
			/// </para>
			/// <para>URL Moniker Notes</para>
			/// <para>This method returns CLSID_StdURLMoniker.</para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ipersist-getclassid HRESULT GetClassID( CLSID *pClassID );
			new Guid GetClassID();

			/// <summary>Determines whether an object has changed since it was last saved to its stream.</summary>
			/// <returns>This method returns S_OK to indicate that the object has changed. Otherwise, it returns S_FALSE.</returns>
			/// <remarks>
			/// <para>
			/// Use this method to determine whether an object should be saved before closing it. The dirty flag for an object is
			/// conditionally cleared in the IPersistStream::Save method.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// You should treat any error return codes as an indication that the object has changed. Unless this method explicitly returns
			/// S_FALSE, assume that the object must be saved.
			/// </para>
			/// <para>
			/// Note that the OLE-provided implementations of the <c>IPersistStream::IsDirty</c> method in the OLE-provided moniker
			/// interfaces always return S_FALSE because their internal state never changes.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ipersiststream-isdirty HRESULT IsDirty( );
			[PreserveSig]
			HRESULT IsDirty();

			/// <summary>Initializes an object from the stream where it was saved previously.</summary>
			/// <param name="pstm">The PSTM.</param>
			/// <remarks>
			/// <para>
			/// This method loads an object from its associated stream. The seek pointer is set as it was in the most recent
			/// IPersistStream::Save method. This method can seek and read from the stream, but cannot write to it.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// Rather than calling <c>IPersistStream::Load</c> directly, you typically call the OleLoadFromStream function does the following:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Calls the ReadClassStm function to get the class identifier from the stream.</term>
			/// </item>
			/// <item>
			/// <term>Calls the CoCreateInstance function to create an instance of the object.</term>
			/// </item>
			/// <item>
			/// <term>Queries the instance for IPersistStream.</term>
			/// </item>
			/// <item>
			/// <term>Calls <c>IPersistStream::Load</c>.</term>
			/// </item>
			/// </list>
			/// <para>
			/// The OleLoadFromStream function assumes that objects are stored in the stream with a class identifier followed by the object
			/// data. This storage pattern is used by the generic, composite-moniker implementation provided by OLE.
			/// </para>
			/// <para>If the objects are not stored using this pattern, you must call the methods separately yourself.</para>
			/// <para>URL Moniker Notes</para>
			/// <para>
			/// Initializes an URL moniker from data within a stream, usually stored there previously using its IPersistStream::Save (using
			/// OleSaveToStream). The binary format of the URL moniker is its URL string in Unicode (may be a full or partial URL string,
			/// see CreateURLMonikerEx for details). This is represented as a <c>ULONG</c> count of characters followed by that many Unicode characters.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ipersiststream-load HRESULT Load( IStream *pStm );
			void Load([In, MarshalAs(UnmanagedType.Interface)] IStream pstm);

			/// <summary>Saves an object to the specified stream.</summary>
			/// <param name="pstm">The PSTM.</param>
			/// <param name="fClearDirty">
			/// Indicates whether to clear the dirty flag after the save is complete. If <c>TRUE</c>, the flag should be cleared. If
			/// <c>FALSE</c>, the flag should be left unchanged.
			/// </param>
			/// <remarks>
			/// <para>
			/// <c>IPersistStream::Save</c> saves an object into the specified stream and indicates whether the object should reset its
			/// dirty flag.
			/// </para>
			/// <para>
			/// The seek pointer is positioned at the location in the stream at which the object should begin writing its data. The object
			/// calls the ISequentialStream::Write method to write its data.
			/// </para>
			/// <para>
			/// On exit, the seek pointer must be positioned immediately past the object data. The position of the seek pointer is undefined
			/// if an error returns.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// Rather than calling <c>IPersistStream::Save</c> directly, you typically call the OleSaveToStream helper function which does
			/// the following:
			/// </para>
			/// <list type="number">
			/// <item>
			/// <term>Calls GetClassID to get the object's CLSID.</term>
			/// </item>
			/// <item>
			/// <term>Calls the WriteClassStm function to write the object's CLSID to the stream.</term>
			/// </item>
			/// <item>
			/// <term>Calls <c>IPersistStream::Save</c>.</term>
			/// </item>
			/// </list>
			/// <para>If you call these methods directly, you can write other data into the stream after the CLSID before calling <c>IPersistStream::Save</c>.</para>
			/// <para>The OLE-provided implementation of IPersistStream follows this same pattern.</para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// The <c>IPersistStream::Save</c> method does not write the CLSID to the stream. The caller is responsible for writing the CLSID.
			/// </para>
			/// <para>
			/// The <c>IPersistStream::Save</c> method can read from, write to, and seek in the stream; but it must not seek to a location
			/// in the stream before that of the seek pointer on entry.
			/// </para>
			/// <para>URL Moniker Notes</para>
			/// <para>
			/// Saves an URL moniker to a stream. The binary format of URL moniker is its URL string in Unicode (may be a full or partial
			/// URL string, see CreateURLMonikerEx for details). This is represented as a <c>ULONG</c> count of characters followed by that
			/// many Unicode characters.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ipersiststream-save HRESULT Save( IStream *pStm, BOOL
			// fClearDirty );
			void Save([In, MarshalAs(UnmanagedType.Interface)] IStream pstm, [In, MarshalAs(UnmanagedType.Bool)] bool fClearDirty);

			/// <summary>Retrieves the size of the stream needed to save the object.</summary>
			/// <returns>The size in bytes of the stream needed to save this object, in bytes.</returns>
			/// <remarks>
			/// <para>
			/// This method returns the size needed to save an object. You can call this method to determine the size and set the necessary
			/// buffers before calling the IPersistStream::Save method.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// The <c>GetSizeMax</c> implementation should return a conservative estimate of the necessary size because the caller might
			/// call the IPersistStream::Save method with a non-growable stream.
			/// </para>
			/// <para>URL Moniker Notes</para>
			/// <para>
			/// This method retrieves the maximum number of bytes in the stream that will be required by a subsequent call to
			/// IPersistStream::Save. This value is sizeof(ULONG)==4 plus sizeof(WCHAR)*n where n is the length of the full or partial URL
			/// string, including the NULL terminator.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/desktop/api/objidl/nf-objidl-ipersiststream-getsizemax HRESULT GetSizeMax(
			// ULARGE_INTEGER *pcbSize );
			ulong GetSizeMax();
		}

		/// <summary>
		/// <para>[The use of this interface is not recommended; use the IProcessInitControl interface instead.]</para>
		/// <para>Used by ISurrogateService to prevent the process from terminating due to a time-out.</para>
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-iprocesslock
		[PInvokeData("objidl.h", MSDNShortId = "NN:objidl.IProcessLock")]
		[ComImport, Guid("000001d5-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IProcessLock
		{
			/// <summary>Increments the reference count of the process.</summary>
			/// <returns>This method returns the new reference count.</returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-iprocesslock-addrefonprocess ULONG AddRefOnProcess();
			[PreserveSig]
			uint AddRefOnProcess();

			/// <summary>Decrements the reference count of the process.</summary>
			/// <returns>This method returns the new reference count.</returns>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-iprocesslock-releaserefonprocess ULONG ReleaseRefOnProcess();
			[PreserveSig]
			uint ReleaseRefOnProcess();
		}

		/// <summary>Enables applications and other objects to receive notifications of changes in the progress of a downloading operation.</summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-iprogressnotify
		[PInvokeData("objidl.h", MSDNShortId = "NN:objidl.IProgressNotify")]
		[ComImport, Guid("a9d758a0-4617-11cf-95fc-00aa00680db4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IProgressNotify
		{
			/// <summary>Notifies registered objects and applications of the progress of a downloading operation.</summary>
			/// <param name="dwProgressCurrent">The amount of data available.</param>
			/// <param name="dwProgressMaximum">The total amount of data to be downloaded.</param>
			/// <param name="fAccurate">
			/// Indicates the accuracy of the values in dwProgressCurrent and dwProgressMaximum. They are either reliable ( <c>TRUE</c>) or
			/// unreliable ( <c>FALSE</c>). The <c>FALSE</c> value indicates that control structures for determining the actual position of,
			/// or amount of, data yet to be downloaded are not available.
			/// </param>
			/// <param name="fOwner">
			/// Indicates whether this <c>OnProgress</c> call can control the blocking behavior of the operation. If <c>TRUE</c>, the caller
			/// can use return values from <c>OnProgress</c> to block (STG_S_BLOCK), retry (STG_S_RETRYNOW), or monitor (STG_S_MONITORING)
			/// the operation. If <c>FALSE</c>, the return value from <c>OnProgress</c> has no influence on blocking behavior.
			/// </param>
			/// <returns>
			/// <para>
			/// This method can return the standard return values E_FAIL, E_INVALIDARG, E_OUTOFMEMORY, and E_UNEXPECTED, as well as the
			/// following values.
			/// </para>
			/// <list type="table">
			/// <listheader>
			/// <term>Return code</term>
			/// <term>Description</term>
			/// </listheader>
			/// <item>
			/// <term>STG_S_RETRYNOW</term>
			/// <term>
			/// The caller is to retry the operation immediately. (This value is most useful for applications that do blocking from within
			/// the callback routine.)
			/// </term>
			/// </item>
			/// <item>
			/// <term>STG_S_BLOCK</term>
			/// <term>
			/// The caller is to block the download and retry the call as needed to determine if additional data is available. This is the
			/// default behavior if no sinks are registered on the connection point.
			/// </term>
			/// </item>
			/// <item>
			/// <term>STG_S_MONITORING</term>
			/// <term>
			/// The callback recipient reliquishes control of the downloading process to one of the other objects or applications that have
			/// registered progress notification sinks on the same stream. This is useful if the notification sink is interested only in
			/// gathering statistics.
			/// </term>
			/// </item>
			/// <item>
			/// <term>E_PENDING</term>
			/// <term>
			/// Data is currently unavailable. The caller is to try again after some desired interval. The notification sink returns this
			/// value if the asynchronous storage is to operate in nonblocking mode.
			/// </term>
			/// </item>
			/// </list>
			/// </returns>
			/// <remarks>
			/// <para>
			/// Sinks may be inherited by any substorage or substream of a given storage. If no sink is registered, the thread will block
			/// until the requested data becomes available, or the download is canceled by the downloader.
			/// </para>
			/// <para>
			/// Where multiple objects or applications have registered progress notification sinks on a single stream, only one of them can
			/// control the behavior of a download. Ownership of the download goes to the first sink to register with the storage or stream,
			/// or any advise skinks that may have been inherited from the parent storage (if the storage was created with ASYNC_MODE_COMPATIBILITY.)
			/// </para>
			/// <para>
			/// Any one of the sinks can relinquish control to the next connection point by returning STG_S_MONITORING to the connection
			/// point making the current caller. After a connection point obtains control (through receiving STG_S_BLOCK or STG_S_RETRYNOW),
			/// all subsequent connection points calling <c>OnProgress</c> will set fOwner to <c>FALSE</c>.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-iprogressnotify-onprogress HRESULT OnProgress( DWORD
			// dwProgressCurrent, DWORD dwProgressMaximum, BOOL fAccurate, BOOL fOwner );
			[PreserveSig]
			HRESULT OnProgress(uint dwProgressCurrent, uint dwProgressMaximum, [MarshalAs(UnmanagedType.Bool)] bool fAccurate, [MarshalAs(UnmanagedType.Bool)] bool fOwner);
		}

		/// <summary>Implemented by monikers to enable the running object table (ROT) to compare monikers against each other.</summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-irotdata
		[PInvokeData("objidl.h", MSDNShortId = "NN:objidl.IROTData")]
		[ComImport, Guid("f29f6bc0-5021-11ce-aa15-00006901293f"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IROTData
		{
			/// <summary>Retrieves data from a moniker that can be used to test the moniker for equality against another moniker.</summary>
			/// <param name="pbData">A pointer to a buffer that receives the comparison data.</param>
			/// <param name="cbMax">The length of the buffer specified in pbData.</param>
			/// <param name="pcbData">A pointer to a variable that receives the length of the comparison data.</param>
			/// <returns>This method can return the standard return values E_OUTOFMEMORY and S_OK.</returns>
			/// <remarks>
			/// <para>
			/// The <c>GetComparisonData</c> method is primarily called by the running object table (ROT). The comparison data returned by
			/// the method is tested for binary equality against the comparison data returned by another moniker. The pcbData parameter
			/// enables the ROT to locate the end of the data retrieved.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// The comparison data that you return must uniquely identify the moniker, while still being as short as possible. The
			/// comparison data should include information about the internal state of the moniker, as well as the moniker's CLSID. For
			/// example, the comparison data for a file moniker would include the path name stored within the moniker, as well as the CLSID
			/// of the file moniker implementation. This makes it possible to distinguish two monikers that happen to store similar state
			/// information but are instances of different moniker classes.
			/// </para>
			/// <para>
			/// The comparison data for a moniker cannot exceed 2048 bytes in length. For composite monikers, the total length of the
			/// comparison data for all of its components cannot exceed 2048 bytes; consequently, if your moniker can be a component within
			/// a composite moniker, the comparison data you return must be significantly less than 2048 bytes.
			/// </para>
			/// <para>
			/// If your comparison data is longer than the value specified by the cbMax parameter, you must return an error. Note that when
			/// <c>GetComparisonData</c> is called on the components of a composite moniker, the value of cbMax becomes smaller for each
			/// moniker in sequence.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-irotdata-getcomparisondata HRESULT GetComparisonData(
			// byte *pbData, ULONG cbMax, ULONG *pcbData );
			[PreserveSig]
			HRESULT GetComparisonData([Out] IntPtr pbData, uint cbMax, out uint pcbData);
		}

		/// <summary>
		/// Enables a container to control the running of its embedded objects. In the case of an object implemented with a local server,
		/// calling the Run method launches the server's .EXE file. In the case of an object implemented with an in-process server, calling
		/// <c>Run</c> causes the object .DLL file to transition into the running state.
		/// </summary>
		// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-irunnableobject
		[PInvokeData("objidl.h", MSDNShortId = "NN:objidl.IRunnableObject")]
		[ComImport, Guid("00000126-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IRunnableObject
		{
			/// <summary>Retrieves the CLSID of a running object.</summary>
			/// <param name="lpClsid">A pointer to the object's class identifier.</param>
			/// <returns>This method can return the standard return values E_INVALIDARG, E_UNEXPECTED, and S_OK.</returns>
			/// <remarks>
			/// If an embedded document was created by an application that is not available on the user's computer, the document, by a call
			/// to CoTreatAsClass, may be able to display itself for editing by emulating a class that is supported on the user's machine.
			/// In this case, the CLSID returned by a call to <c>IRunnableObject::GetRunningClass</c> will be that of the class being
			/// emulated, rather than the document's native class.
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-irunnableobject-getrunningclass HRESULT GetRunningClass(
			// LPCLSID lpClsid );
			[PreserveSig]
			HRESULT GetRunningClass(out Guid lpClsid);

			/// <summary>Forces an object to run.</summary>
			/// <param name="pbc">A pointer to the binding context of the run operation. See IBindCtx. This parameter can be <c>NULL</c>.</param>
			/// <returns>This method can return the standard return values E_INVALIDARG, E_UNEXPECTED, and S_OK.</returns>
			/// <remarks>
			/// <para>
			/// Containers call <c>IRunnableObject::Run</c> to force their objects to enter the running state. If the object is not already
			/// running, calling <c>Run</c> can be an expensive operation, on the order of many seconds. If the object is already running,
			/// then this method has no effect on the object.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// When called on a linked object that has been converted to a new class since the link was last activated,
			/// <c>IRunnableObject::Run</c> may return OLE_E_CLASSDIFF. In this case, the client should call IOleLink::BindToSource.
			/// </para>
			/// <para>
			/// OleRun is a helper function that conveniently repackages the functionality offered by <c>IRunnableObject::Run</c>. With the
			/// release of OLE 2.01, the implementation of <c>OleRun</c> was changed so that it calls QueryInterface, asks for
			/// IRunnableObject, and then calls <c>IRunnableObject::Run</c>. In other words, you can use the interface and the helper
			/// function interchangeably.
			/// </para>
			/// <para>Notes to Implementers</para>
			/// <para>
			/// The object should register in the running object table if it has a moniker assigned. The object should not hold any strong
			/// locks on itself; instead, it should remain in the unstable, unlocked state. The object should be locked when the first
			/// external connection is made to the object.
			/// </para>
			/// <para>
			/// An embedded object must hold a lock on its embedding container while it is in the running state. The default handler
			/// provided by OLE 2 takes care of locking the embedding container on behalf of objects implemented by an EXE object
			/// application. Objects implemented by a DLL object application must explicitly put a lock on their embedding containers, which
			/// they do by first calling IOleClientSite::GetContainer to get a pointer to the container, then calling
			/// IOleContainer::LockContainer to actually place the lock. This lock must be released when IOleObject::Close is called.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-irunnableobject-run HRESULT Run( LPBINDCTX pbc );
			[PreserveSig]
			HRESULT Run(IBindCtx pbc);

			/// <summary>Determines whether an object is currently in the running state.</summary>
			/// <returns>If the object is in the running state, the return value is <c>TRUE</c>. Otherwise, it is <c>FALSE</c>.</returns>
			/// <remarks>
			/// <para>
			/// A container application could call <c>IRunnableObject::IsRunning</c> when it needs to know if the server is immediately
			/// available. For example, a container's implementation of the IOleItemContainer::GetObject method would return an error if the
			/// server is not running and the bindspeed parameter specifies BINDSPEED_IMMEDIATE.
			/// </para>
			/// <para>
			/// An object handler could call <c>IRunnableObject::IsRunning</c> when it wants to avoid conflicts with a running server or
			/// when the running server might have more up-to-date information. For example, a handler's implementation of
			/// IOleObject::GetExtent would delegate to the object server if it is running, because the server's information might be more
			/// current than that in the handler's cache.
			/// </para>
			/// <para>
			/// OleIsRunning is a helper function that conveniently repackages the functionality offered by
			/// <c>IRunnableObject::IsRunning</c>. With the release of OLE 2.01, the implementation of <c>OleIsRunning</c> was changed so
			/// that it calls QueryInterface, asks for IRunnableObject, and then calls <c>IRunnableObject::IsRunning</c>. In other words,
			/// you can use the interface and the helper function interchangeably.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-irunnableobject-isrunning BOOL IsRunning();
			[PreserveSig]
			[return: MarshalAs(UnmanagedType.Bool)]
			bool IsRunning();

			/// <summary>Locks an already running object into its running state or unlocks it from its running state.</summary>
			/// <param name="fLock">
			/// <c>TRUE</c> locks the object into its running state. <c>FALSE</c> unlocks the object from its running state.
			/// </param>
			/// <param name="fLastUnlockCloses">
			/// <c>TRUE</c> specifies that if the connection being released is the last external lock on the object, the object should
			/// close. <c>FALSE</c> specifies that the object should remain open until closed by the user or another process.
			/// </param>
			/// <returns>This method can return the standard return values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, E_FAIL, and S_OK.</returns>
			/// <remarks>
			/// <para>Most implementations of <c>IRunnableObject::LockRunning</c> call CoLockObjectExternal.</para>
			/// <para>
			/// OleLockRunning is a helper function that conveniently repackages the functionality offered by
			/// <c>IRunnableObject::LockRunning</c>. With the release of OLE 2.01, the implementation of <c>OleLockRunning</c> was changed
			/// to call QueryInterface, ask for IRunnableObject, and then call <c>IRunnableObject::LockRunning</c>. In other words, you can
			/// use the interface and the helper function interchangeably.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-irunnableobject-lockrunning HRESULT LockRunning( BOOL
			// fLock, BOOL fLastUnlockCloses );
			[PreserveSig]
			HRESULT LockRunning([MarshalAs(UnmanagedType.Bool)] bool fLock, [MarshalAs(UnmanagedType.Bool)] bool fLastUnlockCloses);

			/// <summary>
			/// Notifies an object that it is embedded in an OLE container, which ensures that reference counting is done correctly for
			/// containers that support links to embedded objects.
			/// </summary>
			/// <param name="fContained">
			/// <c>TRUE</c> specifies that the object is contained in an OLE container. <c>FALSE</c> indicates that it is not.
			/// </param>
			/// <returns>This method can return the standard return values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and S_OK.</returns>
			/// <remarks>
			/// <para>
			/// The <c>SetContainedObject</c> method enables a container to inform an object handler that it is embedded in the container,
			/// rather than acting as a link. This call changes the container's reference on the object from strong, the default for
			/// external connections, to weak. When the object is running visibly, this method is of little significance because the end
			/// user has a lock on the object. During a silent update of an embedded link source, however, the container should not be able
			/// to hold an object in the running state after the link has been broken. For this reason, the container's reference to the
			/// object must be weak.
			/// </para>
			/// <para>Notes to Callers</para>
			/// <para>
			/// A container application must call <c>SetContainedObject</c> if it supports linking to embedded objects. It normally makes
			/// the call immediately after calling OleLoad or OleCreate and never calls the method again, even before it closes. Moreover, a
			/// container almost always calls this method with fContained set to <c>TRUE</c>. The use of this method with fContained set to
			/// <c>FALSE</c> is rare.
			/// </para>
			/// <para>
			/// Calling <c>SetContainedObject</c> is optional only when you know that the embedded object will not be referenced by any
			/// client other than the container. If your container application does not support linking to embedded objects; it is
			/// preferable, but not necessary, to call <c>SetContainedObject</c>.
			/// </para>
			/// <para>
			/// OleSetContainedObject is a helper function that conveniently repackages the functionality offered by
			/// <c>SetContainedObject</c>. With the release of OLE 2.01, the implementation of <c>OleSetContainedObject</c> was changed to
			/// call QueryInterface, ask for IRunnableObject, and then call <c>IRunnableObject::SetContainedObject</c>. In other words, you
			/// can use the interface and the helper function interchangeably.
			/// </para>
			/// </remarks>
			// https://docs.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-irunnableobject-setcontainedobject HRESULT
			// SetContainedObject( BOOL fContained );
			[PreserveSig]
			HRESULT SetContainedObject([MarshalAs(UnmanagedType.Bool)] bool fContained);
		}
	}
}