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.

389 lines
9.0 KiB

  1. /******************************************************************************
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * pathtree.c
  7. *
  8. * Abstract:
  9. * This file contains the implementation for pathtree.
  10. *
  11. * Revision History:
  12. * Kanwaljit S Marok ( kmarok ) 05/17/99
  13. * created
  14. *
  15. *****************************************************************************/
  16. #include "precomp.h"
  17. #include "pathtree.h"
  18. #include "hashlist.h"
  19. #ifndef RING3
  20. //
  21. // linker commands
  22. //
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text( PAGE, ConvertToParsedPath )
  25. #pragma alloc_text( PAGE, MatchPrefix )
  26. #endif // ALLOC_PRAGMA
  27. #endif
  28. static WCHAR g_bWildCardNode[2] = { 4, L'*' };
  29. //
  30. // Converts a Wide Char String to Parsed Path
  31. //
  32. // This routine expects the path to be in the format:
  33. // \[full path]
  34. // Note: There should be no trailing '\' on directory names.
  35. //
  36. BOOL
  37. ConvertToParsedPath(
  38. LPWSTR lpszPath,
  39. WORD nPathLen,
  40. PBYTE pPathBuf,
  41. WORD nBufSize
  42. )
  43. {
  44. BOOL fRet = FALSE;
  45. WORD nLen = 0;
  46. WORD nChars = 0;
  47. WORD nPrefix = 0;
  48. WCHAR *pWStr = NULL;
  49. WCHAR *pWBuf = NULL;
  50. WCHAR *peLength = NULL;
  51. BYTE *pElem = NULL;
  52. if(NULL == lpszPath)
  53. {
  54. #ifndef RING3
  55. SrTrace( LOOKUP, ("lpszPath is null\n")) ;
  56. #endif
  57. goto done;
  58. }
  59. if(NULL == pPathBuf)
  60. {
  61. #ifndef RING3
  62. SrTrace( LOOKUP, ("pPathBuf is null\n")) ;
  63. #endif
  64. goto done;
  65. }
  66. nLen = nPathLen;
  67. pWStr = lpszPath;
  68. if( nLen && nBufSize < CALC_PPATH_SIZE(nLen) )
  69. {
  70. #ifndef RING3
  71. SrTrace( LOOKUP, ("Passed in buffer is too small\n")) ;
  72. #endif
  73. goto done;
  74. }
  75. memset( pPathBuf, 0, nBufSize );
  76. pWStr = lpszPath;
  77. //
  78. // Skip the leading '\'
  79. //
  80. while( *pWStr == L'\\' )
  81. {
  82. pWStr++;
  83. nLen--;
  84. }
  85. //
  86. // Parse and convert to PPATH
  87. //
  88. pWBuf = (PWCHAR)(pPathBuf + 2*sizeof(WCHAR));
  89. nChars = 0;
  90. nPrefix = 2 * sizeof(WCHAR);
  91. peLength = pWBuf;
  92. *peLength = 0;
  93. pWBuf++;
  94. while( nLen )
  95. {
  96. if ( *pWStr == L'\\' )
  97. {
  98. //
  99. // Set pe_length
  100. //
  101. *peLength = (nChars+1)*sizeof(WCHAR);
  102. //
  103. // update PrefixLength
  104. //
  105. nPrefix += (*peLength);
  106. peLength = pWBuf;
  107. nChars = 0;
  108. if (nPrefix >= nBufSize)
  109. {
  110. #ifndef RING3
  111. SrTrace( LOOKUP, ("Passed in buffer is too small - 2\n")) ;
  112. #endif
  113. fRet = FALSE;
  114. goto done;
  115. }
  116. }
  117. else
  118. {
  119. nChars++;
  120. #ifdef RING3
  121. *pWBuf = (WCHAR)CharUpperW((PWCHAR)(*pWStr));
  122. #else
  123. *pWBuf = RtlUpcaseUnicodeChar(*pWStr);
  124. #endif
  125. }
  126. pWStr++;
  127. pWBuf++;
  128. nLen--;
  129. }
  130. //
  131. // When we terminate the above loop, the peLength for the final portion of
  132. // the name will not have been set, but peLength will be pointing to the
  133. // correct location for this sections length. Go ahead and set it now.
  134. //
  135. *peLength = (nChars+1)*sizeof(WCHAR);
  136. //
  137. // Set PrefixLength
  138. //
  139. ( (ParsedPath *)pPathBuf )->pp_prefixLength = nPrefix;
  140. //
  141. // Set TotalLength
  142. //
  143. ( (ParsedPath *)pPathBuf )->pp_totalLength = nPrefix + (*peLength);
  144. //
  145. // Set the last WORD to 0x00
  146. //
  147. *( (PWCHAR)((PBYTE)pPathBuf + nPrefix + (*peLength)) ) = 0;
  148. fRet = TRUE;
  149. done:
  150. return fRet;
  151. }
  152. //
  153. // MatchPrefix : Matches Parsed Path Elements with the given tree.
  154. //
  155. BOOL
  156. MatchPrefix(
  157. BYTE * pTree, // Pointer to the tree blob
  158. INT iFather, // Parent/Starting Node
  159. struct PathElement * ppElem , // PathElement to match
  160. INT * pNode, // Matched node return
  161. INT * pLevel, // Level of matching
  162. INT * pType, // Node type : Incl/Excl/Sfp
  163. BOOL * pfProtected, // Protection flag
  164. BOOL * pfExactMatch // TRUE : if the path matched exactly
  165. )
  166. {
  167. TreeNode * node;
  168. BOOL fRet = FALSE;
  169. if( pLevel )
  170. (*pLevel)++;
  171. if( ppElem->pe_length )
  172. {
  173. INT iNode = 0;
  174. INT iWildCardNode = 0;
  175. iNode = TREE_NODEPTR(pTree, iFather)->m_iSon;
  176. //
  177. // Start by looking at the children of the passed in father
  178. //
  179. while( iNode )
  180. {
  181. node = TREE_NODEPTR(pTree,iNode);
  182. //
  183. // if we encounter a wildcar node, make a note of it
  184. //
  185. if (RtlCompareMemory(g_bWildCardNode,
  186. pTree + node->m_dwData,
  187. ((PathElement *)g_bWildCardNode)->pe_length) ==
  188. ((PathElement *)g_bWildCardNode)->pe_length)
  189. {
  190. iWildCardNode = iNode;
  191. }
  192. //
  193. // compare the node contents
  194. //
  195. if (RtlCompareMemory(ppElem,
  196. pTree + node->m_dwData,
  197. ppElem->pe_length) ==
  198. ppElem->pe_length )
  199. {
  200. break;
  201. }
  202. iNode = node->m_iSibling;
  203. }
  204. //
  205. // Note: Wildcard processing
  206. // incase we don't have a complete node match, use the
  207. // wildcard node if one was found above unless we are at
  208. // last element in the path, in which case we need to
  209. // lookup hashlist first before doing the wildcard match
  210. //
  211. if ( iNode == 0 &&
  212. iWildCardNode != 0 &&
  213. IFSNextElement(ppElem)->pe_length != 0 )
  214. {
  215. iNode = iWildCardNode;
  216. }
  217. //
  218. // Check for lower levels or file children
  219. //
  220. if( iNode != 0 )
  221. {
  222. //
  223. // Since we have found a matching node with non default type
  224. // we need to set the pType to this node type. This is required
  225. // to enforce the parent's type on the children nodes, except
  226. // in the case of SFP type. SFP type is marked on a directory
  227. // to specify there are SFP files in that directory
  228. //
  229. if ( ( NODE_TYPE_UNKNOWN != node->m_dwType ) )
  230. {
  231. *pType = node->m_dwType;
  232. }
  233. //
  234. // if the node is disabled then abort any furthur seach and
  235. // return NODE_TYPE_EXCLUDE from here
  236. //
  237. if ( node->m_dwFlags & TREEFLAGS_DISABLE_SUBTREE )
  238. {
  239. *pType = NODE_TYPE_EXCLUDE;
  240. *pNode = iNode;
  241. fRet = TRUE;
  242. goto Exit;
  243. }
  244. //
  245. // Return from here to preserve the level
  246. //
  247. fRet = MatchPrefix(
  248. pTree,
  249. iNode,
  250. IFSNextElement(ppElem),
  251. pNode,
  252. pLevel,
  253. pType,
  254. pfProtected,
  255. pfExactMatch);
  256. if (fRet)
  257. {
  258. goto Exit;
  259. }
  260. }
  261. else
  262. {
  263. TreeNode * pFatherNode;
  264. //
  265. // if this the last node check in the Hashlist of parent
  266. //
  267. if ( IFSNextElement(ppElem)->pe_length == 0 )
  268. {
  269. pFatherNode = TREE_NODEPTR(pTree,iFather);
  270. if ( pFatherNode->m_dwFileList &&
  271. MatchEntry(
  272. pTree + pFatherNode->m_dwFileList,
  273. (LPWSTR)(ppElem->pe_unichars),
  274. (INT)(ppElem->pe_length - sizeof(USHORT)),
  275. pType)
  276. )
  277. {
  278. //
  279. // Current Father node needs to be returned
  280. //
  281. *pfExactMatch = TRUE;
  282. *pNode = iFather;
  283. fRet = TRUE;
  284. }
  285. else
  286. {
  287. //
  288. // So we have failed to match the hashlist, but
  289. // we have encountered a wildcard node then we
  290. // need to return that node's type as it will
  291. // be the match in this case
  292. //
  293. if ( iWildCardNode != 0 )
  294. {
  295. node = TREE_NODEPTR(pTree,iWildCardNode);
  296. *pNode = iWildCardNode;
  297. *pType = node->m_dwType;
  298. fRet = TRUE;
  299. }
  300. else
  301. {
  302. fRet = FALSE;
  303. }
  304. }
  305. }
  306. }
  307. }
  308. else
  309. {
  310. *pfExactMatch = TRUE;
  311. *pNode = iFather;
  312. fRet = TRUE;
  313. }
  314. (*pLevel)--;
  315. Exit:
  316. return fRet;
  317. }