896 lines
29 KiB
C
896 lines
29 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
HpfsBoot.h
|
||
|
||
Abstract:
|
||
|
||
This module defines globally used procedure and data structures used
|
||
by Hpfs boot.
|
||
|
||
Author:
|
||
|
||
Gary Kimura [GaryKi] 19-Jul-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#ifndef _HPFSBOOT_
|
||
#define _HPFSBOOT_
|
||
|
||
typedef ULONG LBN;
|
||
typedef LBN *PLBN;
|
||
|
||
typedef ULONG VBN;
|
||
typedef VBN *PVBN;
|
||
|
||
|
||
//
|
||
// The following structure is a context block used by the exported
|
||
// procedures in the Hpfs boot package. The context contains our cached
|
||
// part of the boot mcb structure. The max number must not be smaller than
|
||
// the maximum number of leafs possible in a pinball allocation sector plus
|
||
// one.
|
||
//
|
||
|
||
#define MAXIMUM_NUMBER_OF_BOOT_MCB (41)
|
||
|
||
typedef struct _HPFS_BOOT_MCB {
|
||
|
||
//
|
||
// The following fields indicate the number of entries in use by
|
||
// the boot mcb. and the boot mcb itself. The boot mcb is
|
||
// just a collection of vbn - lbn pairs. The last InUse entry
|
||
// Lbn's value is ignored, because it is only used to give the
|
||
// length of the previous run.
|
||
//
|
||
|
||
ULONG InUse;
|
||
|
||
VBN Vbn[ MAXIMUM_NUMBER_OF_BOOT_MCB ];
|
||
LBN Lbn[ MAXIMUM_NUMBER_OF_BOOT_MCB ];
|
||
|
||
} HPFS_BOOT_MCB, *PHPFS_BOOT_MCB;
|
||
|
||
typedef struct _HPFS_STRUCTURE_CONTEXT {
|
||
|
||
//
|
||
// The following field contains the fnode lbn of the file
|
||
//
|
||
|
||
LBN Fnode;
|
||
|
||
//
|
||
// The following field contains the cached mcb
|
||
//
|
||
|
||
HPFS_BOOT_MCB BootMcb;
|
||
|
||
} HPFS_STRUCTURE_CONTEXT, *PHPFS_STRUCTURE_CONTEXT;
|
||
|
||
//
|
||
// Define Hpfs file context structure.
|
||
//
|
||
|
||
typedef struct _HPFS_FILE_CONTEXT {
|
||
|
||
//
|
||
// The following field contains the size of the file, in bytes.
|
||
//
|
||
|
||
ULONG FileSize;
|
||
|
||
} HPFS_FILE_CONTEXT, *PHPFS_FILE_CONTEXT;
|
||
|
||
//
|
||
// HPFS file system structures
|
||
//
|
||
typedef ULONG SIGNATURE;
|
||
typedef SIGNATURE *PSIGNATURE;
|
||
|
||
typedef ULONG PINBALL_TIME;
|
||
typedef PINBALL_TIME *PPINBALL_TIME;
|
||
//
|
||
// There are only three sectors on the disk that have fixed locations. They
|
||
// are the boot sector, the super sector, and the spare sector.
|
||
//
|
||
|
||
#define BOOT_SECTOR_LBN (0)
|
||
#define SUPER_SECTOR_LBN (16)
|
||
#define SPARE_SECTOR_LBN (17)
|
||
|
||
typedef struct _SUPER_SECTOR {
|
||
|
||
//
|
||
// The Super Sector starts with a double signature.
|
||
//
|
||
|
||
SIGNATURE Signature1; // offset = 0x000 0
|
||
SIGNATURE Signature2; // offset = 0x004 4
|
||
|
||
//
|
||
// The version and functional version describe the version of
|
||
// the on-disk file system structures and the oldest version of the
|
||
// file system that can understand this disk.
|
||
//
|
||
|
||
UCHAR Version; // offset = 0x008 8
|
||
UCHAR FunctionalVersion; // offset = 0x009 9
|
||
USHORT Unused1; // offset = 0x00A 10
|
||
|
||
//
|
||
// This field denotes the sector containing the FNODE for the root
|
||
// directory for the volume.
|
||
//
|
||
|
||
LBN RootDirectoryFnode; // offset = 0x00C 12
|
||
|
||
//
|
||
// The follow two fields indicate the number of total sectors on the
|
||
// volume (good and bad), and the number of bad sectors on the volume.
|
||
//
|
||
|
||
ULONG NumberOfSectors; // offset = 0x010 16
|
||
ULONG NumberOfBadSectors; // offset = 0x014 20
|
||
|
||
//
|
||
// This field denotes the sector containing the first level of the
|
||
// volumes bitmap table.
|
||
//
|
||
|
||
LBN BitMapIndirect; // offset = 0x018 24
|
||
ULONG Unused2; // offset = 0x01C 28
|
||
|
||
//
|
||
// This field denotes the sector containing the first bad sector disk
|
||
// buffer for the volume.
|
||
//
|
||
|
||
LBN BadSectorList; // offset = 0x020 32
|
||
ULONG Unused3; // offset = 0x024 36
|
||
|
||
//
|
||
// The following two dates are the time of the last execution of
|
||
// chkdsk and disk optimize on the volume.
|
||
//
|
||
|
||
PINBALL_TIME ChkdskDate; // offset = 0x028 40
|
||
PINBALL_TIME DiskOptimizeDate; // offset = 0x02C 44
|
||
|
||
//
|
||
// The following four fields describe the directory disk buffer pool.
|
||
// It is a contiguous run on of sectors on the disk set aside for
|
||
// holding directory disk buffers. PoolSize is the total number of
|
||
// sectors in the pool. First and Last Sector denote the boundaries
|
||
// of the pool, and BitMap denotes the start of a small bitmap used to
|
||
// describe the directory disk buffer pool's current allocation. The
|
||
// bitmap is 4 contiguous sectors in size, and each bit in the map
|
||
// corresponds to 1 Directory Disk Buffer (i.e., 4 Sectors worth)
|
||
//
|
||
|
||
ULONG DirDiskBufferPoolSize; // offset = 0x030 48
|
||
LBN DirDiskBufferPoolFirstSector; // offset = 0x034 52
|
||
LBN DirDiskBufferPoolLastSector; // offset = 0x038 56
|
||
LBN DirDiskBufferPoolBitMap; // offset = 0x03C 60
|
||
|
||
//
|
||
// The following field contains the name of the volume
|
||
//
|
||
|
||
UCHAR VolumeName[32]; // offset = 0x040 64
|
||
|
||
//
|
||
// The following field denotes the start of the Small ID (SID) table
|
||
// which is used to store the Small ID to GUID mappings used on the
|
||
// volume. The SID table is 8 contiguous sectors in size.
|
||
//
|
||
|
||
LBN SidTable; // offset = 0x060 96
|
||
UCHAR Unused4[512-100]; // offset = 0x064 100
|
||
|
||
} SUPER_SECTOR; // sizeof = 0x200 512
|
||
typedef SUPER_SECTOR *PSUPER_SECTOR;
|
||
|
||
//
|
||
// Super Sector signatures
|
||
//
|
||
|
||
#define SUPER_SECTOR_SIGNATURE1 (0xf995e849)
|
||
#define SUPER_SECTOR_SIGNATURE2 (0xfa53e9c5)
|
||
|
||
//
|
||
// Super Sector versions
|
||
//
|
||
|
||
#define SUPER_SECTOR_VERSION (0x02)
|
||
#define SUPER_SECTOR_FUNC_VERSION (0x02)
|
||
|
||
typedef struct _SPARE_SECTOR {
|
||
|
||
//
|
||
// The Spare Sector starts with a double signature.
|
||
//
|
||
|
||
SIGNATURE Signature1; // offset = 0x000 0
|
||
SIGNATURE Signature2; // offset = 0x004 4
|
||
|
||
//
|
||
// The flags field describe how "clean" the volume is.
|
||
//
|
||
|
||
UCHAR Flags; // offset = 0x008 8
|
||
UCHAR Unused1[3]; // offset = 0x009 9
|
||
|
||
//
|
||
// The following three fields describe the hotfix structure for the
|
||
// volume. The List field is denotes the disk buffer used to store
|
||
// the hotfix table. The InUse describes how many hotfixes are
|
||
// currently being used, and MaxSize is the total number of hotfixes
|
||
// that can be in use at any one time.
|
||
//
|
||
|
||
LBN HotFixList; // offset = 0x00C 12
|
||
ULONG HotFixInUse; // offset = 0x010 16
|
||
ULONG HotFixMaxSize; // offset = 0x014 20
|
||
|
||
//
|
||
// The following two fields describe the "emergency" pool of spare
|
||
// directory disk buffers. Free describes how many spare directory
|
||
// disk buffers are currently available for use. MaxSize is the total
|
||
// number of spare directory disk buffers available. The actual location
|
||
// of the spare directory disk buffers is denoted in the table at the
|
||
// end of the spare sector (i.e., field SpareDirDiskBuffer).
|
||
//
|
||
|
||
ULONG SpareDirDiskBufferAvailable; // offset = 0x018 24
|
||
ULONG SpareDirDiskBufferMaxSize; // offset = 0x01C 28
|
||
|
||
//
|
||
// The following two fields describe the code page information used
|
||
// on the volume. The InfoSector field is the sector of the beginning
|
||
// Code Page Information Sector, and the InUse field is the total number
|
||
// of code pages currently in use on the volume.
|
||
//
|
||
|
||
LBN CodePageInfoSector; // offset = 0x020 32
|
||
ULONG CodePageInUse; // offset = 0x024 36
|
||
ULONG Unused2[17]; // offset = 0x028 40
|
||
|
||
//
|
||
// The following field is an array of LBN's for the spare directory
|
||
// disk buffers that are for "emergency" use.
|
||
//
|
||
|
||
LBN SpareDirDiskBuffer[101]; // offset = 0x06C 108
|
||
|
||
} SPARE_SECTOR; // sizeof = 0x200 512
|
||
typedef SPARE_SECTOR *PSPARE_SECTOR;
|
||
|
||
//
|
||
// Spare Sector signatures
|
||
//
|
||
|
||
#define SPARE_SECTOR_SIGNATURE1 (0xf9911849)
|
||
#define SPARE_SECTOR_SIGNATURE2 (0xfa5229c5)
|
||
|
||
|
||
//
|
||
// The on-disk allocation structure is defined using B-Trees. For every
|
||
// B-Tree block there is an Allocation Header, followed by a list of
|
||
// either Allocation Leafs or Allocation Nodes. This structure will either
|
||
// appear in an FNODE or in an AllocationSector.
|
||
//
|
||
// The allocation header (called Allocation Block in earlier implementations)
|
||
// describes a B-tree block.
|
||
//
|
||
|
||
typedef struct _ALLOCATION_HEADER {
|
||
|
||
//
|
||
// The following flag describes the state of the B-tree block (e.g.,
|
||
// indicates if the block is a leaf or an internal node.
|
||
//
|
||
|
||
UCHAR Flags; // offset = 0x000 0
|
||
UCHAR Unused[3]; // offset = 0x001 1
|
||
|
||
//
|
||
// The following two fields denote the number of free records in the
|
||
// B-Tree block, and the number of records that are currently in use
|
||
//
|
||
|
||
UCHAR FreeCount; // offset = 0x004 4
|
||
UCHAR OccupiedCount; // offset = 0x005 5
|
||
|
||
//
|
||
// The next field contains the offset (in bytes) from the beginning
|
||
// of the allocation header to the first free byte in the B-Tree block
|
||
//
|
||
|
||
USHORT FirstFreeByte; // offset = 0x006 6
|
||
|
||
} ALLOCATION_HEADER; // sizeof = 0x008 8
|
||
typedef ALLOCATION_HEADER *PALLOCATION_HEADER;
|
||
|
||
//
|
||
// Allocation header flags
|
||
//
|
||
// NODE - if set this indicates that the B-Tree block contains internal
|
||
// nodes and not leaf entries.
|
||
//
|
||
// BINARY_SEARCH - if set this suggest that a binary search should be used
|
||
// to search the B-Tree block.
|
||
//
|
||
// FNODE_PARENT - if set this indicates that the sector which is the
|
||
// parent of the sector with this header (not this sector), is an
|
||
// FNODE.
|
||
//
|
||
|
||
#define ALLOCATION_BLOCK_NODE (0x80)
|
||
#define ALLOCATION_BLOCK_BINARY (0x40)
|
||
#define ALLOCATION_BLOCK_FNODE_PARENT (0x20)
|
||
|
||
//
|
||
// Immediately following an allocation header are one or more allocation nodes
|
||
// of allocation leafs.
|
||
//
|
||
|
||
typedef struct _ALLOCATION_NODE {
|
||
|
||
//
|
||
// All children of this allocation node will have values less than
|
||
// the following VBN field.
|
||
//
|
||
|
||
VBN Vbn; // offset = 0x000 0
|
||
|
||
//
|
||
// This is the LBN of the allocation sector refered to by this node
|
||
//
|
||
|
||
LBN Lbn; // offset = 0x004 4
|
||
|
||
} ALLOCATION_NODE; // sizeof = 0x008 8
|
||
typedef ALLOCATION_NODE *PALLOCATION_NODE;
|
||
|
||
typedef struct _ALLOCATION_LEAF {
|
||
|
||
//
|
||
// The following field has the starting VBN for this run
|
||
//
|
||
|
||
VBN Vbn; // offset = 0x000 0
|
||
|
||
//
|
||
// This is the length of the run in sectors
|
||
//
|
||
|
||
ULONG Length; // offset = 0x004 4
|
||
|
||
//
|
||
// This is the starting LBN of the run
|
||
//
|
||
|
||
LBN Lbn; // offset = 0x008 8
|
||
|
||
} ALLOCATION_LEAF; // sizeof = 0x00C 12
|
||
typedef ALLOCATION_LEAF *PALLOCATION_LEAF;
|
||
|
||
//
|
||
// An allocation sector is an on-disk structure that contains allocation
|
||
// information. It contains some bookkeeping information, an allocation
|
||
// header and then an array of either allocation leafs or allocation nodes.
|
||
//
|
||
// AllocationSector
|
||
// +-------------------+
|
||
// | bookkeeping |
|
||
// +- - - - - - - - - -+
|
||
// | Allocation Header |
|
||
// +- - - - - - - - - -+
|
||
// | Allocation Leafs |
|
||
// | or |
|
||
// | Allocation Nodes |
|
||
// +-------------------+
|
||
//
|
||
// where the number of allocation leafs that can be stored in a sector is
|
||
// 40 and the number of nodes is 60.
|
||
//
|
||
|
||
#define ALLOCATION_NODES_PER_SECTOR (60)
|
||
#define ALLOCATION_LEAFS_PER_SECTOR (40)
|
||
|
||
typedef struct _ALLOCATION_SECTOR {
|
||
|
||
//
|
||
// The allocation sector starts off with a signature field
|
||
//
|
||
|
||
SIGNATURE Signature; // offset = 0x000 0
|
||
|
||
//
|
||
// This following two fields contains the LBN of this allocation
|
||
// sector itself, and the LBN of the parent of this sector (the
|
||
// parent is either an FNODE or another allocation sector)
|
||
//
|
||
|
||
LBN Lbn; // offset = 0x004 4
|
||
LBN ParentLbn; // offset = 0x008 8
|
||
|
||
//
|
||
// The allocation header for the sector
|
||
//
|
||
|
||
ALLOCATION_HEADER AllocationHeader; // offset = 0x00C 12
|
||
|
||
//
|
||
// The remainder of the sector is either an array of allocation leafs
|
||
// of allocation nodes
|
||
//
|
||
|
||
union { // offset = 0x014 20
|
||
ALLOCATION_NODE Node[ ALLOCATION_NODES_PER_SECTOR ];
|
||
ALLOCATION_LEAF Leaf[ ALLOCATION_LEAFS_PER_SECTOR ];
|
||
} Allocation;
|
||
|
||
UCHAR Unused[12]; // offset = 0x1F4 500
|
||
|
||
} ALLOCATION_SECTOR; // sizeof = 0x200 512
|
||
typedef ALLOCATION_SECTOR *PALLOCATION_SECTOR;
|
||
|
||
//
|
||
// The allocation sector signature
|
||
//
|
||
|
||
#define ALLOCATION_SECTOR_SIGNATURE (0x37e40aae)
|
||
|
||
//
|
||
// The on-disk FNODE structure is used to describe both files and directories
|
||
// It contains some fixed data information, the EA and ACL lookup information,
|
||
// allocation information and then a free space for storing some EAs and
|
||
// ACLs that fit in the sector
|
||
//
|
||
|
||
#define ALLOCATION_NODES_PER_FNODE (12)
|
||
#define ALLOCATION_LEAFS_PER_FNODE (8)
|
||
|
||
typedef struct _FNODE_SECTOR {
|
||
|
||
//
|
||
// The sector starts with a signature field
|
||
//
|
||
|
||
SIGNATURE Signature; // offset = 0x000 0
|
||
|
||
//
|
||
// The following fields was for history tracking, but in NT Pinball
|
||
// doesn't need this information.
|
||
//
|
||
|
||
ULONG Unused1[2]; // offset = 0x004 4
|
||
|
||
//
|
||
// The following two fields contain the file name length, and the first
|
||
// 15 bytes of the filename, as stored in the dirent that references
|
||
// this fnode. For the root directory theses values are all zeros.
|
||
//
|
||
|
||
UCHAR FileNameLength; // offset = 0x00C 12
|
||
UCHAR FileName[15]; // offset = 0x00D 13
|
||
|
||
//
|
||
// The following field denotes the parent directory's FNODE
|
||
//
|
||
|
||
LBN ParentFnode; // offset = 0x01C 28
|
||
|
||
//
|
||
// The following four fields describe the ACL for the file/directory.
|
||
//
|
||
// AclDiskAllocationLength holds the number of bytes in the ACL that
|
||
// are stored outside of this FNODE. If this value is not zero
|
||
// then AclFnodeLength must be equal to zero.
|
||
//
|
||
// AclLbn points to the first sector of the data run or the allocation
|
||
// sector containing describing the ACL. AclFlags indicates if
|
||
// it is a data run or an allocation sector. AclLbn is only used
|
||
// if AclDiskAllocationLength is not zero.
|
||
//
|
||
// AclFnodeLength holds the number of bytes in the ACL that are
|
||
// stored within this FNODE. If value is not zero then
|
||
// AclDiskAllocationLength must be equal to zero. The ACL, if stored
|
||
// in the FNODE, is located at AclEaFnodeBuffer in this FNODE sector.
|
||
//
|
||
// AclFlags if the data is outside the FNODE this flag indicates whether
|
||
// ACL is stored in a single data run (AclFlags == 0) or via an
|
||
// allocation sector (AclFlags != 0). AclFlags is only used if
|
||
// AclDiskAllocationLength is not zero.
|
||
//
|
||
|
||
ULONG AclDiskAllocationLength; // offset = 0x020 32
|
||
LBN AclLbn; // offset = 0x024 36
|
||
USHORT AclFnodeLength; // offset = 0x028 40
|
||
UCHAR AclFlags; // offset = 0x02A 42
|
||
|
||
//
|
||
// The following field was used for the number of valid history
|
||
// bits but we don't need this field of NT Pinball
|
||
//
|
||
|
||
UCHAR Unused2; // offset = 0x02B 43
|
||
|
||
//
|
||
// The following four fields describe the EA for the file/directory.
|
||
//
|
||
// EaDiskAllocationLength holds the number of bytes in the EA that
|
||
// are stored outside of this FNODE. If this value is not zero
|
||
// then EaFnodeLength must be equal to zero.
|
||
//
|
||
// EaLbn points to the first sector of the data run or the allocation
|
||
// sector containing describing the EA. EaFlags indicates if
|
||
// it is a data run or an allocation sector. EaLbn is only used
|
||
// if EaDiskAllocationLength is not zero.
|
||
//
|
||
// EaFnodeLength holds the number of bytes in the EA that are
|
||
// stored within this FNODE. If value is not zero then
|
||
// EaDiskAllocationLength must be equal to zero. The EA, if stored
|
||
// in the FNODE, is located immediately after the ACL stored in the
|
||
// AclEaFnodeBuffer.
|
||
//
|
||
// EaFlags if the data is outside the FNODE this flag indicates whether
|
||
// EA is stored in a single data run (EaFlags == 0) or via an
|
||
// allocation sector (EaFlags != 0). EaFlags is only used if
|
||
// EaDiskAllocationLength is not zero.
|
||
//
|
||
|
||
ULONG EaDiskAllocationLength; // offset = 0x02C 44
|
||
LBN EaLbn; // offset = 0x030 48
|
||
USHORT EaFnodeLength; // offset = 0x034 52
|
||
UCHAR EaFlags; // offset = 0x036 54
|
||
|
||
//
|
||
// The following byte contains the FNODE flags
|
||
//
|
||
|
||
UCHAR Flags; // offset = 0x037 55
|
||
|
||
//
|
||
// The following two fields describe the top level allocation for
|
||
// this file/directory
|
||
//
|
||
|
||
ALLOCATION_HEADER AllocationHeader; // offset = 0x038 56
|
||
|
||
union { // offset = 0x040 64
|
||
ALLOCATION_NODE Node[ ALLOCATION_NODES_PER_FNODE ];
|
||
ALLOCATION_LEAF Leaf[ ALLOCATION_LEAFS_PER_FNODE ];
|
||
} Allocation;
|
||
|
||
//
|
||
// The following field contains the valid length of the file. The size
|
||
// of the file is stored in the dirent. The difference between these two
|
||
// values is that the file size is the actual size allocated and visible
|
||
// to the user. The Valid length is the number of bytes that have
|
||
// had their data zeroed out or modified. (i.e., if a read request
|
||
// is greater than valid length but less than file size then the file
|
||
// system must first zero out the data in the file up to and including
|
||
// data being read.
|
||
//
|
||
|
||
ULONG ValidDataLength; // offset = 0x0A0 160
|
||
|
||
//
|
||
// The following field contains the number of EAs in this file that have
|
||
// the need ea attribute set.
|
||
//
|
||
|
||
ULONG NeedEaCount; // offset = 0x0A4 164
|
||
UCHAR Unused3[16]; // offset = 0x0A8 168
|
||
|
||
//
|
||
// The following field contains the offset, in bytes, from the start of
|
||
// FNODE to the first ACE stored in the FNODE
|
||
//
|
||
|
||
USHORT AclBase; // offset = 0x0B8 184
|
||
UCHAR Unused4[10]; // offset = 0x0BA 186
|
||
|
||
//
|
||
// The following buffer is used to store acl/ea in the FNODE
|
||
//
|
||
|
||
UCHAR AclEaFnodeBuffer[316]; // offset = 0x0C4 196
|
||
|
||
} FNODE_SECTOR; // sizeof = 0x200 512
|
||
typedef FNODE_SECTOR *PFNODE_SECTOR;
|
||
|
||
//
|
||
// The FNODE Sector signature
|
||
//
|
||
|
||
#define FNODE_SECTOR_SIGNATURE (0xf7e40aae)
|
||
|
||
//
|
||
// The on-disk directory disk buffer is used to contain directory entries.
|
||
// It contains a fixed header followed by a collection of one or more
|
||
// dirents. Dirents are variable so size we cannot use a simply C struct
|
||
// declartion for the entire disk buffer.
|
||
//
|
||
|
||
typedef struct _DIRECTORY_DISK_BUFFER {
|
||
|
||
//
|
||
// The disk buffer starts with a signature field
|
||
//
|
||
|
||
SIGNATURE Signature; // offset = 0x000 0
|
||
|
||
//
|
||
// The following field is the offset to the first free byte in this
|
||
// disk buffer
|
||
//
|
||
|
||
ULONG FirstFree; // offset = 0x004 4
|
||
|
||
//
|
||
// The following field is a change count that is kept around for
|
||
// bookkeeping purposes. It is incremented whenever we move any
|
||
// of the entries in this disk buffer. This means for any file if we
|
||
// remember its offset and its change count we will be able to quickly
|
||
// locate the dirent again without needing to search from the top
|
||
// of the directory again. (i.e., only if the remembered change count
|
||
// and the current change count match). For this to work the file system
|
||
// in memory will need to keep track of whenever it removes a Directory
|
||
// Disk Buffer from a directory, and have each saved dirent location
|
||
// keep this Directory change count, the Directory Disk Buffer Change
|
||
// Count, LBN and Offset.
|
||
//
|
||
// In addition we overload the bit in this value to indicate if this
|
||
// is the topmost directory disk buffer for the directory (low order bit
|
||
// = 1) or if it is a lower lever buffer (low order bit = 0).
|
||
//
|
||
|
||
ULONG ChangeCount; // offset = 0x008 8
|
||
|
||
//
|
||
// The following field contains the LBN of either the parent
|
||
// directory disk buffer containing this disk buffer or the FNODE.
|
||
// It is the FNODE if this is a topmost disk buffer and a parent
|
||
// directory disk buffer otherwise.
|
||
//
|
||
|
||
LBN Parent; // offset = 0x00C 12
|
||
|
||
//
|
||
// The following field is the LBN of the sector containing the
|
||
// start of this disk buffer
|
||
//
|
||
|
||
LBN Sector; // offset = 0x010 16
|
||
|
||
//
|
||
// This following buffer contains the dirents stored in this disk buffer
|
||
//
|
||
|
||
UCHAR Dirents[2028]; // offset = 0x014 20
|
||
|
||
} DIRECTORY_DISK_BUFFER; // sizeof = 0x800 2048
|
||
typedef DIRECTORY_DISK_BUFFER *PDIRECTORY_DISK_BUFFER;
|
||
|
||
//
|
||
// Size of Directory Disk Buffer in sectors.
|
||
//
|
||
|
||
#define DIRECTORY_DISK_BUFFER_SECTORS (4)
|
||
|
||
//
|
||
// Directory Disk Buffer Signature
|
||
//
|
||
|
||
#define DIRECTORY_DISK_BUFFER_SIGNATURE (0x77e40aae)
|
||
|
||
typedef struct _PBDIRENT {
|
||
|
||
USHORT DirentSize; // offset = 0x000 0
|
||
UCHAR Flags; // offset = 0x002 2
|
||
UCHAR FatFlags; // offset = 0x003 3
|
||
|
||
LBN Fnode; // offset = 0x004 4
|
||
|
||
PINBALL_TIME LastModificationTime; // offset = 0x008 8
|
||
|
||
ULONG FileSize; // offset = 0x00C 12
|
||
|
||
PINBALL_TIME LastAccessTime; // offset = 0x010 16
|
||
|
||
PINBALL_TIME FnodeCreationTime; // offset = 0x014 20
|
||
|
||
ULONG EaLength; // offset = 0x018 24
|
||
|
||
UCHAR ResidentAceCount; // offset = 0x01C 28
|
||
UCHAR CodePageIndex; // offset = 0x01D 29
|
||
UCHAR FileNameLength; // offset = 0x01E 30
|
||
UCHAR FileName[1]; // offset = 0x01F 31
|
||
|
||
} PBDIRENT; // sizeof = 0x020 32
|
||
typedef PBDIRENT *PPBDIRENT;
|
||
|
||
//
|
||
// Define sizes of .. and End PBDIRENT.
|
||
//
|
||
|
||
#define SIZEOF_DIR_DOTDOT (sizeof(PBDIRENT) + sizeof(LONG))
|
||
#define SIZEOF_DIR_END (sizeof(PBDIRENT))
|
||
#define SIZEOF_DIR_MAXPBDIRENT (sizeof(PBDIRENT) + 256 + \
|
||
(3*sizeof(PINBALL_ACE)) + sizeof(LBN))
|
||
|
||
#define DIRENT_FIRST_ENTRY (0x0001)
|
||
#define DIRENT_ACL (0x0002)
|
||
#define DIRENT_BTREE_POINTER (0x0004)
|
||
#define DIRENT_END (0x0008)
|
||
#define DIRENT_EXPLICIT_ACL (0x0040)
|
||
#define DIRENT_NEED_EA (0x0080)
|
||
#define DIRENT_NEW_NAMING_RULES (0x4000)
|
||
//
|
||
// The following macros are used to help locate dirents within a Directory
|
||
// Disk Buffer. GetFirstDirent returns a pointer to the first dirent entry
|
||
// in the directory disk buffer. GetNextDirent returns a pointer to the
|
||
// next dirent entry in a directory disk buffer, without checking for the
|
||
// end of the Directory Disk Buffer.
|
||
//
|
||
// PDIRENT
|
||
// GetFirstDirent (
|
||
// IN PDIRECTORY_DISK_BUFFER DirectoryDiskBuffer
|
||
// );
|
||
//
|
||
// PDIRENT
|
||
// GetNextDirent (
|
||
// IN PDIRENT Dirent
|
||
// );
|
||
//
|
||
|
||
#define GetFirstDirent(DIR) ( \
|
||
(PDIRENT)&(DIR)->Dirents[0] \
|
||
)
|
||
|
||
//
|
||
// This macro blindly returns a pointer to the next Dirent, without checking
|
||
// for the end of the Directory Disk Buffer, i.e., callers must always check
|
||
// for the End record in the Directory Disk Buffer. If GetNextDirent is
|
||
// called with the End record as input, it will return the next free byte
|
||
// in the buffer.
|
||
//
|
||
|
||
#define GetNextDirent(ENT) ( \
|
||
(PDIRENT)((PUCHAR)(ENT)+(ENT)->DirentSize) \
|
||
)
|
||
//
|
||
// The following macros are used to help retrieve the variable fields
|
||
// within a dirent. GetAceInDirent returns a pointer to the ACE within
|
||
// the dirent corresponding to the supplied index, or NULL if there isn't
|
||
// a corresponding ACE. GetBtreePointerInDirent returns the LBN field of
|
||
// the down B-tree pointer stored in the dirent, or it returns a value of
|
||
// zero if there isn't a down pointer. SetBtreePointerInDirent sets the
|
||
// LBN downpointer field.
|
||
//
|
||
// PPINBALL_ACE
|
||
// GetAceInDirent (
|
||
// IN PDIRENT Dirent,
|
||
// IN ULONG Index // (0, 1, or 2)
|
||
// );
|
||
//
|
||
// LBN
|
||
// GetBtreePointerInDirent (
|
||
// IN PDIRENT Dirent
|
||
// );
|
||
//
|
||
// VOID
|
||
// SetBtreePointerInDirent (
|
||
// IN OUT PDIRENT Dirent,
|
||
// IN LBN Blbn
|
||
// );
|
||
//
|
||
//
|
||
//
|
||
// To return a pointer to an ACE in a dirent we need to check to see if the
|
||
// index is within the resident ace count. The first ace is the address of
|
||
// the first longword after the filename, the second ace is the second long
|
||
// word.
|
||
//
|
||
|
||
#define GetAceInDirent(ENT,I) ( \
|
||
((I) >= 0 && (I) < (ENT)->ResidentAceCount ? \
|
||
(PPINBALL_ACE)( \
|
||
(LONG)LongAlign((ENT)->FileName[(ENT)->FileNameLength]) + \
|
||
(I)*sizeof(PINBALL_ACE) \
|
||
) \
|
||
: \
|
||
NULL \
|
||
) \
|
||
)
|
||
|
||
//
|
||
// To return the Btree pointer we need to first check to see if there
|
||
// is Btree pointer field, otherwise we return NULL. The field, if present,
|
||
// is located 4 bytes back from the end of the dirent.
|
||
//
|
||
|
||
#define GetBtreePointerInDirent(ENT) ( \
|
||
(FlagOn((ENT)->Flags,DIRENT_BTREE_POINTER) ? \
|
||
*(PLBN)(((PUCHAR)(ENT)) + (ENT)->DirentSize - sizeof(LBN)) \
|
||
: \
|
||
0 \
|
||
) \
|
||
)
|
||
|
||
//
|
||
// To set the Btree pointer we assume there is a Btree pointer field.
|
||
// The field is located 4 bytes back from the end of the dirent.
|
||
//
|
||
|
||
#define SetBtreePointerInDirent(ENT,BLBN) ( \
|
||
*(PLBN)(((PUCHAR)(ENT)) + (ENT)->DirentSize - sizeof(LBN)) = (BLBN) \
|
||
)
|
||
|
||
//
|
||
// Define file I/O prototypes.
|
||
//
|
||
|
||
ARC_STATUS
|
||
HpfsClose (
|
||
IN ULONG FileId
|
||
);
|
||
|
||
ARC_STATUS
|
||
HpfsOpen (
|
||
IN CHAR * FIRMWARE_PTR OpenPath,
|
||
IN OPEN_MODE OpenMode,
|
||
OUT ULONG * FIRMWARE_PTR FileId
|
||
);
|
||
|
||
ARC_STATUS
|
||
HpfsRead (
|
||
IN ULONG FileId,
|
||
OUT VOID * FIRMWARE_PTR Buffer,
|
||
IN ULONG Length,
|
||
OUT ULONG * FIRMWARE_PTR Count
|
||
);
|
||
|
||
ARC_STATUS
|
||
HpfsSeek (
|
||
IN ULONG FileId,
|
||
IN LARGE_INTEGER * FIRMWARE_PTR Offset,
|
||
IN SEEK_MODE SeekMode
|
||
);
|
||
|
||
ARC_STATUS
|
||
HpfsWrite (
|
||
IN ULONG FileId,
|
||
IN VOID * FIRMWARE_PTR Buffer,
|
||
IN ULONG Length,
|
||
OUT ULONG * FIRMWARE_PTR Count
|
||
);
|
||
|
||
ARC_STATUS
|
||
HpfsGetFileInformation (
|
||
IN ULONG FileId,
|
||
OUT FILE_INFORMATION * FIRMWARE_PTR Buffer
|
||
);
|
||
|
||
ARC_STATUS
|
||
HpfsSetFileInformation (
|
||
IN ULONG FileId,
|
||
IN ULONG AttributeFlags,
|
||
IN ULONG AttributeMask
|
||
);
|
||
|
||
ARC_STATUS
|
||
HpfsInitialize(
|
||
VOID
|
||
);
|
||
|
||
#endif // _HPFSBOOT_
|