windows-nt/Source/XPSP1/NT/base/fs/dfs/h/prefix.h
2020-09-26 16:20:57 +08:00

231 lines
8.4 KiB
C

//+-------------------------------------------------------------------------
//
// 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 DfsFreePrefixTable(PDFS_PREFIX_TABLE pTable);
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);
//
// 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);
PVOID DfsNextUnicodePrefixChild(PDFS_PREFIX_TABLE pTable,
PUNICODE_STRING pPath,
PVOID *ppCookie);
#endif // __PREFIX_HXX__