-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/vpb.c
* PURPOSE: Volume Parameter Block managment
- * PROGRAMMER: David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- * Created 22/05/98
+ *
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-#include <internal/string.h>
-#include <internal/ob.h>
-
+#include <ntoskrnl.h>
+#define NDEBUG
#include <internal/debug.h>
+/* GLOBALS *******************************************************************/
+
+static KSPIN_LOCK IoVpbLock;
+
/* FUNCTIONS *****************************************************************/
-NTSTATUS IoAttachVpb(PDEVICE_OBJECT DeviceObject)
+VOID INIT_FUNCTION
+IoInitVpbImplementation(VOID)
{
- PVPB Vpb;
-
- Vpb = ExAllocatePool(NonPagedPool,sizeof(VPB));
- if (Vpb==NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
-
- Vpb->Type = 0;
- Vpb->Size = sizeof(VPB) / sizeof(DWORD);
- Vpb->Flags = 0;
- Vpb->VolumeLabelLength = 0;
- Vpb->DeviceObject = NULL;
- Vpb->RealDevice = DeviceObject;
- Vpb->SerialNumber = 0;
- Vpb->ReferenceCount = 0;
- RtlZeroMemory(Vpb->VolumeLabel,sizeof(WCHAR)*MAXIMUM_VOLUME_LABEL_LENGTH);
-
- DeviceObject->Vpb = Vpb;
+ KeInitializeSpinLock(&IoVpbLock);
}
-PIRP IoBuildVolumeInformationIrp(ULONG MajorFunction,
- PFILE_OBJECT FileObject,
- PVOID FSInformation,
- ULONG Length,
- CINT FSInformationClass,
- PIO_STATUS_BLOCK IoStatusBlock,
- PKEVENT Event)
+NTSTATUS
+STDCALL
+IopAttachVpb(PDEVICE_OBJECT DeviceObject)
{
- PIRP Irp;
- PIO_STACK_LOCATION StackPtr;
- PDEVICE_OBJECT DeviceObject;
-
- DeviceObject = FileObject->DeviceObject;
-
- Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
- if (Irp==NULL)
- {
- return(NULL);
- }
-
- Irp->AssociatedIrp.SystemBuffer = FSInformation;
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = MajorFunction;
- StackPtr->MinorFunction = 0;
- StackPtr->Flags = 0;
- StackPtr->Control = 0;
- StackPtr->DeviceObject = DeviceObject;
- StackPtr->FileObject = FileObject;
- Irp->UserEvent = Event;
- Irp->UserIosb = IoStatusBlock;
-
- if (MajorFunction == IRP_MJ_QUERY_VOLUME_INFORMATION)
- {
- StackPtr->Parameters.SetVolume.Length = Length;
- StackPtr->Parameters.SetVolume.FileInformationClass =
- FSInformationClass;
- }
- else
- {
- StackPtr->Parameters.QueryVolume.Length = Length;
- StackPtr->Parameters.QueryVolume.FileInformationClass =
- FSInformationClass;
- }
- return(Irp);
-}
+ PVPB Vpb;
+
+ /* Allocate the Vpb */
+ Vpb = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(VPB),
+ TAG_VPB);
+ if (Vpb == NULL) return(STATUS_UNSUCCESSFUL);
+
+ /* Clear it so we don't waste time manually */
+ RtlZeroMemory(Vpb, sizeof(VPB));
-NTSTATUS STDCALL NtQueryVolumeInformationFile(
- IN HANDLE FileHandle,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- OUT PVOID FSInformation,
- IN ULONG Length,
- IN CINT FSInformationClass)
+ /* Set the Header and Device Field */
+ Vpb->Type = IO_TYPE_VPB;
+ Vpb->Size = sizeof(VPB);
+ Vpb->RealDevice = DeviceObject;
+
+ /* link it to the Device Object */
+ DeviceObject->Vpb = Vpb;
+ return(STATUS_SUCCESS);
+}
/*
* FUNCTION: Queries the volume information
- * ARGUMENTS:
- * FileHandle = Handle to a file object on the target volume
+ * ARGUMENTS:
+ * FileHandle = Handle to a file object on the target volume
* ReturnLength = DataWritten
- * FSInformation = Caller should supply storage for the information
- * structure.
+ * FsInformation = Caller should supply storage for the information
+ * structure.
* Length = Size of the information structure
- * FSInformationClass = Index to a information structure
+ * FsInformationClass = Index to a information structure
*
* FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION
* FileFsLabelInformation FILE_FS_LABEL_INFORMATION
* FileFsSizeInformation FILE_FS_SIZE_INFORMATION
* FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION
* FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION
- * FileFsControlInformation
+ * FileFsControlInformation
* FileFsQuotaQueryInformation --
* FileFsQuotaSetInformation --
- * FileFsMaximumInformation
+ * FileFsMaximumInformation
*
* RETURNS: Status
+ *
+ * @implemented
*/
-{
- return(ZwQueryVolumeInformationFile(FileHandle,IoStatusBlock,FSInformation,
- Length,FSInformationClass));
-}
-NTSTATUS
-STDCALL
-ZwQueryVolumeInformationFile(
- IN HANDLE FileHandle,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- OUT PVOID FSInformation,
- IN ULONG Length,
- IN CINT FSInformationClass)
+NTSTATUS STDCALL
+NtQueryVolumeInformationFile(IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FsInformation,
+ IN ULONG Length,
+ IN FS_INFORMATION_CLASS FsInformationClass)
{
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
- KEVENT Event;
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PIO_STACK_LOCATION StackPtr;
+ PVOID SystemBuffer;
+ KPROCESSOR_MODE PreviousMode;
+
+ DPRINT("FsInformation %p\n", FsInformation);
+
+ PreviousMode = ExGetPreviousMode();
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ if (IoStatusBlock != NULL)
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ }
+
+ if (Length != 0)
+ {
+ ProbeForWrite(FsInformation,
+ Length,
+ 1);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ ASSERT(IoStatusBlock != NULL);
+ ASSERT(FsInformation != NULL);
+ }
+
Status = ObReferenceObjectByHandle(FileHandle,
- FILE_READ_ATTRIBUTES,
- NULL,
- UserMode,
+ 0, /* FIXME - depends on the information class! */
+ IoFileObjectType,
+ PreviousMode,
(PVOID*)&FileObject,
- NULL);
- if (Status != STATUS_SUCCESS)
+ NULL);
+ if (!NT_SUCCESS(Status))
{
return(Status);
}
-
+
DeviceObject = FileObject->DeviceObject;
-
- KeInitializeEvent(&Event,NotificationEvent,FALSE);
-
- Irp = IoBuildVolumeInformationIrp(IRP_MJ_QUERY_VOLUME_INFORMATION,
- FileObject,
- FSInformation,
- Length,
- FSInformationClass,
- IoStatusBlock,
- &Event);
- Status = IoCallDriver(DeviceObject,Irp);
+
+ Irp = IoAllocateIrp(DeviceObject->StackSize,
+ TRUE);
+ if (Irp == NULL)
+ {
+ ObDereferenceObject(FileObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ Length,
+ TAG_SYSB);
+ if (SystemBuffer == NULL)
+ {
+ IoFreeIrp(Irp);
+ ObDereferenceObject(FileObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Trigger FileObject/Event dereferencing */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+
+ Irp->RequestorMode = PreviousMode;
+ Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
+ KeResetEvent( &FileObject->Event );
+ Irp->UserEvent = &FileObject->Event;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
+ StackPtr->MinorFunction = 0;
+ StackPtr->Flags = 0;
+ StackPtr->Control = 0;
+ StackPtr->DeviceObject = DeviceObject;
+ StackPtr->FileObject = FileObject;
+ StackPtr->Parameters.QueryVolume.Length = Length;
+ StackPtr->Parameters.QueryVolume.FsInformationClass =
+ FsInformationClass;
+
+ Status = IoCallDriver(DeviceObject,
+ Irp);
if (Status == STATUS_PENDING)
{
- KeWaitForSingleObject(&Event,UserRequest,KernelMode,FALSE,NULL);
+ KeWaitForSingleObject(&FileObject->Event,
+ UserRequest,
+ PreviousMode,
+ FALSE,
+ NULL);
Status = IoStatusBlock->Status;
}
+ DPRINT("Status %x\n", Status);
+
+ if (NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ DPRINT("Information %lu\n", IoStatusBlock->Information);
+ RtlCopyMemory(FsInformation,
+ SystemBuffer,
+ IoStatusBlock->Information);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ ExFreePool(SystemBuffer);
+
return(Status);
}
-NTSTATUS
-STDCALL
-NtSetVolumeInformationFile(
- IN HANDLE FileHandle,
- IN CINT VolumeInformationClass,
- PVOID VolumeInformation,
- ULONG Length
- )
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
+ IN FS_INFORMATION_CLASS FsInformationClass,
+ IN ULONG Length,
+ OUT PVOID FsInformation,
+ OUT PULONG ReturnedLength)
{
- return(ZwSetVolumeInformationFile(FileHandle,VolumeInformationClass,
- VolumeInformation,Length));
+ IO_STATUS_BLOCK IoStatusBlock;
+ PIO_STACK_LOCATION StackPtr;
+ PDEVICE_OBJECT DeviceObject;
+ PIRP Irp;
+ NTSTATUS Status;
+
+ ASSERT(FsInformation != NULL);
+
+ DPRINT("FsInformation %p\n", FsInformation);
+
+ Status = ObReferenceObjectByPointer(FileObject,
+ FILE_READ_ATTRIBUTES,
+ IoFileObjectType,
+ KernelMode);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ DeviceObject = FileObject->DeviceObject;
+
+ Irp = IoAllocateIrp(DeviceObject->StackSize,
+ TRUE);
+ if (Irp == NULL)
+ {
+ ObDereferenceObject(FileObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Trigger FileObject/Event dereferencing */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = KernelMode;
+ Irp->AssociatedIrp.SystemBuffer = FsInformation;
+ KeResetEvent( &FileObject->Event );
+ Irp->UserEvent = &FileObject->Event;
+ Irp->UserIosb = &IoStatusBlock;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
+ StackPtr->MinorFunction = 0;
+ StackPtr->Flags = 0;
+ StackPtr->Control = 0;
+ StackPtr->DeviceObject = DeviceObject;
+ StackPtr->FileObject = FileObject;
+ StackPtr->Parameters.QueryVolume.Length = Length;
+ StackPtr->Parameters.QueryVolume.FsInformationClass =
+ FsInformationClass;
+
+ Status = IoCallDriver(DeviceObject,
+ Irp);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ UserRequest,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = IoStatusBlock.Status;
+ }
+ DPRINT("Status %x\n", Status);
+
+ if (ReturnedLength != NULL)
+ {
+ *ReturnedLength = IoStatusBlock.Information;
+ }
+
+ return(Status);
}
-NTSTATUS
-STDCALL
-ZwSetVolumeInformationFile(
- IN HANDLE FileHandle,
- IN CINT VolumeInformationClass,
- PVOID VolumeInformation,
- ULONG Length
- )
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtSetVolumeInformationFile(IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PVOID FsInformation,
+ IN ULONG Length,
+ IN FS_INFORMATION_CLASS FsInformationClass)
{
-
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
- KEVENT Event;
NTSTATUS Status;
+ PIO_STACK_LOCATION StackPtr;
+ PVOID SystemBuffer;
+ KPROCESSOR_MODE PreviousMode;
+
+ PreviousMode = ExGetPreviousMode();
+
+ if (PreviousMode != KernelMode)
+ {
+ Status = STATUS_SUCCESS;
+ _SEH_TRY
+ {
+ if (IoStatusBlock != NULL)
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ }
+
+ if (Length != 0)
+ {
+ ProbeForRead(FsInformation,
+ Length,
+ 1);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ ASSERT(IoStatusBlock != NULL);
+ ASSERT(FsInformation != NULL);
+ }
Status = ObReferenceObjectByHandle(FileHandle,
FILE_WRITE_ATTRIBUTES,
NULL,
- UserMode,
+ PreviousMode,
(PVOID*)&FileObject,
- NULL);
+ NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
DeviceObject = FileObject->DeviceObject;
-
- KeInitializeEvent(&Event,NotificationEvent,FALSE);
-
- Irp = IoBuildVolumeInformationIrp(IRP_MJ_SET_VOLUME_INFORMATION,
- FileObject,
- VolumeInformation,
- Length,
- VolumeInformationClass,
- NULL,
- &Event);
+
+ Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
+ if (Irp == NULL)
+ {
+ ObDereferenceObject(FileObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ Length,
+ TAG_SYSB);
+ if (SystemBuffer == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto failfreeirp;
+ }
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ /* no need to probe again */
+ RtlCopyMemory(SystemBuffer,
+ FsInformation,
+ Length);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(SystemBuffer,
+ TAG_SYSB);
+failfreeirp:
+ IoFreeIrp(Irp);
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+ }
+ else
+ {
+ RtlCopyMemory(SystemBuffer,
+ FsInformation,
+ Length);
+ }
+
+ /* Trigger FileObject/Event dereferencing */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = PreviousMode;
+ Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
+ KeResetEvent( &FileObject->Event );
+ Irp->UserEvent = &FileObject->Event;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
+ StackPtr->MinorFunction = 0;
+ StackPtr->Flags = 0;
+ StackPtr->Control = 0;
+ StackPtr->DeviceObject = DeviceObject;
+ StackPtr->FileObject = FileObject;
+ StackPtr->Parameters.SetVolume.Length = Length;
+ StackPtr->Parameters.SetVolume.FsInformationClass =
+ FsInformationClass;
+
Status = IoCallDriver(DeviceObject,Irp);
if (Status == STATUS_PENDING)
{
- KeWaitForSingleObject(&Event,UserRequest,KernelMode,FALSE,NULL);
+ KeWaitForSingleObject(&FileObject->Event,
+ UserRequest,
+ PreviousMode,
+ FALSE,
+ NULL);
+ _SEH_TRY
+ {
+ Status = IoStatusBlock->Status;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
+
+ ExFreePool(SystemBuffer);
+
return(Status);
}
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+IoAcquireVpbSpinLock(OUT PKIRQL Irql)
+{
+ KeAcquireSpinLock(&IoVpbLock,
+ Irql);
+}
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+IoReleaseVpbSpinLock(IN KIRQL Irql)
+{
+ KeReleaseSpinLock(&IoVpbLock,
+ Irql);
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
+ IN ULONG Length,
+ IN BOOLEAN SetOperation)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/* EOF */