STGM Constants
STGM 常量表示在创建或删除对象以及对象访问模式的条件。 STGM 常量用于 IStorage, IStream, and IPropertySetStorage 接口和 StgCreateDocfile, StgCreateStorageEx, StgCreateDocfileOnILockBytes, StgOpenStorage 以及 StgOpenStorageEx 方法。
这些常量经常用 ”|” 操作符组合在一起。它们被分成不同的组,如下表,每个组只能选择一个元素进行组合。
Group Flag Value
Access STGM_READ 0x00000000L
STGM_WRITE 0x00000001L
STGM_READWRITE 0x00000002L
Sharing STGM_SHARE_DENY_NONE 0x00000040L
STGM_SHARE_DENY_READ 0x00000030L
STGM_SHARE_DENY_WRITE 0x00000020L
STGM_SHARE_EXCLUSIVE 0x00000010L
STGM_PRIORITY 0x00040000L
Creation STGM_CREATE 0x00001000L
STGM_CONVERT 0x00020000L
STGM_FAILIFTHERE 0x00000000L
Transactioning STGM_DIRECT 0x00000000L
STGM_TRANSACTED 0x00010000L
Transactioning Performance STGM_NOSCRATCH 0x00100000L
STGM_NOSNAPSHOT 0x00200000L
Direct SWMR and Simple STGM_SIMPLE 0x08000000L
STGM_DIRECT_SWMR 0x00400000L
Delete On Release STGM_DELETEONRELEASE 0x04000000L
STGM_READ
0x00000000L
表示对象只能读不能修改。例如:如果一个 stream 用 STGM_READ 打开, ISequentialStream::Read 方法可以调用,但是 ISequentialStream::Write 方法不可以,同样,如果一个 stream 用 STGM_READ 打开, IStorage::OpenStream 、 IStorage::OpenStrorage 方法可以调用,但是 IStorage::CreateStream 、 IStorage::CreateStorage 方法不可以用。
STGM_WRITE
0x00000001L
允许你保存对对象的修改,但是不允许访问它的数据。建议在实现 IPropertyStorage 和 IPropertySetStorage 接口的时候不要支持只写模式。
STGM_READWRITE
0x00000002L
允许对对象数据的访问和修改。例如:如果一个 stream 是以这种模式打开,就可以同时使用 IStream::Read 和 IStream::Write 方法。要注意这个常量不是 STGM_WRITE 和 STGM_READ 常量的简单和运算。
STGM_SHARE_DENY_NONE
0x00000040L
表示接下来打开的对象不拒绝读写方法。如果这个组中没有其他的常量被使用时,这是默认的设置。
STGM_SHARE_DENY_READ
0x00000030L
阻止其他方法用 STGM_READ 模式打开对象。它典型的使用是在根 storage 对象。
STGM_SHARE_DENY_WRITE
0x00000020L
阻止其他方法用 STGM_WRITE 模式和 STGM_READWRITE 打开对象。在延时模式, STGM_SHARE_DENY_WRITE 或则 STGM_SHARE_EXCLUSIVE 能够提升效率,因为他们不要求快照。获得更多延时( transactioning )的信息,请参考提示部分。
STGM_SHARE_EXCLUSIVE
0x00000010L
阻止其他方法用任何模式打开对象。注意这个值不是 STGM_SHARE_DENY_READ 和 STGM_SHARE_DENY_WRITE 简单的位与运算。在延时模式, STGM_SHARE_DENY_WRITE 或则 STGM_SHARE_EXCLUSIVE 能够提升效率,因为他们不要求快照。获得更多延时( transactioning )的信息,请参考提示部分。
STGM_PRIORITY
0x00040000L
使用排斥模式去打开 storage 对象,获取最近提交的版本。因此,当用特权模式( priority mode )其他用户不能提交对象的任何修改。在复制操作的时候可以获得较好的效率,但是你阻止了其他用户修改对象。要限制使用特权模式,必须把 STGM_DIRECT 、 STGM_READ 和 STGM_PRIORITY 一起使用,并且不能使用 STGM_DELETEONRELEASE ,因为它只在创建根对象时使用,如 StgCreateStorageEx 使用。当打开一个已经存在的根对象时无效,如
StgOpenStorageEx 使用。当创建一个子元素的时候也是无效的,如 IStorage::OpenStorage 。
STGM_CREATE
0x00001000L
表示在新的对象替换已经存在的对象之前,之前的对象应该被移除。仅在一个已经存在的对象已经成功删除时才能用这个标志创建新对象。
使用情况如下 :
n 创建一个磁盘上的对象,但已有同名的文件。
n 创建一个 storage 中的对象,但已有同名的子对象存在。
n 创建一个字节数组对象,但以后同名存在。
STGM_CONVERT
0x00020000L
为了保护在名字为 ”Contents” 的 stream 中已有的数据而创建一个新的对象。有的时候,一个 storage 或者字节数组中的久数据被格式化到一个 stream ,不管已经存在的文件或者字节数组当前是否包含一个 storage 对象。这个标志只能在创建一个根 storage 对象时使用。它不能使用在 storage 对象,如 IStorage::CreateStream 。在同时使用 STGM_DELETEONRELEASE 和本标志时,本标志变无效。
STGM_FAILIFTHERE
0x00000000L
如果已经有同名对象存在时创建操作失败。此时 STG_E_FILEALREADYEXISTS 会被返回。这个是创建模式( creation mode )的默认模式。
STGM_DIRECT
0x00000000L
表示对 storage 和 stream 元素的每一次修改都被立即写入。这是 Transactioning 组的默认设置。
STGM_TRANSACTED
0x00010000L
在延时模式( transacted mode )下,修改被推迟,仅当显示的执行提交操作。为了忽略作的修改,可以调用 IStream, IStorage, 和 IPropertyStorage 接口的 Revert 方法。 IStorage 的 COM 复合文件的实现不支持延时式的 stream ,亦即 stream 只能用直接模式打开,并不能撤销修改,但是延时模式的 storage 是支持的。 IPropertySetStorage 接口在复合文件、普通文件亦即 NTFS 文件系统的实现中同样不支持延时处理,简单属性设置是因为这些属性保存在 stream 对象中。非简单属性设置的处理,能通过设置 IPropertySetStorage::Create 方法的 grfFlags 参数为 PROPSETFLAG_NONSIMPLE 常量来创建。
STGM_NOSCRATCH
0x00100000L
在本模式下,通常使用一个临时 scratch 文件来保存修改,直到提交方法被调用。使用本标志,可以允许使用原始文件不经常使用的部分作为工作区来代替创建新的文件。这样不会影响原始文件的数据,有时候还可以提升效率。本标志必须和 STGM_TRANSACTED 一起使用,并只能用于根 storage 。更多信息请参考说明部分。
STGM_NOSNAPSHOT
0x00200000L
在打开一个用标志 STGM_TRANSACTED 而没有 STGM_SHARE_EXCLUSIVE 和 STGM_SHARE_DENY_WRITE 的时候使用本标志。这时,指定本标志阻止系统提供的实现创建文件的快照。反而,对文件的修改被写入文件的尾部。除非在提交时执行合并操作,否则未使用的空间不会被收回,只有一个对文件的写者。当文件在本模式打开,另一个打开操作在没有被指定 STGM_NOSNAPSHOT 标志时无法完成。这个标志可能只用于根 storage 。更多信息请参考说明部分。
STGM_SIMPLE
0x08000000L
提供一种有限制的复合文件的快速实现,但经常使用。更多信息请参考说明部分。
STGM_DIRECT_SWMR
0x00400000L
支持单写者多读者的直接模式文件操作。更多信息请参考说明部分。
STGM_DELETEONRELEASE
0x04000000L
表示底层文件在根 storage 被释放的时候被自动删除。这个方法对于创建临时文件非常有用。这个文件只用于创建根对象,如 StgCreateStorageEx 。当打开一个根对象或者创建和打开一个子元素的时候,这个标志无效,如 StgOpenStorageEx ,当然同时使用 STGM_CONVERT 的时候也是无效的。
说明:
你可以组合这些标志,但只能从每一个组里面选择一个标志。
延时模式 (Transacted Mode)
当 STGM_DIRECT 被指定的时候,只有下面访问和共享组中的一种组合可以使用。
STGM_READ | STGM_SHARE_DENY_WRITE
STGM_READWRITE | STGM_SHARE_EXCLUSIVE
STGM_READ | STGM_PRIORITY
注意:在没有 STGM_TRANSACTED 的时候就是默认使用直接模式。
在 STGM_TRANSACTED 使用时,对象的修改直到进行提交操作前是不固定的。比如:延时模式的 storage 对象在 IStroage::Commit 调用之前不是不变的。对这样的 storage 作的修改在提交或者撤销方法之前调用 release 就丢失了。
当一个对象在这个模式创建或打开,对象的实现要记录原始数据和更新过的数据,让在必要时可以撤销修改。这就是为什么要把修改写入到 scratch 区域,或者创建副本,调用快照。
当用延时模式打开根 storage 对象, scratch 数据和快照的位置和行为可以通过设置 STGM_NOSCRATCH 和 STGM_NOSNAPSHOT 来控制优化性能。(如:可以通过 StgOpenStorageEx 来获得一个根 storage 对象, IStorage::OpenStorage 方法获得子 storage 对象)其实 scratch 数据和快照是存贮在临时文件,与 storage 分开。
这些标志的效果依赖于对访问根 storage 读者和 / 或写者的数量。
在单写者的情况下,一个延时模式的 storage 对象用写权限打开,没有其他人可以访问这个文件。亦即文件用 STGM_TRANSACTED ,权限组的 STGM_WRITE 或 STGM_READWRITE ,和共享组的 STGM_SHARE_EXCLUSIVE 等标志打开。对 storage 的修改被写入 scratch 区域。当修改被提交的时候,修改的部分被复制到原始 storage 。然而,如果没有修改,就没有必要做数据的传递。
在多写者情况下,一个延时模式下用于写操作的 storage ,和其他的写者一起工作。亦即使用 STGM_TRANSACTED, STGM_WRITE 或者 STGM_READWRITE, 和 STGM_SHARE_DENY_READ 标志的组合打开 storage 对象。如果使用 STGM_SHARE_DENY_NONE ,那么就成了“多写者,多读者”的情况。这时,在文件打开时会对原始数据进行快照。即使没有对 storage 修改或没有被其他写者同时打开,在打开过程中数据传递仍然有必要。使用 STGM_SHARE_DENY_WRITE 或 STGM_SHARE_EXCLUSIVE 可以提高打开文件的速度。关于在多写者时修改的提交更多信息请参考 IStorage::Commit 。
在“单写者,多读者”情况下,延时写的 storage 对象被多个读者共享。写者用 STGM_TRANSACTED, STGM_READWRITE 或者 STGM_WRITE, 和 STGM_SHARE_DENY_WRITE 标志打开。读者用 STGM_TRANSACTED, STGM_READ, 和 STGM_SHARE_DENY_NONE. 标志打开。写者用 scratch 区域存贮没有提交的修改。在上面的情况中,读者受到创建快照的影响打开速度增加。
一般, scratch 区域是一个临时文件,与原始数据分割开。当没有提交的修改提交回原始数据是,数据从临时文件转出。为了避免数据传递,可以使用 STGM_NOSCRATCH 标志。当这个标志被指定以后, storage 对象文件的部分区域用于 scratch 区域,不是用临时文件。因为只需要少量的数据传递所以提交修改的速度大幅度提高。这个做的缺点是存贮文件的大小会比其他方式要大的多。因为要足够大才能存下原始数据和 scratch 区域。为了混合数据和移除不必要的书,用延时模式重新打开根 storage ,不设置 STGM_NOSCRATCH 标志,接着调用带 STGC_CONSOLIDATE 参数的 IStorage::Commit 方法。
快照区域和 scratch 区域一样一般是临时文件,也会受 STMG 标志的影响。设置 STGM_NOSNAPSHOT ,独立的快照文件不会被创建,即使每个对象有一个写者或多个写者都不会修改原始数据。当提交修改的时候,他们被追加到文件中,但是原始数据保持不变。这种模式可以提高效率,因为通过放弃在打开时创建快照的要求而减少了运行时间。然而这个模式也许会导致非常大的 storage 文件,因为文件中的数据重来没有被覆盖过。在没有快照模式对文件的大小是没有限制的。
直接的单写者、多读者模式( Direct Single-Writer, Multiple-Reader Mode )
如前面描述,一个 storage 对象有一个单独的写者、多个读者是可能的,如果那个对象是工作在延时模式。也可以通过设置 STGM_DIRECT_SWMR 标志来得到单写者、多读者模式。
设置 STGM_DIRECT_SWMR 之后,调用者可以在其他调用者以只读的权限打开文件的同时,用读 / 写权限打开同一个文件。用本标志和 STGM_TRANSACTED 标志是无效的。在本模式下,写者用下面的组合打开对象:
STGM_DIRECT_SWMR | STGM_READWRITE | STGM_SHARE_DENYWRITE
每个读者用下面的标志打开对象:
STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE
在本模式下,修改 storage 对象,写者必须获得对象独占的权限。只有当所有读者关闭文件之后才有可能。读者通过 IDirectWriterLock 接口去获得独占权限。
简单模式( Simple Mode )
简单模式在完成保存操作时非常有用,虽然可以获得效率但也有下面的限制:
l 不支持子 storage
l 从该模式下的对象获得的 storage 对象和 stream 对象不能被封装
l 每个 stream 都有一个最小大小。如果在 stream 释放的时候写入比最小值还少的字节数,这个 stream 被扩展到最小值。例如:对某一个 IStream 实现来说最小值是 4KB ,一个 stream 只有 1KB ,在 stream 释放的时候,就被自动扩展到 4KB 。接下来打开或者调用 IStream::Stat 都会显示 4KB 的大小。
l 不是 IStorage 和 IStream 的所有方法都被实现。获得更多,请看 IStorage – 复合文件的实现, IStream- 复合文件的实现。
封送处理( Marshaling ) 是打包,解包,使用 RPC 穿透线程或者进程边界进行接口方法参数传递的过程。获得更多信息,请看封送详解和接口封送。
当一个 storage 对象是通过简单模式创建:
l stream 元素可以被创建,但不能被打开。
l 当一个 stream 元素通过 IStorage::CreateStream 创建,只有当这个 stream 对象被释放之后才能创建另一个对象。
l 当所有的 stream 被写入之后,调用 IStorage::Commit 完成修改。
如果一个 storage 对象是用简单模式打开而获得:
l 一次只能打开一个 stream.
l 不能调用 IStream::SetSize 或者在 stream 结束之外搜索和写入来设置 stream 的大小。然而,如果所有的 stream 都小于大小的最小值,可以用 stream 去扩展到最小值,即使没有数据。设置 stream 的大小使用 IStream::Stat 方法。
注意:如果一个 storage 元素被一个不是简单模式的 storage 对象修改,那么无法再以简单模式打开这个 storage 元素。
头文件申明在: Objbase.h.