using System; using System.Runtime.InteropServices; using System.Security; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; namespace Vanara.PInvoke { public static partial class Ole32 { /// /// The PROPSETFLAG constants define characteristics of a property set. The values, listed in the following table, are used in the /// grfFlags parameter of IPropertySetStorage methods, the StgCreatePropStg function, and the StgOpenPropStg function. /// /// /// /// These values can be set and checked using bitwise operations that determine how property sets are created and opened. Property /// sets are created using the IPropertySetStorage::Create method or the StgCreatePropStg function. They are opened /// using the IPropertySetStorage::Open method or the StgOpenPropStg function. /// /// /// It is recommended that property sets be created as Unicode by not setting the PROPSETFLAG_ANSI flag in the grfFlags /// parameter. It is also recommended that you avoid using VT_LPSTR values, and use VT_LPWSTR values instead. When the property set /// code page is Unicode, VT_LPSTR string values are converted to Unicode when stored, and converted back to multibyte string values /// when retrieved. When the code page of the property set is not Unicode, property names, VT_BSTR strings, and nonsimple property /// values are converted to multibyte strings when stored, and converted back to Unicode when retrieved, all using the current system /// ANSI code page. /// /// // https://docs.microsoft.com/en-us/windows/desktop/Stg/propsetflag-constants [PInvokeData("Propidl.h", MSDNShortId = "6f865c8f-bbca-4122-b076-14f2bc56f292")] [Flags] public enum PROPSETFLAG : uint { /// /// If left unspecified, by default only simple property values may be written to the property set. Using simple property values /// prevents property sets from being transacted in the compound file and stand-alone implementations of IPropertySetStorage. /// Non-e property values must be used for this purpose. /// PROPSETFLAG_DEFAULT = 0, /// /// If specified, nonsimple property values can be written to the property set and the property set is saved in a storage object. /// Non-simple property values include those with a VARTYPE of VT_STORAGE, VT_STREAM, VT_STORED_OBJECT, or VT_STREAMED_OBJECT. If /// this flag is not specified, non-simple types cannot be written into the property set. In the compound file and stand-alone /// implementations, property sets may be transacted only if PROPSETFLAG_NONSIMPLE is specified. /// PROPSETFLAG_NONSIMPLE = 1, /// /// If specified, all string values in the property set that are not explicitly Unicode, that is, those other than VT_LPWSTR, are /// stored with the current system ANSI code page. For more information, see GetACP. Use of this value is not recommended. For /// more information, see Remarks. /// /// If this value is absent, string values in the new property set are stored in Unicode. The degree of control that this value /// provides is necessary so that clients using the property-related interfaces can interoperate with standard property sets such /// as the OLE2 summary information, which may exist in the ANSI code page. /// /// PROPSETFLAG_ANSI = 2, /// /// Used only with the StgCreatePropStg and StgOpenPropStg functions; that is, in the stand-alone implementations of property set /// interfaces. If specified in these functions, changes to the property set are not buffered. Instead, changes are always /// written directly to the property set. Calls to a property set IPropertyStorage methods will change it. However, by default, /// changes are buffered in an internal property set cache and are subsequently written to the property set when the /// IPropertyStorage::Commit method is called. /// /// Setting PROPSETFLAG_UNBUFFERED decreases performance because the property set internal buffer is automatically flushed after /// every change to the property set.However, writing changes directly will prevent coordination problems.For example, if the /// storage object is opened in transacted mode, and the property set is buffered.Then, if you call the IStorage::Commit method /// on the storage object, the property set changes will not be picked up as part of the transaction, because they are in a /// buffer that has not been flushed yet. You must call IPropertyStorage::Commit prior to calling IStorage::Commit to flush the /// property set buffer before committing changes to the storage.As an alternative to making two calls, you can set /// PROPSETFLAG_UNBUFFERED so that changes are always written directly to the property set and are never buffered in the property /// set's internal cache. Then, the changes will be picked up when the transacted storage is committed. /// /// PROPSETFLAG_UNBUFFERED = 4, /// /// If specified, property names are case sensitive. Case-sensitive property names are only possible in the version 1 property /// set serialization format. For more information, see Property Set Serialization. /// PROPSETFLAG_CASE_SENSITIVE = 8 } /// Values used in PROPSPEC. [PInvokeData("propidl.h", MSDNShortId = "5bb3b9c6-ab82-498c-94f9-13a9ffa7452b")] public enum PRSPEC { /// The lpwstr member is used and set to a string name. PRSPEC_LPWSTR = 0, /// The propid member is used and set to a property ID value. PRSPEC_PROPID = 1 } /// /// /// The IEnumSTATPROPSETSTG interface iterates through an array of STATPROPSETSTG structures. The STATPROPSETSTG /// structures contain statistical data about the property sets managed by the current IPropertySetStorage instance. /// IEnumSTATPROPSETSTG has the same methods as all enumerator interfaces: Next, Skip, Reset, and Clone. /// /// /// The implementation defines the order in which the property sets are enumerated. Property sets that are present when the /// enumerator is created, and are not removed during the enumeration, will be enumerated only once. Property sets added or deleted /// while the enumeration is in progress may or may not be enumerated, but, if enumerated, will not be enumerated more than once. /// /// /// For more information about how the COM compound document implementation of IEnumSTATPROPSETSTG::Next supplies members of the /// STATPROPSETSTG structure, see IEnumSTATPROPSETSTG--Compound File Implementation. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nn-propidl-ienumstatpropsetstg [PInvokeData("propidl.h", MSDNShortId = "8d5e658f-312c-4c91-8794-808b2e8dd182")] [ComImport, Guid("0000013B-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IEnumSTATPROPSETSTG { /// /// /// The Next method retrieves a specified number of STATPROPSETSTG structures that follow subsequently in the enumeration /// sequence. If fewer than the requested number of STATPROPSETSTG structures exist in the enumeration sequence, it retrieves the /// remaining STATPROPSETSTG structures. /// /// /// /// The number of STATPROPSETSTG structures requested. /// /// /// An array of STATPROPSETSTG structures returned. /// /// /// The number of STATPROPSETSTG structures retrieved in the parameter. /// /// /// This method supports the following return values: /// /// /// Return code /// Description /// /// /// S_OK /// The number of STATPROPSETSTG structures returned equals the number specified in the parameter. /// /// /// S_FALSE /// The number of STATPROPSETSTG structures returned is less than the number specified in the parameter. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropsetstg-next [PreserveSig] HRESULT Next(uint celt, IntPtr rgelt, out uint pceltFetched); /// /// The Skip method skips a specified number of STATPROPSETSTG structures in the enumeration sequence. /// /// /// The number of STATPROPSETSTG structures to skip. /// /// /// This method supports the following return values: /// /// /// /// A positive value for the parameter skips forward in the STATPROPSETSTG structure enumeration. A negative value for the /// parameter skips backward in the STATPROPSETSTG structure enumeration. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropsetstg-skip [PreserveSig] HRESULT Skip(uint celt); /// /// The Reset method resets the enumeration sequence to the beginning of the STATPROPSETSTG structure array. /// /// /// This method supports the S_OK return value. /// /// /// Return code /// Description /// /// /// S_OK /// The enumeration sequence was successfully reset to the beginning of the enumeration. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropsetstg-reset void Reset(); /// /// /// The Clone method creates an enumerator that contains the same enumeration state as the current STATPROPSETSTG /// structure enumerator. Using this method, a client can record a particular point in the enumeration sequence and then return /// to that point later. The new enumerator supports the same IEnumSTATPROPSETSTG interface. /// /// /// /// A pointer to the variable that receives the IEnumSTATPROPSETSTG interface pointer. /// If the method does not succeed, the value of the parameter is undefined. /// This method supports exceptions listed in the following table. /// /// /// Return code /// Description /// /// /// E_INVALIDARG /// The parameter is NULL. /// /// /// E_OUTOFMEMORY /// Insufficient memory. /// /// /// E_UNEXPECTED /// An unexpected exception occurred. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropsetstg-clone IEnumSTATPROPSETSTG Clone(); } /// /// /// The IEnumSTATPROPSTG interface iterates through an array of STATPROPSTG structures. The STATPROPSTG structures /// contain statistical data about properties in a property set. IEnumSTATPROPSTG has the same methods as all enumerator /// interfaces: Next, Skip, Reset, and Clone. /// /// /// The implementation defines the order in which the properties in the set are enumerated. Properties that are present when the /// enumerator is created, and are not removed during the enumeration, will be enumerated only once. Properties added or deleted /// while the enumeration is in progress may or may not be enumerated, but will never be enumerated more than once. /// /// /// Reserved property identifiers, properties with a property ID of 0 (dictionary), 1 (code page indicator), or greater than or equal /// to 0x80000000 are not enumerated. /// /// /// Enumeration of a nonsimple property does not necessarily indicate that the property can be read successfully through a call to /// IPropertyStorage::ReadMultiple. This is because the performance overhead of checking existence of the indirect stream or storage /// is prohibitive during property enumeration. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nn-propidl-ienumstatpropstg [PInvokeData("propidl.h", MSDNShortId = "e625e52a-5628-4d18-9282-aa1c141c83af")] [ComImport, Guid("00000139-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IEnumSTATPROPSTG { /// /// /// The Next method retrieves a specified number of STATPROPSTG structures, that follow subsequently in the enumeration /// sequence. If fewer than the requested number of STATPROPSTG structures exist in the enumeration sequence, it retrieves the /// remaining STATPROPSTG structures. /// /// /// /// The number of STATPROPSTG structures requested. /// /// /// An array of STATPROPSTG structures returned. /// /// /// The number of STATPROPSTG structures retrieved in the parameter. /// /// /// This method supports the following return values. /// /// /// Return code /// Description /// /// /// S_OK /// The number of STATPROPSTG structures returned is equal to the number specified in the parameter. /// /// /// S_FALSE /// The number of STATPROPSTG structures returned is less than the number specified in the parameter. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropstg-next [PreserveSig] HRESULT Next(uint celt, IntPtr rgelt, out uint pceltFetched); /// /// The Skip method skips the specified number of STATPROPSTG structures in the enumeration sequence. /// /// /// The number of STATPROPSTG structures to skip. /// /// /// This method supports the following return values: /// /// /// /// A positive value for the parameter skips forward in the STATPROPSTG structure enumeration. A negative value for the parameter /// skips backward in the STATPROPSTG structure enumeration. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropstg-skip [PreserveSig] HRESULT Skip(uint celt); /// /// The Reset method resets the enumeration sequence to the beginning of the STATPROPSTG structure array. /// /// /// This method supports the S_OK return value. /// /// /// Return code /// Description /// /// /// S_OK /// The enumeration sequence was successfully reset to the beginning of the enumeration. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropstg-reset void Reset(); /// /// /// The Clone method creates an enumerator that contains the same enumeration state as the current STATPROPSTG structure /// enumerator. Using this method, a client can record a particular point in the enumeration sequence and then return to that /// point later. The new enumerator supports the same IEnumSTATPROPSTG interface. /// /// /// /// A pointer to the variable that receives the IEnumSTATPROPSTG interface pointer. /// If the method is unsuccessful, the value of the parameter is undefined. /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ienumstatpropstg-clone IEnumSTATPROPSTG Clone(); } /// /// The IPropertySetStorage interface creates, opens, deletes, and enumerates property set storages that support instances of the /// IPropertyStorage interface. The IPropertyStorage interface manages a single property set in a property storage subobject; and the /// IPropertySetStorage interface manages the storage of groups of such property sets. Any file system entity can support /// IPropertySetStorage that is currently implemented in the COM compound file object. /// /// The IPropertySetStorage and IPropertyStorage interfaces provide a uniform way to create and manage property sets, whether or not /// these sets reside in a storage object that supports IStorage.When called through an object supporting IStorage (such as /// structured and compound files) or IStream, the property sets created conform to the COM property set format, described in detail /// in Structured Storage Serialized Property Set Format.Similarly, properties written using IStorage to the COM property set format /// are visible through IPropertySetStorage and IPropertyStorage. /// /// /// IPropertySetStorage methods identify property sets through a globally unique identifier (GUID) called a format identifier /// (FMTID). The FMTID for a property set identifies the property identifiers in the property set, their meaning, and any constraints /// on the values. The FMTID of a property set should also provide the means to manipulate that property set. Only one instance of a /// given FMTID may exist at a time within a single property storage. /// /// [PInvokeData("Propidl.h", MSDNShortId = "0ea3e1e0-c135-4138-81e4-f72412fc3128")] [ComImport, Guid("0000013A-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPropertySetStorage { /// /// The Create method creates and opens a new property set in the property set storage object. /// /// /// /// /// A pointer to the initial class identifier CLSID for this property set. May be NULL, in which case it is set to all /// zeroes. The CLSID is the CLSID of a class that displays and/or provides programmatic access to the property values. If there /// is no such class, it is recommended that the FMTID be used. /// /// /// /// The values from PROPSETFLAG Constants. /// /// /// /// An access mode in which the newly created property set is to be opened, taken from certain values of STGM_Constants, as /// described in the following Remarks section. /// /// /// /// /// This method supports the standard return value E_UNEXPECTED, as well as the following: /// /// /// /// IPropertySetStorage::Create creates and opens a new property set subobject (supporting the IPropertyStorage interface) /// contained in this property set storage object. The property set automatically contains code page and locale ID properties. /// These are set to the Unicode and the current user default, respectively. /// /// /// The parameter is a combination of values taken from PROPSETFLAG Constants. If the PROPSETFLAG_ANSI value from this /// enumeration is used, the code page is set to the current system default, rather than Unicode. /// /// /// The parameter specifies the access mode in which the newly created set is to be opened. Values for this parameter are as in /// the parameter to IPropertySetStorage::Open, with the addition of the values listed in the following table. /// /// /// /// Value /// Meaning /// /// /// STGM_FAILIFTHERE /// /// If another property set with the specified parameter exists, the call fails. This is the default action; that is, unless /// STGM_CREATE is specified, STGM_FAILIFTHERE is implied. /// /// /// /// STGM_CREATE /// If another property set with the specified parameter already exists, it is removed and replaced with this new one. /// /// /// /// The created property set is simple by default, but the caller may request a nonsimple property set by specifying the /// PROPSETFLAG_NONSIMPLE value in the parameter. For more information about simple and nonsimple property sets, see Storage and /// Stream Objects for a Property Set. /// /// /// This method is subject to the constraints of the underlying IStorage::CreateStream (for simple property sets) or /// IStorage::CreateStorage (for nonsimple property sets). For example, when using the IPropertySetStorage-Compound File /// Implementation, specify STGM_SHARE_EXCLUSIVE in the parameter to IPropertySetStorage::Create. Conversely, if using the /// IPropertySetStorage-Stand-alone Implementation, IPropertySetStorage::Create is subject to constraints that apply to /// the caller-specified IStorage. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertysetstorage-create [PreserveSig] HRESULT Create(in Guid rfmtid, [In] IntPtr pclsid, [In] STGM grfFlags, [In] STGM grfMode, out IPropertyStorage ppprstg); /// /// The Open method opens a property set contained in the property set storage object. /// /// /// /// /// The access mode in which the newly created property set is to be opened. These flags are taken from STGM Constants. Flags /// that may be used and their meanings in the context of this method are described in the following Remarks section. /// /// /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// The mode in which the property set is to be opened is specified in the parameter . These flags are taken from STGM Constants, /// but, for this method, legal values and their meanings are as follows (only certain combinations of these flag values are legal). /// /// /// /// Value /// Meaning /// /// /// STGM_DIRECT /// /// Opens the property set without an additional level of transaction nesting. This is the default (the behavior if neither /// STGM_DIRECT nor STGM_TRANSACTED is specified). /// /// /// /// STGM_TRANSACTED /// /// Opens the property set with an additional level of transaction nesting (beyond the transaction, if any, on this property set /// storage object). Transacted mode is available only for nonsimple property sets. Changes in the property set must be committed /// with a call to IPropertyStorage::Commit before they are visible to the transaction on this property set storage. /// /// /// /// STGM_READ /// Opens the property set with read access. Read permission is required on the property set storage. /// /// /// STGM_WRITE /// Opens the property set with write access. Not all implementations of IPropertyStorage support this mode. /// /// /// STGM_READWRITE /// /// Opens the property set with read and write access. Be aware that this flag is not the binary OR of the values STGM_READ and STGM_WRITE. /// /// /// /// STGM_SHARE_DENY_NONE /// /// Subsequent openings of the property set from this property set storage are not denied read or write access. (Not available in /// all implementations.) /// /// /// /// STGM_SHARE_DENY_READ /// /// Subsequent openings of the property set from this property set storage are denied read access. Not available in all implementations. /// /// /// /// STGM_SHARE_DENY_WRITE /// /// Subsequent openings of the property set from this property set storage are denied write access. This value is typically used /// in the transacted mode to prevent making unnecessary copies of an object opened by multiple users. That is, if /// STGM_TRANSACTED is specified, but this value is not specified, a snapshot is made, whether there are subsequent openings or /// not. Thus, you can improve performance by specifying this value. Not available in all implementations. /// /// /// /// STGM_SHARE_EXCLUSIVE /// /// Subsequent openings of the property set from this property set storage are not possible. Be aware that this value is not a /// simple binary OR of the STGM_SHARE_DENY_READ and STGM_SHARE_DENY_WRITE elements. /// /// /// /// /// This method is subject to the constraints of the underlying IStorage::OpenStream (for simple property sets) or /// IStorage::OpenStorage (for nonsimple property sets). For more information about simple and nonsimple property sets, see /// Storage and Stream Objects for a Property Set. For example, when using the IPropertySetStorage-Compound File Implementation, /// you must specify STGM_SHARE_EXCLUSIVE in the parameter to IPropertySetStorage::Open. Conversely, if using the /// IPropertySetStorage-Stand-alone Implementation, IPropertySetStorage::Open is subject to constraints that apply to the /// caller-specified IStorage. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertysetstorage-open [PreserveSig] HRESULT Open(in Guid rfmtid, [In] STGM grfMode, out IPropertyStorage ppprstg); /// /// The Delete method deletes one of the property sets contained in the property set storage object. /// /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// IPropertySetStorage::Delete deletes the property set specified by its FMTID. Specifying a property set that does not /// exist returns an error. Open substorages and streams(opened through one of the storage- or stream-valued properties) are put /// into the reverted state. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertysetstorage-delete [PreserveSig] HRESULT Delete(in Guid rfmtid); /// /// /// The Enum method creates an enumerator object which contains information on the property sets stored in this property /// set storage. On return, this method supplies a pointer to the IEnumSTATPROPSETSTG pointer on the enumerator object. /// /// /// /// /// Pointer to IEnumSTATPROPSETSTG pointer variable that receives the interface pointer to the newly created enumerator object. /// /// /// /// This method can return one of these values. /// /// /// /// IPropertySetStorage::Enum creates an enumerator object that can be used to iterate through STATPROPSETSTG structures. /// These sometimes provide information on the property sets managed by IPropertySetStorage. This method, on return, supplies a /// pointer to the IEnumSTATPROPSETSTG interface on this enumerator object on return. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertysetstorage-enum [PreserveSig] HRESULT Enum(out IEnumSTATPROPSETSTG ppenum); } /// /// /// The IPropertyStorage interface manages the persistent properties of a single property set. Persistent properties consist /// of information that can be stored persistently in a property set, such as the summary information associated with a file. This /// contrasts with run-time properties associated with Controls and Automation, which can be used to affect system behavior. Use the /// methods of the IPropertySetStorage interface to create or open a persistent property set. An instance of the /// IPropertySetStorage interface can manage zero or more IPropertyStorage instances. /// /// /// Each property within a property set is identified by a property identifier (ID), a four-byte ULONG value unique to that /// set. You can also assign a string name to a property through the IPropertyStorage interface. /// /// /// Property IDs differ from the dispatch IDs used in Automation dispid property name tags. One difference is that the /// general-purpose use of property ID values zero and one is prohibited in IPropertyStorage, while no such restriction exists /// in IDispatch. In addition, while there is significant overlap among the data types for property values that may be used in /// IPropertyStorage and IDispatch, the property sets are not identical. Persistent property data types used in /// IPropertyStorage methods are defined in the PROPVARIANT structure. /// /// /// The IPropertyStorage interface can be used to access both simple and nonsimple property sets. Nonsimple property sets can /// hold several complex property types that cannot be held in a simple property set. For more information see Storage and Stream /// Objects for a Property Set. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nn-propidl-ipropertystorage [PInvokeData("propidl.h", MSDNShortId = "c021f695-db54-4861-9f30-35a81d2dccd5")] [ComImport, Guid("00000138-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPropertyStorage { /// /// The ReadMultiple method reads specified properties from the current property set. /// /// /// /// The numeric count of properties to be specified in the array. The value of this parameter can be set to zero; however, that /// defeats the purpose of the method as no properties are thereby read, regardless of the values set in . /// /// /// /// /// An array of PROPSPEC structures specifies which properties are read. Properties can be specified either by a property ID or /// by an optional string name. It is not necessary to specify properties in any particular order in the array. The array can /// contain duplicate properties, resulting in duplicate property values on return for simple properties. Nonsimple properties /// should return access denied on an attempt to open them a second time. The array can contain a mixture of property IDs and /// string IDs. /// /// /// /// /// Caller-allocated array of a PROPVARIANT structure that, on return, contains the values of the properties specified by the /// corresponding elements in the array. The array must be at least large enough to hold values of the parameter of the /// PROPVARIANT structure. The parameter specifies the number of properties set in the array. The caller is not required /// to initialize these PROPVARIANT structure values in any specific order. However, the implementation must fill all /// members correctly on return. If there is no other appropriate value, the implementation must set the vt member of each /// PROPVARIANT structure to VT_EMPTY. /// /// /// /// This method supports the standard return value E_UNEXPECTED, as well as the following: /// /// This function can also return any file system errors or Win32 errors wrapped in an HRESULT data type. For more /// information, see Error Handling Strategies. /// /// For more information, see Property Storage Considerations. /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-readmultiple [PreserveSig] HRESULT ReadMultiple(uint cpspec, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar); /// /// /// The WriteMultiple method writes a specified group of properties to the current property set. If a property with a /// specified name or property identifier already exists, it is replaced, even when the old and new types for the property value /// are different. If a property of a given name or property ID does not exist, it is created. /// /// /// /// /// The number of properties set. The value of this parameter can be set to zero; however, this defeats the purpose of the method /// as no properties are then written. /// /// /// /// /// An array of the property IDs (PROPSPEC) to which properties are set. These need not be in any particular order, and may /// contain duplicates, however the last specified property ID is the one that takes effect. A mixture of property IDs and string /// names is permitted. /// /// /// /// /// An array (of size ) of PROPVARIANT structures that contain the property values to be written. The array must be the size /// specified by . /// /// /// /// /// The minimum value for the property IDs that the method must assign if the parameter specifies string-named properties for /// which no property IDs currently exist. If all string-named properties specified already exist in this set, and thus already /// have property IDs, this value is ignored. When not ignored, this value must be greater than, or equal to, two and less than /// 0x80000000. Property IDs 0 and 1 and greater than 0x80000000 are reserved for special use. /// /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// This function can also return any file system errors or Win32 errors wrapped in an HRESULT data type. For more /// information, see Error Handling Strategies. /// /// /// /// /// If a specified property already exists, its value is replaced with the one specified in , even when the old and new types for /// the property value are different. If the specified property does not already exist, that property is created. The changes are /// not persisted to the underlying storage until IPropertyStorage::Commit has been called. /// /// /// Property names are stored in a special dictionary section of the property set, which maps such names to property IDs. All /// properties have an ID, but names are optional. A string name is supplied by specifying PRSPEC_LPWSTR in the ulKind /// member of the PROPSPEC structure. If a string name is supplied for a property, and the name does not already exist in the /// dictionary, the method will allocate a property ID, and add the property ID and the name to the dictionary. The property ID /// is allocated in such a way that it does not conflict with other IDs in the property set. The value of the property ID also is /// no less than the value specified by the parameter. If the parameter specifies string-named properties for which no property /// IDs currently exist, the parameter specifies the minimum value for the property IDs that the WriteMultiple method must assign. /// /// /// When a new property set is created, the special codepage ( Property ID 1 ) and Locale ID ( Property ID /// 0x80000000 ) properties are written to the property set automatically. These properties can subsequently be read, /// using the IPropertyStorage::ReadMultiple method, by specifying property IDs with the header-defined PID_CODEPAGE and /// PID_LOCALE values, respectively. If a property set is non-empty — has one or more properties in addition to the /// codepage and Locale ID properties or has one or more names in its dictionary — the special codepage and /// Locale ID properties cannot be modified by calling IPropertyStorage::WriteMultiple. However, if the property /// set is empty, one or both of these special properties can be modified. /// /// /// If an element in the array is set with a PRSPEC_PROPID value of 0xffffffff (PID_ILLEGAL), the corresponding value in the /// array is ignored by IPropertyStorage::WriteMultiple. For example, if this method is called with the parameter set to /// 3, but is set to PRSPEC_PROPID and is set to PID_ILLEGAL, only two properties will be written. The element is silently ignored. /// /// Use the PropVariantInit macro to initialize PROPVARIANT structures. /// /// Property sets, not including the data for nonsimple properties, are limited to 256 KB in size for Windows NT 4.0 and earlier. /// For Windows 2000, Windows XP and Windows Server 2003, OLE property sets are limited to 1 MB. If these limits are exceeded, /// the operation fails and the caller receives an error message. There is no possibility of a memory leak or overrun. For more /// information, see Managing Property Sets. /// /// /// Unless PROPSETFLAG_CASE_SENSITIVE is passed to IPropertySetStorage::Create, property set names are case insensitive. /// Specifying a property by its name in IPropertyStorage::WriteMultiple will result in a case-insensitive search of the /// names in the property set. To compare case-insensitive strings, the locale of the strings must be known. For more /// information, see IPropertyStorage::WritePropertyNames. /// /// For more information, see Property Storage Considerations. /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-writemultiple [PreserveSig] HRESULT WriteMultiple(uint cpspec, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar, uint propidNameFirst); /// /// The DeleteMultiple method deletes as many of the indicated properties as exist in this property set. /// /// /// /// The numerical count of properties to be deleted. The value of this parameter can legally be set to zero, however that defeats /// the purpose of the method as no properties are thereby deleted, regardless of the value set in . /// /// /// /// /// Properties to be deleted. A mixture of property identifiers and string-named properties is permitted. There may be /// duplicates, and there is no requirement that properties be specified in any order. /// /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// IPropertyStorage::DeleteMultiple must delete as many of the indicated properties as are in the current property set. /// If a deletion of a stream- or storage-valued property occurs while that property is open, the deletion will succeed and place /// the previously returned IStream or IStorage pointer in the reverted state. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-deletemultiple [PreserveSig] HRESULT DeleteMultiple(uint cpspec, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec); /// /// The ReadPropertyNames method retrieves any existing string names for the specified property IDs. /// /// /// /// The number of elements on input of the array . The value of this parameter can be set to zero, however that defeats the /// purpose of this method as no property names are thereby read. /// /// /// /// An array of property IDs for which names are to be retrieved. /// /// /// /// A caller-allocated array of size of LPWSTR members. On return, the implementation fills in this array. A given entry /// contains either the corresponding string name of a property ID or it can be empty if the property ID has no string names. /// /// Each LPWSTR member of the array should be freed using the CoTaskMemFree function. /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// For each property ID in the list of property IDs supplied in the array, ReadPropertyNames retrieves the corresponding /// string name, if there is one. String names are created either by specifying the names in calls to /// IPropertyStorage::WriteMultiple when creating the property, or through a call to IPropertyStorage::WritePropertyNames. In /// either case, the string name is optional, however all properties must have a property ID. /// /// String names mapped to property IDs must be unique within the set. /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-readpropertynames [PreserveSig] HRESULT ReadPropertyNames(uint cpropid, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] rgpropid, [In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0)] string[] rglpwstrName); /// /// /// The WritePropertyNames method assigns string IPropertyStoragenames to a specified array of property IDs in the current /// property set. /// /// /// /// The size on input of the array . Can be zero. However, making it zero causes this method to become non-operational. /// /// /// An array of the property IDs for which names are to be set. /// /// /// /// An array of new names to be assigned to the corresponding property IDs in the array. These names may not exceed 255 /// characters (not including the NULL terminator). /// /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// For more information about property sets and memory management, see Managing Property Sets. /// /// IPropertyStorage::WritePropertyNames assigns string names to property IDs passed to the method in the array. It /// associates each string name in the array with the respective property ID in . It is explicitly valid to define a name for a /// property ID that is not currently present in the property storage object. /// /// /// It is also valid to change the mapping for an existing string name (determined by a case-insensitive match). That is, you can /// use the WritePropertyNames method to map an existing name to a new property ID, or to map a new name to a property ID /// that already has a name in the dictionary. In either case, the original mapping is deleted. Property names must be unique (as /// are property IDs) within the property set. /// /// /// The storage of string property names preserves the case. Unless PROPSETFLAG_CASE_SENSITIVE is passed to /// IPropertySetStorage::Create, property set names are case insensitive by default. With case-insensitive property sets, the /// name strings passed by the caller are interpreted according to the locale of the property set, as specified by the /// PID_LOCALE property. If the property set has no locale property, the current user is assumed by default. String /// property names are limited in length to 128 characters. Property names that begin with the binary Unicode characters 0x0001 /// through 0x001F are reserved for future use. /// /// /// If the value of an element in the array parameter is set to 0xffffffff (PID_ILLEGAL), the corresponding name is ignored by /// IPropertyStorage::WritePropertyNames. For example, if this method is called with a parameter of 3, but the first /// element of the array, , is set to PID_ILLEGAL, then only two property names are written. The element is ignored. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-writepropertynames [PreserveSig] HRESULT WritePropertyNames(uint cpropid, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] rgpropid, [In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0)] string[] rglpwstrName); /// /// The DeletePropertyNames method deletes specified string names from the current property set. /// /// /// The size on input of the array . If 0, no property names are deleted. /// /// /// Property identifiers for which string names are to be deleted. /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// For each property identifier in , IPropertyStorage::DeletePropertyNames removes any corresponding name-to-property ID /// mapping. An attempt is silently ignored to delete the name of a property that either does not exist or does not currently /// have a string name associated with it. This method has no effect on the properties themselves. /// /// /// Note All the stored string property names can be deleted by deleting property identifier zero, but must be equal to 1 /// for this to be a valid parameter error. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-deletepropertynames [PreserveSig] HRESULT DeletePropertyNames(uint cpropid, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] rgpropid); /// /// The IPropertyStorage::Commit method saves changes made to a property storage object to the parent storage object. /// /// /// /// The flags that specify the conditions under which the commit is to be performed. For more information about specific flags /// and their meanings, see the Remarks section. /// /// /// /// This method supports the standard return value E_UNEXPECTED, as well as the following: /// /// /// /// Like IStorage::Commit, the IPropertyStorage::Commit method ensures that any changes made to a property storage object /// are reflected in the parent storage. /// /// /// In direct mode in the compound file implementation, a call to this method causes any changes currently in the memory buffers /// to be flushed to the underlying property stream. In the compound-file implementation for nonsimple property sets, /// IStorage::Commit is also called on the underlying substorage object with the passed parameter. /// /// /// In transacted mode, this method causes the changes to be permanently reflected in the persistent image of the storage object. /// The changes that are committed must have been made to this property set since it was opened or since the last commit on this /// opening of the property set. The commit method publishes the changes made on one object level to the next level. Of /// course, this remains subject to any outer-level transaction that may be present on the object in which this property set is /// contained. Write permission must be specified when the property set is opened (through IPropertySetStorage) on the property /// set opening for the commit operation to succeed. /// /// /// If the commit operation fails for any reason, the state of the property storage object remains as it was before the commit. /// /// /// This call has no effect on existing storage- or stream-valued properties opened from this property storage, but it does /// commit them. /// /// Valid values for the parameter are listed in the following table. /// /// /// Value /// Meaning /// /// /// STGC_DEFAULT /// Commits per the usual transaction semantics. Last writer wins. This flag may not be specified with other flag values. /// /// /// STGC_ONLYIFCURRENT /// /// Commits the changes only if the current persistent contents of the property set are the ones on which the changes about to be /// committed are based. That is, does not commit changes if the contents of the property set have been changed by a commit from /// another opening of the property set. The error STG_E_NOTCURRENT is returned if the commit does not succeed for this reason. /// /// /// /// STGC_OVERWRITE /// /// Useful only when committing a transaction that has no further outer nesting level of transactions, though acceptable in all cases. /// /// /// /// /// Note Using IPropertyStorage::Commit to write properties to image files on Windows XP does not work. Affected /// image file formats include:Due to a bug in the image file property handler on Windows XP, calling /// IPropertyStorage::Commit actually discards any changes made rather than persisting them. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-commit [PreserveSig] HRESULT Commit(uint grfCommitFlags); /// /// /// The Revert method discards all changes to the named property set since it was last opened or discards changes that /// were last committed to the property set. This method has no effect on a direct-mode property set. /// /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// For transacted-mode property sets, this method discards all changes that have been made in this property set since the set /// was opened or since the time it was last committed, (whichever is later). After this operation, any existing storage- or /// stream-valued properties that have been opened from the property set being reverted are no longer valid and cannot be used. /// The error STG_E_REVERTED will be returned on all calls, except those to Release, using these streams or storages. /// /// For direct-mode property sets, this request is ignored and returns S_OK. /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-revert [PreserveSig] HRESULT Revert(); /// /// /// The Enum method creates an enumerator object designed to enumerate data of type STATPROPSTG, which contains /// information on the current property set. On return, this method supplies a pointer to the IEnumSTATPROPSTG pointer on this object. /// /// /// /// Pointer to IEnumSTATPROPSTG pointer variable that receives the interface pointer to the new enumerator object. /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// IPropertyStorage::Enum creates an enumeration object that can be used to iterate STATPROPSTG structures. On return, /// this method supplies a pointer to an instance of the IEnumSTATPROPSTG interface on this object, whose methods you can call to /// obtain information about the current property set. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-enum [PreserveSig] HRESULT Enum(out IEnumSTATPROPSTG ppenum); /// /// /// The SetTimes method sets the modification, access, and creation times of this property set, if supported by the /// implementation. Not all implementations support all these time values. /// /// /// /// /// Pointer to the new creation time for the property set. May be NULL, indicating that this time is not to be modified by /// this call. /// /// /// /// /// Pointer to the new access time for the property set. May be NULL, indicating that this time is not to be modified by /// this call. /// /// /// /// /// Pointer to the new modification time for the property set. May be NULL, indicating that this time is not to be /// modified by this call. /// /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// Sets the modification, access, and creation times of the current open property set, if supported by the implementation (not /// all implementations support all these time values). Unsupported time stamps are always reported as zero, enabling the caller /// to test for support. A call to IPropertyStorage::Stat supplies (among other data) time-stamp information. /// /// /// Notice that this functionality is provided as an IPropertyStorage method on a property-storage object that is already open, /// in contrast to being provided as a method in IPropertySetStorage. Normally, when the SetTimes method is not explicitly /// called, the access and modification times are updated as a side effect of reading and writing the property set. When /// SetTimes is used, the latest specified times supersede either default times or time values specified in previous calls /// to SetTimes. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-settimes [PreserveSig] HRESULT SetTimes(in FILETIME pctime, in FILETIME patime, in FILETIME pmtime); /// /// /// The SetClass method assigns a new CLSID to the current property storage object, and persistently stores the CLSID with /// the object. /// /// /// /// New CLSID to be associated with the property set. /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// Assigns a CLSID to the current property storage object. The CLSID has no relationship to the stored property IDs. Assigning a /// CLSID allows a piece of code to be associated with a given instance of a property set; such code, for example, might manage /// the user interface (UI). Different CLSIDs can be associated with different property set instances that have the same FMTID. /// /// /// If the property set is created with the parameter of the IPropertySetStorage::Create method specified as NULL, the /// CLSID is set to all zeroes. /// /// /// The current CLSID on a property storage object can be retrieved with a call to IPropertyStorage::Stat. The initial value for /// the CLSID can be specified at the time that the storage is created with a call to IPropertySetStorage::Create. /// /// /// Setting the CLSID on a nonsimple property set (one that can legally contain storage- or stream-valued properties, as /// described in IPropertySetStorage::Create) also sets the CLSID on the underlying sub-storage. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-setclass [PreserveSig] HRESULT SetClass(in Guid clsid); /// /// The Stat method retrieves information about the current open property set. /// /// /// Pointer to a STATPROPSETSTG structure, which contains statistics about the current open property set. /// /// /// This method supports the standard return value E_UNEXPECTED, in addition to the following: /// /// /// /// IPropertyStorage::Stat fills in and returns a pointer to a STATPROPSETSTG structure, containing statistics about the /// current property set. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/nf-propidl-ipropertystorage-stat [PreserveSig] HRESULT Stat(out STATPROPSETSTG pstatpsstg); } /// /// The PropVariantClear function frees all elements that can be freed in a given PROPVARIANT structure. For complex elements with /// known element pointers, the underlying elements are freed prior to freeing the containing element. /// /// /// A pointer to an initialized PROPVARIANT structure for which any deallocatable elements are to be freed. On return, all zeroes are /// written to the PROPVARIANT structure. /// /// /// /// /// S_OK /// The VT types are recognized and all items that can be freed have been freed. /// /// /// STG_E_INVALID_PARAMETER /// The variant has an unknown VT type. /// /// /// [SecurityCritical, SuppressUnmanagedCodeSecurity] [DllImport(Lib.Ole32, ExactSpelling = true, SetLastError = false)] [PInvokeData("Propidl.h", MSDNShortId = "aa380073")] public static extern HRESULT PropVariantClear([In, Out] PROPVARIANT pvar); /// The PropVariantCopy function copies the contents of one PROPVARIANT structure to another. /// Pointer to an uninitialized PROPVARIANT structure that receives the copy. /// Pointer to the PROPVARIANT structure to be copied. /// /// /// /// S_OK /// The VT types are recognized and all items that can be freed have been freed. /// /// /// STG_E_INVALID_PARAMETER /// The variant has an unknown VT type. /// /// /// [DllImport(Lib.Ole32, ExactSpelling = true)] [PInvokeData("Propidl.h", MSDNShortId = "aa380192")] public static extern HRESULT PropVariantCopy([In, Out] PROPVARIANT pDst, [In] PROPVARIANT pSrc); /// /// /// The PROPSPEC structure is used by many of the methods of IPropertyStorage to specify a property either by its property /// identifier (ID) or the associated string name. /// /// /// /// /// String names are optional and can be assigned to a set of properties when the property is created with a call to /// IPropertyStorage::WriteMultiple or later with a call to IPropertyStorage::WritePropertyNames. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/ns-propidl-tagpropspec typedef struct tagPROPSPEC { ULONG ulKind; // union { PROPID propid; LPOLESTR lpwstr; } DUMMYUNIONNAME; } PROPSPEC; [PInvokeData("propidl.h", MSDNShortId = "5bb3b9c6-ab82-498c-94f9-13a9ffa7452b")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct PROPSPEC { /// /// Indicates the union member used. This member can be one of the following values. /// /// /// Name /// Meaning /// /// /// PRSPEC_LPWSTR Value: 0 /// The lpwstr member is used and set to a string name. /// /// /// PRSPEC_PROPID Value: 1 /// The propid member is used and set to a property ID value. /// /// /// public PRSPEC ulKind; /// PROPSPECunion public PROPSPECunion union; [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] public struct PROPSPECunion { /// /// Specifies the value of the property ID. Use either this value or the following lpwstr, not both. /// [FieldOffset(0)] public uint propid; /// /// Specifies the string name of the property as a null-terminated Unicode string. /// [FieldOffset(0)] public string lpwstr; } } /// /// /// The STATPROPSETSTG structure contains information about a property set. To get this information, call /// IPropertyStorage::Stat, which fills in a buffer containing the information describing the current property set. To enumerate the /// STATPROPSETSTG structures for the property sets in the current property-set storage, call IPropertySetStorage::Enum to get /// a pointer to an enumerator. You can then call the enumeration methods of the IEnumSTATPROPSETSTG interface on the enumerator. The /// structure is defined as follows: /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/ns-propidl-tagstatpropsetstg typedef struct tagSTATPROPSETSTG { FMTID // fmtid; CLSID clsid; DWORD grfFlags; FILETIME mtime; FILETIME ctime; FILETIME atime; DWORD dwOSVersion; } STATPROPSETSTG; [PInvokeData("propidl.h", MSDNShortId = "8e5cc502-9f96-4f4b-8729-cac4a1ffcd6f")] [StructLayout(LayoutKind.Sequential)] public struct STATPROPSETSTG { /// /// FMTID of the current property set, specified when the property set was initially created. /// public Guid fmtid; /// /// /// CLSID associated with this property set, specified when the property set was initially created and possibly modified /// thereafter with IPropertyStorage::SetClass. If not set, the value will be CLSID_NULL. /// /// public Guid clsid; /// /// Flag values of the property set, as specified in IPropertySetStorage::Create. /// public uint grfFlags; /// /// Time in Universal Coordinated Time (UTC) when the property set was last modified. /// public FILETIME mtime; /// /// Time in UTC when this property set was created. /// public FILETIME ctime; /// /// Time in UTC when this property set was last accessed. /// public FILETIME atime; /// The OS version. public uint dwOSVersion; } /// /// /// The STATPROPSTG structure contains data about a single property in a property set. This data is the property ID and type /// tag, and the optional string name that may be associated with the property. /// /// /// IPropertyStorage::Enum supplies a pointer to the IEnumSTATPROPSTG interface on an enumerator object that can be used to enumerate /// the STATPROPSTG structures for the properties in the current property set. STATPROPSTG is defined as: /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/propidl/ns-propidl-tagstatpropstg typedef struct tagSTATPROPSTG { LPOLESTR // lpwstrName; PROPID propid; VARTYPE vt; } STATPROPSTG; [PInvokeData("propidl.h", MSDNShortId = "3b8de6d3-18a3-4c0a-94d1-04bcec05d41a")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct STATPROPSTG { /// /// /// A wide-character null-terminated Unicode string that contains the optional string name associated with the property. May be /// NULL. This member must be freed using CoTaskMemFree. /// /// public string lpwstrName; /// /// /// A 32-bit identifier that uniquely identifies the property within the property set. All properties within property sets must /// have unique property identifiers. /// /// public uint propid; /// /// The property type. /// public VARTYPE vt; } } }