|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: prefix.c
//
// Contents: PREFIX table implementation
//
// History: SethuR -- Implemented
//
// Notes:
//
//--------------------------------------------------------------------------
#ifdef KERNEL_MODE
#include <ntifs.h>
#include <ntddser.h>
#include <windef.h>
#else
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#endif
#include <prefix.h>
#include <dfsprefix.h>
PDFS_PREFIX_TABLE_ENTRY DfspNextUnicodeTableEntry( IN PDFS_PREFIX_TABLE_ENTRY pEntry); VOID DfsDeletePrefixTable( IN PDFS_PREFIX_TABLE pTable);
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, DfsFreePrefixTable )
#pragma alloc_text( PAGE, DfsInitializePrefixTable )
#pragma alloc_text( PAGE, DfsDeletePrefixTable )
#pragma alloc_text( PAGE, DfsInsertInPrefixTable )
#pragma alloc_text( PAGE, DfsFindUnicodePrefix )
#pragma alloc_text( PAGE, DfsRemoveFromPrefixTable )
#pragma alloc_text( PAGE, _LookupPrefixTable )
#pragma alloc_text( PAGE, DfsRemoveFromPrefixTableEx )
#pragma alloc_text( PAGE, DfsRemoveFromPrefixTableLockedEx )
#endif // ALLOC_PRAGMA
#if defined (PREFIX_TABLE_HEAP_MEMORY)
HANDLE PrefixTableHeapHandle = NULL; #endif
NTSTATUS DfsPrefixTableInit() {
#if defined (PREFIX_TABLE_HEAP_MEMORY)
PrefixTableHeapHandle = HeapCreate(0, 0, 0); if ( PrefixTableHeapHandle == NULL ) { return STATUS_INSUFFICIENT_RESOURCES; } /* printf("Prefix table using memory heap\n"); */ #endif
return STATUS_SUCCESS; }
void DfsPrefixTableShutdown(void) {
#if defined (PREFIX_TABLE_HEAP_MEMORY)
if ( PrefixTableHeapHandle != NULL ) { HeapDestroy(PrefixTableHeapHandle); PrefixTableHeapHandle = NULL; } /* printf("Prefix table using memory heap\n"); */ #endif
} //+---------------------------------------------------------------------------
//
// Function: DfsInitializePrefixTable
//
// Synopsis: API for initializing the prefix table
//
// Arguments: [pTable] -- the DFS prefix table instance
//
// Returns: one of the following NTSTATUS codes
// STATUS_SUCCESS -- call was successfull.
//
// History: 04-18-94 SethuR Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS DfsInitializePrefixTable( IN OUT PDFS_PREFIX_TABLE *ppTable, IN BOOLEAN fCaseSensitive, IN PVOID Lock)
{ PDFS_PREFIX_TABLE pTable = *ppTable; NTSTATUS Status = STATUS_SUCCESS; ULONG Flags = fCaseSensitive ? PREFIX_TABLE_CASE_SENSITIVE : 0; int i;
if ( pTable == NULL ) { Flags |= PREFIX_TABLE_TABLE_ALLOCATED; pTable = ALLOCATE_PREFIX_TABLE(); if ( pTable == NULL ) Status = STATUS_INSUFFICIENT_RESOURCES; }
if ( NT_SUCCESS(Status) ) { RtlZeroMemory(pTable, sizeof(DFS_PREFIX_TABLE));
DfsInitializeHeader(&pTable->DfsHeader, DFS_OT_PREFIX_TABLE, sizeof(DFS_PREFIX_TABLE));
pTable->Flags = Flags; pTable->LockCount = 0;
// Initialize the root entry
INITIALIZE_PREFIX_TABLE_ENTRY(&pTable->RootEntry);
// Initialize the various buckets.
for ( i = 0;i < NO_OF_HASH_BUCKETS;i++ ) { INITIALIZE_BUCKET(pTable->Buckets[i]); }
pTable->pPrefixTableLock = Lock;
if ( pTable->pPrefixTableLock == NULL ) { pTable->pPrefixTableLock = ALLOCATE_PREFIX_TABLE_LOCK(); if ( pTable->pPrefixTableLock != NULL ) { pTable->Flags |= PREFIX_TABLE_LOCK_ALLOCATED;
Status = INITIALIZE_PREFIX_TABLE_LOCK(pTable->pPrefixTableLock); if (NT_SUCCESS( Status )) { pTable->Flags |= PREFIX_TABLE_LOCK_INITIALIZED; } } else { Status = STATUS_INSUFFICIENT_RESOURCES; } } }
if (!NT_SUCCESS( Status )) { if (pTable) { DfsDeletePrefixTable( pTable ); pTable = NULL; } } *ppTable = pTable;
return Status; }
//+---------------------------------------------------------------------------
//
// Function: DfsInsertInPrefixTableLocked
//
// Synopsis: API for inserting a path in the prefix table
//
// Arguments: [pTable] -- the DFS prefix table instance
//
// [pPath] -- the path to be looked up.
//
// [pData] -- BLOB associated with the path
//
// Returns: one of the following NTSTATUS codes
// STATUS_SUCCESS -- call was successfull.
//
// History: 04-18-94 SethuR Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS DfsInsertInPrefixTableLocked( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pData) { NTSTATUS status = STATUS_SUCCESS; WCHAR Buffer[MAX_PATH_SEGMENT_SIZE]; PWCHAR NameBuffer = Buffer; ULONG BucketNo = 0; USHORT cbNameBuffer = sizeof(Buffer); PDFS_PREFIX_TABLE_ENTRY pEntry = NULL; PDFS_PREFIX_TABLE_ENTRY pParentEntry = NULL; PDFS_PREFIX_TABLE_ENTRY pLastInsertedEntry = NULL; BOOLEAN fNameFound = FALSE; UNICODE_STRING Path,Name; BOOLEAN NewParent = FALSE; if (IS_PREFIX_TABLE_LOCKED(pTable) == FALSE) { return STATUS_INVALID_PARAMETER; }
// There is one special case, i.e., in which the prefix is '\'.
// Since this is the PATH_DELIMITER which is treated in a special
// way, we do the >processing upfront.
Path.Length = pPath->Length; Path.MaximumLength = pPath->MaximumLength; Path.Buffer = &pPath->Buffer[0]; pParentEntry = &pTable->RootEntry;
if ( pPath->Length == 0 ) { return STATUS_SUCCESS; } else if ( pPath->Buffer[0] == PATH_DELIMITER ) { if ( pPath->Length == sizeof(WCHAR) ) { pTable->RootEntry.pData = pData; return STATUS_SUCCESS; } else { Path.Length -= sizeof(WCHAR); Path.Buffer++; } }
if ( Path.Length >= MAX_PATH_SEGMENT_SIZE * sizeof(WCHAR) ) { NameBuffer = PREFIX_TABLE_ALLOCATE_MEMORY(Path.Length + sizeof(WCHAR)); if ( NameBuffer == NULL ) { return( STATUS_INSUFFICIENT_RESOURCES ); } else { cbNameBuffer = Path.Length + sizeof(WCHAR); } }
while ( Path.Length > 0 ) { Name.Length = 0; Name.Buffer = NameBuffer; Name.MaximumLength = cbNameBuffer;
// Process the name segment
if ( pTable->Flags & PREFIX_TABLE_CASE_SENSITIVE ) { SPLIT_CASE_SENSITIVE_PATH(&Path,&Name,BucketNo); } else { SPLIT_CASE_INSENSITIVE_PATH(&Path,&Name,BucketNo); }
if ( Name.Length > 0 ) { // Lookup the table to see if the name segment already exists.
LOOKUP_BUCKET(pTable->Buckets[BucketNo],Name,pParentEntry,pEntry,fNameFound);
if ( pEntry == NULL ) { // Initialize the new entry and initialize the name segment.
pEntry = ALLOCATE_DFS_PREFIX_TABLE_ENTRY(pTable); if ( pEntry != NULL ) { INITIALIZE_PREFIX_TABLE_ENTRY(pEntry);
// Allocate the name space entry if there is no entry in the
// name page.
{ PWSTR pBuffer;
// Allocate the entry in the name page.
pBuffer = ALLOCATE_NAME_BUFFER((Name.Length/sizeof(WCHAR)));
if ( pBuffer != NULL ) { RtlZeroMemory(pBuffer,Name.Length); RtlCopyMemory(pBuffer,Name.Buffer,Name.Length); pEntry->PathSegment = Name; pEntry->PathSegment.Buffer = pBuffer; } else { FREE_DFS_PREFIX_TABLE_ENTRY(pTable, pEntry); status = STATUS_INSUFFICIENT_RESOURCES; break; } }
// thread the entry to point to the parent.
// Increment the no. of children associated with this entry
if (NewParent == FALSE) { pParentEntry->Reference++; NewParent = TRUE; }
pEntry->pParentEntry = pParentEntry; pLastInsertedEntry = pEntry;
// Insert the entry in the bucket.
INSERT_IN_BUCKET(pTable->Buckets[BucketNo],pEntry);
// Insert the entry in the parent's children list.
INSERT_IN_CHILD_LIST(pEntry, pParentEntry); } else { status = STATUS_INSUFFICIENT_RESOURCES; break; } }
pParentEntry = pEntry; } else { status = STATUS_INVALID_PARAMETER; break; } }
// If a new entry was not successfully inserted we need to walk up the chain
// of parent entries to undo the increment to the reference count and
// remove the entries from their parent links.
if (NT_SUCCESS(status) && pEntry != NULL /* to keep PREFAST happy */) { // The entry was successfully inserted in the prefix table. Update
// the data (BLOB) associated with it.
// We do it outside the loop to prevent redundant comparisons within
// the loop.
pEntry->pData = pData; pTable->TotalEntries += 1; } else { pParentEntry = pLastInsertedEntry; while ( pParentEntry != NULL ) { PDFS_PREFIX_TABLE_ENTRY pMaybeTempEntry;
pMaybeTempEntry = pParentEntry; pParentEntry = pParentEntry->pParentEntry;
if ( --pMaybeTempEntry->Reference == 0 ) { //
// If pParentEntry == NULL, pMaybeTempEntry is
// pTable->RootEntry. Do not try to remove it.
//
if ( pParentEntry != NULL ) { REMOVE_FROM_CHILD_LIST(pMaybeTempEntry); REMOVE_FROM_BUCKET(pMaybeTempEntry); FREE_NAME_BUFFER( pMaybeTempEntry->PathSegment.Buffer ); FREE_DFS_PREFIX_TABLE_ENTRY(pTable, pMaybeTempEntry); } } else { break; } } }
if ( NameBuffer != Buffer ) { PREFIX_TABLE_FREE_MEMORY( NameBuffer ); }
return status; }
//+---------------------------------------------------------------------------
//
// Function: DfsFindUnicodePrefixLocked
//
// Synopsis: 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.
//
// Returns: a valid ptr if successfull, NULL otherwise
//
// History: 04-18-94 SethuR Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS DfsFindUnicodePrefixLocked( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PUNICODE_STRING pSuffix, IN PVOID *ppData, OUT PBOOLEAN pSubStringMatch) { NTSTATUS status = STATUS_SUCCESS; PDFS_PREFIX_TABLE_ENTRY pEntry = NULL;
if (IS_PREFIX_TABLE_LOCKED(pTable) == FALSE) { return STATUS_INVALID_PARAMETER; }
*ppData = NULL;
if ( pPath->Length == 0 ) { status = STATUS_INVALID_PARAMETER; } else { status = _LookupPrefixTable(pTable,pPath,pSuffix,&pEntry, pSubStringMatch);
// Update the BLOB placeholder with the results of the lookup.
if ( status == STATUS_SUCCESS ) { *ppData = pEntry->pData; }
} return status; }
//+---------------------------------------------------------------------------
//
// Function: DfsRemoveFromPrefixTable
//
// 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.
//
// 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 DfsRemoveFromPrefixTableLocked( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pMatchingData) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING Path,Suffix;
PDFS_PREFIX_TABLE_ENTRY pEntry = NULL;
if (IS_PREFIX_TABLE_LOCKED(pTable) == FALSE) { return STATUS_INVALID_PARAMETER; }
Suffix.Length = 0; Suffix.Buffer = NULL;
Path.Length = pPath->Length; Path.MaximumLength = pPath->MaximumLength; Path.Buffer = &pPath->Buffer[0];
if ( pPath->Length == 0 ) { return STATUS_SUCCESS; } else if ( pPath->Buffer[0] == PATH_DELIMITER ) { if ( pPath->Length == sizeof(WCHAR) ) { if ( pTable->RootEntry.pData == NULL ) { status = STATUS_OBJECT_PATH_NOT_FOUND; return status; } else { pTable->RootEntry.pData = NULL; return STATUS_SUCCESS; } } else { Path.Length -= sizeof(WCHAR); Path.Buffer++; } }
status = _LookupPrefixTable(pTable,&Path,&Suffix,&pEntry,NULL);
if ( NT_SUCCESS(status)&& (Suffix.Length == 0) ) { if ( (pMatchingData == NULL) || (pMatchingData == pEntry->pData) ) { DfsRemovePrefixTableEntry(pTable, pEntry); pTable->TotalEntries -= 1; } else { status = STATUS_NOT_FOUND; } }
return status; }
NTSTATUS DfsReplaceInPrefixTableLocked( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pReplaceData, IN PVOID *ppMatchingData) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING Path,Suffix;
PDFS_PREFIX_TABLE_ENTRY pEntry = NULL; if (IS_PREFIX_TABLE_LOCKED(pTable) == FALSE) { return STATUS_INVALID_PARAMETER; }
Suffix.Length = 0; Suffix.Buffer = NULL;
Path.Length = pPath->Length; Path.MaximumLength = pPath->MaximumLength; Path.Buffer = &pPath->Buffer[0];
if ( pPath->Length == 0 ) { return STATUS_SUCCESS; } else if ( pPath->Buffer[0] == PATH_DELIMITER ) { if ( pPath->Length == sizeof(WCHAR) ) { if ( pTable->RootEntry.pData == NULL ) { status = STATUS_OBJECT_PATH_NOT_FOUND; return status; } else { pTable->RootEntry.pData = NULL; return STATUS_SUCCESS; } } else { Path.Length -= sizeof(WCHAR); Path.Buffer++; } }
status = _LookupPrefixTable(pTable,&Path,&Suffix,&pEntry,NULL);
if ( NT_SUCCESS(status)&& (Suffix.Length == 0) ) { if ( (*ppMatchingData == NULL) || (*ppMatchingData == pEntry->pData) ) { *ppMatchingData = pEntry->pData; pEntry->pData = pReplaceData; } else { status = STATUS_NOT_FOUND; } }
if ( (status != STATUS_SUCCESS) && (*ppMatchingData == NULL) ) { status = DfsInsertInPrefixTableLocked( pTable, pPath, pReplaceData ); }
return status; }
VOID DfsRemovePrefixTableEntry( IN PDFS_PREFIX_TABLE pTable, IN PDFS_PREFIX_TABLE_ENTRY pEntry ) { UNREFERENCED_PARAMETER(pTable);
// Destroy the association between the data associated with
// this prefix.
pEntry->pData = NULL;
// found an exact match for the given path name in the table.
// traverse the list of parent pointers and delete them if
// required.
while ( pEntry != NULL ) { if ( (--pEntry->Reference) == 0 ) { PDFS_PREFIX_TABLE_ENTRY pTempEntry = pEntry; pEntry = pEntry->pParentEntry;
//
// pEntry == NULL means pTempEntry is pTable->RootEntry.
// Do not try to remove it.
//
if ( pEntry != NULL ) { REMOVE_FROM_CHILD_LIST(pTempEntry); REMOVE_FROM_BUCKET(pTempEntry); FREE_NAME_BUFFER( pTempEntry->PathSegment.Buffer ); FREE_DFS_PREFIX_TABLE_ENTRY(pTable,pTempEntry); } } else { break; }
} return; }
//+---------------------------------------------------------------------------
//
// Function: DfsFreePrefixTable
//
// Synopsis: API for freeing a prefix table
//
// Arguments: [pTable] -- the DFS prefix table instance
//
// Returns: one of the following NTSTATUS codes
// STATUS_SUCCESS -- call was successfull.
//
// History: 08-01-99 JHarper Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS DfsDismantlePrefixTable( IN PDFS_PREFIX_TABLE pTable, IN VOID (*ProcessFunction)(PVOID pEntry))
{ NTSTATUS Status = STATUS_SUCCESS; PDFS_PREFIX_TABLE_ENTRY pEntry = NULL; PDFS_PREFIX_TABLE_ENTRY pSentinelEntry = NULL; ULONG i = 0;
WRITE_LOCK_PREFIX_TABLE(pTable, Status); if ( Status != STATUS_SUCCESS ) goto done;
for ( i = 0; i < NO_OF_HASH_BUCKETS; i++ ) { pSentinelEntry = &pTable->Buckets[i].SentinelEntry; while ( pSentinelEntry->pNextEntry != pSentinelEntry ) { pEntry = pSentinelEntry->pNextEntry; REMOVE_FROM_BUCKET(pEntry); if ( (ProcessFunction) && (pEntry->pData) ) { ProcessFunction(pEntry->pData); } FREE_NAME_BUFFER( pEntry->PathSegment.Buffer ); FREE_DFS_PREFIX_TABLE_ENTRY(pTable, pEntry); } pTable->Buckets[i].NoOfEntries = 0; } if ( pTable->RootEntry.PathSegment.Buffer != NULL ) FREE_NAME_BUFFER(pTable->RootEntry.PathSegment.Buffer);
UNLOCK_PREFIX_TABLE(pTable);
done: return Status; } NTSTATUS DfsDereferencePrefixTable( IN PDFS_PREFIX_TABLE pTable) { PDFS_OBJECT_HEADER pHeader = NULL; USHORT headerType = 0; LONG Ref = 0;
if(pTable == NULL) { return STATUS_INVALID_PARAMETER; }
pHeader = &pTable->DfsHeader;
headerType = DfsGetHeaderType( pHeader );
if (headerType != DFS_OT_PREFIX_TABLE) { return STATUS_UNSUCCESSFUL; }
Ref = DfsDecrementReference( pHeader ); if (Ref == 0) { DfsDeletePrefixTable( pTable ); pTable = NULL; } return STATUS_SUCCESS; }
VOID DfsDeletePrefixTable( IN PDFS_PREFIX_TABLE pTable) { if (pTable != NULL) { if (pTable->Flags & PREFIX_TABLE_LOCK_INITIALIZED) { UNINITIALIZE_PREFIX_TABLE_LOCK( pTable->pPrefixTableLock ); pTable->Flags &= ~(PREFIX_TABLE_LOCK_INITIALIZED); } if (pTable->Flags & PREFIX_TABLE_LOCK_ALLOCATED) { FREE_PREFIX_TABLE_LOCK( pTable->pPrefixTableLock ); pTable->pPrefixTableLock = NULL; pTable->Flags &= ~(PREFIX_TABLE_LOCK_ALLOCATED); } if (pTable->Flags & PREFIX_TABLE_TABLE_ALLOCATED) { FREE_PREFIX_TABLE( pTable ); } }
return; }
//+---------------------------------------------------------------------------
//
// 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, OUT PBOOLEAN pSubStringMatch ) { 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; BOOLEAN SubStringMatch = TRUE;
// 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 = PREFIX_TABLE_ALLOCATE_MEMORY(Path.Length + sizeof(WCHAR)); if ( NameBuffer == NULL ) { 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->Flags & PREFIX_TABLE_CASE_SENSITIVE ) { 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.
LOOKUP_BUCKET(pTable->Buckets[BucketNo],Name,pParentEntry,pEntry,fNameFound);
if ( pEntry != NULL ) { // Cache the data available for this prefix if any.
if ( pEntry->pData != NULL ) { *pSuffix = Path; *ppEntry = pEntry; fPrefixFound = TRUE; } } else { SubStringMatch = FALSE; break; }
// set the stage for processing the next name segment.
pParentEntry = pEntry; } }
if ( !fPrefixFound ) { status = STATUS_OBJECT_PATH_NOT_FOUND; }
if ( NameBuffer != Buffer ) { PREFIX_TABLE_FREE_MEMORY( NameBuffer ); }
if (pSubStringMatch != NULL) { *pSubStringMatch = SubStringMatch; } return status; }
NTSTATUS DfsInsertInPrefixTable( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pData) { NTSTATUS status;
WRITE_LOCK_PREFIX_TABLE(pTable, status); if ( status != STATUS_SUCCESS ) goto done;
status = DfsInsertInPrefixTableLocked(pTable, pPath, pData);
UNLOCK_PREFIX_TABLE(pTable);
done: return status; }
NTSTATUS DfsFindUnicodePrefix( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PUNICODE_STRING pSuffix, IN PVOID *ppData) { NTSTATUS Status;
READ_LOCK_PREFIX_TABLE(pTable, Status); if ( Status != STATUS_SUCCESS ) goto done;
Status = DfsFindUnicodePrefixLocked(pTable, pPath, pSuffix, ppData,NULL);
UNLOCK_PREFIX_TABLE(pTable); done: return Status; }
NTSTATUS DfsRemoveFromPrefixTable( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pMatchingData) { NTSTATUS Status;
WRITE_LOCK_PREFIX_TABLE(pTable, Status); if ( Status != STATUS_SUCCESS ) goto done;
Status = DfsRemoveFromPrefixTableLocked(pTable, pPath, pMatchingData);
UNLOCK_PREFIX_TABLE(pTable);
done: return Status; }
NTSTATUS DfsRemoveFromPrefixTableLockedEx( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pMatchingData, IN PVOID *pReturnedData) {
NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING Path,Suffix;
PDFS_PREFIX_TABLE_ENTRY pEntry = NULL; UNREFERENCED_PARAMETER(pMatchingData);
if (IS_PREFIX_TABLE_LOCKED(pTable) == FALSE) { return STATUS_INVALID_PARAMETER; }
Suffix.Length = 0; Suffix.Buffer = NULL;
Path.Length = pPath->Length; Path.MaximumLength = pPath->MaximumLength; Path.Buffer = &pPath->Buffer[0];
if ( pPath->Length == 0 ) { return STATUS_SUCCESS; } else if ( pPath->Buffer[0] == PATH_DELIMITER ) { if ( pPath->Length == sizeof(WCHAR) ) { if ( pTable->RootEntry.pData == NULL ) { status = STATUS_OBJECT_PATH_NOT_FOUND; return status; } else { pTable->RootEntry.pData = NULL; return STATUS_SUCCESS; } } else { Path.Length -= sizeof(WCHAR); Path.Buffer++; } }
status = _LookupPrefixTable(pTable,&Path,&Suffix,&pEntry,NULL);
if ( NT_SUCCESS(status)&& (Suffix.Length == 0) ) { *pReturnedData = pEntry->pData; DfsRemovePrefixTableEntry(pTable, pEntry); }
return status; }
NTSTATUS DfsRemoveFromPrefixTableEx( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pMatchingData, IN PVOID *pReturnedData) { NTSTATUS Status;
WRITE_LOCK_PREFIX_TABLE(pTable, Status); if ( Status != STATUS_SUCCESS ) goto done;
Status = DfsRemoveFromPrefixTableLockedEx(pTable, pPath, pMatchingData, pReturnedData);
UNLOCK_PREFIX_TABLE(pTable);
done: return Status; }
NTSTATUS DfsReplaceInPrefixTable( IN PDFS_PREFIX_TABLE pTable, IN PUNICODE_STRING pPath, IN PVOID pReplaceData, IN PVOID pMatchingData) { NTSTATUS Status; IN PVOID pGotData = pMatchingData;
WRITE_LOCK_PREFIX_TABLE(pTable, Status); if ( Status != STATUS_SUCCESS ) goto done;
Status = DfsReplaceInPrefixTableLocked(pTable, pPath, pReplaceData, &pGotData);
UNLOCK_PREFIX_TABLE(pTable);
done: return Status; }
#if !defined (KERNEL_MODE)
VOID DumpParentName( IN PDFS_PREFIX_TABLE_ENTRY pEntry) {
if ( pEntry->pParentEntry != NULL ) { DumpParentName(pEntry->pParentEntry); if ( pEntry->pParentEntry->PathSegment.Buffer != NULL ) printf("\\%wZ", &pEntry->pParentEntry->PathSegment); }
return; }
VOID DfsDumpPrefixTable( PDFS_PREFIX_TABLE pPrefixTable, IN VOID (*DumpFunction)(PVOID pEntry)) { PPREFIX_TABLE_BUCKET pBucket; PDFS_PREFIX_TABLE_ENTRY pCurEntry = NULL; ULONG i, NumEntries; NTSTATUS Status;
printf("Prefix table %p\n", pPrefixTable); printf("Prefix table flags %x\n", pPrefixTable->Flags); printf("Prefix table Lock %p\n", pPrefixTable->pPrefixTableLock);
READ_LOCK_PREFIX_TABLE(pPrefixTable, Status); if (Status != STATUS_SUCCESS) return NOTHING;
for ( i = 0; i < NO_OF_HASH_BUCKETS; i++ ) { pBucket = &pPrefixTable->Buckets[i];
pCurEntry = pBucket->SentinelEntry.pNextEntry; NumEntries = 0; while ( pCurEntry != &pBucket->SentinelEntry ) { NumEntries++; if ( pCurEntry->pData != NULL ) { printf("Found Prefix data %p in Bucket %d\n", pCurEntry->pData, i); DumpParentName(pCurEntry); printf("\\%wZ\n", &pCurEntry->PathSegment); if ( DumpFunction ) { DumpFunction(pCurEntry->pData); } } pCurEntry = pCurEntry->pNextEntry; }
printf("Number of entries in Bucket %d is %d\n", i, NumEntries); } UNLOCK_PREFIX_TABLE(pPrefixTable); }
#endif
NTSTATUS DfsPrefixTableAcquireWriteLock( PDFS_PREFIX_TABLE pPrefixTable ) { NTSTATUS Status;
WRITE_LOCK_PREFIX_TABLE(pPrefixTable, Status);
return Status;
}
NTSTATUS DfsPrefixTableAcquireReadLock( PDFS_PREFIX_TABLE pPrefixTable ) { NTSTATUS Status;
READ_LOCK_PREFIX_TABLE(pPrefixTable, Status);
return Status;
}
NTSTATUS DfsPrefixTableReleaseLock( PDFS_PREFIX_TABLE pPrefixTable ) { UNLOCK_PREFIX_TABLE(pPrefixTable);
return STATUS_SUCCESS;
}
NTSTATUS DfsEnumeratePrefixTableLocked( IN PDFS_PREFIX_TABLE pTable, IN VOID (*ProcessFunction)(PVOID pEntry, PVOID pContext), LPVOID lpvClientContext)
{ NTSTATUS Status = STATUS_SUCCESS; PPREFIX_TABLE_BUCKET pBucket = NULL; PDFS_PREFIX_TABLE_ENTRY pCurEntry = NULL; ULONG i = 0;
if(pTable->TotalEntries == 0) { return Status; }
for ( i = 0; i < NO_OF_HASH_BUCKETS; i++ ) { pBucket = &pTable->Buckets[i];
pCurEntry = pBucket->SentinelEntry.pNextEntry; while ( pCurEntry != &pBucket->SentinelEntry ) { if ( pCurEntry->pData != NULL ) { ProcessFunction(pCurEntry->pData, lpvClientContext); }
pCurEntry = pCurEntry->pNextEntry; } }
return Status; }
|