Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

756 lines
31 KiB

  1. // MSITStg.h -- Interface declaration for IMSITStorage
  2. #ifndef __MSITSTG_H__
  3. #define __MSITSTG_H__
  4. // Class ID for the ITSS File System:
  5. DEFINE_GUID(CLSID_ITStorage,
  6. 0x5d02926a, 0x212e, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  7. // Inteface ID for the IITStorage interface:
  8. DEFINE_GUID(IID_ITStorage,
  9. 0x88cc31de, 0x27ab, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  10. // Interface ID for the IITStorageEx interface:
  11. DEFINE_GUID(IID_ITStorageEx,
  12. 0xe74097b0, 0x292d, 0x11d1, 0xb6, 0x7e, 0x0, 0x0, 0xf8, 0x1, 0x49, 0xf6);
  13. // Class ID for the FSStorage wrapper for the Win32 file system:
  14. // {D54EEE56-AAAB-11d0-9E1D-00A0C922E6EC}
  15. DEFINE_GUID(CLSID_IFSStorage,
  16. 0xd54eee56, 0xaaab, 0x11d0, 0x9e, 0x1d, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  17. // Interface ID for the IFSStorage interface:
  18. // {8BB2438A-A70C-11d0-9E1C-00A0C922E6EC}
  19. DEFINE_GUID(IID_IFSStorage,
  20. 0x8bb2438a, 0xa70c, 0x11d0, 0x9e, 0x1c, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  21. // Interface ID for the extended IStream interface
  22. DEFINE_GUID(IID_IStreamITEx,
  23. 0xeb19b681, 0x9360, 0x11d0, 0x9e, 0x16, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  24. // Interface ID for the extended IStorage interface
  25. DEFINE_GUID(IID_IStorageITEx,
  26. 0xeb19b680, 0x9360, 0x11d0, 0x9e, 0x16, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  27. // Interface IDs for the Data Space Manager used within an ITStorage object:
  28. DEFINE_GUID(IID_IDataSpaceManager,
  29. 0x7c01fd0f, 0x7baa, 0x11d0, 0x9e, 0xc, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  30. DEFINE_GUID(IID_IDataSpace,
  31. 0x7c01fd0e, 0x7baa, 0x11d0, 0x9e, 0xc, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  32. DEFINE_GUID(IID_ITransformServices,
  33. 0xa55895fc, 0x89e1, 0x11d0, 0x9e, 0x14, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  34. DEFINE_GUID(IID_IKeyInstance,
  35. 0x96af35ce, 0x88ec, 0x11d0, 0x9e, 0x14, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  36. // Interface IDs for the plug-in data transforms:
  37. DEFINE_GUID(IID_ITransformFactory,
  38. 0x7c01fd0c, 0x7baa, 0x11d0, 0x9e, 0xc, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  39. DEFINE_GUID(IID_ITransformInstance,
  40. 0xeb19b67e, 0x9360, 0x11d0, 0x9e, 0x16, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  41. // Interface ID for the File Finder interface (used with URLs):
  42. DEFINE_GUID(IID_IITFileFinder,
  43. 0x77231260, 0x19c0, 0x11d1, 0xb6, 0x6e, 0x0, 0x0, 0xf8, 0x1, 0x49, 0xf6);
  44. /*
  45. The IITStorage interface parallels the API's defined for creating and
  46. opening Docfiles. So if you have code that currently uses Docfiles for
  47. your storage mechanism, you can easily convert over to using ITS files
  48. instead.
  49. ITS files use a different on-disk structure to optimize them for very
  50. fast stream access and very low overhead. ITS files can manage thousands
  51. or millions of streams with very good access performance and very small
  52. directory space requirements. This makes ITS files ideal for CD-Roms and
  53. for data collections that you'll download across the Internet.
  54. To make the conversion to ITS files you'll need to call CoCreateInstance
  55. with the class-id CLSID_ITStorage and the interface-id IID_ITStorage. You'll
  56. get back an interface pointer, say pItStg. Then you'll need to adjust the
  57. places where your code creates or opens Docfiles. Instead of StgCreateDocfile
  58. you'll call pItStg->StgCreateDocfile, and instead of StgOpenStorage, you'll
  59. call pItStg->StgOpenStorage. In both cases you'll get back an IStorage
  60. interface pointer, say pIStg, which you can use just as you did before.
  61. That's it. In general the rest of your code shouldn't have to change. There
  62. are some functional difference between ITS files and Docfiles -- ITS files
  63. don't support STGM_TRANSACTED, for example. So if you have to have transacted
  64. file operations, you can't use ITS files -- at least for now. However in
  65. almost all other respects ITS files interfaces can directly replace Docfile
  66. interfaces.
  67. Converting your data is also easy. Just open one of your Docfiles using
  68. StgOpenStorage, create a new ITS file via pItStg->StgCreateDocfile, and then
  69. use the CopyTo interface to copy your data objects and their storage heirarchy
  70. over to the ITS file:
  71. pStgDocfile->CopyTo(0, NULL, NULL, pStgITS);
  72. In some cases you may want to exercise some control over the internal parameters
  73. kept in an ITS file. You do this by calling SetControlData to give the IITStorage
  74. interface a block of ITS control data. Then each subsequent call to StgCreateDocfile
  75. will use that control data. The ITS control data determines, among other things,
  76. the tradeoff between efficient random access to the stream data and minimizing the
  77. size of an ITS file.
  78. The actual structure and interpretation of ITS control data is documented below.
  79. (See the ITSFS_Control_Data data type). You can get default control data via the
  80. DefaultControlData fuction. Note that DefaultControlData allocates the control
  81. structure using IMalloc::Alloc as provided by CoGetMalloc and expects that your code will
  82. deallocate the structure using the IMalloc::Free.
  83. */
  84. // IID_IStreamITEx interface declaration:
  85. DECLARE_INTERFACE_(IStreamITEx, IStream)
  86. {
  87. // IStreamITEx methods
  88. STDMETHOD(SetDataSpaceName)(const WCHAR * pwcsDataSpaceName) PURE;
  89. STDMETHOD(GetDataSpaceName)( WCHAR **ppwcsDataSpaceName) PURE;
  90. STDMETHOD(Flush)() = 0;
  91. };
  92. // IID_IStorageITEx interface declaration:
  93. DECLARE_INTERFACE_(IStorageITEx, IStorage)
  94. {
  95. // IStorageITEx methods:
  96. STDMETHOD(GetCheckSum)(ULARGE_INTEGER *puli) PURE;
  97. STDMETHOD(CreateStreamITEx)(const WCHAR * pwcsName, const WCHAR *pwcsDataSpaceName,
  98. DWORD grfMode, DWORD reserved1, DWORD reserved2,
  99. IStreamITEx ** ppstm
  100. ) PURE;
  101. STDMETHOD(OpenStreamITEx)(const WCHAR * pwcsName, void * reserved1, DWORD grfMode,
  102. DWORD reserved2, IStreamITEx ** ppstm) PURE;
  103. };
  104. #pragma warning( disable : 4200)
  105. // ITS_Control_Data is the generic structure of control data passed to the
  106. // IITStorage::SetControlData method or returned by the IITStorage::DefaultControlData
  107. // method.
  108. typedef struct _ITS_Control_Data
  109. {
  110. UINT cdwControlData; // Number of DWords to follow.
  111. UINT adwControlData[0]; // Actually this will be adwControlData[cdwControlData]
  112. } ITS_Control_Data, *PITS_Control_Data;
  113. // ITSFS_Control_Data is the actual prefix structure of control data for IITStorage.
  114. typedef struct _ITSFS_Control_Data
  115. {
  116. UINT cdwFollowing; // Must be 6 or 13
  117. DWORD cdwITFS_Control; // Must be 5
  118. DWORD dwMagic; // Must be MAGIC_ITSFS_CONTROL (see below)
  119. DWORD dwVersion; // Must be 1
  120. DWORD cbDirectoryBlock;// Size in bytes of directory blocks (Default is 8192)
  121. DWORD cMinCacheEntries;// Least upper bound on the number of directory blocks
  122. // which we'll cache in memory. (Default is 20)
  123. DWORD fFlags; // Control bit flags (see below).
  124. // Default value is fDefaultIsCompression.
  125. } ITSFS_Control_Data, *PITSFS_Control_Data;
  126. // Signature value for ITSFS_Control_Data
  127. const DWORD MAGIC_ITSFS_CONTROL = 'I' | ('T' << 8) | ('S' << 16) | ('C' << 24);
  128. // Bit flag definitions for ITSFS_Control_Data::fFlags
  129. const DWORD fDefaultIsCompression = 0x00000001;
  130. const DWORD fDefaultIsUncompressed = 0x00000000;
  131. // Note all other fFlags bits positions are reserved for future releases and should be
  132. // set to zero.
  133. // When ITSFS_Control_Data::cdwFollowing is > 6, we assume that LZX_Control_Data follows
  134. // immediately after. (See the XformControlData type below) LZX_Control_Data defines
  135. // parameters which control the default compressed data space.
  136. //
  137. // If ITSFS_Control_Data::cdwFollowing is 6, we use default values for the LZX
  138. // control data.
  139. typedef struct _LZX_Control_Data
  140. {
  141. UINT cdwControlData; // Must be 6
  142. DWORD dwLZXMagic; // Must be LZX_MAGIC (see below)
  143. DWORD dwVersion; // Must be 2
  144. DWORD dwMulResetBlock;// Number of blocks between compression resets. (Default: 4)
  145. DWORD dwMulWindowSize;// Maximum number of blocks kept in data history (Default: 4)
  146. DWORD dwMulSecondPartition; // Granularity in blocks of sliding history(Default: 2)
  147. DWORD dwOptions; // Option flags (Default: fOptimizeCodeStreams)
  148. } LZX_Control_Data, *PLZX_Control_Data;
  149. // Note: The block size for LZX compression is 32768 bytes.
  150. const DWORD LZX_MAGIC = 'L' | ('Z' << 8 ) | ('X' << 16) | ('C' << 24);
  151. // Values for LZX_Control_Data::dwOptions
  152. const DWORD fOptimizeCodeStreams = 0x00000001;
  153. // Note that all other flag bit positions are reserved for future releases and should be
  154. // set to zero.
  155. // The second parameter for the IITStorage::Compact method below is an enueration
  156. // which defines the level of compaction to do.
  157. typedef enum ECompactionLev {COMPACT_DATA=0, COMPACT_DATA_AND_PATH} ;
  158. DECLARE_INTERFACE_(IITStorage, IUnknown)
  159. {
  160. // IITStorage methods
  161. STDMETHOD(StgCreateDocfile)(const WCHAR * pwcsName, DWORD grfMode,
  162. DWORD reserved, IStorage ** ppstgOpen
  163. ) PURE;
  164. STDMETHOD(StgCreateDocfileOnILockBytes)(ILockBytes * plkbyt, DWORD grfMode,
  165. DWORD reserved, IStorage ** ppstgOpen
  166. ) PURE;
  167. STDMETHOD(StgIsStorageFile)(const WCHAR * pwcsName) PURE;
  168. STDMETHOD(StgIsStorageILockBytes)(ILockBytes * plkbyt) PURE;
  169. STDMETHOD(StgOpenStorage)(const WCHAR * pwcsName, IStorage * pstgPriority,
  170. DWORD grfMode, SNB snbExclude, DWORD reserved,
  171. IStorage ** ppstgOpen
  172. ) PURE;
  173. STDMETHOD(StgOpenStorageOnILockBytes)
  174. (ILockBytes * plkbyt, IStorage * pStgPriority, DWORD grfMode,
  175. SNB snbExclude, DWORD reserved, IStorage ** ppstgOpen
  176. ) PURE;
  177. STDMETHOD(StgSetTimes)(WCHAR const * lpszName, FILETIME const * pctime,
  178. FILETIME const * patime, FILETIME const * pmtime
  179. ) PURE;
  180. STDMETHOD(SetControlData)(PITS_Control_Data pControlData) PURE;
  181. STDMETHOD(DefaultControlData)(PITS_Control_Data *ppControlData) PURE;
  182. STDMETHOD(Compact)(const WCHAR * pwcsName, ECompactionLev iLev) PURE;
  183. };
  184. DECLARE_INTERFACE_(IITStorageEx, IITStorage)
  185. {
  186. STDMETHOD(StgCreateDocfileForLocale)
  187. (const WCHAR * pwcsName, DWORD grfMode, DWORD reserved, LCID lcid,
  188. IStorage ** ppstgOpen
  189. ) PURE;
  190. STDMETHOD(StgCreateDocfileForLocaleOnILockBytes)
  191. (ILockBytes * plkbyt, DWORD grfMode, DWORD reserved, LCID lcid,
  192. IStorage ** ppstgOpen
  193. ) PURE;
  194. STDMETHOD(QueryFileStampAndLocale)(const WCHAR *pwcsName, DWORD *pFileStamp,
  195. DWORD *pFileLocale) PURE;
  196. STDMETHOD(QueryLockByteStampAndLocale)(ILockBytes * plkbyt, DWORD *pFileStamp,
  197. DWORD *pFileLocale) PURE;
  198. };
  199. typedef IITStorage *PIITStorage;
  200. DECLARE_INTERFACE_(IFSStorage, IUnknown)
  201. {
  202. // IUnknown methods
  203. STDMETHOD(QueryInterface) (THIS_ REFIID, VOID **) PURE;
  204. STDMETHOD_(ULONG, AddRef) (THIS) PURE;
  205. STDMETHOD_(ULONG, Release) (THIS) PURE;
  206. // IFSStorage methods
  207. STDMETHOD(FSCreateStorage)(const WCHAR * pwcsName, DWORD grfMode, IStorage **ppstgOpen) PURE;
  208. STDMETHOD(FSOpenStorage)(const WCHAR * pwcsName, DWORD grfMode, IStorage **ppstgOpen) PURE;
  209. STDMETHOD(FSCreateStream)(const WCHAR *pwcsName, DWORD grfMode, IStream **ppStrm) PURE;
  210. STDMETHOD(FSCreateTemporaryStream)(IStream **ppStrm) PURE;
  211. STDMETHOD(FSOpenStream )(const WCHAR *pwcsName, DWORD grfMode, IStream **ppStrm) PURE;
  212. STDMETHOD(FSCreateLockBytes)(const WCHAR *pwcsName, DWORD grfMode, ILockBytes **ppLkb) PURE;
  213. STDMETHOD(FSCreateTemporaryLockBytes)(ILockBytes **ppLkb) PURE;
  214. STDMETHOD(FSOpenLockBytes )(const WCHAR *pwcsName, DWORD grfMode, ILockBytes **ppLkb) PURE;
  215. STDMETHOD(FSStgSetTimes)(WCHAR const * lpszName, FILETIME const * pctime,
  216. FILETIME const * patime, FILETIME const * pmtime
  217. ) PURE;
  218. };
  219. typedef IFSStorage *PIFSStorage;
  220. /*
  221. ** Data Spaces -- What they are.
  222. Within an ITS file we store information in one or more data spaces. A data space
  223. is a container which holds the bits which represent a collection of streams. Each
  224. data space has a name and an associated collection of transforms.
  225. Those transforms take the raw data which you write to an ITS stream and map it into
  226. a representation stream. When you read from an ITS stream they do the reverse mapping
  227. to reconstruct your original data from the representation.
  228. When you first create an ITS file, it contains one data space named "Default_Space"
  229. which applies the LZX data compression transform. By default all of the streams you
  230. create will have their data representations stored in the default data space.
  231. If LZX compression meets your needs, and you're not concerned about data enciphering,
  232. you can skip over the following discussion. If, on the other hand, you want to
  233. create additional data spaces or transforms, read on.
  234. To create a data space, you must first get a pointer to the IDataSpaceManager interface.
  235. Just do a QueryInterface for IID_DataSpaceManager from any storage created by the
  236. IITStorage interface. Then you can call the CreateDataSpace function to define a new
  237. data space.
  238. When you're defining a collection of data spaces, be sure that their names are distinct.
  239. Defining two data spaces with the same name is an error. Data space names follow the
  240. rules for stream names. That is, they must be less than 260 characters long, and may
  241. not contain the characters '/'. '\', '|', ':', or any character less than 0x0020.
  242. Data spaces are kept in a separate name space. So you don't have to worry about
  243. colliding with a stream name or a storage name. As noted above, we have defined one
  244. special data space ("Default_Space") where all data resides if you take no action.
  245. You can redefine that default space simply by creating a new data space with the
  246. name "Default_Space". This is the one case where a name collision is allowed. If
  247. you do redefine the default data space, any data in the old space will automatically
  248. be transformed appropriately and moved into the new default data space.
  249. ** Importing Items
  250. If you have defined additional data spaces, the next step is to define which streams
  251. and storages you want to move into the new data spaces. You do that by means of the
  252. IDataSpace::Import function. For example suppose you've defined the dataspace
  253. *pMyDataSpace and you want to import the stream "Alpha" contained in the storage
  254. *pThatStorage:
  255. pMyDataSpace->Import(pThatStorage, "Alpha");
  256. Similarly if you want to import the storage "HTML_Pages" from pThisStorage:
  257. pMyDataSpace->Import(pThisStorage, "HTML_Pages");
  258. That will recursively import the "HTML_Pages" storage and all of the streams and
  259. storages contained within it. It also conditions those storages so that anything
  260. you create within them will be automatically imported into pMyDataSpace. Note that
  261. subsequent Import operations may alter that conditioning.
  262. If you later decide that you want to move "Alpha" back into the default data
  263. space:
  264. hr = pDataSpaceManager->OpenDataSpace(L"Default_Space", &pDefaultDataSpace);
  265. pDefaultDataSpace->Import(pThatStorage, "Alpha");
  266. ** Data Space Transform Sets
  267. When you define a data space, you must specify a set of transforms to apply to
  268. the items you import into the space. A transform is an interface that converts
  269. data to some other representation. For example the LZX transform converts your
  270. imported data into a more compact, compressed representation. Other transforms
  271. might implement word or phrase based dictionary compression, or they might encipher
  272. your data, or they might just convert from one data format to another. You could,
  273. for example, construct a transform to store HTML data as a Rich Text stream.
  274. When you define a data space with more than one transform, they are applied in
  275. order. For example let's suppose that your transform set consists of these three:
  276. 1. A Dictionary compression transform
  277. 2. The LXZ transform
  278. 3. An data encryption transform
  279. Whenever you write data into this space, it will first be compressed using the
  280. dictionary compression methods, then LZX compression will be applied, and finally
  281. your information will be encrypted. When you read data the process is reversed so
  282. that the encryption transform supplies data to the LZX transform which in turn
  283. provides data for the dictionary compression transform.
  284. You define the transform set via a vector of class ids (paclsidXform). Each class id
  285. defines a location where an implementation of IID_Transform can be found. In addition
  286. you'll supply corresponding control data for each transform (papxfcd). The number of
  287. transforms is defined by the cXforms parameter.
  288. Note that it is legal to define a space with zero transforms. This is useful when
  289. you've got items which are already compressed and which won't benefit from an
  290. additional layer of compression overhead.
  291. The control data for a transform defines how it will operate in a particular
  292. data space. For example the control data for the LZX transform defines how
  293. aggressively it will pursue compression, and it controls the tradeoff between
  294. random access performance and the level of compression.
  295. The actual structure and content of the control data is documented above.
  296. (See the LZX_Control_Data data type.)
  297. ** Transform Factories -- How they are organized; What they do
  298. Transforms have two functional capabilities. They can return default
  299. control data (DefaultControlData), and they can create
  300. transform instances (CreateTransformInstance). When the ITSS code calls your
  301. CreateTransformInstance function, it will supply a storage medium (pXFSpan_Base)
  302. where transformed data is to be stored along with the control data for the
  303. instance and several other useful pieces of information.
  304. The CreateTransformInstance function has several parameters that you can use
  305. when you need to access global and/or instance data streams. They also support
  306. the construction of encryption transforms. You can ignore those parameters if your
  307. transform doesn't do encryption, uses only a single pass over the data, and doesn't
  308. rely on any data beyond the data in the stream being transformed.
  309. -- The rclsidXForm and pwszDataSpace parameters, respectively, tell you the Class ID
  310. by which your code was located, and the name of the data space in which your instance
  311. will be working. These values are used with the ITransformServices interface.
  312. -- The pXformServices parameter points to an instance of the ITranformServices interface.
  313. That interface gives you access to a couple of storages where you can keep global and
  314. instance data for your transform. It also gives you a way to contruct a temporary
  315. stream that is automatically deleted when you release it. That's very handy when
  316. you get a seek operation into the middle of the transformed data followed by a write
  317. operation.
  318. If you're implementing a multipass strategy, you can get access to those storages
  319. from code outside the transform by doing a QueryInterface from any ITS storage for
  320. the interface IID_ITransformServices. You identify the storage in question by the
  321. transform's class id and possibly the name of the data space instance.
  322. The per-transform-instance storage is also a convenient place to put the navigation
  323. data necessary to support fast seek operations.
  324. -- The pKeyManager parameter is an interface pointer used with encryption transforms.
  325. It supplies the read and write keys to use with your encryption transform. Those keys
  326. are set by the SetKeys interface of the ITransformServices interface. This allows you
  327. to separate your user interface code where people will enter passwords from the
  328. transform implementations. This can be useful when you want the same keys to be used
  329. for several different data spaces.
  330. ** Transform Instances -- How they are organized; What they do
  331. A Transform Instance is an object which simulates a data medium which can be
  332. suballocated. Suballocated items are managed as data spans (ITransformedSpan).
  333. You must supply a function to create a data span (CreateTransformedSpan), and
  334. a function to open a data span (OpenTransformedSpan). Both of those functions
  335. return an ITransformedSpan interface when they succeed. In addition you must
  336. supply the function SpaceSize to return the size of the entire untransformed
  337. data image. That is, SpaceSize returns the highest limit offset (offset + size)
  338. of any data span created within the instance.
  339. A span is identified by an ImageSpan structure which defines an offset and a size
  340. for the span. Both values are defined in untransformed space. For the Create function
  341. this is an output parameter, while it is an input parameter for the Open function.
  342. Note the interaction between the ImageSpan and the WriteAt member function of the
  343. ITransformedSpan interface.
  344. ** Transformed Data Spans -- How they are organized; What they do
  345. A transformed Data Span (ITransformedSpan) has two member functions -- ReadAt and
  346. WriteAt. Those functions are very similar to the ReadAt and WriteAt functions of
  347. the ILockBytes interface. The difference is that WriteAt includes an extra output
  348. parameter (pImageSpan) for recording the current span parameters. The ReadAt function
  349. doesn't include that parameter because read operations can never change the span's
  350. size or move it to a different offset.
  351. ** Implementation Strategies
  352. This section describes a few scenarios that you may encounter as you construct a
  353. transform along with strategies for those situations. This is an open ended list
  354. which will expand as we gain more experience with transforms.
  355. Many compression and encryption transforms are designed around sequential I/O. That is,
  356. they expect to get the raw data from a sequence of write opeations with no intervening
  357. seek operations. In many cases such transforms also write out the transformed data to
  358. the base stream in ascending order. Similarly they expect read requests to come to them
  359. with no intervening seek operations.
  360. The key issue for those transforms is how do you implement random access and interleaved
  361. read, write, and seek operations.
  362. Leaving aside write operations for the moment, let's consider a random sequence of reads
  363. interleaved with seek operations. One solution might be to construct a table to map from
  364. raw data offsets to transformed data offsets. You can store such a table in the instance
  365. storage for the current data space.
  366. One complication is that many compression transforms use the raw data as a dictionary.
  367. That is, you can only start reading from the beginning of the transformed data. You can
  368. deal with those transforms telling them to reset themselves periodically. That gives
  369. you a collection of starting points spread fairly evenly throught the transformed
  370. data. When you do this you'll need to supply a control data parameter to control the
  371. frequency of those reset points so that your clients can make an appropriate tradeoff
  372. between compression efficiency and random access performance.
  373. Now what about adding random write operations to the mix? The short answer here is that
  374. you can't do this in the middle of transformed data. One strategy would be to reconstruct
  375. the entire raw data into a temporary stream and do all your I/O to that stream until
  376. release time. Then at release time you can transform the revised data sequentially.
  377. A variation on that strategy is to keep track of which reset spans are modified and
  378. write the modified versions of those transformed spans to the end of the base stream.
  379. This leaves a certain amount of dead space in your transformed data, but it allows
  380. you to defer the sequential reconstruction work to a more convenient time. The down
  381. side is that it requires you to manage yet more navigation data in the instance
  382. storage for the data space.
  383. */
  384. interface IDataSpaceManager;
  385. interface IDataSpace;
  386. interface ITransformServices;
  387. interface IKeyInstance;
  388. interface ITransformFactory;
  389. interface ITransformInstance;
  390. typedef struct _XformControlData
  391. {
  392. UINT cdwControlData; // Size of this structure in DWords
  393. UINT adwControlData[0]; // Actually this will be UINT adwData[cdwData];
  394. } XformControlData, *PXformControlData;
  395. /*
  396. // {7C01FD0F-7BAA-11d0-9E0C-00A0C922E6EC}
  397. DEFINE_GUID(IID_IDataSpaceManager,
  398. 0x7c01fd0f, 0x7baa, 0x11d0, 0x9e, 0xc, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  399. */
  400. interface IDataSpaceManager : public IUnknown
  401. {
  402. public:
  403. virtual HRESULT STDMETHODCALLTYPE CreateDataSpace
  404. (const WCHAR *pwszDataSpace, UINT cXforms,
  405. const CLSID *paclsidXform, PXformControlData paxfcd,
  406. IDataSpace *pITDataSpace
  407. ) = 0;
  408. virtual HRESULT STDMETHODCALLTYPE OpenDataSpace
  409. (const WCHAR *pwszDataSpace,
  410. IDataSpace *pITDataSpace
  411. ) = 0;
  412. virtual HRESULT STDMETHODCALLTYPE DiscardDataSpace
  413. (const WCHAR *pwszDataSpace) = 0;
  414. virtual HRESULT STDMETHODCALLTYPE EnumDataSpaces
  415. (IEnumSTATSTG ** ppenum) = 0;
  416. };
  417. /*
  418. // {7C01FD0E-7BAA-11d0-9E0C-00A0C922E6EC}
  419. DEFINE_GUID(IID_IDataSpace,
  420. 0x7c01fd0e, 0x7baa, 0x11d0, 0x9e, 0xc, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  421. */
  422. interface IDataSpace : public IUnknown
  423. {
  424. public:
  425. virtual HRESULT STDMETHODCALLTYPE GetTransformInfo
  426. (PUINT pcXforms, PUINT pcdwXformControlData,
  427. CLSID *paclsid, PXformControlData pxfcd
  428. ) = 0;
  429. virtual HRESULT STDMETHODCALLTYPE Import
  430. (IStorage *pStg, const WCHAR * pwszElementName) = 0;
  431. virtual HRESULT STDMETHODCALLTYPE ImportSpace(IStorage **ppStg) = 0;
  432. };
  433. /*
  434. // {7C01FD0C-7BAA-11d0-9E0C-00A0C922E6EC}
  435. DEFINE_GUID(IID_ITransformFactory,
  436. 0x7c01fd0c, 0x7baa, 0x11d0, 0x9e, 0xc, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  437. */
  438. interface ITransformFactory : public IUnknown
  439. {
  440. public:
  441. virtual HRESULT STDMETHODCALLTYPE DefaultControlData
  442. (XformControlData **ppXFCD) = 0;
  443. virtual HRESULT STDMETHODCALLTYPE CreateTransformInstance
  444. (ITransformInstance *pXFormMedium, // Container data span for transformed data
  445. ULARGE_INTEGER cbUntransformedSize, // Untransformed size of data
  446. PXformControlData pXFCD, // Control data for this instance
  447. const CLSID *rclsidXForm, // Transform Class ID
  448. const WCHAR *pwszDataSpaceName, // Data space name for this instance
  449. ITransformServices *pXformServices, // Utility routines
  450. IKeyInstance *pKeyManager, // Interface to get enciphering keys
  451. ITransformInstance **ppTransformInstance // Out: Instance transform interface
  452. ) = 0;
  453. };
  454. typedef struct _ImageSpan
  455. {
  456. ULARGE_INTEGER uliHandle;
  457. ULARGE_INTEGER uliSize;
  458. } ImageSpan;
  459. /*
  460. // {EB19B67E-9360-11d0-9E16-00A0C922E6EC}
  461. DEFINE_GUID(IID_ITransformInstance,
  462. 0xeb19b67e, 0x9360, 0x11d0, 0x9e, 0x16, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  463. */
  464. interface ITransformInstance : public IUnknown
  465. {
  466. public:
  467. virtual HRESULT STDMETHODCALLTYPE ReadAt
  468. (ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead,
  469. ImageSpan *pSpan
  470. ) = 0;
  471. virtual HRESULT STDMETHODCALLTYPE WriteAt
  472. (ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten,
  473. ImageSpan *pSpan
  474. ) = 0;
  475. virtual HRESULT STDMETHODCALLTYPE Flush() = 0;
  476. virtual HRESULT STDMETHODCALLTYPE SpaceSize(ULARGE_INTEGER *puliSize) = 0;
  477. // Note: SpaceSize returns the high water mark for the space. That is, the largest
  478. // limit value (uliOffset + uliSize) for any transformed lockbytes created within
  479. // the base (*pXLKB).
  480. };
  481. /*
  482. // {A55895FC-89E1-11d0-9E14-00A0C922E6EC}
  483. DEFINE_GUID(IID_ITransformServices,
  484. 0xa55895fc, 0x89e1, 0x11d0, 0x9e, 0x14, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  485. */
  486. interface ITransformServices : public IUnknown
  487. {
  488. public:
  489. virtual HRESULT STDMETHODCALLTYPE PerTransformStorage
  490. (REFCLSID rclsidXForm, IStorage **ppStg) = 0;
  491. virtual HRESULT STDMETHODCALLTYPE PerTransformInstanceStorage
  492. (REFCLSID rclsidXForm, const WCHAR *pwszDataSpace, IStorage **ppStg) = 0;
  493. virtual HRESULT STDMETHODCALLTYPE SetKeys
  494. (REFCLSID rclsidXForm, const WCHAR *pwszDataSpace,
  495. PBYTE pbReadKey, UINT cbReadKey,
  496. PBYTE pbWriteKey, UINT cbWriteKey
  497. ) = 0;
  498. virtual HRESULT STDMETHODCALLTYPE CreateTemporaryStream(IStream **ppStrm) = 0;
  499. };
  500. /*
  501. // {96AF35CE-88EC-11d0-9E14-00A0C922E6EC}
  502. DEFINE_GUID(IID_IKeyInstance,
  503. 0x96af35ce, 0x88ec, 0x11d0, 0x9e, 0x14, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);
  504. */
  505. interface IKeyInstance : public IUnknown
  506. {
  507. public:
  508. virtual HRESULT STDMETHODCALLTYPE GetKeys
  509. (PBYTE *pbReadKey, PUINT pcbReadKey,
  510. PBYTE *pbWriteKey, PUINT pcbWriteKey
  511. ) = 0;
  512. };
  513. /*
  514. Streams stored in an ITS file may be accessed through URLs with
  515. the form:
  516. its: <File Path> :: <Stream Path>
  517. where <File Path> may be either a Win32 file path or a URL, and
  518. <Stream Path> is the path to a stream stored in the ITS file.
  519. Each <Stream Path> must begin with '/'.
  520. This means that you can copy a Win32 directory tree of HTML files
  521. and associated files into an ITS file and get to them through ITS
  522. URLs. If all the URL references within those HTML files are
  523. relative, they will be resolved within the containing ITS file.
  524. The <File Path> portion of the URL may either be a complete path
  525. to the ITS file, or it may be just the file name. In the later case
  526. you may need to install auxillary information in the registry to
  527. help the ITSS code locate the file. Here are the rules:
  528. 1. If you don't supply a complete path, ITSS looks in the current
  529. working directory for the file.
  530. 2. If the file isn't found in step 1. ITSS looks for a registry
  531. value in the ITSS_MAP section of HKEY_LOCAL_MACHINE. The value
  532. name must match the file name, and the value will be a string
  533. giving the complete file path to be used.
  534. 3. If the file isn't found in steps 1 and 2, ITSS isolates the file's
  535. extension (beginning with the last '.' character) and looks
  536. for a corresponding class id value in the ITSS_FINDER section
  537. of HKEY_LOCAL_MACHINE. The name for the value will match the
  538. extension, and the value will be the class id for an object
  539. which implements the IID_IITFileFinder interface.
  540. 4. If the file isn't found in steps 1 through 3, the URL reference
  541. fails.
  542. */
  543. #define ITSS_MAP "Software\\Microsoft\\Windows\\ITStorage\\Maps"
  544. #define ITSS_FINDER "Software\\Microsoft\\Windows\\ITStorage\\Finders"
  545. interface IITFileFinder : public IUnknown
  546. {
  547. public:
  548. virtual HRESULT STDMETHODCALLTYPE FindThisFile(const WCHAR *pFileName, WCHAR **ppFullPath,
  549. BOOL *pfRecordPathInRegistry
  550. ) = 0;
  551. // The FindThisFile method maps a file name into a complete file path. The file name
  552. // is defined by *pFileName, and a pointer to the complete path is returned in
  553. // *ppFullPath. The returned path will be a string allocated in the IMalloc heap.
  554. // The *pfRecordPathInRegistry result should be TRUE when we should record this mapping
  555. // in the ITSS_MAP registry section and FALSE otherwise.
  556. };
  557. #endif // __MSITSTG_H__