|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: prefix.hxx
//
// Contents: PREFIX table definition
//
// History: SethuR -- Implemented
//
// Notes: The DFS prefix table data structure consists of three
// entities and methods to manipulate them. They are the
// DFS_PREFIX_TABLE_ENTRY,DFS_PREFIX_TABLE_BUCKET and the
// DFS_PREFIX_TABLE.
//
// The DFS_PREFIX_TABLE is a hash table of DFS_PREFIX_TABLE_ENTRY's
// wherein collisions are resolved through linear chaining. The
// hash table is organized as an array of collision lists
// (DFS_PREFIX_TABLE_BUCKET). A brief description with each of
// these entities is attached to the declaration.
//
// There are certain characterstics that distinguish this
// hash table from other hash tables. These are the extensions
// provided to accomodate the special operations.
//
//--------------------------------------------------------------------------
#ifndef __PREFIX_HXX__
#define __PREFIX_HXX__
//+---------------------------------------------------------------------
//
// Struct: DFS_PREFIX_TABLE_ENTRY
//
// History:
//
// Notes: Each DFS_PREFIX_TABLE entry is in reality a member of two linked
// lists -- a doubly linked list chaining the entries in a bucket
// and a singly linked list establishing the path from any entry to
// the root of the name space. In addition we have the data associated
// with each entry, viz., the name and the data (pData). We also
// keep track of the number of children of each entry. It can also
// be defined as the number of paths to the root of which this entry
// is a member.
//
//----------------------------------------------------------------------
typedef struct _DFS_PREFIX_TABLE_ENTRY_ { struct _DFS_PREFIX_TABLE_ENTRY_ *pParentEntry; struct _DFS_PREFIX_TABLE_ENTRY_ *pNextEntry; struct _DFS_PREFIX_TABLE_ENTRY_ *pPrevEntry;
//
// pFirstChildEntry and pSiblingEntry are used purely for enumeration
//
struct _DFS_PREFIX_TABLE_ENTRY_ *pFirstChildEntry; struct _DFS_PREFIX_TABLE_ENTRY_ *pSiblingEntry;
ULONG NoOfChildren;
UNICODE_STRING PathSegment; PVOID pData; } DFS_PREFIX_TABLE_ENTRY, *PDFS_PREFIX_TABLE_ENTRY;
//+---------------------------------------------------------------------
//
// Struct: DFS_PREFIX_TABLE_BUCKET
//
// History:
//
// Notes: The DFS_PREFIX_TABLE_BUCKET is a doubly linked list of
// DFS_PREFIX_TABLE_ENTRY's. The current implementation employs
// the notion of a sentinel entry associated with each bucket. The
// end pointers are never null but are always looped back to the
// sentinel entry. The reason we employ such an organization is that
// it considerably simplifies the list manipulation routines. The
// reason this needs to be a doubly linked list is that we would like
// to have the ability of deleting entries without having to traverse
// the buckets from beginning.
//
// The following inline methods ( macro defns. ) are provided for
// inserting, deleting and looking up an entry in the bucket.
//
//----------------------------------------------------------------------
typedef struct _PREFIX_TABLE_BUCKET_ { ULONG NoOfEntries; // High water mark for entries hashing to the bkt.
DFS_PREFIX_TABLE_ENTRY SentinelEntry; } PREFIX_TABLE_BUCKET, *PPREFIX_TABLE_BUCKET;
//+---------------------------------------------------------------------
//
// Struct: NAME_PAGE
//
// History:
//
// Notes: The name segments associated with the various entries are all
// stored together in a name page. This allows us to amortize the
// memory allocation costs over a number of entries and also allows
// us to speed up traversal ( for details see DFS_PREFIX_TABLE
// definition ).
//
//----------------------------------------------------------------------
#define FREESPACE_IN_NAME_PAGE ((PAGE_SIZE - sizeof(ULONG) - sizeof(PVOID)) / sizeof(WCHAR))
typedef struct _NAME_PAGE_ { struct _NAME_PAGE_ *pNextPage; LONG cFreeSpace; // free space avilable in WCHAR's
WCHAR Names[FREESPACE_IN_NAME_PAGE]; } NAME_PAGE, *PNAME_PAGE;
typedef struct _NAME_PAGE_LIST_ { PNAME_PAGE pFirstPage; } NAME_PAGE_LIST, *PNAME_PAGE_LIST;
//+---------------------------------------------------------------------
//
// Struct: DFS_PREFIX_TABLE
//
// History:
//
// Notes: The DFS_PREFIX_TABLE is a hashed collection of DFS_PREFIX_TABLE_ENTRY
// organized in the form of buckets. In addition one other space
// conserving measure is adopted. There is only one copy of each
// name segment stored in the table. As an example consider the
// two pathnames \foo\bar and \bar\foo. We only store one copy of foo
// and bar eventhough we accomdate both these paths. A beneficial
// side effect of storing single copies is that our traversal of the
// collision chain is considerably speeded up since once we have
// located the pointer to the name, subsequent comparisons need merely
// compare pointers as opposed to strings.
//
//----------------------------------------------------------------------
#define NO_OF_HASH_BUCKETS 57
typedef struct _DFS_PREFIX_TABLE { BOOLEAN CaseSensitive; NAME_PAGE_LIST NamePageList; //
// NextEntry is used purely for enumeration
//
PDFS_PREFIX_TABLE_ENTRY NextEntry; DFS_PREFIX_TABLE_ENTRY RootEntry; PREFIX_TABLE_BUCKET Buckets[NO_OF_HASH_BUCKETS];
#ifdef KERNEL_MODE
// Zone for allocating DFS_PREFIX_TABLE entries .....
ZONE_HEADER PrefixTableEntryZone;
#else
// A DFS_PREFIX_TABLE is part of DS_DATA. We need to make the sizes of
// these structures identical in user and kernel mode, so that user-mode
// utilities like dfsdump can work.
CHAR UnusedBuffer[sizeof(ZONE_HEADER)];
#endif
} DFS_PREFIX_TABLE, *PDFS_PREFIX_TABLE;
//+---------------------------------------------------------------------
//
// Struct: DFS_PREFIX_TABLE API.
//
// History:
//
// Notes: The following API's are provided for manipulating the
// DFS_PREFIX_TABLE.
//
//----------------------------------------------------------------------
extern NTSTATUS DfsInitializePrefixTable(PDFS_PREFIX_TABLE pTable, BOOLEAN fCaseSensitive);
extern NTSTATUS DfsInsertInPrefixTable(PDFS_PREFIX_TABLE pTable, PUNICODE_STRING pPath, PVOID pData); extern NTSTATUS DfsLookupPrefixTable(PDFS_PREFIX_TABLE pTable, PUNICODE_STRING pPath, PUNICODE_STRING pSuffix, PVOID *ppData);
extern NTSTATUS DfsRemoveFromPrefixTable(PDFS_PREFIX_TABLE pTable, PUNICODE_STRING pPath);
NTSTATUS DfsFreePrefixTable( PDFS_PREFIX_TABLE pTable);
//
// The RTL Prefix Table function signatures are slightly different.
// For now we will define a mapping between them to ease the porting
// effort. Subsequently we will change our signatures to confirm to
// the RTL routine.
//
#define DfsInitializeUnicodePrefix(pTable) \
(DfsInitializePrefixTable(pTable,FALSE) == STATUS_SUCCESS)
#define DfsRemoveUnicodePrefix(pTable,pPath) \
(DfsRemoveFromPrefixTable(pTable,pPath) == STATUS_SUCCESS)
#define DfsInsertUnicodePrefix(pTable,pPath,pData) \
(DfsInsertInPrefixTable(pTable,pPath,pData) == STATUS_SUCCESS)
PVOID DfsFindUnicodePrefix(PDFS_PREFIX_TABLE pTable, PUNICODE_STRING pPath, PUNICODE_STRING pSuffix);
PVOID DfsNextUnicodePrefix(PDFS_PREFIX_TABLE pTable, BOOLEAN fRestart);
#endif // __PREFIX_HXX__
|