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.

338 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1995-1996 Microsoft Corporation
  3. Module Name :
  4. svmap.h
  5. Abstract:
  6. Author:
  7. Taylor Weiss ( TaylorW ) 19-Apr-1999
  8. Environment:
  9. Project:
  10. svmap.lib private\inet\iis\isrtl\svmap
  11. Clients:
  12. w3svc.dll private\inet\iis\svcs\w3\server
  13. wam.dll private\inet\iis\svcs\wam\object
  14. Functions Exported:
  15. Revision History:
  16. --*/
  17. #ifndef SVMAP_H
  18. #define SVMAP_H
  19. #include <srvvarid.h>
  20. #define SV_DATA_INVALID_OFFSET (~0)
  21. // Possibly derive from data dictionary
  22. class SV_CACHE_MAP
  23. /*++
  24. Class Description:
  25. Provides a lookup map for server variable names. Maps names onto
  26. IDs. Used to cache server variables for out of process applications.
  27. The interface for this class is similar to that for the HTTP header
  28. map.
  29. Note: This mapping mechanism is specific to the intended use of this
  30. class. May want to replace the implementation with an LKR hash.
  31. The assumption I made was that we would have a lower overhead mapping
  32. mechanism if it was customized for this purpose.
  33. --*/
  34. {
  35. public:
  36. SV_CACHE_MAP()
  37. /*++
  38. Routine Description:
  39. Create a server variable map.
  40. --*/
  41. {
  42. // Init the memory for the cache entries - 0xFF is an empty
  43. // entry
  44. ::FillMemory( m_rgHashTable, sizeof(m_rgHashTable), ~0 );
  45. }
  46. BOOL Initialize( VOID );
  47. BOOL FindOrdinal( IN LPCSTR pszName,
  48. IN INT cchName,
  49. OUT DWORD * pdwOrdinal
  50. ) const;
  51. LPCSTR FindName( IN DWORD dwOrdinal ) const
  52. /*++
  53. Routine Description:
  54. Return the name of the server variable corresponding to dwOrdinal
  55. --*/
  56. {
  57. DBG_ASSERT( dwOrdinal < SVID_COUNT );
  58. return SV_CACHE_MAP::sm_rgNames[dwOrdinal].name;
  59. }
  60. DWORD NumItems( VOID ) const
  61. /*++
  62. Routine Description:
  63. Return the number of items held in the map.
  64. --*/
  65. {
  66. return SV_COUNT;
  67. }
  68. DWORD FindLen( IN DWORD dwOrdinal ) const
  69. /*++
  70. Routine Description:
  71. Return the length of the server variable corresponding to dwOrdinal
  72. --*/
  73. {
  74. DBG_ASSERT( dwOrdinal < SVID_COUNT );
  75. return SV_CACHE_MAP::sm_rgNames[dwOrdinal].len;
  76. }
  77. // The Print functions are unsafe and should only be used when
  78. // debugging and not in regular CHK builds
  79. VOID PrintToBuffer( IN CHAR * pchBuffer,
  80. IN OUT LPDWORD pcch
  81. ) const;
  82. VOID Print( VOID ) const;
  83. private:
  84. enum
  85. {
  86. SV_COUNT = SVID_COUNT,
  87. // Table size based on initial choice of which server variables
  88. // to cache.
  89. TABLE_SIZE = 256,
  90. HASH_MODULUS = 251,
  91. };
  92. // Holds the server variable id.
  93. struct HASH_TABLE_ENTRY
  94. /*++
  95. Class Description:
  96. Since the server variables that are designated as cachable
  97. are preselected, we can use a simple hash entry structure.
  98. Each entry can handle four possible values (slots). Since
  99. the number of server variables is < 128 we use the high bit
  100. to determine if a slot is empty.
  101. The data value is the id of the server variable.
  102. --*/
  103. {
  104. enum
  105. {
  106. MAX_ITEMS = 4,
  107. ITEM_EMPTY_FLAG = 0x80,
  108. };
  109. BOOL InsertValue( DWORD dwValue )
  110. {
  111. DBG_ASSERT( !(dwValue & ITEM_EMPTY_FLAG) );
  112. BOOL fReturn = FALSE;
  113. for( int i = 0; i < MAX_ITEMS; ++i )
  114. {
  115. if( items[i] & ITEM_EMPTY_FLAG )
  116. {
  117. items[i] = (BYTE)dwValue;
  118. fReturn = TRUE;
  119. break;
  120. }
  121. }
  122. return fReturn;
  123. }
  124. BOOL IsSlotEmpty( int item ) const
  125. {
  126. DBG_ASSERT( item >= 0 && item < MAX_ITEMS );
  127. return ( items[item] & ITEM_EMPTY_FLAG );
  128. }
  129. DWORD GetSlotValue( int item ) const
  130. {
  131. DBG_ASSERT( item >= 0 && item < MAX_ITEMS );
  132. return items[item];
  133. }
  134. BYTE items[MAX_ITEMS];
  135. };
  136. // Internal struct used to generate a static table of the
  137. // server variables that we will cache.
  138. struct SV_NAME
  139. {
  140. LPCSTR name;
  141. DWORD len;
  142. };
  143. // String hashing routines based on those used by LKR hash.
  144. // These are pretty generic and should be customizable given
  145. // our limited data set. But I wasn't able to come up with
  146. // anything better.
  147. inline DWORD
  148. HashString( LPCSTR psz ) const
  149. {
  150. DWORD dwHash = 0;
  151. for ( ; *psz; ++psz)
  152. {
  153. dwHash = 37 * dwHash + *psz;
  154. }
  155. return dwHash % HASH_MODULUS;
  156. }
  157. inline DWORD
  158. HashStringWithCount( LPCSTR psz, DWORD *pch ) const
  159. {
  160. DWORD dwHash = 0;
  161. DWORD cch = 0;
  162. for ( ; *psz; ++psz, ++cch)
  163. {
  164. dwHash = 37 * dwHash + *psz;
  165. }
  166. *pch = cch;
  167. return dwHash % HASH_MODULUS;
  168. }
  169. inline BOOL
  170. StringMatches(
  171. IN LPCSTR psz,
  172. IN DWORD cch,
  173. IN DWORD dwOrdinal
  174. ) const
  175. /*++
  176. Routine Description:
  177. Compare the given string to the server variable name corresponding
  178. to dwOrdinal.
  179. --*/
  180. {
  181. return ( cch == FindLen(dwOrdinal) &&
  182. strcmp( psz, FindName(dwOrdinal) ) == 0
  183. );
  184. }
  185. private:
  186. // Member data
  187. // Our hash table. Maps SV_NAMES to ordinals
  188. HASH_TABLE_ENTRY m_rgHashTable[TABLE_SIZE];
  189. // Static data
  190. // Table of the server variables that are cachable
  191. static SV_NAME sm_rgNames[SV_COUNT];
  192. };
  193. class SV_CACHE_LIST
  194. /*++
  195. Class Description:
  196. This actually forms the "cache" of the server variables. We don't
  197. store any data here only the intent to store data.
  198. This class is a list of those server variables that we will retrieve
  199. and then marshal to the remote application.
  200. --*/
  201. {
  202. public:
  203. DWORD Size( VOID )
  204. {
  205. return SVID_COUNT;
  206. }
  207. BOOL GetCacheIt( DWORD item )
  208. {
  209. return m_rgItems[item].fCached;
  210. }
  211. VOID SetCacheIt( DWORD item, BOOL fCacheIt = TRUE )
  212. {
  213. m_rgItems[item].fCached = fCacheIt;
  214. }
  215. // This is kinda hokey
  216. // BUFFER_ITEM and GetBufferItems are use to initialize the
  217. // array that we will marshal to the remote process. There should
  218. // be much better way to do this, but I want to avoid any locking
  219. // issues so keeping around the number of cached items is
  220. // problematic.
  221. struct BUFFER_ITEM
  222. {
  223. DWORD svid;
  224. DWORD dwOffset;
  225. };
  226. VOID
  227. GetBufferItems
  228. (
  229. IN OUT BUFFER_ITEM * pBufferItems,
  230. IN OUT DWORD * pdwBufferItemCount
  231. );
  232. private:
  233. // We are using a single bit to indicate the cached/not-cached
  234. // status. We want to minimize space usage as this may end up
  235. // being cached on a per-url basis.
  236. struct ITEM
  237. {
  238. // Init here or zero the memory in SV_CACHE_LIST ctor
  239. // It looks like when this is built fre that it does a
  240. // pretty good job of optimizing it. But if ZeroMemory is
  241. // linked in locally it might be faster.
  242. ITEM() : fCached(FALSE) {}
  243. BOOL fCached : 1;
  244. };
  245. ITEM m_rgItems[SVID_COUNT];
  246. };
  247. #endif // SVMAP_H