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.

514 lines
16 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. cmmprops.h
  5. Abstract:
  6. This module contains the definition of the property search class
  7. Author:
  8. Keith Lau (keithlau@microsoft.com)
  9. Revision History:
  10. keithlau 03/02/98 created
  11. --*/
  12. #ifndef _PROPS_H_
  13. #define _PROPS_H_
  14. #include "blockmgr.h"
  15. #include "propid.h"
  16. #include "mailmsgprops.h"
  17. /*
  18. This file defines a generice class for property tables. The following is
  19. the terminology used in relation to property tables:
  20. Search key - A value used to uniquely identify a property
  21. Property - A tuple consisting of a { Property Identifier, Value } pair.
  22. Property Identifier - the search key for the property table. The property
  23. table class does not restrict the data type or length of the property
  24. identifier, but rather, the caller must specify the length of the
  25. property identifier and provide a compare function when an instance
  26. of the property table is created.
  27. Value - A tuple consisting of a { Offset, Length } pair. The offset points
  28. to the physical location of the value and its length is specified by
  29. the Length element.
  30. Property Table - A collection of properties keyed off the designated
  31. property identifier.
  32. A property table contains an instance info record (PROPERTY_TABLE_INSTANCE),
  33. which describes the parameters of the table, such as the length of each
  34. property item record (PROPERTY_ITEM), how many items fit in a fragment
  35. (PROPERTY_TABLE_FRAGMENT), and a link to the first fragment.
  36. Fragments are linked together and thus a property table can hold an
  37. arbitrarily larger number of properties, until the identifier space is
  38. exhausted. Fragments contain property item records, each item record
  39. contains an ordered tuple: { Offset, Length, Max Length, Property Identifier }
  40. In the definition of PROPERTY_ITEM, the Property Identifier element is not
  41. explicitly defined, but it is implied that whatever follows Max Length
  42. is the property identifier. This allows maximum flexibility for different
  43. search key types. Similarly, although PROPERTY_TABLE_FRAGMENT does not
  44. include an array of PROPERTY_ITEMs, it is implied that an array of item
  45. records follow after faNextFragment. The size of the property identifier field
  46. is specified during instance creation so the size of each property item
  47. is fixed and known at run time.
  48. Since the property identifiers can be of different sizes, the creator must
  49. provide a function that knows how to compare a search key against a
  50. property item.
  51. A memory manager must be specified when the property table is created.
  52. This provides a mechanism for memory to be allocated and released in
  53. a linear, flat address space.
  54. */
  55. // Define the well-known property item structure. We will have a sorted
  56. // array of these items that make up the list of well-known properties.
  57. //
  58. // Arrays of this type MUST be sorted for correct search results.
  59. typedef struct _INTERNAL_PROPERTY_ITEM
  60. {
  61. PROP_ID idProp; // Prop ID
  62. DWORD dwIndex; // Reserved index of this prop ID
  63. } INTERNAL_PROPERTY_ITEM, *LPINTERNAL_PROPERTY_ITEM;
  64. // Define a generic structure to represent a property in the property
  65. // table
  66. // Each property table that uses this class as the accessor must have
  67. // an item structure that includes this structure as its first member
  68. typedef struct _PROPERTY_ITEM
  69. {
  70. FLAT_ADDRESS faOffset; // Offset in flat space to value
  71. DWORD dwSize; // Size of value data in bytes
  72. DWORD dwMaxSize; // Max size allocated for value
  73. } PROPERTY_ITEM, *LPPROPERTY_ITEM;
  74. // Define a generic structure to describe a fragment in the property table
  75. typedef struct _PROPERTY_TABLE_FRAGMENT
  76. {
  77. DWORD dwSignature; // Signature of fragment
  78. FLAT_ADDRESS faNextFragment; // Link to next fragment
  79. } PROPERTY_TABLE_FRAGMENT, *LPPROPERTY_TABLE_FRAGMENT;
  80. // Define a function type specifying the generic compare function passed
  81. // into the search routine
  82. //
  83. // Arguments:
  84. // LPVOID - pointer to search key value, the compare function must have
  85. // intimate knowledge of how to retrieve the property key from
  86. // the pointer and its size.
  87. // LPPROPERTY_ITEM - pointer to item to compare against. The compare
  88. // function must have intimate knowledge of how to retrieve the
  89. // property key from the item pointer. The actual size of this
  90. // structure is in PROPERTY_TABLE_INSTANCE.dwItemSize.
  91. //
  92. // Return values:
  93. // SUCCESS(HRESULT) - The item matches the search key
  94. // !SUCCESS(HRESULT) - The item does not match the search key
  95. //
  96. typedef HRESULT (*LPPROPERTY_COMPARE_FUNCTION)(LPVOID, LPPROPERTY_ITEM);
  97. // Define a generic structure to describe the property table instance
  98. // Each property table that uses this class as the accessor must have
  99. // an instance structure that includes this structure as its first member
  100. typedef struct _PROPERTY_TABLE_INSTANCE
  101. {
  102. DWORD dwSignature; // Signature of instance
  103. FLAT_ADDRESS faFirstFragment;// Link to first fragment
  104. DWORD dwFragmentSize; // Size of each fragment
  105. DWORD dwItemBits; // # lower bits that represent the item
  106. DWORD dwItemSize; // Size of a specific PROPERTY_ITEM
  107. DWORD dwProperties; // # properties in this instance
  108. FLAT_ADDRESS faExtendedInfo; // Link to any specific extended into
  109. } PROPERTY_TABLE_INSTANCE, *LPPROPERTY_TABLE_INSTANCE;
  110. // Enumerate the different applications of the property table
  111. // This is used to track what kind of table we are looking at for debugging
  112. typedef enum _PROPERTY_TABLE_TYPES
  113. {
  114. PTT_INVALID_TYPE = 0, // Default value
  115. PTT_PROPERTY_TABLE, // Standard property table
  116. PTT_RECIPIENT_TABLE, // Recipient table
  117. PTT_PROP_ID_TABLE // Prop ID management table
  118. } PROPERTY_TABLE_TYPES;
  119. // Enumerate the different types of operations GetOrSetNextExistingItem
  120. // supports
  121. typedef enum _PROPERTY_ITEM_OPERATIONS
  122. {
  123. PIO_INVALID_TYPE = 0, // Default value
  124. PIO_READ_ITEM, // Normal read
  125. PIO_WRITE_ITEM, // Normal write
  126. PIO_ATOMIC_WRITE_ITEM // Protected write
  127. } PROPERTY_ITEM_OPERATIONS;
  128. #include "cmmtypes.h"
  129. // =================================================================
  130. // class for accessing items from the property table. This class
  131. // hides the details of fragmentation.
  132. //
  133. // This class is single-threaded
  134. //
  135. class CPropertyTableItem
  136. {
  137. public:
  138. CPropertyTableItem(
  139. CBlockManager *pBlockManager,
  140. LPPROPERTY_TABLE_INSTANCE pInstanceInfo
  141. );
  142. ~CPropertyTableItem();
  143. HRESULT AddItem(
  144. LPPROPERTY_ITEM pItem,
  145. DWORD *pdwIndex,
  146. FLAT_ADDRESS *pfaOffsetToItem = NULL
  147. );
  148. HRESULT UpdateItem(
  149. DWORD dwIndex,
  150. LPPROPERTY_ITEM pItem,
  151. FLAT_ADDRESS *pfaOffsetToItem = NULL
  152. );
  153. HRESULT GetItemAtIndex(
  154. DWORD dwIndex,
  155. LPPROPERTY_ITEM pItem,
  156. LPFLAT_ADDRESS pfaOffset = NULL
  157. );
  158. HRESULT GetNextItem(
  159. LPPROPERTY_ITEM pItem
  160. );
  161. HRESULT GetOffsetToCurrentItem(
  162. FLAT_ADDRESS *pfaOffset
  163. )
  164. { if (pfaOffset) *pfaOffset = m_faOffsetToCurrentItem; return(S_OK); }
  165. private:
  166. HRESULT GetOrSetNextExistingItem(
  167. // This looks at m_dwCurrentItem for index
  168. LPPROPERTY_ITEM pItem,
  169. DWORD dwOperation,
  170. LPFLAT_ADDRESS pfaOffset = NULL
  171. );
  172. HRESULT ReadFragmentFromFragmentNumber(
  173. DWORD dwFragmentNumber
  174. );
  175. HRESULT ReadFragment(
  176. FLAT_ADDRESS faOffset
  177. );
  178. public:
  179. HRESULT ReadItem(
  180. FLAT_ADDRESS faOffset,
  181. LPPROPERTY_ITEM pItem
  182. );
  183. private:
  184. HRESULT WriteItem(
  185. FLAT_ADDRESS faOffset,
  186. LPPROPERTY_ITEM pItem,
  187. BOOL fAtomic
  188. );
  189. // Info of parent instance
  190. LPPROPERTY_TABLE_INSTANCE m_pInstanceInfo;
  191. // Current fragment being processed
  192. BOOL m_fLoaded;
  193. PROPERTY_TABLE_FRAGMENT m_Fragment;
  194. DWORD m_dwCurrentFragment;
  195. FLAT_ADDRESS m_faOffsetToFragment;
  196. DWORD m_dwCurrentItem;
  197. DWORD m_dwCurrentItemInFragment;
  198. FLAT_ADDRESS m_faOffsetToCurrentItem;
  199. // Memory manager pointer and context for fast access
  200. CBlockManager *m_pBlockManager;
  201. CBlockContext m_bcContext;
  202. };
  203. // =================================================================
  204. // class for accessing an instance of a property table
  205. //
  206. class CPropertyTable
  207. {
  208. public:
  209. CPropertyTable(
  210. PROPERTY_TABLE_TYPES pttTableType,
  211. DWORD dwValidSignature,
  212. CBlockManager *pBlockManager,
  213. LPPROPERTY_TABLE_INSTANCE pInstanceInfo,
  214. LPPROPERTY_COMPARE_FUNCTION pfnCompare,
  215. const LPINTERNAL_PROPERTY_ITEM pInternalProperties = NULL,
  216. DWORD dwInternalProperties = 0
  217. );
  218. ~CPropertyTable();
  219. BOOL IsValid();
  220. BOOL IsInstanceInfoValid();
  221. //
  222. // Method to return the property count
  223. //
  224. // GetCount - Returns the current property count
  225. //
  226. // Arguments
  227. // pdwCount - Pointer to DWORD to return count
  228. //
  229. // Return values
  230. //
  231. // S_OK - Succeeded
  232. //
  233. HRESULT GetCount(
  234. DWORD *pdwCount
  235. );
  236. //
  237. // Method to create or update a property item and value given a search key
  238. //
  239. // PutProperty - Creates the specified property if the property does not
  240. // exist, or updates the value of the property otherwise.
  241. //
  242. // Arguments
  243. // pvPropKey - Pointer to the search key
  244. // pItem - Pointer to the property item to write
  245. // dwSize - Size of property value data
  246. // pbValue - Pointer to property value data. If this value is NULL,
  247. // then no data is written, only the item record is created
  248. // or updated. dwSize must also be zero.
  249. //
  250. // Return values
  251. //
  252. // S_OK - Succeeded, property already exists, but the
  253. // value is updated as specified.
  254. // S_FALSE - Succeeded, new property is created
  255. // STG_E_INVALIDPARAMETER - Error, one or more parameters are invalid, or
  256. // otherwise inconsistent.
  257. // STG_E_WRITEFAULT - Error, The write failed to complete.
  258. // TYPE_E_OUTOFBOUNDS - Debug Error, a write is issued to write past
  259. // the current allocated block.
  260. //
  261. HRESULT PutProperty(
  262. LPVOID pvPropKey,
  263. LPPROPERTY_ITEM pItem,
  264. DWORD dwSize,
  265. LPBYTE pbValue
  266. );
  267. //
  268. // Method to retrieve a property item given a search key
  269. //
  270. // GetPropertyItem - Attempts to find the property item specified by the
  271. // Search key. If found, the property item record will
  272. // be returned.
  273. //
  274. // Arguments
  275. // pvPropKey - Pointer to the search key
  276. // pItem - Pointer to the property item to return, sufficient space
  277. // must be allocated by the caller to hold the property item
  278. //
  279. // Return values
  280. //
  281. // S_OK - Succeeded
  282. // STG_E_UNKNOWN - Error, specified property not found.
  283. // STG_E_INVALIDPARAMETER - Error, one or more parameters are invalid, or
  284. // otherwise inconsistent.
  285. // STG_E_READFAULT - Error, The read failed to complete.
  286. // TYPE_E_OUTOFBOUNDS - Debug Error, a read is issued to write past
  287. // the current allocated block.
  288. //
  289. HRESULT GetPropertyItem(
  290. LPVOID pvPropKey,
  291. LPPROPERTY_ITEM pItem
  292. );
  293. //
  294. // Method to retrieve a property item and its associated value
  295. //
  296. // GetPropertyItemAndValue - Attempts to find the property item specified
  297. // by the Search key. If found, the property item record, as
  298. // well as the value data will be returned.
  299. //
  300. // Arguments
  301. // pvPropKey - Pointer to the search key
  302. // pItem - Pointer to the property item to return, sufficient space
  303. // must be allocated by the caller to hold the property item
  304. // dwLength - Size of buffer allocated for value data
  305. // pdwLengthRead- Size of value data actually read, if the provided buffer is
  306. // insufficient, then the full length of the property data is
  307. // returned.
  308. // pbValue - Pointer to return property value data.
  309. //
  310. // Return values
  311. //
  312. // S_OK - Succeeded
  313. // STG_E_UNKNOWN - Error, specified property not found.
  314. // HRESULT_FROM_WIN32(ERROR_MORE_DATA) - Error, the buffer provided is not
  315. // large enough to hold all the value data.
  316. // *pdwLengthRead returns the full length. *pItem
  317. // would still return the item record in this case.
  318. // STG_E_INVALIDPARAMETER - Error, one or more parameters are invalid, or
  319. // otherwise inconsistent.
  320. // STG_E_READFAULT - Error, The read failed to complete.
  321. // TYPE_E_OUTOFBOUNDS - Debug Error, a read is issued to write past
  322. // the current allocated block.
  323. //
  324. HRESULT GetPropertyItemAndValue(
  325. LPVOID pvPropKey,
  326. LPPROPERTY_ITEM pItem,
  327. DWORD dwLength,
  328. DWORD *pdwLengthRead,
  329. LPBYTE pbValue
  330. );
  331. //
  332. // Method to retrieve a property item and its associated value, using an
  333. // internal index instead of a search key.
  334. //
  335. // GetPropertyItemAndValueUsingIndex - Attempts to find the property item
  336. // specified by the Search key. If found, the property item
  337. // record, as well as the value data will be returned.
  338. //
  339. // Arguments
  340. // dwIndex - Index of item to retrieve, this is actually the dwIndex'th
  341. // item in the property table. One can walk the entire table
  342. // using this method.
  343. // pItem - Pointer to the property item to return, sufficient space
  344. // must be allocated by the caller to hold the property item
  345. // dwLength - Size of buffer allocated for value data
  346. // pdwLengthRead- Size of value data actually read, if the provided buffer is
  347. // insufficient, then the full length of the property data is
  348. // returned.
  349. // pbValue - Pointer to return property value data.
  350. //
  351. // Return values
  352. //
  353. // S_OK - Succeeded
  354. // STG_E_UNKNOWN - Error, specified property not found.
  355. // HRESULT_FROM_WIN32(ERROR_MORE_DATA) - Error, the buffer provided is not
  356. // large enough to hold all the value data.
  357. // *pdwLengthRead returns the full length. *pItem
  358. // would still return the item record in this case.
  359. // STG_E_INVALIDPARAMETER - Error, one or more parameters are invalid, or
  360. // otherwise inconsistent.
  361. // STG_E_READFAULT - Error, The read failed to complete.
  362. // TYPE_E_OUTOFBOUNDS - Debug Error, a read is issued to write past
  363. // the current allocated block.
  364. //
  365. HRESULT GetPropertyItemAndValueUsingIndex(
  366. DWORD dwIndex,
  367. LPPROPERTY_ITEM pItem,
  368. DWORD dwLength,
  369. DWORD *pdwLengthRead,
  370. LPBYTE pbValue
  371. );
  372. private:
  373. // Method to search the property table and return the associated
  374. // property item, if found
  375. HRESULT SearchForProperty(
  376. LPVOID pvPropKey,
  377. LPPROPERTY_ITEM pItem,
  378. DWORD *pdwIndexToItem,
  379. FLAT_ADDRESS *pfaOffsetToItem
  380. );
  381. //
  382. // map a propid into an array index into m_rgWellKnownProps. returns
  383. // -1 if the prop isn't well known
  384. //
  385. int MapCachedProp(DWORD iPropId) {
  386. if (m_cCachedProps &&
  387. iPropId >= m_iCachedPropsBase &&
  388. iPropId < m_iCachedPropsBase + m_cCachedProps)
  389. {
  390. int i = iPropId - m_iCachedPropsBase;
  391. _ASSERT(i < (int) m_cCachedProps);
  392. return i;
  393. } else {
  394. return -1;
  395. }
  396. }
  397. //
  398. // Initialize the property cache
  399. //
  400. void InitializePropCache();
  401. //
  402. // set an item in the property cache. to invalidate an item pass in
  403. // INVALID_FLAT_ADDRESS for fa.
  404. //
  405. void UpdatePropCache(LPPROPERTY_ITEM pItem,
  406. FLAT_ADDRESS fa,
  407. DWORD dwIndex);
  408. DWORD m_dwSignature;
  409. DWORD m_dwTableType;
  410. DWORD m_dwValidInstanceSignature;
  411. // Keep a local instance structure, and track the offset to the
  412. // copy in flat space
  413. PROPERTY_TABLE_INSTANCE *m_pInstanceInfo;
  414. // List of well-known properties, we will use the count to determine
  415. // whether there are any well-known properties
  416. //
  417. // Note that well-known
  418. LPINTERNAL_PROPERTY_ITEM m_pInternalProperties;
  419. DWORD m_dwInternalProperties;
  420. // Function pointer to do property comparisons
  421. LPPROPERTY_COMPARE_FUNCTION m_pfnCompare;
  422. // Memory manager to use
  423. CBlockManager *m_pBlockManager;
  424. // this structure is used for each item in the cache.
  425. typedef struct {
  426. // the flat address for this item, or INVALID_FLAT_ADDRESS if its not in the cache
  427. FLAT_ADDRESS fa;
  428. // its index
  429. DWORD dwIndex;
  430. } PROPCACHEITEM;
  431. // array of cached property offsets for the predefined properties.
  432. // if its GLOBAL_PTABLE_INSTANCE_SIGNATURE_VALID
  433. // then this has the prop ids from IMMPID_MP_BEFORE+1 to IMMPID_MP_AFTER
  434. // otherwise this will be NULL
  435. //
  436. // There is no reason to cache recipient property offsets at this
  437. // time since the recipient property table is instantiated, used
  438. // once, then thrown away. we'd spend more time making the cache
  439. // then the linear search in SearchForProperty costs
  440. PROPCACHEITEM *m_rgCachedProps;
  441. DWORD m_iCachedPropsBase;
  442. DWORD m_cCachedProps;
  443. };
  444. #endif