summaryrefslogtreecommitdiffstats
path: root/private/ntos/cntfs/views/viewprop.h
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/cntfs/views/viewprop.h
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/cntfs/views/viewprop.h')
-rw-r--r--private/ntos/cntfs/views/viewprop.h600
1 files changed, 600 insertions, 0 deletions
diff --git a/private/ntos/cntfs/views/viewprop.h b/private/ntos/cntfs/views/viewprop.h
new file mode 100644
index 000000000..2f681ad0b
--- /dev/null
+++ b/private/ntos/cntfs/views/viewprop.h
@@ -0,0 +1,600 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ViewProp.h
+
+Abstract:
+
+ This module defines the routines used in ViewProp.Sys to service view and
+ property requests.
+
+ *********************************
+ *No other clients are supported.*
+ *********************************
+
+Author:
+
+ Mark Zbikowski [MarkZ] 21-Dec-95
+
+Revision History:
+
+
+--*/
+
+#include <ntfsproc.h>
+
+#include <ntrtl.h>
+#include <nturtl.h> // needs ntrtl.h
+#include <objidl.h> // needs nturtl.h
+#include <propset.h> // needs objidl.h
+#include "ntfsprop.h" // needs objidl.h
+
+//
+// Big picture of Views implementation
+//
+// Directories are the only objects that contain views. Views' purpose is
+// to provide an up-to-date sorted list of objects in a directory. This is
+// only single-level containment as we don't do transitive closure.
+//
+// A view is simply an index whose entries are an ordered list of property
+// values. Each view has a description that lists the sources of each
+// property value.
+//
+// All views of a directory are stored as index attributes of the directory
+// itself. All view descriptsions are stored in a single data sttribute of
+// the directory.
+//
+// Creation of a view consists of:
+// Dispatched via FsCtl
+// Acquiring the directory
+// Creating/opening the view description attribute
+// Adding a record describing the view (what properties are included,
+// which ones are sorted, and whether the sort is up or down). This
+// is a logged operation.
+// Creating the view index
+// Releasing the directory
+//
+// Deleting a view consists of:
+// Dispatched via FsCtl
+// Acquiring the directory
+// Opening the view description attribute
+// Finding/deleting the record describing the view. This is a logged
+// operation
+// Deleting the view index
+// Releasing the directory
+//
+// Updating a view consists of:
+// Dispatched via property change call, security change call,
+// DUPLICATED_INFO change, or STAT_INFO change
+// Acquiring the object
+// Acquiring the parent directory
+// Opening the view description
+// For each view that contains a property that is being changed
+// From the object, build the old row and build the new row
+// Open the view
+// Delete the old row
+// Insert the new row
+// Releasing the parent
+// Releasing the object
+//
+
+
+#if DBG
+#define PROPASSERT(exp) \
+ ((exp) ? TRUE : \
+ (DbgPrint( "%s:%d %s\n",__FILE__,__LINE__,#exp ), \
+ DbgBreakPoint(), \
+ TRUE))
+#else // DBG
+#define PROPASSERT(exp)
+#endif
+
+//
+// Property set storage format
+//
+// Each property set is stored within a single stream and is limited to
+// VACB_MAPPING_GRANULARITY in size. The storage format is optimized for
+// the following operations:
+//
+// Write all properties. (written via save/save-all/copy/restore)
+// Write in place.
+// Write and extend length of variable length property.
+// Add one or several new properties.
+// Delete all properties.
+// Delete one or several properties.
+//
+// Read all properties. (open/copy/backup)
+// Read one or several properties.
+//
+// Name via ID.
+// Name via string.
+//
+// Each property set is comprised of three pieces: a fixed-size header,
+// a property ID table and a property-value heap.
+//
+// The header describes the sizes and offsets of the table and heap within the
+// stream. The header is always at offset 0i64. Planning for a future where
+// this format might be exposed to user-space code, the header is included from
+// the OLE property set format and has several additional fields.
+//
+
+typedef struct _PROPERTY_SET_HEADER {
+
+ //
+ // Header from OLE describing version number and containing fields
+ // for format and class Id
+ //
+
+ PROPERTYSETHEADER;
+
+ //
+ // Offset to PropertyIdTable
+ //
+
+ ULONG IdTableOffset;
+
+ //
+ // Offset to PropertyValueHeap
+ //
+
+ ULONG ValueHeapOffset;
+
+} PROPERTY_SET_HEADER, *PPROPERTY_SET_HEADER;
+typedef const PROPERTY_SET_HEADER *PCPROPERTY_SET_HEADER;
+
+#define PSH_FORMAT_VERSION 2
+#define PSH_DWOSVER 0x00020005
+
+#define PROPERTY_ID_TABLE(psh) \
+ ((PPROPERTY_ID_TABLE)Add2Ptr( (psh), (psh)->IdTableOffset ))
+#define PROPERTY_HEAP_HEADER(psh) \
+ ((PPROPERTY_HEAP_HEADER)Add2Ptr( (psh), (psh)->ValueHeapOffset ))
+
+
+//
+// Following the header in the stream is the PropertyIdTable.
+//
+// The Property Id Table allows for a quick mapping of PropertyId to offset
+// within the Property Heap. The table is a sorted (on PropertyId) array of
+// Id/Offset pairs. The table is allowed to contain some extra slots so that
+// insertion of a new element can often be made without shuffling the heap.
+//
+// As an implementation efficiency, the Entry array is addressed in the code in
+// 1-based fashion. The array, however, will always occupy entry [0].
+//
+
+typedef struct _PROPERTY_TABLE_ENTRY {
+
+ //
+ // Property ID used for sorting
+ //
+
+ ULONG PropertyId;
+
+ //
+ // Offset within the property heap of the value of this property
+ //
+
+ ULONG PropertyValueOffset;
+
+} PROPERTY_TABLE_ENTRY, *PPROPERTY_TABLE_ENTRY;
+
+
+typedef struct _PROPERTY_ID_TABLE {
+
+ //
+ // Number of entries that are currently in the table
+ //
+
+ ULONG PropertyCount;
+
+ //
+ // Maximum number of entries that the table could contain
+ //
+
+ ULONG MaximumPropertyCount;
+
+ //
+ // Beginning of the table itself
+ //
+
+ PROPERTY_TABLE_ENTRY Entry[1];
+
+} PROPERTY_ID_TABLE, *PPROPERTY_ID_TABLE;
+
+typedef const PROPERTY_ID_TABLE *PCPROPERTY_ID_TABLE;
+
+#define PIT_PROPERTY_DELTA 0x10
+
+#define PROPERTY_ID_TABLE_SIZE(c) \
+ (VARIABLE_STRUCTURE_SIZE( PROPERTY_ID_TABLE, PROPERTY_TABLE_ENTRY, c ))
+#define PROPERTY_ID_ENTRY(p,i) \
+ ((p)->Entry[i])
+
+
+//
+// Following the PropertyIdTable in the stream is the PropertyValueHeap
+//
+// The PropertyValueHeap is a boundary-tagged heap. The contents of each
+// heap element contains the Length of the element, PropertyId of the element,
+// the unicode string name, if one has been assigned, and the serialized property
+// value of the property.
+//
+// The length of the element may be larger than the data contained within it. This
+// enables replacement of long values with shorter ones without forcing
+// reallocation. When reallocation must take place, the existing heap item is
+// marked with an invalid property Id and a new item is allocated at the end of the
+// heap.
+//
+// Over time, this may result in unused space within the heap. When writing a
+// property set for the first time, the total amount of free space is calculated
+// and stored in the SCB. If that amount is either > 4K or >20% of the size of the
+// stream, a compaction is done.
+//
+// The serialized format of property values is dictated by OLE. This results in a
+// common set of source to manipulate the serialized formats.
+//
+
+typedef struct _PROPERTY_HEAP_ENTRY {
+
+ //
+ // Length of this value in bytes
+ //
+
+ ULONG PropertyValueLength;
+
+ //
+ // Property Id for this heap item. This is used for updating the Property
+ // Table during compaction.
+ //
+
+ ULONG PropertyId;
+
+ //
+ // Length in bytes of the string name. If zero, then no name
+ // is assigned.
+ //
+
+ USHORT PropertyNameLength;
+
+ //
+ // Name, if present
+ //
+
+ WCHAR PropertyName[1];
+
+ //
+ // Following the name, on a DWORD boundary is the SERIALIZEDPROPERTYVALUE.
+ //
+
+} PROPERTY_HEAP_ENTRY, *PPROPERTY_HEAP_ENTRY;
+
+#define PROPERTY_HEAP_ENTRY_SIZE(n,v) \
+ (LongAlign( sizeof( PROPERTY_HEAP_ENTRY ) + (n)) + (v))
+#define PROPERTY_HEAP_ENTRY_VALUE(p) \
+ ((SERIALIZEDPROPERTYVALUE *) LongAlign( Add2Ptr( &(p)->PropertyName[0], (p)->PropertyNameLength )))
+#define PROPERTY_HEAP_ENTRY_VALUE_LENGTH(p) \
+ ((p)->PropertyValueLength - PtrOffset( (p), PROPERTY_HEAP_ENTRY_VALUE( p )))
+#define IS_INDIRECT_VALUE(p) \
+ (IsIndirectVarType( PROPERTY_HEAP_ENTRY_VALUE( (p) )->dwType ))
+
+
+
+//
+// The heap has a header as well, that contains the total size of the heap
+//
+
+typedef struct _PROPERTY_HEAP_HEADER {
+
+ //
+ // Length of the heap, including this structure, in bytes. This must
+ // never span beyond the end of data in the stream.
+ //
+
+ ULONG PropertyHeapLength;
+
+ //
+ // First PropertyHeapEntry
+ //
+
+ PROPERTY_HEAP_ENTRY PropertyHeapEntry[1];
+
+} PROPERTY_HEAP_HEADER, *PPROPERTY_HEAP_HEADER;
+typedef const PROPERTY_HEAP_HEADER *PCPROPERTY_HEAP_HEADER;
+
+#define PROPERTY_HEAP_HEADER_SIZE \
+ (sizeof( PROPERTY_HEAP_HEADER ) - sizeof( PROPERTY_HEAP_ENTRY ))
+
+#define PHH_INITIAL_SIZE 0x80
+
+#define GET_HEAP_ENTRY(phh,off) \
+ ((PPROPERTY_HEAP_ENTRY) Add2Ptr( (phh), (off) ))
+#define FIRST_HEAP_ENTRY(phh) \
+ (&(phh)->PropertyHeapEntry[0])
+#define NEXT_HEAP_ENTRY(pvh) \
+ ((PPROPERTY_HEAP_ENTRY) Add2Ptr( (pvh), (pvh)->PropertyValueLength ))
+#define IS_LAST_HEAP_ENTRY(phh,pvh) \
+ ((PCHAR)(pvh) >= (PCHAR)(phh) + (phh)->PropertyHeapLength)
+
+
+//
+// Debug levels for printing
+//
+
+#define DEBUG_TRACE_PROP_FSCTL 0x00000001
+#define DEBUG_TRACE_READ_PROPERTY 0x00000002
+#define DEBUG_TRACE_WRITE_PROPERTY 0x00000004
+
+
+
+//
+// Runtime structures.
+//
+
+//
+// PROPERTY_INFO is a structure built out of the input, either from
+// PROPERTY_SPECIFIERS or PROPERTY_IDS.
+//
+
+typedef struct _PROPERTY_INFO_ENTRY {
+ PPROPERTY_HEAP_ENTRY Heap;
+ PROPID Id;
+} PROPERTY_INFO_ENTRY;
+
+typedef struct _PROPERTY_INFO {
+ ULONG Count;
+ ULONG TotalIdsSize;
+ ULONG TotalValuesSize;
+ ULONG TotalNamesSize;
+ ULONG TotalIndirectSize;
+ ULONG IndirectCount;
+ PROPERTY_INFO_ENTRY Entries[1];
+} PROPERTY_INFO, *PPROPERTY_INFO;
+
+#define PROPERTY_INFO_SIZE(c) \
+ (VARIABLE_STRUCTURE_SIZE( PROPERTY_INFO, PROPERTY_INFO_ENTRY, c ))
+
+#define PROPERTY_INFO_HEAP_ENTRY(p,i) \
+ ((p)->Entries[(i)].Heap)
+#define PROPERTY_INFO_ID(p,i) \
+ ((p)->Entries[(i)].Id)
+
+
+//
+// PROPERTY_CONTEXT is used to pass a large group of related parameters around.
+//
+
+typedef struct _PROPERTY_CONTEXT {
+ PIRP_CONTEXT IrpContext;
+ OBJECT_HANDLE Object;
+ ATTRIBUTE_HANDLE Attribute;
+ MAP_HANDLE Map;
+ PPROPERTY_SET_HEADER Header;
+ PPROPERTY_ID_TABLE IdTable;
+ PPROPERTY_HEAP_HEADER HeapHeader;
+ PPROPERTY_INFO Info;
+} PROPERTY_CONTEXT, *PPROPERTY_CONTEXT;
+
+#define InitializePropertyContext(C,I,O,A) \
+ { \
+ (C)->IrpContext = (I); \
+ (C)->Object = (O); \
+ (C)->Attribute = (A); \
+ NtOfsInitializeMapHandle( &(C)->Map ); \
+ DebugDoit( (C)->Header = NULL ); \
+ DebugDoit( (C)->IdTable = NULL ); \
+ DebugDoit( (C)->HeapHeader = NULL ); \
+ DebugDoit( (C)->Info = NULL ); \
+ }
+
+#define MapPropertyContext(C) \
+ (NtOfsMapAttribute( \
+ (C)->IrpContext, \
+ (C)->Attribute, \
+ Views0, \
+ (ULONG)(C)->Attribute->Header.FileSize.QuadPart, \
+ &(C)->Header, \
+ &(C)->Map ), \
+ SetPropertyContextPointersFromMap(C))
+
+#define SetPropertyContextPointersFromMap(C) \
+ ((C)->IdTable = PROPERTY_ID_TABLE( (C)->Header ), \
+ (C)->HeapHeader = PROPERTY_HEAP_HEADER( (C)->Header ))
+
+#define CleanupPropertyContext(C) \
+ NtOfsReleaseMap( (C)->IrpContext, &(C)->Map )
+
+#define ContextOffset(C,P) \
+ (PtrOffset( (C)->Map.Buffer, (P) ))
+#define HeapOffset(C,P) \
+ (PtrOffset( (C)->HeapHeader, (P) ))
+
+
+//
+// Default not-found property value header
+//
+
+typedef struct _NOT_FOUND_PROPERTY {
+ //
+ // BEGINNING OF PROPERY_VALUE_HEADER
+ //
+
+ ULONG PropertyValueLength;
+ ULONG PropertyId;
+ USHORT PropertyNameLength;
+ // NO NAME
+ USHORT PadToDWord;
+
+ //
+ // BEGINNING OF SERIALIZED VALUE
+ //
+
+ DWORD dwType;
+} NOT_FOUND_PROPERTY;
+
+extern NOT_FOUND_PROPERTY DefaultEmptyProperty;
+
+#define EMPTY_PROPERTY ((PPROPERTY_HEAP_ENTRY) &DefaultEmptyProperty)
+
+extern LONGLONG Views0;
+
+
+//
+// Function prototypes
+//
+
+//
+// check.c
+//
+
+VOID
+CheckPropertySet (
+ IN PPROPERTY_CONTEXT Context
+ );
+
+VOID
+DumpPropertyData (
+ IN PPROPERTY_CONTEXT Context
+ );
+
+
+//
+// heap.c
+//
+
+ULONG
+FindStringInHeap (
+ IN PPROPERTY_CONTEXT Context,
+ IN PCOUNTED_STRING Name
+ );
+
+VOID
+SetValueInHeap(
+ IN PPROPERTY_CONTEXT Context,
+ IN PPROPERTY_HEAP_ENTRY HeapEntry,
+ IN PROPID Id,
+ IN USHORT NameLength,
+ IN PWCHAR Name,
+ IN ULONG ValueLength,
+ IN SERIALIZEDPROPERTYVALUE *Value
+ );
+
+ULONG
+AddValueToHeap(
+ IN PPROPERTY_CONTEXT Context,
+ IN PROPID Id,
+ IN ULONG Length,
+ IN USHORT NameLength,
+ IN PWCHAR Name OPTIONAL,
+ IN ULONG ValueLength,
+ IN SERIALIZEDPROPERTYVALUE *Value
+ );
+
+VOID
+DeleteFromHeap(
+ IN PPROPERTY_CONTEXT Context,
+ IN PPROPERTY_HEAP_ENTRY HeapEntry
+ );
+
+ULONG
+ChangeHeap (
+ IN PPROPERTY_CONTEXT Context,
+ IN ULONG HeapEntryOffset,
+ IN PROPID Id,
+ IN USHORT NameLength,
+ IN PWCHAR Name,
+ IN ULONG ValueLength,
+ IN SERIALIZEDPROPERTYVALUE *Value
+ );
+
+
+//
+// initprop.c
+//
+
+VOID
+InitializePropertyData (
+ IN PPROPERTY_CONTEXT Context
+ );
+
+
+//
+// readprop.c
+//
+
+PPROPERTY_INFO
+BuildPropertyInfoFromPropSpec (
+ IN PPROPERTY_CONTEXT Context,
+ IN PPROPERTY_SPECIFICATIONS Specs,
+ IN PVOID InBufferEnd,
+ IN PROPID NextId
+ );
+
+PPROPERTY_INFO
+BuildPropertyInfoFromIds (
+ IN PPROPERTY_CONTEXT Context,
+ IN PPROPERTY_IDS Ids
+ );
+
+PVOID
+BuildPropertyIds (
+ IN PPROPERTY_INFO Info,
+ OUT PVOID OutBuffer
+ );
+
+VOID
+ReadPropertyData (
+ IN PPROPERTY_CONTEXT Context,
+ IN ULONG InBufferLength,
+ IN PVOID InBuffer,
+ OUT PULONG OutBufferLength,
+ OUT PVOID OutBuffer
+ );
+
+
+//
+// table.c
+//
+
+ULONG
+BinarySearchIdTable (
+ IN PPROPERTY_CONTEXT Context,
+ IN PROPID PropertyId
+ );
+
+ULONG
+FindIdInTable (
+ IN PPROPERTY_CONTEXT Context,
+ IN PROPID PropertyId
+ );
+
+PROPID
+FindFreeIdInTable (
+ IN PPROPERTY_CONTEXT Context,
+ IN PROPID Id
+ );
+
+VOID
+ChangeTable (
+ IN PPROPERTY_CONTEXT Context,
+ IN PROPID Id,
+ IN ULONG Offset
+ );
+
+
+//
+// writprop.c
+//
+
+VOID
+WritePropertyData (
+ IN PPROPERTY_CONTEXT Context,
+ IN ULONG InBufferLength,
+ IN PVOID InBuffer,
+ OUT PULONG OutBufferLength,
+ OUT PVOID OutBuffer
+ );
+