using System; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; using static Vanara.PInvoke.Ole32; namespace Vanara.PInvoke { public static partial class OleAut32 { /// SafeArray advanced features. [Flags] [PInvokeData("OAIdl.h", MSDNShortId = "cc237824")] public enum ADVFEATUREFLAGS : ushort { /// An array that is allocated on the stack. FADF_AUTO = 0x0001, /// An array that is statically allocated. FADF_STATIC = 0x0002, /// An array that is embedded in a structure. FADF_EMBEDDED = 0x0004, /// An array that may not be resized or reallocated. FADF_FIXEDSIZE = 0x0010, /// /// An array that contains records. When set, there will be a pointer to the IRecordInfo interface at negative offset 4 in the /// array descriptor. /// FADF_RECORD = 0x0020, /// /// An array that has an IID identifying interface. When set, there will be a GUID at negative offset 16 in the safe array /// descriptor. Flag is set only when FADF_DISPATCH or FADF_UNKNOWN is also set. /// FADF_HAVEIID = 0x0040, /// An array that has a variant type. The variant type can be retrieved with SafeArrayGetVartype. FADF_HAVEVARTYPE = 0x0080, /// An array of BSTRs. FADF_BSTR = 0x0100, /// An array of IUnknown*. FADF_UNKNOWN = 0x0200, /// An array of IDispatch*. FADF_DISPATCH = 0x0400, /// An array of VARIANTs. FADF_VARIANT = 0x0800 } /// /// Increments the lock count of an array, and retrieves a pointer to the array data. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The array data. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is not valid. /// /// /// E_UNEXPECTED /// The array could not be locked. /// /// /// /// /// After calling SafeArrayAccessData, you must call the SafeArrayUnaccessData function to unlock the array. /// Examples /// /// The following example sorts a safe array of one dimension that contains BSTRs by accessing the array elements directly. This /// approach is faster than using SafeArrayGetElement and SafeArrayPutElement. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayaccessdata HRESULT SafeArrayAccessData( SAFEARRAY // *psa, void HUGEP **ppvData ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "ded2112e-f6cd-4982-bacb-b95370e80187")] public static extern HRESULT SafeArrayAccessData(SafeSAFEARRAY psa, out IntPtr ppvData); /// /// /// The safe array for which the pinning reference count of the descriptor should increase. While that count remains greater than 0, /// the memory for the descriptor is prevented from being freed by calls to the SafeArrayDestroy or SafeArrayDestroyDescriptor functions. /// /// /// Returns the safe array data for which a pinning reference was added, if SafeArrayAddRef also added a pinning reference for /// the safe array data. This parameter is NULL if SafeArrayAddRef did not add a pinning reference for the safe array data. /// SafeArrayAddRef does not add a pinning reference for the safe array data if that safe array data was not dynamically allocated. /// /// /// /// /// The safe array for which the pinning reference count of the descriptor should increase. While that count remains greater than 0, /// the memory for the descriptor is prevented from being freed by calls to the SafeArrayDestroy or SafeArrayDestroyDescriptor functions. /// /// /// /// /// Returns the safe array data for which a pinning reference was added, if SafeArrayAddRef also added a pinning reference for /// the safe array data. This parameter is NULL if SafeArrayAddRef did not add a pinning reference for the safe array data. /// SafeArrayAddRef does not add a pinning reference for the safe array data if that safe array data was not dynamically allocated. /// /// /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// /// Safe arrays have not traditionally had a reference count. All existing usage of safe arrays will continue to work with no /// changes. The SafeArrayAddRef, SafeArrayReleaseData, SafeArrayReleaseDescriptor functions add the ability to use reference /// counting to pin the safe array into memory before calling from an untrusted script into an IDispatch method that may not expect /// the script to free that memory before the method returns, so that the script cannot force the code for that method into accessing /// memory that has been freed. After such a method safely returns, the pinning references should be released. You can release the /// pinning references by calling the following functions: /// /// /// /// SafeArrayReleaseData, for the data that the ppDataToRelease parameter points to, if it is not null. /// /// /// SafeArrayReleaseDescriptor, for the descriptor that the psa parameter specifies. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayaddref HRESULT SafeArrayAddRef( SAFEARRAY *psa, // PVOID *ppDataToRelease ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "0745D2E7-447E-4688-ADCF-1F889BC55BFB")] public static extern HRESULT SafeArrayAddRef(SafeSAFEARRAY psa, out IntPtr ppDataToRelease); /// /// Allocates memory for a safe array, based on a descriptor created with SafeArrayAllocDescriptor. /// /// /// A safe array descriptor created by SafeArrayAllocDescriptor. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is not valid. /// /// /// E_UNEXPECTED /// The array could not be locked. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayallocdata HRESULT SafeArrayAllocData( SAFEARRAY // *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "a1f984cd-9638-415d-8582-25b1bdfbd694")] public static extern HRESULT SafeArrayAllocData(SafeSAFEARRAY psa); /// /// Allocates memory for a safe array descriptor. /// /// /// The number of dimensions of the array. /// /// /// The safe array descriptor. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa was not valid. /// /// /// E_UNEXPECTED /// The array could not be locked. /// /// /// /// /// /// This function allows the creation of safe arrays that contain elements with data types other than those provided by /// SafeArrayCreate. After creating an array descriptor using SafeArrayAllocDescriptor, set the element size in the array /// descriptor, an call SafeArrayAllocData to allocate memory for the array elements. /// /// Examples /// The following example creates a safe array using the SafeArrayAllocDescriptor and SafeArrayAllocData functions. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayallocdescriptor HRESULT SafeArrayAllocDescriptor( // UINT cDims, SAFEARRAY **ppsaOut ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "8fe5c802-cdc0-4e7a-9410-ba65f9a5140e")] public static extern HRESULT SafeArrayAllocDescriptor(uint cDims, out SafeDescriptorSAFEARRAY ppsaOut); /// /// /// Creates a safe array descriptor for an array of any valid variant type, including VT_RECORD, without allocating the array data. /// /// /// /// The variant type. /// /// /// The number of dimensions in the array. /// /// /// The safe array descriptor. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa was not valid. /// /// /// /// /// /// Because SafeArrayAllocDescriptor does not take a VARTYPE, it is not possible to use it to create the safe array descriptor for an /// array of records. The SafeArrayAllocDescriptorEx is used to allocate a safe array descriptor for an array of records of /// the given dimensions. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayallocdescriptorex HRESULT // SafeArrayAllocDescriptorEx( VARTYPE vt, UINT cDims, SAFEARRAY **ppsaOut ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "c368d278-ef62-4cf3-a7f8-c48549207c09")] public static extern HRESULT SafeArrayAllocDescriptorEx(VARTYPE vt, uint cDims, out SafeDescriptorSAFEARRAY ppsaOut); /// /// Creates a copy of an existing safe array. /// /// /// A safe array descriptor created by SafeArrayCreate. /// /// /// The safe array descriptor. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa was not valid. /// /// /// E_OUTOFMEMORY /// Insufficient memory to complete the operation. /// /// /// /// /// /// SafeArrayCopy calls the string or variant manipulation functions if the array to copy contains either of these data types. /// If the array being copied contains object references, the reference counts for the objects are incremented. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycopy HRESULT SafeArrayCopy( SAFEARRAY *psa, // SAFEARRAY **ppsaOut ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "8f84d4f6-1852-4ad8-b174-f3fa37e5bbd6")] public static extern HRESULT SafeArrayCopy(SafeSAFEARRAY psa, out SafeSAFEARRAY ppsaOut); /// /// /// Copies the source array to the specified target array after releasing any resources in the target array. This is similar to /// SafeArrayCopy, except that the target array has to be set up by the caller. The target is not allocated or reallocated. /// /// /// /// The safe array to copy. /// /// /// The target safe array. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa was not valid. /// /// /// E_OUTOFMEMORY /// Insufficient memory to complete the operation. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycopydata HRESULT SafeArrayCopyData( SAFEARRAY // *psaSource, SAFEARRAY *psaTarget ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "32c1fc4f-3fe0-490f-b5af-640514a8cecc")] public static extern HRESULT SafeArrayCopyData(SafeSAFEARRAY psaSource, SafeSAFEARRAY psaTarget); /// /// /// Creates a new array descriptor, allocates and initializes the data for the array, and returns a pointer to the new array descriptor. /// /// /// /// /// The base type of the array (the VARTYPE of each element of the array). The VARTYPE is restricted to a subset of the variant /// types. Neither the VT_ARRAY nor the VT_BYREF flag can be set. VT_EMPTY and VT_NULL are not valid base types for the array. All /// other types are legal. /// /// /// /// The number of dimensions in the array. The number cannot be changed after the array is created. /// /// /// A vector of bounds (one for each dimension) to allocate for the array. /// /// /// A safe array descriptor, or null if the array could not be created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreate SAFEARRAY * SafeArrayCreate( VARTYPE vt, // UINT cDims, SAFEARRAYBOUND *rgsabound ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "5b94f1a2-a558-473f-85dd-9545c0464cc7")] public static extern SafeSAFEARRAY SafeArrayCreate(VARTYPE vt, uint cDims, in SAFEARRAYBOUND rgsabound); /// /// Creates and returns a safe array descriptor from the specified VARTYPE, number of dimensions and bounds. /// /// /// /// The base type or the VARTYPE of each element of the array. The FADF_RECORD flag can be set for a variant type VT_RECORD, The /// FADF_HAVEIID flag can be set for VT_DISPATCH or VT_UNKNOWN, and FADF_HAVEVARTYPE can be set for all other VARTYPEs. /// /// /// /// The number of dimensions in the array. /// /// /// A vector of bounds (one for each dimension) to allocate for the array. /// /// /// /// the type information of the user-defined type, if you are creating a safe array of user-defined types. If the vt parameter is /// VT_RECORD, then pvExtra will be a pointer to an IRecordInfo describing the record. If the vt parameter is VT_DISPATCH or /// VT_UNKNOWN, then pvExtra will contain a pointer to a GUID representing the type of interface being passed to the array. /// /// /// /// A safe array descriptor, or null if the array could not be created. /// /// /// /// If the VARTYPE is VT_RECORD then SafeArraySetRecordInfo is called. If the VARTYPE is VT_DISPATCH or VT_UNKNOWN then the elements /// of the array must contain interfaces of the same type. Part of the process of marshaling this array to other processes does /// include generating the proxy/stub code of the IID pointed to by the pvExtra parameter. To actually pass heterogeneous interfaces /// one will need to specify either IID_IUnknown or IID_IDispatch in pvExtra and provide some other means for the caller to identify /// how to query for the actual interface. /// /// Examples /// The following example describes how a safe array of user-defined types is stored into a variant of type VT_RECORD. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreateex SAFEARRAY * SafeArrayCreateEx( VARTYPE // vt, UINT cDims, SAFEARRAYBOUND *rgsabound, PVOID pvExtra ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "63117428-6676-4fb5-a0ae-7e3b22546d77")] // public static extern SAFEARRAY * SafeArrayCreateEx(VARTYPE vt, uint cDims, ref SAFEARRAYBOUND rgsabound, IntPtr pvExtra); public static extern SafeSAFEARRAY SafeArrayCreateEx(VARTYPE vt, uint cDims, in SAFEARRAYBOUND rgsabound, IntPtr pvExtra); /// /// Creates and returns a safe array descriptor from the specified VARTYPE, number of dimensions and bounds. /// /// /// /// The base type or the VARTYPE of each element of the array. The FADF_RECORD flag can be set for a variant type VT_RECORD, The /// FADF_HAVEIID flag can be set for VT_DISPATCH or VT_UNKNOWN, and FADF_HAVEVARTYPE can be set for all other VARTYPEs. /// /// /// /// The number of dimensions in the array. /// /// /// A vector of bounds (one for each dimension) to allocate for the array. /// /// /// /// the type information of the user-defined type, if you are creating a safe array of user-defined types. If the vt parameter is /// VT_RECORD, then pvExtra will be a pointer to an IRecordInfo describing the record. If the vt parameter is VT_DISPATCH or /// VT_UNKNOWN, then pvExtra will contain a pointer to a GUID representing the type of interface being passed to the array. /// /// /// /// A safe array descriptor, or null if the array could not be created. /// /// /// /// If the VARTYPE is VT_RECORD then SafeArraySetRecordInfo is called. If the VARTYPE is VT_DISPATCH or VT_UNKNOWN then the elements /// of the array must contain interfaces of the same type. Part of the process of marshaling this array to other processes does /// include generating the proxy/stub code of the IID pointed to by the pvExtra parameter. To actually pass heterogeneous interfaces /// one will need to specify either IID_IUnknown or IID_IDispatch in pvExtra and provide some other means for the caller to identify /// how to query for the actual interface. /// /// Examples /// The following example describes how a safe array of user-defined types is stored into a variant of type VT_RECORD. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreateex SAFEARRAY * SafeArrayCreateEx( VARTYPE // vt, UINT cDims, SAFEARRAYBOUND *rgsabound, PVOID pvExtra ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "63117428-6676-4fb5-a0ae-7e3b22546d77")] // public static extern SAFEARRAY * SafeArrayCreateEx(VARTYPE vt, uint cDims, ref SAFEARRAYBOUND rgsabound, IntPtr pvExtra); public static extern SafeSAFEARRAY SafeArrayCreateEx(VARTYPE vt, uint cDims, in SAFEARRAYBOUND rgsabound, IRecordInfo pvExtra); /// /// Creates and returns a safe array descriptor from the specified VARTYPE, number of dimensions and bounds. /// /// /// /// The base type or the VARTYPE of each element of the array. The FADF_RECORD flag can be set for a variant type VT_RECORD, The /// FADF_HAVEIID flag can be set for VT_DISPATCH or VT_UNKNOWN, and FADF_HAVEVARTYPE can be set for all other VARTYPEs. /// /// /// /// The number of dimensions in the array. /// /// /// A vector of bounds (one for each dimension) to allocate for the array. /// /// /// /// the type information of the user-defined type, if you are creating a safe array of user-defined types. If the vt parameter is /// VT_RECORD, then pvExtra will be a pointer to an IRecordInfo describing the record. If the vt parameter is VT_DISPATCH or /// VT_UNKNOWN, then pvExtra will contain a pointer to a GUID representing the type of interface being passed to the array. /// /// /// /// A safe array descriptor, or null if the array could not be created. /// /// /// /// If the VARTYPE is VT_RECORD then SafeArraySetRecordInfo is called. If the VARTYPE is VT_DISPATCH or VT_UNKNOWN then the elements /// of the array must contain interfaces of the same type. Part of the process of marshaling this array to other processes does /// include generating the proxy/stub code of the IID pointed to by the pvExtra parameter. To actually pass heterogeneous interfaces /// one will need to specify either IID_IUnknown or IID_IDispatch in pvExtra and provide some other means for the caller to identify /// how to query for the actual interface. /// /// Examples /// The following example describes how a safe array of user-defined types is stored into a variant of type VT_RECORD. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreateex SAFEARRAY * SafeArrayCreateEx( VARTYPE // vt, UINT cDims, SAFEARRAYBOUND *rgsabound, PVOID pvExtra ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "63117428-6676-4fb5-a0ae-7e3b22546d77")] // public static extern SAFEARRAY * SafeArrayCreateEx(VARTYPE vt, uint cDims, ref SAFEARRAYBOUND rgsabound, IntPtr pvExtra); public static extern SafeSAFEARRAY SafeArrayCreateEx(VARTYPE vt, uint cDims, in SAFEARRAYBOUND rgsabound, in Guid pvExtra); /// /// /// Creates a one-dimensional array. A safe array created with SafeArrayCreateVector is a fixed size, so the constant /// FADF_FIXEDSIZE is always set. /// /// /// /// /// The base type of the array (the VARTYPE of each element of the array). The VARTYPE is restricted to a subset of the variant /// types. Neither the VT_ARRAY nor the VT_BYREF flag can be set. VT_EMPTY and VT_NULL are not valid base types for the array. All /// other types are legal. /// /// /// /// The lower bound for the array. This parameter can be negative. /// /// /// The number of elements in the array. /// /// /// A safe array descriptor, or null if the array could not be created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreatevector SAFEARRAY * SafeArrayCreateVector( // VARTYPE vt, LONG lLbound, ULONG cElements ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "b794b8c6-a523-4636-8681-a936dff3fc6f")] public static extern SafeSAFEARRAY SafeArrayCreateVector(VARTYPE vt, int lLbound, uint cElements); /// /// Creates and returns a one-dimensional safe array of the specified VARTYPE and bounds. /// /// /// /// The base type of the array (the VARTYPE of each element of the array). The FADF_RECORD flag can be set for VT_RECORD. The /// FADF_HAVEIID can be set for VT_DISPATCH or VT_UNKNOWN and FADF_HAVEVARTYPE can be set for all other types. /// /// /// /// The lower bound for the array. This parameter can be negative. /// /// /// The number of elements in the array. /// /// /// /// The type information of the user-defined type, if you are creating a safe array of user-defined types. If the vt parameter is /// VT_RECORD, then pvExtra will be a pointer to an IRecordInfo describing the record. If the vt parameter is VT_DISPATCH or /// VT_UNKNOWN, then pvExtra will contain a pointer to a GUID representing the type of interface being passed to the array. /// /// /// /// A safe array descriptor, or null if the array could not be created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreatevectorex SAFEARRAY * // SafeArrayCreateVectorEx( VARTYPE vt, LONG lLbound, ULONG cElements, PVOID pvExtra ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "45f2ba42-4189-42eb-9f6c-772198296906")] public static extern SafeSAFEARRAY SafeArrayCreateVectorEx(VARTYPE vt, int lLbound, uint cElements, IntPtr pvExtra); /// /// Creates and returns a one-dimensional safe array of the specified VARTYPE and bounds. /// /// /// /// The base type of the array (the VARTYPE of each element of the array). The FADF_RECORD flag can be set for VT_RECORD. The /// FADF_HAVEIID can be set for VT_DISPATCH or VT_UNKNOWN and FADF_HAVEVARTYPE can be set for all other types. /// /// /// /// The lower bound for the array. This parameter can be negative. /// /// /// The number of elements in the array. /// /// /// /// The type information of the user-defined type, if you are creating a safe array of user-defined types. If the vt parameter is /// VT_RECORD, then pvExtra will be a pointer to an IRecordInfo describing the record. If the vt parameter is VT_DISPATCH or /// VT_UNKNOWN, then pvExtra will contain a pointer to a GUID representing the type of interface being passed to the array. /// /// /// /// A safe array descriptor, or null if the array could not be created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreatevectorex SAFEARRAY * // SafeArrayCreateVectorEx( VARTYPE vt, LONG lLbound, ULONG cElements, PVOID pvExtra ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "45f2ba42-4189-42eb-9f6c-772198296906")] public static extern SafeSAFEARRAY SafeArrayCreateVectorEx(VARTYPE vt, int lLbound, uint cElements, IRecordInfo pvExtra); /// /// Creates and returns a one-dimensional safe array of the specified VARTYPE and bounds. /// /// /// /// The base type of the array (the VARTYPE of each element of the array). The FADF_RECORD flag can be set for VT_RECORD. The /// FADF_HAVEIID can be set for VT_DISPATCH or VT_UNKNOWN and FADF_HAVEVARTYPE can be set for all other types. /// /// /// /// The lower bound for the array. This parameter can be negative. /// /// /// The number of elements in the array. /// /// /// /// The type information of the user-defined type, if you are creating a safe array of user-defined types. If the vt parameter is /// VT_RECORD, then pvExtra will be a pointer to an IRecordInfo describing the record. If the vt parameter is VT_DISPATCH or /// VT_UNKNOWN, then pvExtra will contain a pointer to a GUID representing the type of interface being passed to the array. /// /// /// /// A safe array descriptor, or null if the array could not be created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraycreatevectorex SAFEARRAY * // SafeArrayCreateVectorEx( VARTYPE vt, LONG lLbound, ULONG cElements, PVOID pvExtra ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "45f2ba42-4189-42eb-9f6c-772198296906")] public static extern SafeSAFEARRAY SafeArrayCreateVectorEx(VARTYPE vt, int lLbound, uint cElements, in Guid pvExtra); /// /// /// Destroys an existing array descriptor and all of the data in the array. If objects are stored in the array, Release is /// called on each object in the array. /// /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is not valid. /// /// /// DISP_E_ARRAYISLOCKED /// The array is locked. /// /// /// /// /// /// Safe arrays of variant will have the VariantClear function called on each member and safe arrays of BSTR will have the /// SysFreeString function called on each element. IRecordInfo::RecordClear will be called to release object references and other /// values of a record without deallocating the record. /// /// Examples /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraydestroy HRESULT SafeArrayDestroy( SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "fc94f7e7-b903-4c78-905c-54df1f8d13fa")] public static extern HRESULT SafeArrayDestroy(IntPtr psa); /// /// Destroys all the data in the specified safe array. /// /// /// A safe array descriptor. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa was not valid. /// /// /// DISP_E_ARRAYISLOCKED /// The array is locked. /// /// /// /// /// /// This function is typically used when freeing safe arrays that contain elements with data types other than variants. If objects /// are stored in the array, Release is called on each object in the array. Safe arrays of variant will have the VariantClear /// function called on each member and safe arrays of BSTR will have the SysFreeString function called on each element. /// IRecordInfo::RecordClear will be called to release object references and other values of a record without deallocating the record. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraydestroydata HRESULT SafeArrayDestroyData( // SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "aa9c62ba-79b5-4fcf-b3ed-664016486dfc")] public static extern HRESULT SafeArrayDestroyData(SafeSAFEARRAY psa); /// /// Destroys the descriptor of the specified safe array. /// /// /// A safe array descriptor. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa was not valid. /// /// /// DISP_E_ARRAYISLOCKED /// The array is locked. /// /// /// /// /// /// This function is typically used to destroy the descriptor of a safe array that contains elements with data types other than /// variants. Destroying the array descriptor does not destroy the elements in the array. Before destroying the array descriptor, /// call SafeArrayDestroyData to free the elements. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraydestroydescriptor HRESULT // SafeArrayDestroyDescriptor( SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "f1e8de45-673b-4f20-a639-18c724c82df1")] public static extern HRESULT SafeArrayDestroyDescriptor(IntPtr psa); /// /// Gets the number of dimensions in the array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The number of dimensions in the array. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetdim UINT SafeArrayGetDim( SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "bc52b23b-d323-478c-881f-d2a31a3289c5")] public static extern uint SafeArrayGetDim(SafeSAFEARRAY psa); /// /// Retrieves a single element of the array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// /// A vector of indexes for each dimension of the array. The right-most (least significant) dimension is rgIndices[0]. The left-most /// dimension is stored at . /// /// /// /// The element of the array. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// DISP_E_BADINDEX /// The specified index is not valid. /// /// /// E_INVALIDARG /// One of the arguments is not valid. /// /// /// E_OUTOFMEMORY /// Memory could not be allocated for the element. /// /// /// /// /// /// This function calls SafeArrayLock and SafeArrayUnlock automatically, before and after retrieving the element. The caller must /// provide a storage area of the correct size to receive the data. If the data element is a string, object, or variant, the function /// copies the element in the correct way. /// /// Examples /// The following example is taken from the COM Fundamentals SPoly sample (Cenumpt.cpp). /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetelement HRESULT SafeArrayGetElement( SAFEARRAY // *psa, LONG *rgIndices, void *pv ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "47e9ee31-1e3b-4193-8467-6ef0db05966e")] public static extern HRESULT SafeArrayGetElement(SafeSAFEARRAY psa, [MarshalAs(UnmanagedType.LPArray)] int[] rgIndices, [Out] IntPtr pv); /// /// Gets the size of an element. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The size of an element in a safe array, in bytes. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetelemsize UINT SafeArrayGetElemsize( SAFEARRAY // *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "27bd4a3f-0e9d-45f7-ad7c-0c0b59579dd0")] public static extern int SafeArrayGetElemsize(SafeSAFEARRAY psa); /// /// Gets the GUID of the interface contained within the specified safe array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The GUID of the interface. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is null or the array descriptor does not have the FADF_HAVEIID flag set. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetiid HRESULT SafeArrayGetIID( SAFEARRAY *psa, // GUID *pguid ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "9416f7f8-aee0-4e6a-be4f-ca6061adb244")] public static extern HRESULT SafeArrayGetIID(SafeSAFEARRAY psa, out Guid pguid); /// /// Gets the lower bound for any dimension of the specified safe array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The array dimension for which to get the lower bound. /// /// /// The lower bound. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// One of the arguments is not valid. /// /// /// DISP_E_BADINDEX /// The specified index is out of bounds. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetlbound HRESULT SafeArrayGetLBound( SAFEARRAY // *psa, UINT nDim, LONG *plLbound ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "f3134cc9-759b-4908-ada0-d025a525e795")] public static extern HRESULT SafeArrayGetLBound(SafeSAFEARRAY psa, uint nDim, out int plLbound); /// /// Retrieves the IRecordInfo interface of the UDT contained in the specified safe array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The IRecordInfo interface. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is null or the array descriptor does not have the FADF_RECORD flag set. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetrecordinfo HRESULT SafeArrayGetRecordInfo( // SAFEARRAY *psa, IRecordInfo **prinfo ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "1584c00e-06a5-44f4-8c4b-a2b23737a652")] public static extern HRESULT SafeArrayGetRecordInfo(SafeSAFEARRAY psa, out IRecordInfo prinfo); /// /// Gets the upper bound for any dimension of the specified safe array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The array dimension for which to get the upper bound. /// /// /// The upper bound. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// DISP_E_BADINDEX /// The specified index is out of bounds. /// /// /// DISP_E_OVERFLOW /// Overflow occurred while computing the upper bound. /// /// /// E_INVALIDARG /// One of the arguments is not valid. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetubound HRESULT SafeArrayGetUBound( SAFEARRAY // *psa, UINT nDim, LONG *plUbound ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "aed339d5-d962-4adc-ac01-6c15a54c51ca")] public static extern HRESULT SafeArrayGetUBound(SafeSAFEARRAY psa, uint nDim, out int plUbound); /// /// Gets the VARTYPE stored in the specified safe array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// The VARTYPE. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// One of the arguments is not valid. /// /// /// /// /// /// If FADF_HAVEVARTYPE is set, SafeArrayGetVartype returns the VARTYPE stored in the array descriptor. If FADF_RECORD is set, /// it returns VT_RECORD; if FADF_DISPATCH is set, it returns VT_DISPATCH; and if FADF_UNKNOWN is set, it returns VT_UNKNOWN. /// /// /// SafeArrayGetVartype can fail to return VT_UNKNOWN for SAFEARRAY types that are based on IUnknown. Callers should /// additionally check whether the SAFEARRAY type's fFeatures field has the FADF_UNKNOWN flag set. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraygetvartype HRESULT SafeArrayGetVartype( SAFEARRAY // *psa, VARTYPE *pvt ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "8ec0e736-bac8-4df4-ba32-433cd8478c55")] public static extern HRESULT SafeArrayGetVartype(SafeSAFEARRAY psa, out VARTYPE pvt); /// /// Increments the lock count of an array, and places a pointer to the array data in pvData of the array descriptor. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is not valid. /// /// /// E_UNEXPECTED /// The array could not be locked. /// /// /// /// /// /// The pointer in the array descriptor is valid until the SafeArrayUnlock function is called. Calls to SafeArrayLock can be /// nested, in which case an equal number of calls to SafeArrayUnlock are required. /// /// An array cannot be deleted while it is locked. /// Thread Safety /// /// All public static (Shared in Visual Basic) members of the SAFEARRAY data type are thread safe. Instance members are not /// guaranteed to be thread safe. /// /// /// For example, consider an application that uses the SafeArrayLock and SafeArrayUnlock functions. If these functions are called /// concurrently from different threads on the same SAFEARRAY data type instance, an inconsistent lock count may be created. This /// will eventually cause the SafeArrayUnlock function to return E_UNEXPECTED. You can prevent this by providing your own /// synchronization code. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraylock HRESULT SafeArrayLock( SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "cb29d862-c7c5-4852-b017-c29e88d5f1c4")] public static extern HRESULT SafeArrayLock(SafeSAFEARRAY psa); /// Gets a pointer to an array element. /// An array descriptor created by SafeArrayCreate. /// /// An array of index values that identify an element of the array. All indexes for the element must be specified. /// /// The array element. /// /// This function can return one of these values. /// /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// DISP_E_BADINDEX /// The specified index is not valid. /// /// /// E_INVALIDARG /// One of the arguments is not valid. /// /// /// /// // HRESULT SafeArrayPtrOfIndex( _In_ SAFEARRAY *psa, _In_ LONG *rgIndices, _Out_ void **ppvData); https://msdn.microsoft.com/en-us/library/windows/desktop/ms221452(v=vs.85).aspx [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("OleAuto.h", MSDNShortId = "ms221452")] public static extern HRESULT SafeArrayPtrOfIndex(SafeSAFEARRAY psa, [In] int[] rgIndices, out IntPtr ppvData); /// /// Stores the data element at the specified location in the array. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// /// A vector of indexes for each dimension of the array. The right-most (least significant) dimension is rgIndices[0]. The left-most /// dimension is stored at . /// /// /// /// /// The data to assign to the array. The variant types VT_DISPATCH, VT_UNKNOWN, and VT_BSTR are pointers, and do not require another /// level of indirection. /// /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// DISP_E_BADINDEX /// The specified index is not valid. /// /// /// E_INVALIDARG /// One of the arguments is not valid. /// /// /// E_OUTOFMEMORY /// Memory could not be allocated for the element. /// /// /// /// /// /// This function automatically calls SafeArrayLock and SafeArrayUnlock before and after assigning the element. If the data element /// is a string, object, or variant, the function copies it correctly when the safe array is destroyed. If the existing element is a /// string, object, or variant, it is cleared correctly. If the data element is a VT_DISPATCH or VT_UNKNOWN, AddRef is called /// to increment the object's reference count. /// /// Note Multiple locks can be on an array. Elements can be put into an array while the array is locked by other operations. /// /// For an example that demonstrates calling SafeArrayPutElement, see the COM Fundamentals Lines sample (CLines::Add in Lines.cpp). /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayputelement HRESULT SafeArrayPutElement( SAFEARRAY // *psa, LONG *rgIndices, void *pv ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "7c837b4f-d319-4d98-934a-b585fe521bf8")] public static extern HRESULT SafeArrayPutElement(SafeSAFEARRAY psa, [MarshalAs(UnmanagedType.LPArray)] int[] rgIndicies, [In] IntPtr pv); /// /// Changes the right-most (least significant) bound of the specified safe array. /// /// /// A safe array descriptor. /// /// /// /// A new safe array bound structure that contains the new array boundary. You can change only the least significant dimension of an array. /// /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is not valid. /// /// /// DISP_E_ARRAYISLOCKED /// The array is locked. /// /// /// /// /// /// If you reduce the bound of an array, SafeArrayRedim deallocates the array elements outside the new array boundary. If the /// bound of an array is increased, SafeArrayRedim allocates and initializes the new array elements. The data is preserved for /// elements that exist in both the old and new array. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayredim HRESULT SafeArrayRedim( SAFEARRAY *psa, // SAFEARRAYBOUND *psaboundNew ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "1c7fa627-e5e4-4bb9-8237-2f7358ebc4b8")] public static extern HRESULT SafeArrayRedim(SafeSAFEARRAY psa, in SAFEARRAYBOUND psaboundNew); /// /// The safe array data for which the pinning reference count should decrease. /// /// /// The safe array data for which the pinning reference count should decrease. /// /// /// This function does not return a value. /// /// /// /// A call to the SafeArrayReleaseData function should match every previous call to the SafeArrayAddRef function that returned /// a non-null value in the ppDataToRelease parameter. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayreleasedata void SafeArrayReleaseData( PVOID // pData ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "AF3C36A3-2B3A-4159-8183-DB082FBFD215")] public static extern void SafeArrayReleaseData(IntPtr pData); /// /// The safe array for which the pinning reference count of the descriptor should decrease. /// /// /// The safe array for which the pinning reference count of the descriptor should decrease. /// /// /// This function does not return a value. /// /// /// A call to the SafeArrayReleaseDescriptor function should match every previous call to the SafeArrayAddRef function. /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayreleasedescriptor void // SafeArrayReleaseDescriptor( SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "D6678B17-B537-46CF-AC64-4D0C0DC4CDF3")] public static extern void SafeArrayReleaseDescriptor(SafeSAFEARRAY psa); /// /// Sets the GUID of the interface for the specified safe array. /// /// /// The safe array descriptor. /// /// /// The IID. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is null or the array descriptor does not have the FADF_HAVEIID flag set. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraysetiid HRESULT SafeArraySetIID( SAFEARRAY *psa, // REFGUID guid ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "851b8a44-9da4-418c-88bc-80c9fc55d25c")] public static extern HRESULT SafeArraySetIID(SafeSAFEARRAY psa, in Guid guid); /// /// Sets the record info in the specified safe array. /// /// /// The array descriptor. /// /// /// The record info. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is null or the array descriptor does not have the FADF_RECORD flag set. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearraysetrecordinfo HRESULT SafeArraySetRecordInfo( // SAFEARRAY *psa, IRecordInfo *prinfo ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "85317e8e-7625-4799-9c34-73245f164f85")] public static extern HRESULT SafeArraySetRecordInfo(SafeSAFEARRAY psa, IRecordInfo prinfo); /// /// Decrements the lock count of an array, and invalidates the pointer retrieved by SafeArrayAccessData. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is not valid. /// /// /// E_UNEXPECTED /// The array could not be unlocked. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayunaccessdata HRESULT SafeArrayUnaccessData( // SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "61b482cb-f0a3-4efb-9a68-f373f241e89a")] public static extern HRESULT SafeArrayUnaccessData(SafeSAFEARRAY psa); /// /// Decrements the lock count of an array so it can be freed or resized. /// /// /// An array descriptor created by SafeArrayCreate. /// /// /// This function can return one of these values. /// /// /// Return code /// Description /// /// /// S_OK /// Success. /// /// /// E_INVALIDARG /// The argument psa is not valid. /// /// /// E_UNEXPECTED /// The array could not be unlocked. /// /// /// /// /// This function is called after access to the data in an array is finished. /// Thread Safety /// /// All public static members of the SAFEARRAY data type are thread safe. Instance members are not guaranteed to be thread safe. /// /// /// For example, consider an application that uses the SafeArrayLock and SafeArrayUnlock functions. If these functions are called /// concurrently from different threads on the same SAFEARRAY data type instance, an inconsistent lock count may be created. This /// will eventually cause the SafeArrayUnlock function to return E_UNEXPECTED. You can prevent this by providing your own /// synchronization code. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/nf-oleauto-safearrayunlock HRESULT SafeArrayUnlock( SAFEARRAY *psa ); [DllImport(Lib.OleAut32, SetLastError = false, ExactSpelling = true)] [PInvokeData("oleauto.h", MSDNShortId = "654995ab-1959-44dc-9e26-11c34e489c14")] public static extern HRESULT SafeArrayUnlock(SafeSAFEARRAY psa); /// Represents a safe array. /// [StructLayout(LayoutKind.Sequential, Pack = 4)] [PInvokeData("OaIdl.h", MSDNShortId = "ms221482")] public struct SAFEARRAY { /// The number of dimensions. public ushort cDims; /// Flags. public ADVFEATUREFLAGS fFeatures; /// The size of an array element. public uint cbElements; /// The number of times the array has been locked without a corresponding unlock. public uint cLocks; /// The data. public IntPtr pvData; /// One bound for each dimension. public IntPtr rgsabound; /// Gets the bounds pointed to by . public SAFEARRAYBOUND[] Bounds => rgsabound.ToArray(cDims); } /// Represents the bounds of one dimension of the array. [StructLayout(LayoutKind.Sequential, Pack = 4)] [PInvokeData("OaIdl.h", MSDNShortId = "ms221167")] public struct SAFEARRAYBOUND { /// The number of elements in the dimension. public uint cElements; /// The lower bound of the dimension. public int lLbound; /// Initializes a new instance of the struct. /// The number of elements in the dimension. /// The lower bound of the dimension. public SAFEARRAYBOUND(uint upperBound, int lowerBound = 0) { cElements = upperBound; lLbound = lowerBound; } } /// Provides a to a safe array that releases a created SAFEARRAY instance at disposal using SafeArrayDestroy. public class SafeSAFEARRAY : HANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// to reliably release the handle during the finalization phase; otherwise, (not recommended). public SafeSAFEARRAY(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. protected SafeSAFEARRAY() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator SAFEARRAY(SafeSAFEARRAY h) => h.IsInvalid ? new SAFEARRAY() : (SAFEARRAY)Marshal.PtrToStructure(h.handle, typeof(SAFEARRAY)); /// protected override bool InternalReleaseHandle() => SafeArrayDestroy(handle).Succeeded; } public class SafeDescriptorSAFEARRAY : SafeSAFEARRAY { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// to reliably release the handle during the finalization phase; otherwise, (not recommended). public SafeDescriptorSAFEARRAY(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeDescriptorSAFEARRAY() : base() { } /// protected override bool InternalReleaseHandle() => SafeArrayDestroyDescriptor(handle).Succeeded; } /// Construct for handling the paired calling of and . /// /// /// using (var data = new SafeArrayScopedAccessData(safeArray)) /// { /// // The Data property provides access to the array's data while in scope. /// FILETIME ft = (FILETIME)Marshal.PtrToStructure(data.Data, typeof(FILETIME)); /// } /// /// /// [PInvokeData("OleAuto.h")] public class SafeArrayScopedAccessData : IDisposable { private readonly SafeSAFEARRAY psa; private IntPtr ppvData; /// /// Initializes a new instance of the class using the array descriptor that holds the data. /// /// An array descriptor created by SafeArrayCreate. public SafeArrayScopedAccessData(SafeSAFEARRAY psa) { var hr = SafeArrayAccessData(psa, out ppvData); hr.ThrowIfFailed(); this.psa = psa; } /// Gets the pointer exposed by the call to . /// A pointer to the raw data within the array descriptor. public IntPtr Data => ppvData; /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. public void Dispose() { SafeArrayUnaccessData(psa); ppvData = IntPtr.Zero; } } } }