2002-09-07 15:13:13 +00:00
|
|
|
/* $Id: fs.c,v 1.28 2002/09/07 15:12:52 chorns Exp $
|
2000-03-06 01:02:30 +00:00
|
|
|
*
|
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 *****************************************************************/
|
|
|
|
|
2002-09-07 15:13:13 +00:00
|
|
|
#include <ntoskrnl.h>
|
1998-08-28 23:24:25 +00:00
|
|
|
|
2002-09-07 15:13:13 +00:00
|
|
|
//#define NDEBUG
|
1998-08-28 23:24:25 +00:00
|
|
|
#include <internal/debug.h>
|
|
|
|
|
2002-04-19 10:10:29 +00:00
|
|
|
|
1998-08-28 23:24:25 +00:00
|
|
|
/* TYPES *******************************************************************/
|
|
|
|
|
2002-04-19 10:10:29 +00:00
|
|
|
typedef struct _FILE_SYSTEM_OBJECT
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
2001-12-05 12:14:13 +00:00
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
LIST_ENTRY Entry;
|
2002-04-19 10:10:29 +00:00
|
|
|
} FILE_SYSTEM_OBJECT, *PFILE_SYSTEM_OBJECT;
|
1998-08-28 23:24:25 +00:00
|
|
|
|
2002-04-19 10:10:29 +00:00
|
|
|
typedef struct _FS_CHANGE_NOTIFY_ENTRY
|
2001-12-05 12:14:13 +00:00
|
|
|
{
|
|
|
|
LIST_ENTRY FsChangeNotifyList;
|
|
|
|
PDRIVER_OBJECT DriverObject;
|
2002-09-07 15:13:13 +00:00
|
|
|
PDRIVER_FS_NOTIFICATION FSDNotificationProc;
|
2002-04-19 10:10:29 +00:00
|
|
|
} FS_CHANGE_NOTIFY_ENTRY, *PFS_CHANGE_NOTIFY_ENTRY;
|
|
|
|
|
2001-12-05 12:14:13 +00:00
|
|
|
|
1998-08-28 23:24:25 +00:00
|
|
|
/* 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
|
|
|
|
2001-12-05 12:14:13 +00:00
|
|
|
static KSPIN_LOCK FsChangeNotifyListLock;
|
|
|
|
static LIST_ENTRY FsChangeNotifyListHead;
|
|
|
|
|
|
|
|
#define TAG_FILE_SYSTEM TAG('F', 'S', 'Y', 'S')
|
|
|
|
#define TAG_FS_CHANGE_NOTIFY TAG('F', 'S', 'C', 'N')
|
|
|
|
|
|
|
|
|
2002-04-19 10:10:29 +00:00
|
|
|
static VOID
|
|
|
|
IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject,
|
|
|
|
BOOLEAN DriverActive);
|
|
|
|
|
2001-03-07 16:48:45 +00:00
|
|
|
|
1998-08-28 23:24:25 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2001-12-05 12:14:13 +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
|
|
|
)
|
|
|
|
{
|
2000-05-13 13:51:08 +00:00
|
|
|
NTSTATUS Status;
|
1999-01-16 02:11:45 +00:00
|
|
|
PFILE_OBJECT FileObject;
|
2000-05-13 13:51:08 +00:00
|
|
|
PDEVICE_OBJECT DeviceObject;
|
1999-01-16 02:11:45 +00:00
|
|
|
PIRP Irp;
|
2002-09-07 15:13:13 +00:00
|
|
|
PEXTENDED_IO_STACK_LOCATION StackPtr;
|
2002-04-27 19:22:55 +00:00
|
|
|
PKEVENT ptrEvent;
|
2001-11-02 22:22:33 +00:00
|
|
|
IO_STATUS_BLOCK IoSB;
|
2000-05-13 13:51:08 +00:00
|
|
|
|
2001-05-05 19:13:10 +00:00
|
|
|
DPRINT("NtFsControlFile(DeviceHandle %x EventHandle %x ApcRoutine %x "
|
|
|
|
"ApcContext %x IoStatusBlock %x IoControlCode %x "
|
2000-05-13 13:51:08 +00:00
|
|
|
"InputBuffer %x InputBufferSize %x OutputBuffer %x "
|
|
|
|
"OutputBufferSize %x)\n",
|
2001-05-05 19:13:10 +00:00
|
|
|
DeviceHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,
|
2000-05-13 13:51:08 +00:00
|
|
|
IoControlCode,InputBuffer,InputBufferSize,OutputBuffer,
|
|
|
|
OutputBufferSize);
|
|
|
|
|
|
|
|
Status = ObReferenceObjectByHandle(DeviceHandle,
|
|
|
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
|
|
|
NULL,
|
|
|
|
KernelMode,
|
|
|
|
(PVOID *) &FileObject,
|
|
|
|
NULL);
|
1999-01-16 02:11:45 +00:00
|
|
|
|
2000-05-13 13:51:08 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
2000-05-13 13:51:08 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
2002-04-27 19:22:55 +00:00
|
|
|
|
|
|
|
if (EventHandle != NULL)
|
|
|
|
{
|
|
|
|
Status = ObReferenceObjectByHandle (EventHandle,
|
|
|
|
SYNCHRONIZE,
|
|
|
|
ExEventObjectType,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)&ptrEvent,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KeResetEvent (&FileObject->Event);
|
|
|
|
ptrEvent = &FileObject->Event;
|
|
|
|
}
|
|
|
|
|
2000-05-13 13:51:08 +00:00
|
|
|
|
|
|
|
DeviceObject = FileObject->DeviceObject;
|
|
|
|
|
|
|
|
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
|
|
|
|
DeviceObject,
|
|
|
|
InputBuffer,
|
|
|
|
InputBufferSize,
|
|
|
|
OutputBuffer,
|
|
|
|
OutputBufferSize,
|
|
|
|
FALSE,
|
2002-04-27 19:22:55 +00:00
|
|
|
ptrEvent,
|
2001-11-02 22:22:33 +00:00
|
|
|
&IoSB);
|
2000-05-13 13:51:08 +00:00
|
|
|
|
|
|
|
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
|
|
|
|
Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
|
|
|
|
|
2002-09-07 15:13:13 +00:00
|
|
|
StackPtr = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
|
2001-07-15 15:36:31 +00:00
|
|
|
StackPtr->FileObject = FileObject;
|
2000-05-13 13:51:08 +00:00
|
|
|
StackPtr->DeviceObject = DeviceObject;
|
|
|
|
StackPtr->Parameters.FileSystemControl.InputBufferLength = InputBufferSize;
|
|
|
|
StackPtr->Parameters.FileSystemControl.OutputBufferLength =
|
|
|
|
OutputBufferSize;
|
|
|
|
StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
|
|
|
|
|
|
|
|
Status = IoCallDriver(DeviceObject,Irp);
|
2001-11-02 22:22:33 +00:00
|
|
|
if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
2002-04-27 19:22:55 +00:00
|
|
|
KeWaitForSingleObject(ptrEvent,Executive,KernelMode,FALSE,NULL);
|
2001-11-02 22:22:33 +00:00
|
|
|
Status = IoSB.Status;
|
|
|
|
}
|
|
|
|
if (IoStatusBlock)
|
|
|
|
{
|
|
|
|
*IoStatusBlock = IoSB;
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
return(Status);
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
IoInitFileSystemImplementation(VOID)
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
2001-12-05 12:14:13 +00:00
|
|
|
InitializeListHead(&FileSystemListHead);
|
|
|
|
KeInitializeSpinLock(&FileSystemListLock);
|
|
|
|
|
|
|
|
InitializeListHead(&FsChangeNotifyListHead);
|
|
|
|
KeInitializeSpinLock(&FsChangeNotifyListLock);
|
1998-08-28 23:24:25 +00:00
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
IoShutdownRegisteredFileSystems(VOID)
|
2000-10-05 19:15:50 +00:00
|
|
|
{
|
2000-12-29 13:43:13 +00:00
|
|
|
KIRQL oldlvl;
|
|
|
|
PLIST_ENTRY current_entry;
|
|
|
|
FILE_SYSTEM_OBJECT* current;
|
|
|
|
PIRP Irp;
|
|
|
|
KEVENT Event;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2000-10-05 19:15:50 +00:00
|
|
|
DPRINT("IoShutdownRegisteredFileSystems()\n");
|
2000-12-29 13:43:13 +00:00
|
|
|
|
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
KeInitializeEvent(&Event,NotificationEvent,FALSE);
|
|
|
|
|
|
|
|
current_entry = FileSystemListHead.Flink;
|
|
|
|
while (current_entry!=(&FileSystemListHead))
|
|
|
|
{
|
|
|
|
current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
|
|
|
|
|
|
|
|
/* send IRP_MJ_SHUTDOWN */
|
|
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
|
|
|
|
current->DeviceObject,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
&Event,
|
|
|
|
&IoStatusBlock);
|
|
|
|
|
|
|
|
Status = IoCallDriver(current->DeviceObject,Irp);
|
|
|
|
if (Status==STATUS_PENDING)
|
|
|
|
{
|
|
|
|
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entry = current_entry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
2000-10-05 19:15:50 +00:00
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2002-05-15 09:42:19 +00:00
|
|
|
static NTSTATUS
|
|
|
|
IopMountFileSystem(PDEVICE_OBJECT DeviceObject,
|
|
|
|
PDEVICE_OBJECT DeviceToMount)
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
2002-05-15 09:42:19 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
PIO_STACK_LOCATION StackPtr;
|
|
|
|
PKEVENT Event;
|
|
|
|
PIRP Irp;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("IoAskFileSystemToMountDevice(DeviceObject %x, DeviceToMount %x)\n",
|
|
|
|
DeviceObject,DeviceToMount);
|
|
|
|
|
|
|
|
assert_irql(PASSIVE_LEVEL);
|
|
|
|
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
|
|
|
|
if (Event == NULL)
|
|
|
|
{
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
KeInitializeEvent(Event, NotificationEvent, FALSE);
|
|
|
|
|
|
|
|
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
|
|
|
if (Irp==NULL)
|
|
|
|
{
|
|
|
|
ExFreePool(Event);
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->UserIosb = &IoStatusBlock;
|
|
|
|
DPRINT("Irp->UserIosb %x\n", Irp->UserIosb);
|
|
|
|
Irp->UserEvent = Event;
|
|
|
|
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
|
|
|
|
|
|
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
|
|
|
StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
|
|
|
|
StackPtr->MinorFunction = IRP_MN_MOUNT_VOLUME;
|
|
|
|
StackPtr->Flags = 0;
|
|
|
|
StackPtr->Control = 0;
|
|
|
|
StackPtr->DeviceObject = DeviceObject;
|
|
|
|
StackPtr->FileObject = NULL;
|
|
|
|
StackPtr->CompletionRoutine = NULL;
|
|
|
|
|
|
|
|
StackPtr->Parameters.MountVolume.Vpb = DeviceToMount->Vpb;
|
|
|
|
StackPtr->Parameters.MountVolume.DeviceObject = DeviceToMount;
|
|
|
|
|
|
|
|
Status = IoCallDriver(DeviceObject,Irp);
|
|
|
|
if (Status==STATUS_PENDING)
|
|
|
|
{
|
|
|
|
KeWaitForSingleObject(Event,Executive,KernelMode,FALSE,NULL);
|
|
|
|
Status = IoStatusBlock.Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExFreePool(Event);
|
|
|
|
|
|
|
|
return(Status);
|
1998-08-28 23:24:25 +00:00
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2002-05-15 09:42:19 +00:00
|
|
|
static NTSTATUS
|
|
|
|
IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
2002-05-15 09:42:19 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
PIO_STACK_LOCATION StackPtr;
|
|
|
|
PKEVENT Event;
|
|
|
|
PIRP Irp;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("IopLoadFileSystem(DeviceObject %x)\n", DeviceObject);
|
|
|
|
|
|
|
|
assert_irql(PASSIVE_LEVEL);
|
|
|
|
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
|
|
|
|
if (Event == NULL)
|
|
|
|
{
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
KeInitializeEvent(Event, NotificationEvent, FALSE);
|
|
|
|
|
|
|
|
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
|
|
|
if (Irp==NULL)
|
|
|
|
{
|
|
|
|
ExFreePool(Event);
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->UserIosb = &IoStatusBlock;
|
|
|
|
DPRINT("Irp->UserIosb %x\n", Irp->UserIosb);
|
|
|
|
Irp->UserEvent = Event;
|
|
|
|
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
|
|
|
|
|
|
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
|
|
|
StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
|
|
|
|
StackPtr->MinorFunction = IRP_MN_LOAD_FILE_SYSTEM;
|
|
|
|
StackPtr->Flags = 0;
|
|
|
|
StackPtr->Control = 0;
|
|
|
|
StackPtr->DeviceObject = DeviceObject;
|
|
|
|
StackPtr->FileObject = NULL;
|
|
|
|
StackPtr->CompletionRoutine = NULL;
|
|
|
|
|
|
|
|
Status = IoCallDriver(DeviceObject,Irp);
|
|
|
|
if (Status==STATUS_PENDING)
|
|
|
|
{
|
|
|
|
KeWaitForSingleObject(Event,Executive,KernelMode,FALSE,NULL);
|
|
|
|
Status = IoStatusBlock.Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExFreePool(Event);
|
|
|
|
|
|
|
|
return(Status);
|
1998-08-28 23:24:25 +00:00
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
NTSTATUS
|
2002-05-15 09:42:19 +00:00
|
|
|
IoMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN BOOLEAN AllowRawMount)
|
1998-08-28 23:24:25 +00:00
|
|
|
/*
|
2002-05-15 09:42:19 +00:00
|
|
|
* FUNCTION: Mounts a logical volume
|
1998-08-28 23:24:25 +00:00
|
|
|
* ARGUMENTS:
|
2002-05-15 09:42:19 +00:00
|
|
|
* DeviceObject = Device to mount
|
1998-08-28 23:24:25 +00:00
|
|
|
* RETURNS: Status
|
|
|
|
*/
|
|
|
|
{
|
2002-04-19 10:10:29 +00:00
|
|
|
KIRQL oldlvl;
|
|
|
|
PLIST_ENTRY current_entry;
|
|
|
|
FILE_SYSTEM_OBJECT* current;
|
|
|
|
NTSTATUS Status;
|
|
|
|
DEVICE_TYPE MatchingDeviceType;
|
|
|
|
|
|
|
|
assert_irql(PASSIVE_LEVEL);
|
|
|
|
|
2002-05-15 09:42:19 +00:00
|
|
|
DPRINT("IoMountVolume(DeviceObject %x AllowRawMount %x)\n",
|
|
|
|
DeviceObject, AllowRawMount);
|
2002-04-19 10:10:29 +00:00
|
|
|
|
|
|
|
switch (DeviceObject->DeviceType)
|
|
|
|
{
|
|
|
|
case FILE_DEVICE_DISK:
|
|
|
|
case FILE_DEVICE_VIRTUAL_DISK: /* ?? */
|
|
|
|
MatchingDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FILE_DEVICE_CD_ROM:
|
|
|
|
MatchingDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FILE_DEVICE_NETWORK:
|
|
|
|
MatchingDeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FILE_DEVICE_TAPE:
|
|
|
|
MatchingDeviceType = FILE_DEVICE_TAPE_FILE_SYSTEM;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
CPRINT("No matching file system type found for device type: %x\n",
|
|
|
|
DeviceObject->DeviceType);
|
|
|
|
return(STATUS_UNRECOGNIZED_VOLUME);
|
|
|
|
}
|
|
|
|
|
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
current_entry = FileSystemListHead.Flink;
|
|
|
|
while (current_entry!=(&FileSystemListHead))
|
|
|
|
{
|
|
|
|
current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
|
|
|
|
if (current->DeviceObject->DeviceType != MatchingDeviceType)
|
|
|
|
{
|
|
|
|
current_entry = current_entry->Flink;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
2002-05-15 09:42:19 +00:00
|
|
|
Status = IopMountFileSystem(current->DeviceObject,
|
|
|
|
DeviceObject);
|
2002-04-19 10:10:29 +00:00
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
switch (Status)
|
|
|
|
{
|
|
|
|
case STATUS_FS_DRIVER_REQUIRED:
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
2002-05-15 09:42:19 +00:00
|
|
|
Status = IopLoadFileSystem(current->DeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
2002-04-19 10:10:29 +00:00
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
current_entry = FileSystemListHead.Flink;
|
2002-05-15 09:42:19 +00:00
|
|
|
continue;
|
2002-04-19 10:10:29 +00:00
|
|
|
|
|
|
|
case STATUS_SUCCESS:
|
|
|
|
DeviceObject->Vpb->Flags = DeviceObject->Vpb->Flags |
|
|
|
|
VPB_MOUNTED;
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
|
|
|
|
case STATUS_UNRECOGNIZED_VOLUME:
|
|
|
|
default:
|
|
|
|
current_entry = current_entry->Flink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
|
|
|
|
return(STATUS_UNRECOGNIZED_VOLUME);
|
1998-08-28 23:24:25 +00:00
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* IoVerifyVolume
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
2002-05-15 09:42:19 +00:00
|
|
|
* Verify the file system type and volume information or mount
|
2002-04-10 09:58:45 +00:00
|
|
|
* a file system.
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* DeviceObject
|
|
|
|
* Device to verify or mount
|
|
|
|
*
|
|
|
|
* AllowRawMount
|
|
|
|
* ...
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* Status
|
|
|
|
*/
|
|
|
|
NTSTATUS STDCALL
|
|
|
|
IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN BOOLEAN AllowRawMount)
|
|
|
|
{
|
2002-04-19 10:10:29 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
2002-05-15 09:42:19 +00:00
|
|
|
PIO_STACK_LOCATION StackPtr;
|
2002-04-19 10:10:29 +00:00
|
|
|
PKEVENT Event;
|
2002-04-10 09:58:45 +00:00
|
|
|
PIRP Irp;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2002-05-15 09:42:19 +00:00
|
|
|
DPRINT("IoVerifyVolume(DeviceObject %x AllowRawMount %x)\n",
|
|
|
|
DeviceObject, AllowRawMount);
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
KeWaitForSingleObject(&DeviceObject->DeviceLock,
|
|
|
|
Executive,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
|
2002-05-24 07:52:09 +00:00
|
|
|
DeviceObject->Flags &= ~DO_VERIFY_VOLUME;
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
if (DeviceObject->Vpb->Flags & VPB_MOUNTED)
|
|
|
|
{
|
2002-04-19 10:10:29 +00:00
|
|
|
/* Issue verify request to the FSD */
|
|
|
|
Event = ExAllocatePool(NonPagedPool,
|
|
|
|
sizeof(KEVENT));
|
|
|
|
if (Event == NULL)
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
|
|
|
|
KeInitializeEvent(Event,
|
|
|
|
NotificationEvent,
|
|
|
|
FALSE);
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2002-05-15 09:42:19 +00:00
|
|
|
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
|
|
|
if (Irp==NULL)
|
|
|
|
{
|
|
|
|
ExFreePool(Event);
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->UserIosb = &IoStatusBlock;
|
|
|
|
Irp->UserEvent = Event;
|
|
|
|
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
|
|
|
|
|
|
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
|
|
|
StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
|
|
|
|
StackPtr->MinorFunction = IRP_MN_VERIFY_VOLUME;
|
|
|
|
StackPtr->Flags = 0;
|
|
|
|
StackPtr->Control = 0;
|
|
|
|
StackPtr->DeviceObject = DeviceObject;
|
|
|
|
StackPtr->FileObject = NULL;
|
|
|
|
StackPtr->CompletionRoutine = NULL;
|
|
|
|
|
|
|
|
StackPtr->Parameters.VerifyVolume.Vpb = DeviceObject->Vpb;
|
|
|
|
StackPtr->Parameters.VerifyVolume.DeviceObject = DeviceObject;
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2002-04-19 10:10:29 +00:00
|
|
|
Status = IoCallDriver(DeviceObject,
|
|
|
|
Irp);
|
|
|
|
if (Status==STATUS_PENDING)
|
|
|
|
{
|
|
|
|
KeWaitForSingleObject(Event,Executive,KernelMode,FALSE,NULL);
|
|
|
|
Status = IoStatusBlock.Status;
|
|
|
|
}
|
|
|
|
ExFreePool(Event);
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KeSetEvent(&DeviceObject->DeviceLock,
|
|
|
|
IO_NO_INCREMENT,
|
|
|
|
FALSE);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Status == STATUS_WRONG_VOLUME)
|
|
|
|
{
|
2002-05-24 07:52:09 +00:00
|
|
|
/* Clean existing VPB. This unmounts the filesystem (in an ugly way). */
|
|
|
|
DPRINT("Wrong volume!\n");
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2002-05-24 07:52:09 +00:00
|
|
|
DeviceObject->Vpb->DeviceObject = NULL;
|
|
|
|
DeviceObject->Vpb->Flags &= ~VPB_MOUNTED;
|
2002-04-10 09:58:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Start mount sequence */
|
2002-05-15 09:42:19 +00:00
|
|
|
Status = IoMountVolume(DeviceObject,
|
|
|
|
AllowRawMount);
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
KeSetEvent(&DeviceObject->DeviceLock,
|
|
|
|
IO_NO_INCREMENT,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-19 10:10:29 +00:00
|
|
|
PDEVICE_OBJECT STDCALL
|
|
|
|
IoGetDeviceToVerify(IN PETHREAD Thread)
|
|
|
|
/*
|
|
|
|
* FUNCTION: Returns a pointer to the device, representing a removable-media
|
|
|
|
* device, that is the target of the given thread's I/O request
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
return(Thread->DeviceToVerify);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-05 12:14:13 +00:00
|
|
|
VOID STDCALL
|
2002-04-19 10:10:29 +00:00
|
|
|
IoSetDeviceToVerify(IN PETHREAD Thread,
|
|
|
|
IN PDEVICE_OBJECT DeviceObject)
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
2002-04-19 10:10:29 +00:00
|
|
|
Thread->DeviceToVerify = DeviceObject;
|
1998-08-28 23:24:25 +00:00
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2001-12-05 12:14:13 +00:00
|
|
|
VOID STDCALL
|
2002-04-19 10:10:29 +00:00
|
|
|
IoSetHardErrorOrVerifyDevice(IN PIRP Irp,
|
|
|
|
IN PDEVICE_OBJECT DeviceObject)
|
1998-08-28 23:24:25 +00:00
|
|
|
{
|
2002-04-19 10:10:29 +00:00
|
|
|
Irp->Tail.Overlay.Thread->DeviceToVerify = DeviceObject;
|
|
|
|
}
|
1998-09-13 15:55:55 +00:00
|
|
|
|
2002-04-19 10:10:29 +00:00
|
|
|
|
|
|
|
VOID STDCALL
|
|
|
|
IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
{
|
|
|
|
PFILE_SYSTEM_OBJECT Fs;
|
|
|
|
|
|
|
|
DPRINT("IoRegisterFileSystem(DeviceObject %x)\n",DeviceObject);
|
|
|
|
|
|
|
|
Fs = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
sizeof(FILE_SYSTEM_OBJECT),
|
|
|
|
TAG_FILE_SYSTEM);
|
|
|
|
assert(Fs!=NULL);
|
|
|
|
|
|
|
|
Fs->DeviceObject = DeviceObject;
|
|
|
|
ExInterlockedInsertTailList(&FileSystemListHead,
|
|
|
|
&Fs->Entry,
|
|
|
|
&FileSystemListLock);
|
|
|
|
IopNotifyFileSystemChange(DeviceObject,
|
|
|
|
TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID STDCALL
|
|
|
|
IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
{
|
|
|
|
KIRQL oldlvl;
|
|
|
|
PLIST_ENTRY current_entry;
|
|
|
|
PFILE_SYSTEM_OBJECT current;
|
|
|
|
|
|
|
|
DPRINT("IoUnregisterFileSystem(DeviceObject %x)\n",DeviceObject);
|
|
|
|
|
|
|
|
KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
|
|
|
|
current_entry = FileSystemListHead.Flink;
|
|
|
|
while (current_entry!=(&FileSystemListHead))
|
|
|
|
{
|
|
|
|
current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
|
|
|
|
if (current->DeviceObject == DeviceObject)
|
|
|
|
{
|
|
|
|
RemoveEntryList(current_entry);
|
|
|
|
ExFreePool(current);
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
|
|
|
IopNotifyFileSystemChange(DeviceObject, FALSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
current_entry = current_entry->Flink;
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&FileSystemListLock,oldlvl);
|
1998-08-28 23:24:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-03-05 19:17:43 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* IoGetBaseFileSystemDeviceObject@4
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* Get the DEVICE_OBJECT associated to
|
|
|
|
* a FILE_OBJECT.
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* FileObject
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
*
|
|
|
|
* NOTE
|
|
|
|
* From Bo Branten's ntifs.h v13.
|
|
|
|
*/
|
2001-12-05 12:14:13 +00:00
|
|
|
PDEVICE_OBJECT STDCALL
|
|
|
|
IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject)
|
2000-03-05 19:17:43 +00:00
|
|
|
{
|
|
|
|
PDEVICE_OBJECT DeviceObject = NULL;
|
|
|
|
PVPB Vpb = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the FILE_OBJECT's VPB is defined,
|
|
|
|
* get the device from it.
|
|
|
|
*/
|
|
|
|
if (NULL != (Vpb = FileObject->Vpb))
|
|
|
|
{
|
|
|
|
if (NULL != (DeviceObject = Vpb->DeviceObject))
|
|
|
|
{
|
|
|
|
/* Vpb->DeviceObject DEFINED! */
|
|
|
|
return DeviceObject;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If that failed, try the VPB
|
|
|
|
* in the FILE_OBJECT's DeviceObject.
|
|
|
|
*/
|
|
|
|
DeviceObject = FileObject->DeviceObject;
|
|
|
|
if (NULL == (Vpb = DeviceObject->Vpb))
|
|
|
|
{
|
|
|
|
/* DeviceObject->Vpb UNDEFINED! */
|
|
|
|
return DeviceObject;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If that pointer to the VPB is again
|
|
|
|
* undefined, return directly the
|
|
|
|
* device object from the FILE_OBJECT.
|
|
|
|
*/
|
|
|
|
return (
|
|
|
|
(NULL == Vpb->DeviceObject)
|
|
|
|
? DeviceObject
|
|
|
|
: Vpb->DeviceObject
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-05 12:14:13 +00:00
|
|
|
static VOID
|
|
|
|
IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject,
|
|
|
|
BOOLEAN DriverActive)
|
2000-03-26 19:38:32 +00:00
|
|
|
{
|
2001-12-05 12:14:13 +00:00
|
|
|
PFS_CHANGE_NOTIFY_ENTRY ChangeEntry;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
KIRQL oldlvl;
|
|
|
|
|
|
|
|
KeAcquireSpinLock(&FsChangeNotifyListLock,&oldlvl);
|
|
|
|
Entry = FsChangeNotifyListHead.Flink;
|
|
|
|
while (Entry != &FsChangeNotifyListHead)
|
|
|
|
{
|
|
|
|
ChangeEntry = CONTAINING_RECORD(Entry, FS_CHANGE_NOTIFY_ENTRY, FsChangeNotifyList);
|
|
|
|
|
|
|
|
(ChangeEntry->FSDNotificationProc)(DeviceObject, DriverActive);
|
|
|
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock(&FsChangeNotifyListLock,oldlvl);
|
2000-03-26 19:38:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-05 12:14:13 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
|
2002-09-07 15:13:13 +00:00
|
|
|
IN PDRIVER_FS_NOTIFICATION FSDNotificationProc)
|
2000-03-26 19:38:32 +00:00
|
|
|
{
|
2001-12-05 12:14:13 +00:00
|
|
|
PFS_CHANGE_NOTIFY_ENTRY Entry;
|
|
|
|
|
|
|
|
Entry = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
sizeof(FS_CHANGE_NOTIFY_ENTRY),
|
|
|
|
TAG_FS_CHANGE_NOTIFY);
|
|
|
|
if (Entry == NULL)
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
|
|
|
|
Entry->DriverObject = DriverObject;
|
|
|
|
Entry->FSDNotificationProc = FSDNotificationProc;
|
|
|
|
|
|
|
|
ExInterlockedInsertHeadList(&FsChangeNotifyListHead,
|
|
|
|
&Entry->FsChangeNotifyList,
|
|
|
|
&FsChangeNotifyListLock);
|
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
2000-03-26 19:38:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-09-07 15:13:13 +00:00
|
|
|
NTSTATUS STDCALL
|
2001-12-05 12:14:13 +00:00
|
|
|
IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
|
2002-09-07 15:13:13 +00:00
|
|
|
IN PDRIVER_FS_NOTIFICATION FSDNotificationProc)
|
2001-12-05 12:14:13 +00:00
|
|
|
{
|
|
|
|
PFS_CHANGE_NOTIFY_ENTRY ChangeEntry;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
KIRQL oldlvl;
|
|
|
|
|
|
|
|
Entry = FsChangeNotifyListHead.Flink;
|
|
|
|
while (Entry != &FsChangeNotifyListHead)
|
|
|
|
{
|
|
|
|
ChangeEntry = CONTAINING_RECORD(Entry, FS_CHANGE_NOTIFY_ENTRY, FsChangeNotifyList);
|
|
|
|
if (ChangeEntry->DriverObject == DriverObject &&
|
|
|
|
ChangeEntry->FSDNotificationProc == FSDNotificationProc)
|
|
|
|
{
|
|
|
|
KeAcquireSpinLock(&FsChangeNotifyListLock,&oldlvl);
|
|
|
|
RemoveEntryList(Entry);
|
|
|
|
KeReleaseSpinLock(&FsChangeNotifyListLock,oldlvl);
|
|
|
|
|
|
|
|
ExFreePool(Entry);
|
2002-09-07 15:13:13 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-12-05 12:14:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
2002-09-07 15:13:13 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-12-05 12:14:13 +00:00
|
|
|
}
|
|
|
|
|
2000-03-05 19:17:43 +00:00
|
|
|
/* EOF */
|