ext2 import by filip navara with minor editing by arty.

svn path=/branches/ext2/; revision=13009
This commit is contained in:
Art Yerkes 2005-01-13 01:51:33 +00:00
parent b8ed66e011
commit d31a52e423
38 changed files with 20152 additions and 1653 deletions

View file

@ -1,136 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/attr.c
* PURPOSE: Set/Get file attributes support
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <wchar.h>
#include <string.h>
//#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS STDCALL
Ext2SetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT("Ext2SetInformation(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_UNSUCCESSFUL);
}
NTSTATUS STDCALL
Ext2QueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
PIO_STACK_LOCATION Param;
PFILE_OBJECT FileObject;
PDEVICE_EXTENSION DeviceExt;
ULONG Length;
PFILE_BASIC_INFORMATION PFileBasicInformation;
PFILE_STANDARD_INFORMATION PFileStandardInformation;
PFILE_INTERNAL_INFORMATION PFileInternalInformation;
PFILE_EA_INFORMATION PFileEaInformation;
PFILE_ACCESS_INFORMATION PFileAccessInformation;
PFILE_NAME_INFORMATION PFileNameInformation;
PFILE_POSITION_INFORMATION PFilePositionInformation;
PVOID Buffer;
DPRINT("Ext2QueryInformation(DeviceObject %x Irp %x)\n", DeviceObject, Irp);
Param = IoGetCurrentIrpStackLocation(Irp);
FileObject = Param->FileObject;
DeviceExt = DeviceObject->DeviceExtension;
Length = Param->Parameters.QueryFile.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
switch (Param->Parameters.QueryFile.FileInformationClass)
{
case FileDirectoryInformation:
case FileFullDirectoryInformation:
case FileBothDirectoryInformation:
Status = STATUS_NOT_IMPLEMENTED;
break;
case FileBasicInformation:
PFileBasicInformation = (PFILE_BASIC_INFORMATION)Buffer;
memset(PFileBasicInformation, 0, sizeof(FILE_BASIC_INFORMATION));
Status = STATUS_SUCCESS;
break;
case FileStandardInformation:
PFileStandardInformation = (PFILE_STANDARD_INFORMATION)Buffer;
memset(PFileStandardInformation, 0, sizeof(FILE_STANDARD_INFORMATION));
Status = STATUS_SUCCESS;
break;
case FileInternalInformation:
PFileInternalInformation = (PFILE_INTERNAL_INFORMATION)Buffer;
memset(PFileInternalInformation, 0, sizeof(FILE_INTERNAL_INFORMATION));
Status = STATUS_SUCCESS;
break;
case FileEaInformation:
PFileEaInformation = (PFILE_EA_INFORMATION)Buffer;
memset(PFileEaInformation, 0, sizeof(FILE_EA_INFORMATION));
PFileEaInformation->EaSize = 0;
Status = STATUS_SUCCESS;
break;
case FileAccessInformation:
PFileAccessInformation = (PFILE_ACCESS_INFORMATION)Buffer;
memset(PFileAccessInformation, 0, sizeof(FILE_ACCESS_INFORMATION));
PFileAccessInformation->AccessFlags = 0;
Status = STATUS_SUCCESS;
break;
case FileNameInformation:
PFileNameInformation = (PFILE_NAME_INFORMATION)Buffer;
memset(PFileNameInformation, 0, sizeof(FILE_NAME_INFORMATION));
Status = STATUS_SUCCESS;
break;
case FilePositionInformation:
PFilePositionInformation = (PFILE_POSITION_INFORMATION)Buffer;
memcpy(PFilePositionInformation,
&FileObject->CurrentByteOffset,
sizeof(FileObject->CurrentByteOffset));
Status = STATUS_SUCCESS;
break;
case FileRenameInformation:
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
Status = STATUS_NOT_SUPPORTED;
}
Irp->IoStatus.Status = Status;
if (NT_SUCCESS(Status))
Irp->IoStatus.Information =
Param->Parameters.QueryFile.Length - Length;
else
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(Status);
}

View file

@ -1,155 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/blockdev.c
* PURPOSE: Temporary sector reading support
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS ***************************************************************/
BOOLEAN
Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN PVOID Buffer)
{
LARGE_INTEGER sectorNumber;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
NTSTATUS status;
ULONG sectorSize;
int j;
DPRINT("VFATReadSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
pDeviceObject,DiskSector,Buffer);
sectorNumber.u.HighPart = 0;
sectorNumber.u.LowPart = DiskSector * BLOCKSIZE;
DPRINT("DiskSector:%ld BLKSZ:%ld sectorNumber:%ld:%ld\n",
(unsigned long) DiskSector,
(unsigned long) BLOCKSIZE,
(unsigned long) sectorNumber.u.HighPart,
(unsigned long) sectorNumber.u.LowPart);
KeInitializeEvent(&event, NotificationEvent, FALSE);
sectorSize = BLOCKSIZE*SectorCount;
DPRINT("Building synchronous FSD Request...\n");
irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
pDeviceObject,
Buffer,
sectorSize,
&sectorNumber,
&event,
&ioStatus );
if (!irp)
{
DbgPrint("READ failed!!!\n");
return FALSE;
}
DPRINT("Calling IO Driver...\n");
status = IoCallDriver(pDeviceObject, irp);
DPRINT("Waiting for IO Operation...\n");
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
NULL);
DPRINT("Getting IO Status...\n");
status = ioStatus.Status;
}
if (!NT_SUCCESS(status))
{
DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status);
return FALSE;
}
return TRUE;
}
BOOLEAN VFATWriteSectors(IN PDEVICE_OBJECT pDeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN UCHAR* Buffer)
{
LARGE_INTEGER sectorNumber;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
NTSTATUS status;
ULONG sectorSize;
PULONG mbr;
int j;
DPRINT("VFATWriteSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
pDeviceObject,DiskSector,Buffer);
sectorNumber.u.HighPart = 0;
sectorNumber.u.LowPart = DiskSector * BLOCKSIZE;
KeInitializeEvent(&event, NotificationEvent, FALSE);
sectorSize = BLOCKSIZE*SectorCount;
DPRINT("Building synchronous FSD Request...\n");
irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
pDeviceObject,
Buffer,
sectorSize,
&sectorNumber,
&event,
&ioStatus );
if (!irp) {
DbgPrint("WRITE failed!!!\n");
return FALSE;
}
DPRINT("Calling IO Driver...\n");
status = IoCallDriver(pDeviceObject,
irp);
DPRINT("Waiting for IO Operation...\n");
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
NULL);
DPRINT("Getting IO Status...\n");
status = ioStatus.Status;
}
if (!NT_SUCCESS(status)) {
DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status);
return FALSE;
}
ExFreePool(mbr);
DPRINT("Block request succeeded\n");
return TRUE;
}

View file

@ -1,338 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/dir.c
* PURPOSE: ext2 filesystem
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <wchar.h>
#include <string.h>
//#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS *****************************************************************/
static VOID Ext2ConvertName(PWSTR Out, PCH In, ULONG Len)
{
ULONG i;
for (i=0; i<Len; i++)
{
*Out = *In;
Out++;
In++;
}
*Out = 0;
}
PVOID Ext2ProcessDirEntry(PDEVICE_EXTENSION DeviceExt,
struct ext2_dir_entry* dir_entry,
PIO_STACK_LOCATION IoStack,
PVOID Buffer,
ULONG FileIndex)
{
PFILE_DIRECTORY_INFORMATION FDI;
PFILE_NAMES_INFORMATION FNI;
PFILE_BOTH_DIRECTORY_INFORMATION FBI;
struct ext2_inode inode;
DPRINT("FileIndex %d\n",FileIndex);
DPRINT("Buffer %x\n",Buffer);
Ext2ReadInode(DeviceExt,
dir_entry->inode,
&inode);
switch (IoStack->Parameters.QueryDirectory.FileInformationClass)
{
case FileNamesInformation:
FNI = (PFILE_NAMES_INFORMATION)Buffer;
FNI->NextEntryOffset = sizeof(FileDirectoryInformation) +
dir_entry->name_len + 1;
FNI->FileNameLength = dir_entry->name_len;
Ext2ConvertName(FNI->FileName, dir_entry->name, dir_entry->name_len);
Buffer = Buffer + FNI->NextEntryOffset;
break;
case FileDirectoryInformation:
FDI = (PFILE_DIRECTORY_INFORMATION)Buffer;
FDI->NextEntryOffset = sizeof(FileDirectoryInformation) +
dir_entry->name_len + 1;
FDI->FileIndex = FileIndex;
// FDI->CreationTime = 0;
// FDI->LastAccessTime = 0;
// FDI->LastWriteTime = 0;
// FDI->ChangeTime = 0;
FDI->AllocationSize.QuadPart = FDI->EndOfFile.QuadPart = inode.i_size;
FDI->FileAttributes = 0;
FDI->FileNameLength = dir_entry->name_len;
Ext2ConvertName(FDI->FileName, dir_entry->name, dir_entry->name_len);
Buffer = Buffer + FDI->NextEntryOffset;
break;
case FileBothDirectoryInformation:
FBI = (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer;
FBI->NextEntryOffset = sizeof(FileBothDirectoryInformation) +
dir_entry->name_len + 1;
FBI->FileIndex = FileIndex;
FBI->AllocationSize.QuadPart = FBI->EndOfFile.QuadPart = inode.i_size;
FBI->FileAttributes = 0;
FBI->FileNameLength = dir_entry->name_len;
Ext2ConvertName(FBI->FileName, dir_entry->name, dir_entry->name_len);
memset(FBI->ShortName, 0, sizeof(FBI->ShortName));
Buffer = Buffer + FBI->NextEntryOffset;
break;
default:
UNIMPLEMENTED;
}
return(Buffer);
}
NTSTATUS Ext2QueryDirectory(PDEVICE_EXTENSION DeviceExt,
PEXT2_FCB Fcb,
PIRP Irp,
PIO_STACK_LOCATION IoStack)
{
ULONG Max;
ULONG i;
ULONG StartIndex;
PVOID Buffer = NULL;
struct ext2_dir_entry dir_entry;
Buffer = Irp->UserBuffer;
DPRINT("Buffer %x\n",Buffer);
DPRINT("IoStack->Flags %x\n",IoStack->Flags);
if (IoStack->Flags & SL_RETURN_SINGLE_ENTRY)
{
Max = 1;
}
else
{
UNIMPLEMENTED;
}
DPRINT("Buffer->FileIndex %d\n",
((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex);
if (IoStack->Flags & SL_INDEX_SPECIFIED)
{
StartIndex = ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex;
}
else
{
StartIndex = 0;
}
if (IoStack->Flags & SL_RESTART_SCAN)
{
StartIndex = 0;
}
DPRINT("StartIndex %d\n",StartIndex);
for (i=0; i<Max ;i++)
{
if (!Ext2ScanDir(DeviceExt,&Fcb->inode,"*",&dir_entry,&StartIndex))
{
((PFILE_DIRECTORY_INFORMATION)Buffer)->NextEntryOffset = 0;
return(STATUS_NO_MORE_FILES);
}
Buffer = Ext2ProcessDirEntry(DeviceExt,
&dir_entry,
IoStack,
Buffer,
StartIndex);
}
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = Stack->FileObject;
PEXT2_FCB Fcb = (PVOID)FileObject->FsContext;
NTSTATUS Status;
PDEVICE_EXTENSION DeviceExt;
DPRINT("Ext2DirectoryControl(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
DeviceExt = DeviceObject->DeviceExtension;
switch (Stack->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
Status = Ext2QueryDirectory(DeviceExt, Fcb, Irp, Stack);
break;
default:
Status = STATUS_UNSUCCESSFUL;
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}
BOOL Ext2ScanDir(PDEVICE_EXTENSION DeviceExt,
struct ext2_inode* dir,
PCH filename,
struct ext2_dir_entry* ret,
PULONG StartIndex)
{
ULONG i;
char* buffer;
ULONG offset;
char name[255];
struct ext2_dir_entry* current;
ULONG block;
BOOL b;
DPRINT("Ext2ScanDir(dir %x, filename %s, ret %x)\n",dir,filename,ret);
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
for (i=0; i<((*StartIndex)/BLOCKSIZE); i++);
for (; (block = Ext2BlockMap(DeviceExt, dir, i)) != 0; i++)
{
DPRINT("block %d\n",block);
b = Ext2ReadSectors(DeviceExt->StorageDevice,
block,
1,
buffer);
if (!b)
{
DbgPrint("ext2fs:%s:%d: Disk io failed\n", __FILE__, __LINE__);
return(FALSE);
}
offset = (*StartIndex)%BLOCKSIZE;
while (offset < BLOCKSIZE)
{
current = &buffer[offset];
strncpy(name,current->name,current->name_len);
name[current->name_len]=0;
DPRINT("Scanning offset %d inode %d name %s\n",
offset,current->inode,name);
DPRINT("Comparing %s %s\n",name,filename);
if (strcmp(name,filename)==0 || strcmp(filename,"*")==0)
{
DPRINT("Match found\n");
*StartIndex = (i*BLOCKSIZE) + offset + current->rec_len;
memcpy(ret,current,sizeof(struct ext2_dir_entry));
ExFreePool(buffer);
return(TRUE);
}
offset = offset + current->rec_len;
ASSERT(current->rec_len != 0);
DPRINT("offset %d\n",offset);
}
DPRINT("Onto next block\n");
}
DPRINT("No match\n");
ExFreePool(buffer);
return(FALSE);
}
void unicode_to_ansi(PCH StringA, PWSTR StringW)
{
while((*StringW)!=0)
{
*StringA = *StringW;
StringA++;
StringW++;
}
*StringA = 0;
}
NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
PWSTR FileName)
/*
* FUNCTION: Opens a file
*/
{
EXT2_INODE parent_inode;
struct ext2_dir_entry entry;
char name[255];
ULONG current_inode = 2;
char* current_segment;
PEXT2_FCB Fcb;
ULONG StartIndex = 0;
DPRINT("Ext2OpenFile(DeviceExt %x, FileObject %x, FileName %S)\n",
DeviceExt,FileObject,FileName);
Fcb = ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB));
unicode_to_ansi(name,FileName);
DPRINT("name %s\n",name);
DPRINT("strtok %x\n",strtok);
current_segment = strtok(name,"\\");
DPRINT("current_segment %x\n", current_segment);
while (current_segment!=NULL)
{
Ext2LoadInode(DeviceExt,
current_inode,
&parent_inode);
if (!Ext2ScanDir(DeviceExt,
parent_inode.inode,
current_segment,
&entry,
&StartIndex))
{
Ext2ReleaseInode(DeviceExt,
&parent_inode);
ExFreePool(Fcb);
return(STATUS_UNSUCCESSFUL);
}
current_inode = entry.inode;
current_segment = strtok(NULL,"\\");
StartIndex = 0;
Ext2ReleaseInode(DeviceExt,
&parent_inode);
}
DPRINT("Found file\n");
Fcb->inode = current_inode;
CcRosInitializeFileCache(FileObject, &Fcb->Bcb, PAGE_SIZE*3);
FileObject->FsContext = Fcb;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = Stack->FileObject;
NTSTATUS Status;
PDEVICE_EXTENSION DeviceExt;
DPRINT("Ext2Create(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
DeviceExt = DeviceObject->DeviceExtension;
Status = Ext2OpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}

View file

@ -1,289 +0,0 @@
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
BOOLEAN Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN PVOID Buffer);
#define BLOCKSIZE (1024)
struct ext2_super_block {
ULONG s_inodes_count; /* Inodes count */
ULONG s_blocks_count; /* Blocks count */
ULONG s_r_blocks_count; /* Reserved blocks count */
ULONG s_free_blocks_count; /* Free blocks count */
ULONG s_free_inodes_count; /* Free inodes count */
ULONG s_first_data_block; /* First Data Block */
ULONG s_log_block_size; /* Block size */
LONG s_log_frag_size; /* Fragment size */
ULONG s_blocks_per_group; /* # Blocks per group */
ULONG s_frags_per_group; /* # Fragments per group */
ULONG s_inodes_per_group; /* # Inodes per group */
ULONG s_mtime; /* Mount time */
ULONG s_wtime; /* Write time */
USHORT s_mnt_count; /* Mount count */
SHORT s_max_mnt_count; /* Maximal mount count */
USHORT s_magic; /* Magic signature */
USHORT s_state; /* File system state */
USHORT s_errors; /* Behaviour when detecting errors */
USHORT s_minor_rev_level; /* minor revision level */
ULONG s_lastcheck; /* time of last check */
ULONG s_checkinterval; /* max. time between checks */
ULONG s_creator_os; /* OS */
ULONG s_rev_level; /* Revision level */
USHORT s_def_resuid; /* Default uid for reserved blocks */
USHORT s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
ULONG s_first_ino; /* First non-reserved inode */
USHORT s_inode_size; /* size of inode structure */
USHORT s_block_group_nr; /* block group # of this superblock */
ULONG s_feature_compat; /* compatible feature set */
ULONG s_feature_incompat; /* incompatible feature set */
ULONG s_feature_ro_compat; /* readonly-compatible feature set */
ULONG s_reserved[230]; /* Padding to the end of the block */
};
/*
* Codes for operating systems
*/
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
#define EXT2_OS_MASIX 2
#define EXT2_OS_FREEBSD 3
#define EXT2_OS_LITES 4
/*
* Revision levels
*/
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
/*
* The second extended file system magic number
*/
#define EXT2_SUPER_MAGIC 0xEF53
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
/*
* Structure of an inode on the disk
*/
struct ext2_inode {
USHORT i_mode; /* File mode */
USHORT i_uid; /* Owner Uid */
ULONG i_size; /* Size in bytes */
ULONG i_atime; /* Access time */
ULONG i_ctime; /* Creation time */
ULONG i_mtime; /* Modification time */
ULONG i_dtime; /* Deletion Time */
USHORT i_gid; /* Group Id */
USHORT i_links_count; /* Links count */
ULONG i_blocks; /* Blocks count */
ULONG i_flags; /* File flags */
union {
struct {
ULONG l_i_reserved1;
} linux1;
struct {
ULONG h_i_translator;
} hurd1;
struct {
ULONG m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
ULONG i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
ULONG i_version; /* File version (for NFS) */
ULONG i_file_acl; /* File ACL */
ULONG i_dir_acl; /* Directory ACL */
ULONG i_faddr; /* Fragment address */
union {
struct {
UCHAR l_i_frag; /* Fragment number */
UCHAR l_i_fsize; /* Fragment size */
USHORT i_pad1;
ULONG l_i_reserved2[2];
} linux2;
struct {
UCHAR h_i_frag; /* Fragment number */
UCHAR h_i_fsize; /* Fragment size */
USHORT h_i_mode_high;
USHORT h_i_uid_high;
USHORT h_i_gid_high;
ULONG h_i_author;
} hurd2;
struct {
UCHAR m_i_frag; /* Fragment number */
UCHAR m_i_fsize; /* Fragment size */
USHORT m_pad1;
ULONG m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
};
#if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
#define i_frag osd2.linux2.l_i_frag
#define i_fsize osd2.linux2.l_i_fsize
#define i_reserved2 osd2.linux2.l_i_reserved2
#endif
#ifdef __hurd__
#define i_translator osd1.hurd1.h_i_translator
#define i_frag osd2.hurd2.h_i_frag;
#define i_fsize osd2.hurd2.h_i_fsize;
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
#endif
#ifdef __masix__
#define i_reserved1 osd1.masix1.m_i_reserved1
#define i_frag osd2.masix2.m_i_frag
#define i_fsize osd2.masix2.m_i_fsize
#define i_reserved2 osd2.masix2.m_i_reserved2
#endif
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
/*
* Inode flags
*/
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
/*
* Structure of a blocks group descriptor
*/
struct ext2_group_desc
{
ULONG bg_block_bitmap; /* Blocks bitmap block */
ULONG bg_inode_bitmap; /* Inodes bitmap block */
ULONG bg_inode_table; /* Inodes table block */
USHORT bg_free_blocks_count; /* Free blocks count */
USHORT bg_free_inodes_count; /* Free inodes count */
USHORT bg_used_dirs_count; /* Directories count */
USHORT bg_pad;
ULONG bg_reserved[3];
};
#define EXT2_NAME_LEN 255
struct ext2_dir_entry {
ULONG inode; /* Inode number */
USHORT rec_len; /* Directory entry length */
USHORT name_len; /* Name length */
char name[EXT2_NAME_LEN]; /* File name */
};
typedef struct
{
PDEVICE_OBJECT StorageDevice;
struct ext2_super_block* superblock;
PFILE_OBJECT FileObject;
PBCB Bcb;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _EXT2_GROUP_DESC
{
ERESOURCE Lock;
struct ext2_group_desc* desc;
PCACHE_SEGMENT CacheSeg;
PVOID BaseAddress;
} EXT2_GROUP_DESC, *PEXT2_GROUP_DESC;
PEXT2_GROUP_DESC Ext2LoadGroup(PDEVICE_EXTENSION DeviceExt,
ULONG BlockGrp);
VOID Ext2ReleaseGroup(PDEVICE_EXTENSION DeviceExt,
PEXT2_GROUP_DESC GrpDesc);
VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt,
ULONG ino,
struct ext2_inode* inode);
struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt,
ULONG block_group);
typedef struct _EXT2_INODE
{
struct ext2_inode* inode;
PVOID BaseAddress;
PCACHE_SEGMENT CacheSeg;
} EXT2_INODE, *PEXT2_INODE;
typedef struct _EXT2_FCB
{
ULONG inode;
EXT2_INODE i;
PBCB Bcb;
} EXT2_FCB, *PEXT2_FCB;
ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt,
struct ext2_inode* inode,
ULONG offset);
NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
PWSTR FileName);
NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PVOID Buffer,
ULONG Length,
LARGE_INTEGER Offset);
NTSTATUS STDCALL Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2QueryQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2SetQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2SetSecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2QuerySecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2SetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2QueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2Read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2Write(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2Cleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2FlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL Ext2Shutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS Ext2ReadPage(PDEVICE_EXTENSION DeviceExt,
PEXT2_FCB Fcb,
PVOID Buffer,
ULONG Offset);
VOID Ext2LoadInode(PDEVICE_EXTENSION DeviceExt,
ULONG ino,
PEXT2_INODE Inode);
VOID Ext2ReleaseInode(PDEVICE_EXTENSION DeviceExt,
PEXT2_INODE Inode);

View file

@ -1,61 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/super.c
* PURPOSE: ext2 filesystem
* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS ****************************************************************/
#define addr_per_block (BLOCKSIZE / sizeof(ULONG))
ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt,
struct ext2_inode* inode,
ULONG offset)
{
ULONG block;
PULONG TempBuffer;
BOOL b;
DPRINT("Ext2BlockMap(DeviceExt %x, inode %x, offset %d)\n",
DeviceExt,inode,offset);
if (offset < EXT2_NDIR_BLOCKS)
{
block = inode->i_block[offset];
DPRINT("block %d\n",block);
return(block);
}
offset = offset - EXT2_NDIR_BLOCKS;
if (offset < addr_per_block)
{
block = inode->i_block[EXT2_IND_BLOCK];
TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
b = Ext2ReadSectors(DeviceExt->StorageDevice,
block,
1,
TempBuffer);
if (!b)
{
DbgPrint("ext2fs:%s:%d: Disk io failed\n", __FILE__, __LINE__);
return(0);
}
block = TempBuffer[offset];
ExFreePool(TempBuffer);
return(block);
}
offset = offset - addr_per_block;
DbgPrint("Failed at %s:%d\n",__FILE__,__LINE__);
for(;;);
}

View file

@ -0,0 +1,68 @@
/*************************************************************************
*
* File: errmsg.msg
*
* Product: Ext2 FSD
*
* Module: Ext2 FSD Event Log Messages
*
* Description:
* Contains error strings in a format understandable to the message compiler.
* Please compile (using mc) with the -c option which will set the
* "Customer" bit in all errors.
* Use values beginning at 0xA000 (e.g. 0xA001) for the Ext2 FSD
* errors.
* Do NOT use %1 for insertion strings. The I/O manager assumes that
* the first insertion string is the name of the driver/device.
*
*
*************************************************************************/
//
// Values are 32 bit values layed out as follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
//
// where
//
// Sev - is the severity code
//
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
//
// C - is the Customer code flag
//
// R - is a reserved bit
//
// Facility - is the facility code
//
// Code - is the facility's status code
//
//
// Define the facility codes
//
//
// Define the severity codes
//
#define STATUS_SEVERITY_WARNING 0x2
#define STATUS_SEVERITY_SUCCESS 0x0
#define STATUS_SEVERITY_INFORMATIONAL 0x1
#define STATUS_SEVERITY_ERROR 0x3
//
// MessageId: EXT2_ERROR_INTERNAL_ERROR
//
// MessageText:
//
// The Ext2 FSD encountered an internal error. Please check log data information.
//
#define EXT2_ERROR_INTERNAL_ERROR ((ULONG)0xE004A001L)

View file

@ -0,0 +1,615 @@
/*
* linux/include/linux/ext2_fs.h
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
* linux/include/linux/minix_fs.h
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#ifndef _LINUX_EXT2_FS_H
#define _LINUX_EXT2_FS_H
// #include <linux/types.h>
/*
* The second extended filesystem constants/structures
*/
/*
* Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
*/
#define EXT2_PREALLOCATE
#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
/*
* The second extended file system version
*/
#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b"
/*
* Debug code
*/
/*
* Special inodes numbers
*/
#define EXT2_BAD_INO 1 /* Bad blocks inode */
#define EXT2_ROOT_INO 2 /* Root inode */
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
/* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11
/*
* The second extended file system magic number
*/
#define EXT2_SUPER_MAGIC 0xEF53
/*
* Maximal count of links to a file
*/
#define EXT2_LINK_MAX 32000
/*
* Macro-instructions used to manage several block sizes
*/
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
#else
# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
#endif
#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
#else
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
#endif
#ifdef __KERNEL__
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
#else
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_INODE_SIZE : \
(s)->s_inode_size)
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_FIRST_INO : \
(s)->s_first_ino)
#endif
/*
* Macro-instructions used to manage fragments
*/
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
#define EXT2_MIN_FRAG_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
#else
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
#endif
/*
* ACL structures
*/
struct ext2_acl_header /* Header of Access Control Lists */
{
__u32 aclh_size;
__u32 aclh_file_count;
__u32 aclh_acle_count;
__u32 aclh_first_acle;
};
struct ext2_acl_entry /* Access Control List Entry */
{
__u32 acle_size;
__u16 acle_perms; /* Access permissions */
__u16 acle_type; /* Type of entry */
__u16 acle_tag; /* User or group identity */
__u16 acle_pad1;
__u32 acle_next; /* Pointer on next entry for the */
/* same inode or on next free entry */
};
/*
* Structure of a blocks group descriptor
*/
struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_pad;
__u32 bg_reserved[3];
};
/*
* Macro-instructions used to manage group descriptors
*/
#ifdef __KERNEL__
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
#else
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
#endif
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
/*
* Inode flags
*/
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define EXT2_DIRTY_FL 0x00000100
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
/* End compression flags --- maybe not all used */
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */
#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
/*
* ioctl commands
*/
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
/*
* Structure of an inode on the disk
*/
struct ext2_inode {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_reserved1;
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
struct {
__u32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_dir_acl; /* Directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__u16 i_pad1;
__u16 l_i_uid_high; /* these 2 fields */
__u16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* Fragment number */
__u8 m_i_fsize; /* Fragment size */
__u16 m_pad1;
__u32 m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
};
#define i_size_high i_dir_acl
#if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
#define i_frag osd2.linux2.l_i_frag
#define i_fsize osd2.linux2.l_i_fsize
#define i_uid_low i_uid
#define i_gid_low i_gid
#define i_uid_high osd2.linux2.l_i_uid_high
#define i_gid_high osd2.linux2.l_i_gid_high
#define i_reserved2 osd2.linux2.l_i_reserved2
#endif
#ifdef __hurd__
#define i_translator osd1.hurd1.h_i_translator
#define i_frag osd2.hurd2.h_i_frag;
#define i_fsize osd2.hurd2.h_i_fsize;
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
#endif
#ifdef __masix__
#define i_reserved1 osd1.masix1.m_i_reserved1
#define i_frag osd2.masix2.m_i_frag
#define i_fsize osd2.masix2.m_i_fsize
#define i_reserved2 osd2.masix2.m_i_reserved2
#endif
/*
* File system states
*/
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
/*
* Mount flags
*/
#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
EXT2_MOUNT_##opt)
/*
* Maximal mount counts between two filesystem checks
*/
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
/*
* Behaviour when detecting errors
*/
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
#define EXT2_ERRORS_PANIC 3 /* Panic */
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
/*
* Structure of the super block
*/
struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
__u32 s_r_blocks_count; /* Reserved blocks count */
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
__s32 s_log_frag_size; /* Fragment size */
__u32 s_blocks_per_group; /* # Blocks per group */
__u32 s_frags_per_group; /* # Fragments per group */
__u32 s_inodes_per_group; /* # Inodes per group */
__u32 s_mtime; /* Mount time */
__u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_COMPAT_PREALLOC flag is on.
*/
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_padding1;
__u32 s_reserved[204]; /* Padding to the end of the block */
};
#ifdef __KERNEL__
#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
#else
/* Assume that user mode programs are passing in an ext2fs superblock, not
* a kernel struct super_block. This will allow us to call the feature-test
* macros from user land. */
#define EXT2_SB(sb) (sb)
#endif
/*
* Codes for operating systems
*/
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
#define EXT2_OS_MASIX 2
#define EXT2_OS_FREEBSD 3
#define EXT2_OS_LITES 4
/*
* Revision levels
*/
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
#define EXT2_GOOD_OLD_INODE_SIZE 128
/*
* Feature set definitions
*/
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
#define EXT2_SET_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
#define EXT2_SET_RO_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
#define EXT2_SET_INCOMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
#define EXT2_CLEAR_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
#define EXT2_CLEAR_RO_COMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
#define EXT2_CLEAR_INCOMPAT_FEATURE(sb,mask) \
EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
/*
* Default values for user and/or group using reserved blocks
*/
#define EXT2_DEF_RESUID 0
#define EXT2_DEF_RESGID 0
/*
* Structure of a directory entry
*/
#define EXT2_NAME_LEN 255
struct ext2_dir_entry {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u16 name_len; /* Name length */
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* The new version of the directory entry. Since EXT2 structures are
* stored in intel byte order, and the name_len field could never be
* bigger than 255 chars, it's safe to reclaim the extra byte for the
* file_type field.
*/
struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* Ext2 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now.
*/
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_REG_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHRDEV 3
#define EXT2_FT_BLKDEV 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*
* NOTE: It must be a multiple of 4
*/
#define EXT2_DIR_PAD 4
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
#ifdef __KERNEL__
/*
* Function prototypes
*/
/*
* Ok, these declarations are also in <linux/kernel.h> but none of the
* ext2 source programs needs to include it so they are duplicated here.
*/
# define NORET_TYPE /**/
# define ATTRIB_NORET __attribute__((noreturn))
# define NORET_AND noreturn,
/* acl.c */
extern int ext2_permission (struct inode *, int);
/* balloc.c */
extern int ext2_bg_has_super(struct super_block *sb, int group);
extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
extern int ext2_new_block (struct inode *, unsigned long,
__u32 *, __u32 *, int *);
extern void ext2_free_blocks (struct inode *, unsigned long,
unsigned long);
extern unsigned long ext2_count_free_blocks (struct super_block *);
extern void ext2_check_blocks_bitmap (struct super_block *);
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh);
/* bitmap.c */
extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
/* dir.c */
extern int ext2_check_dir_entry (const char *, struct inode *,
struct ext2_dir_entry_2 *, struct buffer_head *,
unsigned long);
/* file.c */
extern int ext2_read (struct inode *, struct file *, char *, int);
extern int ext2_write (struct inode *, struct file *, char *, int);
/* fsync.c */
extern int ext2_sync_file (struct file *, struct dentry *, int);
extern int ext2_fsync_inode (struct inode *, int);
/* ialloc.c */
extern struct inode * ext2_new_inode (const struct inode *, int);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
/* inode.c */
extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *, int);
extern void ext2_put_inode (struct inode *);
extern void ext2_delete_inode (struct inode *);
extern int ext2_sync_inode (struct inode *);
extern void ext2_discard_prealloc (struct inode *);
/* ioctl.c */
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
unsigned long);
/* namei.c */
extern struct inode_operations ext2_dir_inode_operations;
/* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
const char *, ...)
__attribute__ ((NORET_AND format (printf, 3, 4)));
extern void ext2_warning (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
extern void ext2_update_dynamic_rev (struct super_block *sb);
extern void ext2_put_super (struct super_block *);
extern void ext2_write_super (struct super_block *);
extern int ext2_remount (struct super_block *, int *, char *);
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern int ext2_statfs (struct super_block *, struct statfs *);
/* truncate.c */
extern void ext2_truncate (struct inode *);
/*
* Inodes and files operations
*/
/* dir.c */
extern struct file_operations ext2_dir_operations;
/* file.c */
extern struct inode_operations ext2_file_inode_operations;
extern struct file_operations ext2_file_operations;
/* symlink.c */
extern struct inode_operations ext2_fast_symlink_inode_operations;
extern struct address_space_operations ext2_aops;
#endif /* __KERNEL__ */
#endif /* _LINUX_EXT2_FS_H */

View file

@ -0,0 +1,250 @@
/*************************************************************************
*
* File: ext2fsd.h
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* The main include file for the Ext2 file system driver.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#ifndef _EXT2_FSD_H_
#define _EXT2_FSD_H_
#define EXT2_POOL_WITH_TAG
// some constant definitions
#define EXT2_PANIC_IDENTIFIER (0x86427531)
// any directory information EXT2 obtains from the local file system
// will use a buffer of the following size ... (in KB)
#define EXT2_READ_DIR_BUFFER_LENGTH (512)
#define EXT2_MAXCLOSABLE_FCBS_UL 20
#define EXT2_MAXCLOSABLE_FCBS_LL 10
// Some type definitions...
// These are used later...
typedef unsigned char UCHAR;
typedef unsigned int UINT;
typedef UCHAR BYTE;
typedef UCHAR BOOLEAN; // winnt
typedef BOOLEAN * PBOOLEAN; // winnt
typedef void * PVOID64; // winnt
typedef long LONG;
typedef LONG HRESULT;
#if defined(_M_IX86)
#define FASTCALL _fastcall
#else
#define FASTCALL
#endif
// Common include files - should be in the include dir of the MS supplied IFS Kit
#include <ntifs.h>
#include <ntdddisk.h>
/* REACTOS FIXME */
#undef DeleteFile
/* This is deprecated and should be changed in the EXT2FS driver. */
#define RtlLargeIntegerLessThan(a, b) (a).QuadPart < (b).QuadPart
#define RtlLargeIntegerGreaterThan(a, b) (a).QuadPart > (b).QuadPart
// the following include files should be in the inc sub-dir associated with this driver
#include "ext2metadata.h"
#include "struct.h"
#include "protos.h"
#include "errmsg.h"
// global variables - minimize these
extern Ext2Data Ext2GlobalData;
// try-finally simulation
#define try_return(S) { S; goto try_exit; }
#define try_return1(S) { S; goto try_exit1; }
#define try_return2(S) { S; goto try_exit2; }
// some global (helpful) macros
#define Ext2IsFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0)))
#define Ext2SetFlag(Flag, Value) ((Flag) |= (Value))
#define Ext2ClearFlag(Flag, Value) ((Flag) &= ~(Value))
#define Ext2QuadAlign(Value) ((((uint32)(Value)) + 7) & 0xfffffff8)
// to perform a bug-check (panic), the following macro is used
#define Ext2Panic(arg1, arg2, arg3) \
(KeBugCheckEx(EXT2_PANIC_IDENTIFIER, EXT2_BUG_CHECK_ID | __LINE__, (uint32)(arg1), (uint32)(arg2), (uint32)(arg3)))
// a convenient macro (must be invoked in the context of the thread that acquired the resource)
#define Ext2ReleaseResource(Resource) \
(ExReleaseResourceForThreadLite((Resource), ExGetCurrentResourceThread()))
// each file has a unique bug-check identifier associated with it.
// Here is a list of constant definitions for these identifiers
#define EXT2_FILE_INIT (0x00000001)
#define EXT2_FILE_REGISTRY (0x00000002)
#define EXT2_FILE_CREATE (0x00000003)
#define EXT2_FILE_CLEANUP (0x00000004)
#define EXT2_FILE_CLOSE (0x00000005)
#define EXT2_FILE_READ (0x00000006)
#define EXT2_FILE_WRITE (0x00000007)
#define EXT2_FILE_INFORMATION (0x00000008)
#define EXT2_FILE_FLUSH (0x00000009)
#define EXT2_FILE_VOL_INFORMATION (0x0000000A)
#define EXT2_FILE_DIR_CONTROL (0x0000000B)
#define EXT2_FILE_FILE_CONTROL (0x0000000C)
#define EXT2_FILE_DEVICE_CONTROL (0x0000000D)
#define EXT2_FILE_SHUTDOWN (0x0000000E)
#define EXT2_FILE_LOCK_CONTROL (0x0000000F)
#define EXT2_FILE_SECURITY (0x00000010)
#define EXT2_FILE_EXT_ATTR (0x00000011)
#define EXT2_FILE_MISC (0x00000012)
#define EXT2_FILE_FAST_IO (0x00000013)
#define EXT2_FILE_IO (0x00000014)
#define EXT2_FILE_METADATA_IO (0x00000015)
#if DBG
#define Ext2BreakPoint() DbgBreakPoint()
#else
#define Ext2BreakPoint()
#endif
#define Ext2RaiseStatus(IRPCONTEXT,STATUS) \
{ \
(IRPCONTEXT)->ExceptionStatus = (STATUS); \
ExRaiseStatus( (STATUS) ); \
}
#ifdef EXT2_POOL_WITH_TAG
#define Ext2AllocatePool(PoolType,NumberOfBytes) \
ExAllocatePoolWithTag( PoolType, NumberOfBytes, '2txE' )
#else
#define Ext2AllocatePool(PoolType,NumberOfBytes) \
ExAllocatePool( PoolType, NumberOfBytes )
#endif
#if DBG
//
// Trace types...
// Any number of these may be enabled...
//
#define DEBUG_TRACE_IRQL (0x00000001)
#define DEBUG_TRACE_IRP_ENTRY (0x00000002)
#define DEBUG_TRACE_RESOURCE_ACQUIRE (0x00000004)
#define DEBUG_TRACE_RESOURCE_RELEASE (0x00000008)
#define DEBUG_TRACE_RESOURCE_RETRY (0x00000010)
#define DEBUG_TRACE_ASYNC (0x00000020)
#define DEBUG_TRACE_MOUNT (0x00000040)
#define DEBUG_TRACE_RESOURCE_STATE (0x00000080)
#define DEBUG_TRACE_MISC (0x00000100)
#define DEBUG_TRACE_FILE_OBJ (0x00000200)
#define DEBUG_TRACE_FILE_NAME (0x00000400)
#define DEBUG_TRACE_SPECIAL (0x00000800)
#define DEBUG_TRACE_ERROR (0x00001000)
#define DEBUG_TRACE_READ_DETAILS (0x00002000)
#define DEBUG_TRACE_WRITE_DETAILS (0x00004000)
#define DEBUG_TRACE_FILEINFO (0x00008000)
#define DEBUG_TRACE_DIRINFO (0x00010000)
#define DEBUG_TRACE_REFERENCE (0x00020000)
#define DEBUG_TRACE_FSCTRL (0x00040000)
#define DEBUG_TRACE_FREE (0x00080000)
#define DEBUG_TRACE_LINENO (0x00100000)
#define DEBUG_TRACE_TRIPLE (0x00200000)
#define DEBUG_TRACE_ALL (0xffffffff)
#define DEBUG_TRACE_NONE 0
//
// The permitted DebugTrace types...
//
#define PERMITTED_DEBUG_TRACE_TYPES /* DEBUG_TRACE_TRIPLE */ DEBUG_TRACE_ALL
/*
#define PERMITTED_DEBUG_TRACE_TYPES DEBUG_TRACE_ERROR | DEBUG_TRACE_IRP_ENTRY | \
DEBUG_TRACE_FILE_NAME | DEBUG_TRACE_SPECIAL | \
DEBUG_TRACE_ASYNC
*/
#define DebugTrace( TYPE, X, Y ) \
{ \
if( ( TYPE ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
{ \
DbgPrint("\n "); \
DbgPrint(X,Y); \
if( ( DEBUG_TRACE_IRQL ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
{ \
DbgPrint( " IRQL = %d ", KeGetCurrentIrql( ) ); \
} \
if( ( DEBUG_TRACE_LINENO ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
{ \
DbgPrint( " [%s] Line No = %ld", __FILE__, __LINE__ ); \
} \
} \
}
#define DebugTraceState( STR, X1, X2, X3) \
{ \
if( ( DEBUG_TRACE_RESOURCE_STATE ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
{ \
DbgPrint("\nState: "); \
DbgPrint( STR, X1, X2, X3 ); \
if( ( DEBUG_TRACE_IRQL ) & ( PERMITTED_DEBUG_TRACE_TYPES ) ) \
{ \
DbgPrint( " IRQL = %d ", KeGetCurrentIrql( ) ); \
} \
} \
}
#define AssertFCB( PtrFCB ) \
{ \
if( !(PtrFCB) || (PtrFCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB ) \
{ \
Ext2BreakPoint(); \
} \
}
#define AssertVCB( PtrVCB ) \
{ \
if( !(PtrVCB) || (PtrVCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_VCB ) \
{ \
Ext2BreakPoint(); \
} \
}
#define AssertFCBorVCB( PtrVCBorFCB ) \
{ \
if( !(PtrVCBorFCB) || \
( (PtrVCBorFCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_VCB && \
(PtrVCBorFCB)->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB ) ) \
{ \
Ext2BreakPoint(); \
} \
}
#else
#define DebugTrace( TYPE, X, Y )
#define DebugTraceState( STR, X1, X2, X3 )
#define AssertFCB( PtrFCB )
#define AssertVCB( PtrVCB )
#define AssertFCBorVCB( PtrVCBorFCB )
#endif
#endif // _EXT2_FSD_H_

View file

@ -0,0 +1,115 @@
/*************************************************************************
*
* File: ext2metadata.h
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains the definitions for the Ext2 Metadata structures.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#ifndef EXT2_METADATA_STRUCTURES
#define EXT2_METADATA_STRUCTURES
//
// Some type definitions...
// These are used in the ext2_fs.h header file
//
typedef unsigned int __u32 ;
typedef signed int __s32 ;
typedef unsigned short int __u16 ;
typedef signed short int __s16 ;
typedef unsigned char __u8 ;
//
//******************************************************
//
// Using Remy Card's (slightly modified) Ext2 header...
//
#include "ext2_fs.h"
//
//******************************************************
//
typedef struct ext2_super_block EXT2_SUPER_BLOCK;
typedef EXT2_SUPER_BLOCK * PEXT2_SUPER_BLOCK;
typedef struct ext2_inode EXT2_INODE;
typedef EXT2_INODE * PEXT2_INODE;
typedef struct ext2_group_desc EXT2_GROUP_DESCRIPTOR;
typedef EXT2_GROUP_DESCRIPTOR * PEXT2_GROUP_DESCRIPTOR;
typedef struct ext2_dir_entry_2 EXT2_DIR_ENTRY;
typedef EXT2_DIR_ENTRY * PEXT2_DIR_ENTRY;
//
// Ext2 Supported File Types...
//
#define IMODE_FIFO 0x01
#define IMODE_CHARDEV 0x02
#define IMODE_DIR 0x04
#define IMODE_BLOCKDEV 0x06
#define IMODE_FILE 0x08
#define IMODE_SLINK 0x0A
#define IMODE_SOCKET 0x0C
#define _MKMODE(m) ( ( (m) >> 12 ) & 0x000F)
#define Ext2IsModeRegularFile(m) ( _MKMODE(m) == IMODE_FILE )
#define Ext2IsModeDirectory(m) ( _MKMODE(m) == IMODE_DIR )
#define Ext2IsModeSymbolicLink(m) ( _MKMODE(m) == IMODE_SLINK )
#define Ext2IsModePipe(m) ( _MKMODE(m) == IMODE_FIFO )
#define Ext2IsModeCharacterDevice(m) ( _MKMODE(m) == IMODE_CHARDEV )
#define Ext2IsModeBlockDevice(m) ( _MKMODE(m) == IMODE_BLOCKDEV )
#define Ext2IsModeSocket(m) ( _MKMODE(m) == IMODE_SOCKET )
#define Ext2IsModeHidden(m) ( (m & 0x124) == 0) // No Read Permission
#define Ext2IsModeReadOnly(m) ( (m & 0x92) == 0) // No write Permission
#define Ext2SetModeHidden(m) m = (m & (~0x124)); // Turn off Read Permission
#define Ext2SetModeReadOnly(m) m = (m & (~0x92)); // Turn off write Permission
#define Ext2SetModeReadWrite(m) m = (m & 0x1ff); // Set read/write Permission
//
// Define the Packed and Unpacked BIOS Parameter Block
//
typedef struct _PACKED_BIOS_PARAMETER_BLOCK {
UCHAR BytesPerSector[2]; // offset = 0x000 0
UCHAR SectorsPerCluster[1]; // offset = 0x002 2
UCHAR ReservedSectors[2]; // offset = 0x003 3
UCHAR Fats[1]; // offset = 0x005 5
UCHAR RootEntries[2]; // offset = 0x006 6
UCHAR Sectors[2]; // offset = 0x008 8
UCHAR Media[1]; // offset = 0x00A 10
UCHAR SectorsPerFat[2]; // offset = 0x00B 11
UCHAR SectorsPerTrack[2]; // offset = 0x00D 13
UCHAR Heads[2]; // offset = 0x00F 15
UCHAR HiddenSectors[4]; // offset = 0x011 17
UCHAR LargeSectors[4]; // offset = 0x015 21
} PACKED_BIOS_PARAMETER_BLOCK; // sizeof = 0x019 25
typedef PACKED_BIOS_PARAMETER_BLOCK *PPACKED_BIOS_PARAMETER_BLOCK;
//
// Define the boot sector
//
typedef struct _PACKED_BOOT_SECTOR {
UCHAR Jump[3]; // offset = 0x000 0
UCHAR Oem[8]; // offset = 0x003 3
PACKED_BIOS_PARAMETER_BLOCK PackedBpb; // offset = 0x00B 11
UCHAR PhysicalDriveNumber; // offset = 0x024 36
UCHAR CurrentHead; // offset = 0x025 37
UCHAR Signature; // offset = 0x026 38
UCHAR Id[4]; // offset = 0x027 39
UCHAR VolumeLabel[11]; // offset = 0x02B 43
UCHAR SystemId[8]; // offset = 0x036 54
} PACKED_BOOT_SECTOR; // sizeof = 0x03E 62
typedef PACKED_BOOT_SECTOR *PPACKED_BOOT_SECTOR;
#endif

View file

@ -0,0 +1,782 @@
/*************************************************************************
*
* File: protos.h
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains the prototypes for functions in this sample FSD.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#ifndef _EXT2_PROTOS_H_
#define _EXT2_PROTOS_H_
#ifdef __REACTOS__
typedef PIO_STACK_LOCATION PEXTENDED_IO_STACK_LOCATION;
#endif
/*************************************************************************
* Prototypes for the file sfsdinit.c
*************************************************************************/
extern NTSTATUS STDCALL DriverEntry(
PDRIVER_OBJECT DriverObject, // created by the I/O sub-system
PUNICODE_STRING RegistryPath); // path to the registry key
extern void STDCALL Ext2FsdInitializeFunctionPointers(
PDRIVER_OBJECT DriverObject); // created by the I/O sub-system
extern VOID STDCALL Ext2QueueHandlerThread(
IN PVOID StartContext);
/*************************************************************************
* Prototypes for the file fsctrl.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2FileSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
extern NTSTATUS STDCALL Ext2VerifyVolume (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp );
/*************************************************************************
* Prototypes for the file create.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2Create(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonCreate(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
BOOLEAN FirstAttempt );
extern NTSTATUS STDCALL Ext2OpenVolume(
PtrExt2VCB PtrVCB, // volume to be opened
PtrExt2IrpContext PtrIrpContext, // IRP context
PIRP PtrIrp, // original/user IRP
unsigned short ShareAccess, // share access
PIO_SECURITY_CONTEXT PtrSecurityContext, // caller's context (incl access)
PFILE_OBJECT PtrNewFileObject); // I/O Mgr. created file object
extern NTSTATUS STDCALL Ext2OpenRootDirectory(
PtrExt2VCB PtrVCB, // volume to be opened
PtrExt2IrpContext PtrIrpContext, // IRP context
PIRP PtrIrp, // original/user IRP
unsigned short ShareAccess, // share access
PIO_SECURITY_CONTEXT PtrSecurityContext, // caller's context (incl access)
PFILE_OBJECT PtrNewFileObject); // I/O Mgr. created file object
extern void STDCALL Ext2InitializeFCB(
PtrExt2FCB PtrNewFCB, // FCB structure to be initialized
PtrExt2VCB PtrVCB, // logical volume (VCB) pointer
PtrExt2ObjectName PtrObjectName, // name of the object
uint32 Flags, // is this a file/directory, etc.
PFILE_OBJECT PtrFileObject);// optional file object to be initialized
extern PtrExt2FCB STDCALL Ext2LocateChildFCBInCore(
PtrExt2VCB PtrVCB,
PUNICODE_STRING PtrName,
ULONG ParentInodeNo );
extern PtrExt2FCB STDCALL Ext2LocateFCBInCore(
PtrExt2VCB PtrVCB,
ULONG InodeNo );
extern ULONG STDCALL Ext2LocateFileInDisk(
PtrExt2VCB PtrVCB,
PUNICODE_STRING PtrCurrentName,
PtrExt2FCB PtrParentFCB,
ULONG *Type );
extern ULONG STDCALL Ext2CreateFile(
PtrExt2IrpContext PtrIrpContext,
PtrExt2VCB PtrVCB,
PUNICODE_STRING PtrName,
PtrExt2FCB PtrParentFCB,
ULONG Type);
extern BOOLEAN STDCALL Ext2OverwriteFile(
PtrExt2FCB PtrFCB,
PtrExt2IrpContext PtrIrpContext);
extern BOOLEAN STDCALL Ext2SupersedeFile(
PtrExt2FCB PtrFCB,
PtrExt2IrpContext PtrIrpContext);
/*************************************************************************
* Prototypes for the file misc.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2InitializeZones(
void);
extern void STDCALL Ext2DestroyZones(
void);
extern BOOLEAN STDCALL Ext2IsIrpTopLevel(
PIRP Irp); // the IRP sent to our dispatch routine
extern long STDCALL Ext2ExceptionFilter(
PtrExt2IrpContext PtrIrpContext,
PEXCEPTION_POINTERS PtrExceptionPointers);
extern NTSTATUS STDCALL Ext2ExceptionHandler(
PtrExt2IrpContext PtrIrpContext,
PIRP Irp);
extern void STDCALL Ext2LogEvent(
NTSTATUS Ext2EventLogId, // the Ext2 private message id
NTSTATUS RC); // any NT error code we wish to log ...
extern PtrExt2ObjectName STDCALL Ext2AllocateObjectName(
void);
extern void STDCALL Ext2ReleaseObjectName(
PtrExt2ObjectName PtrObjectName);
extern PtrExt2CCB STDCALL Ext2AllocateCCB(
void );
extern PtrExt2FCB STDCALL Ext2GetUsedFCB(
PtrExt2VCB PtrVCB );
extern BOOLEAN STDCALL Ext2CloseClosableFCB(
PtrExt2FCB PtrFCB );
extern void STDCALL Ext2ReleaseCCB(
PtrExt2CCB PtrCCB);
extern PtrExt2FCB STDCALL Ext2AllocateFCB(
void);
extern NTSTATUS STDCALL Ext2CreateNewFCB(
PtrExt2FCB *ReturnedFCB,
LARGE_INTEGER AllocationSize,
LARGE_INTEGER EndOfFile,
PFILE_OBJECT PtrFileObject,
PtrExt2VCB PtrVCB,
PtrExt2ObjectName PtrObjectName);
extern NTSTATUS STDCALL Ext2CreateNewCCB(
PtrExt2CCB *ReturnedCCB,
PtrExt2FCB PtrFCB,
PFILE_OBJECT PtrFileObject);
extern void STDCALL Ext2ReleaseFCB(
PtrExt2FCB PtrFCB);
extern PtrExt2FileLockInfo STDCALL Ext2AllocateByteLocks(
void);
extern void STDCALL Ext2ReleaseByteLocks(
PtrExt2FileLockInfo PtrByteLocks);
extern PtrExt2IrpContext STDCALL Ext2AllocateIrpContext(
PIRP Irp,
PDEVICE_OBJECT PtrTargetDeviceObject);
extern void STDCALL Ext2ReleaseIrpContext(
PtrExt2IrpContext PtrIrpContext);
extern NTSTATUS STDCALL Ext2PostRequest(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp);
extern void STDCALL Ext2CommonDispatch(
void *Context); // actually an IRPContext structure
extern void STDCALL Ext2InitializeVCB(
PDEVICE_OBJECT PtrVolumeDeviceObject,
PDEVICE_OBJECT PtrTargetDeviceObject,
PVPB PtrVPB,
PLARGE_INTEGER AllocationSize);
extern void STDCALL Ext2CompleteRequest(
IN PIRP Irp OPTIONAL,
IN NTSTATUS Status
);
extern NTSTATUS STDCALL Ext2DenyAccess(
IN PIRP Irp
);
extern NTSTATUS STDCALL Ext2GetFCB_CCB_VCB_FromFileObject(
IN PFILE_OBJECT PtrFileObject,
OUT PtrExt2FCB *PPtrFCB,
OUT PtrExt2CCB *PPtrCCB,
OUT PtrExt2VCB *PPtrVCB );
extern void STDCALL Ext2CopyUnicodeString(
IN OUT PUNICODE_STRING PtrDestinationString,
IN PUNICODE_STRING PtrSourceString );
extern void STDCALL Ext2CopyWideCharToUnicodeString(
IN OUT PUNICODE_STRING PtrDestinationString,
IN PCWSTR PtrSourceString );
extern void STDCALL Ext2CopyCharToUnicodeString(
IN OUT PUNICODE_STRING PtrDestinationString,
IN PCSTR PtrSourceString,
IN USHORT SourceStringLength );
extern void STDCALL Ext2CopyZCharToUnicodeString(
IN OUT PUNICODE_STRING PtrDestinationString,
IN PCSTR PtrSourceString );
extern void STDCALL Ext2DeallocateUnicodeString(
PUNICODE_STRING PtrUnicodeString );
extern void STDCALL Ext2ZerooutUnicodeString(
PUNICODE_STRING PtrUnicodeString );
extern BOOLEAN STDCALL Ext2SaveBCB(
PtrExt2IrpContext PtrIrpContext,
PBCB PtrBCB,
PFILE_OBJECT PtrFileObject);
extern BOOLEAN STDCALL Ext2FlushSavedBCBs(
PtrExt2IrpContext PtrIrpContext);
extern BOOLEAN STDCALL AssertBCB(
PBCB PtrBCB);
extern ULONG STDCALL Ext2Align(
ULONG NumberToBeAligned,
ULONG Alignment);
extern LONGLONG STDCALL Ext2Align64(
LONGLONG NumberToBeAligned,
LONGLONG Alignment);
extern ULONG STDCALL Ext2GetCurrentTime();
/*************************************************************************
* Prototypes for the file cleanup.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2Cleanup(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonCleanup(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
BOOLEAN FirstAttempt );
/*************************************************************************
* Prototypes for the file close.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2Close(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonClose(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
BOOLEAN FirstAttempt );
/*************************************************************************
* Prototypes for the file read.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2Read(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonRead(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
BOOLEAN FirstAttempt );
extern void * STDCALL Ext2GetCallersBuffer(
PIRP PtrIrp);
extern NTSTATUS STDCALL Ext2LockCallersBuffer(
PIRP PtrIrp,
BOOLEAN IsReadOperation,
uint32 Length);
extern void STDCALL Ext2MdlComplete(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PIO_STACK_LOCATION PtrIoStackLocation,
BOOLEAN ReadCompletion);
/*************************************************************************
* Prototypes for the file write.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2Write(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonWrite(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp);
extern void STDCALL Ext2DeferredWriteCallBack (
void *Context1, // Should be PtrIrpContext
void *Context2); // Should be PtrIrp
/*************************************************************************
* Prototypes for the file fileinfo.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2FileInfo(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonFileInfo(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp);
extern NTSTATUS STDCALL Ext2GetBasicInformation(
PtrExt2FCB PtrFCB,
PFILE_BASIC_INFORMATION PtrBuffer,
long *PtrReturnedLength);
extern NTSTATUS STDCALL Ext2GetStandardInformation(
PtrExt2FCB PtrFCB,
PFILE_STANDARD_INFORMATION PtrStdInformation,
long *PtrReturnedLength);
extern NTSTATUS STDCALL Ext2GetNetworkOpenInformation(
PtrExt2FCB PtrFCB,
PFILE_NETWORK_OPEN_INFORMATION PtrNetworkOpenInformation,
long *PtrReturnedLength );
extern NTSTATUS STDCALL Ext2GetFullNameInformation(
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB,
PFILE_NAME_INFORMATION PtrNameInformation,
long *PtrReturnedLength);
extern NTSTATUS STDCALL Ext2SetBasicInformation(
PtrExt2IrpContext PtrIrpContext,
PtrExt2FCB PtrFCB,
PFILE_OBJECT PtrFileObject,
PFILE_BASIC_INFORMATION PtrFileInformation );
extern NTSTATUS STDCALL Ext2SetDispositionInformation(
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB,
PtrExt2VCB PtrVCB,
PFILE_OBJECT PtrFileObject,
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PFILE_DISPOSITION_INFORMATION PtrBuffer);
extern NTSTATUS STDCALL Ext2SetAllocationInformation(
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB,
PtrExt2VCB PtrVCB,
PFILE_OBJECT PtrFileObject,
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PFILE_ALLOCATION_INFORMATION PtrBuffer);
/*************************************************************************
* Prototypes for the file flush.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2Flush(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonFlush(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp);
extern void STDCALL Ext2FlushAFile(
PtrExt2NTRequiredFCB PtrReqdFCB,
PIO_STATUS_BLOCK PtrIoStatus);
extern void STDCALL Ext2FlushLogicalVolume(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PtrExt2VCB PtrVCB);
extern NTSTATUS STDCALL Ext2FlushCompletion(
PDEVICE_OBJECT PtrDeviceObject,
PIRP PtrIrp,
PVOID Context);
/*************************************************************************
* Prototypes for the file dircntrl.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2DirControl(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonDirControl(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp);
extern NTSTATUS STDCALL Ext2QueryDirectory(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
PFILE_OBJECT PtrFileObject,
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB);
extern NTSTATUS STDCALL Ext2NotifyChangeDirectory(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
PFILE_OBJECT PtrFileObject,
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB);
/*************************************************************************
* Prototypes for the file devcntrl.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2DeviceControl(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonDeviceControl(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp);
extern NTSTATUS STDCALL Ext2DevIoctlCompletion(
PDEVICE_OBJECT PtrDeviceObject,
PIRP PtrIrp,
void *Context);
extern NTSTATUS STDCALL Ext2HandleQueryPath(
void *BufferPointer);
/*************************************************************************
* Prototypes for the file shutdown.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2Shutdown(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
extern NTSTATUS STDCALL Ext2CommonShutdown(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp);
/*************************************************************************
* Prototypes for the file volinfo.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2QueryVolInfo(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp); // I/O Request Packet
NTSTATUS STDCALL Ext2SetVolInfo(
IN PDEVICE_OBJECT DeviceObject, // the logical volume device object
IN PIRP Irp); // I/O Request Packet
/*************************************************************************
* Prototypes for the file fastio.c
*************************************************************************/
extern BOOLEAN STDCALL Ext2FastIoCheckIfPossible(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN BOOLEAN CheckForReadOperation,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoQueryBasicInfo(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
OUT PFILE_BASIC_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoQueryStdInfo(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
OUT PFILE_STANDARD_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoLock(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length,
PEPROCESS ProcessId,
ULONG Key,
BOOLEAN FailImmediately,
BOOLEAN ExclusiveLock,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoUnlockSingle(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length,
PEPROCESS ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoUnlockAll(
IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoUnlockAllByKey(
IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern void STDCALL Ext2FastIoAcqCreateSec(
IN PFILE_OBJECT FileObject);
extern void STDCALL Ext2FastIoRelCreateSec(
IN PFILE_OBJECT FileObject);
extern BOOLEAN STDCALL Ext2AcqLazyWrite(
IN PVOID Context,
IN BOOLEAN Wait);
extern void STDCALL Ext2RelLazyWrite(
IN PVOID Context);
extern BOOLEAN STDCALL Ext2AcqReadAhead(
IN PVOID Context,
IN BOOLEAN Wait);
extern void STDCALL Ext2RelReadAhead(
IN PVOID Context);
// the remaining are only valid under NT Version 4.0 and later
#if(_WIN32_WINNT >= 0x0400)
extern BOOLEAN STDCALL Ext2FastIoQueryNetInfo(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoMdlRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoMdlReadComplete(
IN PFILE_OBJECT FileObject,
OUT PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoPrepareMdlWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject);
extern BOOLEAN STDCALL Ext2FastIoMdlWriteComplete(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
OUT PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject);
extern NTSTATUS STDCALL Ext2FastIoAcqModWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER EndingOffset,
OUT PERESOURCE *ResourceToRelease,
IN PDEVICE_OBJECT DeviceObject);
extern NTSTATUS STDCALL Ext2FastIoRelModWrite(
IN PFILE_OBJECT FileObject,
IN PERESOURCE ResourceToRelease,
IN PDEVICE_OBJECT DeviceObject);
extern NTSTATUS STDCALL Ext2FastIoAcqCcFlush(
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject);
extern NTSTATUS STDCALL Ext2FastIoRelCcFlush(
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject);
#endif // (_WIN32_WINNT >= 0x0400)
/*************************************************************************
* Prototypes for the file DiskIO.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2ReadLogicalBlocks(
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
VOID *Buffer, // The Buffer that takes the data read in
LARGE_INTEGER StartLogicalBlock, // The logical block from which reading is to start
unsigned int NoOfLogicalBlocks); // The no. of logical blocks to be read
extern NTSTATUS STDCALL Ext2ReadPhysicalBlocks(
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
VOID *Buffer, // The Buffer that takes the data read in
LARGE_INTEGER StartBlock, // The Physical block from which reading is to start
unsigned int NoOfBlocks); // The no. of Physical blocks to be read
/*************************************************************************
* Prototypes for the file metadata.c
*************************************************************************/
extern void STDCALL Ext2InitializeFCBInodeInfo (
PtrExt2FCB PtrFCB );
extern NTSTATUS STDCALL Ext2ReadInode(
PtrExt2VCB PtrVcb, // the Volume Control Block
uint32 InodeNo, // The Inode no
PEXT2_INODE PtrInode ); // The Inode Buffer
extern NTSTATUS STDCALL Ext2WriteInode(
PtrExt2IrpContext PtrIrpContext,
PtrExt2VCB PtrVcb, // the Volume Control Block
uint32 InodeNo, // The Inode no
PEXT2_INODE PtrInode // The Inode Buffer
);
extern ULONG STDCALL Ext2AllocInode(
PtrExt2IrpContext PtrIrpContext,
PtrExt2VCB PtrVCB,
ULONG ParentINodeNo );
extern BOOLEAN STDCALL Ext2DeallocInode(
PtrExt2IrpContext PtrIrpContext,
PtrExt2VCB PtrVCB,
ULONG INodeNo );
extern BOOLEAN STDCALL Ext2MakeNewDirectoryEntry(
PtrExt2IrpContext PtrIrpContext, // The Irp context
PtrExt2FCB PtrParentFCB, // Parent Folder FCB
PFILE_OBJECT PtrFileObject, // Parent Folder Object
PUNICODE_STRING PtrName, // New entry's name
ULONG Type, // The type of the new entry
ULONG NewInodeNo); // The inode no of the new entry...
extern BOOLEAN STDCALL Ext2FreeDirectoryEntry(
PtrExt2IrpContext PtrIrpContext,
PtrExt2FCB PtrParentFCB,
PUNICODE_STRING PtrName);
extern BOOLEAN STDCALL Ext2AddBlockToFile(
PtrExt2IrpContext PtrIrpContext,
PtrExt2VCB PtrVCB,
PtrExt2FCB PtrFCB,
PFILE_OBJECT PtrFileObject,
BOOLEAN UpdateFileSize);
extern BOOLEAN STDCALL Ext2ReleaseDataBlocks(
PtrExt2FCB PtrFCB,
PtrExt2IrpContext PtrIrpContext);
extern BOOLEAN STDCALL Ext2TruncateFileAllocationSize(
PtrExt2IrpContext PtrIrpContext,
PtrExt2FCB PtrFCB,
PFILE_OBJECT PtrFileObject,
PLARGE_INTEGER PtrAllocationSize );
extern ULONG STDCALL Ext2AllocBlock(
PtrExt2IrpContext PtrIrpContext,
PtrExt2VCB PtrVCB,
ULONG Count);
extern BOOLEAN STDCALL Ext2DeallocBlock(
PtrExt2IrpContext PtrIrpContext,
PtrExt2VCB PtrVCB,
ULONG BlockNo);
extern BOOLEAN STDCALL Ext2UpdateFileSize(
PtrExt2IrpContext PtrIrpContext,
PFILE_OBJECT PtrFileObject,
PtrExt2FCB PtrFCB);
extern BOOLEAN STDCALL Ext2DeleteFile(
PtrExt2FCB PtrFCB,
PtrExt2IrpContext PtrIrpContext);
extern BOOLEAN STDCALL Ext2IsDirectoryEmpty(
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB,
PtrExt2IrpContext PtrIrpContext);
extern NTSTATUS STDCALL Ext2RenameOrLinkFile(
PtrExt2FCB PtrSourceFCB,
PFILE_OBJECT PtrSourceFileObject,
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PFILE_RENAME_INFORMATION PtrRenameInfo);
/*************************************************************************
* Prototypes for the file io.c
*************************************************************************/
extern NTSTATUS STDCALL Ext2PassDownSingleReadWriteIRP(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PtrExt2VCB PtrVCB,
LARGE_INTEGER ByteOffset,
uint32 ReadWriteLength,
BOOLEAN SynchronousIo);
extern NTSTATUS STDCALL Ext2PassDownMultiReadWriteIRP(
PEXT2_IO_RUN PtrIoRuns,
UINT Count,
ULONG TotalReadWriteLength,
PtrExt2IrpContext PtrIrpContext,
PtrExt2FCB PtrFCB,
BOOLEAN SynchronousIo);
extern NTSTATUS STDCALL Ext2SingleSyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
);
extern NTSTATUS STDCALL Ext2SingleAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
);
extern NTSTATUS STDCALL Ext2MultiSyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt);
extern NTSTATUS STDCALL Ext2MultiAsyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt);
#endif // _EXT2_PROTOS_H_

View file

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by D:\Work\VC\Drivers\ext2FSD\src\ext2.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -0,0 +1,674 @@
/*************************************************************************
*
* File: struct.h
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* This file contains structure definitions for the sample file system
* driver. Note that all structures are prefixed with the letters
* "Ext2". The structures are all aligned using normal alignment
* used by the compiler (typically quad-word aligned).
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#ifndef _EXT2_STRUCTURES_H_
#define _EXT2_STRUCTURES_H_
/**************************************************************************
some useful definitions
**************************************************************************/
#ifdef _CPU_X86_
typedef char int8;
typedef short int16;
typedef int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef PVOID PBCB;
// we will use the LARGE_INTEGER structure as defined by NT
#else // Please define appropriate types here
!!!! You must define your types here for compilation to proceed !!!!
#endif // if _CPU_X86_
/**************************************************************************
some empty typedefs defined here so we can reference them easily
**************************************************************************/
struct _Ext2Identifier;
struct _Ext2ObjectName;
struct _Ext2ContextControlBlock;
struct _Ext2NTRequiredFCB;
struct _Ext2DiskDependentFCB;
struct _Ext2FileControlBlock;
struct _Ext2FileByteLocks;
struct _Ext2VolumeControlBlock;
struct _Ext2IrpContext;
struct _Ext2Data;
/**************************************************************************
each structure has a unique "node type" or signature associated with it
**************************************************************************/
#define EXT2_NODE_TYPE_OBJECT_NAME (0xfdecba01)
#define EXT2_NODE_TYPE_CCB (0xfdecba02)
#define EXT2_NODE_TYPE_FCB (0xfdecba03)
#define EXT2_NODE_TYPE_LOCKS (0xfdecba04)
#define EXT2_NODE_TYPE_VCB (0xfdecba05)
#define EXT2_NODE_TYPE_IRP_CONTEXT (0xfdecba06)
#define EXT2_NODE_TYPE_GLOBAL_DATA (0xfdecba07)
#define EXT2_NODE_TYPE_IO_CONTEXT (0xfdecba08)
#define EXT2_NODE_TYPE_SAVED_BCB (0xfdecba09)
#define EXT2_NODE_TYPE_FREED (0x10101010)
#define EXT2_NODE_TYPE_INVALID (0x10101010)
/**************************************************************************
every structure has a node type, and a node size associated with it.
The node type serves as a signature field. The size is used for
consistency checking ...
**************************************************************************/
typedef struct _Ext2Identifier {
uint32 NodeType; // a 32 bit identifier for the structure
uint32 NodeSize; // computed as sizeof(structure)
} Ext2Identifier, *PtrExt2Identifier;
/**************************************************************************
Structures for byte-range lock support.
**************************************************************************/
typedef struct Ext2FileLockAnchor {
LIST_ENTRY GrantedFileLockList;
LIST_ENTRY PendingFileLockList;
} Ext2FileLockAnchor, *PtrExt2FileLockAnchor;
typedef struct Ext2FileLockInfo {
Ext2Identifier NodeIdentifier;
uint32 FileLockFlags;
PVOID OwningProcess;
LARGE_INTEGER StartingOffset;
LARGE_INTEGER Length;
LARGE_INTEGER EndingOffset;
ULONG Key;
BOOLEAN ExclusiveLock;
PIRP PendingIRP;
LIST_ENTRY NextFileLockEntry;
} Ext2FileLockInfo, *PtrExt2FileLockInfo;
#define EXT2_BYTE_LOCK_NOT_FROM_ZONE (0x80000000)
#define EXT2_BYTE_LOCK_IS_PENDING (0x00000001)
/**************************************************************************
Every open on-disk object must have a name associated with it
This name has two components:
(a) the path-name (prefix) that leads to this on-disk object
(b) the name of the object itself
Note that with multiply linked objects, a single object might be
associated with more than one name structure.
This sample FSD does not correctly support multiply linked objects.
This structure must be quad-word aligned because it is zone allocated.
**************************************************************************/
typedef struct _Ext2ObjectName {
Ext2Identifier NodeIdentifier;
uint32 ObjectNameFlags;
// an absolute pathname of the object is stored below
UNICODE_STRING ObjectName;
} Ext2ObjectName, *PtrExt2ObjectName;
#define EXT2_OB_NAME_NOT_FROM_ZONE (0x80000000)
/**************************************************************************
Each file open instance is represented by a context control block.
For each successful create/open request; a file object and a CCB will
be created.
For open operations performed internally by the FSD, there may not
exist file objects; but a CCB will definitely be created.
This structure must be quad-word aligned because it is zone allocated.
**************************************************************************/
typedef struct _Ext2ContextControlBlock {
Ext2Identifier NodeIdentifier;
// ptr to the associated FCB
struct _Ext2FileControlBlock *PtrFCB;
// all CCB structures for a FCB are linked together
LIST_ENTRY NextCCB;
// each CCB is associated with a file object
PFILE_OBJECT PtrFileObject;
// flags (see below) associated with this CCB
uint32 CCBFlags;
// current byte offset is required sometimes
LARGE_INTEGER CurrentByteOffset;
// if this CCB represents a directory object open, we may
// need to maintain a search pattern
// PSTRING DirectorySearchPattern;
UNICODE_STRING DirectorySearchPattern;
// The full path name for the file...
UNICODE_STRING AbsolutePathName;
// Rename/Link Target file name
// Used only in a Rename/Link operation
UNICODE_STRING RenameLinkTargetFileName;
// we must maintain user specified file time values
uint32 UserSpecifiedTime;
} Ext2CCB, *PtrExt2CCB;
/**************************************************************************
the following CCBFlags values are relevant. These flag
values are bit fields; therefore we can test whether
a bit position is set (1) or not set (0).
**************************************************************************/
// some on-disk file/directories are opened by EXT2 itself
// as opposed to being opened on behalf of a user process
#define EXT2_CCB_OPENED_BY_EXT2 (0x00000001)
// the file object specified synchronous access at create/open time.
// this implies that EXT2 must maintain the current byte offset
#define EXT2_CCB_OPENED_FOR_SYNC_ACCESS (0x00000002)
// file object specified sequential access for this file
#define EXT2_CCB_OPENED_FOR_SEQ_ACCESS (0x00000004)
// the CCB has had an IRP_MJ_CLEANUP issued on it. we must
// no longer allow the file object / CCB to be used in I/O requests.
#define EXT2_CCB_CLEANED (0x00000008)
// if we were invoked via the fast i/o path to perform file i/o;
// we should set the CCB access/modification time at cleanup
#define EXT2_CCB_ACCESSED (0x00000010)
#define EXT2_CCB_MODIFIED (0x00000020)
// if an application process set the file date time, we must
// honor that request and *not* overwrite the values at cleanup
#define EXT2_CCB_ACCESS_TIME_SET (0x00000040)
#define EXT2_CCB_MODIFY_TIME_SET (0x00000080)
#define EXT2_CCB_CREATE_TIME_SET (0x00000100)
#define EXT2_CCB_NOT_FROM_ZONE (0x80000000)
// this CCB was allocated for a "volume open" operation
#define EXT2_CCB_VOLUME_OPEN (0x00000100)
/**************************************************************************
each open file/directory/volume is represented by a file control block.
NOTE: Currently, EXT2 does not handle multiply linked files correctly.
In your FSD implementation, you must be careful about handling
such on-disk files correctly i.e. a single (unique) FCB must
represent an on-disk file/directory regardless of the path used
to access the on-disk object.
With the current EXT2 implementation, an on-disk file object
with more than a single (hard) link will be treated incorrectly!
Each FCB can logically be divided into two:
(a) a structure that must have a field of type FSRTL_COMMON_FCB_HEADER
as the first field in the structure.
This portion should also contain other structures/resources required
by the NT Cache Manager
We will call this structure the "NT Required" FCB. Note that this
portion of the FCB must be allocated from non-paged pool.
(b) the remainder of the FCB is dependent upon the particular FSD
requirements.
This portion of the FCB could possibly be allocated from paged
memory, though in the sample FSD, it will always be allocated
from non-paged pool.
FCB structures are protected by the MainResource as well as the
PagingIoResource. Of course, if your FSD implementation requires
it, you can associate other syncronization structures with the
FCB.
This structure must be quad-word aligned because it is zone allocated.
**************************************************************************/
typedef struct _Ext2NTRequiredFCB
{
FSRTL_COMMON_FCB_HEADER CommonFCBHeader;
SECTION_OBJECT_POINTERS SectionObject;
ERESOURCE MainResource;
ERESOURCE PagingIoResource;
} Ext2NTRequiredFCB, *PtrExt2NTRequiredFCB;
typedef struct _Ext2DiskDependentFCB
{
// although the sample FSD does not maintain on-disk data structures,
// this structure serves as a reminder of the logical separation that
// your FSD can maintain between the disk dependent and the disk
// independent portions of the FCB.
uint16 DummyField; // placeholder
} Ext2DiskDependentFCB, *PtrExt2DiskDependentFCB;
typedef struct _Ext2FileControlBlock
{
Ext2Identifier NodeIdentifier;
// we will go ahead and embed the "NT Required FCB" right here.
// Note though that it is just as acceptable to simply allocate
// memory separately for the other half of the FCB and store a
// pointer to the "NT Required" portion here instead of embedding
// it ...
Ext2NTRequiredFCB NTRequiredFCB;
// the disk dependent portion of the FCB is embedded right here
Ext2DiskDependentFCB DiskDependentFCB;
// this FCB belongs to some mounted logical volume
struct _Ext2VolumeControlBlock *PtrVCB;
// to be able to access all open file(s) for a volume, we will
// link all FCB structures for a logical volume together
LIST_ENTRY NextFCB;
// to be used if this FCB is on the Closable FCB List...
struct _ClosableFCBs
{
LIST_ENTRY ClosableFCBList;
BOOLEAN OnClosableFCBList;
}ClosableFCBs;
// some state information for the FCB is maintained using the
// flags field
uint32 FCBFlags;
// all CCB's for this particular FCB are linked off the following
// list head.
LIST_ENTRY CCBListHead;
// NT requires that a file system maintain and honor the various
// SHARE_ACCESS modes ...
SHARE_ACCESS FCBShareAccess;
// to identify the lazy writer thread(s) we will grab and store
// the thread id here when a request to acquire resource(s)
// arrives ..
uint32 LazyWriterThreadID;
// whenever a file stream has a create/open operation performed,
// the Reference count below is incremented AND the OpenHandle count
// below is also incremented.
// When an IRP_MJ_CLEANUP is received, the OpenHandle count below
// is decremented.
// When an IRP_MJ_CLOSE is received, the Reference count below is
// decremented.
// When the Reference count goes down to zero, the FCB can be de-allocated.
// Note that a zero Reference count implies a zero OpenHandle count.
// This invariant must always hold true ... (if it is really an invariant,
// shoudn't the previous statement be redundant ... hmmm!!!)
LONG ReferenceCount;
LONG OpenHandleCount;
// for the sample fsd, there exists a 1-1 correspondence between an
// object name structure and a FCB
PtrExt2ObjectName FCBName;
// we will maintain some time information here to make our life easier
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
// Byte-range file lock support (we roll our own)
Ext2FileLockAnchor FCBByteRangeLock;
// The OPLOCK support package requires the following structure
OPLOCK FCBOplock;
// The I-Node no of this file / folder
ULONG INodeNo;
ULONG ParentINodeNo;
// Pointers to blocks
uint32 IBlock[EXT2_N_BLOCKS];
USHORT LinkCount;
union _DCBFCB
{
struct
{
PFILE_OBJECT PtrDirFileObject;
} Dcb;
struct _FCB
{
PFILE_OBJECT PtrDirFileObject;
// FCB specific stuff go here...
} Fcb;
}DcbFcb;
} Ext2FCB, *PtrExt2FCB, Ext2DCB, *PtrExt2DCB;
/**************************************************************************
the following FCBFlags values are relevant. These flag
values are bit fields; therefore we can test whether
a bit position is set (1) or not set (0).
**************************************************************************/
#define EXT2_FCB_IN_INIT (0x00000001)
#define EXT2_FCB_IN_TEARDOWN (0x00000002)
#define EXT2_FCB_PAGE_FILE (0x00000004)
#define EXT2_FCB_DIRECTORY (0x00000008)
#define EXT2_FCB_ROOT_DIRECTORY (0x00000018)
#define EXT2_FCB_WRITE_THROUGH (0x00000020)
#define EXT2_FCB_MAPPED (0x00000040)
#define EXT2_FCB_FAST_IO_READ_IN_PROGESS (0x00000080)
#define EXT2_FCB_FAST_IO_WRITE_IN_PROGESS (0x00000100)
#define EXT2_FCB_DELETE_ON_CLOSE (0x00000200)
#define EXT2_FCB_MODIFIED (0x00000400)
#define EXT2_FCB_ACCESSED (0x00000800)
#define EXT2_FCB_READ_ONLY (0x00001000)
#define EXT2_INITIALIZED_MAIN_RESOURCE (0x00002000)
#define EXT2_INITIALIZED_PAGING_IO_RESOURCE (0x00004000)
#define EXT2_FCB_BLOCKS_INITIALIZED (0x00008000)
#define EXT2_FCB_SPECIAL_FILE (0x00010000)
#define EXT2_FCB_HIDDEN_FILE (0x00020000)
#define EXT2_FCB_NOT_FROM_ZONE (0x80000000)
typedef struct _GroupDescriptors
{
uint32 InodeTablesBlock; /* Inodes table block => bg_inode_table */
uint32 InodeBitmapBlock; /* Inodes bitmap block => bg_inode_bitmap */
uint32 BlockBitmapBlock; /* Blocks bitmap block => bg_block_bitmap */
uint32 FreeBlocksCount;
uint32 FreeInodesCount;
}Ext2GroupDescriptors, *PtrExt2GroupDescriptors;
/**************************************************************************
A logical volume is represented using the following structure.
This structure is allocated as part of the device extension
for a device object that this sample FSD will create, to represent
the mounted logical volume.
NOTE: If you were to extend this sample FSD to be a "real" FSD,
you would be worried about allocated clusters/sectiors,
bitmaps providing such information for the mounted volume,
dirty/modified clusters/sectiors etc.
This sample FSD does not maintain such information in the
in-memory VCB, though you may wish to consider it.
**************************************************************************/
typedef struct _Ext2VolumeControlBlock
{
Ext2Identifier NodeIdentifier;
// Required to use the Cache Manager.
FSRTL_COMMON_FCB_HEADER CommonVCBHeader;
SECTION_OBJECT_POINTERS SectionObject;
// a resource to protect the fields contained within the VCB
ERESOURCE VCBResource;
// a resource to synchronise paging io
ERESOURCE PagingIoResource;
// Pointer to a stream file object created for the volume information
// to be more easily read from secondary storage (with the support of
// the NT Cache Manager).
PFILE_OBJECT PtrStreamFileObject;
// each VCB is accessible off a global linked list
LIST_ENTRY NextVCB;
// each VCB points to a VPB structure created by the NT I/O Manager
PVPB PtrVPB;
// a set of flags that might mean something useful
uint32 VCBFlags;
// A count of the number of open files/directories
// As long as the count is != 0, the volume cannot
// be dismounted or locked.
uint32 VCBOpenCount;
// a global list of all FCB structures associated with the VCB
LIST_ENTRY FCBListHead;
//
// a list of FCBs created at the FSD's initiative...
// These FCBs have a reference count of 0
// This list should never be allowed to cross a limit...
//
struct Ext2ClosableFCB
{
LIST_ENTRY ClosableFCBListHead;
ULONG Count;
}ClosableFCBs;
// we will maintain a global list of IRP's that are pending
// because of a directory notify request.
LIST_ENTRY NextNotifyIRP;
// the above list is protected only by the mutex declared below
KMUTEX NotifyIRPMutex;
// for each mounted volume, we create a device object. Here then
// is a back pointer to that device object
PDEVICE_OBJECT VCBDeviceObject;
// We also retain a pointer to the physical device object on which we
// have mounted ourselves. The I/O Manager passes us a pointer to this
// device object when requesting a mount operation.
PDEVICE_OBJECT TargetDeviceObject;
// the volume structure contains a pointer to the root directory FCB
PtrExt2FCB PtrRootDirectoryFCB;
// the complete name of the user visible drive letter we serve
uint8 *PtrVolumePath;
// For volume open operations, we do not create a FCB (we use the VCB
// directly instead). Therefore, all CCB structures for the volume
// open operation are linked directly off the VCB
LIST_ENTRY VolumeOpenListHead;
// Volume information
ULONG BlocksCount;
ULONG InodesCount;
ULONG ReservedBlocksCount;
ULONG FreeBlocksCount;
ULONG FreeInodesCount;
ULONG LogBlockSize; // Block size = 1024 << LogBlockSize
// Group Information Saved up in the VCB...
PtrExt2GroupDescriptors PtrGroupDescriptors;
ULONG NoOfGroups;
uint32 InodesPerGroup;
uint32 BlocksPerGroup;
} Ext2VCB, *PtrExt2VCB;
// some valid flags for the VCB
#define EXT2_VCB_FLAGS_VOLUME_MOUNTED (0x00000001)
#define EXT2_VCB_FLAGS_VOLUME_LOCKED (0x00000002)
#define EXT2_VCB_FLAGS_BEING_DISMOUNTED (0x00000004)
#define EXT2_VCB_FLAGS_SHUTDOWN (0x00000008)
#define EXT2_VCB_FLAGS_VOLUME_READ_ONLY (0x00000010)
#define EXT2_VCB_FLAGS_VCB_INITIALIZED (0x00000020)
typedef struct _EXT2_IO_CONTEXT
{
Ext2Identifier NodeIdentifier;
ULONG ReadWriteLength;
LONG Count;
PIRP PtrMasterIrp;
PKEVENT PtrSyncEvent;
} EXT2_IO_CONTEXT, *PEXT2_IO_CONTEXT;
typedef struct _Ext2SavedBCBs
{
Ext2Identifier NodeIdentifier;
PBCB PtrBCB;
LIST_ENTRY SavedBCBsListEntry;
} EXT2_SAVED_BCBS, *PEXT2_SAVED_BCBS;
/**************************************************************************
The IRP context encapsulates the current request. This structure is
used in the "common" dispatch routines invoked either directly in
the context of the original requestor, or indirectly in the context
of a system worker thread.
**************************************************************************/
typedef struct _Ext2IrpContext
{
Ext2Identifier NodeIdentifier;
uint32 IrpContextFlags;
// copied from the IRP
uint8 MajorFunction;
// copied from the IRP
uint8 MinorFunction;
// to queue this IRP for asynchronous processing
WORK_QUEUE_ITEM WorkQueueItem;
// the IRP for which this context structure was created
PIRP Irp;
// the target of the request (obtained from the IRP)
PDEVICE_OBJECT TargetDeviceObject;
// if an exception occurs, we will store the code here
NTSTATUS SavedExceptionCode;
// This list entry is used if asnchronous processing is required...
LIST_ENTRY ThreadQueueListEntry;
// This list entry is used if BCBs are to be saved and then flushed...
// Could have been put somewhere else...
LIST_ENTRY SavedBCBsListHead;
ULONG SavedCount;
} Ext2IrpContext, *PtrExt2IrpContext;
#define EXT2_IRP_CONTEXT_CAN_BLOCK (0x00000001)
#define EXT2_IRP_CONTEXT_WRITE_THROUGH (0x00000002)
#define EXT2_IRP_CONTEXT_EXCEPTION (0x00000004)
#define EXT2_IRP_CONTEXT_DEFERRED_WRITE (0x00000008)
#define EXT2_IRP_CONTEXT_ASYNC_PROCESSING (0x00000010)
#define EXT2_IRP_CONTEXT_NOT_TOP_LEVEL (0x00000020)
#define EXT2_IRP_CONTEXT_NOT_FROM_ZONE (0x80000000)
typedef struct _Ext2ThreadQueue
{
HANDLE QueueHandlerThread;
LIST_ENTRY ThreadQueueListHead; // This holds the Contexts
// that are to be scheduled
KSPIN_LOCK SpinLock; // To synchronize access to
// the list
KEVENT QueueEvent; // The Worker thread queue
// package waits on this event
} Ext2ThreadQueue;
/**************************************************************************
we will store all of our global variables in one structure.
Global variables are not specific to any mounted volume BUT
by definition are required for successful operation of the
FSD implementation.
**************************************************************************/
typedef struct _Ext2Data
{
Ext2Identifier NodeIdentifier;
// the fields in this list are protected by the following resource
ERESOURCE GlobalDataResource;
// each driver has a driver object created for it by the NT I/O Mgr.
// we are no exception to this rule.
PDRIVER_OBJECT Ext2DriverObject;
// we will create a device object for our FSD as well ...
// Although not really required, it helps if a helper application
// writen by us wishes to send us control information via
// IOCTL requests ...
PDEVICE_OBJECT Ext2DeviceObject;
// we will keep a list of all logical volumes for our sample FSD
LIST_ENTRY NextVCB;
// the NT Cache Manager, the I/O Manager and we will conspire
// to bypass IRP usage using the function pointers contained
// in the following structure
FAST_IO_DISPATCH Ext2FastIoDispatch;
// The NT Cache Manager uses the following call backs to ensure
// correct locking hierarchy is maintained
CACHE_MANAGER_CALLBACKS CacheMgrCallBacks;
// structures allocated from a zone need some fields here. Note
// that under version 4.0, it might be better to use lookaside
// lists
KSPIN_LOCK ZoneAllocationSpinLock;
ZONE_HEADER ObjectNameZoneHeader;
ZONE_HEADER CCBZoneHeader;
ZONE_HEADER FCBZoneHeader;
ZONE_HEADER ByteLockZoneHeader;
ZONE_HEADER IrpContextZoneHeader;
void *ObjectNameZone;
void *CCBZone;
void *FCBZone;
void *ByteLockZone;
void *IrpContextZone;
// currently, there is a single default zone size value used for
// all zones. This should ideally be changed by you to be 1 per
// type of zone (e.g. a default size for the FCB zone might be
// different from the default size for the ByteLock zone).
// Of course, you will need to use different values (min/max)
// for lookaside lists (if you decide to use them instead)
uint32 DefaultZoneSizeInNumStructs;
// some state information is maintained in the flags field
uint32 Ext2Flags;
// Handle returned by the MUP is stored here.
HANDLE MupHandle;
// Time difference
LARGE_INTEGER TimeDiff;
// The Worker Thread package uses this structure...
Ext2ThreadQueue ThreadQueue;
}Ext2Data, *PtrExt2Data;
// valid flag values for the global data structure
#define EXT2_DATA_FLAGS_RESOURCE_INITIALIZED (0x00000001)
#define EXT2_DATA_FLAGS_ZONES_INITIALIZED (0x00000002)
// a default size of the number of pages of non-paged pool allocated
// for each of the zones ...
// Note that the values are absolutely arbitrary, the only information
// worth using from the values themselves is that they increase for
// larger systems (i.e. systems with more memory)
#define EXT2_DEFAULT_ZONE_SIZE_SMALL_SYSTEM (0x4)
#define EXT2_DEFAULT_ZONE_SIZE_MEDIUM_SYSTEM (0x8)
#define EXT2_DEFAULT_ZONE_SIZE_LARGE_SYSTEM (0xc)
// another simplistic (brain dead ? :-) method used is to simply double
// the values for a "server" machine
// So, for all you guys who "modified" the registry ;-) to change the
// wkstation into a server, tough luck !
#define EXT2_NTAS_MULTIPLE (0x2)
/***************************************************************************
The following locking hierarchy is maintained in this sample filesystem
driver:
(a) the global structure resource can be acquired at any time. However,
it is an "end resource" i.e. once acquired, no other resource can
be obtained until the global structure resource is released.
(b) the logical volume resource must be acquired (if required) before
any of the other resources are acquired.
(c) a file control block can be acquired next (if required). If two
FCB structures need to be acquired, the FCB "higher" in the directory
tree must be acquired first.
For a FCB, the "main resource" must be acquired first before a
"paging i/o" resource is acquired.
Whenever a file is opened, the logical volume structure is referenced.
This ensures that the volume cannot be dismounted while any file is open.
***************************************************************************/
typedef struct _IO_RUN
{
UINT LogicalBlock;
UINT StartOffset;
UINT EndOffset;
PIRP PtrAssociatedIrp;
} EXT2_IO_RUN, *PEXT2_IO_RUN;
typedef struct _SIBlocks
{
PBCB PtrBCB;
ULONG * PtrSIBlocks;
} EXT2_SIBLOCKS, *PEXT2_SIBLOCKS;
#endif // has this file been included?

View file

@ -1,148 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/inode.c
* PURPOSE: Manipulating inodes
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
* 26/12/98: Created
*/
/* INCLUDES ****************************************************************/
#include <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS ***************************************************************/
struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt,
ULONG block_group)
{
struct ext2_group_desc* buffer;
ULONG block;
struct ext2_group_desc* gdp;
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
block = block_group / (BLOCKSIZE / sizeof(struct ext2_group_desc));
Ext2ReadSectors(DeviceExt->StorageDevice,
2 + block,
1,
buffer);
gdp = &buffer[block_group % (BLOCKSIZE / sizeof(struct ext2_group_desc))];
DPRINT("gdp->bg_free_blocks_count %d\n",gdp->bg_free_blocks_count);
DPRINT("gdp->bg_inode_table %d\n",gdp->bg_inode_table);
return(gdp);
}
#define INODES_PER_PAGE (PAGE_SIZE / sizeof(struct ext2_inode))
#define INODES_PER_BLOCK (BLOCKSIZE / sizeof(struct ext2_inode))
VOID Ext2LoadInode(PDEVICE_EXTENSION DeviceExt,
ULONG ino,
PEXT2_INODE Inode)
{
ULONG block_group;
struct ext2_group_desc* gdp;
ULONG offset;
ULONG dsec;
BOOLEAN Uptodate;
struct ext2_inode* ibuffer;
DPRINT("Ext2LoadInode(DeviceExt %x, ino %d, Inode %x)\n",
DeviceExt, ino, Inode);
block_group = (ino - 1) / DeviceExt->superblock->s_inodes_per_group;
DPRINT("block_group %d\n",block_group);
gdp = Ext2LoadGroupDesc(DeviceExt, block_group);
offset = (ino - 1) % DeviceExt->superblock->s_inodes_per_group;
DPRINT("offset %d\n", offset);
dsec = (gdp->bg_inode_table + (offset / INODES_PER_BLOCK)) * BLOCKSIZE;
DPRINT("dsec %d (dsec/BLOCKSIZE) %d PAGE_ROUND_DOWN(dsec) %d\n",
dsec, (dsec/BLOCKSIZE), PAGE_ROUND_DOWN(dsec));
CcRequestCachePage(DeviceExt->Bcb,
PAGE_ROUND_DOWN(dsec),
&Inode->BaseAddress,
&Uptodate,
&Inode->CacheSeg);
DPRINT("PAGE_ROUND_DOWN(dsec)/BLOCKSIZE %d\n",
PAGE_ROUND_DOWN(dsec)/BLOCKSIZE);
if (!Uptodate)
{
Ext2ReadSectors(DeviceExt->StorageDevice,
PAGE_ROUND_DOWN(dsec) / BLOCKSIZE,
4,
Inode->BaseAddress);
}
ibuffer = ((struct ext2_inode *)Inode->BaseAddress) +
(dsec - PAGE_ROUND_DOWN(dsec));
DPRINT("Inode->BaseAddress 0x%x ibuffer 0x%x\n",
Inode->BaseAddress, ibuffer);
Inode->inode = &ibuffer[offset % INODES_PER_PAGE];
DPRINT("inode->i_uid %d\n",Inode->inode->i_uid);
DPRINT("inode->i_links_count %d\n",Inode->inode->i_links_count);
DPRINT("inode->i_blocks %d\n",Inode->inode->i_blocks);
DPRINT("Ext2LoadInode() finished\n");
}
VOID Ext2ReleaseInode(PDEVICE_EXTENSION DeviceExt,
PEXT2_INODE Inode)
{
CcReleaseCachePage(DeviceExt->Bcb,
Inode->CacheSeg,
TRUE);
Inode->CacheSeg = NULL;
Inode->BaseAddress = NULL;
Inode->inode = NULL;
}
VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt,
ULONG ino,
struct ext2_inode* inode)
{
ULONG block_group;
struct ext2_group_desc* gdp;
ULONG offset;
struct ext2_inode* buffer;
DPRINT("Ext2ReadInode(DeviceExt %x, ino %d, inode %x)\n",
DeviceExt,ino,inode);
block_group = (ino - 1) / DeviceExt->superblock->s_inodes_per_group;
gdp = Ext2LoadGroupDesc(DeviceExt, block_group);
offset = (ino - 1) % DeviceExt->superblock->s_inodes_per_group;
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
Ext2ReadSectors(DeviceExt->StorageDevice,
gdp->bg_inode_table + (offset / INODES_PER_BLOCK),
1,
buffer);
memcpy(inode,&buffer[offset % INODES_PER_BLOCK],sizeof(struct ext2_inode));
DPRINT("inode->i_uid %d\n",inode->i_uid);
DPRINT("inode->i_links_count %d\n",inode->i_links_count);
DPRINT("inode->i_blocks %d\n",inode->i_blocks);
}

View file

@ -1,26 +1,54 @@
# $Id$
PATH_TO_TOP = ../../..
TARGET_BOOTSTRAP = yes
TARGET_TYPE = driver
TARGET_NAME = ext2
TARGET_GCCLIBS = gcc
TARGET_CFLAGS = -Iinc -I$(W32API_PATH)/include/ddk -D__USE_W32API \
-D_CPU_X86_ -O2 -DDBG=1 -D__REACTOS__
TARGET_NAME = ext2fs
# FIXME: Enabling this reveals that there is quite a few pieces of unused
# code.
#TARGET_CFLAGS += -Wall
TARGET_CFLAGS = -I./include -DDBG
# FIXME: Do not b*tch about multi-character constants used for TAGs. Use
# the TAG macro instead?
TARGET_CFLAGS += -Wno-multichar
# FIXME: Force STDCALL as default calling convention. Due bug in GCC it
# it still produces non-STDCALL function if an function declaration
# preceeds the actual function definition and doesn't explicitely
# specify calling convention.
TARGET_CFLAGS += -mrtd
# FIXME: Until PSEH and MS2PS will get up to speed we'll ignore SEH.
TARGET_CFLAGS += "-Dtry=if(1)" "-Dexcept(x)=if(0)" "-Dfinally=if(1)"
TARGET_OBJECTS = \
attr.o \
blockdev.o \
dir.o \
file.o \
inode.o \
rw.o \
quota.o \
security.o \
super.o
src/cleanup.o \
src/close.o \
src/create.o \
src/devcntrl.o \
src/dircntrl.o \
src/DiskIO.o \
src/ext2init.o \
src/fastio.o \
src/fileinfo.o \
src/flush.o \
src/fsctrl.o \
src/io.o \
src/metadata.o \
src/misc.o \
src/read.o \
src/shutdown.o \
src/volinfo.o \
src/write.o
TARGET_RC_SRCS = src/ext2.rc
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(PATH_TO_TOP)/config
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
# EOF
include $(TOOLS_PATH)/depend.mk

View file

@ -1,49 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/quota.c
* PURPOSE: Quota support
* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <wchar.h>
#include <string.h>
//#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS STDCALL
Ext2QueryQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}
NTSTATUS STDCALL
Ext2SetQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}

View file

@ -1,219 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/super.c
* PURPOSE: ext2 filesystem
* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <string.h>
#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS Ext2ReadPage(PDEVICE_EXTENSION DeviceExt,
PEXT2_FCB Fcb,
PVOID Buffer,
ULONG Offset)
{
ULONG block, i;
for (i=0; i<4; i++)
{
block = Ext2BlockMap(DeviceExt,
Fcb->i.inode,
Offset + i);
Ext2ReadSectors(DeviceExt->StorageDevice,
block,
1,
Buffer + (i*BLOCKSIZE));
}
return(STATUS_SUCCESS);
}
NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PVOID Buffer,
ULONG Length,
LARGE_INTEGER OffsetL)
{
PVOID BaseAddress;
BOOLEAN Uptodate = FALSE;
PCACHE_SEGMENT CacheSeg;
ULONG Offset = (ULONG)OffsetL.u.LowPart;
PEXT2_FCB Fcb;
ULONG block, i, Delta;
DPRINT("Ext2ReadFile(DeviceExt %x, FileObject %x, Buffer %x, Length %d, \n"
"OffsetL %d)\n",DeviceExt,FileObject,Buffer,Length,(ULONG)OffsetL);
Fcb = (PEXT2_FCB)FileObject->FsContext;
Ext2LoadInode(DeviceExt,
Fcb->inode,
&Fcb->i);
if (Offset >= Fcb->i.inode->i_size)
{
DPRINT("Returning end of file\n");
return(STATUS_END_OF_FILE);
}
if ((Offset + Length) > Fcb->i.inode->i_size)
{
Length = Fcb->i.inode->i_size - Offset;
}
Ext2ReleaseInode(DeviceExt,
&Fcb->i);
if ((Offset % PAGE_SIZE) != 0)
{
Delta = min(PAGE_SIZE - (Offset % PAGE_SIZE),Length);
CcRequestCachePage(Fcb->Bcb,
Offset,
&BaseAddress,
&Uptodate,
&CacheSeg);
if (Uptodate == FALSE)
{
Ext2ReadPage(DeviceExt,
Fcb,
BaseAddress,
Offset / BLOCKSIZE);
}
memcpy(Buffer, BaseAddress + (Offset % PAGE_SIZE), Delta);
CcReleaseCachePage(Fcb->Bcb,
CacheSeg,
TRUE);
Length = Length - Delta;
Offset = Offset + Delta;
Buffer = Buffer + Delta;
}
CHECKPOINT;
for (i=0; i<(Length/PAGE_SIZE); i++)
{
CcRequestCachePage(Fcb->Bcb,
Offset,
&BaseAddress,
&Uptodate,
&CacheSeg);
if (Uptodate == FALSE)
{
Ext2ReadPage(DeviceExt,
Fcb,
BaseAddress,
(Offset / BLOCKSIZE));
}
memcpy(Buffer, BaseAddress, PAGE_SIZE);
CcReleaseCachePage(Fcb->Bcb,
CacheSeg,
TRUE);
Length = Length - PAGE_SIZE;
Offset = Offset + PAGE_SIZE;
Buffer = Buffer + PAGE_SIZE;
}
CHECKPOINT;
if ((Length % PAGE_SIZE) != 0)
{
CcRequestCachePage(Fcb->Bcb,
Offset,
&BaseAddress,
&Uptodate,
&CacheSeg);
if (Uptodate == FALSE)
{
Ext2ReadPage(DeviceExt,
Fcb,
BaseAddress,
(Offset / BLOCKSIZE));
}
DPRINT("Copying %x to %x Length %d\n",BaseAddress,Buffer,Length);
memcpy(Buffer,BaseAddress,Length);
CcReleaseCachePage(Fcb->Bcb,
CacheSeg,
TRUE);
}
CHECKPOINT;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
Ext2Write(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT("Ext2Write(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
return(STATUS_UNSUCCESSFUL);
}
NTSTATUS STDCALL
Ext2FlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT("Ext2FlushBuffers(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
return(STATUS_UNSUCCESSFUL);
}
NTSTATUS STDCALL
Ext2Shutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT("Ext2Shutdown(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
return(STATUS_UNSUCCESSFUL);
}
NTSTATUS STDCALL
Ext2Cleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DbgPrint("Ext2Cleanup(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
DbgPrint("Ext2Cleanup() finished\n");
return(STATUS_UNSUCCESSFUL);
}
NTSTATUS STDCALL
Ext2Read(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
ULONG Length;
PVOID Buffer;
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = Stack->FileObject;
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
NTSTATUS Status;
DPRINT("Ext2Read(DeviceObject %x, FileObject %x, Irp %x)\n",
DeviceObject, FileObject, Irp);
Length = Stack->Parameters.Read.Length;
CHECKPOINT;
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
CHECKPOINT;
CHECKPOINT;
Status = Ext2ReadFile(DeviceExt,FileObject,Buffer,Length,
Stack->Parameters.Read.ByteOffset);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return(Status);
}

View file

@ -1,41 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/security.c
* PURPOSE: Security support
* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <wchar.h>
#include <string.h>
//#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS STDCALL
Ext2QuerySecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT("Ext2QuerySecurity(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
return(STATUS_UNSUCCESSFUL);
}
NTSTATUS STDCALL
Ext2SetSecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT("Ext2SetSecurity(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
return(STATUS_UNSUCCESSFUL);
}

View file

@ -0,0 +1,9 @@
base.tmp
junk.tmp
temp.exp
vfatfs.coff
*.d
*.o
*.sys
*.sym
*.map

View file

@ -0,0 +1,215 @@
/*************************************************************************
*
* File: DiskIO.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Should contain code to handle Disk IO.
*
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
#define EXT2_BUG_CHECK_ID EXT2_FILE_DISK_IO
#define DEBUG_LEVEL ( DEBUG_TRACE_DISKIO )
/*************************************************************************
*
* Function: Ext2ReadLogicalBlocks()
*
* Description:
* The higherlevel functions will use this to read in logical blocks
* This function deals with the logical to physical block translation
*
* LogicalBlock - This is a 1 based index.
* That is, the first block is Block 1
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: The Status of the Read IO
*
*************************************************************************/
NTSTATUS Ext2ReadLogicalBlocks (
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
VOID *Buffer, // The Buffer that takes the data read in
LARGE_INTEGER StartLogicalBlock, // The logical block from which reading is to start
unsigned int NoOfLogicalBlocks // The no. of logical blocks to be read
)
{
// The Status to be returned...
NTSTATUS Status = STATUS_SUCCESS;
// The Device Object representing the mounted volume
PDEVICE_OBJECT PtrVolumeDeviceObject = NULL;
// Volume Control Block
PtrExt2VCB PtrVCB = NULL;
// Logical Block Size
ULONG LogicalBlockSize;
// Physical Block Size
ULONG PhysicalBlockSize;
// The starting Physical Block No...
LARGE_INTEGER StartPhysicalBlock;
unsigned int NoOfPhysicalBlocks;
// Done with declerations...
// Now for some code ;)
// Getting the Logical and Physical Sector sizes
PtrVolumeDeviceObject = PtrTargetDeviceObject->Vpb->DeviceObject;
ASSERT( PtrVolumeDeviceObject );
PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension);
ASSERT(PtrVCB);
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
PhysicalBlockSize = PtrTargetDeviceObject->SectorSize;
NoOfPhysicalBlocks = NoOfLogicalBlocks * LogicalBlockSize / PhysicalBlockSize;
StartPhysicalBlock.QuadPart = ( StartLogicalBlock.QuadPart ) *
( LogicalBlockSize / PhysicalBlockSize );
Status = Ext2ReadPhysicalBlocks( PtrTargetDeviceObject,
Buffer, StartPhysicalBlock, NoOfPhysicalBlocks );
return Status;
}
/*************************************************************************
*
* Function: Ext2ReadPhysicalBlocks()
*
* Description:
* The higherlevel functions will use this to read in physical blocks
*
* PhysicalBlock - This is a 0 based number.
* That is, the first block is Block 0
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: The Status of the Read IO
*
*************************************************************************/
NTSTATUS Ext2ReadPhysicalBlocks (
PDEVICE_OBJECT PtrTargetDeviceObject, // the Target Device Object
VOID *Buffer, // The Buffer that takes the data read in
LARGE_INTEGER StartPhysicalBlock, // The block from which reading is to start
unsigned int NoOfBlocks // The no. of blocks to be read
)
{
// The Status to be returned...
NTSTATUS Status = STATUS_SUCCESS;
// Physical Block Size
ULONG PhysicalBlockSize;
// No of bytes to read
ULONG NumberOfBytesToRead;
// Synchronisation Event
KEVENT Event;
// IRP
PIRP Irp;
// Status Block
IO_STATUS_BLOCK Iosb;
// Byte Offset
LARGE_INTEGER ByteOffset;
// Done with declerations...
// Now for some code ;)
// Getting the Physical Sector size
PhysicalBlockSize = PtrTargetDeviceObject->SectorSize;
NumberOfBytesToRead = PhysicalBlockSize * NoOfBlocks;
ByteOffset.QuadPart = StartPhysicalBlock.QuadPart * PhysicalBlockSize;
try
{
//
// Initialize the event we're going to use
//
KeInitializeEvent( &Event, NotificationEvent, FALSE );
//
// Build the irp for the operation and also set the overrride flag
//
Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
PtrTargetDeviceObject,
Buffer,
NumberOfBytesToRead,
&ByteOffset ,
&Event,
&Iosb );
if ( Irp == NULL )
{
DebugTrace(DEBUG_TRACE_MISC, " !!!! Unable to create an IRP", 0 );
Status = STATUS_INSUFFICIENT_RESOURCES;
try_return( Status );
}
//
// Call the device to do the read and wait for it to finish.
//
Status = IoCallDriver( PtrTargetDeviceObject, Irp );
//
// Check if it is done already!!!!
//
if (Status == STATUS_PENDING)
{
//
// Read not done yet...
// Wait till it is...
//
(VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
Status = Iosb.Status;
}
try_exit: NOTHING;
}
finally
{
if (!NT_SUCCESS(Status))
{
if( Status == STATUS_VERIFY_REQUIRED )
{
DebugTrace(DEBUG_TRACE_MISC, " !!!! Verify Required! Failed to read disk",0 );
}
else if (Status == STATUS_INVALID_PARAMETER)
{
DebugTrace(DEBUG_TRACE_MISC, " !!!! Invalid Parameter! Failed to read disk",0 );
}
else
{
DebugTrace(DEBUG_TRACE_MISC, " !!!! Failed to read disk! Status returned = %d", Status );
}
}
}
return Status;
}

View file

@ -0,0 +1,400 @@
/*************************************************************************
*
* File: cleanup.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Should contain code to handle the "Cleanup" dispatch entry point.
* This file serves as a placeholder. Please update this file as part
* of designing and implementing your FSD.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLEANUP
#define DEBUG_LEVEL (DEBUG_TRACE_CLEANUP)
/*************************************************************************
*
* Function: Ext2Cleanup()
*
* Description:
* The I/O Manager will invoke this routine to handle a cleanup
* request
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS Ext2Cleanup(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{
NTSTATUS RC = STATUS_SUCCESS;
PtrExt2IrpContext PtrIrpContext = NULL;
BOOLEAN AreWeTopLevel = FALSE;
DebugTrace( DEBUG_TRACE_IRP_ENTRY, "Cleanup IRP Received...", 0);
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
// set the top level context
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try
{
// get an IRP context structure and issue the request
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = Ext2CommonCleanup(PtrIrpContext, Irp, TRUE);
}
except( Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation() ) )
{
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel)
{
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
}
/*************************************************************************
*
* Function: Ext2CommonCleanup()
*
* Description:
* The actual work is performed here. This routine may be invoked in one'
* of the two possible contexts:
* (a) in the context of a system worker thread
* (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS Ext2CommonCleanup(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
BOOLEAN FirstAttempt )
{
NTSTATUS RC = STATUS_SUCCESS;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
PFILE_OBJECT PtrFileObject = NULL;
PtrExt2FCB PtrFCB = NULL;
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL;
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
PERESOURCE PtrResourceAcquired = NULL;
IO_STATUS_BLOCK LocalIoStatus;
BOOLEAN CompleteIrp = TRUE;
BOOLEAN PostRequest = FALSE;
BOOLEAN AcquiredVCB = FALSE;
BOOLEAN CanWait = FALSE;
BOOLEAN BlockForResource;
int i = 1;
try
{
// First, get a pointer to the current I/O stack location
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
PtrFileObject = PtrIoStackLocation->FileObject;
ASSERT(PtrFileObject);
if( !PtrFileObject->FsContext2 )
{
// This must be a Cleanup request received
// as a result of IoCreateStreamFileObject
// Only such a File object would have a NULL CCB
DebugTrace( DEBUG_TRACE_MISC, " === Cleanup with NULL CCB", 0);
if( PtrFileObject )
{
DebugTrace( DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
}
try_return( RC );
}
Ext2GetFCB_CCB_VCB_FromFileObject (
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
{
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
}
else
{
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup Volume", 0);
}
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
ASSERT(PtrVCB);
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
// (a) Acquiring the VCBResource Exclusively...
// This is done to synchronise with the close and cleanup routines...
BlockForResource = !FirstAttempt;
if( !FirstAttempt )
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire VCB Exclusively [Cleanup]", 0);
}
else
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire VCB Exclusively [Cleanup]", 0);
}
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
}
i = 1;
while( !AcquiredVCB )
{
DebugTraceState("VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
if( ! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
{
DebugTrace( DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquisition FAILED [Cleanup]", 0);
if( BlockForResource && i != 1000 )
{
LARGE_INTEGER Delay;
Delay.QuadPart = -500 * i;
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
}
else
{
if( i == 1000 )
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
PostRequest = TRUE;
try_return( RC = STATUS_PENDING );
}
}
else
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquired in [Cleanup]", 0);
AcquiredVCB = TRUE;
}
i *= 10;
}
// (b) Acquire the file (FCB) exclusively
if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
{
// This FCB is an FCB indeed. ;)
// So acquiring it exclusively...
// This is done to synchronise with read/write routines...
if( !FirstAttempt )
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire FCB Exclusively [Cleanup]", 0);
}
else
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire FCB Exclusively [Cleanup]", 0);
}
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
}
i = 1;
while( !PtrResourceAcquired )
{
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) )
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB Acquisition FAILED [Cleanup]", 0);
if( BlockForResource && i != 1000 )
{
LARGE_INTEGER Delay;
Delay.QuadPart = -500 * i;
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
}
else
{
if( i == 1000 )
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
PostRequest = TRUE;
try_return( RC = STATUS_PENDING );
}
}
else
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB acquired [Cleanup]", 0);
PtrResourceAcquired = & ( PtrFCB->NTRequiredFCB.MainResource );
}
i *= 10;
}
// (c) Flush file data to disk
if ( PtrFileObject->PrivateCacheMap != NULL)
{
IO_STATUS_BLOCK Status;
CcFlushCache( PtrFileObject->SectionObjectPointer, NULL, 0, &Status );
}
// (d) Talk to the FSRTL package (if you use it) about pending oplocks.
// (e) Notify the FSRTL package (if you use it) for use with pending
// notification IRPs
// (f) Unlock byte-range locks (if any were acquired by process)
// (g) Attempting to update time stamp values
// Errors are ignored...
// Not considered as critical errors...
/*
if( PtrFCB->OpenHandleCount == 1 )
{
ULONG CreationTime, AccessTime, ModificationTime;
EXT2_INODE Inode;
CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
{
// Update time stamps in the inode...
Inode.i_ctime = CreationTime;
Inode.i_atime = AccessTime;
Inode.i_mtime = ModificationTime;
// Updating the inode...
Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode );
}
}
*/
// (h) Inform the Cache Manager to uninitialize Cache Maps ...
CcUninitializeCacheMap( PtrFileObject, NULL, NULL );
// (i) Decrementing the Open Handle count...
if( PtrFCB->OpenHandleCount )
{
InterlockedDecrement( &PtrFCB->OpenHandleCount );
}
else
{
Ext2BreakPoint();
}
PtrFCB->FCBFlags |= FO_CLEANUP_COMPLETE;
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Cleanup]", PtrFCB->ReferenceCount );
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Cleanup]", PtrFCB->OpenHandleCount );
// (j) Remove share access...
// Will do that later ;)
// (k) Is this a close on delete file?
// If so, delete the file...
if( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE) &&
!PtrFCB->OpenHandleCount )
{
//
// Have to delete this file...
//
Ext2DeleteFile( PtrFCB, PtrIrpContext );
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart = 0;
PtrFCB->INodeNo = 0;
}
}
else
{
// This must be a volume close...
// Just go ahead and complete this IRP...
PtrVCB->VCBOpenCount--;
DebugTrace(DEBUG_TRACE_MISC, "VCB Cleanup Requested !!!", 0);
CompleteIrp = TRUE;
}
try_return( RC );
try_exit: NOTHING;
}
finally
{
if(PtrResourceAcquired)
{
Ext2ReleaseResource(PtrResourceAcquired);
DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** Resource Released [Cleanup]", 0);
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]",
PtrResourceAcquired->ActiveCount,
PtrResourceAcquired->NumberOfExclusiveWaiters,
PtrResourceAcquired->NumberOfSharedWaiters );
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
}
}
if( AcquiredVCB )
{
ASSERT(PtrVCB);
Ext2ReleaseResource(&(PtrVCB->VCBResource));
DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** VCB Released [Cleanup]", 0);
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
AcquiredVCB = FALSE;
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
}
}
if( PostRequest )
{
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
}
if( RC != STATUS_PENDING )
{
Ext2ReleaseIrpContext( PtrIrpContext );
// complete the IRP
IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
}
} // end of "finally" processing
return(RC);
}

View file

@ -0,0 +1,459 @@
/*************************************************************************
*
* File: close.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Should contain code to handle the "Close" dispatch entry point.
* This file serves as a placeholder. Please update this file as part
* of designing and implementing your FSD.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLOSE
#define DEBUG_LEVEL (DEBUG_TRACE_CLOSE)
/*************************************************************************
*
* Function: Ext2Close()
*
* Description:
* The I/O Manager will invoke this routine to handle a close
* request
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS Ext2Close(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{
NTSTATUS RC = STATUS_SUCCESS;
PtrExt2IrpContext PtrIrpContext = NULL;
BOOLEAN AreWeTopLevel = FALSE;
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Close IRP Received...", 0);
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
// set the top level context
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try
{
// get an IRP context structure and issue the request
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = Ext2CommonClose(PtrIrpContext, Irp, TRUE);
}
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
{
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel)
{
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
}
/*************************************************************************
*
* Function: Ext2CommonClose()
*
* Description:
* The actual work is performed here. This routine may be invoked in one'
* of the two possible contexts:
* (a) in the context of a system worker thread
* (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS Ext2CommonClose(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
BOOLEAN FirstAttempt )
{
NTSTATUS RC = STATUS_SUCCESS;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
PFILE_OBJECT PtrFileObject = NULL;
PtrExt2FCB PtrFCB = NULL;
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL;
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
PERESOURCE PtrResourceAcquired = NULL;
IO_STATUS_BLOCK LocalIoStatus;
BOOLEAN CompleteIrp = TRUE;
BOOLEAN PostRequest = FALSE;
BOOLEAN AcquiredVCB = FALSE;
BOOLEAN CanWait = FALSE;
BOOLEAN BlockForResource;
int i = 1;
try
{
// First, get a pointer to the current I/O stack location
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
PtrFileObject = PtrIoStackLocation->FileObject;
ASSERT(PtrFileObject);
if( !PtrFileObject->FsContext2 )
{
// This must be a Cleanup request received
// as a result of IoCreateStreamFileObject
// Only such a File object would have a NULL CCB
DebugTrace( DEBUG_TRACE_SPECIAL, " === Close with NULL CCB", 0);
if( PtrFileObject )
{
DebugTrace( DEBUG_TRACE_SPECIAL, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
Ext2BreakPoint();
try_return( RC );
}
// Get the FCB and CCB pointers
Ext2GetFCB_CCB_VCB_FromFileObject (
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
ASSERT( PtrVCB );
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
{
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
}
else
{
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -null-", 0);
}
// (a) Acquiring the VCBResource Exclusively...
// This is done to synchronise with the close and cleanup routines...
// if( ExTryToAcquireResourceExclusiveLite(&(PtrVCB->VCBResource) ) )
BlockForResource = !FirstAttempt;
if( !FirstAttempt )
{
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Close]", 0);
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [Close]", 0);
}
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
i = 1;
while( !AcquiredVCB )
{
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
if(! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
{
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquisition FAILED [Close]", 0);
if( BlockForResource && i != 1000 )
{
LARGE_INTEGER Delay;
//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
Delay.QuadPart = -500 * i;
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
}
else
{
if( i == 1000 )
DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
PostRequest = TRUE;
try_return( RC = STATUS_PENDING );
}
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired in [Close]", 0);
AcquiredVCB = TRUE;
}
i *= 10;
}
// (b) Acquire the file (FCB) exclusively
if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
{
// This FCB is an FCB indeed. ;)
// So acquiring it exclusively...
// This is done to synchronise with read/write routines...
if( !FirstAttempt )
{
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire FCB Exclusively [Close]", 0);
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Exclusively [Close]", 0);
}
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
i = 1;
while( !PtrResourceAcquired )
{
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Close]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) )
{
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [Close]", 0);
if( BlockForResource && i != 1000 )
{
LARGE_INTEGER Delay;
//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
Delay.QuadPart = -500 * i;
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
}
else
{
if( i == 1000 )
DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
PostRequest = TRUE;
try_return( RC = STATUS_PENDING );
}
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [Close]", 0);
PtrResourceAcquired = & ( PtrFCB->NTRequiredFCB.MainResource );
}
i *= 10;
}
// (c) Delete the CCB structure (free memory)
RemoveEntryList( &PtrCCB->NextCCB );
Ext2ReleaseCCB( PtrCCB );
PtrFileObject->FsContext2 = NULL;
// (d) Decrementing the Reference Count...
if( PtrFCB->ReferenceCount )
{
InterlockedDecrement( &PtrFCB->ReferenceCount );
}
else
{
Ext2BreakPoint();
}
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Close]", PtrFCB->ReferenceCount );
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Close]", PtrFCB->OpenHandleCount );
if( PtrFCB->ReferenceCount == 0 )
{
// Attempting to update time stamp values
// Errors are ignored...
// Not considered as critical errors...
{
ULONG CreationTime, AccessTime, ModificationTime;
EXT2_INODE Inode;
CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
{
// Update time stamps in the inode...
Inode.i_ctime = CreationTime;
Inode.i_atime = AccessTime;
Inode.i_mtime = ModificationTime;
// Updating the inode...
Ext2WriteInode( NULL, PtrVCB, PtrFCB->INodeNo, &Inode );
}
}
if( PtrFCB->INodeNo == EXT2_ROOT_INO )
{
//
// Root Directory FCB
// Preserve this
// FSD has a File Object for this FCB...
//
DebugTrace(DEBUG_TRACE_MISC, "^^^^^Root Directory FCB ; leaveing it alone[Close]", 0);
// Do nothing...
}
else if( PtrFCB->DcbFcb.Dcb.PtrDirFileObject )
{
//
// If this is a FCB created on the FSD's initiative
// Leave it alone
//
DebugTrace(DEBUG_TRACE_MISC, "^^^^^FCB Created on the FSD's initiative; leaveing it alone[Close]", 0);
if( !PtrFCB->ClosableFCBs.OnClosableFCBList )
{
InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
&PtrFCB->ClosableFCBs.ClosableFCBList );
PtrVCB->ClosableFCBs.Count++;
PtrFCB->ClosableFCBs.OnClosableFCBList = TRUE;
}
if( PtrVCB->ClosableFCBs.Count > EXT2_MAXCLOSABLE_FCBS_UL )
{
PtrExt2FCB PtrTempFCB = NULL;
// Checking if Closable FCBs are too many in number...
// Shouldn't block the
// Should do this asynchronously...
// Maybe later...
PLIST_ENTRY PtrEntry = NULL;
PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead );
PtrTempFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList );
if( Ext2CloseClosableFCB( PtrTempFCB ) )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Close]", PtrTempFCB );
ExFreePool( PtrTempFCB );
PtrVCB->ClosableFCBs.Count--;
}
else
{
// Put the FCB back in the list...
InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
&PtrTempFCB->ClosableFCBs.ClosableFCBList );
}
DebugTrace( DEBUG_TRACE_SPECIAL, "ClosableFCBs Count = %ld [Close]", PtrVCB->ClosableFCBs.Count );
}
}
else
{
// Remove this FCB as well...
DebugTrace(DEBUG_TRACE_MISC, "^^^^^Deleting FCB [Close]", 0);
RemoveEntryList( &PtrFCB->NextFCB );
if ( PtrResourceAcquired )
{
Ext2ReleaseResource(PtrResourceAcquired);
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Close]",
PtrResourceAcquired->ActiveCount,
PtrResourceAcquired->NumberOfExclusiveWaiters,
PtrResourceAcquired->NumberOfSharedWaiters );
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
PtrResourceAcquired = FALSE;
}
Ext2ReleaseFCB( PtrFCB );
}
}
CompleteIrp = TRUE;
}
else
{
// This must be a volume close...
// What do I do now? ;)
DebugTrace(DEBUG_TRACE_MISC, "VCB Close Requested !!!", 0);
CompleteIrp = TRUE;
}
try_return( RC );
try_exit: NOTHING;
}
finally
{
if ( PtrResourceAcquired )
{
Ext2ReleaseResource(PtrResourceAcquired);
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Close]",
PtrResourceAcquired->ActiveCount,
PtrResourceAcquired->NumberOfExclusiveWaiters,
PtrResourceAcquired->NumberOfSharedWaiters );
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
PtrResourceAcquired = FALSE;
}
if (AcquiredVCB)
{
ASSERT(PtrVCB);
Ext2ReleaseResource(&(PtrVCB->VCBResource));
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Close]", 0);
AcquiredVCB = FALSE;
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
}
if( PostRequest )
{
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
}
else if( CompleteIrp && RC != STATUS_PENDING )
{
// complete the IRP
IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
Ext2ReleaseIrpContext( PtrIrpContext );
}
} // end of "finally" processing
return(RC);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,210 @@
/*************************************************************************
*
* File: devcntrl.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains code to handle the "Device IOCTL" dispatch entry point.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_DEVICE_CONTROL
#define DEBUG_LEVEL DEBUG_TRACE_DEVCTRL
#if(_WIN32_WINNT < 0x0400)
#define IOCTL_REDIR_QUERY_PATH CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 99, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef struct _QUERY_PATH_REQUEST
{
ULONG PathNameLength;
PIO_SECURITY_CONTEXT SecurityContext;
WCHAR FilePathName[1];
} QUERY_PATH_REQUEST, *PQUERY_PATH_REQUEST;
typedef struct _QUERY_PATH_RESPONSE
{
ULONG LengthAccepted;
} QUERY_PATH_RESPONSE, *PQUERY_PATH_RESPONSE;
#endif
/*************************************************************************
*
* Function: Ext2DeviceControl()
*
* Description:
* The I/O Manager will invoke this routine to handle a Device IOCTL
* request
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2DeviceControl(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{
NTSTATUS RC = STATUS_SUCCESS;
PtrExt2IrpContext PtrIrpContext = NULL;
BOOLEAN AreWeTopLevel = FALSE;
// Ext2BreakPoint();
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Device Control IRP Received...", 0);
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
// set the top level context
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try {
// get an IRP context structure and issue the request
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = Ext2CommonDeviceControl(PtrIrpContext, Irp);
} except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel) {
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
}
/*************************************************************************
*
* Function: Ext2CommonDeviceControl()
*
* Description:
* The actual work is performed here. This routine may be invoked in one'
* of the two possible contexts:
* (a) in the context of a system worker thread
* (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2CommonDeviceControl(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp)
{
NTSTATUS RC = STATUS_SUCCESS;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
PIO_STACK_LOCATION PtrNextIoStackLocation = NULL;
PFILE_OBJECT PtrFileObject = NULL;
PtrExt2FCB PtrFCB = NULL;
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL;
ULONG IoControlCode = 0;
void *BufferPointer = NULL;
try
{
// First, get a pointer to the current I/O stack location
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
PtrFileObject = PtrIoStackLocation->FileObject;
ASSERT(PtrFileObject);
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
ASSERT(PtrCCB);
PtrFCB = PtrCCB->PtrFCB;
ASSERT(PtrFCB);
if( PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB )
{
PtrVCB = (PtrExt2VCB)(PtrFCB);
}
else
{
AssertFCB( PtrFCB );
ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB);
PtrVCB = PtrFCB->PtrVCB;
}
// Get the IoControlCode value
IoControlCode = PtrIoStackLocation->Parameters.DeviceIoControl.IoControlCode;
// You may wish to allow only volume open operations.
// Invoke the lower level driver in the chain.
PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp);
*PtrNextIoStackLocation = *PtrIoStackLocation;
// Set a completion routine.
IoSetCompletionRoutine(PtrIrp, Ext2DevIoctlCompletion, NULL, TRUE, TRUE, TRUE);
// Send the request.
RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
try_exit: NOTHING;
}
finally
{
// Release the IRP context
if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION))
{
// Free up the Irp Context
Ext2ReleaseIrpContext(PtrIrpContext);
}
}
return(RC);
}
/*************************************************************************
*
* Function: Ext2DevIoctlCompletion()
*
* Description:
* Completion routine.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS
*
*************************************************************************/
NTSTATUS Ext2DevIoctlCompletion(
PDEVICE_OBJECT PtrDeviceObject,
PIRP PtrIrp,
void *Context)
{
if (PtrIrp->PendingReturned) {
IoMarkIrpPending(PtrIrp);
}
return(STATUS_SUCCESS);
}

View file

@ -0,0 +1,937 @@
/*************************************************************************
*
* File: dircntrl.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains code to handle the "directory control" dispatch entry point.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_DIR_CONTROL
#define DEBUG_LEVEL (DEBUG_TRACE_DIRCTRL)
/*************************************************************************
*
* Function: Ext2DirControl()
*
* Description:
* The I/O Manager will invoke this routine to handle a directory control
* request
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2DirControl(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{
NTSTATUS RC = STATUS_SUCCESS;
PtrExt2IrpContext PtrIrpContext = NULL;
BOOLEAN AreWeTopLevel = FALSE;
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "DIR Control IRP received...", 0);
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
// set the top level context
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try
{
// get an IRP context structure and issue the request
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = Ext2CommonDirControl(PtrIrpContext, Irp);
}
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
{
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel) {
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
}
/*************************************************************************
*
* Function: Ext2CommonDirControl()
*
* Description:
* The actual work is performed here. This routine may be invoked in one'
* of the two possible contexts:
* (a) in the context of a system worker thread
* (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2CommonDirControl(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp)
{
NTSTATUS RC = STATUS_SUCCESS;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
PFILE_OBJECT PtrFileObject = NULL;
PtrExt2FCB PtrFCB = NULL;
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL;
// First, get a pointer to the current I/O stack location
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
PtrFileObject = PtrIoStackLocation->FileObject;
ASSERT(PtrFileObject);
// Get the FCB and CCB pointers
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
ASSERT(PtrCCB);
PtrFCB = PtrCCB->PtrFCB;
AssertFCB( PtrFCB );
// Get some of the parameters supplied to us
switch (PtrIoStackLocation->MinorFunction) {
case IRP_MN_QUERY_DIRECTORY:
#ifdef _GNU_NTIFS_
RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, (PEXTENDED_IO_STACK_LOCATION)PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
#else
RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
#endif
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
{
RC = STATUS_NOT_IMPLEMENTED;
PtrIrp->IoStatus.Status = RC;
PtrIrp->IoStatus.Information = 0;
IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
}
// RC = Ext2NotifyChangeDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
break;
default:
// This should not happen.
RC = STATUS_INVALID_DEVICE_REQUEST;
PtrIrp->IoStatus.Status = RC;
PtrIrp->IoStatus.Information = 0;
// Free up the Irp Context
Ext2ReleaseIrpContext(PtrIrpContext);
// complete the IRP
IoCompleteRequest(PtrIrp, IO_NO_INCREMENT);
break;
}
return(RC);
}
/*************************************************************************
*
* Function: Ext2QueryDirectory()
*
* Description:
* Query directory request.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2QueryDirectory(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
#ifdef _GNU_NTIFS_
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
#else
PIO_STACK_LOCATION PtrIoStackLocation,
#endif
PFILE_OBJECT PtrFileObject,
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB)
{
NTSTATUS RC = STATUS_SUCCESS;
BOOLEAN CompleteRequest = TRUE;
BOOLEAN PostRequest = FALSE;
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
BOOLEAN CanWait = FALSE;
PtrExt2VCB PtrVCB = NULL;
BOOLEAN AcquiredFCB = FALSE;
unsigned long BufferLength = 0;
unsigned long BufferIndex = 0;
unsigned long FileIndex = 0;
PUNICODE_STRING PtrSearchPattern = NULL;
FILE_INFORMATION_CLASS FileInformationClass;
BOOLEAN RestartScan = FALSE;
BOOLEAN ReturnSingleEntry = FALSE;
BOOLEAN IndexSpecified = FALSE;
unsigned char *Buffer = NULL;
BOOLEAN FirstTimeQuery = FALSE;
unsigned long StartingIndexForSearch = 0;
unsigned long BytesReturned = 0;
BOOLEAN BufferUsedup = FALSE;
BOOLEAN SearchWithWildCards = FALSE;
PFILE_BOTH_DIR_INFORMATION BothDirInformation = NULL;
PFILE_FULL_DIR_INFORMATION FullDirInformation = NULL;
PFILE_DIRECTORY_INFORMATION DirectoryInformation = NULL;
PFILE_NAMES_INFORMATION NamesInformation = NULL;
PEXT2_DIR_ENTRY PtrDirEntry = NULL;
PEXT2_INODE PtrInode = NULL;
unsigned long LogicalBlockSize;
unsigned long ThisBlock;
// The starting Physical Block No...
//LARGE_INTEGER StartPhysicalBlock;
LARGE_INTEGER StartBufferOffset ;
ULONG PinBufferLength;
// Buffer Control Block
PBCB PtrBCB = NULL;
BYTE * PtrPinnedBlockBuffer = NULL;
unsigned int i,j;
DebugTrace(DEBUG_TRACE_MISC, " === Querying Directory %S", PtrFCB->FCBName->ObjectName.Buffer );
try
{
// Validate the sent-in FCB
if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY))
{
// We will only allow notify requests on directories.
RC = STATUS_INVALID_PARAMETER;
}
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
PtrVCB = PtrFCB->PtrVCB;
//
// Asynchronous IO requested
// Posting request...
//
/*
* This is incorrect because posted IRP_MJ_DIRECTORY_CONTROL
* requests aren't handled in the worker thread yet. I tried
* adding handling of them to the worked routine, but there
* were problems with accessing the PtrIoStackLocation->
* Parameters.QueryDirectory.FileName variable.
* -- Filip Navara, 18/08/2004
*/
#if 0
if (!CanWait)
{
PostRequest = TRUE;
try_return(RC = STATUS_PENDING);
}
#endif
// Obtain the callers parameters
BufferLength = PtrIoStackLocation->Parameters.QueryDirectory.Length;
PtrSearchPattern = ( PUNICODE_STRING ) PtrIoStackLocation->Parameters.QueryDirectory.FileName;
FileInformationClass = PtrIoStackLocation->Parameters.QueryDirectory.FileInformationClass;
FileIndex = PtrIoStackLocation->Parameters.QueryDirectory.FileIndex;
// Some additional arguments that affect the FSD behavior
RestartScan = (PtrIoStackLocation->Flags & SL_RESTART_SCAN);
ReturnSingleEntry = (PtrIoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY);
IndexSpecified = (PtrIoStackLocation->Flags & SL_INDEX_SPECIFIED);
//
// Acquiring exclusive access to the FCB.
// This is not mandatory
//
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire FCB Exclusively[DirCtrl]", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [DirCtrl]", 0);
AcquiredFCB = TRUE;
// We must determine the buffer pointer to be used. Since this
// routine could either be invoked directly in the context of the
// calling thread, or in the context of a worker thread, here is
// a general way of determining what we should use.
Buffer = Ext2GetCallersBuffer ( PtrIrp );
// The method of determining where to look from and what to look for is
// unfortunately extremely confusing. However, here is a methodology you
// you can broadly adopt:
// (a) You have to maintain a search buffer per CCB structure.
// (b) This search buffer is initialized the very first time
// a query directory operation is performed using the file object.
// (For the sample FSD, the search buffer is stored in the
// DirectorySearchPattern field)
// However, the caller still has the option of "overriding" this stored
// search pattern by supplying a new one in a query directory operation.
//
if( PtrCCB->DirectorySearchPattern.Length )
{
if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 )
{
DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&& PtrCCB->DirectorySearchPattern not NULL terminated!", 0);
}
DebugTrace(DEBUG_TRACE_MISC, " === Old Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer );
}
if (PtrSearchPattern != NULL)
{
// User has supplied a search pattern
// Now validate that the search pattern is legitimate
if ( PtrCCB->DirectorySearchPattern.Length == 0 )
{
// This must be the very first query request.
FirstTimeQuery = TRUE;
}
else
{
// We should ignore the search pattern in the CCB and instead,
// use the user-supplied pattern for this particular query
// directory request.
Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern );
}
// Now, allocate enough memory to contain the caller
// supplied search pattern and fill in the DirectorySearchPattern
// field in the CCB
Ext2CopyUnicodeString( &PtrCCB->DirectorySearchPattern, PtrSearchPattern );
/*
PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof( PtrSearchPattern ) );
ASSERT(PtrCCB->DirectorySearchPattern);
RtlCopyMemory( PtrCCB->DirectorySearchPattern, PtrSearchPattern, sizeof( PtrSearchPattern ) );
*/
}
else if ( PtrCCB->DirectorySearchPattern.Length == 0 )
{
// This MUST be the first directory query operation (else the
// DirectorySearchPattern field would never be empty. Also, the caller
// has neglected to provide a pattern so we MUST invent one.
// Use "*" (following NT conventions) as your search pattern
// and store it in the PtrCCB->DirectorySearchPattern field.
/*
PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof(L"*") );
ASSERT(PtrCCB->DirectorySearchPattern);
RtlCopyMemory( PtrCCB->DirectorySearchPattern, L"*", 4 );*/
Ext2CopyWideCharToUnicodeString( &PtrCCB->DirectorySearchPattern, L"*" );
FirstTimeQuery = TRUE;
}
else
{
// The caller has not supplied any search pattern...
// Using previously supplied pattern
PtrSearchPattern = &PtrCCB->DirectorySearchPattern;
}
if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 )
{
DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&& PtrCCB->DirectorySearchPattern not NULL terminated!", 0 );
}
DebugTrace(DEBUG_TRACE_MISC, " === Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer );
SearchWithWildCards = FsRtlDoesNameContainWildCards( PtrSearchPattern );
// There is one other piece of information that your FSD must store
// in the CCB structure for query directory support. This is the index
// value (i.e. the offset in your on-disk directory structure) from
// which you should start searching.
// However, the flags supplied with the IRP can make us override this
// as well.
if (FileIndex)
{
// Caller has told us wherefrom to begin.
// You may need to round this to an appropriate directory entry
// entry alignment value.
StartingIndexForSearch = FileIndex;
}
else if (RestartScan)
{
StartingIndexForSearch = 0;
}
else
{
// Get the starting offset from the CCB.
StartingIndexForSearch = PtrCCB->CurrentByteOffset.LowPart;
}
// Read in the file inode if it hasn't already been read...
Ext2InitializeFCBInodeInfo( PtrFCB );
if (PtrFileObject->PrivateCacheMap == NULL)
{
CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrReqdFCB->CommonFCBHeader.AllocationSize)),
TRUE, // We will utilize pin access for directories
&(Ext2GlobalData.CacheMgrCallBacks), // callbacks
PtrCCB); // The context used in callbacks
}
//
// Read in the next Data Block of this directory
//
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
StartBufferOffset.QuadPart = ( StartingIndexForSearch / LogicalBlockSize );
StartBufferOffset.QuadPart *= LogicalBlockSize; // This should be the StartBufferOffset alaigned to LBlock boundary...
PinBufferLength = PtrReqdFCB->CommonFCBHeader.FileSize.LowPart - StartBufferOffset.LowPart;
if ( !CcMapData( PtrFileObject,
&StartBufferOffset,
PinBufferLength,
TRUE,
&PtrBCB,
(PVOID*)&PtrPinnedBlockBuffer ) )
{
// Read Failure
DebugTrace(DEBUG_TRACE_MISC, "Cache read failiure while reading in volume meta data", 0);
try_return( STATUS_ACCESS_DENIED );
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
}
PtrInode = Ext2AllocatePool( PagedPool, sizeof( EXT2_INODE ) );
//
// Walking through the directory entries...
for( BufferUsedup = FALSE, BufferIndex = 0; !BufferUsedup && StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; )
{
PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ StartingIndexForSearch - StartBufferOffset.LowPart ];
StartingIndexForSearch += PtrDirEntry->rec_len;
PtrCCB->CurrentByteOffset.LowPart = StartingIndexForSearch;
if( PtrDirEntry->inode == 0 )
{
continue;
}
if( PtrDirEntry->name_len == 0 || PtrDirEntry->rec_len == 0 )
{
//
// This should not happen
// Hqw can this be so!!!
//
Ext2BreakPoint();
if( BothDirInformation )
{
BothDirInformation->NextEntryOffset = 0;
}
if( !BytesReturned )
{
if( FirstTimeQuery )
RC = STATUS_NO_SUCH_FILE;
else
RC = STATUS_NO_MORE_FILES;
}
break;
}
// Does this entry match the search criterian?
// Checking
//
{
UNICODE_STRING FileName;
LONG Matched = 0;
// Constructing a counted Unicode string out of PtrDirEntry
Ext2CopyCharToUnicodeString( &FileName, PtrDirEntry->name, PtrDirEntry->name_len );
if ( SearchWithWildCards )
{
Matched = FsRtlIsNameInExpression ( PtrSearchPattern, &FileName, FALSE, NULL );
}
else
{
Matched = ! RtlCompareUnicodeString( PtrSearchPattern, &FileName, FALSE );
}
Ext2DeallocateUnicodeString( &FileName );
if( !Matched )
{
continue;
}
}
switch( FileInformationClass )
{
case FileBothDirectoryInformation:
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileBothDirectoryInformation", 0 );
ThisBlock = sizeof( FILE_BOTH_DIR_INFORMATION );
ThisBlock += PtrDirEntry->name_len*2;
ThisBlock = Ext2QuadAlign( ThisBlock );
if( ( BufferIndex + ThisBlock ) > BufferLength )
{
//
// Next entry won't fit into the buffer...
// will have to return...
// :(
//
if( BothDirInformation )
BothDirInformation->NextEntryOffset = 0;
if( !BytesReturned )
RC = STATUS_NO_MORE_FILES;
BufferUsedup = TRUE;
break;
}
Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode );
if( !PtrInode )
{
try_return( RC = STATUS_UNSUCCESSFUL );
}
BothDirInformation = ( PFILE_BOTH_DIR_INFORMATION ) ( Buffer + ( BufferIndex ) );
BothDirInformation->EaSize = 0;
BothDirInformation->AllocationSize.QuadPart = PtrInode->i_blocks * 512;
BothDirInformation->EndOfFile.QuadPart = PtrInode->i_size;
BothDirInformation->ChangeTime.QuadPart = 0;
BothDirInformation->CreationTime.QuadPart = ( __int64 ) PtrInode->i_ctime * 10000000;
BothDirInformation->CreationTime.QuadPart += Ext2GlobalData.TimeDiff.QuadPart;
BothDirInformation->LastAccessTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 );
BothDirInformation->LastWriteTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 );
// Getting the file type...
BothDirInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) )
{
// Not a reqular file...
if( Ext2IsModeDirectory( PtrInode->i_mode) )
{
// Directory...
BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
}
else
{
// Special File...
// Treated with respect... ;)
//
BothDirInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
// FILE_ATTRIBUTE_DEVICE
}
if ( Ext2IsModeHidden( PtrInode->i_mode ) )
{
BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
}
if ( Ext2IsModeReadOnly( PtrInode->i_mode ) )
{
BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
}
}
BothDirInformation->FileIndex = StartingIndexForSearch;
BothDirInformation->FileNameLength = PtrDirEntry->name_len*2 + 2;
BothDirInformation->ShortNameLength = 0;
BothDirInformation->ShortName[0] = 0;
// Copying out the name as WCHAR null terminated strings
for( j = 0; j< PtrDirEntry->name_len ; j ++ )
{
// BothDirInformation->ShortName[ j ] = PtrDirEntry->name[j];
BothDirInformation->FileName[ j ] = PtrDirEntry->name[j];
// if( j < 11 )
// BothDirInformation->ShortName[j] = PtrDirEntry->name[j];;
}
/*
if( j < 11 )
{
BothDirInformation->ShortNameLength = j * 2 + 2;
BothDirInformation->ShortName[ j ] = 0;
}
else
{
BothDirInformation->ShortNameLength = 24;
BothDirInformation->ShortName[ 11 ] = 0;
}*/
BothDirInformation->FileName[ j ] = 0;
BytesReturned += ThisBlock;
BufferIndex += ThisBlock;
if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ))
BothDirInformation->NextEntryOffset = ThisBlock;
else
BothDirInformation->NextEntryOffset = 0;
break;
case FileDirectoryInformation:
// DirectoryInformation
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileDirectoryInformation", 0 );
ThisBlock = sizeof( FILE_DIRECTORY_INFORMATION );
ThisBlock += PtrDirEntry->name_len*2;
ThisBlock = Ext2QuadAlign( ThisBlock );
if( ( BufferIndex + ThisBlock ) > BufferLength )
{
//
// Next entry won't fit into the buffer...
// will have to return...
// :(
//
if( DirectoryInformation )
DirectoryInformation->NextEntryOffset = 0;
if( !BytesReturned )
RC = STATUS_NO_MORE_FILES;
BufferUsedup = TRUE;
break;
}
Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode );
if( !PtrInode )
{
try_return( RC = STATUS_UNSUCCESSFUL );
}
DirectoryInformation = ( PFILE_DIRECTORY_INFORMATION ) ( Buffer + ( BufferIndex ) );
DirectoryInformation->AllocationSize.QuadPart = PtrInode->i_blocks * 512;
DirectoryInformation->EndOfFile.QuadPart = PtrInode->i_size;
DirectoryInformation->ChangeTime.QuadPart = 0;
DirectoryInformation->CreationTime.QuadPart = ( __int64 ) PtrInode->i_ctime * 10000000;
DirectoryInformation->CreationTime.QuadPart += Ext2GlobalData.TimeDiff.QuadPart;
DirectoryInformation->LastAccessTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 );
DirectoryInformation->LastWriteTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 );
// Getting the file type...
DirectoryInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) )
{
// Not a reqular file...
if( Ext2IsModeDirectory( PtrInode->i_mode) )
{
// Directory...
DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
}
else
{
// Special File...
// Treated with respect... ;)
//
DirectoryInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
// FILE_ATTRIBUTE_DEVICE
}
if ( Ext2IsModeHidden( PtrInode->i_mode ) )
{
DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
}
if ( Ext2IsModeReadOnly( PtrInode->i_mode ) )
{
DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
}
}
DirectoryInformation->FileIndex = StartingIndexForSearch;
DirectoryInformation->FileNameLength = PtrDirEntry->name_len*2 + 2;
// Copying out the name as WCHAR null terminated strings
for( j = 0; j< PtrDirEntry->name_len ; j ++ )
{
DirectoryInformation->FileName[ j ] = PtrDirEntry->name[j];
}
DirectoryInformation->FileName[ j ] = 0;
BytesReturned += ThisBlock;
BufferIndex += ThisBlock;
if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ))
DirectoryInformation->NextEntryOffset = ThisBlock;
else
DirectoryInformation->NextEntryOffset = 0;
break;
case FileFullDirectoryInformation:
// FullDirInformation->
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileFullDirectoryInformation - Not handled", 0 );
try_return( RC );
case FileNamesInformation:
// NamesInformation->
DebugTrace(DEBUG_TRACE_DIRINFO, " === FileNamesInformation - Not handled", 0 );
try_return( RC );
default:
DebugTrace(DEBUG_TRACE_DIRINFO, " === Invalid Dir Info class - Not handled", 0 );
try_return( RC = STATUS_INVALID_INFO_CLASS );
}
if( ReturnSingleEntry )
{
break;
}
}// end of for...
if( !BytesReturned && StartingIndexForSearch >= ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart) )
{
Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern );
PtrCCB->CurrentByteOffset.QuadPart = 0;
if( FirstTimeQuery )
RC = STATUS_NO_SUCH_FILE;
else
RC = STATUS_NO_MORE_FILES;
try_return( RC );
}
else if( BytesReturned )
{
BothDirInformation->NextEntryOffset = 0;
}
try_exit: NOTHING;
}
finally
{
if( PtrInode )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [DirCtrl]", PtrInode );
ExFreePool( PtrInode );
}
if( PtrBCB )
{
CcUnpinData( PtrBCB );
PtrBCB = NULL;
}
if (PostRequest)
{
if (AcquiredFCB)
{
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released in [DirCtrl]", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
PtrReqdFCB->MainResource.ActiveCount,
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
}
// Map the users buffer and then post the request.
RC = Ext2LockCallersBuffer(PtrIrp, TRUE, BufferLength);
ASSERT(NT_SUCCESS(RC));
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
}
else if (!(PtrIrpContext->IrpContextFlags &
EXT2_IRP_CONTEXT_EXCEPTION))
{
if (AcquiredFCB)
{
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [DirCtrl]", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
PtrReqdFCB->MainResource.ActiveCount,
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
}
// Complete the request.
PtrIrp->IoStatus.Status = RC;
PtrIrp->IoStatus.Information = BytesReturned;
// Free up the Irp Context
Ext2ReleaseIrpContext(PtrIrpContext);
// complete the IRP
IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
}
// Flush the saved BCBs...
// Ext2FlushSavedBCBs ( PtrIrpContext );
}
return(RC);
}
/*************************************************************************
*
* Function: Ext2NotifyChangeDirectory()
*
* Description:
* Handle the notify request.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2NotifyChangeDirectory(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
#ifdef _GNU_NTIFS_
PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation,
#else
PIO_STACK_LOCATION PtrIoStackLocation,
#endif
PFILE_OBJECT PtrFileObject,
PtrExt2FCB PtrFCB,
PtrExt2CCB PtrCCB)
{
NTSTATUS RC = STATUS_SUCCESS;
BOOLEAN CompleteRequest = FALSE;
BOOLEAN PostRequest = FALSE;
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
BOOLEAN CanWait = FALSE;
ULONG CompletionFilter = 0;
BOOLEAN WatchTree = FALSE;
PtrExt2VCB PtrVCB = NULL;
BOOLEAN AcquiredFCB = FALSE;
try {
// Validate the sent-in FCB
if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) {
// We will only allow notify requests on directories.
RC = STATUS_INVALID_PARAMETER;
CompleteRequest = TRUE;
}
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
PtrVCB = PtrFCB->PtrVCB;
// Acquire the FCB resource shared
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Shared[DirCtrl]", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait))
{
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [DirCtrl]", 0);
PostRequest = TRUE;
try_return(RC = STATUS_PENDING);
}
AcquiredFCB = TRUE;
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [DirCtrl]", 0);
// Obtain some parameters sent by the caller
CompletionFilter = PtrIoStackLocation->Parameters.NotifyDirectory.CompletionFilter;
WatchTree = (PtrIoStackLocation->Flags & SL_WATCH_TREE ? TRUE : FALSE);
// If you wish to capture the subject context, you can do so as
// follows:
// {
// PSECURITY_SUBJECT_CONTEXT SubjectContext;
// SubjectContext = Ext2AllocatePool(PagedPool,
// sizeof(SECURITY_SUBJECT_CONTEXT) );
// SeCaptureSubjectContext(SubjectContext);
// }
FsRtlNotifyFullChangeDirectory((PNOTIFY_SYNC)&(PtrVCB->NotifyIRPMutex), &(PtrVCB->NextNotifyIRP), (void *)PtrCCB,
(PSTRING)(PtrFCB->FCBName->ObjectName.Buffer), WatchTree, FALSE, CompletionFilter, PtrIrp,
NULL, // Ext2TraverseAccessCheck(...) ?
NULL); // SubjectContext ?
RC = STATUS_PENDING;
try_exit: NOTHING;
}
finally
{
if (PostRequest)
{
// Perform appropriate post related processing here
if (AcquiredFCB)
{
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released in DirCtrl", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
PtrReqdFCB->MainResource.ActiveCount,
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
AcquiredFCB = FALSE;
}
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
}
else if (CompleteRequest)
{
PtrIrp->IoStatus.Status = RC;
PtrIrp->IoStatus.Information = 0;
// Free up the Irp Context
Ext2ReleaseIrpContext(PtrIrpContext);
// complete the IRP
IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
} else {
// Simply free up the IrpContext since the IRP has been queued
Ext2ReleaseIrpContext(PtrIrpContext);
}
// Release the FCB resources if acquired.
if (AcquiredFCB)
{
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
DebugTrace(DEBUG_TRACE_MISC, "*** FReleased in [DirCtrl]", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]",
PtrReqdFCB->MainResource.ActiveCount,
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
AcquiredFCB = FALSE;
}
}
return(RC);
}

View file

@ -0,0 +1,116 @@
//Microsoft Developer Studio generated resource script.
//
#include "../inc/resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/* REACTOS FIXME */
/* #include "ntverp.h" */
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"..\\inc\\resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""ntverp.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,0,0,3
PRODUCTVERSION 0,0,0,3
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x29L
#else
FILEFLAGS 0x28L
#endif
FILEOS 0x40004L
FILETYPE 0x3L
FILESUBTYPE 0x7L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "Ext2 File System Driver\0"
VALUE "CompanyName", "Purayidathil\0"
VALUE "FileDescription", "Ext2 File System Driver\0"
VALUE "FileVersion", "0, 0, 0, 3\0"
VALUE "InternalName", "ext2.sys\0"
VALUE "LegalCopyright", "Copyright © 2002 Manoj Paul Joseph\0"
VALUE "LegalTrademarks", " - \0"
VALUE "OriginalFilename", "ext2.sys\0"
VALUE "PrivateBuild", " - \0"
VALUE "ProductName", "Ext2 File System Driver for Windows NT\0"
VALUE "ProductVersion", "0, 0, 0, 3\0"
VALUE "SpecialBuild", " - \0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View file

@ -0,0 +1,381 @@
/*************************************************************************
*
* File: ext2init.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* This file contains the initialization code for the kernel mode
* Ext2 FSD module. The DriverEntry() routine is called by the I/O
* sub-system to initialize the FSD.
*
* Author: Manoj Paul Joseph
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_INIT
#define DEBUG_LEVEL (DEBUG_TRACE_INIT)
#define EXT2_FS_NAME L"\\ext2"
// global variables are declared here
Ext2Data Ext2GlobalData;
/*************************************************************************
*
* Function: DriverEntry()
*
* Description:
* This routine is the standard entry point for all kernel mode drivers.
* The routine is invoked at IRQL PASSIVE_LEVEL in the context of a
* system worker thread.
* All FSD specific data structures etc. are initialized here.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded).
*
*************************************************************************/
NTSTATUS DriverEntry(
PDRIVER_OBJECT DriverObject, // created by the I/O sub-system
PUNICODE_STRING RegistryPath) // path to the registry key
{
NTSTATUS RC = STATUS_SUCCESS;
UNICODE_STRING DriverDeviceName;
BOOLEAN RegisteredShutdown = FALSE;
#if 0
Ext2BreakPoint();
#endif
try
{
try
{
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Ext2 File System Driver Entry <<<<<<<", 0);
// initialize the global data structure
RtlZeroMemory(&Ext2GlobalData, sizeof(Ext2GlobalData));
// initialize some required fields
Ext2GlobalData.NodeIdentifier.NodeType = EXT2_NODE_TYPE_GLOBAL_DATA;
Ext2GlobalData.NodeIdentifier.NodeSize = sizeof(Ext2GlobalData);
// initialize the global data resource and remember the fact that
// the resource has been initialized
RC = ExInitializeResourceLite(&(Ext2GlobalData.GlobalDataResource));
ASSERT(NT_SUCCESS(RC));
Ext2SetFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_RESOURCE_INITIALIZED);
// keep a ptr to the driver object sent to us by the I/O Mgr
Ext2GlobalData.Ext2DriverObject = DriverObject;
// initialize the mounted logical volume list head
InitializeListHead( &( Ext2GlobalData.NextVCB ) );
// before we proceed with any more initialization, read in
// user supplied configurable values ...
// if (!NT_SUCCESS(RC = Ext2ObtainRegistryValues(RegistryPath))) {
// in your commercial driver implementation, it would be
// advisable for your driver to print an appropriate error
// message to the system error log before leaving
// try_return(RC);
// }
// we should have the registry data (if any), allocate zone memory ...
// This is an example of when FSD implementations try to pre-allocate
// some fixed amount of memory to avoid internal fragmentation and/or waiting
// later during run-time ...
#ifdef USE_ZONES
if (!NT_SUCCESS(RC = Ext2InitializeZones()))
{
// we failed, print a message and leave ...
try_return(RC);
}
#endif
//
// Initialize the Thread queue structure...
//
KeInitializeEvent(
&Ext2GlobalData.ThreadQueue.QueueEvent,
SynchronizationEvent,
FALSE
);
KeInitializeSpinLock( &Ext2GlobalData.ThreadQueue.SpinLock );
InitializeListHead( &Ext2GlobalData.ThreadQueue.ThreadQueueListHead );
//
// Done Initializing...
// Now Creating a worker thread to handle Worker threads...
//
PsCreateSystemThread(
&Ext2GlobalData.ThreadQueue.QueueHandlerThread, (ACCESS_MASK) 0L,
NULL, NULL, NULL, Ext2QueueHandlerThread, NULL );
// initialize the IRP major function table, and the fast I/O table
Ext2FsdInitializeFunctionPointers(DriverObject);
// create a device object representing the driver itself
// so that requests can be targeted to the driver ...
// e.g. for a disk-based FSD, "mount" requests will be sent to
// this device object by the I/O Manager.\
// For a redirector/server, you may have applications
// send "special" IOCTL's using this device object ...
RtlInitUnicodeString(&DriverDeviceName, EXT2_FS_NAME);
if (!NT_SUCCESS(RC = IoCreateDevice(
DriverObject, // our driver object
0, // don't need an extension for this object
&DriverDeviceName,// name - can be used to "open" the driver
// see the book for alternate choices
FILE_DEVICE_DISK_FILE_SYSTEM,
0, // no special characteristics
// do not want this as an exclusive device, though you might
FALSE,
&(Ext2GlobalData.Ext2DeviceObject))))
{
// failed to create a device object, leave ...
try_return(RC);
}
// register the driver with the I/O Manager, pretend as if this is
// a physical disk based FSD (or in order words, this FSD manages
// logical volumes residing on physical disk drives)
IoRegisterFileSystem(Ext2GlobalData.Ext2DeviceObject);
{
TIME_FIELDS TimeFields;
TimeFields.Day = 1;
TimeFields.Hour = 0;
TimeFields.Milliseconds = 0;
TimeFields.Minute = 0;
TimeFields.Month = 1;
TimeFields.Second = 0;
TimeFields.Weekday = 0;
TimeFields.Year = 1970;
RtlTimeFieldsToTime( &TimeFields, &Ext2GlobalData.TimeDiff );
/*
Ext2GlobalData.TimeDiff.QuadPart = 0;
RtlTimeToTimeFields( &Ext2GlobalData.TimeDiff,&TimeFields );
TimeFields.Year = 2002;
RtlTimeFieldsToTime( &TimeFields, &Ext2GlobalData.TimeDiff );
*/
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
// we encountered an exception somewhere, eat it up
RC = GetExceptionCode();
}
try_exit: NOTHING;
}
finally
{
// start unwinding if we were unsuccessful
if (!NT_SUCCESS(RC))
{
// Now, delete any device objects, etc. we may have created
if (Ext2GlobalData.Ext2DeviceObject)
{
IoDeleteDevice(Ext2GlobalData.Ext2DeviceObject);
Ext2GlobalData.Ext2DeviceObject = NULL;
}
// free up any memory we might have reserved for zones/lookaside
// lists
if (Ext2GlobalData.Ext2Flags & EXT2_DATA_FLAGS_ZONES_INITIALIZED)
{
Ext2DestroyZones();
}
// delete the resource we may have initialized
if (Ext2GlobalData.Ext2Flags & EXT2_DATA_FLAGS_RESOURCE_INITIALIZED)
{
// un-initialize this resource
ExDeleteResourceLite(&(Ext2GlobalData.GlobalDataResource));
Ext2ClearFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_RESOURCE_INITIALIZED);
}
}
}
return(RC);
}
/*************************************************************************
*
* Function: Ext2FsdInitializeFunctionPointers()
*
* Description:
* Initialize the IRP... function pointer array in the driver object
* structure. Also initialize the fast-io function ptr array ...
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
void Ext2FsdInitializeFunctionPointers(
PDRIVER_OBJECT DriverObject) // created by the I/O sub-system
{
PFAST_IO_DISPATCH PtrFastIoDispatch = NULL;
// initialize the function pointers for the IRP major
// functions that this FSD is prepared to handle ...
// NT Version 4.0 has 28 possible functions that a
// kernel mode driver can handle.
// NT Version 3.51 and before has only 22 such functions,
// of which 18 are typically interesting to most FSD's.
// The only interesting new functions that a FSD might
// want to respond to beginning with Version 4.0 are the
// IRP_MJ_QUERY_QUOTA and the IRP_MJ_SET_QUOTA requests.
// The code below does not handle quota manipulation, neither
// does the NT Version 4.0 operating system (or I/O Manager).
// However, you should be on the lookout for any such new
// functionality that your FSD might have to implement in
// the near future.
DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2Create;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2Close;
DriverObject->MajorFunction[IRP_MJ_READ] = Ext2Read;
DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2Write;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = Ext2FileInfo;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2FileInfo;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2Flush;
// To implement support for querying and modifying volume attributes
// (volume information query/set operations), enable initialization
// of the following two function pointers and then implement the supporting
// functions. Use Chapter 11 in the text to assist you in your efforts.
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = Ext2QueryVolInfo;
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = Ext2SetVolInfo;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = Ext2DirControl;
// To implement support for file system IOCTL calls, enable initialization
// of the following function pointer and implement appropriate support. Use
// Chapter 11 in the text to assist you in your efforts.
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = Ext2FileSystemControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ext2DeviceControl;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2Shutdown;
// For byte-range lock support, enable initialization of the following
// function pointer and implement appropriate support. Use Chapter 10
// in the text to assist you in your efforts.
// DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = Ext2LockControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2Cleanup;
// If your FSD supports security attributes, you should provide appropriate
// dispatch entry points and initialize the function pointers as given below.
// DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = Ext2Security;
// DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = Ext2Security;
// If you support extended attributes, you should provide appropriate
// dispatch entry points and initialize the function pointers as given below.
// DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = Ext2ExtendedAttr;
// DriverObject->MajorFunction[IRP_MJ_SET_EA] = Ext2ExtendedAttr;
// Now, it is time to initialize the fast-io stuff ...
/*
DriverObject->FastIoDispatch = NULL;
*/
PtrFastIoDispatch = DriverObject->FastIoDispatch = &(Ext2GlobalData.Ext2FastIoDispatch);
// initialize the global fast-io structure
// NOTE: The fast-io structure has undergone a substantial revision
// in Windows NT Version 4.0. The structure has been extensively expanded.
// Therefore, if your driver needs to work on both V3.51 and V4.0+,
// you will have to be able to distinguish between the two versions at compile time.
PtrFastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
PtrFastIoDispatch->FastIoCheckIfPossible = Ext2FastIoCheckIfPossible;
PtrFastIoDispatch->FastIoRead = Ext2FastIoRead;
PtrFastIoDispatch->FastIoWrite = Ext2FastIoWrite;
PtrFastIoDispatch->FastIoQueryBasicInfo = Ext2FastIoQueryBasicInfo;
PtrFastIoDispatch->FastIoQueryStandardInfo = Ext2FastIoQueryStdInfo;
PtrFastIoDispatch->FastIoLock = Ext2FastIoLock;
PtrFastIoDispatch->FastIoUnlockSingle = Ext2FastIoUnlockSingle;
PtrFastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll;
PtrFastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey;
PtrFastIoDispatch->AcquireFileForNtCreateSection = Ext2FastIoAcqCreateSec;
PtrFastIoDispatch->ReleaseFileForNtCreateSection = Ext2FastIoRelCreateSec;
// the remaining are only valid under NT Version 4.0 and later
#if(_WIN32_WINNT >= 0x0400)
PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetInfo;
PtrFastIoDispatch->AcquireForModWrite = Ext2FastIoAcqModWrite;
PtrFastIoDispatch->ReleaseForModWrite = Ext2FastIoRelModWrite;
PtrFastIoDispatch->AcquireForCcFlush = Ext2FastIoAcqCcFlush;
PtrFastIoDispatch->ReleaseForCcFlush = Ext2FastIoRelCcFlush;
// MDL functionality
PtrFastIoDispatch->MdlRead = Ext2FastIoMdlRead;
PtrFastIoDispatch->MdlReadComplete = Ext2FastIoMdlReadComplete;
PtrFastIoDispatch->PrepareMdlWrite = Ext2FastIoPrepareMdlWrite;
PtrFastIoDispatch->MdlWriteComplete = Ext2FastIoMdlWriteComplete;
// although this FSD does not support compressed read/write functionality,
// NTFS does, and if you design a FSD that can provide such functionality,
// you should consider initializing the fast io entry points for reading
// and/or writing compressed data ...
#endif // (_WIN32_WINNT >= 0x0400)
// last but not least, initialize the Cache Manager callback functions
// which are used in CcInitializeCacheMap()
Ext2GlobalData.CacheMgrCallBacks.AcquireForLazyWrite = Ext2AcqLazyWrite;
Ext2GlobalData.CacheMgrCallBacks.ReleaseFromLazyWrite = Ext2RelLazyWrite;
Ext2GlobalData.CacheMgrCallBacks.AcquireForReadAhead = Ext2AcqReadAhead;
Ext2GlobalData.CacheMgrCallBacks.ReleaseFromReadAhead = Ext2RelReadAhead;
return;
}
VOID Ext2QueueHandlerThread(
IN PVOID StartContext )
{
DebugTrace(DEBUG_TRACE_MISC, "Ext2QueueHandlerThread!!!", 0);
while( 1 )
{
KeWaitForSingleObject( &Ext2GlobalData.ThreadQueue.QueueEvent,
Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
DebugTrace(DEBUG_TRACE_MISC, "Ext2QueueHandlerThread Alerted!!!", 0);
while( !IsListEmpty( &Ext2GlobalData.ThreadQueue.ThreadQueueListHead ) )
{
HANDLE ThreadHandle;
PLIST_ENTRY PtrEntry = NULL;
PtrExt2IrpContext PtrIrpContext = NULL;
PtrEntry = ExInterlockedRemoveHeadList(
&Ext2GlobalData.ThreadQueue.ThreadQueueListHead,
&Ext2GlobalData.ThreadQueue.SpinLock );
ASSERT( PtrEntry );
PtrIrpContext = CONTAINING_RECORD( PtrEntry, Ext2IrpContext, ThreadQueueListEntry );
PsCreateSystemThread(
&ThreadHandle, (ACCESS_MASK) 0L,
NULL, NULL, NULL, Ext2CommonDispatch, PtrIrpContext );
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,350 @@
/*************************************************************************
*
* File: flush.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains code to handle the "Flush Buffers" dispatch entry point.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_FLUSH
#define DEBUG_LEVEL (DEBUG_TRACE_FLUSH)
/*************************************************************************
*
* Function: Ext2Flush()
*
* Description:
* The I/O Manager will invoke this routine to handle a flush buffers
* request
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2Flush(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{
NTSTATUS RC = STATUS_SUCCESS;
PtrExt2IrpContext PtrIrpContext = NULL;
BOOLEAN AreWeTopLevel = FALSE;
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Flush IRP Received...", 0);
// Ext2BreakPoint();
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
// set the top level context
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try
{
// get an IRP context structure and issue the request
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = Ext2CommonFlush(PtrIrpContext, Irp);
} except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel) {
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
}
/*************************************************************************
*
* Function: Ext2CommonFlush()
*
* Description:
* The actual work is performed here. This routine may be invoked in one'
* of the two possible contexts:
* (a) in the context of a system worker thread
* (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS Ext2CommonFlush(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp)
{
NTSTATUS RC = STATUS_SUCCESS;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
PFILE_OBJECT PtrFileObject = NULL;
PtrExt2FCB PtrFCB = NULL;
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL;
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
BOOLEAN AcquiredFCB = FALSE;
BOOLEAN PostRequest = FALSE;
BOOLEAN CanWait = TRUE;
try {
// First, get a pointer to the current I/O stack location
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
PtrFileObject = PtrIoStackLocation->FileObject;
ASSERT(PtrFileObject);
// Get the FCB and CCB pointers
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
ASSERT(PtrCCB);
PtrFCB = PtrCCB->PtrFCB;
AssertFCB( PtrFCB );
/*ASSERT(PtrFCB);
ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
// Get some of the parameters supplied to us
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
// If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous.
if (!CanWait) {
PostRequest = TRUE;
try_return(RC);
}
// Check the type of object passed-in. That will determine the course of
// action we take.
if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & EXT2_FCB_ROOT_DIRECTORY)) {
if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) {
PtrVCB = (PtrExt2VCB)(PtrFCB);
} else {
PtrVCB = PtrFCB->PtrVCB;
}
// The caller wishes to flush all files for the mounted
// logical volume. The flush volume routine below should simply
// walk through all of the open file streams, acquire the
// FCB resource, and request the flush operation from the Cache
// Manager. Basically, the sequence of operations listed below
// for a single file should be executed on all open files.
Ext2FlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB);
try_return(RC);
}
if (!(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY))
{
// This is a regular file.
ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
AcquiredFCB = TRUE;
// Request the Cache Manager to perform a flush operation.
// Further, instruct the Cache Manager that we wish to flush the
// entire file stream.
Ext2FlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus));
RC = PtrIrp->IoStatus.Status;
// All done. You may want to also flush the directory entry for the
// file stream at this time.
// Some log-based FSD implementations may wish to flush their
// log files at this time. Finally, you should update the time-stamp
// values for the file stream appropriately. This would involve
// obtaining the current time and modifying the appropriate directory
// entry fields.
}
try_exit:
if (AcquiredFCB)
{
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Flush]", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
PtrReqdFCB->MainResource.ActiveCount,
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
AcquiredFCB = FALSE;
}
if (!PostRequest)
{
PIO_STACK_LOCATION PtrNextIoStackLocation = NULL;
NTSTATUS RC1 = STATUS_SUCCESS;
// Send the request down at this point.
// To do this, you must set the next IRP stack location, and
// maybe set a completion routine.
// Be careful about marking the IRP pending if the lower level
// driver returned pending and you do have a completion routine!
PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp);
*PtrNextIoStackLocation = *PtrIoStackLocation;
// Set the completion routine to "eat-up" any
// STATUS_INVALID_DEVICE_REQUEST error code returned by the lower
// level driver.
IoSetCompletionRoutine(PtrIrp, Ext2FlushCompletion, NULL, TRUE, TRUE, TRUE);
/*
* The exception handlers propably masked out the
* fact that PtrVCB was never set.
* -- Filip Navara, 18/08/2004
*/
PtrVCB = PtrFCB->PtrVCB;
RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1);
}
} finally {
if (PostRequest) {
// Nothing to lock now.
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
} else {
// Release the IRP context at this time.
Ext2ReleaseIrpContext(PtrIrpContext);
}
}
return(RC);
}
/*************************************************************************
*
* Function: Ext2FlushAFile()
*
* Description:
* Tell the Cache Manager to perform a flush.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
void Ext2FlushAFile(
PtrExt2NTRequiredFCB PtrReqdFCB,
PIO_STATUS_BLOCK PtrIoStatus)
{
CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus);
return;
}
/*************************************************************************
*
* Function: Ext2FlushLogicalVolume()
*
* Description:
* Flush everything beginning at root directory.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
void Ext2FlushLogicalVolume(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PtrExt2VCB PtrVCB)
{
BOOLEAN AcquiredVCB = FALSE;
PtrExt2FCB PtrFCB = NULL;
PLIST_ENTRY PtrNextFCB = NULL;
try {
ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE);
AcquiredVCB = TRUE;
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired Ex [Flush] ", 0);
// Go through the list of FCB's. You would probably
// flush all of the files. Then, you could flush the
// directories that you may have have pinned into memory.
// NOTE: This function may also be invoked internally as part of
// processing a shutdown request.
}
finally
{
if (AcquiredVCB)
{
Ext2ReleaseResource(&(PtrVCB->VCBResource));
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Flush]", 0);
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
PtrVCB->VCBResource.ActiveCount,
PtrVCB->VCBResource.NumberOfExclusiveWaiters,
PtrVCB->VCBResource.NumberOfSharedWaiters );
}
}
return;
}
/*************************************************************************
*
* Function: Ext2FlushCompletion()
*
* Description:
* Eat up any bad errors.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
NTSTATUS Ext2FlushCompletion(
PDEVICE_OBJECT PtrDeviceObject,
PIRP PtrIrp,
PVOID Context)
{
NTSTATUS RC = STATUS_SUCCESS;
if (PtrIrp->PendingReturned) {
IoMarkIrpPending(PtrIrp);
}
if (PtrIrp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) {
// cannot do much here, can we?
PtrIrp->IoStatus.Status = STATUS_SUCCESS;
}
return(STATUS_SUCCESS);
}

View file

@ -0,0 +1,944 @@
/*************************************************************************
*
* File: fsctrl.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains code to handle the various File System Control calls.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_FILE_CONTROL
#define DEBUG_LEVEL (DEBUG_TRACE_FSCTRL)
NTSTATUS
Ext2MountVolume(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp );
NTSTATUS
Ext2GetPartitionInfo(
IN PDEVICE_OBJECT TargetDeviceObject,
IN PPARTITION_INFORMATION PartitionInformation
);
NTSTATUS
Ext2GetDriveLayout(
IN PDEVICE_OBJECT TargetDeviceObject,
IN PDRIVE_LAYOUT_INFORMATION DriveLayoutInformation,
IN int BufferSize
);
BOOLEAN
Ext2PerformVerifyDiskRead(
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVOID Buffer,
IN LONGLONG Lbo,
IN ULONG NumberOfBytesToRead
);
NTSTATUS Ext2UserFileSystemRequest(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp );
/*************************************************************************
*
* Function: Ext2FileSystemControl
*
* Description:
* The I/O Manager will invoke this routine to handle a
* File System Control IRP
*
* Expected Interrupt Level (for execution) :
*
* ???
*
* Arguments:
*
* DeviceObject - Supplies the volume device object where the
* file exists
*
* Irp - Supplies the Irp being processed
*
*
* Return Value:
*
* NTSTATUS - The FSD status for the IRP
*
*************************************************************************/
NTSTATUS
Ext2FileSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "File System Control IRP Received...", 0);
// Ext2BreakPoint();
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
//
// Get a pointer to the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
if( IrpSp->MinorFunction == IRP_MN_MOUNT_VOLUME )
{
DebugTrace(DEBUG_TRACE_MOUNT, "Mount Request Received...", 0);
Status = Ext2MountVolume ( Irp, IrpSp );
Ext2CompleteRequest( Irp, Status );
}
else if( IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST )
{
DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_USER_FS_REQUEST received...", 0);
Status = Ext2UserFileSystemRequest( Irp, IrpSp );
Ext2CompleteRequest( Irp, Status );
}
else
{
if( IrpSp->MinorFunction == IRP_MN_VERIFY_VOLUME )
{
DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_VERIFY_VOLUME received...", 0);
}
else if( IrpSp->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM )
{
DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_LOAD_FILE_SYSTEM received...", 0);
}
else
{
DebugTrace(DEBUG_TRACE_FSCTRL, "Unknown Minor IRP code received...", 0);
}
Status = STATUS_INVALID_DEVICE_REQUEST;
Ext2CompleteRequest( Irp, Status );
}
FsRtlExitFileSystem();
return Status;
}
/*************************************************************************
*
* Function: Ext2MountVolume()
*
* Description:
* This routine verifies and mounts the volume;
* Called by FSCTRL IRP handler to attempt a
* volume mount.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
*
* Arguments:
*
* Irp - Supplies the Irp being processed
* IrpSp - Irp Stack Location pointer
*
* Return Value:
*
* NTSTATUS - The Mount status
*
*************************************************************************/
NTSTATUS
Ext2MountVolume (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp )
{
// Volume Parameter Block
PVPB PtrVPB;
// The target device object
PDEVICE_OBJECT TargetDeviceObject = NULL;
// The new volume device object (to be created if partition is Ext2)
PDEVICE_OBJECT PtrVolumeDeviceObject = NULL;
// Return Status
NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME;
// Number of bytes to read for Volume verification...
unsigned long NumberOfBytesToRead = 0;
// Starting Offset for 'read'
LONGLONG StartingOffset = 0;
// Boot Sector information...
PPACKED_BOOT_SECTOR BootSector = NULL;
// Ext2 Super Block information...
PEXT2_SUPER_BLOCK SuperBlock = NULL;
// Volume Control Block
PtrExt2VCB PtrVCB = NULL;
// The File Object for the root directory
PFILE_OBJECT PtrRootFileObject = NULL;
// Flag
int WeClearedVerifyRequiredBit;
// Used by a for loop...
unsigned int i;
//
LARGE_INTEGER VolumeByteOffset;
unsigned long LogicalBlockSize = 0;
// Buffer Control Block
PBCB PtrBCB = NULL;
// Cache Buffer - used for pinned access of volume...
PVOID PtrCacheBuffer = NULL;
PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL;
PEXT2_INODE PtrInode = NULL;
// Inititalising variables
PtrVPB = IrpSp->Parameters.MountVolume.Vpb;
TargetDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject;
try
{
//
// 1. Reading in Volume meta data
//
// Temporarily clear the DO_VERIFY_VOLUME Flag
WeClearedVerifyRequiredBit = 0;
if ( Ext2IsFlagOn( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ) )
{
Ext2ClearFlag( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME );
WeClearedVerifyRequiredBit = 1;
}
// Allocating memory for reading in Boot Sector...
NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), TargetDeviceObject->SectorSize );
BootSector = Ext2AllocatePool( PagedPool, NumberOfBytesToRead );
RtlZeroMemory( BootSector, NumberOfBytesToRead );
// Reading in Boot Sector
StartingOffset = 0L;
Ext2PerformVerifyDiskRead ( TargetDeviceObject,
BootSector, StartingOffset, NumberOfBytesToRead );
// Allocating memory for reading in Super Block...
SuperBlock = Ext2AllocatePool( PagedPool, NumberOfBytesToRead );
RtlZeroMemory( SuperBlock, NumberOfBytesToRead );
StartingOffset = 1024;
// Reading in the Super Block...
Ext2PerformVerifyDiskRead ( TargetDeviceObject,
SuperBlock, StartingOffset, NumberOfBytesToRead );
// Resetting the DO_VERIFY_VOLUME Flag
if( WeClearedVerifyRequiredBit )
{
PtrVPB->RealDevice->Flags |= DO_VERIFY_VOLUME;
}
// Verifying the Super Block..
if( SuperBlock->s_magic == EXT2_SUPER_MAGIC )
{
//
// Found a valid super block.
// No more tests for now.
// Assuming that this is an ext2 partition...
// Going ahead with mount.
//
DebugTrace(DEBUG_TRACE_MOUNT, "Valid Ext2 partition detected\nMounting %s...", SuperBlock->s_volume_name);
//
// 2. Creating a volume device object
//
if (!NT_SUCCESS( IoCreateDevice(
Ext2GlobalData.Ext2DriverObject, // (This) Driver object
Ext2QuadAlign( sizeof(Ext2VCB) ), // Device Extension
NULL, // Device Name - no name ;)
FILE_DEVICE_DISK_FILE_SYSTEM, // Disk File System
0, // DeviceCharacteristics
FALSE, // Not an exclusive device
(PDEVICE_OBJECT *)&PtrVolumeDeviceObject)) // The Volume Device Object
)
{
try_return( Status );
}
//
// Our alignment requirement is the larger of the processor alignment requirement
// already in the volume device object and that in the TargetDeviceObject
//
if (TargetDeviceObject->AlignmentRequirement > PtrVolumeDeviceObject->AlignmentRequirement)
{
PtrVolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
}
//
// Clearing the Device Initialising Flag
//
Ext2ClearFlag( PtrVolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
//
// Setting the Stack Size for the newly created Volume Device Object
//
PtrVolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
//
// 3. Creating the link between Target Device Object
// and the Volume Device Object via the Volume Parameter Block
//
PtrVPB->DeviceObject = PtrVolumeDeviceObject;
// Remembring the Volume parameters in the VPB bock
for( i = 0; i < 16 ; i++ )
{
PtrVPB->VolumeLabel[i] = SuperBlock->s_volume_name[i];
if( SuperBlock->s_volume_name[i] == 0 )
break;
}
PtrVPB->VolumeLabelLength = i * 2;
PtrVPB->SerialNumber = ((ULONG*)SuperBlock->s_uuid)[0];
//
// 4. Initialise the Volume Comtrol Block
//
{
LARGE_INTEGER AllocationSize;
AllocationSize .QuadPart =
( EXT2_MIN_BLOCK_SIZE << SuperBlock->s_log_block_size ) *
SuperBlock->s_blocks_count;
Ext2InitializeVCB(
PtrVolumeDeviceObject,
TargetDeviceObject,
PtrVPB,
&AllocationSize);
PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension);
ASSERT( PtrVCB );
}
PtrVCB->InodesCount = SuperBlock->s_inodes_count;
PtrVCB->BlocksCount = SuperBlock->s_blocks_count;
PtrVCB->ReservedBlocksCount = SuperBlock->s_r_blocks_count;
PtrVCB->FreeBlocksCount = SuperBlock->s_free_blocks_count;
PtrVCB->FreeInodesCount = SuperBlock->s_free_inodes_count;
PtrVCB->LogBlockSize = SuperBlock->s_log_block_size;
PtrVCB->InodesPerGroup = SuperBlock->s_inodes_per_group;
PtrVCB->BlocksPerGroup = SuperBlock->s_blocks_per_group;
PtrVCB->NoOfGroups = ( SuperBlock->s_blocks_count - SuperBlock->s_first_data_block
+ SuperBlock->s_blocks_per_group - 1 )
/ SuperBlock->s_blocks_per_group;
PtrVCB->PtrGroupDescriptors = Ext2AllocatePool( NonPagedPool, sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups );
RtlZeroMemory( PtrVCB->PtrGroupDescriptors , sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups );
//
// Attempting to Read in some matadata from the Cache...
// using pin access...
//
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
//
// Reading Group Descriptors...
//
if( PtrVCB->LogBlockSize )
{
// First block contains the descriptors...
VolumeByteOffset.QuadPart = LogicalBlockSize;
}
else
{
// Second block contains the descriptors...
VolumeByteOffset.QuadPart = LogicalBlockSize * 2;
}
NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc );
NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize );
if (!CcMapData( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
NumberOfBytesToRead,
TRUE,
&PtrBCB,
&PtrCacheBuffer ))
{
DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
}
else
{
//
// Saving up Often Used Group Descriptor Information in the VCB...
//
unsigned int DescIndex ;
DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
PtrGroupDescriptor = (PEXT2_GROUP_DESCRIPTOR )PtrCacheBuffer;
for( DescIndex = 0; DescIndex < PtrVCB->NoOfGroups; DescIndex++ )
{
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeTablesBlock
= PtrGroupDescriptor[ DescIndex ].bg_inode_table;
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeBitmapBlock
= PtrGroupDescriptor[ DescIndex ].bg_inode_bitmap
;
PtrVCB->PtrGroupDescriptors[ DescIndex ].BlockBitmapBlock
= PtrGroupDescriptor[ DescIndex ].bg_block_bitmap
;
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeBlocksCount
= PtrGroupDescriptor[ DescIndex ].bg_free_blocks_count;
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeInodesCount
= PtrGroupDescriptor[ DescIndex ].bg_free_inodes_count;
}
CcUnpinData( PtrBCB );
PtrBCB = NULL;
}
//
// 5. Creating a Root Directory FCB
//
PtrRootFileObject = IoCreateStreamFileObject(NULL, TargetDeviceObject );
if( !PtrRootFileObject )
{
try_return( Status );
}
//
// Associate the file stream with the Volume parameter block...
// I do it now
//
PtrRootFileObject->Vpb = PtrVCB->PtrVPB;
PtrRootFileObject->ReadAccess = TRUE;
PtrRootFileObject->WriteAccess = TRUE;
{
PtrExt2ObjectName PtrObjectName;
LARGE_INTEGER ZeroSize;
PtrObjectName = Ext2AllocateObjectName();
RtlInitUnicodeString( &PtrObjectName->ObjectName, L"\\" );
Ext2CopyWideCharToUnicodeString( &PtrObjectName->ObjectName, L"\\" );
ZeroSize.QuadPart = 0;
if ( !NT_SUCCESS( Ext2CreateNewFCB(
&PtrVCB->PtrRootDirectoryFCB, // Root FCB
ZeroSize, // AllocationSize,
ZeroSize, // EndOfFile,
PtrRootFileObject, // The Root Dircetory File Object
PtrVCB,
PtrObjectName ) ) )
{
try_return( Status );
}
PtrVCB->PtrRootDirectoryFCB->FCBFlags |= EXT2_FCB_DIRECTORY | EXT2_FCB_ROOT_DIRECTORY;
}
PtrVCB->PtrRootDirectoryFCB->DcbFcb.Dcb.PtrDirFileObject = PtrRootFileObject;
PtrVCB->PtrRootDirectoryFCB->INodeNo = EXT2_ROOT_INO;
PtrRootFileObject->SectionObjectPointer = &(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.SectionObject);
RtlInitUnicodeString( &PtrRootFileObject->FileName, L"\\" );
Ext2InitializeFCBInodeInfo( PtrVCB->PtrRootDirectoryFCB );
//
// Initiating caching for root directory...
//
CcInitializeCacheMap(PtrRootFileObject,
(PCC_FILE_SIZES)(&(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)),
TRUE, // We will utilize pin access for directories
&(Ext2GlobalData.CacheMgrCallBacks), // callbacks
PtrVCB->PtrRootDirectoryFCB ); // The context used in callbacks
//
// 6. Update the VCB Flags
//
PtrVCB->VCBFlags |= EXT2_VCB_FLAGS_VOLUME_MOUNTED ; // | EXT2_VCB_FLAGS_VOLUME_READ_ONLY;
//
// 7. Mount Success
//
Status = STATUS_SUCCESS;
{
//
// This block is for testing....
// To be removed...
/*
EXT2_INODE Inode ;
Ext2ReadInode( PtrVCB, 100, &Inode );
DebugTrace( DEBUG_TRACE_MISC, "Inode size= %lX [FS Ctrl]", Inode.i_size );
Ext2DeallocInode( NULL, PtrVCB, 0xfb6 );
*/
}
// ObDereferenceObject( TargetDeviceObject );
}
else
{
DebugTrace(DEBUG_TRACE_MOUNT, "Failing mount. Partition not Ext2...", 0);
}
try_exit: NOTHING;
}
finally
{
// Freeing Allocated Memory...
if( SuperBlock != NULL )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", SuperBlock );
ExFreePool( SuperBlock );
}
if( BootSector != NULL )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", BootSector);
ExFreePool( BootSector );
}
// start unwinding if we were unsuccessful
if (!NT_SUCCESS( Status ))
{
}
}
return Status;
}
/*************************************************************************
*
* Function: Ext2MountVolume()
*
* Description:
* This routine is used for querying the partition information.
*
* Expected Interrupt Level (for execution) :
* IRQL_PASSIVE_LEVEL
*
* Arguments:
*
* TargetDeviceObject - The target of the query
* PartitionInformation - Receives the result of the query
*
* Return Value:
*
* NTSTATUS - The return status for the operation
*
*************************************************************************/
NTSTATUS
Ext2GetPartitionInfo (
IN PDEVICE_OBJECT TargetDeviceObject,
IN PPARTITION_INFORMATION PartitionInformation
)
{
PIRP Irp;
KEVENT *PtrEvent = NULL;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
//
// Query the partition table
//
PtrEvent = ( KEVENT * )Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof( KEVENT ) ) );
KeInitializeEvent( PtrEvent, NotificationEvent, FALSE );
Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_PARTITION_INFO,
TargetDeviceObject,
NULL,
0,
PartitionInformation,
sizeof(PARTITION_INFORMATION),
FALSE,
PtrEvent,
&Iosb );
if ( Irp == NULL )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
ExFreePool( PtrEvent );
return 0;
}
Status = IoCallDriver( TargetDeviceObject, Irp );
if ( Status == STATUS_PENDING ) {
(VOID) KeWaitForSingleObject( PtrEvent,
Executive,
KernelMode,
FALSE,
(PLARGE_INTEGER)NULL );
Status = Iosb.Status;
}
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
ExFreePool( PtrEvent );
return Status;
}
/*************************************************************************
*
* Function: Ext2MountVolume()
*
* Description:
* This routine is used for querying the Drive Layout Information.
*
* Expected Interrupt Level (for execution) :
* IRQL_PASSIVE_LEVEL
*
* Arguments:
*
* TargetDeviceObject - The target of the query
* PartitionInformation - Receives the result of the query
*
* Return Value:
*
* NTSTATUS - The return status for the operation
*
*************************************************************************/
NTSTATUS Ext2GetDriveLayout (
IN PDEVICE_OBJECT TargetDeviceObject,
IN PDRIVE_LAYOUT_INFORMATION DriveLayoutInformation,
IN int BufferSize
)
{
PIRP Irp;
KEVENT *PtrEvent = NULL;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
//
// Query the partition table
//
PtrEvent = ( KEVENT * )Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof( KEVENT ) ) );
KeInitializeEvent( PtrEvent, NotificationEvent, FALSE );
Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_LAYOUT,
TargetDeviceObject,
NULL,
0,
DriveLayoutInformation,
BufferSize,
FALSE,
PtrEvent,
&Iosb );
if ( Irp == NULL )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
ExFreePool( PtrEvent );
return 0;
}
Status = IoCallDriver( TargetDeviceObject, Irp );
if ( Status == STATUS_PENDING ) {
(VOID) KeWaitForSingleObject( PtrEvent,
Executive,
KernelMode,
FALSE,
(PLARGE_INTEGER)NULL );
Status = Iosb.Status;
}
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
ExFreePool( PtrEvent );
return Status;
}
/*************************************************************************
*
* Function: Ext2MountVolume()
*
* Description:
* This routine is used for performing a verify read...
*
* Expected Interrupt Level (for execution) :
* IRQL_PASSIVE_LEVEL
*
* Arguments:
* TargetDeviceObject - The target of the query
* PartitionInformation - Receives the result of the query
*
* Return Value:
* NTSTATUS - The return status for the operation
*
*************************************************************************/
BOOLEAN Ext2PerformVerifyDiskRead(
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVOID Buffer,
IN LONGLONG Lbo,
IN ULONG NumberOfBytesToRead )
{
KEVENT Event;
PIRP Irp;
LARGE_INTEGER ByteOffset;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
//
// Initialize the event we're going to use
//
KeInitializeEvent( &Event, NotificationEvent, FALSE );
//
// Build the irp for the operation
//
ByteOffset.QuadPart = Lbo;
Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
TargetDeviceObject,
Buffer,
NumberOfBytesToRead,
&ByteOffset,
&Event,
&Iosb );
if ( Irp == NULL )
{
Status = FALSE;
}
Ext2SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
//
// Call the device to do the read and wait for it to finish.
//
Status = IoCallDriver( TargetDeviceObject, Irp );
if (Status == STATUS_PENDING)
{
(VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
Status = Iosb.Status;
}
ASSERT(Status != STATUS_VERIFY_REQUIRED);
//
// Special case this error code because this probably means we used
// the wrong sector size and we want to reject STATUS_WRONG_VOLUME.
//
if (Status == STATUS_INVALID_PARAMETER)
{
return FALSE;
}
//
// If it doesn't succeed then either return or raise the error.
//
if (!NT_SUCCESS(Status))
{
return FALSE;
}
//
// And return to our caller
//
return TRUE;
}
/*************************************************************************
*
* Function: Ext2UserFileSystemRequest()
*
* Description:
* This routine handles User File System Requests
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
*
* Arguments:
*
* Irp - Supplies the Irp being processed
* IrpSp - Irp Stack Location pointer
*
* Return Value: NT_STATUS
*
*************************************************************************/
NTSTATUS Ext2UserFileSystemRequest (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp )
{
NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
ULONG FsControlCode;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
try
{
#ifdef _GNU_NTIFS_
FsControlCode = ((PEXTENDED_IO_STACK_LOCATION)IrpSp)->Parameters.FileSystemControl.FsControlCode;
#else
FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
#endif
switch ( FsControlCode )
{
case FSCTL_REQUEST_OPLOCK_LEVEL_1:
DebugTrace(DEBUG_TRACE_FSCTRL, "FSCTL_REQUEST_OPLOCK_LEVEL_1", 0);
break;
case FSCTL_REQUEST_OPLOCK_LEVEL_2:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL ", 0);
break;
case FSCTL_REQUEST_BATCH_OPLOCK:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_REQUEST_OPLOCK_LEVEL_2 ", 0);
break;
case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
DebugTrace(DEBUG_TRACE_MISC, " FSCTL_OPLOCK_BREAK_ACKNOWLEDGE ", 0);
break;
case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPBATCH_ACK_CLOSE_PENDING ", 0);
break;
case FSCTL_OPLOCK_BREAK_NOTIFY:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPLOCK_BREAK_NOTIFY ", 0);
break;
case FSCTL_OPLOCK_BREAK_ACK_NO_2:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPLOCK_BREAK_ACK_NO_2 ", 0);
break;
case FSCTL_LOCK_VOLUME:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_LOCK_VOLUME ", 0);
break;
case FSCTL_UNLOCK_VOLUME:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_UNLOCK_VOLUME ", 0);
break;
case FSCTL_DISMOUNT_VOLUME:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_DISMOUNT_VOLUME ", 0);
break;
case FSCTL_MARK_VOLUME_DIRTY:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_MARK_VOLUME_DIRTY ", 0);
break;
case FSCTL_IS_VOLUME_DIRTY:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_VOLUME_DIRTY ", 0);
break;
case FSCTL_IS_VOLUME_MOUNTED:
Status = Ext2VerifyVolume(Irp, IrpSp );
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_VOLUME_MOUNTED ", 0);
break;
case FSCTL_IS_PATHNAME_VALID:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_PATHNAME_VALID ", 0);
break;
case FSCTL_QUERY_RETRIEVAL_POINTERS:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_QUERY_RETRIEVAL_POINTERS ", 0);
break;
case FSCTL_QUERY_FAT_BPB:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_QUERY_FAT_BPB ", 0);
break;
case FSCTL_FILESYSTEM_GET_STATISTICS:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_FILESYSTEM_GET_STATISTICS ", 0);
break;
case FSCTL_GET_VOLUME_BITMAP:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_GET_VOLUME_BITMAP ", 0);
break;
case FSCTL_GET_RETRIEVAL_POINTERS:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_GET_RETRIEVAL_POINTERS ", 0);
break;
case FSCTL_MOVE_FILE:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_MOVE_FILE ", 0);
break;
case FSCTL_ALLOW_EXTENDED_DASD_IO:
DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_ALLOW_EXTENDED_DASD_IO ", 0);
break;
default :
DebugTrace(DEBUG_TRACE_FSCTRL, "Unknown FSCTRL !!!", 0);
}
try_exit: NOTHING;
}
finally
{
}
return Status;
}
NTSTATUS Ext2VerifyVolume (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp )
{
PVPB PtrVPB;
PtrVPB = IrpSp->Parameters.VerifyVolume.Vpb;
if( IrpSp->FileObject )
{
PtrVPB = IrpSp->FileObject->Vpb;
}
if( !PtrVPB )
{
PtrVPB = IrpSp->Parameters.VerifyVolume.Vpb;
}
if( !PtrVPB )
{
return STATUS_WRONG_VOLUME;
}
if ( Ext2IsFlagOn( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ) )
{
//
// Not doing a verify!
// Just acting as if everyting is fine!
// THis should do for now
//
Ext2ClearFlag( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME );
}
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,543 @@
/*************************************************************************
*
* File: io.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* This file contains low level disk io routines.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_IO
/*************************************************************************
*
* Function: Ext2PassDownMultiReadWriteIRP()
*
* Description:
* pass down multiple read IRPs as Associated IRPs
*
* Expected Interrupt Level (for execution) :
*
* ?
*
* Return Value: STATUS_SUCCESS / STATUS_PENDING / Error
*
*************************************************************************/
NTSTATUS Ext2PassDownMultiReadWriteIRP(
PEXT2_IO_RUN PtrIoRuns,
UINT Count,
ULONG TotalReadWriteLength,
PtrExt2IrpContext PtrIrpContext,
PtrExt2FCB PtrFCB,
BOOLEAN SynchronousIo)
{
PIRP PtrMasterIrp;
PIRP PtrAssociatedIrp;
PIO_STACK_LOCATION PtrIrpSp;
PMDL PtrMdl;
PtrExt2VCB PtrVCB;
UINT i;
ULONG BufferOffset;
PEXT2_IO_CONTEXT PtrIoContext = NULL;
PKEVENT PtrSyncEvent = NULL;
ULONG LogicalBlockSize;
ULONG ReadWriteLength;
NTSTATUS RC = STATUS_SUCCESS;
PtrVCB = PtrFCB->PtrVCB;
PtrMasterIrp = PtrIrpContext->Irp;
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
try
{
if( !SynchronousIo )
{
IoMarkIrpPending( PtrIrpContext->Irp );
// We will be returning STATUS_PENDING...
}
if( !PtrMasterIrp->MdlAddress )
{
Ext2LockCallersBuffer( PtrMasterIrp, TRUE, TotalReadWriteLength );
}
if( SynchronousIo )
{
PtrSyncEvent = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) ) );
if ( !PtrSyncEvent )
{
RC = STATUS_INSUFFICIENT_RESOURCES;
try_return ( RC );
}
KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE );
}
//
// Allocate and initialize a completion context
//
PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) ) );
if ( !PtrIoContext )
{
RC = STATUS_INSUFFICIENT_RESOURCES;
try_return ( RC );
}
RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) );
PtrIoContext->Count = Count;
PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT;
PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT );
PtrIoContext->PtrMasterIrp = PtrMasterIrp;
PtrIoContext->PtrSyncEvent = PtrSyncEvent;
PtrIoContext->ReadWriteLength = TotalReadWriteLength;
for( ReadWriteLength = 0, BufferOffset = 0, i = 0; i < Count; i++, BufferOffset += ReadWriteLength )
{
ReadWriteLength = PtrIoRuns[ i].EndOffset - PtrIoRuns[ i].StartOffset;
//
// Allocating an Associated IRP...
//
PtrAssociatedIrp = IoMakeAssociatedIrp( PtrMasterIrp,
(CCHAR) (PtrVCB->TargetDeviceObject->StackSize + 1 ) );
PtrIoRuns[ i].PtrAssociatedIrp = PtrAssociatedIrp;
ASSERT ( PtrAssociatedIrp );
PtrMasterIrp->AssociatedIrp.IrpCount ++;
//
// Allocating a Memory Descriptor List...
//
PtrMdl = IoAllocateMdl( (PCHAR) PtrMasterIrp->UserBuffer + BufferOffset, // Virtual Address
ReadWriteLength, FALSE, FALSE, PtrAssociatedIrp );
//
// and building a partial MDL...
//
IoBuildPartialMdl( PtrMasterIrp->MdlAddress,
PtrMdl, (PCHAR)PtrMasterIrp->UserBuffer + BufferOffset, ReadWriteLength );
//
// Create an Irp stack location for ourselves...
//
IoSetNextIrpStackLocation( PtrAssociatedIrp );
PtrIrpSp = IoGetCurrentIrpStackLocation( PtrAssociatedIrp );
//
// Setup the Stack location to describe our read.
//
PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
{
PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
PtrIrpSp->Parameters.Read.ByteOffset.QuadPart =
PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
}
else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
{
PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
PtrIrpSp->Parameters.Write.ByteOffset.QuadPart =
PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
}
// PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
// PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock;
//
// Setup a completion routine...
//
IoSetCompletionRoutine( PtrAssociatedIrp,
SynchronousIo ?
Ext2MultiSyncCompletionRoutine :
Ext2MultiAsyncCompletionRoutine,
PtrIoContext, TRUE, TRUE, TRUE );
//
// Initialise the next stack location for the driver below us to use...
//
PtrIrpSp = IoGetNextIrpStackLocation( PtrAssociatedIrp );
PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
{
PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
}
else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
{
PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
}
// PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
// PtrIrpSp->Parameters.Read.ByteOffset.QuadPart =
// PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
}
for( i = 0; i < Count; i++ ) {
DbgPrint("PASSING DOWN IRP %d TO TARGET DEVICE\n", i);
IoCallDriver( PtrVCB->TargetDeviceObject, PtrIoRuns[ i].PtrAssociatedIrp );
}
if( SynchronousIo )
{
//
// Synchronous IO
// Wait for the IO to complete...
//
DbgPrint("DEADLY WAIT (%d)\n", KeGetCurrentIrql());
KeWaitForSingleObject( PtrSyncEvent,
Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
DbgPrint("DEADLY WAIT DONE\n");
try_return ( RC );
}
else
{
// Asynchronous IO...
RC = STATUS_PENDING;
try_return ( RC );
}
try_exit: NOTHING;
}
finally
{
if( PtrSyncEvent )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrSyncEvent );
ExFreePool( PtrSyncEvent );
}
if( PtrIoContext && ! ( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) )
{
//
// This means we are getting out of
// this function without doing a read
// due to an error, maybe...
//
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrIoContext);
ExFreePool( PtrIoContext );
}
}
return(RC);
}
NTSTATUS Ext2PassDownSingleReadWriteIRP(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PtrExt2VCB PtrVCB,
LARGE_INTEGER ByteOffset,
uint32 ReadWriteLength,
BOOLEAN SynchronousIo)
{
NTSTATUS RC = STATUS_SUCCESS;
PEXT2_IO_CONTEXT PtrIoContext = NULL;
PKEVENT PtrSyncEvent = NULL;
PVOID PtrReadBuffer = NULL;
ULONG ReadBufferLength = 0;
ULONG LogicalBlockNo = 0;
ULONG LogicalBlockSize = 0;
ULONG PhysicalBlockSize = 0;
uint32 NumberBytesRead = 0;
int i;
PIO_STACK_LOCATION PtrIrpNextSp = NULL;
try
{
if( !PtrIrp->MdlAddress )
{
Ext2LockCallersBuffer( PtrIrp, TRUE, ReadWriteLength );
}
if( SynchronousIo )
{
PtrSyncEvent = Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) ) );
if ( !PtrSyncEvent )
{
RC = STATUS_INSUFFICIENT_RESOURCES;
try_return ( RC );
}
KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE );
}
//
// Allocate and initialize a completion context
//
PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) ) );
if ( !PtrIoContext )
{
RC = STATUS_INSUFFICIENT_RESOURCES;
try_return ( RC );
}
RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) );
PtrIoContext->Count = 1;
PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT;
PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT );
PtrIoContext->PtrMasterIrp = NULL;
PtrIoContext->PtrSyncEvent = PtrSyncEvent;
PtrIoContext->ReadWriteLength = ReadWriteLength;
IoSetCompletionRoutine( PtrIrp,
SynchronousIo ?
Ext2SingleSyncCompletionRoutine:
Ext2SingleAsyncCompletionRoutine,
PtrIoContext, TRUE, TRUE, TRUE );
//
// Setup the next IRP stack location in the associated Irp for the disk
// driver beneath us.
//
PtrIrpNextSp = IoGetNextIrpStackLocation( PtrIrp );
//
// Setup the Stack location to do a read from the disk driver.
//
PtrIrpNextSp->MajorFunction = PtrIrpContext->MajorFunction;
if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
{
PtrIrpNextSp->Parameters.Read.Length = ReadWriteLength;
PtrIrpNextSp->Parameters.Read.ByteOffset = ByteOffset;
}
else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
{
PtrIrpNextSp->Parameters.Write.Length = ReadWriteLength;
PtrIrpNextSp->Parameters.Write.ByteOffset = ByteOffset;
}
//
// Issue the read / write request
//
RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
if( SynchronousIo )
{
//
// Wait for completion...
//
RC = KeWaitForSingleObject( &PtrIoContext->PtrSyncEvent,
Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
RC = STATUS_SUCCESS;
}
else
{
RC = STATUS_PENDING;
}
try_exit: NOTHING;
}
finally
{
if( PtrSyncEvent )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrSyncEvent );
ExFreePool( PtrSyncEvent );
}
if( PtrIoContext && !( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) )
{
//
// This means we are getting out of
// this function without doing a read / write
// due to an error, maybe...
//
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrIoContext );
ExFreePool( PtrIoContext );
}
}
return RC;
}
/*************************************************************************
*
* Function: Ext2SingleSyncCompletionRoutine()
*
* Description:
* Synchronous I/O Completion Routine
*
* Expected Interrupt Level (for execution) :
*
* ?
*
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
*
*************************************************************************/
NTSTATUS Ext2SingleSyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
)
{
PEXT2_IO_CONTEXT PtrContext = Contxt;
if( Irp->PendingReturned )
IoMarkIrpPending( Irp );
ASSERT( PtrContext );
ASSERT( PtrContext->NodeIdentifier.NodeType == EXT2_NODE_TYPE_IO_CONTEXT );
KeSetEvent( PtrContext->PtrSyncEvent, 0, FALSE );
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
ExFreePool( PtrContext );
return STATUS_SUCCESS;
}
/*************************************************************************
*
* Function: Ext2SingleAsyncCompletionRoutine()
*
* Description:
* Asynchronous I/O Completion Routine
*
* Expected Interrupt Level (for execution) :
*
* ?
*
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
*
*************************************************************************/
NTSTATUS Ext2SingleAsyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
)
{
PEXT2_IO_CONTEXT PtrContext = Contxt;
if( Irp->PendingReturned )
IoMarkIrpPending( Irp );
ASSERT( PtrContext );
ASSERT( PtrContext->NodeIdentifier.NodeType == EXT2_NODE_TYPE_IO_CONTEXT );
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
ExFreePool( PtrContext );
return STATUS_SUCCESS;
}
/*************************************************************************
*
* Function: Ext2MultiSyncCompletionRoutine()
*
* Description:
* Synchronous I/O Completion Routine
*
* Expected Interrupt Level (for execution) :
*
* ?
*
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
*
*************************************************************************/
NTSTATUS Ext2MultiSyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
)
{
PEXT2_IO_CONTEXT PtrContext = Contxt;
ASSERT( PtrContext );
if( Irp->PendingReturned )
{
IoMarkIrpPending( Irp );
}
if (!NT_SUCCESS( Irp->IoStatus.Status ))
{
PtrContext->PtrMasterIrp->IoStatus.Status = Irp->IoStatus.Status;
}
if (InterlockedDecrement( &PtrContext->Count ) == 0)
{
if ( NT_SUCCESS( PtrContext->PtrMasterIrp->IoStatus.Status ) )
{
PtrContext->PtrMasterIrp->IoStatus.Information = PtrContext->ReadWriteLength;
}
else
{
PtrContext->PtrMasterIrp->IoStatus.Information = 0;
}
KeSetEvent( PtrContext->PtrSyncEvent, 0, FALSE );
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
ExFreePool( PtrContext );
}
//
// The master Irp will be automatically completed
// when all the associated IRPs are completed
//
return STATUS_SUCCESS;
}
/*************************************************************************
*
* Function: Ext2MultiAsyncCompletionRoutine()
*
* Description:
* Asynchronous I/O Completion Routine
*
* Expected Interrupt Level (for execution) :
*
* ?
*
* Return Value: NTSTATUS - STATUS_SUCCESS(always)
*
*************************************************************************/
NTSTATUS Ext2MultiAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
)
{
PEXT2_IO_CONTEXT PtrContext = Contxt;
ASSERT( PtrContext );
if( Irp->PendingReturned )
{
IoMarkIrpPending( Irp );
}
if (!NT_SUCCESS( Irp->IoStatus.Status ))
{
PtrContext->PtrMasterIrp->IoStatus.Status = Irp->IoStatus.Status;
}
if (InterlockedDecrement( &PtrContext->Count ) == 0)
{
if ( NT_SUCCESS( PtrContext->PtrMasterIrp->IoStatus.Status ) )
{
PtrContext->PtrMasterIrp->IoStatus.Information = PtrContext->ReadWriteLength;
}
else
{
PtrContext->PtrMasterIrp->IoStatus.Information = 0;
}
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [io]", PtrContext );
ExFreePool( PtrContext );
}
//
// The master Irp will be automatically completed
// when all the associated IRPs are completed
// Returning STATUS_SUCCESS to continue postprocessing...
//
return STATUS_SUCCESS;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,211 @@
/*************************************************************************
*
* File: shutdown.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains code to handle the "shutdown notification" dispatch entry point.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_SHUTDOWN
#define DEBUG_LEVEL (DEBUG_TRACE_SHUTDOWN)
/*************************************************************************
*
* Function: Ext2Shutdown()
*
* Description:
* All disk-based FSDs can expect to receive this shutdown notification
* request whenever the system is about to be halted gracefully. If you
* design and implement a network redirector, you must register explicitly
* for shutdown notification by invoking the IoRegisterShutdownNotification()
* routine from your driver entry.
*
* Note that drivers that register to receive shutdown notification get
* invoked BEFORE disk-based FSDs are told about the shutdown notification.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: Irrelevant.
*
*************************************************************************/
NTSTATUS Ext2Shutdown(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{
NTSTATUS RC = STATUS_SUCCESS;
PtrExt2IrpContext PtrIrpContext = NULL;
BOOLEAN AreWeTopLevel = FALSE;
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Shutdown IRP received...", 0);
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
// set the top level context
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try
{
// get an IRP context structure and issue the request
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = Ext2CommonShutdown(PtrIrpContext, Irp);
}
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
{
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel)
{
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
}
/*************************************************************************
*
* Function: Ext2CommonShutdown()
*
* Description:
* The actual work is performed here. Basically, all we do here is
* internally invoke a flush on all mounted logical volumes. This, in
* tuen, will result in all open file streams being flushed to disk.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: Irrelevant
*
*************************************************************************/
NTSTATUS Ext2CommonShutdown(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp)
{
NTSTATUS RC = STATUS_SUCCESS;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
IO_STATUS_BLOCK LocalIoStatus;
try
{
// First, get a pointer to the current I/O stack location
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
// (a) Block all new "mount volume" requests by acquiring an appropriate
// global resource/lock.
// (b) Go through your linked list of mounted logical volumes and for
// each such volume, do the following:
// (i) acquire the volume resource exclusively
// (ii) invoke Ext2FlushLogicalVolume() (internally) to flush the
// open data streams belonging to the volume from the system
// cache
// (iii) Invoke the physical/virtual/logical target device object
// on which the volume is mounted and inform this device
// about the shutdown request (Use IoBuildSynchronousFsdRequest()
// to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you
// will then issue to the target device object).
// (iv) Wait for the completion of the shutdown processing by the target
// device object
// (v) Release the VCB resource you will have acquired in (i) above.
// Once you have processed all the mounted logical volumes, you can release
// all acquired global resources and leave (in peace :-)
/*////////////////////////////////////////////
//
// Update the Group...
//
if( PtrVCB->LogBlockSize )
{
// First block contains the descriptors...
VolumeByteOffset.QuadPart = LogicalBlockSize;
}
else
{
// Second block contains the descriptors...
VolumeByteOffset.QuadPart = LogicalBlockSize * 2;
}
NumberOfBytesToRead = sizeof( struct ext2_group_desc );
NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize );
if (!CcMapData( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
NumberOfBytesToRead,
TRUE,
&PtrBCB,
&PtrCacheBuffer ))
{
DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
}
else
{
//
// Saving up Often Used Group Descriptor Information in the VCB...
//
unsigned int DescIndex ;
DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
PtrGroupDescriptor = (PEXT2_GROUP_DESCRIPTOR )PtrCacheBuffer;
for( DescIndex = 0; DescIndex < PtrVCB->NoOfGroups; DescIndex++ )
{
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeTablesBlock
= PtrGroupDescriptor[ DescIndex ].bg_inode_table;
PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeBitmapBlock
= PtrGroupDescriptor[ DescIndex ].bg_inode_bitmap
;
PtrVCB->PtrGroupDescriptors[ DescIndex ].BlockBitmapBlock
= PtrGroupDescriptor[ DescIndex ].bg_block_bitmap
;
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeBlocksCount
= PtrGroupDescriptor[ DescIndex ].bg_free_blocks_count;
PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeInodesCount
= PtrGroupDescriptor[ DescIndex ].bg_free_inodes_count;
}
CcUnpinData( PtrBCB );
PtrBCB = NULL;
}
*/////////////////////////////////////////////
try_exit: NOTHING;
}
finally
{
// See the read/write examples for how to fill in this portion
} // end of "finally" processing
return(RC);
}

View file

@ -0,0 +1,339 @@
/*************************************************************************
*
* File: volinfo.c
*
* Module: Ext2 File System Driver (Kernel mode execution only)
*
* Description:
* Contains code to handle the various Volume Information related calls.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h"
// define the file specific bug-check id
#define EXT2_BUG_CHECK_ID EXT2_FILE_VOL_INFORMATION
#define DEBUG_LEVEL (DEBUG_TRACE_VOLINFO)
/*************************************************************************
*
* Function: Ext2QueryVolInfo()
*
* Description:
* The I/O Manager will invoke this routine to handle a
* Query Volume Info IRP
*
* Expected Interrupt Level (for execution) :
*
* ???
*
* Arguments:
*
* DeviceObject - Supplies the volume device object where the
* file exists
*
* Irp - Supplies the Irp being processed
*
*
* Return Value:
*
* NTSTATUS - The FSD status for the IRP
*
*************************************************************************/
NTSTATUS Ext2QueryVolInfo (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
// The Return Status
NTSTATUS Status = STATUS_SUCCESS;
// The IRP Stack Location
PIO_STACK_LOCATION IrpSp = NULL;
// Volume Control Block
PtrExt2VCB PtrVCB = NULL;
// The class of the query IRP
FS_INFORMATION_CLASS FsInformationClass;
// The System Buffer Pointer
PVOID Buffer = NULL;
// Parameter Length
ULONG Length = 0;
// Bytes copied...
ULONG BytesCopied = 0;
// Pointers to the Output Information...
PFILE_FS_VOLUME_INFORMATION PtrVolumeInformation = NULL;
PFILE_FS_SIZE_INFORMATION PtrSizeInformation = NULL;
PFILE_FS_ATTRIBUTE_INFORMATION PtrAttributeInformation = NULL;
PFILE_FS_DEVICE_INFORMATION PtrDeviceInformation = NULL;
PFILE_FS_FULL_SIZE_INFORMATION PtrFullSizeInformation = NULL;
// Now for the handler code...
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "QueryVolumeInformation IRP", 0);
FsRtlEnterFileSystem();
try
{
// Getting a pointer to the current I/O stack location
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ASSERT( IrpSp );
// Getting the VCB and Verifying it...
PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension );
ASSERT(PtrVCB);
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
// Getting the query parameters...
Length = IrpSp->Parameters.QueryVolume.Length;
FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
Buffer = Irp->AssociatedIrp.SystemBuffer;
// Now servicing the request depending on the type...
switch (FsInformationClass)
{
case FileFsVolumeInformation:
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsVolumeInformation", 0);
PtrVolumeInformation = Buffer;
PtrVolumeInformation->SupportsObjects = FALSE;
PtrVolumeInformation->VolumeCreationTime.QuadPart = 0;
RtlCopyMemory(
PtrVolumeInformation->VolumeLabel, // destination
PtrVCB->PtrVPB->VolumeLabel, // source
PtrVCB->PtrVPB->VolumeLabelLength );
PtrVolumeInformation->VolumeLabelLength = PtrVCB->PtrVPB->VolumeLabelLength;
PtrVolumeInformation->VolumeSerialNumber = PtrVCB->PtrVPB->SerialNumber;
BytesCopied = sizeof( FILE_FS_VOLUME_INFORMATION ) + PtrVolumeInformation->VolumeLabelLength - sizeof( WCHAR);
break;
case FileFsSizeInformation:
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsSizeInformation", 0);
PtrSizeInformation = Buffer;
PtrSizeInformation->BytesPerSector = DeviceObject->SectorSize;
PtrSizeInformation->AvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount;
PtrSizeInformation->SectorsPerAllocationUnit = ( EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize;
PtrSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount;
BytesCopied = sizeof( FILE_FS_SIZE_INFORMATION );
break;
case FileFsDeviceInformation:
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsDeviceInformation", 0);
PtrDeviceInformation = Buffer;
PtrDeviceInformation->DeviceType = FILE_DEVICE_DISK;
PtrDeviceInformation->Characteristics = FILE_DEVICE_IS_MOUNTED;
BytesCopied = sizeof( FILE_FS_DEVICE_INFORMATION );
break;
case FileFsAttributeInformation:
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsAttributeInformation", 0);
PtrAttributeInformation = Buffer;
RtlCopyMemory( PtrAttributeInformation->FileSystemName, L"EXT2", 10 );
PtrAttributeInformation->FileSystemNameLength = 8;
PtrAttributeInformation->MaximumComponentNameLength = 255;
PtrAttributeInformation->FileSystemAttributes =
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
BytesCopied = sizeof( FILE_FS_ATTRIBUTE_INFORMATION ) + 8;
break;
case FileFsFullSizeInformation:
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - FileFsFullSizeInformation", 0);
PtrFullSizeInformation = Buffer;
PtrFullSizeInformation->BytesPerSector = DeviceObject->SectorSize;
PtrFullSizeInformation->ActualAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount;
PtrFullSizeInformation->SectorsPerAllocationUnit = (EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize) / DeviceObject->SectorSize;
PtrFullSizeInformation->TotalAllocationUnits.QuadPart = PtrVCB->BlocksCount;
PtrFullSizeInformation->CallerAvailableAllocationUnits.QuadPart = PtrVCB->FreeBlocksCount - PtrVCB->ReservedBlocksCount;
BytesCopied = sizeof( FILE_FS_FULL_SIZE_INFORMATION );
break;
default:
Status = STATUS_INVALID_PARAMETER;
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0);
break;
}
if( IrpSp->Parameters.QueryVolume.Length < BytesCopied )
{
BytesCopied = IrpSp->Parameters.QueryVolume.Length;
Status = STATUS_BUFFER_OVERFLOW;
DebugTrace(DEBUG_TRACE_MISC, " === Buffer insufficient", 0);
}
try_exit: NOTHING;
}
finally
{
Irp->IoStatus.Information = BytesCopied;
Ext2CompleteRequest( Irp, Status );
}
FsRtlExitFileSystem();
//
// Now return to the caller
//
return Status;
}
NTSTATUS Ext2SetVolInfo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
// The Return Status
NTSTATUS Status = STATUS_SUCCESS;
// The IRP Stack Location
PIO_STACK_LOCATION IrpSp = NULL;
// Volume Control Block
PtrExt2VCB PtrVCB = NULL;
// The class of the query IRP
FS_INFORMATION_CLASS FsInformationClass;
// Pointers to the Output Information...
PFILE_FS_LABEL_INFORMATION PtrVolumeLabelInformation = NULL;
// Now for the handler code...
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Set Volume Information IRP", 0);
FsRtlEnterFileSystem();
try
{
// Getting a pointer to the current I/O stack location
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ASSERT( IrpSp );
// Getting the VCB and Verifying it...
PtrVCB = ( PtrExt2VCB )( DeviceObject->DeviceExtension );
AssertVCB(PtrVCB);
// Getting the query parameters...
// Length = IrpSp->Parameters.SetVolume.Length;
#ifdef _GNU_NTIFS_
FsInformationClass = ((PEXTENDED_IO_STACK_LOCATION)IrpSp)->Parameters.SetVolume.FsInformationClass;
#else
FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
#endif
// Now servicing the request depending on the type...
switch (FsInformationClass)
{
case FileFsLabelInformation:
PtrVolumeLabelInformation = Irp->AssociatedIrp.SystemBuffer;
if( PtrVolumeLabelInformation->VolumeLabelLength > MAXIMUM_VOLUME_LABEL_LENGTH || // This is the maximum that the
// VPB can take...
PtrVolumeLabelInformation->VolumeLabelLength > 32 ) // this is the maximum that Ext2 FS can support..
{
try_return( Status = STATUS_INVALID_VOLUME_LABEL );
}
PtrVCB->PtrVPB->VolumeLabelLength = (USHORT)PtrVolumeLabelInformation->VolumeLabelLength ;
RtlCopyMemory(
PtrVCB->PtrVPB->VolumeLabel, // destination
PtrVolumeLabelInformation->VolumeLabel, // source
PtrVolumeLabelInformation->VolumeLabelLength );
{
// Now update the volume's super block...
PEXT2_SUPER_BLOCK PtrSuperBlock = NULL;
PBCB PtrSuperBlockBCB = NULL;
LARGE_INTEGER VolumeByteOffset;
ULONG LogicalBlockSize = 0;
ULONG NumberOfBytesToRead = 0;
// Reading in the super block...
VolumeByteOffset.QuadPart = 1024;
LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
// THis shouldn't be more than a block in size...
NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize );
if( !CcPinRead( PtrVCB->PtrStreamFileObject,
&VolumeByteOffset,
NumberOfBytesToRead,
TRUE,
&PtrSuperBlockBCB,
(PVOID*)&PtrSuperBlock ) )
{
DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
try_return( Status = STATUS_INVALID_VOLUME_LABEL );
}
else
{
ULONG i;
for( i = 0; i < (PtrVolumeLabelInformation->VolumeLabelLength/2) ; i++ )
{
PtrSuperBlock->s_volume_name[i] =
(char) PtrVolumeLabelInformation->VolumeLabel[i] ;
if( PtrSuperBlock->s_volume_name[i] == 0 )
{
break;
}
}
if( i < 16 )
{
PtrSuperBlock->s_volume_name[i] = 0;
}
CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL );
// Not saving and flushing this information synchronously...
// This is not a critical information..
// Settling for lazy writing of this information
// Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject );
if( PtrSuperBlockBCB )
{
CcUnpinData( PtrSuperBlockBCB );
PtrSuperBlockBCB = NULL;
}
}
}
break;
default:
Status = STATUS_INVALID_PARAMETER;
DebugTrace(DEBUG_TRACE_MISC, "Query Volume - STATUS_INVALID_PARAMETER", 0);
break;
}
try_exit: NOTHING;
}
finally
{
Irp->IoStatus.Information = 0;
Ext2CompleteRequest( Irp, Status );
}
FsRtlExitFileSystem();
//
// Now return to the caller
//
return Status;
}

File diff suppressed because it is too large Load diff

View file

@ -1,202 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ext2/super.c
* PURPOSE: ext2 filesystem
* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <rosrtl/string.h>
//#define NDEBUG
#include <debug.h>
#include "ext2fs.h"
/* GLOBALS *****************************************************************/
static PDRIVER_OBJECT DriverObject;
/* FUNCTIONS ****************************************************************/
NTSTATUS STDCALL
Ext2Close(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
PEXT2_FCB Fcb;
DbgPrint("Ext2Close(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
Stack = IoGetCurrentIrpStackLocation(Irp);
FileObject = Stack->FileObject;
DeviceExtension = DeviceObject->DeviceExtension;
if (FileObject == DeviceExtension->FileObject)
{
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}
Fcb = (PEXT2_FCB)FileObject->FsContext;
if (Fcb != NULL)
{
if (Fcb->Bcb != NULL)
{
CcRosReleaseFileCache(FileObject, Fcb->Bcb);
}
ExFreePool(Fcb);
FileObject->FsContext = NULL;
}
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}
NTSTATUS Ext2Mount(PDEVICE_OBJECT DeviceToMount)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExt;
PVOID BlockBuffer;
struct ext2_super_block* superblock;
DPRINT("Ext2Mount(DeviceToMount %x)\n",DeviceToMount);
BlockBuffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
Ext2ReadSectors(DeviceToMount,
1,
1,
BlockBuffer);
superblock = BlockBuffer;
if (superblock->s_magic != EXT2_SUPER_MAGIC)
{
ExFreePool(BlockBuffer);
return(STATUS_UNRECOGNIZED_VOLUME);
}
DPRINT("Volume recognized\n");
DPRINT("s_inodes_count %d\n",superblock->s_inodes_count);
DPRINT("s_blocks_count %d\n",superblock->s_blocks_count);
IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FILE_DEVICE_FILE_SYSTEM,
0,
FALSE,
&DeviceObject);
DPRINT("DeviceObject %x\n",DeviceObject);
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
DeviceExt = (PVOID)DeviceObject->DeviceExtension;
DPRINT("DeviceExt %x\n",DeviceExt);
DeviceExt->StorageDevice = DeviceToMount;
DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
DPRINT("DeviceExt->StorageDevice %x\n", DeviceExt->StorageDevice);
DeviceExt->FileObject = IoCreateStreamFileObject(NULL, DeviceObject);
DeviceExt->superblock = superblock;
CcRosInitializeFileCache(DeviceExt->FileObject,
&DeviceExt->Bcb,
PAGE_SIZE * 3);
DPRINT("Ext2Mount() = STATUS_SUCCESS\n");
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
Ext2FileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PVPB vpb = Stack->Parameters.Mount.Vpb;
PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
NTSTATUS Status;
Status = Ext2Mount(DeviceToMount);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Status);
}
NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT _DriverObject,
PUNICODE_STRING RegistryPath)
/*
* FUNCTION: Called by the system to initalize the driver
* ARGUMENTS:
* DriverObject = object describing this driver
* RegistryPath = path to our configuration entries
* RETURNS: Success or failure
*/
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS ret;
UNICODE_STRING DeviceName = ROS_STRING_INITIALIZER(L"\\Device\\Ext2Fsd");
DbgPrint("Ext2 FSD 0.0.1\n");
DriverObject = _DriverObject;
ret = IoCreateDevice(DriverObject,
0,
&DeviceName,
FILE_DEVICE_FILE_SYSTEM,
0,
FALSE,
&DeviceObject);
if (ret!=STATUS_SUCCESS)
{
return(ret);
}
DeviceObject->Flags=0;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2Close;
DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2Create;
DriverObject->MajorFunction[IRP_MJ_READ] = Ext2Read;
DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2Write;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
Ext2FileSystemControl;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
Ext2DirectoryControl;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
Ext2QueryInformation;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2SetInformation;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2FlushBuffers;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2Shutdown;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2Cleanup;
DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = Ext2QuerySecurity;
DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = Ext2SetSecurity;
DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = Ext2QueryQuota;
DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = Ext2SetQuota;
DriverObject->DriverUnload = NULL;
IoRegisterFileSystem(DeviceObject);
return(STATUS_SUCCESS);
}