/*++

Copyright (c) 1989-1996  Microsoft Corporation

Module Name:

    ntfsprop.h

Abstract:

    This module contains the structure definitions for nt property Fsctl calls.

Author:

    Mark Zbikowski (MarkZ) 23-April-1996


--*/


#ifndef _NTFSPROP_
#define _NTFSPROP_

//
//  WARNING!  This file requires OBJIDL.H.
//


//
//  VARIABLE_STRUCTURE_SIZE returns the size of a structure S that contains
//  an array of C structures V
//

#define VARIABLE_STRUCTURE_SIZE(S,V,C) ((int)sizeof( S ) + ((C) - 1) * (int)sizeof( V ))

//
//  COUNTED_STRING is length-preceded unicode string.  This does NOT include
//  a trailing L'\0'
//

typedef struct _COUNTED_STRING
{
    USHORT Length;
    WCHAR Text[1];
} COUNTED_STRING, *PCOUNTED_STRING;

#define COUNTED_STRING_SIZE(l)      \
    (sizeof( COUNTED_STRING ) - sizeof ( WCHAR ) + (l))
#define COUNTED_STRING_LENGTH(c)    \
    ((c)->Length)
#define COUNTED_STRING_TEXT(c)      \
    (&(c)->Text[0])

//
//  PROPERTY_SPECIFIER is a serialized form of a PROPSPEC.  Instead of
//  a LPWSTR, there is an offset from the beginning of the
//  PROPERTY_SPECIFICATIONS to a COUNTED_STRING
//
//  #define	PRSPEC_LPWSTR	( 0 )
//  #define	PRSPEC_PROPID	( 1 )

typedef struct _PROPERTY_SPECIFIER
{
    ULONG Variant;                  //  Distinguish the type
    union {                         //  Switch on Variant
        PROPID Id;                  //  Property ID
        ULONG NameOffset;           //  Offset to COUNTED_STRING
    };
} PROPERTY_SPECIFIER, *PPROPERTY_SPECIFIER;


//
//  PROPERTY_SPECIFICATIONS is a serialized form of an array PROPERTY_SPECIFIERs.
//  Immediately following PROPERTY_SPECIFICATIONS on a USHORT boundary are
//  of the name strings.  Each name string is a COUNTED_STRING
//

typedef struct _PROPERTY_SPECIFICATIONS {
    ULONG Length;                   //  Length in bytes of structure and name strings
    ULONG Count;                    //  Count of PROPERTY_SPECIFIERS
    PROPERTY_SPECIFIER Specifiers[1];   //  Array of actual specifiers, length Count
} PROPERTY_SPECIFICATIONS, *PPROPERTY_SPECIFICATIONS;

#define PROPERTY_SPECIFICATIONS_SIZE(c) \
    (VARIABLE_STRUCTURE_SIZE( PROPERTY_SPECIFICATIONS, PROPERTY_SPECIFIER, (c) ))
#define PROPERTY_SPECIFIER_ID(PS,I)      \
    ((PS)->Specifiers[(I)].Id)
#define PROPERTY_SPECIFIER_COUNTED_STRING(PS,I)  \
    ((PCOUNTED_STRING)Add2Ptr( (PS), (PS)->Specifiers[(I)].NameOffset))
#define PROPERTY_SPECIFIER_NAME(PS,I)    \
    (&PROPERTY_SPECIFIER_COUNTED_STRING( PS, I )->Text[0])
#define PROPERTY_SPECIFIER_NAME_LENGTH(PS,I) \
    (PROPERTY_SPECIFIER_COUNTED_STRING( PS, I )->Length)


//
//  PROPERTY_VALUES is a serialized form of an array of SERIALIZEDPROPERTYVALUES.
//  Immediately following the structure are the values, each of which is on a DWORD
//  boundary.  The last PropertyValue (count+1) is used only to help determine the
//  size of the last property value.  The offsets to the values are relative
//  to the address of the PROPERTY_VALUES structure itself.
//

typedef struct _PROPERTY_VALUES {
    ULONG Length;                   //  Length in bytes of structure and values
    ULONG Count;                    //  Count of SERIALIZEDPROPERTYVALUES
    ULONG PropertyValueOffset[1];   //  Array of offsets to actual values, length count + 1
} PROPERTY_VALUES, *PPROPERTY_VALUES;

#define PROPERTY_VALUES_SIZE(c) \
    (VARIABLE_STRUCTURE_SIZE( PROPERTY_VALUES, ULONG, (c) + 1 ))
#define PROPERTY_VALUE_LENGTH(v,i)  \
    ((v)->PropertyValueOffset[(i) + 1] - (v)->PropertyValueOffset[(i)])
#define PROPERTY_VALUE(v,i) \
    ((SERIALIZEDPROPERTYVALUE *) Add2Ptr( (v), (v)->PropertyValueOffset[(i)]))


//
//  PROPERTY_IDS is a serialized form of an array of PROPIDs
//

typedef struct _PROPERTY_IDS {
    ULONG Count;                    //  Count of the number of propids
    PROPID PropertyIds[1];          //  Array of propids, length Count
} PROPERTY_IDS, *PPROPERTY_IDS;

#define PROPERTY_IDS_SIZE(c)    \
    (VARIABLE_STRUCTURE_SIZE( PROPERTY_IDS, PROPID, (c) ))
#define PROPERTY_ID(p,i)        \
    ((p)->PropertyIds[i])


//
//  INDIRECT_PROPERTIES is a serialized form of an array of PROPID/string-value
//  pairs.  Immediately following the structure are the INDIRECT_ENTRIES, each of
//  which is on a WCHAR boundary.
//

typedef struct _INDIRECT_ENTRY {
    PROPID PropertyId;              //  Propid of indirect property
    ULONG IndirectValueOffset;      //  Offset to the string text, L'\0' terminated
} INDIRECT_ENTRY;

typedef struct _INDIRECT_PROPERTIES {
    ULONG Length;                   //  Length in bytes of structure and values
    ULONG Count;                    //  Count of indirect properties being replaced
    INDIRECT_ENTRY Entrys[1];       //  First indirect entry
} INDIRECT_PROPERTIES, *PINDIRECT_PROPERTIES;

#define INDIRECT_PROPERTIES_SIZE(c) \
    (VARIABLE_STRUCTURE_SIZE( INDIRECT_PROPERTIES, INDIRECT_ENTRY, (c) + 1 ))
#define INDIRECT_VALUE_ID(v,i)      \
    ((v)->Entrys[i].PropertyId)
#define INDIRECT_VALUE_LENGTH(v,i)  \
    ((v)->IndirectValueOffset[(i) + 1] - (v)->IndirectValueOffset[(i)])
#define INDIRECT_VALUE(v,i)         \
    ((SERIALIZED_PROPERTY_VALUE *) Add2Ptr( (v), (v)->Entrys[i].IndirectValueOffset))


//
//  PROPERTY_STAT_DATA is a serialized array of STATPROPSTG.  Following the
//  structure are the individual STATPROPSTG instances each of which is on a DWORD
//  boundary.
//

typedef struct _PROPERTY_STAT_DATA {
    ULONG Length;                   //  Length in bytes of structure and values
    ULONG Count;                    //  Count of STATPROPSTG entries that follow
    STATPROPSTG PropertyStat[1];    //  First statpropstg
} PROPERTY_STAT_DATA, *PPROPERTY_STAT_DATA;


//
//  PROPERTY_NAMES is a serialized array of strings's.  Following the structure
//  are the individual strings, each of which is on a WCHAR boundary.  The
//  offsets to the property names are relative to the beginning of the
//  PROPERTY_NAMES structure.  There are count+1 offsets allowing the length
//  of each to be calculated.
//

typedef struct _PROPERTY_NAMES {
    ULONG Length;                   //  Length in bytes of structure and values
    ULONG Count;                    //  Count of strings
    ULONG PropertyNameOffset[1];    //  Array of offsets to property names.
} PROPERTY_NAMES, *PPROPERTY_NAMES;

#define PROPERTY_NAMES_SIZE(c)  \
    (VARIABLE_STRUCTURE_SIZE( PROPERTY_NAMES, ULONG, (c) + 1 ))
#define PROPERTY_NAME_LENGTH(v,i)   \
    ((v)->PropertyNameOffset[(i) + 1] - (v)->PropertyNameOffset[(i)])
#define PROPERTY_NAME(v,i)          \
    ((PWCHAR) Add2Ptr( (v), (v)->PropertyNameOffset[(i)]))


//
//  PROPERTY_READ_CONTROL is the structure used to control all property read
//  operations.  Following the structure on a DWORD boundary is either
//  an instance of PROPERTY_IDS or PROPERTY_SPECIFICATIONS, depending on
//  the operation code.
//
//  On successful output, the data buffer will contain, on DWORD boundaries,
//  in order PROPERTY_VALUES, PROPERTY_IDS, and PROPERTY_NAMES.  Each structure
//  may be absent depending on the setting of the operation code:
//
//  PRC_READ_PROP:   PROPERTY_SPECIFICATIONS => PROPERTY_VALUES
//
//  PRC_READ_NAME:   PROPERTY_IDS => PROPERTY_NAMES
//
//                             / PROPERTY_IDS
//  PRC_READ_ALL:    <empty> =>  PROPERTY_NAMES
//                             \ PROPERTY_VALUES
//
//

typedef enum _READ_CONTROL_OPERATION {
    PRC_READ_PROP = 0,
    PRC_READ_NAME = 1,
    PRC_READ_ALL  = 2,
} READ_CONTROL_OPERATION;

typedef struct _PROPERTY_READ_CONTROL {
    READ_CONTROL_OPERATION Op;
} PROPERTY_READ_CONTROL, *PPROPERTY_READ_CONTROL;


//
//  PROPERTY_WRITE_CONTROL is the structure used to control all property write
//  operations.  Following the structure on a DWORD boundary is either an instance
//  of PROPERTY_IDS or PROPERTY_SPECIFICATIONS (used to control which properties are
//  being changed) and followed by PROPERTY_VALUES and PROPERTY_NAMES.  The
//  presence of these are dependent on the operation code.
//
//  On successful outputs, the data buffer will contain, on DWORD boundaries,
//  in order PROPERTY_IDS and INDIRECT_PROPERTIES.  Each structure may be absent
//  depending on the setting of the operation code:
//
//  PWC_WRITE_PROP:  PROPERTY_SPECIFICATIONS \__/ PROPERTY_IDS
//                   PROPERTY_VALUES         /  \ INDIRECT_PROPERTIES
//
//  PWC_DELETE_PROP: PROPERTY_SPECIFICATIONS => <empty>
//
//  PWC_WRITE_NAME:  PROPERTY_IDS   \__ <empty>
//                   PROPERTY_NAMES /
//
//  PWC_DELETE_NAME: PROPERTY_IDS => <empty>
//
//                   PROPERTY_IDS    \
//  PWC_WRITE_ALL:   PROPERTY_NAMES   => <empty>
//                   PROPERTY_VALUES /

typedef enum _WRITE_CONTROL_OPERATION {
    PWC_WRITE_PROP  = 0,
    PWC_DELETE_PROP = 1,
    PWC_WRITE_NAME  = 2,
    PWC_DELETE_NAME = 3,
    PWC_WRITE_ALL   = 4,
} WRITE_CONTROL_OPERATION;

typedef struct _PROPERTY_WRITE_CONTROL {
    WRITE_CONTROL_OPERATION Op;
    PROPID NextPropertyId;
} PROPERTY_WRITE_CONTROL, *PPROPERTY_WRITE_CONTROL;

#endif  //  _NTFSPROP_
