/****************************************************************************** * * Copyright (c) 1999 Microsoft Corporation * * Module Name: * pathtree.c * * Abstract: * This file contains the implementation for pathtree. * * Revision History: * Kanwaljit S Marok ( kmarok ) 05/17/99 * created * *****************************************************************************/ #include "precomp.h" #include "pathtree.h" #include "hashlist.h" #ifndef RING3 // // linker commands // #ifdef ALLOC_PRAGMA #pragma alloc_text( PAGE, ConvertToParsedPath ) #pragma alloc_text( PAGE, MatchPrefix ) #endif // ALLOC_PRAGMA #endif static WCHAR g_bWildCardNode[2] = { 4, L'*' }; // // Converts a Wide Char String to Parsed Path // // This routine expects the path to be in the format: // \[full path] // Note: There should be no trailing '\' on directory names. // BOOL ConvertToParsedPath( LPWSTR lpszPath, WORD nPathLen, PBYTE pPathBuf, WORD nBufSize ) { BOOL fRet = FALSE; WORD nLen = 0; WORD nChars = 0; WORD nPrefix = 0; WCHAR *pWStr = NULL; WCHAR *pWBuf = NULL; WCHAR *peLength = NULL; BYTE *pElem = NULL; if(NULL == lpszPath) { #ifndef RING3 SrTrace( LOOKUP, ("lpszPath is null\n")) ; #endif goto done; } if(NULL == pPathBuf) { #ifndef RING3 SrTrace( LOOKUP, ("pPathBuf is null\n")) ; #endif goto done; } nLen = nPathLen; pWStr = lpszPath; if( nLen && nBufSize < CALC_PPATH_SIZE(nLen) ) { #ifndef RING3 SrTrace( LOOKUP, ("Passed in buffer is too small\n")) ; #endif goto done; } memset( pPathBuf, 0, nBufSize ); pWStr = lpszPath; // // Skip the leading '\' // while( *pWStr == L'\\' ) { pWStr++; nLen--; } // // Parse and convert to PPATH // pWBuf = (PWCHAR)(pPathBuf + 2*sizeof(WCHAR)); nChars = 0; nPrefix = 2 * sizeof(WCHAR); peLength = pWBuf; *peLength = 0; pWBuf++; while( nLen ) { if ( *pWStr == L'\\' ) { // // Set pe_length // *peLength = (nChars+1)*sizeof(WCHAR); // // update PrefixLength // nPrefix += (*peLength); peLength = pWBuf; nChars = 0; if (nPrefix >= nBufSize) { #ifndef RING3 SrTrace( LOOKUP, ("Passed in buffer is too small - 2\n")) ; #endif fRet = FALSE; goto done; } } else { nChars++; #ifdef RING3 *pWBuf = (WCHAR)CharUpperW((PWCHAR)(*pWStr)); #else *pWBuf = RtlUpcaseUnicodeChar(*pWStr); #endif } pWStr++; pWBuf++; nLen--; } // // When we terminate the above loop, the peLength for the final portion of // the name will not have been set, but peLength will be pointing to the // correct location for this sections length. Go ahead and set it now. // *peLength = (nChars+1)*sizeof(WCHAR); // // Set PrefixLength // ( (ParsedPath *)pPathBuf )->pp_prefixLength = nPrefix; // // Set TotalLength // ( (ParsedPath *)pPathBuf )->pp_totalLength = nPrefix + (*peLength); // // Set the last WORD to 0x00 // *( (PWCHAR)((PBYTE)pPathBuf + nPrefix + (*peLength)) ) = 0; fRet = TRUE; done: return fRet; } // // MatchPrefix : Matches Parsed Path Elements with the given tree. // BOOL MatchPrefix( BYTE * pTree, // Pointer to the tree blob INT iFather, // Parent/Starting Node struct PathElement * ppElem , // PathElement to match INT * pNode, // Matched node return INT * pLevel, // Level of matching INT * pType, // Node type : Incl/Excl/Sfp BOOL * pfProtected, // Protection flag BOOL * pfExactMatch // TRUE : if the path matched exactly ) { TreeNode * node; BOOL fRet = FALSE; if( pLevel ) (*pLevel)++; if( ppElem->pe_length ) { INT iNode = 0; INT iWildCardNode = 0; iNode = TREE_NODEPTR(pTree, iFather)->m_iSon; // // Start by looking at the children of the passed in father // while( iNode ) { node = TREE_NODEPTR(pTree,iNode); // // if we encounter a wildcar node, make a note of it // if (RtlCompareMemory(g_bWildCardNode, pTree + node->m_dwData, ((PathElement *)g_bWildCardNode)->pe_length) == ((PathElement *)g_bWildCardNode)->pe_length) { iWildCardNode = iNode; } // // compare the node contents // if (RtlCompareMemory(ppElem, pTree + node->m_dwData, ppElem->pe_length) == ppElem->pe_length ) { break; } iNode = node->m_iSibling; } // // Note: Wildcard processing // incase we don't have a complete node match, use the // wildcard node if one was found above unless we are at // last element in the path, in which case we need to // lookup hashlist first before doing the wildcard match // if ( iNode == 0 && iWildCardNode != 0 && IFSNextElement(ppElem)->pe_length != 0 ) { iNode = iWildCardNode; } // // Check for lower levels or file children // if( iNode != 0 ) { // // Since we have found a matching node with non default type // we need to set the pType to this node type. This is required // to enforce the parent's type on the children nodes, except // in the case of SFP type. SFP type is marked on a directory // to specify there are SFP files in that directory // if ( ( NODE_TYPE_UNKNOWN != node->m_dwType ) ) { *pType = node->m_dwType; } // // if the node is disabled then abort any furthur seach and // return NODE_TYPE_EXCLUDE from here // if ( node->m_dwFlags & TREEFLAGS_DISABLE_SUBTREE ) { *pType = NODE_TYPE_EXCLUDE; *pNode = iNode; fRet = TRUE; goto Exit; } // // Return from here to preserve the level // fRet = MatchPrefix( pTree, iNode, IFSNextElement(ppElem), pNode, pLevel, pType, pfProtected, pfExactMatch); if (fRet) { goto Exit; } } else { TreeNode * pFatherNode; // // if this the last node check in the Hashlist of parent // if ( IFSNextElement(ppElem)->pe_length == 0 ) { pFatherNode = TREE_NODEPTR(pTree,iFather); if ( pFatherNode->m_dwFileList && MatchEntry( pTree + pFatherNode->m_dwFileList, (LPWSTR)(ppElem->pe_unichars), (INT)(ppElem->pe_length - sizeof(USHORT)), pType) ) { // // Current Father node needs to be returned // *pfExactMatch = TRUE; *pNode = iFather; fRet = TRUE; } else { // // So we have failed to match the hashlist, but // we have encountered a wildcard node then we // need to return that node's type as it will // be the match in this case // if ( iWildCardNode != 0 ) { node = TREE_NODEPTR(pTree,iWildCardNode); *pNode = iWildCardNode; *pType = node->m_dwType; fRet = TRUE; } else { fRet = FALSE; } } } } } else { *pfExactMatch = TRUE; *pNode = iFather; fRet = TRUE; } (*pLevel)--; Exit: return fRet; }