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.

450 lines
9.9 KiB

  1. //++
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // pathtree.cpp
  7. //
  8. // Abstract:
  9. // Used to create a pathtree blob. closeley tied into the CFLDatBuilder
  10. // class.
  11. //
  12. // Revision History:
  13. // Eugene Mesgar (eugenem) 6/16/99
  14. // created
  15. // Kanwaljit Marok (kmarok) 6/07/2000
  16. // Converted to unicode and ported to NT
  17. //--
  18. #include "flstructs.h"
  19. #include "flbuilder.h"
  20. #include "flpathtree.h"
  21. #include "flhashlist.h"
  22. #include "commonlibh.h"
  23. #ifdef THIS_FILE
  24. #undef THIS_FILE
  25. #endif
  26. static char __szTraceSourceFile[] = __FILE__;
  27. #define THIS_FILE __szTraceSourceFile
  28. #define TRACE_FILEID 0
  29. #define FILEID 0
  30. CFLPathTree::CFLPathTree(HANDLE hHeap)
  31. {
  32. m_pBasePointer = NULL;
  33. m_lNumElements = 0;
  34. m_dwSize = 0;
  35. m_pTreeHeader = NULL;
  36. m_pNodeIndex = NULL;
  37. m_pBlobHeader = NULL;
  38. m_hHeapToUse = hHeap;
  39. }
  40. CFLPathTree::CFLPathTree()
  41. {
  42. TraceFunctEnter("CFLPathTree::CFLPathTree");
  43. m_hHeapToUse = GetProcessHeap();
  44. m_pBasePointer = NULL;
  45. m_lNumElements = 0;
  46. m_dwSize = 0;
  47. m_pTreeHeader = NULL;
  48. m_pNodeIndex = NULL;
  49. m_pBlobHeader = NULL;
  50. TraceFunctLeave();
  51. }
  52. CFLPathTree::~CFLPathTree()
  53. {
  54. TraceFunctEnter("CFLPathTree::~CFLPathTree");
  55. CleanUpMemory();
  56. TraceFunctLeave();
  57. }
  58. void CFLPathTree::CleanUpMemory()
  59. {
  60. TraceFunctEnter("CFLPathTree::CleanUpMemory");
  61. if( m_pBasePointer )
  62. {
  63. if( HeapFree( m_hHeapToUse, 0, m_pBasePointer) == 0)
  64. {
  65. printf("%d\n", GetLastError() );
  66. }
  67. m_pBasePointer = NULL;
  68. }
  69. m_lNumElements = 0;
  70. m_dwSize = 0;
  71. m_pTreeHeader = NULL;
  72. m_pNodeIndex = NULL;
  73. m_pBlobHeader = NULL;
  74. TraceFunctLeave();
  75. }
  76. BOOL
  77. CFLPathTree::BuildTree(
  78. LPFLTREE_NODE pTree,
  79. LONG lNumNodes,
  80. DWORD dwDefaultType,
  81. LONG lNumFileList,
  82. LONG lNumFiles,
  83. LONG lNumBuckets,
  84. LONG lNumChars)
  85. {
  86. DWORD dwBlobSize;
  87. TraceFunctEnter("CFLPathTree::BuildTree");
  88. //
  89. // size of the header, and all the entries;
  90. //
  91. dwBlobSize = sizeof( TreeHeader ) + ( sizeof( TreeNode ) * lNumNodes );
  92. //
  93. // size of all filelist hashes
  94. //
  95. dwBlobSize += ( sizeof( ListHeader ) * lNumFileList ) + ( sizeof( ListEntry ) * lNumFiles );
  96. //
  97. // each file list tacks on one extra used file. so we need to account this.
  98. //
  99. dwBlobSize += sizeof( ListEntry ) * lNumFileList;
  100. //
  101. // tack on the space we need for all our hash array buckets
  102. //
  103. dwBlobSize += (lNumBuckets * sizeof(DWORD));
  104. //
  105. // data file pathlengths. (numtreenodes)*ushort (this is for
  106. // the pe->length in the pathtree element) + lNumFiles*ushort
  107. // (pe->length in the pathtree elemtn) + numchars*ushort
  108. //
  109. dwBlobSize += sizeof(USHORT) * ( lNumFiles + lNumChars + lNumNodes );
  110. CleanUpMemory();
  111. if( (m_pBasePointer = HeapAlloc( m_hHeapToUse, 0, dwBlobSize ) ) == NULL )
  112. {
  113. DebugTrace(FILEID, "Error allocating memory.",0);
  114. goto cleanup;
  115. }
  116. memset( m_pBasePointer, 0, dwBlobSize );
  117. m_pBlobHeader = (BlobHeader *) m_pBasePointer;
  118. m_pTreeHeader = (TreeHeader *) m_pBasePointer;
  119. m_pNodeIndex = (TreeNode *) ((BYTE *) m_pBasePointer + sizeof( TreeHeader ) );
  120. m_pBlobHeader->m_dwBlbType = BLOB_TYPE_PATHTREE;
  121. m_pBlobHeader->m_dwVersion = BLOB_VERSION_NUM;
  122. m_pBlobHeader->m_dwMagicNum= BLOB_MAGIC_NUM ;
  123. m_pBlobHeader->m_dwEntries = lNumNodes;
  124. m_pBlobHeader->m_dwMaxSize = dwBlobSize;
  125. m_pTreeHeader->m_dwDataOff = sizeof(TreeHeader) + (sizeof(TreeNode) * lNumNodes );
  126. m_pTreeHeader->m_dwMaxNodes = lNumNodes;
  127. m_pTreeHeader->m_dwDataSize = dwBlobSize - sizeof(TreeHeader) - ( sizeof(TreeNode) * lNumNodes );
  128. m_pTreeHeader->m_dwDefault = dwDefaultType;
  129. m_dwSize = dwBlobSize;
  130. m_lNumElements = lNumNodes;
  131. if( RecBuildTree( pTree, 0 ) == FALSE )
  132. {
  133. DebugTrace(FILEID, "Error building path tree blob", 0);
  134. goto cleanup;
  135. }
  136. TraceFunctLeave();
  137. return(TRUE);
  138. cleanup:
  139. TraceFunctLeave();
  140. return(FALSE);
  141. }
  142. BOOL CFLPathTree::CopyPathElem (WCHAR * pszPath, TreeNode *pNode)
  143. {
  144. TraceFunctEnter("CFLPathTree::CopyPathElem");
  145. LONG lPeSize;
  146. BYTE abBuf[1024];
  147. if( (lPeSize = CreatePathElem( pszPath, abBuf )) == 0 )
  148. {
  149. DebugTrace(FILEID,"Error creating path element",0);
  150. goto cleanup;
  151. }
  152. if( (ULONG) lPeSize > ( m_dwSize - m_pTreeHeader->m_dwDataOff ) )
  153. {
  154. DebugTrace(FILEID, "Not enougn memory to allocate path element.",0);
  155. goto cleanup;
  156. }
  157. pNode->m_dwData = m_pTreeHeader->m_dwDataOff;
  158. m_pTreeHeader->m_dwDataOff += lPeSize;
  159. memcpy( (BYTE *) m_pBasePointer + pNode->m_dwData , abBuf, lPeSize );
  160. TraceFunctLeave();
  161. return TRUE;
  162. cleanup:
  163. TraceFunctLeave();
  164. return FALSE;
  165. }
  166. BOOL
  167. CFLPathTree::RecBuildTree(
  168. LPFLTREE_NODE pTree,
  169. LONG lLevel )
  170. {
  171. TreeNode *pNode;
  172. TraceFunctEnter("CFLPathTree::RecBuildTree");
  173. if( ! m_pBasePointer )
  174. {
  175. TraceFunctLeave();
  176. return(FALSE);
  177. }
  178. //
  179. // we've ended our recursion
  180. //
  181. if( !pTree )
  182. {
  183. TraceFunctLeave();
  184. return( TRUE );
  185. }
  186. //
  187. // We enumerated all the nodes when we created them
  188. // initially so makeing this tree is cake.
  189. //
  190. pNode = m_pNodeIndex + pTree->lNodeNumber;
  191. if( pTree->pParent )
  192. {
  193. pNode->m_iFather = pTree->pParent->lNodeNumber;
  194. }
  195. if( pTree->pSibling )
  196. {
  197. pNode->m_iSibling = pTree->pSibling->lNodeNumber;
  198. }
  199. if( pTree->pChild )
  200. {
  201. pNode->m_iSon = pTree->pChild->lNodeNumber;
  202. }
  203. //
  204. // set the node type.
  205. //
  206. if( pTree->chType == _TEXT('i') || pTree->chType == _TEXT('I') )
  207. pNode->m_dwType = NODE_TYPE_INCLUDE;
  208. else if( pTree->chType == _TEXT('e') || pTree->chType == _TEXT('E') )
  209. pNode->m_dwType = NODE_TYPE_EXCLUDE;
  210. else
  211. pNode->m_dwType = NODE_TYPE_UNKNOWN;
  212. if (CopyPathElem (pTree->szPath, pNode) == FALSE)
  213. goto cleanup;
  214. if (pTree->fDisableDirectory)
  215. {
  216. pNode->m_dwFlags |= TREEFLAGS_DISABLE_SUBTREE;
  217. }
  218. else
  219. {
  220. pNode->m_dwFlags &= ~TREEFLAGS_DISABLE_SUBTREE;
  221. }
  222. //
  223. // now take care of the file list.
  224. //
  225. if( pTree->pFileList )
  226. {
  227. LPFL_FILELIST pList = pTree->pFileList;
  228. CFLHashList hashList( m_hHeapToUse );
  229. if( hashList.Init( pTree->lNumFilesHashed, pTree->lFileDataSize) == FALSE )
  230. {
  231. DebugTrace(FILEID, "Error initializeing a hashlist blob",0);
  232. goto cleanup;
  233. }
  234. //
  235. // build the list
  236. //
  237. while( pList )
  238. {
  239. if( hashList.AddFile( pList->szFileName, pList->chType ) == FALSE )
  240. {
  241. hashList.CleanUpMemory();
  242. goto cleanup;
  243. }
  244. pList = pList->pNext;
  245. }
  246. //
  247. // do we have enough memory?
  248. //
  249. if( (ULONG) hashList.GetSize() > ( m_dwSize - m_pTreeHeader->m_dwDataOff ) )
  250. {
  251. hashList.CleanUpMemory();
  252. DebugTrace(FILEID, "Hash blob too big to fit in memory.",0);
  253. goto cleanup;
  254. }
  255. //
  256. // set the node's data pointer
  257. //
  258. pNode->m_dwFileList = m_pTreeHeader->m_dwDataOff;
  259. //
  260. // move forward the global data pointer offset
  261. //
  262. m_pTreeHeader->m_dwDataOff += hashList.GetSize();
  263. //
  264. // copy the memory over
  265. //
  266. memcpy( (BYTE *) m_pBasePointer + pNode->m_dwFileList, hashList.GetBasePointer(), hashList.GetSize() );
  267. hashList.CleanUpMemory();
  268. }
  269. if( pTree->pChild )
  270. {
  271. if( RecBuildTree( pTree->pChild, lLevel + 1 ) == FALSE )
  272. {
  273. goto cleanup;
  274. }
  275. }
  276. if( pTree->pSibling )
  277. {
  278. if( RecBuildTree( pTree->pSibling, lLevel ) == FALSE )
  279. {
  280. goto cleanup;
  281. }
  282. }
  283. TraceFunctLeave();
  284. return( TRUE );
  285. cleanup:
  286. TraceFunctLeave();
  287. return( FALSE );
  288. }
  289. DWORD CFLPathTree::GetSize()
  290. {
  291. return( m_dwSize );
  292. }
  293. LPVOID CFLPathTree::GetBasePointer()
  294. {
  295. return( m_pBasePointer );
  296. }
  297. DWORD
  298. CFLPathTree::CreatePathElem(
  299. LPTSTR pszData,
  300. BYTE *pbLargeBuffer )
  301. {
  302. int cbLen, i;
  303. DWORD dwReturn=0;
  304. PathElement *pElem = (PathElement *)pbLargeBuffer;
  305. TraceFunctEnter("CFLHashList::CreatePathElem");
  306. if( NULL == pszData )
  307. {
  308. ErrorTrace(FILEID, "NULL pszData sent to CreatePathElem",0);
  309. goto cleanup;
  310. }
  311. cbLen = _tcslen(pszData);
  312. //
  313. // Add on to cbLen for LENGH char in prefixed strings.
  314. //
  315. pElem->pe_length = (USHORT) (cbLen+1)*sizeof(USHORT);
  316. //
  317. // if we're not in unicode, lets make sure the high bits are clean
  318. // Add sizeof(USHORT) to pElem offset to move past length char.
  319. //
  320. memset( pElem + sizeof(USHORT), 0, cbLen*2);
  321. #ifndef UNICODE
  322. if( !MultiByteToWideChar(
  323. GetCurrentCodePage(),
  324. 0,
  325. pszData,
  326. -1,
  327. pElem->pe_unichars, // move right 2 bytes past the length prefix
  328. MAX_BUFFER) )
  329. {
  330. DWORD dwError;
  331. dwError = GetLastError();
  332. ErrorTrace(FILEID, "Error converting to Wide char ec-%d",dwError);
  333. goto cleanup;
  334. }
  335. #else
  336. RtlCopyMemory( pElem->pe_unichars,
  337. pszData,
  338. cbLen*sizeof(WCHAR) );
  339. #endif
  340. dwReturn = pElem->pe_length;
  341. cleanup:
  342. TraceFunctLeave();
  343. return dwReturn;
  344. }