IPropertyStorage-Compound 文件实现

结构化存储体系结构的 COM 实现称为 复合文件。 复合文件中实现的存储对象包括 IPropertyStorage(管理单个持久属性集的接口)和 IPropertySetStorage(管理持久属性集组的接口)的实现。 有关 IPropertyStorage 接口的详细信息,请参阅 IPropertyStorage属性存储注意事项

若要获取指向 IPropertyStorage 的复合文件实现的指针,请调用 StgCreateStorageEx 创建新的复合文件对象,或 调用 StgOpenStorageEx 打开以前创建的复合文件对象。 对于 StgCreateStorageExstgfmt 参数应设置为 STGFMT_STORAGE。 对于 StgOpenStorageExstgfmt 参数应设置为 STGFMT_STORAGE 或 STGFMT_ANY。 在这两种情况下, riid 参数都应设置为 IID_IPropertySetStorage。 这两个函数都提供指向对象 IPropertySetStorage 接口的 指针。 通过调用该接口的 CreateOpen 方法,你将获得指向 IPropertyStorage 接口的指针,该接口可用于调用其任何方法。

获取指向 IPropertySetStorage 复合文件实现的指针的另一种方法是调用较旧的 StgCreateDocfileStgOpenStorage 函数,或指定 stgCreateStorageExStgOpenStorageEx 函数IID_IStorage riid 参数。 在任一情况下,都返回指向对象的 IStorage 接口的指针。 使用永久性属性集时,为 IPropertySetStorage 接口调用 QueryInterface,为接口标识符指定标头定义的名称 (IID) IID_IPropertySetStorage。

何时使用

使用 IPropertyStorage 管理单个属性集中的属性。 其方法支持读取、写入和删除属性以及可与属性标识符关联的可选字符串名称。 其他方法支持标准提交和还原存储操作。 还有一种方法可用于设置与属性存储关联的时间,另一种方法允许分配 CLSID,该 CLSID 可用于将其他代码(如用户界面代码)与属性集相关联。 调用 Enum 方法会提供指向 IEnumSTATPROPSTG 的复合文件实现的指针,这使你可以枚举集中的属性。

注意

如果通过在简单模式属性集存储上调用 StgCreateDocfileStgCreateStorageExStgOpenStorageStgOpenStorageEx 来获取指向 IPropertyStorage 的指针,则 IPropertyStorage 方法遵循简单模式流的规则。 如果属性集存储是为使用 STGM_SIMPLE 标志创建或打开的文件获取的,则属性集存储为简单模式。 在这种情况下,并不总是能够使基础流更大,并且不可能将现有属性替换为更大的属性。 有关详细信息,请参阅 IPropertySetStorage-Compound 文件实现

 

IPropertyStorage 和缓存

IPropertyStorage 的复合文件实现将打开的属性集缓存在内存中,以提高性能。 因此,在调用 CommitRelease (最后一个引用) 方法之前,不会将属性集的更改写入复合文件。

简单模式属性集

如果从简单模式属性集存储对象创建属性存储对象,则属性存储对象处于简单模式。 例如,如果属性集存储对象是从 StgOpenStorageEx 函数获取的,并在 grfMode 参数中设置了 STGM_SIMPLE 标志,则该对象将处于简单模式。 请注意,“简单模式”与“简单属性集”无关。 如果在 grfFlags 参数中设置PROPSETFLAG_NONSIMPLE标志的情况下调用 IPropertySetStorage::Create 来创建属性集,则属性集很简单。 有关简单和非简单属性集的详细信息,请参阅 属性集的存储和流对象

创建简单模式属性存储对象时,对其使用没有限制。 打开现有的简单模式属性存储对象时,无法扩展存储该属性集的基础流对象。 因此,如果更改需要更大的流,则并不总是可以修改此类属性存储对象。

属性集格式

IPropertyStorage 的复合文件实现支持版本 0 和版本 1 属性集序列化格式。 在 Windows 2000 上运行的计算机上支持版本 1 格式。 有关详细信息,请参阅 属性集序列化。 属性集以版本 0 格式创建,除非请求新功能,否则将保留该格式。 发生这种情况时,格式将更新为版本 1。

例如,如果使用 PROPSETFLAG_DEFAULT 标志创建属性集,则其格式为版本 0。 只要将符合版本 0 格式的属性类型写入该属性集并从中读取,该属性集将保持为版本 0 格式。 如果将版本 1 属性类型写入属性集,则属性集会自动更新为版本 1。 随后,仅识别版本 0 的实现无法再读取该属性集。

IPropertyStorage 和 Variant 类型

IPropertyStorage 的复合文件实现不支持 PROPVARIANT 结构的 vt 成员中VT_UNKNOWN或VT_DISPATCH的变体类型。

下表列出了 SafeArray 中支持的变体类型;也就是说,这些值可以与 PROPVARIANT 结构的 vt 成员中的VT_ARRAY组合使用。

IPropertyStorage 的复合文件实现在 SafeArray 中支持的变体类型

VT_I1

VT_UI1

VT_I2

VT_UI2

VT_I4

VT_UI4

VT_INT

VT_UINT

VT_R4

VT_R8

VT_CY

VT_DATE

VT_BSTR

VT_BOOL

VT_DECIMAL

VT_ERROR

VT_VARIANT

 

 

当VT_VARIANT与 VT_ARRAY 结合使用时,SafeArray 本身会保留 PROPVARIANT 结构。 但是,这些元素的类型必须取自前面的列表,不能VT_VARIANT,也不能包括VT_VECTOR、VT_ARRAY或VT_BYREF指示器。

IPropertyStorage 方法

IPropertyStorage 的复合文件实现支持以下方法:

IPropertyStorage::ReadMultiple

读取 rgpspec 数组中指定的属性,并提供 PROPVARIANT 的 rgvar 数组中所有有效属性的值。 在 COM 复合文件实现中,引用流或存储类型的重复属性标识符会导致多次调用 IStorage::OpenStreamIStorage::OpenStorage而 ReadMultiple 的成功与否取决于基础存储实现共享打开操作的能力。 由于在复合文件中STGM_SHARE_EXCLUSIVE是强制的,因此多次打开尝试将失败。 不支持从同一父存储多次打开同一存储对象。 必须指定STGM_SHARE_EXCLUSIVE标志。

此外,为了确保在通过 COM 复合文件实现中的同一 IPropertyStorage 指针多次请求相同的流或存储值属性时线程安全操作,打开操作将成功或失败,具体取决于属性是否已打开,以及基础文件系统是否处理流或存储的多个打开。 因此,对流或存储值属性执行的 ReadMultiple 操作始终会导致调用 IStorage::OpenStreamIStorage::OpenStorage,后者传递访问 (STGM_READWRITE,依此类推) 和共享标志 (STGM_SHARE_EXCLUSIVE,) 打开或创建原始属性集时指定。

如果方法失败,则写入 rgvar[] 的值未定义。 如果某些流值或存储值属性已成功打开,但在执行完成之前发生错误,则应在方法返回之前释放这些属性。

IPropertyStorage::WriteMultiple

写入 rgpspec[] 数组中指定的属性,并为其分配 rgvar[] 中指定的 PROPVARIANT 标记和值。 为已存在的属性分配指定的 PROPVARIANT 值。 创建当前不存在的属性。

IPropertyStorage::D eleteMultiple

删除 rgpspec[] 中指定的属性。

IPropertyStorage::ReadPropertyNames

读取与 rgpropid[] 数组中指定的属性 ID 关联的现有字符串名称。

IPropertyStorage::WritePropertyNames

rglpwstrName 数组中指定的字符串名称分配给 rgpropid 数组中指定的属性 ID。

IPropertyStorage::D eletePropertyNames

删除 rgpropid[] 数组中指定的属性的属性名称。

IPropertyStorage::SetClass

设置属性集流的 CLSID 。 在复合文件实现中,在非简单属性集上设置 CLSID (可合法包含存储或流值属性集,如 IPropertySetStorage::Create) 还会设置基础子存储上的 CLSID,以便可以通过调用 IStorage::Stat 获取它。

IPropertyStorage::Commit

对于简单和非简单属性集,将属性集内存映像刷新到基础存储。 此外,对于非简单事务处理模式属性集,此方法对包含属性集的存储执行提交 (如 IStorage::Commit) 中所示。

IPropertyStorage::Revert

仅对于非简单属性集,调用基础存储的 Revert 方法并重新打开“contents”流。 对于简单属性集,此接口始终返回S_OK。 非简单属性集是使用 IPropertySetStorage::Create 方法中的 PROPSETFLAG_NONSIMPLE 标志创建的属性集。 有关详细信息,请参阅 属性集的存储和流对象

IPropertyStorage::Enum

构造 IEnumSTATPROPSTG 的实例,可调用其方法枚举 STATPROPSTG 结构,这些结构提供有关集中每个属性的信息。 此实现将创建一个数组,该数组将读取整个属性集,并在调用 IEnumSTATPROPSTG::Clone 时可以共享该数组。 对属性集的更改不会反映在打开的 IEnumSTATPROPSTG 实例中。 若要查看此类更改,必须构造此枚举器的新实例。

IPropertyStorage::Stat

填充 STATPROPSETSTG 结构的成员,该结构包含有关整个属性集的数据。 返回时,提供指向 结构的指针。 对于非简单存储集,此实现调用 IStorage::Stat (或 IStream::Stat) ,以从基础存储或流获取时间。 对于简单存储集,不保留任何时间。

IPropertyStorage::SetTimes

仅对于非简单属性集,设置基础存储支持的时间。 复合文件存储实现支持以下三项:修改、访问和创建。 SetTimes 的此实现调用基础存储的 IStorage::SetElementTimes 方法来检索这些时间。

IPropertyStorage

IStorage::SetElementTimes