Leaked source code of windows server 2003
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.

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