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.

446 lines
12 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. hash.c
  5. Abstract:
  6. BUGBUG: comment.
  7. Author:
  8. vadimb created sometime in 2000
  9. Revision History:
  10. --*/
  11. #include "sdbp.h"
  12. #define DEFAULT_STR_HASH_SIZE 8147
  13. #if defined(KERNEL_MODE) && defined(ALLOC_DATA_PRAGMA)
  14. #pragma data_seg()
  15. #endif // KERNEL_MODE && ALLOC_DATA_PRAGMA
  16. //
  17. // Table used to calculate CRC32. This is used to generate
  18. // the hash index for strings.
  19. //
  20. static DWORD rgdwCrc[] =
  21. {
  22. 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
  23. 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
  24. 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
  25. 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
  26. 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  27. 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
  28. 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
  29. 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
  30. 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
  31. 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  32. 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
  33. 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
  34. 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
  35. 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
  36. 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  37. 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
  38. 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
  39. 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
  40. 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
  41. 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  42. 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
  43. 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
  44. 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
  45. 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
  46. 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  47. 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
  48. 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
  49. 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
  50. 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
  51. 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  52. 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
  53. 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
  54. 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
  55. 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
  56. 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  57. 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
  58. 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
  59. 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
  60. 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
  61. 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  62. 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
  63. 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
  64. 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
  65. 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
  66. 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  67. 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
  68. 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
  69. 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
  70. 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
  71. 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  72. 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
  73. 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
  74. 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
  75. 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
  76. 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  77. 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
  78. 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
  79. 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
  80. 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
  81. 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  82. 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
  83. 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
  84. 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
  85. 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
  86. };
  87. #if defined(KERNEL_MODE) && defined(ALLOC_PRAGMA)
  88. #pragma alloc_text(PAGE, HashCreate)
  89. #pragma alloc_text(PAGE, HashFree)
  90. #pragma alloc_text(PAGE, HashStringRef)
  91. #pragma alloc_text(PAGE, HashString)
  92. #pragma alloc_text(PAGE, HashFindString)
  93. #pragma alloc_text(PAGE, HashFindStringByRef)
  94. #pragma alloc_text(PAGE, HashAddString)
  95. #pragma alloc_text(PAGE, HashAddStringByRef)
  96. #endif // KERNEL_MODE && ALLOC_PRAGMA
  97. PVOID
  98. HashCreate(
  99. void
  100. )
  101. /*++
  102. Return: The hash.
  103. Desc: Creates and initializes the hash.
  104. --*/
  105. {
  106. PSTRHASH pHash;
  107. pHash = (PSTRHASH)SdbAlloc(sizeof(STRHASH));
  108. if (pHash == NULL) {
  109. DBGPRINT((sdlError,
  110. "HashCreate",
  111. "Failed to allocate %d bytes.\n",
  112. sizeof(STRHASH)));
  113. return NULL;
  114. }
  115. pHash->dwHashSize = DEFAULT_STR_HASH_SIZE;
  116. pHash->pTable = (PSTRHASHELEMENT*)SdbAlloc(sizeof(PSTRHASHELEMENT) * DEFAULT_STR_HASH_SIZE);
  117. if (pHash->pTable == NULL) {
  118. DBGPRINT((sdlError,
  119. "HashCreate",
  120. "Failed to allocate %d bytes for the table.\n",
  121. sizeof(PSTRHASHELEMENT) * DEFAULT_STR_HASH_SIZE));
  122. SdbFree(pHash);
  123. return NULL;
  124. }
  125. return pHash;
  126. }
  127. void
  128. HashFree(
  129. IN PVOID pStringHash // the hash to be freed.
  130. )
  131. /*++
  132. Return: void
  133. Desc: BUGBUG: comments ?
  134. --*/
  135. {
  136. PSTRHASHELEMENT phe, pheNext;
  137. PSTRHASH pHash = (PSTRHASH)pStringHash;
  138. int i;
  139. if (pHash == NULL) {
  140. DBGPRINT((sdlError, "HashFree", "Invalid argument.\n"));
  141. return;
  142. }
  143. if (pHash->pTable != NULL) {
  144. for (i = 0; i < (int)pHash->dwHashSize; i++) {
  145. for (phe = pHash->pTable[i]; phe != NULL; ) {
  146. pheNext = phe->pNext;
  147. SdbFree(phe);
  148. phe = pheNext;
  149. }
  150. }
  151. SdbFree(pHash->pTable);
  152. }
  153. SdbFree(pHash);
  154. }
  155. DWORD
  156. HashStringRef(
  157. IN PSTRHASH pHash, // pointer to the string hash structure.
  158. IN STRINGREF srString // string-reference (a dword) that is used to
  159. // identify the string in an sdb file.
  160. )
  161. /*++
  162. Return: Hash index for the string
  163. Desc: BUGBUG: comments ?
  164. --*/
  165. {
  166. //
  167. // really simple for now
  168. //
  169. return (srString % pHash->dwHashSize);
  170. }
  171. DWORD
  172. HashString(
  173. IN PSTRHASH pHash, // pointer to the string hash structure.
  174. IN LPCTSTR szString // the string to be hashed
  175. )
  176. /*++
  177. Return: The string reference in the hash.
  178. Desc: BUGBUG: comments ?
  179. --*/
  180. {
  181. DWORD dwHash = 0;
  182. while (*szString) {
  183. dwHash += (dwHash << 5) + dwHash + *szString++;
  184. }
  185. dwHash %= pHash->dwHashSize;
  186. return dwHash;
  187. }
  188. STRINGREF
  189. HashFindString(
  190. IN PSTRHASH pHash, // pointer to the string hash structure.
  191. IN LPCTSTR szString // string to search for.
  192. )
  193. /*++
  194. Return: The string ref if the string is found in the hash, 0 otherwise.
  195. Desc: Searches for the specified string in the hash table.
  196. --*/
  197. {
  198. DWORD dwHash;
  199. PSTRHASHELEMENT phe;
  200. int iCmp;
  201. STRINGREF srReturn = STRINGREF_NULL;
  202. dwHash = HashString(pHash, szString);
  203. phe = pHash->pTable[dwHash];
  204. for (; phe != NULL; phe = phe->pNext) {
  205. iCmp = _tcsicmp(szString, phe->szStr);
  206. //
  207. // The list of items related to the entry dwHash in the table
  208. // is sorted in ascending order by the "add" routine
  209. // therefore we compare until we find an item that is greater or equal
  210. // to the search string.
  211. //
  212. if (iCmp <= 0) {
  213. //
  214. // Found or failure, stop the search.
  215. //
  216. srReturn = (iCmp == 0 ? phe->srStr : STRINGREF_NULL);
  217. break;
  218. }
  219. }
  220. return srReturn;
  221. }
  222. LPTSTR
  223. HashFindStringByRef(
  224. IN PSTRHASH pHash, // pointer to the string hash structure.
  225. IN STRINGREF srString // stringref of the string to search for.
  226. )
  227. /*++
  228. Return: The pointer to the found string or NULL.
  229. Desc: Searches for the specified string in the hash table.
  230. --*/
  231. {
  232. DWORD dwHash;
  233. PSTRHASHELEMENT phe;
  234. LPTSTR pStr = NULL;
  235. dwHash = HashStringRef(pHash, srString);
  236. phe = pHash->pTable[dwHash];
  237. for (; phe != NULL; phe = phe->pNext) {
  238. if (phe->srStr >= srString) {
  239. pStr = ((phe->srStr == srString) ? phe->szStr : NULL);
  240. break;
  241. }
  242. }
  243. return pStr;
  244. }
  245. BOOL
  246. HashAddString(
  247. IN PSTRHASH pHash, // pointer to the string hash structure.
  248. IN LPCTSTR szString, // the string to be added
  249. IN STRINGREF srString // the string ref for the string to be added
  250. )
  251. /*++
  252. Return: TRUE on success, FALSE otherwise.
  253. Desc: BUGBUG: comments ?
  254. --*/
  255. {
  256. DWORD dwHash;
  257. PSTRHASHELEMENT phe;
  258. PSTRHASHELEMENT pheLast;
  259. PSTRHASHELEMENT pheNew;
  260. DWORD dwStrSize;
  261. dwHash = HashString(pHash, szString);
  262. phe = pHash->pTable[dwHash];
  263. dwStrSize = (DWORD)(_tcslen(szString) + 1) * sizeof(TCHAR);
  264. //
  265. // Now check where to insert the string.
  266. //
  267. for (pheLast = NULL;
  268. phe != NULL && _tcsicmp(szString, phe->szStr) > 0;
  269. pheLast = phe, phe = phe->pNext) {
  270. ;
  271. }
  272. //
  273. // Insert it.
  274. //
  275. pheNew = (PSTRHASHELEMENT)SdbAlloc(sizeof(STRHASHELEMENT) + dwStrSize);
  276. if (pheNew == NULL) {
  277. DBGPRINT((sdlError,
  278. "HashAddString",
  279. "Failed to allocate %d bytes.\n",
  280. sizeof(STRHASHELEMENT) + dwStrSize));
  281. return FALSE;
  282. }
  283. pheNew->szStr = (LPTSTR)(pheNew + 1);
  284. pheNew->srStr = srString;
  285. RtlMoveMemory(pheNew->szStr, szString, dwStrSize);
  286. pheNew->pNext = phe;
  287. if (pheLast == NULL) {
  288. pHash->pTable[dwHash] = pheNew;
  289. } else {
  290. pheLast->pNext = pheNew;
  291. }
  292. return TRUE;
  293. }
  294. LPTSTR
  295. HashAddStringByRef(
  296. IN PSTRHASH pHash,
  297. IN LPCTSTR szString,
  298. IN STRINGREF srString
  299. )
  300. /*++
  301. Return: The pointer to the string added in the hash table.
  302. Desc: BUGBUG: comments ?
  303. --*/
  304. {
  305. DWORD dwHash;
  306. PSTRHASHELEMENT phe;
  307. PSTRHASHELEMENT pheLast;
  308. PSTRHASHELEMENT pheNew;
  309. DWORD dwStrSize;
  310. LPTSTR lpszCachedString = NULL;
  311. dwHash = HashStringRef(pHash, srString);
  312. phe = pHash->pTable[dwHash];
  313. dwStrSize = (DWORD)(_tcslen(szString) + 1) * sizeof(TCHAR);
  314. //
  315. // Check where to insert the string.
  316. //
  317. for (pheLast = NULL;
  318. phe != NULL && srString > phe->srStr;
  319. pheLast = phe, phe = phe->pNext);
  320. //
  321. // Insert it.
  322. //
  323. pheNew = (PSTRHASHELEMENT)SdbAlloc(sizeof(STRHASHELEMENT) + dwStrSize);
  324. if (pheNew == NULL) {
  325. DBGPRINT((sdlError,
  326. "HashAddStringByRef",
  327. "Failed to allocate %d bytes.\n",
  328. sizeof(STRHASHELEMENT) + dwStrSize));
  329. return NULL;
  330. }
  331. pheNew->szStr = (LPTSTR)(pheNew + 1);
  332. pheNew->srStr = srString;
  333. RtlMoveMemory(pheNew->szStr, szString, dwStrSize);
  334. pheNew->pNext = phe;
  335. if (pheLast == NULL) {
  336. pHash->pTable[dwHash] = pheNew;
  337. } else {
  338. pheLast->pNext = pheNew;
  339. }
  340. lpszCachedString = pheNew->szStr;
  341. return lpszCachedString;
  342. }