1998-08-28 23:24:25 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: ntoskrnl/io/fs.c
|
|
|
|
* PURPOSE: Filesystem functions
|
|
|
|
* PROGRAMMER: David Welch (welch@mcmail.com)
|
|
|
|
* UPDATE HISTORY:
|
|
|
|
* Created 22/05/98
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include <ddk/ntddk.h>
|
1998-09-13 15:55:55 +00:00
|
|
|
#include <internal/io.h>
|
1998-08-28 23:24:25 +00:00
|
|
|
|
1999-01-16 21:03:00 +00:00
|
|
|
#define NDEBUG
|
1998-08-28 23:24:25 +00:00
|
|
|
#include <internal/debug.h>
|
|
|
|
|
|
|
|
/* TYPES *******************************************************************/
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
LIST_ENTRY Entry;
|
|
|
|
} FILE_SYSTEM_OBJECT;
|
|
|
|
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
1999-12-22 14:48:30 +00:00
|
|
|
static KSPIN_LOCK FileSystemListLock;
|
|
|
|
static LIST_ENTRY FileSystemListHead;
|
1998-08-28 23:24:25 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
1998-10-05 04:01:30 +00:00
|
|
|
NTSTATUS
|
|
|
|
STDCALL
|
1999-06-18 22:11:21 +00:00
|
|
|
NtFsControlFile (
|
|
|
|
IN HANDLE DeviceHandle,
|
|
|
|
IN HANDLE EventHandle OPTIONAL,
|
|
|
|
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
|
|
|
IN PVOID ApcContext OPTIONAL,
|
|
|
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
|
|
IN ULONG IoControlCode,
|
|
|
|
IN PVOID InputBuffer,
|
|
|
|
IN ULONG InputBufferSize,
|
|
|
|
OUT PVOID OutputBuffer,
|
|
|
|
IN ULONG OutputBufferSize
|
1998-10-05 04:01:30 +00:00
|
|
|
)
|
|
|
|
{
|
1999-01-16 02:11:45 +00:00
|
|
|
NTSTATUS Status = -1;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
PIRP Irp;
|
|
|
|
PIO_STACK_LOCATION StackPtr;
|
|
|
|
KEVENT Event;
|
|
|
|
|
1999-04-18 08:56:23 +00:00
|
|
|
if (InputBufferSize > 0)
|
|
|
|
{
|
1999-01-16 02:11:45 +00:00
|
|
|
Status = ObReferenceObjectByHandle(DeviceHandle,
|
1999-04-18 08:56:23 +00:00
|
|
|
FILE_WRITE_DATA|FILE_READ_DATA,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
(PVOID *) &FileObject,
|
|
|
|
NULL);
|
1999-01-16 02:11:45 +00:00
|
|
|
if (Status != STATUS_SUCCESS)
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
1999-01-16 02:11:45 +00:00
|
|
|
return(Status);
|
1999-04-18 08:56:23 +00:00
|
|
|
}
|
|
|
|
|
1999-01-16 02:11:45 +00:00
|
|
|
KeInitializeEvent(&Event,NotificationEvent,FALSE);
|
|
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
|
1999-04-18 08:56:23 +00:00
|
|
|
FileObject->DeviceObject,
|
|
|
|
InputBuffer,
|
|
|
|
InputBufferSize,
|
|
|
|
0,
|
|
|
|
&Event,
|
|
|
|
IoStatusBlock);
|
|
|
|
if (Irp == NULL)
|
|
|
|
{
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
1999-04-18 08:56:23 +00:00
|
|
|
if (StackPtr == NULL)
|
|
|
|
{
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
|
|
|
|
StackPtr->FileObject = FileObject;
|
|
|
|
StackPtr->Parameters.Write.Length = InputBufferSize;
|
|
|
|
DPRINT("FileObject->DeviceObject %x\n",FileObject->DeviceObject);
|
|
|
|
Status = IoCallDriver(FileObject->DeviceObject,Irp);
|
|
|
|
if (Status==STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
|
|
|
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
|
|
|
|
}
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(Irp->IoStatus.Status);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
1999-04-18 08:56:23 +00:00
|
|
|
if (OutputBufferSize > 0)
|
|
|
|
{
|
1999-01-16 02:11:45 +00:00
|
|
|
CHECKPOINT;
|
|
|
|
Status = ObReferenceObjectByHandle(DeviceHandle,
|
1999-04-18 08:56:23 +00:00
|
|
|
FILE_WRITE_DATA|FILE_READ_DATA,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
(PVOID *) &FileObject,
|
|
|
|
NULL);
|
1999-01-16 02:11:45 +00:00
|
|
|
if (Status != STATUS_SUCCESS)
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
CHECKPOINT;
|
|
|
|
KeInitializeEvent(&Event,NotificationEvent,FALSE);
|
|
|
|
CHECKPOINT;
|
|
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
|
1999-04-18 08:56:23 +00:00
|
|
|
FileObject->DeviceObject,
|
|
|
|
OutputBuffer,
|
|
|
|
OutputBufferSize,
|
|
|
|
0,
|
|
|
|
&Event,
|
|
|
|
IoStatusBlock);
|
|
|
|
if (Irp == NULL)
|
|
|
|
{
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
1999-04-18 08:56:23 +00:00
|
|
|
if (StackPtr == NULL)
|
|
|
|
{
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
|
|
|
|
StackPtr->FileObject = FileObject;
|
|
|
|
StackPtr->Parameters.Read.Length = OutputBufferSize;
|
|
|
|
DPRINT("FileObject->DeviceObject %x\n",FileObject->DeviceObject);
|
|
|
|
Status = IoCallDriver(FileObject->DeviceObject,Irp);
|
|
|
|
if (Status==STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
|
|
|
|
{
|
1999-04-18 08:56:23 +00:00
|
|
|
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
1999-04-18 08:56:23 +00:00
|
|
|
return(Irp->IoStatus.Status);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
return(Status);
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 23:24:25 +00:00
|
|
|
VOID IoInitFileSystemImplementation(VOID)
|
|
|
|
{
|
|
|
|
InitializeListHead(&FileSystemListHead);
|
|
|
|
KeInitializeSpinLock(&FileSystemListLock);
|
|
|
|
}
|
|
|
|
|
1998-09-13 15:55:55 +00:00
|
|
|
NTSTATUS IoAskFileSystemToMountDevice(PDEVICE_OBJECT DeviceObject,
|
|
|
|
PDEVICE_OBJECT DeviceToMount)
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
1998-09-13 15:55:55 +00:00
|
|
|
PIRP Irp;
|
|
|
|
KEVENT Event;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("IoAskFileSystemToMountDevice(DeviceObject %x, DeviceToMount %x)\n",
|
|
|
|
DeviceObject,DeviceToMount);
|
|
|
|
|
1999-05-29 00:15:17 +00:00
|
|
|
assert_irql(PASSIVE_LEVEL);
|
|
|
|
|
1998-09-13 15:55:55 +00:00
|
|
|
KeInitializeEvent(&Event,NotificationEvent,FALSE);
|
|
|
|
Irp = IoBuildFilesystemControlRequest(IRP_MN_MOUNT_VOLUME,
|
|
|
|
DeviceObject,
|
|
|
|
&Event,
|
|
|
|
&IoStatusBlock,
|
|
|
|
DeviceToMount);
|
|
|
|
Status = IoCallDriver(DeviceObject,Irp);
|
|
|
|
if (Status==STATUS_PENDING)
|
|
|
|
{
|
|
|
|
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
|
|
|
|
Status = IoStatusBlock.Status;
|
|
|
|
}
|
|
|
|
return(Status);
|
1998-08-28 23:24:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS IoAskFileSystemToLoad(PDEVICE_OBJECT DeviceObject)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS IoTryToMountStorageDevice(PDEVICE_OBJECT DeviceObject)
|
|
|
|
/*
|
|
|
|
* FUNCTION: Trys to mount a storage device
|
|
|
|
* ARGUMENTS:
|
|
|
|
* DeviceObject = Device to try and mount
|
|
|
|
* RETURNS: Status
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
KIRQL oldlvl;
|
|
|
|
PLIST_ENTRY current_entry;
|
|
|
|
FILE_SYSTEM_OBJECT* current;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
1999-05-29 00:15:17 +00:00
|
|
|
assert_irql(PASSIVE_LEVEL);
|
|
|
|
|
1998-09-13 15:55:55 +00:00
|
|
|
DPRINT("IoTryToMountStorageDevice(DeviceObject %x)\n",DeviceObject);
|
|
|
|
|
1998-08-28 23:24:25 +00:00
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
current_entry = FileSystemListHead.Flink;
|
1998-09-13 15:55:55 +00:00
|
|
|
while (current_entry!=(&FileSystemListHead))
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
|
|
|
current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
|
1999-05-29 00:15:17 +00:00
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
1998-09-13 15:55:55 +00:00
|
|
|
Status = IoAskFileSystemToMountDevice(current->DeviceObject,
|
|
|
|
DeviceObject);
|
1999-05-29 00:15:17 +00:00
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
1998-08-28 23:24:25 +00:00
|
|
|
switch (Status)
|
|
|
|
{
|
|
|
|
case STATUS_FS_DRIVER_REQUIRED:
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
(void)IoAskFileSystemToLoad(DeviceObject);
|
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
current_entry = FileSystemListHead.Flink;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_SUCCESS:
|
1998-12-19 18:56:57 +00:00
|
|
|
DeviceObject->Vpb->Flags = DeviceObject->Vpb->Flags |
|
|
|
|
VPB_MOUNTED;
|
1998-08-28 23:24:25 +00:00
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
|
|
|
|
case STATUS_UNRECOGNIZED_VOLUME:
|
|
|
|
default:
|
|
|
|
current_entry = current_entry->Flink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
return(STATUS_UNRECOGNIZED_VOLUME);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
|
|
|
|
{
|
|
|
|
FILE_SYSTEM_OBJECT* fs;
|
|
|
|
|
1998-09-13 15:55:55 +00:00
|
|
|
DPRINT("IoRegisterFileSystem(DeviceObject %x)\n",DeviceObject);
|
|
|
|
|
1998-08-28 23:24:25 +00:00
|
|
|
fs=ExAllocatePool(NonPagedPool,sizeof(FILE_SYSTEM_OBJECT));
|
|
|
|
assert(fs!=NULL);
|
|
|
|
|
|
|
|
fs->DeviceObject = DeviceObject;
|
|
|
|
ExInterlockedInsertTailList(&FileSystemListHead,&fs->Entry,
|
|
|
|
&FileSystemListLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
|
|
|
|
{
|
|
|
|
KIRQL oldlvl;
|
|
|
|
PLIST_ENTRY current_entry;
|
|
|
|
FILE_SYSTEM_OBJECT* current;
|
1998-09-13 15:55:55 +00:00
|
|
|
|
|
|
|
DPRINT("IoUnregisterFileSystem(DeviceObject %x)\n",DeviceObject);
|
1998-08-28 23:24:25 +00:00
|
|
|
|
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
current_entry = FileSystemListHead.Flink;
|
1998-09-13 15:55:55 +00:00
|
|
|
while (current_entry!=(&FileSystemListHead))
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
|
|
|
current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
|
|
|
|
if (current->DeviceObject == DeviceObject)
|
|
|
|
{
|
1998-09-05 17:34:23 +00:00
|
|
|
RemoveEntryList(current_entry);
|
1998-10-05 04:01:30 +00:00
|
|
|
ExFreePool(current);
|
1998-08-28 23:24:25 +00:00
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
current_entry = current_entry->Flink;
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
}
|
|
|
|
|
|
|
|
|