mirror of
https://github.com/reactos/reactos.git
synced 2024-08-18 17:37:02 +00:00
ext2 import by filip navara with minor editing by arty.
svn path=/branches/ext2/; revision=13009
This commit is contained in:
parent
b8ed66e011
commit
d31a52e423
|
@ -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);
|
||||
}
|
|
@ -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,
|
||||
§orNumber,
|
||||
&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,
|
||||
§orNumber,
|
||||
&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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
@ -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(;;);
|
||||
}
|
||||
|
68
reactos/drivers/fs/ext2/inc/errmsg.h
Normal file
68
reactos/drivers/fs/ext2/inc/errmsg.h
Normal 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)
|
||||
|
615
reactos/drivers/fs/ext2/inc/ext2_fs.h
Normal file
615
reactos/drivers/fs/ext2/inc/ext2_fs.h
Normal 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 */
|
250
reactos/drivers/fs/ext2/inc/ext2fsd.h
Normal file
250
reactos/drivers/fs/ext2/inc/ext2fsd.h
Normal 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_
|
115
reactos/drivers/fs/ext2/inc/ext2metadata.h
Normal file
115
reactos/drivers/fs/ext2/inc/ext2metadata.h
Normal 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
|
782
reactos/drivers/fs/ext2/inc/protos.h
Normal file
782
reactos/drivers/fs/ext2/inc/protos.h
Normal 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_
|
16
reactos/drivers/fs/ext2/inc/resource.h
Normal file
16
reactos/drivers/fs/ext2/inc/resource.h
Normal 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
|
674
reactos/drivers/fs/ext2/inc/struct.h
Normal file
674
reactos/drivers/fs/ext2/inc/struct.h
Normal 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?
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
9
reactos/drivers/fs/ext2/src/.cvsignore
Normal file
9
reactos/drivers/fs/ext2/src/.cvsignore
Normal file
|
@ -0,0 +1,9 @@
|
|||
base.tmp
|
||||
junk.tmp
|
||||
temp.exp
|
||||
vfatfs.coff
|
||||
*.d
|
||||
*.o
|
||||
*.sys
|
||||
*.sym
|
||||
*.map
|
215
reactos/drivers/fs/ext2/src/DiskIO.c
Normal file
215
reactos/drivers/fs/ext2/src/DiskIO.c
Normal 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;
|
||||
}
|
||||
|
||||
|
400
reactos/drivers/fs/ext2/src/cleanup.c
Normal file
400
reactos/drivers/fs/ext2/src/cleanup.c
Normal 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);
|
||||
}
|
459
reactos/drivers/fs/ext2/src/close.c
Normal file
459
reactos/drivers/fs/ext2/src/close.c
Normal 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);
|
||||
}
|
1681
reactos/drivers/fs/ext2/src/create.c
Normal file
1681
reactos/drivers/fs/ext2/src/create.c
Normal file
File diff suppressed because it is too large
Load diff
210
reactos/drivers/fs/ext2/src/devcntrl.c
Normal file
210
reactos/drivers/fs/ext2/src/devcntrl.c
Normal 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);
|
||||
}
|
937
reactos/drivers/fs/ext2/src/dircntrl.c
Normal file
937
reactos/drivers/fs/ext2/src/dircntrl.c
Normal 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);
|
||||
}
|
116
reactos/drivers/fs/ext2/src/ext2.rc
Normal file
116
reactos/drivers/fs/ext2/src/ext2.rc
Normal 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
|
||||
|
381
reactos/drivers/fs/ext2/src/ext2init.c
Normal file
381
reactos/drivers/fs/ext2/src/ext2init.c
Normal 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 );
|
||||
}
|
||||
}
|
||||
}
|
1757
reactos/drivers/fs/ext2/src/fastio.c
Normal file
1757
reactos/drivers/fs/ext2/src/fastio.c
Normal file
File diff suppressed because it is too large
Load diff
1125
reactos/drivers/fs/ext2/src/fileinfo.c
Normal file
1125
reactos/drivers/fs/ext2/src/fileinfo.c
Normal file
File diff suppressed because it is too large
Load diff
350
reactos/drivers/fs/ext2/src/flush.c
Normal file
350
reactos/drivers/fs/ext2/src/flush.c
Normal 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);
|
||||
}
|
944
reactos/drivers/fs/ext2/src/fsctrl.c
Normal file
944
reactos/drivers/fs/ext2/src/fsctrl.c
Normal 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;
|
||||
}
|
543
reactos/drivers/fs/ext2/src/io.c
Normal file
543
reactos/drivers/fs/ext2/src/io.c
Normal 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;
|
||||
}
|
2837
reactos/drivers/fs/ext2/src/metadata.c
Normal file
2837
reactos/drivers/fs/ext2/src/metadata.c
Normal file
File diff suppressed because it is too large
Load diff
2116
reactos/drivers/fs/ext2/src/misc.c
Normal file
2116
reactos/drivers/fs/ext2/src/misc.c
Normal file
File diff suppressed because it is too large
Load diff
1476
reactos/drivers/fs/ext2/src/read.c
Normal file
1476
reactos/drivers/fs/ext2/src/read.c
Normal file
File diff suppressed because it is too large
Load diff
211
reactos/drivers/fs/ext2/src/shutdown.c
Normal file
211
reactos/drivers/fs/ext2/src/shutdown.c
Normal 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);
|
||||
}
|
339
reactos/drivers/fs/ext2/src/volinfo.c
Normal file
339
reactos/drivers/fs/ext2/src/volinfo.c
Normal 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;
|
||||
}
|
1483
reactos/drivers/fs/ext2/src/write.c
Normal file
1483
reactos/drivers/fs/ext2/src/write.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in a new issue