|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: prefixp.c
//
// Contents: PREFIX table implementation
//
// History: SethuR -- Implemented
//
// Notes:
//
//--------------------------------------------------------------------------
#ifdef KERNEL_MODE
#include <dfsprocs.h>
#define Dbg DEBUG_TRACE_RTL
#else
#define DebugTrace(x,y,z,a)
#endif
#include <prefix.h>
#include <prefixp.h>
//
// This macro takes a pointer (or ulong) and returns its rounded up quadword
// value
//
#define QuadAlign(Ptr) ( \
((((ULONG)(Ptr)) + 7) & 0xfffffff8) \ )
//+---------------------------------------------------------------------------
//
// Function: _InitializePrefixTableEntryAllocation
//
// Synopsis: private fn. for initializing prefix table entry allocation
//
// Arguments: [pTable] -- table to be initialized
//
// Returns: one of the following NTSTATUS codes
// STATUS_SUCCESS -- call was successfull.
// STATUS_NO_MEMORY -- no resource available
//
// History: 04-18-94 SethuR Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS _InitializePrefixTableEntryAllocation(PDFS_PREFIX_TABLE pTable) { NTSTATUS status = STATUS_SUCCESS;
return status; }
//+---------------------------------------------------------------------------
//
// Function: _AllocateNamePageEntry
//
// Synopsis: private fn. for allocating a name page entry
//
// Arguments: [pNamePageList] -- name page list to allocate from
//
// [cLength] -- length of the buffer in WCHAR's
//
// Returns: NULL if unsuccessfull otherwise valid pointer
//
// History: 04-18-94 SethuR Created
//
// Notes:
//
//----------------------------------------------------------------------------
PWSTR _AllocateNamePageEntry(PNAME_PAGE_LIST pNamePageList, ULONG cLength) { PNAME_PAGE pTempPage = pNamePageList->pFirstPage; PWSTR pBuffer = NULL;
//
// We alloc in chunks of FREESPACE_IN_NAME_PAGE, so if cLength is
// greater than that, we can't alloc anything.
//
if (cLength > FREESPACE_IN_NAME_PAGE) {
return NULL;
}
while (pTempPage != NULL) { if (pTempPage->cFreeSpace >= (LONG)cLength) break; else pTempPage = pTempPage->pNextPage; }
if (pTempPage == NULL) { pTempPage = ALLOCATE_NAME_PAGE();
if (pTempPage != NULL) { INITIALIZE_NAME_PAGE(pTempPage); pTempPage->pNextPage = pNamePageList->pFirstPage; pNamePageList->pFirstPage = pTempPage; pTempPage->cFreeSpace = FREESPACE_IN_NAME_PAGE; } }
if ((pTempPage != NULL) && (pTempPage->cFreeSpace >= (LONG)cLength)) { pTempPage->cFreeSpace -= cLength; pBuffer = &pTempPage->Names[pTempPage->cFreeSpace]; }
return pBuffer; }
//+---------------------------------------------------------------------------
//
// Function: _LookupPrefixTable
//
// Synopsis: private fn. for looking up a name segment in a prefix table
//
// Arguments: [pTable] -- the DFS prefix table instance
//
// [pPath] -- the path to be looked up.
//
// [pSuffix] -- the suffix that could not be found.
//
// [ppEntry] -- placeholder for the matching entry for the prefix.
//
//
// Returns: one of the following NTSTATUS codes
// STATUS_SUCCESS -- call was successfull.
// STATUS_OBJECT_PATH_NOT_FOUND -- no entry for the path
//
// History: 04-18-94 SethuR Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS _LookupPrefixTable(PDFS_PREFIX_TABLE pTable, UNICODE_STRING *pPath, UNICODE_STRING *pSuffix, PDFS_PREFIX_TABLE_ENTRY *ppEntry) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING Path = *pPath; WCHAR Buffer[MAX_PATH_SEGMENT_SIZE]; PWCHAR NameBuffer = Buffer; USHORT cbNameBuffer = sizeof(Buffer); UNICODE_STRING Name; ULONG BucketNo; BOOLEAN fPrefixFound = FALSE; PDFS_PREFIX_TABLE_ENTRY pEntry = NULL; PDFS_PREFIX_TABLE_ENTRY pParentEntry = &pTable->RootEntry; BOOLEAN fNameFound = FALSE;
DebugTrace(0, Dbg, "_LookupPrefixTable -- Entry\n", 0);
// The \ is treated as a special case. The test for all names starting with
// a delimiter is done before we initiate the complete search process.
if (Path.Buffer[0] == PATH_DELIMITER) { Path.Length = Path.Length - sizeof(WCHAR); Path.Buffer += 1; // Skip the path delimiter at the beginning.
if (pTable->RootEntry.pData != NULL) { fPrefixFound = TRUE; *pSuffix = Path; *ppEntry = &pTable->RootEntry; } }
if (Path.Length > MAX_PATH_SEGMENT_SIZE) { NameBuffer = ExAllocatePoolWithTag( NonPagedPool, Path.Length + sizeof(WCHAR), ' sfD' ); if (NameBuffer == NULL) { DebugTrace(0, Dbg, "Unable to allocate %d non-paged bytes\n", (Path.Length + sizeof(WCHAR)) ); return( STATUS_INSUFFICIENT_RESOURCES ); } else { cbNameBuffer = Path.Length + sizeof(WCHAR); } }
while (Path.Length > 0) { Name.Length = 0; Name.Buffer = NameBuffer; Name.MaximumLength = cbNameBuffer;
if (pTable->CaseSensitive) { SPLIT_CASE_SENSITIVE_PATH(&Path,&Name,BucketNo); } else { SPLIT_CASE_INSENSITIVE_PATH(&Path,&Name,BucketNo); }
if (Name.Length > 0) { // Process the name segment
// Lookup the bucket to see if the entry exists.
DebugTrace(0, Dbg, "LOOKUP_BUCKET: Bucket(%ld)", ULongToPtr( BucketNo )); DebugTrace(0, Dbg, "for Name(%wZ)\n", &Name);
LOOKUP_BUCKET(pTable->Buckets[BucketNo],Name,pParentEntry,pEntry,fNameFound);
DebugTrace(0, Dbg, "Returned pEntry(%lx)", pEntry); DebugTrace(0, Dbg, " and fNameFound(%s)\n",fNameFound ? "TRUE" : "FALSE" );
if (pEntry != NULL) { // Cache the data available for this prefix if any.
if (pEntry->pData != NULL) { *pSuffix = Path; *ppEntry = pEntry; fPrefixFound = TRUE; } } else { break; }
// set the stage for processing the next name segment.
pParentEntry = pEntry; } }
if (!fPrefixFound) { status = STATUS_OBJECT_PATH_NOT_FOUND; DebugTrace(0, Dbg, "_LookupPrefixTable Error -- %lx\n", ULongToPtr( status )); }
if (NameBuffer != Buffer) { ExFreePool( NameBuffer ); }
DebugTrace(-1, Dbg, "_LookupPrefixTable -- Exit\n", 0); return status; }
|