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.

403 lines
8.5 KiB

  1. //++
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // hashlist.cpp
  7. //
  8. // Abstract:
  9. // Used for creating hash list blobs.
  10. //
  11. // Revision History:
  12. // Eugene Mesgar (eugenem) 6/16/99
  13. // created
  14. // Kanwaljit Marok (kmaork ) 6/07/99
  15. // modified and ported to NT
  16. //
  17. //--
  18. #include "flstructs.h"
  19. #include "flhashlist.h"
  20. #include "commonlibh.h"
  21. #ifdef THIS_FILE
  22. #undef THIS_FILE
  23. #endif
  24. static char __szTraceSourceFile[] = __FILE__;
  25. #define THIS_FILE __szTraceSourceFile
  26. #define TRACE_FILEID 0
  27. #define FILEID 0
  28. #define SAFEDELETE(p) if (p) { HeapFree( m_hHeapToUse, 0, p); p = NULL;} else ;
  29. CFLHashList::CFLHashList()
  30. {
  31. m_pBasePointer = NULL;
  32. m_pListHeader = NULL;
  33. m_paHashArray = NULL;
  34. m_pBlobHeader = NULL;
  35. m_lNumElements = m_ilOpenEntry = 0;
  36. m_dwSize = 0;
  37. m_ilOpenEntry = 0;
  38. m_hHeapToUse = GetProcessHeap();
  39. }
  40. CFLHashList::CFLHashList(HANDLE hHeap )
  41. {
  42. m_pBasePointer = NULL;
  43. m_pListHeader = NULL;
  44. m_paHashArray = NULL;
  45. m_pBlobHeader = NULL;
  46. m_lNumElements = m_ilOpenEntry = 0;
  47. m_dwSize = 0;
  48. m_ilOpenEntry = 0;
  49. m_hHeapToUse = hHeap;
  50. }
  51. CFLHashList::~CFLHashList()
  52. {
  53. CleanUpMemory();
  54. }
  55. BOOL CFLHashList::CleanUpMemory()
  56. {
  57. if( m_pBasePointer )
  58. {
  59. HeapFree( m_hHeapToUse, 0, m_pBasePointer );
  60. m_pBasePointer = NULL;
  61. }
  62. m_dwSize = 0;
  63. m_ilOpenEntry = 0;
  64. m_lNumElements = 0;
  65. m_pBasePointer = NULL;
  66. m_pBlobHeader = NULL;
  67. m_paHashArray = NULL;
  68. m_pListHeader = NULL;
  69. return(TRUE);
  70. }
  71. //
  72. // Init function.. allocates memory, sets up base structures
  73. //
  74. BOOL
  75. CFLHashList::Init(
  76. LONG lNumNodes,
  77. DWORD dwNumChars)
  78. {
  79. DWORD dwBlobSize;
  80. DWORD dwNumBuckets=0;
  81. TraceFunctEnter("CFLHashList::Init");
  82. //
  83. // Get the number of buckets we need
  84. //
  85. dwNumBuckets = GetNextHighestPrime( lNumNodes );
  86. //
  87. // We add 1 to NumNodes since the vxddat ignores node index since
  88. // in the hashtable index 0 is null.
  89. //
  90. lNumNodes++;
  91. //
  92. // header
  93. // size for dynmaic hash buckets
  94. // list entries physical data
  95. //
  96. dwBlobSize = sizeof( ListHeader ) +
  97. ( sizeof(DWORD) * dwNumBuckets ) +
  98. ( sizeof(ListEntry) * (lNumNodes) ) +
  99. ( dwNumChars*sizeof(WCHAR)) +
  100. ( sizeof(WCHAR)*(lNumNodes-1)) ;
  101. if( m_pBasePointer )
  102. {
  103. if( CleanUpMemory() == FALSE )
  104. {
  105. DebugTrace(FILEID, "Error cleaning up memory.",0);
  106. goto cleanup;
  107. }
  108. }
  109. if( (m_pBasePointer = HeapAlloc( m_hHeapToUse, 0, dwBlobSize ) ) == NULL )
  110. {
  111. DebugTrace(FILEID, "Error allocating memory.", 0);
  112. goto cleanup;
  113. }
  114. memset(m_pBasePointer, 0, dwBlobSize );
  115. m_pBlobHeader = (BlobHeader *) m_pBasePointer;
  116. m_pListHeader = (ListHeader *) m_pBasePointer;
  117. m_pNodeIndex = (ListEntry *) ( (BYTE *) m_pBasePointer +
  118. sizeof( ListHeader ) +
  119. ( sizeof(DWORD) * dwNumBuckets ) );
  120. m_paHashArray = (DWORD *) ( (BYTE *) m_pBasePointer + sizeof( ListHeader ));
  121. m_pBlobHeader->m_dwBlbType = BLOB_TYPE_HASHLIST;
  122. m_pBlobHeader->m_dwVersion = BLOB_VERSION_NUM;
  123. m_pBlobHeader->m_dwMagicNum= BLOB_MAGIC_NUM ;
  124. m_pBlobHeader->m_dwEntries = lNumNodes - 1; // actual entries is one less
  125. m_pBlobHeader->m_dwMaxSize = dwBlobSize;
  126. m_pListHeader->m_dwDataOff = sizeof(ListHeader) +
  127. ( sizeof(DWORD) * dwNumBuckets ) +
  128. ( sizeof(ListEntry) * lNumNodes );
  129. m_pListHeader->m_iHashBuckets = dwNumBuckets;
  130. m_dwSize = dwBlobSize;
  131. m_ilOpenEntry = 1;
  132. m_lNumElements = lNumNodes;
  133. TraceFunctLeave();
  134. return(TRUE);
  135. cleanup:
  136. SAFEDELETE( m_pBasePointer );
  137. TraceFunctLeave();
  138. return( FALSE );
  139. }
  140. //
  141. // is prime? these functions can be optimized i bet
  142. //
  143. BOOL
  144. CFLHashList::IsPrime(
  145. DWORD dwNumber)
  146. {
  147. DWORD cdw;
  148. //
  149. // prevent divide by 0 problems
  150. //
  151. if( dwNumber == 0 )
  152. {
  153. return FALSE;
  154. }
  155. if( dwNumber == 1 )
  156. {
  157. return TRUE;
  158. }
  159. for(cdw = 2;cdw < dwNumber;cdw++)
  160. {
  161. if( (dwNumber % cdw ) == 0 )
  162. {
  163. return FALSE;
  164. }
  165. }
  166. return TRUE;
  167. }
  168. //
  169. // get the next prime number
  170. //
  171. DWORD CFLHashList::GetNextHighestPrime( DWORD dwNumber )
  172. {
  173. LONG clLoop;
  174. if( dwNumber >= LARGEST_HASH_SIZE )
  175. {
  176. return( LARGEST_HASH_SIZE );
  177. }
  178. for( clLoop = dwNumber; clLoop < LARGEST_HASH_SIZE;clLoop++)
  179. {
  180. if( IsPrime( clLoop ) )
  181. {
  182. return( clLoop );
  183. }
  184. }
  185. // nothing found, return large hash size.
  186. return( LARGEST_HASH_SIZE );
  187. }
  188. //
  189. // Adds a file to the hashed list
  190. //
  191. BOOL CFLHashList::AddFile(LPTSTR szFile, TCHAR chType)
  192. {
  193. BYTE abBuf[1024];
  194. LONG lPeSize, lHashIndex, lNodeNum;
  195. ListEntry *pEntry;
  196. TraceFunctEnter("CFLHashList::AddFile");
  197. if( (lPeSize = CreatePathElem( szFile, abBuf )) == 0 )
  198. {
  199. DebugTrace(FILEID,"Error creating PathElement",0);
  200. goto cleanup;
  201. }
  202. if( m_ilOpenEntry == m_lNumElements )
  203. {
  204. DebugTrace(FILEID,"Too many elements in HashList.",0);
  205. goto cleanup;
  206. }
  207. if( (ULONG) lPeSize > ( m_dwSize - m_pListHeader->m_dwDataOff ) )
  208. {
  209. DebugTrace(FILEID,"Insuffienct space left in data section",0);
  210. goto cleanup;
  211. }
  212. //
  213. // get a new node
  214. //
  215. lNodeNum = m_ilOpenEntry++;
  216. //
  217. // m_pNodeIndex is the base pointer to all file nodes
  218. //
  219. pEntry = m_pNodeIndex + lNodeNum;
  220. pEntry->m_dwDataLen = lPeSize;
  221. pEntry->m_dwData = m_pListHeader->m_dwDataOff;
  222. //
  223. // move global data offset.
  224. //
  225. m_pListHeader->m_dwDataOff += lPeSize;
  226. //
  227. // copy the entry into our data space
  228. //
  229. memcpy( (BYTE *) m_pBasePointer + pEntry->m_dwData, abBuf, lPeSize );
  230. //
  231. // hash the name and add it to the linked lsit
  232. //
  233. lHashIndex = HASH( (BYTE *) m_pListHeader, (PathElement *) abBuf );
  234. pEntry->m_iNext = m_paHashArray[lHashIndex];
  235. m_paHashArray[lHashIndex] = lNodeNum;
  236. //
  237. // set the type.
  238. //
  239. if( chType == _TEXT('i') || chType == _TEXT('I') )
  240. pEntry->m_dwType = NODE_TYPE_INCLUDE;
  241. else if( chType == _TEXT('e') || chType == _TEXT('E') )
  242. pEntry->m_dwType = NODE_TYPE_EXCLUDE;
  243. else
  244. pEntry->m_dwType = NODE_TYPE_UNKNOWN;
  245. TraceFunctLeave();
  246. return(TRUE);
  247. cleanup:
  248. TraceFunctLeave();
  249. return(FALSE);
  250. }
  251. //
  252. // Helper to convert path elements
  253. //
  254. DWORD CFLHashList::CreatePathElem( LPTSTR pszData, BYTE *pbLargeBuffer )
  255. {
  256. int cbLen, i;
  257. DWORD dwReturn=0;
  258. PathElement *pElem = (PathElement *)pbLargeBuffer;
  259. TraceFunctEnter("CFLHashList::CreatePathElem");
  260. if( NULL == pszData )
  261. {
  262. ErrorTrace(FILEID, "NULL pszData sent to CreatePathElem",0);
  263. goto cleanup;
  264. }
  265. cbLen = _tcslen(pszData);
  266. //
  267. // Add on to cbLen for LENGH char in prefixed strings.
  268. //
  269. pElem->pe_length = (USHORT) (cbLen+1)*sizeof(USHORT);
  270. //
  271. // if we're not in unicode, lets make sure the high bits are clean
  272. // Add sizeof(USHORT) to pElem offset to move past length char.
  273. //
  274. memset( pElem + sizeof(USHORT), 0, cbLen*2);
  275. #ifndef UNICODE
  276. if( !MultiByteToWideChar(
  277. GetCurrentCodePage(),
  278. 0,
  279. pszData,
  280. -1,
  281. pElem->pe_unichars, //move right 2 bytes past the length prefix
  282. MAX_BUFFER) )
  283. {
  284. DWORD dwError;
  285. dwError = GetLastError();
  286. ErrorTrace(FILEID, "Error converting to Wide char ec-%d",dwError);
  287. goto cleanup;
  288. }
  289. #else
  290. RtlCopyMemory( pElem->pe_unichars,
  291. pszData,
  292. cbLen*sizeof(WCHAR) );
  293. #endif
  294. dwReturn = pElem->pe_length;
  295. cleanup:
  296. TraceFunctLeave();
  297. return dwReturn;
  298. }
  299. DWORD CFLHashList::GetSize()
  300. {
  301. return( m_dwSize );
  302. }
  303. LPVOID CFLHashList::GetBasePointer()
  304. {
  305. return( m_pBasePointer );
  306. }